Merge kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 22 Jun 2005 19:22:12 +0000 (12:22 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 22 Jun 2005 19:22:12 +0000 (12:22 -0700)
Do arch/ia64/defconfig by hand.

784 files changed:
CREDITS
Documentation/fb/intelfb.txt [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/isofs.txt
Documentation/filesystems/tmpfs.txt
Documentation/i2c/busses/i2c-sis69x
Documentation/i2c/chips/adm1021 [new file with mode: 0644]
Documentation/i2c/chips/adm1025 [new file with mode: 0644]
Documentation/i2c/chips/adm1026 [new file with mode: 0644]
Documentation/i2c/chips/adm1031 [new file with mode: 0644]
Documentation/i2c/chips/adm9240 [new file with mode: 0644]
Documentation/i2c/chips/asb100 [new file with mode: 0644]
Documentation/i2c/chips/ds1621 [new file with mode: 0644]
Documentation/i2c/chips/eeprom [new file with mode: 0644]
Documentation/i2c/chips/fscher [new file with mode: 0644]
Documentation/i2c/chips/gl518sm [new file with mode: 0644]
Documentation/i2c/chips/it87 [new file with mode: 0644]
Documentation/i2c/chips/lm63 [new file with mode: 0644]
Documentation/i2c/chips/lm75 [new file with mode: 0644]
Documentation/i2c/chips/lm77 [new file with mode: 0644]
Documentation/i2c/chips/lm78 [new file with mode: 0644]
Documentation/i2c/chips/lm80 [new file with mode: 0644]
Documentation/i2c/chips/lm83 [new file with mode: 0644]
Documentation/i2c/chips/lm85 [new file with mode: 0644]
Documentation/i2c/chips/lm87 [new file with mode: 0644]
Documentation/i2c/chips/lm90 [new file with mode: 0644]
Documentation/i2c/chips/lm92 [new file with mode: 0644]
Documentation/i2c/chips/max1619 [new file with mode: 0644]
Documentation/i2c/chips/max6875 [new file with mode: 0644]
Documentation/i2c/chips/pc87360 [new file with mode: 0644]
Documentation/i2c/chips/pca9539 [new file with mode: 0644]
Documentation/i2c/chips/pcf8574 [new file with mode: 0644]
Documentation/i2c/chips/pcf8591 [new file with mode: 0644]
Documentation/i2c/chips/sis5595 [new file with mode: 0644]
Documentation/i2c/chips/smsc47b397 [new file with mode: 0644]
Documentation/i2c/chips/smsc47b397.txt [deleted file]
Documentation/i2c/chips/smsc47m1 [new file with mode: 0644]
Documentation/i2c/chips/via686a [new file with mode: 0644]
Documentation/i2c/chips/w83627hf [new file with mode: 0644]
Documentation/i2c/chips/w83781d [new file with mode: 0644]
Documentation/i2c/chips/w83l785ts [new file with mode: 0644]
Documentation/i2c/porting-clients
Documentation/i2c/userspace-tools [new file with mode: 0644]
Documentation/i2c/writing-clients
Documentation/s390/CommonIO
Documentation/sgi-ioc4.txt [new file with mode: 0644]
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/CMIPCI.txt
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
Documentation/sound/alsa/emu10k1-jack.txt [new file with mode: 0644]
Documentation/sound/alsa/hdspm.txt [new file with mode: 0644]
Documentation/w1/w1.generic
MAINTAINERS
arch/arm/mm/mmap.c
arch/frv/mm/init.c
arch/i386/boot/Makefile
arch/i386/kernel/syscall_table.S
arch/i386/kernel/traps.c
arch/i386/lib/delay.c
arch/i386/mm/hugetlbpage.c
arch/i386/mm/init.c
arch/ia64/Kconfig
arch/ia64/configs/sn2_defconfig
arch/ia64/defconfig
arch/ia64/kernel/Makefile
arch/ia64/kernel/efi.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/uncached.c [new file with mode: 0644]
arch/ia64/mm/hugetlbpage.c
arch/ia64/sn/kernel/xpc_partition.c
arch/m32r/Kconfig
arch/m32r/boot/compressed/m32r_sio.c
arch/m32r/defconfig
arch/m32r/kernel/Makefile
arch/m32r/kernel/io_m32700ut.c
arch/m32r/kernel/io_mappi.c
arch/m32r/kernel/io_mappi2.c
arch/m32r/kernel/io_mappi3.c [new file with mode: 0644]
arch/m32r/kernel/io_oaks32r.c
arch/m32r/kernel/io_opsput.c
arch/m32r/kernel/io_usrv.c
arch/m32r/kernel/setup.c
arch/m32r/kernel/setup_m32700ut.c
arch/m32r/kernel/setup_mappi.c
arch/m32r/kernel/setup_mappi2.c
arch/m32r/kernel/setup_mappi3.c [new file with mode: 0644]
arch/m32r/kernel/setup_oaks32r.c
arch/m32r/kernel/setup_opsput.c
arch/m32r/kernel/setup_usrv.c
arch/m32r/m32700ut/defconfig.m32700ut.smp
arch/m32r/m32700ut/defconfig.m32700ut.up
arch/m32r/mappi/defconfig.nommu
arch/m32r/mappi/defconfig.smp
arch/m32r/mappi/defconfig.up
arch/m32r/mappi2/defconfig.vdec2
arch/m32r/mappi3/defconfig.smp [new file with mode: 0644]
arch/m32r/mappi3/dot.gdbinit [new file with mode: 0644]
arch/m32r/mm/extable.c
arch/m32r/oaks32r/defconfig.nommu
arch/m32r/opsput/defconfig.opsput
arch/mips/mm/init.c
arch/ppc/Kconfig
arch/ppc/boot/ld.script
arch/ppc/boot/openfirmware/Makefile
arch/ppc/boot/openfirmware/common.c
arch/ppc/boot/simple/Makefile
arch/ppc/boot/utils/addSystemMap.c [deleted file]
arch/ppc/configs/mpc8548_cds_defconfig [new file with mode: 0644]
arch/ppc/kernel/cputable.c
arch/ppc/kernel/entry.S
arch/ppc/kernel/head_4xx.S
arch/ppc/kernel/head_booke.h
arch/ppc/kernel/setup.c
arch/ppc/kernel/traps.c
arch/ppc/lib/locks.c
arch/ppc/mm/fsl_booke_mmu.c
arch/ppc/mm/init.c
arch/ppc/mm/mmu_decl.h
arch/ppc/mm/pgtable.c
arch/ppc/platforms/83xx/mpc834x_sys.c
arch/ppc/platforms/85xx/Kconfig
arch/ppc/platforms/85xx/Makefile
arch/ppc/platforms/85xx/mpc8540_ads.c
arch/ppc/platforms/85xx/mpc8560_ads.c
arch/ppc/platforms/85xx/mpc85xx_ads_common.c
arch/ppc/platforms/85xx/mpc85xx_cds_common.c
arch/ppc/platforms/85xx/sbc8560.c
arch/ppc/platforms/85xx/sbc85xx.c
arch/ppc/platforms/85xx/stx_gp3.c
arch/ppc/platforms/sandpoint.c
arch/ppc/syslib/Makefile
arch/ppc/syslib/mpc10x_common.c
arch/ppc/syslib/mpc85xx_devices.c
arch/ppc/syslib/mpc85xx_sys.c
arch/ppc/syslib/open_pic.c
arch/ppc/syslib/open_pic2.c
arch/ppc/syslib/ppc4xx_kgdb.c [deleted file]
arch/ppc/syslib/ppc83xx_setup.c
arch/ppc/syslib/ppc85xx_setup.c
arch/ppc/xmon/xmon.c
arch/ppc64/Kconfig
arch/ppc64/Makefile
arch/ppc64/kernel/HvLpEvent.c
arch/ppc64/kernel/ItLpQueue.c
arch/ppc64/kernel/Makefile
arch/ppc64/kernel/XmPciLpEvent.c [deleted file]
arch/ppc64/kernel/asm-offsets.c
arch/ppc64/kernel/dma.c
arch/ppc64/kernel/eeh.c
arch/ppc64/kernel/head.S
arch/ppc64/kernel/iSeries_VpdInfo.c
arch/ppc64/kernel/iSeries_iommu.c
arch/ppc64/kernel/iSeries_irq.c
arch/ppc64/kernel/iSeries_pci.c
arch/ppc64/kernel/iSeries_pci_reset.c [deleted file]
arch/ppc64/kernel/iSeries_proc.c
arch/ppc64/kernel/iSeries_setup.c
arch/ppc64/kernel/iSeries_smp.c
arch/ppc64/kernel/idle.c
arch/ppc64/kernel/irq.c
arch/ppc64/kernel/lparcfg.c
arch/ppc64/kernel/mf.c
arch/ppc64/kernel/process.c
arch/ppc64/kernel/prom.c
arch/ppc64/kernel/ras.c
arch/ppc64/kernel/rtc.c
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/sys_ppc32.c
arch/ppc64/kernel/vio.c
arch/ppc64/kernel/viopath.c
arch/ppc64/lib/Makefile
arch/ppc64/mm/hash_utils.c
arch/ppc64/mm/hugetlbpage.c
arch/ppc64/mm/imalloc.c
arch/ppc64/mm/init.c
arch/ppc64/xmon/xmon.c
arch/s390/kernel/compat_ioctl.c
arch/s390/kernel/head.S
arch/s390/kernel/head64.S
arch/s390/kernel/traps.c
arch/s390/mm/cmm.c
arch/sh/kernel/sys_sh.c
arch/sh/lib/delay.c
arch/sh/mm/hugetlbpage.c
arch/sh64/mm/hugetlbpage.c
arch/sparc/mm/init.c
arch/sparc64/kernel/sys_sparc.c
arch/sparc64/lib/delay.c
arch/sparc64/mm/hugetlbpage.c
arch/sparc64/solaris/socket.c
arch/um/Kconfig
arch/um/Makefile
arch/um/drivers/line.c
arch/um/drivers/net_kern.c
arch/um/drivers/port_kern.c
arch/um/drivers/xterm_kern.c
arch/um/kernel/irq.c
arch/um/kernel/irq_user.c
arch/um/kernel/mem.c
arch/um/kernel/tt/Makefile
arch/um/kernel/tt/unmap.c [deleted file]
arch/um/kernel/uml.lds.S
arch/um/scripts/Makefile.rules
arch/um/scripts/Makefile.unmap [new file with mode: 0644]
arch/um/sys-i386/Makefile
arch/um/sys-i386/unmap.c [new file with mode: 0644]
arch/um/sys-x86_64/Makefile
arch/um/sys-x86_64/unmap.c [new file with mode: 0644]
arch/x86_64/ia32/ia32_aout.c
arch/x86_64/ia32/ia32_binfmt.c
arch/x86_64/kernel/process.c
arch/x86_64/kernel/ptrace.c
arch/x86_64/kernel/sys_x86_64.c
arch/x86_64/lib/delay.c
arch/x86_64/mm/fault.c
drivers/Kconfig
drivers/Makefile
drivers/acorn/char/pcf8583.c
drivers/acpi/processor_idle.c
drivers/base/node.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/mem.c
drivers/char/vr41xx_giu.c [new file with mode: 0644]
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-sibyte.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-frodo.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-i810.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-ibm_iic.h
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-isa.c
drivers/i2c/busses/i2c-ite.c
drivers/i2c/busses/i2c-ixp2000.c
drivers/i2c/busses/i2c-ixp4xx.c
drivers/i2c/busses/i2c-keywest.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-pca-isa.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-prosavage.c
drivers/i2c/busses/i2c-rpx.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-savage4.c
drivers/i2c/busses/i2c-sibyte.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-stub.c
drivers/i2c/busses/i2c-via.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/i2c-voodoo3.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/i2c/chips/adm1021.c
drivers/i2c/chips/adm1025.c
drivers/i2c/chips/adm1026.c
drivers/i2c/chips/adm1031.c
drivers/i2c/chips/adm9240.c [new file with mode: 0644]
drivers/i2c/chips/asb100.c
drivers/i2c/chips/atxp1.c [new file with mode: 0644]
drivers/i2c/chips/ds1337.c
drivers/i2c/chips/ds1374.c [new file with mode: 0644]
drivers/i2c/chips/ds1621.c
drivers/i2c/chips/eeprom.c
drivers/i2c/chips/fscher.c
drivers/i2c/chips/gl518sm.c
drivers/i2c/chips/isp1301_omap.c
drivers/i2c/chips/it87.c
drivers/i2c/chips/lm63.c
drivers/i2c/chips/lm75.c
drivers/i2c/chips/lm77.c
drivers/i2c/chips/lm78.c
drivers/i2c/chips/lm80.c
drivers/i2c/chips/lm83.c
drivers/i2c/chips/lm85.c
drivers/i2c/chips/lm87.c
drivers/i2c/chips/lm90.c
drivers/i2c/chips/m41t00.c
drivers/i2c/chips/max1619.c
drivers/i2c/chips/max6875.c [new file with mode: 0644]
drivers/i2c/chips/pc87360.c
drivers/i2c/chips/pca9539.c [new file with mode: 0644]
drivers/i2c/chips/pcf8574.c
drivers/i2c/chips/rtc8564.c
drivers/i2c/chips/sis5595.c
drivers/i2c/chips/smsc47m1.c
drivers/i2c/chips/tps65010.c [new file with mode: 0644]
drivers/i2c/chips/via686a.c
drivers/i2c/chips/w83627ehf.c [new file with mode: 0644]
drivers/i2c/chips/w83627hf.c
drivers/i2c/chips/w83781d.c
drivers/i2c/chips/w83l785ts.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/Kconfig
drivers/ide/pci/sgiioc4.c
drivers/input/gameport/gameport.c
drivers/macintosh/therm_windtunnel.c
drivers/md/Makefile
drivers/md/bitmap.c [new file with mode: 0644]
drivers/md/dm-crypt.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/multipath.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid6main.c
drivers/media/video/adv7170.c
drivers/media/video/adv7175.c
drivers/media/video/bt819.c
drivers/media/video/bt832.c
drivers/media/video/bt856.c
drivers/media/video/msp3400.c
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa7110.c
drivers/media/video/saa7111.c
drivers/media/video/saa7114.c
drivers/media/video/saa7134/saa6752hs.c
drivers/media/video/saa7185.c
drivers/media/video/tda7432.c
drivers/media/video/tda9840.c
drivers/media/video/tda9875.c
drivers/media/video/tda9887.c
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/tuner-3036.c
drivers/media/video/tuner-core.c
drivers/media/video/tvaudio.c
drivers/media/video/tveeprom.c
drivers/media/video/vpx3220.c
drivers/misc/ibmasm/command.c
drivers/misc/ibmasm/dot_command.c
drivers/misc/ibmasm/event.c
drivers/misc/ibmasm/heartbeat.c
drivers/misc/ibmasm/ibmasm.h
drivers/misc/ibmasm/ibmasmfs.c
drivers/misc/ibmasm/lowlevel.c
drivers/misc/ibmasm/module.c
drivers/misc/ibmasm/r_heartbeat.c
drivers/misc/ibmasm/remote.c
drivers/misc/ibmasm/remote.h
drivers/net/3c59x.c
drivers/net/8390.c
drivers/oprofile/buffer_sync.c
drivers/pcmcia/Kconfig
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_cfc.h
drivers/s390/cio/blacklist.c
drivers/scsi/megaraid.c
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/cpm_uart/cpm_uart_cpm2.c
drivers/serial/ioc4_serial.c
drivers/sn/Kconfig [new file with mode: 0644]
drivers/sn/Makefile
drivers/sn/ioc4.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/arcfb.c [new file with mode: 0644]
drivers/video/chipsfb.c
drivers/video/console/Kconfig
drivers/video/console/Makefile
drivers/video/console/bitblit.c
drivers/video/console/font_10x18.c [new file with mode: 0644]
drivers/video/console/font_7x14.c [new file with mode: 0644]
drivers/video/console/font_sun12x22.c
drivers/video/console/fonts.c
drivers/video/console/vgacon.c
drivers/video/fbmem.c
drivers/video/i810/i810_main.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/matrox/matroxfb_maven.c
drivers/video/nvidia/nvidia.c
drivers/video/pm3fb.c
drivers/video/riva/fbdev.c
drivers/video/s1d13xxxfb.c
drivers/video/savage/savagefb_driver.c
drivers/video/softcursor.c
drivers/video/vesafb.c
drivers/w1/Kconfig
drivers/w1/ds_w1_bridge.c
drivers/w1/matrox_w1.c
drivers/w1/w1.c
drivers/w1/w1.h
drivers/w1/w1_family.c
drivers/w1/w1_family.h
drivers/w1/w1_int.c
drivers/w1/w1_int.h
drivers/w1/w1_io.c
drivers/w1/w1_io.h
drivers/w1/w1_log.h
drivers/w1/w1_netlink.h
drivers/w1/w1_smem.c
drivers/w1/w1_therm.c
fs/autofs4/autofs_i.h
fs/autofs4/expire.c
fs/autofs4/root.c
fs/autofs4/waitq.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/buffer.c
fs/hugetlbfs/inode.c
fs/isofs/dir.c
fs/isofs/inode.c
fs/isofs/isofs.h
fs/isofs/namei.c
fs/isofs/rock.c
fs/isofs/rock.h
fs/proc/proc_misc.c
fs/super.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_buf.h
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_linux.h
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_lrw.h
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_vfs.h
fs/xfs/linux-2.6/xfs_vnode.c
fs/xfs/linux-2.6/xfs_vnode.h
fs/xfs/quota/xfs_dquot.c
fs/xfs/quota/xfs_dquot.h
fs/xfs/quota/xfs_dquot_item.c
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm.h
fs/xfs/quota/xfs_qm_bhv.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/quota/xfs_quota_priv.h
fs/xfs/quota/xfs_trans_dquot.c
fs/xfs/support/debug.c
fs/xfs/support/debug.h
fs/xfs/xfs_alloc.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr.h
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_attr_leaf.h
fs/xfs/xfs_bit.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.h
fs/xfs/xfs_bmap_btree.c
fs/xfs/xfs_bmap_btree.h
fs/xfs/xfs_btree.c
fs/xfs/xfs_btree.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_buf_item.h
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_da_btree.h
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_dir2_data.c
fs/xfs/xfs_dir2_data.h
fs/xfs/xfs_dir2_leaf.c
fs/xfs/xfs_dir2_leaf.h
fs/xfs/xfs_dir_leaf.c
fs/xfs/xfs_dir_leaf.h
fs/xfs/xfs_dmapi.h
fs/xfs/xfs_error.c
fs/xfs/xfs_error.h
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_extfree_item.h
fs/xfs/xfs_fs.h
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ialloc_btree.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_macros.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_quota.h
fs/xfs/xfs_rename.c
fs/xfs/xfs_trans.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_trans_buf.c
fs/xfs/xfs_trans_inode.c
fs/xfs/xfs_types.h
fs/xfs/xfs_utils.c
fs/xfs/xfs_vfsops.c
fs/xfs/xfs_vnodeops.c
include/asm-alpha/smp.h
include/asm-arm/arch-omap/tps65010.h
include/asm-arm/smp.h
include/asm-arm/system.h
include/asm-generic/pgtable.h
include/asm-i386/page.h
include/asm-i386/pgtable.h
include/asm-i386/smp.h
include/asm-i386/unistd.h
include/asm-ia64/mmzone.h
include/asm-ia64/pgtable.h
include/asm-ia64/smp.h
include/asm-ia64/sn/mspec.h [new file with mode: 0644]
include/asm-ia64/uncached.h [new file with mode: 0644]
include/asm-ia64/unistd.h
include/asm-m32r/div64.h
include/asm-m32r/ide.h
include/asm-m32r/m32102.h
include/asm-m32r/m32102peri.h [deleted file]
include/asm-m32r/m32r.h
include/asm-m32r/mappi3/mappi3_pld.h [new file with mode: 0644]
include/asm-m32r/smp.h
include/asm-mips/smp.h
include/asm-mips/vr41xx/giu.h [new file with mode: 0644]
include/asm-mips/vr41xx/vr41xx.h
include/asm-parisc/smp.h
include/asm-ppc/irq.h
include/asm-ppc/mpc10x.h
include/asm-ppc/mpc85xx.h
include/asm-ppc/pgtable.h
include/asm-ppc/ppc_sys.h
include/asm-ppc/smp.h
include/asm-ppc64/dma.h
include/asm-ppc64/iSeries/HvCall.h
include/asm-ppc64/iSeries/HvCallCfg.h [deleted file]
include/asm-ppc64/iSeries/HvCallEvent.h
include/asm-ppc64/iSeries/HvCallHpt.h
include/asm-ppc64/iSeries/HvCallPci.h
include/asm-ppc64/iSeries/HvCallSc.h
include/asm-ppc64/iSeries/HvCallSm.h
include/asm-ppc64/iSeries/HvCallXm.h
include/asm-ppc64/iSeries/HvLpConfig.h
include/asm-ppc64/iSeries/HvLpEvent.h
include/asm-ppc64/iSeries/HvReleaseData.h
include/asm-ppc64/iSeries/HvTypes.h
include/asm-ppc64/iSeries/IoHriMainStore.h
include/asm-ppc64/iSeries/IoHriProcessorVpd.h
include/asm-ppc64/iSeries/ItExtVpdPanel.h
include/asm-ppc64/iSeries/ItIplParmsReal.h
include/asm-ppc64/iSeries/ItLpNaca.h
include/asm-ppc64/iSeries/ItLpQueue.h
include/asm-ppc64/iSeries/ItLpRegSave.h
include/asm-ppc64/iSeries/ItSpCommArea.h
include/asm-ppc64/iSeries/ItVpdAreas.h
include/asm-ppc64/iSeries/LparData.h [deleted file]
include/asm-ppc64/iSeries/LparMap.h
include/asm-ppc64/iSeries/XmPciLpEvent.h [deleted file]
include/asm-ppc64/iSeries/iSeries_io.h
include/asm-ppc64/iSeries/iSeries_irq.h
include/asm-ppc64/iSeries/iSeries_pci.h
include/asm-ppc64/iSeries/iSeries_proc.h [deleted file]
include/asm-ppc64/iSeries/mf.h
include/asm-ppc64/iSeries/vio.h
include/asm-ppc64/imalloc.h
include/asm-ppc64/iommu.h
include/asm-ppc64/paca.h
include/asm-ppc64/page.h
include/asm-ppc64/pgtable.h
include/asm-ppc64/processor.h
include/asm-ppc64/smp.h
include/asm-s390/smp.h
include/asm-sh/page.h
include/asm-sh/pgtable.h
include/asm-sh/smp.h
include/asm-sh64/page.h
include/asm-sh64/pgtable.h
include/asm-sparc/smp.h
include/asm-sparc64/page.h
include/asm-sparc64/pgtable.h
include/asm-sparc64/processor.h
include/asm-sparc64/smp.h
include/asm-um/smp.h
include/asm-x86_64/a.out.h
include/asm-x86_64/page.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/processor.h
include/asm-x86_64/smp.h
include/linux/arcfb.h [new file with mode: 0644]
include/linux/auto_fs4.h
include/linux/fb.h
include/linux/font.h
include/linux/fsl_devices.h
include/linux/genalloc.h [new file with mode: 0644]
include/linux/gfp.h
include/linux/hugetlb.h
include/linux/hwmon-sysfs.h [new file with mode: 0644]
include/linux/i2c-id.h
include/linux/i2c-sysfs.h [deleted file]
include/linux/i2c-vid.h
include/linux/i2c.h
include/linux/ioc4.h [new file with mode: 0644]
include/linux/ioc4_common.h [deleted file]
include/linux/irq.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/page-flags.h
include/linux/pagemap.h
include/linux/pci_ids.h
include/linux/raid/bitmap.h [new file with mode: 0644]
include/linux/raid/md.h
include/linux/raid/md_k.h
include/linux/raid/md_p.h
include/linux/raid/md_u.h
include/linux/raid/raid1.h
include/linux/sched.h
include/linux/smp.h
include/linux/swap.h
include/net/route.h
include/net/snmp.h
include/sound/ac97_codec.h
include/sound/asound.h
include/sound/control.h
include/sound/emu10k1.h
include/sound/gus.h
include/sound/hdspm.h [new file with mode: 0644]
include/sound/pcm.h
include/sound/seq_midi_event.h
include/sound/seq_virmidi.h
include/sound/timer.h
include/sound/version.h
init/main.c
kernel/fork.c
kernel/irq/manage.c
kernel/module.c
kernel/power/smp.c
kernel/sched.c
kernel/stop_machine.c
kernel/sys_ni.c
lib/Kconfig
lib/Makefile
lib/genalloc.c [new file with mode: 0644]
lib/idr.c
lib/kernel_lock.c
lib/smp_processor_id.c [new file with mode: 0644]
mm/hugetlb.c
mm/madvise.c
mm/memory.c
mm/mempolicy.c
mm/mmap.c
mm/msync.c
mm/nommu.c
mm/oom_kill.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/slab.c
mm/swapfile.c
mm/vmscan.c
net/ipv4/Kconfig
security/selinux/hooks.c
sound/Kconfig
sound/arm/Kconfig
sound/arm/Makefile
sound/arm/aaci.c [new file with mode: 0644]
sound/arm/aaci.h [new file with mode: 0644]
sound/arm/devdma.c [new file with mode: 0644]
sound/arm/devdma.h [new file with mode: 0644]
sound/core/control.c
sound/core/memalloc.c
sound/core/oss/pcm_oss.c
sound/core/oss/pcm_plugin.c
sound/core/pcm.c
sound/core/pcm_lib.c
sound/core/pcm_memory.c
sound/core/pcm_misc.c
sound/core/pcm_native.c
sound/core/seq/oss/seq_oss_synth.c
sound/core/seq/seq_dummy.c
sound/core/seq/seq_midi.c
sound/core/seq/seq_midi_event.c
sound/core/seq/seq_queue.c
sound/core/seq/seq_queue.h
sound/core/seq/seq_timer.c
sound/core/seq/seq_timer.h
sound/core/seq/seq_virmidi.c
sound/core/sound.c
sound/core/timer.c
sound/core/timer_compat.c
sound/drivers/vx/vx_pcm.c
sound/i2c/tea6330t.c
sound/isa/Kconfig
sound/isa/ad1816a/ad1816a.c
sound/isa/cs423x/cs4236.c
sound/isa/gus/gus_io.c
sound/isa/gus/gus_main.c
sound/isa/gus/gus_mem.c
sound/isa/gus/gus_pcm.c
sound/isa/gus/gus_reset.c
sound/isa/gus/gus_synth.c
sound/isa/gus/gus_tables.h
sound/isa/gus/gus_volume.c
sound/oss/rme96xx.c
sound/pci/Kconfig
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_patch.c
sound/pci/ac97/ac97_patch.h
sound/pci/ali5451/ali5451.c
sound/pci/als4000.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106.h
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/ca0106/ca0106_proc.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/irq.c
sound/pci/emu10k1/p16v.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/Makefile
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/hda_patch.h
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cmedia.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c [new file with mode: 0644]
sound/pci/ice1712/amp.c
sound/pci/ice1712/amp.h
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/phase.c
sound/pci/ice1712/phase.h
sound/pci/ice1712/vt1720_mobo.c
sound/pci/ice1712/vt1720_mobo.h
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/maestro3.c
sound/pci/mixart/mixart.c
sound/pci/nm256/nm256.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/Makefile
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c [new file with mode: 0644]
sound/pci/rme9652/rme9652.c
sound/pci/sonicvibes.c
sound/pci/trident/trident.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/vx222/vx222.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/vx/vx_entry.c
sound/synth/emux/emux_effect.c
sound/usb/Kconfig
sound/usb/usbaudio.c
sound/usb/usbaudio.h
sound/usb/usbmidi.c
sound/usb/usbmixer.c
sound/usb/usbmixer_maps.c
sound/usb/usbquirks.h
sound/usb/usx2y/usbusx2y.c
sound/usb/usx2y/usbusx2yaudio.c

diff --git a/CREDITS b/CREDITS
index d65ffe5a4d0803c59159592b258f0dfc049ec8d3..3b7a1548aaf9c945d6c9c46f2ef310b4f2de1807 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1880,6 +1880,13 @@ S: Schlehenweg 9
 S: D-91080 Uttenreuth
 S: Germany
 
+N: Jaya Kumar
+E: jayalk@intworks.biz
+W: http://www.intworks.biz
+D: Arc monochrome LCD framebuffer driver, x86 reboot fixups
+S: Gurgaon, India
+S: Kuala Lumpur, Malaysia
+
 N: Gabor Kuti
 M: seasons@falcon.sch.bme.hu
 M: seasons@makosteszta.sote.hu
@@ -2373,9 +2380,10 @@ E: tmolina@cablespeed.com
 D: bug fixes, documentation, minor hackery
 
 N: James Morris
-E: jmorris@intercode.com.au
+E: jmorris@redhat.com
 W: http://www.intercode.com.au/jmorris/
-D: Netfilter, Linux Security Modules (LSM).
+D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec,
+D: Crypto API, general networking, miscellaneous.
 S: PO Box 707
 S: Spit Junction NSW 2088
 S: Australia
diff --git a/Documentation/fb/intelfb.txt b/Documentation/fb/intelfb.txt
new file mode 100644 (file)
index 0000000..c12d39a
--- /dev/null
@@ -0,0 +1,135 @@
+Intel 830M/845G/852GM/855GM/865G/915G Framebuffer driver
+================================================================
+
+A. Introduction
+       This is a framebuffer driver for various Intel 810/815 compatible
+graphics devices.  These would include:
+
+       Intel 830M
+       Intel 810E845G
+       Intel 852GM
+       Intel 855GM
+       Intel 865G
+       Intel 915G
+
+B.  List of available options
+
+   a. "video=intelfb"
+       enables the intelfb driver
+
+       Recommendation: required
+
+   b. "mode=<xres>x<yres>[-<bpp>][@<refresh>]"
+       select mode
+
+       Recommendation: user preference
+       (default = 1024x768-32@70)
+
+   c. "vram=<value>"
+       select amount of system RAM in MB to allocate for the video memory
+       if not enough RAM was already allocated by the BIOS.
+
+       Recommendation: 1 - 4 MB.
+       (default = 4 MB)
+
+   d. "voffset=<value>"
+        select at what offset in MB of the logical memory to allocate the
+       framebuffer memory.  The intent is to avoid the memory blocks
+       used by standard graphics applications (XFree86). Depending on your
+        usage, adjust the value up or down, (0 for maximum usage, 63/127 MB
+        for the least amount).  Note, an arbitrary setting may conflict
+        with XFree86.
+
+       Recommendation: do not set
+       (default = 48 MB)
+
+   e. "accel"
+       enable text acceleration.  This can be enabled/reenabled anytime
+       by using 'fbset -accel true/false'.
+
+       Recommendation: enable
+       (default = set)
+
+   f. "hwcursor"
+       enable cursor acceleration.
+
+       Recommendation: enable
+       (default = set)
+
+   g. "mtrr"
+       enable MTRR.  This allows data transfers to the framebuffer memory
+       to occur in bursts which can significantly increase performance.
+       Not very helpful with the intel chips because of 'shared memory'.
+
+       Recommendation: set
+       (default = set)
+
+   h. "fixed"
+       disable mode switching.
+
+       Recommendation: do not set
+       (default = not set)
+
+   The binary parameters can be unset with a "no" prefix, example "noaccel".
+   The default parameter (not named) is the mode.
+
+C. Kernel booting
+
+Separate each option/option-pair by commas (,) and the option from its value
+with an equals sign (=) as in the following:
+
+video=i810fb:option1,option2=value2
+
+Sample Usage
+------------
+
+In /etc/lilo.conf, add the line:
+
+append="video=intelfb:800x600-32@75,accel,hwcursor,vram=8"
+
+This will initialize the framebuffer to 800x600 at 32bpp and 75Hz. The
+framebuffer will use 8 MB of System RAM. hw acceleration of text and cursor
+will be enabled.
+
+D.  Module options
+
+       The module parameters are essentially similar to the kernel
+parameters. The main difference is that you need to include a Boolean value
+(1 for TRUE, and 0 for FALSE) for those options which don't need a value.
+
+Example, to enable MTRR, include "mtrr=1".
+
+Sample Usage
+------------
+
+Using the same setup as described above, load the module like this:
+
+       modprobe intelfb mode=800x600-32@75 vram=8 accel=1 hwcursor=1
+
+Or just add the following to /etc/modprobe.conf
+
+       options intelfb mode=800x600-32@75 vram=8 accel=1 hwcursor=1
+
+and just do a
+
+       modprobe intelfb
+
+
+E.  Acknowledgment:
+
+       1.  Geert Uytterhoeven - his excellent howto and the virtual
+                                 framebuffer driver code made this possible.
+
+       2.  Jeff Hartmann for his agpgart code.
+
+       3.  David Dawes for his original kernel 2.4 code.
+
+       4.  The X developers.  Insights were provided just by reading the
+           XFree86 source code.
+
+       5.  Antonino A. Daplas for his inspiring i810fb driver.
+
+       6.  Andrew Morton for his kernel patches maintenance.
+
+###########################
+Sylvain
index b9eb209318ab7d737ba7e6be2a0587ce9e8a9d25..26414bc87c6536d2015953cc6d6415719ac387ec 100644 (file)
@@ -83,3 +83,13 @@ Why: Deprecated in favour of the new ioctl-based rawiso interface, which is
        more efficient.  You should really be using libraw1394 for raw1394
        access anyway.
 Who:   Jody McIntyre <scjody@steamballoon.com>
+
+---------------------------
+
+What:  i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
+When:  November 2005
+Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
+Why:   Match the other drivers' name for the same function, duplicate names
+       will be available until removal of old names.
+Who:   Grant Coady <gcoady@gmail.com>
+
index f64a10506689124943a5bdd9d1b43271d62b387c..424585ff6ea1c18daf7b9f47da97edd72b72dba1 100644 (file)
@@ -26,7 +26,11 @@ Mount options unique to the isofs filesystem.
   mode=xxx      Sets the permissions on files to xxx
   nojoliet      Ignore Joliet extensions if they are present.
   norock        Ignore Rock Ridge extensions if they are present.
-  unhide        Show hidden files.
+  hide         Completely strip hidden files from the file system.
+  showassoc    Show files marked with the 'associated' bit
+  unhide       Deprecated; showing hidden files is now default;
+               If given, it is a synonym for 'showassoc' which will
+               recreate previous unhide behavior
   session=x     Select number of session on multisession CD
   sbsector=xxx  Session begins from sector xxx
 
index 417e3095fe39a65f054ece975d01e68d99d0c018..0d783c504eade32e666e7a19b6fa89f85bfb9416 100644 (file)
@@ -71,8 +71,8 @@ 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
+If nr_blocks=0 (or size=0), blocks will not be limited in that instance;
+if nr_inodes=0, inodes will not be limited.  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.
@@ -97,4 +97,4 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
 Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
 Updated:
-   Hugh Dickins <hugh@veritas.com>, 01 September 2004
+   Hugh Dickins <hugh@veritas.com>, 13 March 2005
index 5be48769f65bdd0627b97d58ced690992b6e7ad0..b88953dfd58022aef1680c266c7438605b146fc8 100644 (file)
@@ -42,7 +42,7 @@ I suspect that this driver could be made to work for the following SiS
 chipsets as well: 635, and 635T. If anyone owns a board with those chips
 AND is willing to risk crashing & burning an otherwise well-behaved kernel
 in the name of progress... please contact me at <mhoffman@lightlink.com> or
-via the project's mailing list: <sensors@stimpy.netroedge.com>.  Please
+via the project's mailing list: <lm-sensors@lm-sensors.org>.  Please
 send bug reports and/or success stories as well.
 
 
diff --git a/Documentation/i2c/chips/adm1021 b/Documentation/i2c/chips/adm1021
new file mode 100644 (file)
index 0000000..03d02bf
--- /dev/null
@@ -0,0 +1,111 @@
+Kernel driver adm1021
+=====================
+
+Supported chips:
+  * Analog Devices ADM1021
+    Prefix: 'adm1021'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Analog Devices website
+  * Analog Devices ADM1021A/ADM1023
+    Prefix: 'adm1023'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Analog Devices website
+  * Genesys Logic GL523SM
+    Prefix: 'gl523sm'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet:
+  * Intel Xeon Processor
+    Prefix: - any other - may require 'force_adm1021' parameter
+    Addresses scanned: none
+    Datasheet: Publicly available at Intel website
+  * Maxim MAX1617
+    Prefix: 'max1617'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Maxim website
+  * Maxim MAX1617A
+    Prefix: 'max1617a'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Maxim website
+  * National Semiconductor LM84
+    Prefix: 'lm84'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the National Semiconductor website
+  * Philips NE1617
+    Prefix: 'max1617' (probably detected as a max1617)
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Philips website
+  * Philips NE1617A
+    Prefix: 'max1617' (probably detected as a max1617)
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Philips website
+  * TI THMC10
+    Prefix: 'thmc10'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the TI website
+  * Onsemi MC1066
+    Prefix: 'mc1066'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Onsemi website
+
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>
+
+Module Parameters
+-----------------
+
+* read_only: int
+  Don't set any values, read only mode
+
+
+Description
+-----------
+
+The chips supported by this driver are very similar. The Maxim MAX1617 is
+the oldest; it has the problem that it is not very well detectable. The
+MAX1617A solves that. The ADM1021 is a straight clone of the MAX1617A.
+Ditto for the THMC10. From here on, we will refer to all these chips as
+ADM1021-clones.
+
+The ADM1021 and MAX1617A reports a die code, which is a sort of revision
+code. This can help us pinpoint problems; it is not very useful
+otherwise.
+
+ADM1021-clones implement two temperature sensors. One of them is internal,
+and measures the temperature of the chip itself; the other is external and
+is realised in the form of a transistor-like device. A special alarm
+indicates whether the remote sensor is connected.
+
+Each sensor has its own low and high limits. When they are crossed, the
+corresponding alarm is set and remains on as long as the temperature stays
+out of range. Temperatures are measured in degrees Celsius. Measurements
+are possible between -65 and +127 degrees, with a resolution of one degree.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared!
+
+This driver only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values. It is possible to make
+ADM1021-clones do faster measurements, but there is really no good reason
+for that.
+
+Xeon support
+------------
+
+Some Xeon processors have real max1617, adm1021, or compatible chips
+within them, with two temperature sensors.
+
+Other Xeons have chips with only one sensor.
+
+If you have a Xeon, and the adm1021 module loads, and both temperatures
+appear valid, then things are good.
+
+If the adm1021 module doesn't load, you should try this:
+       modprobe adm1021 force_adm1021=BUS,ADDRESS
+       ADDRESS can only be 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e.
+
+If you have dual Xeons you may have appear to have two separate
+adm1021-compatible chips, or two single-temperature sensors, at distinct
+addresses.
diff --git a/Documentation/i2c/chips/adm1025 b/Documentation/i2c/chips/adm1025
new file mode 100644 (file)
index 0000000..39d2b78
--- /dev/null
@@ -0,0 +1,51 @@
+Kernel driver adm1025
+=====================
+
+Supported chips:
+  * Analog Devices ADM1025, ADM1025A
+    Prefix: 'adm1025'
+    Addresses scanned: I2C 0x2c - 0x2e
+    Datasheet: Publicly available at the Analog Devices website
+  * Philips NE1619
+    Prefix: 'ne1619'
+    Addresses scanned: I2C 0x2c - 0x2d
+    Datasheet: Publicly available at the Philips website
+
+The NE1619 presents some differences with the original ADM1025:
+  * Only two possible addresses (0x2c - 0x2d).
+  * No temperature offset register, but we don't use it anyway.
+  * No INT mode for pin 16. We don't play with it anyway.
+
+Authors:
+        Chen-Yuan Wu <gwu@esoft.com>,
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+(This is from Analog Devices.) The ADM1025 is a complete system hardware
+monitor for microprocessor-based systems, providing measurement and limit
+comparison of various system parameters. Five voltage measurement inputs
+are provided, for monitoring +2.5V, +3.3V, +5V and +12V power supplies and
+the processor core voltage. The ADM1025 can monitor a sixth power-supply
+voltage by measuring its own VCC. One input (two pins) is dedicated to a
+remote temperature-sensing diode and an on-chip temperature sensor allows
+ambient temperature to be monitored.
+
+One specificity of this chip is that the pin 11 can be hardwired in two
+different manners. It can act as the +12V power-supply voltage analog
+input, or as the a fifth digital entry for the VID reading (bit 4). It's
+kind of strange since both are useful, and the reason for designing the
+chip that way is obscure at least to me. The bit 5 of the configuration
+register can be used to define how the chip is hardwired. Please note that
+it is not a choice you have to make as the user. The choice was already
+made by your motherboard's maker. If the configuration bit isn't set
+properly, you'll have a wrong +12V reading or a wrong VID reading. The way
+the driver handles that is to preserve this bit through the initialization
+process, assuming that the BIOS set it up properly beforehand. If it turns
+out not to be true in some cases, we'll provide a module parameter to force
+modes.
+
+This driver also supports the ADM1025A, which differs from the ADM1025
+only in that it has "open-drain VID inputs while the ADM1025 has on-chip
+100k pull-ups on the VID inputs". It doesn't make any difference for us.
diff --git a/Documentation/i2c/chips/adm1026 b/Documentation/i2c/chips/adm1026
new file mode 100644 (file)
index 0000000..473c689
--- /dev/null
@@ -0,0 +1,93 @@
+Kernel driver adm1026
+=====================
+
+Supported chips:
+  * Analog Devices ADM1026
+    Prefix: 'adm1026'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: Publicly available at the Analog Devices website
+               http://www.analog.com/en/prod/0,,766_825_ADM1026,00.html
+
+Authors:
+        Philip Pokorny <ppokorny@penguincomputing.com> for Penguin Computing
+        Justin Thiessen <jthiessen@penguincomputing.com>
+
+Module Parameters
+-----------------
+
+* gpio_input: int array (min = 1, max = 17)
+  List of GPIO pins (0-16) to program as inputs
+* gpio_output: int array (min = 1, max = 17)
+  List of GPIO pins (0-16) to program as outputs
+* gpio_inverted: int array (min = 1, max = 17)
+  List of GPIO pins (0-16) to program as inverted
+* gpio_normal: int array (min = 1, max = 17)
+  List of GPIO pins (0-16) to program as normal/non-inverted
+* gpio_fan: int array (min = 1, max = 8)
+  List of GPIO pins (0-7) to program as fan tachs
+
+
+Description
+-----------
+
+This driver implements support for the Analog Devices ADM1026. Analog
+Devices calls it a "complete thermal system management controller."
+
+The ADM1026 implements three (3) temperature sensors, 17 voltage sensors,
+16 general purpose digital I/O lines, eight (8) fan speed sensors (8-bit),
+an analog output and a PWM output along with limit, alarm and mask bits for
+all of the above. There is even 8k bytes of EEPROM memory on chip.
+
+Temperatures are measured in degrees Celsius. There are two external
+sensor inputs and one internal sensor. Each sensor has a high and low
+limit. If the limit is exceeded, an interrupt (#SMBALERT) can be
+generated. The interrupts can be masked. In addition, there are over-temp
+limits for each sensor. If this limit is exceeded, the #THERM output will
+be asserted. The current temperature and limits have a resolution of 1
+degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute) but measured
+in counts of a 22.5kHz internal clock. Each fan has a high limit which
+corresponds to a minimum fan speed. If the limit is exceeded, an interrupt
+can be generated. Each fan can be programmed to divide the reference clock
+by 1, 2, 4 or 8. Not all RPM values can accurately be represented, so some
+rounding is done. With a divider of 8, the slowest measurable speed of a
+two pulse per revolution fan is 661 RPM.
+
+There are 17 voltage sensors. An alarm is triggered if the voltage has
+crossed a programmable minimum or maximum limit. Note that minimum in this
+case always means 'closest to zero'; this is important for negative voltage
+measurements. Several inputs have integrated attenuators so they can measure
+higher voltages directly. 3.3V, 5V, 12V, -12V and battery voltage all have
+dedicated inputs. There are several inputs scaled to 0-3V full-scale range
+for SCSI terminator power. The remaining inputs are not scaled and have
+a 0-2.5V full-scale range. A 2.5V or 1.82V reference voltage is provided
+for negative voltage measurements.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 2.0
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The ADM1026 measures continuously. Analog inputs are measured about 4
+times a second. Fan speed measurement time depends on fan speed and
+divisor. It can take as long as 1.5 seconds to measure all fan speeds.
+
+The ADM1026 has the ability to automatically control fan speed based on the
+temperature sensor inputs. Both the PWM output and the DAC output can be
+used to control fan speed. Usually only one of these two outputs will be
+used. Write the minimum PWM or DAC value to the appropriate control
+register. Then set the low temperature limit in the tmin values for each
+temperature sensor. The range of control is fixed at 20 °C, and the
+largest difference between current and tmin of the temperature sensors sets
+the control output. See the datasheet for several example circuits for
+controlling fan speed with the PWM and DAC outputs. The fan speed sensors
+do not have PWM compensation, so it is probably best to control the fan
+voltage from the power lead rather than on the ground lead.
+
+The datasheet shows an example application with VID signals attached to
+GPIO lines. Unfortunately, the chip may not be connected to the VID lines
+in this way. The driver assumes that the chips *is* connected this way to
+get a VID voltage.
diff --git a/Documentation/i2c/chips/adm1031 b/Documentation/i2c/chips/adm1031
new file mode 100644 (file)
index 0000000..130a383
--- /dev/null
@@ -0,0 +1,35 @@
+Kernel driver adm1031
+=====================
+
+Supported chips:
+  * Analog Devices ADM1030
+    Prefix: 'adm1030'
+    Addresses scanned: I2C 0x2c to 0x2e
+    Datasheet: Publicly available at the Analog Devices website
+               http://products.analog.com/products/info.asp?product=ADM1030
+
+  * Analog Devices ADM1031
+    Prefix: 'adm1031'
+    Addresses scanned: I2C 0x2c to 0x2e
+    Datasheet: Publicly available at the Analog Devices website
+               http://products.analog.com/products/info.asp?product=ADM1031
+
+Authors:
+        Alexandre d'Alton <alex@alexdalton.org>
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The ADM1030 and ADM1031 are digital temperature sensors and fan controllers.
+They sense their own temperature as well as the temperature of up to one
+(ADM1030) or two (ADM1031) external diodes.
+
+All temperature values are given in degrees Celsius. Resolution is 0.5
+degree for the local temperature, 0.125 degree for the remote temperatures.
+
+Each temperature channel has its own high and low limits, plus a critical
+limit.
+
+The ADM1030 monitors a single fan speed, while the ADM1031 monitors up to
+two. Each fan channel has its own low speed limit.
diff --git a/Documentation/i2c/chips/adm9240 b/Documentation/i2c/chips/adm9240
new file mode 100644 (file)
index 0000000..35f618f
--- /dev/null
@@ -0,0 +1,177 @@
+Kernel driver adm9240
+=====================
+
+Supported chips:
+  * Analog Devices ADM9240
+    Prefix: 'adm9240'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Publicly available at the Analog Devices website
+    http://www.analog.com/UploadedFiles/Data_Sheets/79857778ADM9240_0.pdf
+
+  * Dallas Semiconductor DS1780
+    Prefix: 'ds1780'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Publicly available at the Dallas Semiconductor (Maxim) website
+    http://pdfserv.maxim-ic.com/en/ds/DS1780.pdf
+
+  * National Semiconductor LM81
+    Prefix: 'lm81'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Publicly available at the National Semiconductor website
+    http://www.national.com/ds.cgi/LM/LM81.pdf
+
+Authors:
+    Frodo Looijaard <frodol@dds.nl>,
+    Philip Edelbrock <phil@netroedge.com>,
+    Michiel Rook <michiel@grendelproject.nl>,
+    Grant Coady <gcoady@gmail.com> with guidance
+        from Jean Delvare <khali@linux-fr.org>
+
+Interface
+---------
+The I2C addresses listed above assume BIOS has not changed the
+chip MSB 5-bit address. Each chip reports a unique manufacturer
+identification code as well as the chip revision/stepping level.
+
+Description
+-----------
+[From ADM9240] The ADM9240 is a complete system hardware monitor for
+microprocessor-based systems, providing measurement and limit comparison
+of up to four power supplies and two processor core voltages, plus
+temperature, two fan speeds and chassis intrusion. Measured values can
+be read out via an I2C-compatible serial System Management Bus, and values
+for limit comparisons can be programmed in over the same serial bus. The
+high speed successive approximation ADC allows frequent sampling of all
+analog channels to ensure a fast interrupt response to any out-of-limit
+measurement.
+
+The ADM9240, DS1780 and LM81 are register compatible, the following
+details are common to the three chips. Chip differences are described
+after this section.
+
+
+Measurements
+------------
+The measurement cycle
+
+The adm9240 driver will take a measurement reading no faster than once
+each two seconds. User-space may read sysfs interface faster than the
+measurement update rate and will receive cached data from the most
+recent measurement.
+
+ADM9240 has a very fast 320us temperature and voltage measurement cycle
+with independent fan speed measurement cycles counting alternating rising
+edges of the fan tacho inputs.
+
+DS1780 measurement cycle is about once per second including fan speed.
+
+LM81 measurement cycle is about once per 400ms including fan speed.
+The LM81 12-bit extended temperature measurement mode is not supported.
+
+Temperature
+-----------
+On chip temperature is reported as degrees Celsius as 9-bit signed data
+with resolution of 0.5 degrees Celsius. High and low temperature limits
+are 8-bit signed data with resolution of one degree Celsius.
+
+Temperature alarm is asserted once the temperature exceeds the high limit,
+and is cleared when the temperature falls below the temp1_max_hyst value.
+
+Fan Speed
+---------
+Two fan tacho inputs are provided, the ADM9240 gates an internal 22.5kHz
+clock via a divider to an 8-bit counter. Fan speed (rpm) is calculated by:
+
+rpm = (22500 * 60) / (count * divider)
+
+Automatic fan clock divider
+
+  * User sets 0 to fan_min limit
+    - low speed alarm is disabled
+    - fan clock divider not changed
+    - auto fan clock adjuster enabled for valid fan speed reading
+
+  * User sets fan_min limit too low
+    - low speed alarm is enabled
+    - fan clock divider set to max
+    - fan_min set to register value 254 which corresponds
+      to 664 rpm on adm9240
+    - low speed alarm will be asserted if fan speed is
+      less than minimum measurable speed
+    - auto fan clock adjuster disabled
+
+  * User sets reasonable fan speed
+    - low speed alarm is enabled
+    - fan clock divider set to suit fan_min
+    - auto fan clock adjuster enabled: adjusts fan_min
+
+  * User sets unreasonably high low fan speed limit
+    - resolution of the low speed limit may be reduced
+    - alarm will be asserted
+    - auto fan clock adjuster enabled: adjusts fan_min
+
+    * fan speed may be displayed as zero until the auto fan clock divider
+      adjuster brings fan speed clock divider back into chip measurement
+      range, this will occur within a few measurement cycles.
+
+Analog Output
+-------------
+An analog output provides a 0 to 1.25 volt signal intended for an external
+fan speed amplifier circuit. The analog output is set to maximum value on
+power up or reset. This doesn't do much on the test Intel SE440BX-2.
+
+Voltage Monitor
+
+Voltage (IN) measurement is internally scaled:
+
+    nr  label       nominal     maximum   resolution
+                      mV          mV         mV
+    0   +2.5V        2500        3320       13.0
+    1   Vccp1        2700        3600       14.1
+    2   +3.3V        3300        4380       17.2
+    3     +5V        5000        6640       26.0
+    4    +12V       12000       15940       62.5
+    5   Vccp2        2700        3600       14.1
+
+The reading is an unsigned 8-bit value, nominal voltage measurement is
+represented by a reading of 192, being 3/4 of the measurement range.
+
+An alarm is asserted for any voltage going below or above the set limits.
+
+The driver reports and accepts voltage limits scaled to the above table.
+
+VID Monitor
+-----------
+The chip has five inputs to read the 5-bit VID and reports the mV value
+based on detected CPU type.
+
+Chassis Intrusion
+-----------------
+An alarm is asserted when the CI pin goes active high. The ADM9240
+Datasheet has an example of an external temperature sensor driving
+this pin. On an Intel SE440BX-2 the Chassis Intrusion header is
+connected to a normally open switch.
+
+The ADM9240 provides an internal open drain on this line, and may output
+a 20 ms active low pulse to reset an external Chassis Intrusion latch.
+
+Clear the CI latch by writing value 1 to the sysfs chassis_clear file.
+
+Alarm flags reported as 16-bit word
+
+    bit     label               comment
+    ---     -------------       --------------------------
+     0      +2.5 V_Error        high or low limit exceeded
+     1      VCCP_Error          high or low limit exceeded
+     2      +3.3 V_Error        high or low limit exceeded
+     3      +5 V_Error          high or low limit exceeded
+     4      Temp_Error          temperature error
+     6      FAN1_Error          fan low limit exceeded
+     7      FAN2_Error          fan low limit exceeded
+     8      +12 V_Error         high or low limit exceeded
+     9      VCCP2_Error         high or low limit exceeded
+    12      Chassis_Error       CI pin went high
+
+Remaining bits are reserved and thus undefined. It is important to note
+that alarm bits may be cleared on read, user-space may latch alarms and
+provide the end-user with a method to clear alarm memory.
diff --git a/Documentation/i2c/chips/asb100 b/Documentation/i2c/chips/asb100
new file mode 100644 (file)
index 0000000..ab7365e
--- /dev/null
@@ -0,0 +1,72 @@
+Kernel driver asb100
+====================
+
+Supported Chips:
+  * Asus ASB100 and ASB100-A "Bach"
+    Prefix: 'asb100'
+    Addresses scanned: I2C 0x2d
+    Datasheet: none released
+
+Author: Mark M. Hoffman <mhoffman@lightlink.com>
+
+Description
+-----------
+
+This driver implements support for the Asus ASB100 and ASB100-A "Bach".
+These are custom ASICs available only on Asus mainboards. Asus refuses to
+supply a datasheet for these chips. Thanks go to many people who helped
+investigate their hardware, including:
+
+Vitaly V. Bursov
+Alexander van Kaam (author of MBM for Windows)
+Bertrik Sikken
+
+The ASB100 implements seven voltage sensors, three fan rotation speed
+sensors, four temperature sensors, VID lines and alarms. In addition to
+these, the ASB100-A also implements a single PWM controller for fans 2 and
+3 (i.e. one setting controls both.) If you have a plain ASB100, the PWM
+controller will simply not work (or maybe it will for you... it doesn't for
+me).
+
+Temperatures are measured and reported in degrees Celsius.
+
+Fan speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit.
+
+Voltage sensors (also known as IN sensors) report values in volts.
+
+The VID lines encode the core voltage value: the voltage level your
+processor should work with. This is hardcoded by the mainboard and/or
+processor itself. It is a value in volts.
+
+Alarms: (TODO question marks indicate may or may not work)
+
+0x0001 => in0 (?)
+0x0002 => in1 (?)
+0x0004 => in2
+0x0008 => in3
+0x0010 => temp1 (1)
+0x0020 => temp2
+0x0040 => fan1
+0x0080 => fan2
+0x0100 => in4
+0x0200 => in5 (?) (2)
+0x0400 => in6 (?) (2)
+0x0800 => fan3
+0x1000 => chassis switch
+0x2000 => temp3
+
+Alarm Notes:
+
+(1) This alarm will only trigger if the hysteresis value is 127C.
+I.e. it behaves the same as w83781d.
+
+(2) The min and max registers for these values appear to
+be read-only or otherwise stuck at 0x00.
+
+TODO:
+* Experiment with fan divisors > 8.
+* Experiment with temp. sensor types.
+* Are there really 13 voltage inputs? Probably not...
+* Cleanups, no doubt...
+
diff --git a/Documentation/i2c/chips/ds1621 b/Documentation/i2c/chips/ds1621
new file mode 100644 (file)
index 0000000..1fee6f1
--- /dev/null
@@ -0,0 +1,108 @@
+Kernel driver ds1621
+====================
+
+Supported chips:
+  * Dallas Semiconductor DS1621
+    Prefix: 'ds1621'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.dalsemi.com/
+  * Dallas Semiconductor DS1625
+    Prefix: 'ds1621'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.dalsemi.com/
+
+Authors:
+        Christian W. Zuckschwerdt <zany@triq.net>
+        valuable contributions by Jan M. Sendler <sendler@sendler.de>
+        ported to 2.6 by Aurelien Jarno <aurelien@aurel32.net>
+        with the help of Jean Delvare <khali@linux-fr.org>
+
+Module Parameters
+------------------
+
+* polarity int
+  Output's polarity: 0 = active high, 1 = active low
+
+Description
+-----------
+
+The DS1621 is a (one instance) digital thermometer and thermostat. It has
+both high and low temperature limits which can be user defined (i.e.
+programmed into non-volatile on-chip registers). Temperature range is -55
+degree Celsius to +125 in 0.5 increments. You may convert this into a
+Fahrenheit range of -67 to +257 degrees with 0.9 steps. If polarity
+parameter is not provided, original value is used.
+
+As for the thermostat, behavior can also be programmed using the polarity
+toggle. On the one hand ("heater"), the thermostat output of the chip,
+Tout, will trigger when the low limit temperature is met or underrun and
+stays high until the high limit is met or exceeded. On the other hand
+("cooler"), vice versa. That way "heater" equals "active low", whereas
+"conditioner" equals "active high". Please note that the DS1621 data sheet
+is somewhat misleading in this point since setting the polarity bit does
+not simply invert Tout.
+
+A second thing is that, during extensive testing, Tout showed a tolerance
+of up to +/- 0.5 degrees even when compared against precise temperature
+readings. Be sure to have a high vs. low temperature limit gap of al least
+1.0 degree Celsius to avoid Tout "bouncing", though!
+
+As for alarms, you can read the alarm status of the DS1621 via the 'alarms'
+/sys file interface. The result consists mainly of bit 6 and 5 of the
+configuration register of the chip; bit 6 (0x40 or 64) is the high alarm
+bit and bit 5 (0x20 or 32) the low one. These bits are set when the high or
+low limits are met or exceeded and are reset by the module as soon as the
+respective temperature ranges are left.
+
+The alarm registers are in no way suitable to find out about the actual
+status of Tout. They will only tell you about its history, whether or not
+any of the limits have ever been met or exceeded since last power-up or
+reset. Be aware: When testing, it showed that the status of Tout can change
+with neither of the alarms set.
+
+Temperature conversion of the DS1621 takes up to 1000ms; internal access to
+non-volatile registers may last for 10ms or below.
+
+High Accuracy Temperature Reading
+---------------------------------
+
+As said before, the temperature issued via the 9-bit i2c-bus data is
+somewhat arbitrary. Internally, the temperature conversion is of a
+different kind that is explained (not so...) well in the DS1621 data sheet.
+To cut the long story short: Inside the DS1621 there are two oscillators,
+both of them biassed by a temperature coefficient.
+
+Higher resolution of the temperature reading can be achieved using the
+internal projection, which means taking account of REG_COUNT and REG_SLOPE
+(the driver manages them):
+
+Taken from Dallas Semiconductors App Note 068: 'Increasing Temperature
+Resolution on the DS1620' and App Note 105: 'High Resolution Temperature
+Measurement with Dallas Direct-to-Digital Temperature Sensors'
+
+- Read the 9-bit temperature and strip the LSB (Truncate the .5 degs)
+- The resulting value is TEMP_READ.
+- Then, read REG_COUNT.
+- And then, REG_SLOPE.
+
+      TEMP = TEMP_READ - 0.25 + ((REG_SLOPE - REG_COUNT) / REG_SLOPE)
+
+Note that this is what the DONE bit in the DS1621 configuration register is
+good for: Internally, one temperature conversion takes up to 1000ms. Before
+that conversion is complete you will not be able to read valid things out
+of REG_COUNT and REG_SLOPE. The DONE bit, as you may have guessed by now,
+tells you whether the conversion is complete ("done", in plain English) and
+thus, whether the values you read are good or not.
+
+The DS1621 has two modes of operation: "Continuous" conversion, which can
+be understood as the default stand-alone mode where the chip gets the
+temperature and controls external devices via its Tout pin or tells other
+i2c's about it if they care. The other mode is called "1SHOT", that means
+that it only figures out about the temperature when it is explicitly told
+to do so; this can be seen as power saving mode.
+
+Now if you want to read REG_COUNT and REG_SLOPE, you have to either stop
+the continuous conversions until the contents of these registers are valid,
+or, in 1SHOT mode, you have to have one conversion made.
diff --git a/Documentation/i2c/chips/eeprom b/Documentation/i2c/chips/eeprom
new file mode 100644 (file)
index 0000000..f7e8104
--- /dev/null
@@ -0,0 +1,96 @@
+Kernel driver eeprom
+====================
+
+Supported chips:
+  * Any EEPROM chip in the designated address range
+    Prefix: 'eeprom'
+    Addresses scanned: I2C 0x50 - 0x57
+    Datasheets: Publicly available from:
+                Atmel (www.atmel.com),
+                Catalyst (www.catsemi.com),
+                Fairchild (www.fairchildsemi.com),
+                Microchip (www.microchip.com),
+                Philips (www.semiconductor.philips.com),
+                Rohm (www.rohm.com),
+                ST (www.st.com),
+                Xicor (www.xicor.com),
+                and others.
+
+        Chip     Size (bits)    Address
+        24C01     1K            0x50 (shadows at 0x51 - 0x57)
+        24C01A    1K            0x50 - 0x57 (Typical device on DIMMs)
+        24C02     2K            0x50 - 0x57
+        24C04     4K            0x50, 0x52, 0x54, 0x56
+                                (additional data at 0x51, 0x53, 0x55, 0x57)
+        24C08     8K            0x50, 0x54 (additional data at 0x51, 0x52,
+                                0x53, 0x55, 0x56, 0x57)
+        24C16    16K            0x50 (additional data at 0x51 - 0x57)
+        Sony      2K            0x57
+
+        Atmel     34C02B  2K    0x50 - 0x57, SW write protect at 0x30-37
+        Catalyst  34FC02  2K    0x50 - 0x57, SW write protect at 0x30-37
+        Catalyst  34RC02  2K    0x50 - 0x57, SW write protect at 0x30-37
+        Fairchild 34W02   2K    0x50 - 0x57, SW write protect at 0x30-37
+        Microchip 24AA52  2K    0x50 - 0x57, SW write protect at 0x30-37
+        ST        M34C02  2K    0x50 - 0x57, SW write protect at 0x30-37
+
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Jean Delvare <khali@linux-fr.org>,
+        Greg Kroah-Hartman <greg@kroah.com>,
+        IBM Corp.
+
+Description
+-----------
+
+This is a simple EEPROM module meant to enable reading the first 256 bytes
+of an EEPROM (on a SDRAM DIMM for example). However, it will access serial
+EEPROMs on any I2C adapter. The supported devices are generically called
+24Cxx, and are listed above; however the numbering for these
+industry-standard devices may vary by manufacturer.
+
+This module was a programming exercise to get used to the new project
+organization laid out by Frodo, but it should be at least completely
+effective for decoding the contents of EEPROMs on DIMMs.
+
+DIMMS will typically contain a 24C01A or 24C02, or the 34C02 variants.
+The other devices will not be found on a DIMM because they respond to more
+than one address.
+
+DDC Monitors may contain any device. Often a 24C01, which responds to all 8
+addresses, is found.
+
+Recent Sony Vaio laptops have an EEPROM at 0x57. We couldn't get the
+specification, so it is guess work and far from being complete.
+
+The Microchip 24AA52/24LCS52, ST M34C02, and others support an additional
+software write protect register at 0x30 - 0x37 (0x20 less than the memory
+location). The chip responds to "write quick" detection at this address but
+does not respond to byte reads. If this register is present, the lower 128
+bytes of the memory array are not write protected. Any byte data write to
+this address will write protect the memory array permanently, and the
+device will no longer respond at the 0x30-37 address. The eeprom driver
+does not support this register.
+
+Lacking functionality:
+
+* Full support for larger devices (24C04, 24C08, 24C16). These are not
+typically found on a PC. These devices will appear as separate devices at
+multiple addresses.
+
+* Support for really large devices (24C32, 24C64, 24C128, 24C256, 24C512).
+These devices require two-byte address fields and are not supported.
+
+* Enable Writing. Again, no technical reason why not, but making it easy
+to change the contents of the EEPROMs (on DIMMs anyway) also makes it easy
+to disable the DIMMs (potentially preventing the computer from booting)
+until the values are restored somehow.
+
+Use:
+
+After inserting the module (and any other required SMBus/i2c modules), you
+should have some EEPROM directories in /sys/bus/i2c/devices/* of names such
+as "0-0050". Inside each of these is a series of files, the eeprom file
+contains the binary data from EEPROM.
diff --git a/Documentation/i2c/chips/fscher b/Documentation/i2c/chips/fscher
new file mode 100644 (file)
index 0000000..6403165
--- /dev/null
@@ -0,0 +1,169 @@
+Kernel driver fscher
+====================
+
+Supported chips:
+  * Fujitsu-Siemens Hermes chip
+    Prefix: 'fscher'
+    Addresses scanned: I2C 0x73
+
+Authors:
+        Reinhard Nissl <rnissl@gmx.de> based on work
+        from Hermann Jung <hej@odn.de>,
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>
+
+Description
+-----------
+
+This driver implements support for the Fujitsu-Siemens Hermes chip. It is
+described in the 'Register Set Specification BMC Hermes based Systemboard'
+from Fujitsu-Siemens.
+
+The Hermes chip implements a hardware-based system management, e.g. for
+controlling fan speed and core voltage. There is also a watchdog counter on
+the chip which can trigger an alarm and even shut the system down.
+
+The chip provides three temperature values (CPU, motherboard and
+auxiliary), three voltage values (+12V, +5V and battery) and three fans
+(power supply, CPU and auxiliary).
+
+Temperatures are measured in degrees Celsius. The resolution is 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). The value
+can be divided by a programmable divider (1, 2 or 4) which is stored on
+the chip.
+
+Voltage sensors (also known as "in" sensors) report their values in volts.
+
+All values are reported as final values from the driver. There is no need
+for further calculations.
+
+
+Detailed description
+--------------------
+
+Below you'll find a single line description of all the bit values. With
+this information, you're able to decode e. g. alarms, wdog, etc. To make
+use of the watchdog, you'll need to set the watchdog time and enable the
+watchdog. After that it is necessary to restart the watchdog time within
+the specified period of time, or a system reset will occur.
+
+* revision
+  READING & 0xff = 0x??: HERMES revision identification
+
+* alarms
+  READING & 0x80 = 0x80: CPU throttling active
+  READING & 0x80 = 0x00: CPU running at full speed
+
+  READING & 0x10 = 0x10: software event (see control:1)
+  READING & 0x10 = 0x00: no software event
+
+  READING & 0x08 = 0x08: watchdog event (see wdog:2)
+  READING & 0x08 = 0x00: no watchdog event
+
+  READING & 0x02 = 0x02: thermal event (see temp*:1)
+  READING & 0x02 = 0x00: no thermal event
+
+  READING & 0x01 = 0x01: fan event (see fan*:1)
+  READING & 0x01 = 0x00: no fan event
+
+  READING & 0x13 ! 0x00: ALERT LED is flashing
+
+* control
+  READING & 0x01 = 0x01: software event
+  READING & 0x01 = 0x00: no software event
+
+  WRITING & 0x01 = 0x01: set software event
+  WRITING & 0x01 = 0x00: clear software event
+
+* watchdog_control
+  READING & 0x80 = 0x80: power off on watchdog event while thermal event
+  READING & 0x80 = 0x00: watchdog power off disabled (just system reset enabled)
+
+  READING & 0x40 = 0x40: watchdog timebase 60 seconds (see also wdog:1)
+  READING & 0x40 = 0x00: watchdog timebase  2 seconds
+
+  READING & 0x10 = 0x10: watchdog enabled
+  READING & 0x10 = 0x00: watchdog disabled
+
+  WRITING & 0x80 = 0x80: enable "power off on watchdog event while thermal event"
+  WRITING & 0x80 = 0x00: disable "power off on watchdog event while thermal event"
+
+  WRITING & 0x40 = 0x40: set watchdog timebase to 60 seconds
+  WRITING & 0x40 = 0x00: set watchdog timebase to  2 seconds
+
+  WRITING & 0x20 = 0x20: disable watchdog
+
+  WRITING & 0x10 = 0x10: enable watchdog / restart watchdog time
+
+* watchdog_state
+  READING & 0x02 = 0x02: watchdog system reset occurred
+  READING & 0x02 = 0x00: no watchdog system reset occurred
+
+  WRITING & 0x02 = 0x02: clear watchdog event
+
+* watchdog_preset
+  READING & 0xff = 0x??: configured watch dog time in units (see wdog:3 0x40)
+
+  WRITING & 0xff = 0x??: configure watch dog time in units
+
+* in*     (0: +5V, 1: +12V, 2: onboard 3V battery)
+  READING: actual voltage value
+
+* temp*_status   (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor)
+  READING & 0x02 = 0x02: thermal event (overtemperature)
+  READING & 0x02 = 0x00: no thermal event
+
+  READING & 0x01 = 0x01: sensor is working
+  READING & 0x01 = 0x00: sensor is faulty
+
+  WRITING & 0x02 = 0x02: clear thermal event
+
+* temp*_input   (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor)
+  READING: actual temperature value
+
+* fan*_status   (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+  READING & 0x04 = 0x04: fan event (fan fault)
+  READING & 0x04 = 0x00: no fan event
+
+  WRITING & 0x04 = 0x04: clear fan event
+
+* fan*_div (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+       Divisors 2,4 and 8 are supported, both for reading and writing
+
+* fan*_pwm   (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+  READING & 0xff = 0x00: fan may be switched off
+  READING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V)
+  READING & 0xff = 0xff: fan must run at maximum speed (supply: 12V)
+  READING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V)
+
+  WRITING & 0xff = 0x00: fan may be switched off
+  WRITING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V)
+  WRITING & 0xff = 0xff: fan must run at maximum speed (supply: 12V)
+  WRITING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V)
+
+* fan*_input   (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+  READING: actual RPM value
+
+
+Limitations
+-----------
+
+* Measuring fan speed
+It seems that the chip counts "ripples" (typical fans produce 2 ripples per
+rotation while VERAX fans produce 18) in a 9-bit register. This register is
+read out every second, then the ripple prescaler (2, 4 or 8) is applied and
+the result is stored in the 8 bit output register. Due to the limitation of
+the counting register to 9 bits, it is impossible to measure a VERAX fan
+properly (even with a prescaler of 8). At its maximum speed of 3500 RPM the
+fan produces 1080 ripples per second which causes the counting register to
+overflow twice, leading to only 186 RPM.
+
+* Measuring input voltages
+in2 ("battery") reports the voltage of the onboard lithium battery and not
++3.3V from the power supply.
+
+* Undocumented features
+Fujitsu-Siemens Computers has not documented all features of the chip so
+far. Their software, System Guard, shows that there are a still some
+features which cannot be controlled by this implementation.
diff --git a/Documentation/i2c/chips/gl518sm b/Documentation/i2c/chips/gl518sm
new file mode 100644 (file)
index 0000000..ce08818
--- /dev/null
@@ -0,0 +1,74 @@
+Kernel driver gl518sm
+=====================
+
+Supported chips:
+  * Genesys Logic GL518SM release 0x00
+    Prefix: 'gl518sm'
+    Addresses scanned: I2C 0x2c and 0x2d
+    Datasheet: http://www.genesyslogic.com/pdf
+  * Genesys Logic GL518SM release 0x80
+    Prefix: 'gl518sm'
+    Addresses scanned: I2C 0x2c and 0x2d
+    Datasheet: http://www.genesyslogic.com/pdf
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Kyösti Mälkki <kmalkki@cc.hut.fi>
+        Hong-Gunn Chew <hglinux@gunnet.org>
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+IMPORTANT:
+
+For the revision 0x00 chip, the in0, in1, and in2  values (+5V, +3V,
+and +12V) CANNOT be read. This is a limitation of the chip, not the driver.
+
+This driver supports the Genesys Logic GL518SM chip. There are at least
+two revision of this chip, which we call revision 0x00 and 0x80. Revision
+0x80 chips support the reading of all voltages and revision 0x00 only
+for VIN3.
+
+The GL518SM implements one temperature sensor, two fan rotation speed
+sensors, and four voltage sensors. It can report alarms through the
+computer speakers.
+
+Temperatures are measured in degrees Celsius. An alarm goes off while the
+temperature is above the over temperature limit, and has not yet dropped
+below the hysteresis limit. The alarm always reflects the current
+situation. Measurements are guaranteed between -10 degrees and +110
+degrees, with a accuracy of +/-3 degrees.
+
+Rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. In
+case when you have selected to turn fan1 off, no fan1 alarm is triggered.
+
+Fan readings can be divided by a programmable divider (1, 2, 4 or 8) to
+give the readings more range or accuracy.  Not all RPM values can
+accurately be represented, so some rounding is done. With a divider
+of 2, the lowest representable value is around 1900 RPM.
+
+Voltage sensors (also known as VIN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. The VDD input
+measures voltages between 0.000 and 5.865 volt, with a resolution of 0.023
+volt. The other inputs measure voltages between 0.000 and 4.845 volt, with
+a resolution of 0.019 volt. Note that revision 0x00 chips do not support
+reading the current voltage of any input except for VIN3; limit setting and
+alarms work fine, though.
+
+When an alarm is triggered, you can be warned by a beeping signal through your
+computer speaker. It is possible to enable all beeping globally, or only the
+beeping for some alarms.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once (except for temperature alarms). This means that the
+cause for the alarm may already have disappeared! Note that in the current
+implementation, all hardware registers are read whenever any data is read
+(unless it is less than 1.5 seconds since the last update). This means that
+you can easily miss once-only alarms.
+
+The GL518SM only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/it87 b/Documentation/i2c/chips/it87
new file mode 100644 (file)
index 0000000..0d01950
--- /dev/null
@@ -0,0 +1,96 @@
+Kernel driver it87
+==================
+
+Supported chips:
+  * IT8705F
+    Prefix: 'it87'
+    Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the ITE website
+               http://www.ite.com.tw/
+  * IT8712F
+    Prefix: 'it8712'
+    Addresses scanned: I2C 0x28 - 0x2f
+                       from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the ITE website
+               http://www.ite.com.tw/
+  * SiS950   [clone of IT8705F]
+    Prefix: 'sis950'
+    Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+    Datasheet: No longer be available
+
+Author: Christophe Gauthron <chrisg@0-in.com>
+
+
+Module Parameters
+-----------------
+
+* update_vbat: int
+
+  0 if vbat should report power on value, 1 if vbat should be updated after
+  each read. Default is 0. On some boards the battery voltage is provided
+  by either the battery or the onboard power supply. Only the first reading
+  at power on will be the actual battery voltage (which the chip does
+  automatically). On other boards the battery voltage is always fed to
+  the chip so can be read at any time. Excessive reading may decrease
+  battery life but no information is given in the datasheet.
+
+* fix_pwm_polarity int
+
+  Force PWM polarity to active high (DANGEROUS). Some chips are
+  misconfigured by BIOS - PWM values would be inverted. This option tries
+  to fix this. Please contact your BIOS manufacturer and ask him for fix.
+
+Description
+-----------
+
+This driver implements support for the IT8705F, IT8712F and SiS950 chips.
+
+This driver also supports IT8712F, which adds SMBus access, and a VID
+input, used to report the Vcore voltage of the Pentium processor.
+The IT8712F additionally features VID inputs.
+
+These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
+joysticks and other miscellaneous stuff. For hardware monitoring, they
+include an 'environment controller' with 3 temperature sensors, 3 fan
+rotation speed sensors, 8 voltage sensors, and associated alarms.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give the
+readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts. An
+alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution of
+0.016 volt. The battery voltage in8 does not have limit registers.
+
+The VID lines (IT8712F only) encode the core voltage value: the voltage
+level your processor should work with. This is hardcoded by the mainboard
+and/or processor itself. It is a value in volts.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 1.5
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The IT87xx only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+To change sensor N to a thermistor, 'echo 2 > tempN_type' where N is 1, 2,
+or 3. To change sensor N to a thermal diode, 'echo 3 > tempN_type'.
+Give 0 for unused sensor. Any other value is invalid. To configure this at
+startup, consult lm_sensors's /etc/sensors.conf. (2 = thermistor;
+3 = thermal diode)
+
+The fan speed control features are limited to manual PWM mode. Automatic
+"Smart Guardian" mode control handling is not implemented. However
+if you want to go for "manual mode" just write 1 to pwmN_enable.
diff --git a/Documentation/i2c/chips/lm63 b/Documentation/i2c/chips/lm63
new file mode 100644 (file)
index 0000000..31660bf
--- /dev/null
@@ -0,0 +1,57 @@
+Kernel driver lm63
+==================
+
+Supported chips:
+  * National Semiconductor LM63
+    Prefix: 'lm63'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM63.html
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Thanks go to Tyan and especially Alex Buckingham for setting up a remote
+access to their S4882 test platform for this driver.
+  http://www.tyan.com/
+
+Description
+-----------
+
+The LM63 is a digital temperature sensor with integrated fan monitoring
+and control.
+
+The LM63 is basically an LM86 with fan speed monitoring and control
+capabilities added. It misses some of the LM86 features though:
+ - No low limit for local temperature.
+ - No critical limit for local temperature.
+ - Critical limit for remote temperature can be changed only once. We
+   will consider that the critical limit is read-only.
+
+The datasheet isn't very clear about what the tachometer reading is.
+
+An explanation from National Semiconductor: The two lower bits of the read
+value have to be masked out. The value is still 16 bit in width.
+
+All temperature values are given in degrees Celsius. Resolution is 1.0
+degree for the local temperature, 0.125 degree for the remote temperature.
+
+The fan speed is measured using a tachometer. Contrary to most chips which
+store the value in an 8-bit register and have a selectable clock divider
+to make sure that the result will fit in the register, the LM63 uses 16-bit
+value for measuring the speed of the fan. It can measure fan speeds down to
+83 RPM, at least in theory.
+
+Note that the pin used for fan monitoring is shared with an alert out
+function. Depending on how the board designer wanted to use the chip, fan
+speed monitoring will or will not be possible. The proper chip configuration
+is left to the BIOS, and the driver will blindly trust it.
+
+A PWM output can be used to control the speed of the fan. The LM63 has two
+PWM modes: manual and automatic. Automatic mode is not fully implemented yet
+(you cannot define your custom PWM/temperature curve), and mode change isn't
+supported either.
+
+The lm63 driver will not update its values more frequently than every
+second; reading them more often will do no harm, but will return 'old'
+values.
+
diff --git a/Documentation/i2c/chips/lm75 b/Documentation/i2c/chips/lm75
new file mode 100644 (file)
index 0000000..8e6356f
--- /dev/null
@@ -0,0 +1,65 @@
+Kernel driver lm75
+==================
+
+Supported chips:
+  * National Semiconductor LM75
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+  * Dallas Semiconductor DS75
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.maxim-ic.com/
+  * Dallas Semiconductor DS1775
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.maxim-ic.com/
+  * Maxim MAX6625, MAX6626
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4b
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/
+  * Microchip (TelCom) TCN75
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Microchip website
+               http://www.microchip.com/
+
+Author: Frodo Looijaard <frodol@dds.nl>
+
+Description
+-----------
+
+The LM75 implements one temperature sensor. Limits can be set through the
+Overtemperature Shutdown register and Hysteresis register. Each value can be
+set and read to half-degree accuracy.
+An alarm is issued (usually to a connected LM78) when the temperature
+gets higher then the Overtemperature Shutdown value; it stays on until
+the temperature falls below the Hysteresis value.
+All temperatures are in degrees Celsius, and are guaranteed within a
+range of -55 to +125 degrees.
+
+The LM75 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+The LM75 is usually used in combination with LM78-like chips, to measure
+the temperature of the processor(s).
+
+The DS75, DS1775, MAX6625, and MAX6626 are supported as well.
+They are not distinguished from an LM75. While most of these chips
+have three additional bits of accuracy (12 vs. 9 for the LM75),
+the additional bits are not supported. Not only that, but these chips will
+not be detected if not in 9-bit precision mode (use the force parameter if
+needed).
+
+The TCN75 is supported as well, and is not distinguished from an LM75.
+
+The LM75 is essentially an industry standard; there may be other
+LM75 clones not listed here, with or without various enhancements,
+that are supported.
+
+The LM77 is not supported, contrary to what we pretended for a long time.
+Both chips are simply not compatible, value encoding differs.
diff --git a/Documentation/i2c/chips/lm77 b/Documentation/i2c/chips/lm77
new file mode 100644 (file)
index 0000000..57c3a46
--- /dev/null
@@ -0,0 +1,22 @@
+Kernel driver lm77
+==================
+
+Supported chips:
+  * National Semiconductor LM77
+    Prefix: 'lm77'
+    Addresses scanned: I2C 0x48 - 0x4b
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+
+Author: Andras BALI <drewie@freemail.hu>
+
+Description
+-----------
+
+The LM77 implements one temperature sensor. The temperature
+sensor incorporates a band-gap type temperature sensor,
+10-bit ADC, and a digital comparator with user-programmable upper
+and lower limit values.
+
+Limits can be set through the Overtemperature Shutdown register and
+Hysteresis register.
diff --git a/Documentation/i2c/chips/lm78 b/Documentation/i2c/chips/lm78
new file mode 100644 (file)
index 0000000..357086e
--- /dev/null
@@ -0,0 +1,82 @@
+Kernel driver lm78
+==================
+
+Supported chips:
+  * National Semiconductor LM78
+    Prefix: 'lm78'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+  * National Semiconductor LM78-J
+    Prefix: 'lm78-j'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+  * National Semiconductor LM79
+    Prefix: 'lm79'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+
+Author: Frodo Looijaard <frodol@dds.nl>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM78, LM78-J
+and LM79. They are described as 'Microprocessor System Hardware Monitors'.
+
+There is almost no difference between the three supported chips. Functionally,
+the LM78 and LM78-J are exactly identical. The LM79 has one more VID line,
+which is used to report the lower voltages newer Pentium processors use.
+From here on, LM7* means either of these three types.
+
+The LM7* implements one temperature sensor, three fan rotation speed sensors,
+seven voltage sensors, VID lines, alarms, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed; it is triggered again
+as soon as it drops below the Hysteresis value. A more useful behavior
+can be found by setting the Hysteresis value to +127 degrees Celsius; in
+this case, alarms are issued during all the time when the actual temperature
+is above the Overtemperature Shutdown value. Measurements are guaranteed
+between -55 and +125 degrees, with a resolution of 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution
+of 0.016 volt.
+
+The VID lines encode the core voltage value: the voltage level your processor
+should work with. This is hardcoded by the mainboard and/or processor itself.
+It is a value in volts. When it is unconnected, you will often find the
+value 3.50 V here.
+
+In addition to the alarms described above, there are a couple of additional
+ones. There is a BTI alarm, which gets triggered when an external chip has
+crossed its limits. Usually, this is connected to all LM75 chips; if at
+least one crosses its limits, this bit gets set. The CHAS alarm triggers
+if your computer case is open. The FIFO alarms should never trigger; it
+indicates an internal error. The SMI_IN alarm indicates some other chip
+has triggered an SMI interrupt. As we do not use SMI interrupts at all,
+this condition usually indicates there is a problem with some other
+device.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The LM7* only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/lm80 b/Documentation/i2c/chips/lm80
new file mode 100644 (file)
index 0000000..cb5b407
--- /dev/null
@@ -0,0 +1,56 @@
+Kernel driver lm80
+==================
+
+Supported chips:
+  * National Semiconductor LM80
+    Prefix: 'lm80'
+    Addresses scanned: I2C 0x28 - 0x2f
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM80.
+It is described as a 'Serial Interface ACPI-Compatible Microprocessor
+System Hardware Monitor'.
+
+The LM80 implements one temperature sensor, two fan rotation speed sensors,
+seven voltage sensors, alarms, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. There are two sets of limits
+which operate independently. When the HOT Temperature Limit is crossed,
+this will cause an alarm that will be reasserted until the temperature
+drops below the HOT Hysteresis. The Overtemperature Shutdown (OS) limits
+should work in the same way (but this must be checked; the datasheet
+is unclear about this). Measurements are guaranteed between -55 and
++125 degrees. The current temperature measurement has a resolution of
+0.0625 degrees; the limits have a resolution of 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 2.55 volts, with a resolution
+of 0.01 volt.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 2.0 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The LM80 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/lm83 b/Documentation/i2c/chips/lm83
new file mode 100644 (file)
index 0000000..061d9ed
--- /dev/null
@@ -0,0 +1,76 @@
+Kernel driver lm83
+==================
+
+Supported chips:
+  * National Semiconductor LM83
+    Prefix: 'lm83'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM83.html
+
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The LM83 is a digital temperature sensor. It senses its own temperature as
+well as the temperature of up to three external diodes. It is compatible
+with many other devices such as the LM84 and all other ADM1021 clones.
+The main difference between the LM83 and the LM84 in that the later can
+only sense the temperature of one external diode.
+
+Using the adm1021 driver for a LM83 should work, but only two temperatures
+will be reported instead of four.
+
+The LM83 is only found on a handful of motherboards. Both a confirmed
+list and an unconfirmed list follow. If you can confirm or infirm the
+fact that any of these motherboards do actually have an LM83, please
+contact us. Note that the LM90 can easily be misdetected as a LM83.
+
+Confirmed motherboards:
+    SBS         P014
+
+Unconfirmed motherboards:
+    Gigabyte    GA-8IK1100
+    Iwill       MPX2
+    Soltek      SL-75DRV5
+
+The driver has been successfully tested by Magnus Forsström, who I'd
+like to thank here. More testers will be of course welcome.
+
+The fact that the LM83 is only scarcely used can be easily explained.
+Most motherboards come with more than just temperature sensors for
+health monitoring. They also have voltage and fan rotation speed
+sensors. This means that temperature-only chips are usually used as
+secondary chips coupled with another chip such as an IT8705F or similar
+chip, which provides more features. Since systems usually need three
+temperature sensors (motherboard, processor, power supply) and primary
+chips provide some temperature sensors, the secondary chip, if needed,
+won't have to handle more than two temperatures. Thus, ADM1021 clones
+are sufficient, and there is no need for a four temperatures sensor
+chip such as the LM83. The only case where using an LM83 would make
+sense is on SMP systems, such as the above-mentioned Iwill MPX2,
+because you want an additional temperature sensor for each additional
+CPU.
+
+On the SBS P014, this is different, since the LM83 is the only hardware
+monitoring chipset. One temperature sensor is used for the motherboard
+(actually measuring the LM83's own temperature), one is used for the
+CPU. The two other sensors must be used to measure the temperature of
+two other points of the motherboard. We suspect these points to be the
+north and south bridges, but this couldn't be confirmed.
+
+All temperature values are given in degrees Celsius. Local temperature
+is given within a range of 0 to +85 degrees. Remote temperatures are
+given within a range of 0 to +125 degrees. Resolution is 1.0 degree,
+accuracy is guaranteed to 3.0 degrees (see the datasheet for more
+details).
+
+Each sensor has its own high limit, but the critical limit is common to
+all four sensors. There is no hysteresis mechanism as found on most
+recent temperature sensors.
+
+The lm83 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
diff --git a/Documentation/i2c/chips/lm85 b/Documentation/i2c/chips/lm85
new file mode 100644 (file)
index 0000000..9549237
--- /dev/null
@@ -0,0 +1,221 @@
+Kernel driver lm85
+==================
+
+Supported chips:
+  * National Semiconductor LM85 (B and C versions)
+    Prefix: 'lm85'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.national.com/pf/LM/LM85.html
+  * Analog Devices ADM1027
+    Prefix: 'adm1027'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.analog.com/en/prod/0,,766_825_ADM1027,00.html
+  * Analog Devices ADT7463
+    Prefix: 'adt7463'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.analog.com/en/prod/0,,766_825_ADT7463,00.html
+  * SMSC EMC6D100, SMSC EMC6D101
+    Prefix: 'emc6d100'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.smsc.com/main/tools/discontinued/6d100.pdf
+  * SMSC EMC6D102
+    Prefix: 'emc6d102'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.smsc.com/main/catalog/emc6d102.html
+
+Authors:
+        Philip Pokorny <ppokorny@penguincomputing.com>,
+        Frodo Looijaard <frodol@dds.nl>,
+        Richard Barrington <rich_b_nz@clear.net.nz>,
+        Margit Schubert-While <margitsw@t-online.de>,
+        Justin Thiessen <jthiessen@penguincomputing.com>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM85 and
+compatible chips including the Analog Devices ADM1027, ADT7463 and
+SMSC EMC6D10x chips family.
+
+The LM85 uses the 2-wire interface compatible with the SMBUS 2.0
+specification. Using an analog to digital converter it measures three (3)
+temperatures and five (5) voltages. It has four (4) 16-bit counters for
+measuring fan speed. Five (5) digital inputs are provided for sampling the
+VID signals from the processor to the VRM. Lastly, there are three (3) PWM
+outputs that can be used to control fan speed.
+
+The voltage inputs have internal scaling resistors so that the following
+voltage can be measured without external resistors:
+
+  2.5V, 3.3V, 5V, 12V, and CPU core voltage (2.25V)
+
+The temperatures measured are one internal diode, and two remote diodes.
+Remote 1 is generally the CPU temperature. These inputs are designed to
+measure a thermal diode like the one in a Pentium 4 processor in a socket
+423 or socket 478 package. They can also measure temperature using a
+transistor like the 2N3904.
+
+A sophisticated control system for the PWM outputs is designed into the
+LM85 that allows fan speed to be adjusted automatically based on any of the
+three temperature sensors. Each PWM output is individually adjustable and
+programmable. Once configured, the LM85 will adjust the PWM outputs in
+response to the measured temperatures without further host intervention.
+This feature can also be disabled for manual control of the PWM's.
+
+Each of the measured inputs (voltage, temperature, fan speed) has
+corresponding high/low limit values. The LM85 will signal an ALARM if any
+measured value exceeds either limit.
+
+The LM85 samples all inputs continuously. The lm85 driver will not read
+the registers more often than once a second. Further, configuration data is
+only read once each 5 minutes. There is twice as much config data as
+measurements, so this would seem to be a worthwhile optimization.
+
+Special Features
+----------------
+
+The LM85 has four fan speed monitoring modes. The ADM1027 has only two.
+Both have special circuitry to compensate for PWM interactions with the
+TACH signal from the fans. The ADM1027 can be configured to measure the
+speed of a two wire fan, but the input conditioning circuitry is different
+for 3-wire and 2-wire mode. For this reason, the 2-wire fan modes are not
+exposed to user control. The BIOS should initialize them to the correct
+mode. If you've designed your own ADM1027, you'll have to modify the
+init_client function and add an insmod parameter to set this up.
+
+To smooth the response of fans to changes in temperature, the LM85 has an
+optional filter for smoothing temperatures. The ADM1027 has the same
+config option but uses it to rate limit the changes to fan speed instead.
+
+The ADM1027 and ADT7463 have a 10-bit ADC and can therefore measure
+temperatures with 0.25 degC resolution. They also provide an offset to the
+temperature readings that is automatically applied during measurement.
+This offset can be used to zero out any errors due to traces and placement.
+The documentation says that the offset is in 0.25 degC steps, but in
+initial testing of the ADM1027 it was 1.00 degC steps. Analog Devices has
+confirmed this "bug". The ADT7463 is reported to work as described in the
+documentation. The current lm85 driver does not show the offset register.
+
+The ADT7463 has a THERM asserted counter. This counter has a 22.76ms
+resolution and a range of 5.8 seconds. The driver implements a 32-bit
+accumulator of the counter value to extend the range to over a year. The
+counter will stay at it's max value until read.
+
+See the vendor datasheets for more information. There is application note
+from National (AN-1260) with some additional information about the LM85.
+The Analog Devices datasheet is very detailed and describes a procedure for
+determining an optimal configuration for the automatic PWM control.
+
+The SMSC EMC6D100 & EMC6D101 monitor external voltages, temperatures, and
+fan speeds. They use this monitoring capability to alert the system to out
+of limit conditions and can automatically control the speeds of multiple
+fans in a PC or embedded system. The EMC6D101, available in a 24-pin SSOP
+package, and the EMC6D100, available in a 28-pin SSOP package, are designed
+to be register compatible. The EMC6D100 offers all the features of the
+EMC6D101 plus additional voltage monitoring and system control features.
+Unfortunately it is not possible to distinguish between the package
+versions on register level so these additional voltage inputs may read
+zero. The EMC6D102 features addtional ADC bits thus extending precision
+of voltage and temperature channels.
+
+
+Hardware Configurations
+-----------------------
+
+The LM85 can be jumpered for 3 different SMBus addresses. There are
+no other hardware configuration options for the LM85.
+
+The lm85 driver detects both LM85B and LM85C revisions of the chip. See the
+datasheet for a complete description of the differences. Other than
+identifying the chip, the driver behaves no differently with regard to
+these two chips. The LM85B is recommended for new designs.
+
+The ADM1027 and ADT7463 chips have an optional SMBALERT output that can be
+used to signal the chipset in case a limit is exceeded or the temperature
+sensors fail. Individual sensor interrupts can be masked so they won't
+trigger SMBALERT. The SMBALERT output if configured replaces one of the other
+functions (PWM2 or IN0). This functionality is not implemented in current
+driver.
+
+The ADT7463 also has an optional THERM output/input which can be connected
+to the processor PROC_HOT output. If available, the autofan control
+dynamic Tmin feature can be enabled to keep the system temperature within
+spec (just?!) with the least possible fan noise.
+
+Configuration Notes
+-------------------
+
+Besides standard interfaces driver adds following:
+
+* Temperatures and Zones
+
+Each temperature sensor is associated with a Zone. There are three
+sensors and therefore three zones (# 1, 2 and 3). Each zone has the following
+temperature configuration points:
+
+* temp#_auto_temp_off - temperature below which fans should be off or spinning very low.
+* temp#_auto_temp_min - temperature over which fans start to spin.
+* temp#_auto_temp_max - temperature when fans spin at full speed.
+* temp#_auto_temp_crit - temperature when all fans will run full speed.
+
+* PWM Control
+
+There are three PWM outputs. The LM85 datasheet suggests that the
+pwm3 output control both fan3 and fan4. Each PWM can be individually
+configured and assigned to a zone for it's control value. Each PWM can be
+configured individually according to the following options.
+
+* pwm#_auto_pwm_min - this specifies the PWM value for temp#_auto_temp_off
+                      temperature. (PWM value from 0 to 255)
+
+* pwm#_auto_pwm_freq - select base frequency of PWM output. You can select
+                       in range of 10.0 to 94.0 Hz in .1 Hz units.
+                      (Values 100 to 940).
+
+The pwm#_auto_pwm_freq can be set to one of the following 8 values. Setting the
+frequency to a value not on this list, will result in the next higher frequency
+being selected. The actual device frequency may vary slightly from this
+specification as designed by the manufacturer. Consult the datasheet for more
+details. (PWM Frequency values:  100, 150, 230, 300, 380, 470, 620, 940)
+
+* pwm#_auto_pwm_minctl - this flags selects for temp#_auto_temp_off temperature
+                         the bahaviour of fans. Write 1 to let fans spinning at
+                        pwm#_auto_pwm_min or write 0 to let them off.
+
+NOTE: It has been reported that there is a bug in the LM85 that causes the flag
+to be associated with the zones not the PWMs. This contradicts all the
+published documentation. Setting pwm#_min_ctl in this case actually affects all
+PWMs controlled by zone '#'.
+
+* PWM Controlling Zone selection
+
+* pwm#_auto_channels - controls zone that is associated with PWM
+
+Configuration choices:
+
+   Value     Meaning
+  ------  ------------------------------------------------
+      1    Controlled by Zone 1
+      2    Controlled by Zone 2
+      3    Controlled by Zone 3
+     23    Controlled by higher temp of Zone 2 or 3
+    123    Controlled by highest temp of Zone 1, 2 or 3
+      0    PWM always 0%  (off)
+     -1    PWM always 100%  (full on)
+     -2    Manual control (write to 'pwm#' to set)
+
+The National LM85's have two vendor specific configuration
+features. Tach. mode and Spinup Control. For more details on these,
+see the LM85 datasheet or Application Note AN-1260.
+
+The Analog Devices ADM1027 has several vendor specific enhancements.
+The number of pulses-per-rev of the fans can be set, Tach monitoring
+can be optimized for PWM operation, and an offset can be applied to
+the temperatures to compensate for systemic errors in the
+measurements.
+
+In addition to the ADM1027 features, the ADT7463 also has Tmin control
+and THERM asserted counts. Automatic Tmin control acts to adjust the
+Tmin value to maintain the measured temperature sensor at a specified
+temperature. There isn't much documentation on this feature in the
+ADT7463 data sheet. This is not supported by current driver.
diff --git a/Documentation/i2c/chips/lm87 b/Documentation/i2c/chips/lm87
new file mode 100644 (file)
index 0000000..c952c57
--- /dev/null
@@ -0,0 +1,73 @@
+Kernel driver lm87
+==================
+
+Supported chips:
+  * National Semiconductor LM87
+    Prefix: 'lm87'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: http://www.national.com/pf/LM/LM87.html
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Mark Studebaker <mdsxyz123@yahoo.com>,
+        Stephen Rousset <stephen.rousset@rocketlogix.com>,
+        Dan Eaton <dan.eaton@rocketlogix.com>,
+        Jean Delvare <khali@linux-fr.org>,
+        Original 2.6 port Jeff Oliver
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM87.
+
+The LM87 implements up to three temperature sensors, up to two fan
+rotation speed sensors, up to seven voltage sensors, alarms, and some
+miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. Each input has a high
+and low alarm settings. A high limit produces an alarm when the value
+goes above it, and an alarm is also produced when the value goes below
+the low limit.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in
+volts. An alarm is triggered if the voltage has crossed a programmable
+minimum or maximum limit. Note that minimum in this case always means
+'closest to zero'; this is important for negative voltage measurements.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.0 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The lm87 driver only updates its values each 1.0 seconds; reading it more
+often will do no harm, but will return 'old' values.
+
+
+Hardware Configurations
+-----------------------
+
+The LM87 has four pins which can serve one of two possible functions,
+depending on the hardware configuration.
+
+Some functions share pins, so not all functions are available at the same
+time. Which are depends on the hardware setup. This driver assumes that
+the BIOS configured the chip correctly. In that respect, it differs from
+the original driver (from lm_sensors for Linux 2.4), which would force the
+LM87 to an arbitrary, compile-time chosen mode, regardless of the actual
+chipset wiring.
+
+For reference, here is the list of exclusive functions:
+ - in0+in5 (default) or temp3
+ - fan1 (default) or in6
+ - fan2 (default) or in7
+ - VID lines (default) or IRQ lines (not handled by this driver)
diff --git a/Documentation/i2c/chips/lm90 b/Documentation/i2c/chips/lm90
new file mode 100644 (file)
index 0000000..2c4cf39
--- /dev/null
@@ -0,0 +1,121 @@
+Kernel driver lm90
+==================
+
+Supported chips:
+  * National Semiconductor LM90
+    Prefix: 'lm90'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM90.html
+  * National Semiconductor LM89
+    Prefix: 'lm99'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM89.html
+  * National Semiconductor LM99
+    Prefix: 'lm99'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM99.html
+  * National Semiconductor LM86
+    Prefix: 'lm86'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM86.html
+  * Analog Devices ADM1032
+    Prefix: 'adm1032'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Analog Devices website
+               http://products.analog.com/products/info.asp?product=ADM1032
+  * Analog Devices ADT7461
+    Prefix: 'adt7461'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Analog Devices website
+               http://products.analog.com/products/info.asp?product=ADT7461
+    Note: Only if in ADM1032 compatibility mode
+  * Maxim MAX6657
+    Prefix: 'max6657'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+  * Maxim MAX6658
+    Prefix: 'max6657'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+  * Maxim MAX6659
+    Prefix: 'max6657'
+    Addresses scanned: I2C 0x4c, 0x4d (unsupported 0x4e)
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+
+The LM90 is a digital temperature sensor. It senses its own temperature as
+well as the temperature of up to one external diode. It is compatible
+with many other devices such as the LM86, the LM89, the LM99, the ADM1032,
+the MAX6657, MAX6658 and the MAX6659 all of which are supported by this driver.
+Note that there is no easy way to differentiate between the last three
+variants. The extra address and features of the MAX6659 are not supported by
+this driver. Additionally, the ADT7461 is supported if found in ADM1032
+compatibility mode.
+
+The specificity of this family of chipsets over the ADM1021/LM84
+family is that it features critical limits with hysteresis, and an
+increased resolution of the remote temperature measurement.
+
+The different chipsets of the family are not strictly identical, although
+very similar. This driver doesn't handle any specific feature for now,
+but could if there ever was a need for it. For reference, here comes a
+non-exhaustive list of specific features:
+
+LM90:
+  * Filter and alert configuration register at 0xBF.
+  * ALERT is triggered by temperatures over critical limits.
+
+LM86 and LM89:
+  * Same as LM90
+  * Better external channel accuracy
+
+LM99:
+  * Same as LM89
+  * External temperature shifted by 16 degrees down
+
+ADM1032:
+  * Consecutive alert register at 0x22.
+  * Conversion averaging.
+  * Up to 64 conversions/s.
+  * ALERT is triggered by open remote sensor.
+
+ADT7461
+  * Extended temperature range (breaks compatibility)
+  * Lower resolution for remote temperature
+
+MAX6657 and MAX6658:
+  * Remote sensor type selection
+
+MAX6659
+  * Selectable address
+  * Second critical temperature limit
+  * Remote sensor type selection
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree for the local temperature, 0.125 degree for the remote
+temperature.
+
+Each sensor has its own high and low limits, plus a critical limit.
+Additionally, there is a relative hysteresis value common to both critical
+values. To make life easier to user-space applications, two absolute values
+are exported, one for each channel, but these values are of course linked.
+Only the local hysteresis can be set from user-space, and the same delta
+applies to the remote hysteresis.
+
+The lm90 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
+
diff --git a/Documentation/i2c/chips/lm92 b/Documentation/i2c/chips/lm92
new file mode 100644 (file)
index 0000000..7705bfa
--- /dev/null
@@ -0,0 +1,37 @@
+Kernel driver lm92
+==================
+
+Supported chips:
+  * National Semiconductor LM92
+    Prefix: 'lm92'
+    Addresses scanned: I2C 0x48 - 0x4b
+    Datasheet: http://www.national.com/pf/LM/LM92.html
+  * National Semiconductor LM76
+    Prefix: 'lm92'
+    Addresses scanned: none, force parameter needed
+    Datasheet: http://www.national.com/pf/LM/LM76.html
+  * Maxim MAX6633/MAX6634/MAX6635
+    Prefix: 'lm92'
+    Addresses scanned: I2C 0x48 - 0x4b
+    MAX6633 with address in 0x40 - 0x47, 0x4c - 0x4f needs force parameter
+    and MAX6634 with address in 0x4c - 0x4f needs force parameter
+    Datasheet: http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
+
+Authors:
+        Abraham van der Merwe <abraham@2d3d.co.za>
+        Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM92
+temperature sensor.
+
+Each LM92 temperature sensor supports a single temperature sensor. There are
+alarms for high, low, and critical thresholds. There's also an hysteresis to
+control the thresholds for resetting alarms.
+
+Support was added later for the LM76 and Maxim MAX6633/MAX6634/MAX6635,
+which are mostly compatible. They have not all been tested, so you
+may need to use the force parameter.
diff --git a/Documentation/i2c/chips/max1619 b/Documentation/i2c/chips/max1619
new file mode 100644 (file)
index 0000000..d6f8d9c
--- /dev/null
@@ -0,0 +1,29 @@
+Kernel driver max1619
+=====================
+
+Supported chips:
+  * Maxim MAX1619
+    Prefix: 'max1619'
+    Addresses scanned: I2C 0x18-0x1a, 0x29-0x2b, 0x4c-0x4e
+    Datasheet: Publicly available at the Maxim website
+               http://pdfserv.maxim-ic.com/en/ds/MAX1619.pdf
+
+Authors:
+        Alexey Fisher <fishor@mail.ru>,
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The MAX1619 is a digital temperature sensor. It senses its own temperature as
+well as the temperature of up to one external diode.
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree for the local temperature and for the remote temperature.
+
+Only the external sensor has high and low limits.
+
+The max1619 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
+
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
new file mode 100644 (file)
index 0000000..b4fb49b
--- /dev/null
@@ -0,0 +1,54 @@
+Kernel driver max6875
+=====================
+
+Supported chips:
+  * Maxim max6874, max6875
+    Prefixes: 'max6875'
+    Addresses scanned: 0x50, 0x52
+    Datasheets:
+        http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
+
+Author: Ben Gardner <bgardner@wabtec.com>
+
+
+Module Parameters
+-----------------
+
+* allow_write int
+  Set to non-zero to enable write permission:
+  *0: Read only
+   1: Read and write
+
+
+Description
+-----------
+
+The MAXIM max6875 is a EEPROM-programmable power-supply sequencer/supervisor.
+It provides timed outputs that can be used as a watchdog, if properly wired.
+It also provides 512 bytes of user EEPROM.
+
+At reset, the max6875 reads the configuration eeprom into its configuration
+registers.  The chip then begins to operate according to the values in the
+registers.
+
+See the datasheet for details on how to program the EEPROM.
+
+
+Sysfs entries
+-------------
+
+eeprom_user   - 512 bytes of user-defined EEPROM space. Only writable if
+                allow_write was set and register 0x43 is 0.
+
+eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
+                loaded into register space until a power cycle or device reset.
+
+reg_config    - 70 bytes of register space. Any changes take affect immediately.
+
+
+General Remarks
+---------------
+
+A typical application will require that the EEPROMs be programmed once and
+never altered afterwards.
+
diff --git a/Documentation/i2c/chips/pc87360 b/Documentation/i2c/chips/pc87360
new file mode 100644 (file)
index 0000000..89a8fcf
--- /dev/null
@@ -0,0 +1,189 @@
+Kernel driver pc87360
+=====================
+
+Supported chips:
+  * National Semiconductor PC87360, PC87363, PC87364, PC87365 and PC87366
+    Prefixes: 'pc87360', 'pc87363', 'pc87364', 'pc87365', 'pc87366'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheets:
+        http://www.national.com/pf/PC/PC87360.html
+        http://www.national.com/pf/PC/PC87363.html
+        http://www.national.com/pf/PC/PC87364.html
+        http://www.national.com/pf/PC/PC87365.html
+        http://www.national.com/pf/PC/PC87366.html
+
+Authors: Jean Delvare <khali@linux-fr.org>
+
+Thanks to Sandeep Mehta, Tonko de Rooy and Daniel Ceregatti for testing.
+Thanks to Rudolf Marek for helping me investigate conversion issues.
+
+
+Module Parameters
+-----------------
+
+* init int
+  Chip initialization level:
+   0: None
+  *1: Forcibly enable internal voltage and temperature channels, except in9
+   2: Forcibly enable all voltage and temperature channels, except in9
+   3: Forcibly enable all voltage and temperature channels, including in9
+
+Note that this parameter has no effect for the PC87360, PC87363 and PC87364
+chips.
+
+Also note that for the PC87366, initialization levels 2 and 3 don't enable
+all temperature channels, because some of them share pins with each other,
+so they can't be used at the same time.
+
+
+Description
+-----------
+
+The National Semiconductor PC87360 Super I/O chip contains monitoring and
+PWM control circuitry for two fans. The PC87363 chip is similar, and the
+PC87364 chip has monitoring and PWM control for a third fan.
+
+The National Semiconductor PC87365 and PC87366 Super I/O chips are complete
+hardware monitoring chipsets, not only controlling and monitoring three fans,
+but also monitoring eleven voltage inputs and two (PC87365) or up to four
+(PC87366) temperatures.
+
+  Chip        #vin    #fan    #pwm    #temp   devid
+
+  PC87360     -       2       2       -       0xE1
+  PC87363     -       2       2       -       0xE8
+  PC87364     -       3       3       -       0xE4
+  PC87365     11      3       3       2       0xE5
+  PC87366     11      3       3       3-4     0xE9
+
+The driver assumes that no more than one chip is present, and one of the
+standard Super I/O addresses is used (0x2E/0x2F or 0x4E/0x4F)
+
+Fan Monitoring
+--------------
+
+Fan rotation speeds are reported in RPM (revolutions per minute). An alarm
+is triggered if the rotation speed has dropped below a programmable limit.
+A different alarm is triggered if the fan speed is too low to be measured.
+
+Fan readings are affected by a programmable clock divider, giving the
+readings more range or accuracy. Usually, users have to learn how it works,
+but this driver implements dynamic clock divider selection, so you don't
+have to care no more.
+
+For reference, here are a few values about clock dividers:
+
+                slowest         accuracy        highest
+                measurable      around 3000     accurate
+    divider     speed (RPM)     RPM (RPM)       speed (RPM)
+         1        1882              18           6928
+         2         941              37           4898
+         4         470              74           3464
+         8         235             150           2449
+
+For the curious, here is how the values above were computed:
+ * slowest measurable speed: clock/(255*divider)
+ * accuracy around 3000 RPM: 3000^2/clock
+ * highest accurate speed: sqrt(clock*100)
+The clock speed for the PC87360 family is 480 kHz. I arbitrarily chose 100
+RPM as the lowest acceptable accuracy.
+
+As mentioned above, you don't have to care about this no more.
+
+Note that not all RPM values can be represented, even when the best clock
+divider is selected. This is not only true for the measured speeds, but
+also for the programmable low limits, so don't be surprised if you try to
+set, say, fan1_min to 2900 and it finally reads 2909.
+
+
+Fan Control
+-----------
+
+PWM (pulse width modulation) values range from 0 to 255, with 0 meaning
+that the fan is stopped, and 255 meaning that the fan goes at full speed.
+
+Be extremely careful when changing PWM values. Low PWM values, even
+non-zero, can stop the fan, which may cause irreversible damage to your
+hardware if temperature increases too much. When changing PWM values, go
+step by step and keep an eye on temperatures.
+
+One user reported problems with PWM. Changing PWM values would break fan
+speed readings. No explanation nor fix could be found.
+
+
+Temperature Monitoring
+----------------------
+
+Temperatures are reported in degrees Celsius. Each temperature measured has
+associated low, high and overtemperature limits, each of which triggers an
+alarm when crossed.
+
+The first two temperature channels are external. The third one (PC87366
+only) is internal.
+
+The PC87366 has three additional temperature channels, based on
+thermistors (as opposed to thermal diodes for the first three temperature
+channels). For technical reasons, these channels are held by the VLM
+(voltage level monitor) logical device, not the TMS (temperature
+measurement) one. As a consequence, these temperatures are exported as
+voltages, and converted into temperatures in user-space.
+
+Note that these three additional channels share their pins with the
+external thermal diode channels, so you (physically) can't use them all at
+the same time. Although it should be possible to mix the two sensor types,
+the documents from National Semiconductor suggest that motherboard
+manufacturers should choose one type and stick to it. So you will more
+likely have either channels 1 to 3 (thermal diodes) or 3 to 6 (internal
+thermal diode, and thermistors).
+
+
+Voltage Monitoring
+------------------
+
+Voltages are reported relatively to a reference voltage, either internal or
+external. Some of them (in7:Vsb, in8:Vdd and in10:AVdd) are divided by two
+internally, you will have to compensate in sensors.conf. Others (in0 to in6)
+are likely to be divided externally. The meaning of each of these inputs as
+well as the values of the resistors used for division is left to the
+motherboard manufacturers, so you will have to document yourself and edit
+sensors.conf accordingly. National Semiconductor has a document with
+recommended resistor values for some voltages, but this still leaves much
+room for per motherboard specificities, unfortunately. Even worse,
+motherboard manufacturers don't seem to care about National Semiconductor's
+recommendations.
+
+Each voltage measured has associated low and high limits, each of which
+triggers an alarm when crossed.
+
+When available, VID inputs are used to provide the nominal CPU Core voltage.
+The driver will default to VRM 9.0, but this can be changed from user-space.
+The chipsets can handle two sets of VID inputs (on dual-CPU systems), but
+the driver will only export one for now. This may change later if there is
+a need.
+
+
+General Remarks
+---------------
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that all hardware registers are read whenever any
+data is read (unless it is less than 2 seconds since the last update, in
+which case cached values are returned instead). As a consequence, when
+a once-only alarm triggers, it may take 2 seconds for it to show, and 2
+more seconds for it to disappear.
+
+Monitoring of in9 isn't enabled at lower init levels (<3) because that
+channel measures the battery voltage (Vbat). It is a known fact that
+repeatedly sampling the battery voltage reduces its lifetime. National
+Semiconductor smartly designed their chipset so that in9 is sampled only
+once every 1024 sampling cycles (that is every 34 minutes at the default
+sampling rate), so the effect is attenuated, but still present.
+
+
+Limitations
+-----------
+
+The datasheets suggests that some values (fan mins, fan dividers)
+shouldn't be changed once the monitoring has started, but we ignore that
+recommendation. We'll reconsider if it actually causes trouble.
diff --git a/Documentation/i2c/chips/pca9539 b/Documentation/i2c/chips/pca9539
new file mode 100644 (file)
index 0000000..c4fce6a
--- /dev/null
@@ -0,0 +1,47 @@
+Kernel driver pca9539
+=====================
+
+Supported chips:
+  * Philips PCA9539
+    Prefix: 'pca9539'
+    Addresses scanned: 0x74 - 0x77
+    Datasheet:
+        http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf
+
+Author: Ben Gardner <bgardner@wabtec.com>
+
+
+Description
+-----------
+
+The Philips PCA9539 is a 16 bit low power I/O device.
+All 16 lines can be individually configured as an input or output.
+The input sense can also be inverted.
+The 16 lines are split between two bytes.
+
+
+Sysfs entries
+-------------
+
+Each is a byte that maps to the 8 I/O bits.
+A '0' suffix is for bits 0-7, while '1' is for bits 8-15.
+
+input[01]     - read the current value
+output[01]    - sets the output value
+direction[01] - direction of each bit: 1=input, 0=output
+invert[01]    - toggle the input bit sense
+
+input reads the actual state of the line and is always available.
+The direction defaults to input for all channels.
+
+
+General Remarks
+---------------
+
+Note that each output, direction, and invert entry controls 8 lines.
+You should use the read, modify, write sequence.
+For example. to set output bit 0 of 1.
+  val=$(cat output0)
+  val=$(( $val | 1 ))
+  echo $val > output0
+
diff --git a/Documentation/i2c/chips/pcf8574 b/Documentation/i2c/chips/pcf8574
new file mode 100644 (file)
index 0000000..2752c8c
--- /dev/null
@@ -0,0 +1,69 @@
+Kernel driver pcf8574
+=====================
+
+Supported chips:
+  * Philips PCF8574
+    Prefix: 'pcf8574'
+    Addresses scanned: I2C 0x20 - 0x27
+    Datasheet: Publicly available at the Philips Semiconductors website
+               http://www.semiconductors.philips.com/pip/PCF8574P.html
+
+ * Philips PCF8574A
+    Prefix: 'pcf8574a'
+    Addresses scanned: I2C 0x38 - 0x3f
+    Datasheet: Publicly available at the Philips Semiconductors website
+               http://www.semiconductors.philips.com/pip/PCF8574P.html
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Dan Eaton <dan.eaton@rocketlogix.com>,
+        Aurelien Jarno <aurelien@aurel32.net>,
+        Jean Delvare <khali@linux-fr.org>,
+
+
+Description
+-----------
+The PCF8574(A) is an 8-bit I/O expander for the I2C bus produced by Philips
+Semiconductors. It is designed to provide a byte I2C interface to up to 16
+separate devices (8 x PCF8574 and 8 x PCF8574A).
+
+This device consists of a quasi-bidirectional port. Each of the eight I/Os
+can be independently used as an input or output. To setup an I/O as an
+input, you have to write a 1 to the corresponding output.
+
+For more informations see the datasheet.
+
+
+Accessing PCF8574(A) via /sys interface
+-------------------------------------
+
+! Be careful !
+The PCF8574(A) is plainly impossible to detect ! Stupid chip.
+So every chip with address in the interval [20..27] and [38..3f] are
+detected as PCF8574(A). If you have other chips in this address
+range, the workaround is to load this module after the one
+for your others chips.
+
+On detection (i.e. insmod, modprobe et al.), directories are being
+created for each detected PCF8574(A):
+
+/sys/bus/i2c/devices/<0>-<1>/
+where <0> is the bus the chip was detected on (e. g. i2c-0)
+and <1> the chip address ([20..27] or [38..3f]):
+
+(example: /sys/bus/i2c/devices/1-0020/)
+
+Inside these directories, there are two files each:
+read and write (and one file with chip name).
+
+The read file is read-only. Reading gives you the current I/O input
+if the corresponding output is set as 1, otherwise the current output
+value, that is to say 0.
+
+The write file is read/write. Writing a value outputs it on the I/O
+port. Reading returns the last written value.
+
+On module initialization the chip is configured as eight inputs (all
+outputs to 1), so you can connect any circuit to the PCF8574(A) without
+being afraid of short-circuit.
diff --git a/Documentation/i2c/chips/pcf8591 b/Documentation/i2c/chips/pcf8591
new file mode 100644 (file)
index 0000000..5628fcf
--- /dev/null
@@ -0,0 +1,90 @@
+Kernel driver pcf8591
+=====================
+
+Supported chips:
+  * Philips PCF8591
+    Prefix: 'pcf8591'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Philips Semiconductor website
+               http://www.semiconductors.philips.com/pip/PCF8591P.html
+
+Authors:
+        Aurelien Jarno <aurelien@aurel32.net>
+        valuable contributions by Jan M. Sendler <sendler@sendler.de>,
+        Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
+analog output) for the I2C bus produced by Philips Semiconductors. It
+is designed to provide a byte I2C interface to up to 4 separate devices.
+
+The PCF8591 has 4 analog inputs programmable as single-ended or
+differential inputs :
+- mode 0 : four single ended inputs
+        Pins AIN0 to AIN3 are single ended inputs for channels 0 to 3
+
+- mode 1 : three differential inputs
+        Pins AIN3 is the common negative differential input
+        Pins AIN0 to AIN2 are positive differential inputs for channels 0 to 2
+
+- mode 2 : single ended and differential mixed
+        Pins AIN0 and AIN1 are single ended inputs for channels 0 and 1
+        Pins AIN2 is the positive differential input for channel 3
+        Pins AIN3 is the negative differential input for channel 3
+
+- mode 3 : two differential inputs
+        Pins AIN0 is the positive differential input for channel 0
+        Pins AIN1 is the negative differential input for channel 0
+        Pins AIN2 is the positive differential input for channel 1
+        Pins AIN3 is the negative differential input for channel 1
+
+See the datasheet for details.
+
+Module parameters
+-----------------
+
+* input_mode int
+
+    Analog input mode:
+         0 = four single ended inputs
+         1 = three differential inputs
+         2 = single ended and differential mixed
+         3 = two differential inputs
+
+
+Accessing PCF8591 via /sys interface
+-------------------------------------
+
+! Be careful !
+The PCF8591 is plainly impossible to detect ! Stupid chip.
+So every chip with address in the interval [48..4f] is
+detected as PCF8591. If you have other chips in this address
+range, the workaround is to load this module after the one
+for your others chips.
+
+On detection (i.e. insmod, modprobe et al.), directories are being
+created for each detected PCF8591:
+
+/sys/bus/devices/<0>-<1>/
+where <0> is the bus the chip was detected on (e. g. i2c-0)
+and <1> the chip address ([48..4f])
+
+Inside these directories, there are such files:
+in0, in1, in2, in3, out0_enable, out0_output, name
+
+Name contains chip name.
+
+The in0, in1, in2 and in3 files are RO. Reading gives the value of the
+corresponding channel. Depending on the current analog inputs configuration,
+files in2 and/or in3 do not exist. Values range are from 0 to 255 for single
+ended inputs and -128 to +127 for differential inputs (8-bit ADC).
+
+The out0_enable file is RW. Reading gives "1" for analog output enabled and
+"0" for analog output disabled. Writing accepts "0" and "1" accordingly.
+
+The out0_output file is RW. Writing a number between 0 and 255 (8-bit DAC), send
+the value to the digital-to-analog converter. Note that a voltage will
+only appears on AOUT pin if aout0_enable equals 1. Reading returns the last
+value written.
diff --git a/Documentation/i2c/chips/sis5595 b/Documentation/i2c/chips/sis5595
new file mode 100644 (file)
index 0000000..b7ae36b
--- /dev/null
@@ -0,0 +1,106 @@
+Kernel driver sis5595
+=====================
+
+Supported chips:
+  * Silicon Integrated Systems Corp. SiS5595 Southbridge Hardware Monitor
+    Prefix: 'sis5595'
+    Addresses scanned: ISA in PCI-space encoded address
+    Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
+
+Authors:
+        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+        Mark D. Studebaker <mdsxyz123@yahoo.com>,
+        Aurelien Jarno <aurelien@aurel32.net> 2.6 port
+
+   SiS southbridge has a LM78-like chip integrated on the same IC.
+   This driver is a customized copy of lm78.c
+
+   Supports following revisions:
+       Version         PCI ID          PCI Revision
+       1               1039/0008       AF or less
+       2               1039/0008       B0 or greater
+
+   Note: these chips contain a 0008 device which is incompatible with the
+        5595. We recognize these by the presence of the listed
+        "blacklist" PCI ID and refuse to load.
+
+   NOT SUPPORTED       PCI ID          BLACKLIST PCI ID
+        540            0008            0540
+        550            0008            0550
+       5513            0008            5511
+       5581            0008            5597
+       5582            0008            5597
+       5597            0008            5597
+        630            0008            0630
+        645            0008            0645
+        730            0008            0730
+        735            0008            0735
+
+
+Module Parameters
+-----------------
+force_addr=0xaddr      Set the I/O base address. Useful for boards
+                       that don't set the address in the BIOS. Does not do a
+                       PCI force; the device must still be present in lspci.
+                       Don't use this unless the driver complains that the
+                       base address is not set.
+                       Example: 'modprobe sis5595 force_addr=0x290'
+
+
+Description
+-----------
+
+The SiS5595 southbridge has integrated hardware monitor functions. It also
+has an I2C bus, but this driver only supports the hardware monitor. For the
+I2C bus driver see i2c-sis5595.
+
+The SiS5595 implements zero or one temperature sensor, two fan speed
+sensors, four or five voltage sensors, and alarms.
+
+On the first version of the chip, there are four voltage sensors and one
+temperature sensor.
+
+On the second version of the chip, the temperature sensor (temp) and the
+fifth voltage sensor (in4) share a pin which is configurable, but not
+through the driver. Sorry. The driver senses the configuration of the pin,
+which was hopefully set by the BIOS.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the max is crossed; it is also triggered when it drops below the min
+value. Measurements are guaranteed between -55 and +125 degrees, with a
+resolution of 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts. An
+alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution of
+0.016 volt.
+
+In addition to the alarms described above, there is a BTI alarm, which gets
+triggered when an external chip has crossed its limits. Usually, this is
+connected to some LM75-like chip; if at least one crosses its limits, this
+bit gets set.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 1.5
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The SiS5595 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+Problems
+--------
+Some chips refuse to be enabled. We don't know why.
+The driver will recognize this and print a message in dmesg.
+
diff --git a/Documentation/i2c/chips/smsc47b397 b/Documentation/i2c/chips/smsc47b397
new file mode 100644 (file)
index 0000000..da9d80c
--- /dev/null
@@ -0,0 +1,158 @@
+Kernel driver smsc47b397
+========================
+
+Supported chips:
+  * SMSC LPC47B397-NC
+    Prefix: 'smsc47b397'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: In this file
+
+Authors: Mark M. Hoffman <mhoffman@lightlink.com>
+         Utilitek Systems, Inc.
+
+November 23, 2004
+
+The following specification describes the SMSC LPC47B397-NC sensor chip
+(for which there is no public datasheet available). This document was
+provided by Craig Kelly (In-Store Broadcast Network) and edited/corrected
+by Mark M. Hoffman <mhoffman@lightlink.com>.
+
+* * * * *
+
+Methods for detecting the HP SIO and reading the thermal data on a dc7100.
+
+The thermal information on the dc7100 is contained in the SIO Hardware Monitor
+(HWM). The information is accessed through an index/data pair. The index/data
+pair is located at the HWM Base Address + 0 and the HWM Base Address + 1. The
+HWM Base address can be obtained from Logical Device 8, registers 0x60 (MSB)
+and 0x61 (LSB). Currently we are using 0x480 for the HWM Base Address and
+0x480 and 0x481 for the index/data pair.
+
+Reading temperature information.
+The temperature information is located in the following registers:
+Temp1          0x25    (Currently, this reflects the CPU temp on all systems).
+Temp2          0x26
+Temp3          0x27
+Temp4          0x80
+
+Programming Example
+The following is an example of how to read the HWM temperature registers:
+MOV    DX,480H
+MOV    AX,25H
+OUT    DX,AL
+MOV    DX,481H
+IN     AL,DX
+
+AL contains the data in hex, the temperature in Celsius is the decimal
+equivalent.
+
+Ex: If AL contains 0x2A, the temperature is 42 degrees C.
+
+Reading tach information.
+The fan speed information is located in the following registers:
+               LSB     MSB
+Tach1          0x28    0x29    (Currently, this reflects the CPU
+                               fan speed on all systems).
+Tach2          0x2A    0x2B
+Tach3          0x2C    0x2D
+Tach4          0x2E    0x2F
+
+Important!!!
+Reading the tach LSB locks the tach MSB.
+The LSB Must be read first.
+
+How to convert the tach reading to RPM.
+The tach reading (TCount) is given by: (Tach MSB * 256) + (Tach LSB)
+The SIO counts the number of 90kHz (11.111us) pulses per revolution.
+RPM = 60/(TCount * 11.111us)
+
+Example:
+Reg 0x28 = 0x9B
+Reg 0x29 = 0x08
+
+TCount = 0x89B = 2203
+
+RPM = 60 / (2203 * 11.11111 E-6) = 2451 RPM
+
+Obtaining the SIO version.
+
+CONFIGURATION SEQUENCE
+To program the configuration registers, the following sequence must be followed:
+1. Enter Configuration Mode
+2. Configure the Configuration Registers
+3. Exit Configuration Mode.
+
+Enter Configuration Mode
+To place the chip into the Configuration State The config key (0x55) is written
+to the CONFIG PORT (0x2E).
+
+Configuration Mode
+In configuration mode, the INDEX PORT is located at the CONFIG PORT address and
+the DATA PORT is at INDEX PORT address + 1.
+
+The desired configuration registers are accessed in two steps:
+a.     Write the index of the Logical Device Number Configuration Register
+       (i.e., 0x07) to the INDEX PORT and then write the number of the
+       desired logical device to the DATA PORT.
+
+b.     Write the address of the desired configuration register within the
+       logical device to the INDEX PORT and then write or read the config-
+       uration register through the DATA PORT.
+
+Note: If accessing the Global Configuration Registers, step (a) is not required.
+
+Exit Configuration Mode
+To exit the Configuration State the write 0xAA to the CONFIG PORT (0x2E).
+The chip returns to the RUN State.  (This is important).
+
+Programming Example
+The following is an example of how to read the SIO Device ID located at 0x20
+
+; ENTER CONFIGURATION MODE
+MOV    DX,02EH
+MOV    AX,055H
+OUT    DX,AL
+; GLOBAL CONFIGURATION  REGISTER
+MOV    DX,02EH
+MOV    AL,20H
+OUT    DX,AL
+; READ THE DATA
+MOV    DX,02FH
+IN     AL,DX
+; EXIT CONFIGURATION MODE
+MOV    DX,02EH
+MOV    AX,0AAH
+OUT    DX,AL
+
+The registers of interest for identifying the SIO on the dc7100 are Device ID
+(0x20) and Device Rev  (0x21).
+
+The Device ID will read 0X6F
+The Device Rev currently reads 0x01
+
+Obtaining the HWM Base Address.
+The following is an example of how to read the HWM Base Address located in
+Logical Device 8.
+
+; ENTER CONFIGURATION MODE
+MOV    DX,02EH
+MOV    AX,055H
+OUT    DX,AL
+; CONFIGURE REGISTER CRE0,
+; LOGICAL DEVICE 8
+MOV    DX,02EH
+MOV    AL,07H
+OUT    DX,AL ;Point to LD# Config Reg
+MOV    DX,02FH
+MOV    AL, 08H
+OUT    DX,AL;Point to Logical Device 8
+;
+MOV    DX,02EH
+MOV    AL,60H
+OUT    DX,AL   ; Point to HWM Base Addr MSB
+MOV    DX,02FH
+IN     AL,DX   ; Get MSB of HWM Base Addr
+; EXIT CONFIGURATION MODE
+MOV    DX,02EH
+MOV    AX,0AAH
+OUT    DX,AL
diff --git a/Documentation/i2c/chips/smsc47b397.txt b/Documentation/i2c/chips/smsc47b397.txt
deleted file mode 100644 (file)
index 389edae..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-November 23, 2004
-
-The following specification describes the SMSC LPC47B397-NC sensor chip
-(for which there is no public datasheet available).  This document was
-provided by Craig Kelly (In-Store Broadcast Network) and edited/corrected
-by Mark M. Hoffman <mhoffman@lightlink.com>.
-
-* * * * *
-
-Methods for detecting the HP SIO and reading the thermal data on a dc7100.
-
-The thermal information on the dc7100 is contained in the SIO Hardware Monitor
-(HWM).  The information is accessed through an index/data pair.  The index/data
-pair is located at the HWM Base Address + 0 and the HWM Base Address + 1.  The
-HWM Base address can be obtained from Logical Device 8, registers 0x60 (MSB)
-and 0x61 (LSB).  Currently we are using 0x480 for the HWM Base Address and
-0x480 and 0x481 for the index/data pair.
-
-Reading temperature information.
-The temperature information is located in the following registers:
-Temp1          0x25    (Currently, this reflects the CPU temp on all systems).
-Temp2          0x26
-Temp3          0x27
-Temp4          0x80
-
-Programming Example
-The following is an example of how to read the HWM temperature registers:
-MOV    DX,480H
-MOV    AX,25H
-OUT    DX,AL
-MOV    DX,481H
-IN     AL,DX
-
-AL contains the data in hex, the temperature in Celsius is the decimal
-equivalent.
-
-Ex: If AL contains 0x2A, the temperature is 42 degrees C.
-
-Reading tach information.
-The fan speed information is located in the following registers:
-               LSB     MSB
-Tach1          0x28    0x29    (Currently, this reflects the CPU
-                               fan speed on all systems).
-Tach2          0x2A    0x2B
-Tach3          0x2C    0x2D
-Tach4          0x2E    0x2F
-
-Important!!!
-Reading the tach LSB locks the tach MSB.
-The LSB Must be read first.
-
-How to convert the tach reading to RPM.
-The tach reading (TCount) is given by:  (Tach MSB * 256) + (Tach LSB)
-The SIO counts the number of 90kHz (11.111us) pulses per revolution.
-RPM = 60/(TCount * 11.111us)
-
-Example:
-Reg 0x28 = 0x9B
-Reg 0x29 = 0x08
-
-TCount = 0x89B = 2203
-
-RPM = 60 / (2203 * 11.11111 E-6) = 2451 RPM
-
-Obtaining the SIO version.
-
-CONFIGURATION SEQUENCE
-To program the configuration registers, the following sequence must be followed:
-1. Enter Configuration Mode
-2. Configure the Configuration Registers
-3. Exit Configuration Mode.
-
-Enter Configuration Mode
-To place the chip into the Configuration State The config key (0x55) is written
-to the CONFIG PORT (0x2E). 
-
-Configuration Mode
-In configuration mode, the INDEX PORT is located at the CONFIG PORT address and
-the DATA PORT is at INDEX PORT address + 1.
-
-The desired configuration registers are accessed in two steps: 
-a.     Write the index of the Logical Device Number Configuration Register
-       (i.e., 0x07) to the INDEX PORT and then write the number of the
-       desired logical device to the DATA PORT.
-
-b.     Write the address of the desired configuration register within the
-       logical device to the INDEX PORT and then write or read the config-
-       uration register through the DATA PORT.  
-
-Note: If accessing the Global Configuration Registers, step (a) is not required.
-
-Exit Configuration Mode
-To exit the Configuration State the write 0xAA to the CONFIG PORT (0x2E).
-The chip returns to the RUN State.  (This is important).
-
-Programming Example
-The following is an example of how to read the SIO Device ID located at 0x20
-
-; ENTER CONFIGURATION MODE   
-MOV    DX,02EH
-MOV    AX,055H
-OUT    DX,AL
-; GLOBAL CONFIGURATION  REGISTER 
-MOV    DX,02EH
-MOV    AL,20H
-OUT    DX,AL 
-; READ THE DATA
-MOV    DX,02FH
-IN     AL,DX
-; EXIT CONFIGURATION MODE     
-MOV    DX,02EH
-MOV    AX,0AAH
-OUT    DX,AL
-
-The registers of interest for identifying the SIO on the dc7100 are Device ID
-(0x20) and Device Rev  (0x21).
-
-The Device ID will read 0X6F
-The Device Rev currently reads 0x01
-
-Obtaining the HWM Base Address.
-The following is an example of how to read the HWM Base Address located in
-Logical Device 8.
-
-; ENTER CONFIGURATION MODE   
-MOV    DX,02EH
-MOV    AX,055H
-OUT    DX,AL
-; CONFIGURE REGISTER CRE0,   
-; LOGICAL DEVICE 8           
-MOV    DX,02EH
-MOV    AL,07H
-OUT    DX,AL ;Point to LD# Config Reg
-MOV    DX,02FH
-MOV    AL, 08H
-OUT    DX,AL;Point to Logical Device 8
-;
-MOV    DX,02EH 
-MOV    AL,60H
-OUT    DX,AL   ; Point to HWM Base Addr MSB
-MOV    DX,02FH
-IN     AL,DX   ; Get MSB of HWM Base Addr
-; EXIT CONFIGURATION MODE     
-MOV    DX,02EH
-MOV    AX,0AAH
-OUT    DX,AL
diff --git a/Documentation/i2c/chips/smsc47m1 b/Documentation/i2c/chips/smsc47m1
new file mode 100644 (file)
index 0000000..34e6478
--- /dev/null
@@ -0,0 +1,52 @@
+Kernel driver smsc47m1
+======================
+
+Supported chips:
+  * SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192
+    Addresses scanned: none, address read from Super I/O config space
+    Prefix: 'smsc47m1'
+    Datasheets:
+        http://www.smsc.com/main/datasheets/47b27x.pdf
+        http://www.smsc.com/main/datasheets/47m10x.pdf
+        http://www.smsc.com/main/tools/discontinued/47m13x.pdf
+        http://www.smsc.com/main/datasheets/47m14x.pdf
+        http://www.smsc.com/main/tools/discontinued/47m15x.pdf
+        http://www.smsc.com/main/datasheets/47m192.pdf
+
+Authors:
+        Mark D. Studebaker <mdsxyz123@yahoo.com>,
+        With assistance from Bruce Allen <ballen@uwm.edu>, and his
+        fan.c program: http://www.lsc-group.phys.uwm.edu/%7Eballen/driver/
+        Gabriele Gorla <gorlik@yahoo.com>,
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips
+contain monitoring and PWM control circuitry for two fans.
+
+The 47M15x and 47M192 chips contain a full 'hardware monitoring block'
+in addition to the fan monitoring and control. The hardware monitoring
+block is not supported by the driver.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+PWM values are from 0 to 255.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+
+**********************
+The lm_sensors project gratefully acknowledges the support of
+Intel in the development of this driver.
diff --git a/Documentation/i2c/chips/via686a b/Documentation/i2c/chips/via686a
new file mode 100644 (file)
index 0000000..b82014c
--- /dev/null
@@ -0,0 +1,65 @@
+Kernel driver via686a
+=====================
+
+Supported chips:
+  * Via VT82C686A, VT82C686B  Southbridge Integrated Hardware Monitor
+    Prefix: 'via686a'
+    Addresses scanned: ISA in PCI-space encoded address
+    Datasheet: On request through web form (http://www.via.com.tw/en/support/datasheets/)
+
+Authors:
+        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+        Mark D. Studebaker <mdsxyz123@yahoo.com>
+        Bob Dougherty <bobd@stanford.edu>
+        (Some conversion-factor data were contributed by
+        Jonathan Teh Soon Yew <j.teh@iname.com>
+        and Alex van Kaam <darkside@chello.nl>.)
+
+Module Parameters
+-----------------
+
+force_addr=0xaddr       Set the I/O base address. Useful for Asus A7V boards
+                        that don't set the address in the BIOS. Does not do a
+                        PCI force; the via686a must still be present in lspci.
+                        Don't use this unless the driver complains that the
+                        base address is not set.
+                        Example: 'modprobe via686a force_addr=0x6000'
+
+Description
+-----------
+
+The driver does not distinguish between the chips and reports
+all as a 686A.
+
+The Via 686a southbridge has integrated hardware monitor functionality.
+It also has an I2C bus, but this driver only supports the hardware monitor.
+For the I2C bus driver, see <file:Documentation/i2c/busses/i2c-viapro>
+
+The Via 686a implements three temperature sensors, two fan rotation speed
+sensors, five voltage sensors and alarms.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed; it is triggered again
+as soon as it drops below the hysteresis value.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Voltages are internally scalled, so each voltage channel
+has a different resolution and range.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The driver only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/w83627hf b/Documentation/i2c/chips/w83627hf
new file mode 100644 (file)
index 0000000..78f37c2
--- /dev/null
@@ -0,0 +1,66 @@
+Kernel driver w83627hf
+======================
+
+Supported chips:
+  * Winbond W83627HF (ISA accesses ONLY)
+    Prefix: 'w83627hf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf
+  * Winbond W83627THF
+    Prefix: 'w83627thf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond.com/PDF/sheet/w83627thf.pdf
+  * Winbond W83697HF
+    Prefix: 'w83697hf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond.com/PDF/sheet/697hf.pdf
+  * Winbond W83637HF
+    Prefix: 'w83637hf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Mark Studebaker <mdsxyz123@yahoo.com>,
+        Bernhard C. Schrenk <clemy@clemy.org>
+
+Module Parameters
+-----------------
+
+* force_addr: int
+  Initialize the ISA address of the sensors
+* force_i2c: int
+  Initialize the I2C address of the sensors
+* init: int
+  (default is 1)
+  Use 'init=0' to bypass initializing the chip.
+  Try this if your computer crashes when you load the module.
+
+Description
+-----------
+
+This driver implements support for ISA accesses *only* for
+the Winbond W83627HF, W83627THF, W83697HF and W83637HF Super I/O chips.
+We will refer to them collectively as Winbond chips.
+
+This driver supports ISA accesses, which should be more reliable
+than i2c accesses. Also, for Tyan boards which contain both a
+Super I/O chip and a second i2c-only Winbond chip (often a W83782D),
+using this driver will avoid i2c address conflicts and complex
+initialization that were required in the w83781d driver.
+
+If you really want i2c accesses for these Super I/O chips,
+use the w83781d driver. However this is not the preferred method
+now that this ISA driver has been developed.
+
+Technically, the w83627thf does not support a VID reading. However, it's
+possible or even likely that your mainboard maker has routed these signals
+to a specific set of general purpose IO pins (the Asus P4C800-E is one such
+board). The w83627thf driver now interprets these as VID. If the VID on
+your board doesn't work, first see doc/vid in the lm_sensors package. If
+that still doesn't help, email us at lm-sensors@lm-sensors.org.
+
+For further information on this driver see the w83781d driver
+documentation.
+
diff --git a/Documentation/i2c/chips/w83781d b/Documentation/i2c/chips/w83781d
new file mode 100644 (file)
index 0000000..e545933
--- /dev/null
@@ -0,0 +1,402 @@
+Kernel driver w83781d
+=====================
+
+Supported chips:
+  * Winbond W83781D
+    Prefix: 'w83781d'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83781d.pdf
+  * Winbond W83782D
+    Prefix: 'w83782d'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: http://www.winbond.com/PDF/sheet/w83782d.pdf
+  * Winbond W83783S
+    Prefix: 'w83783s'
+    Addresses scanned: I2C 0x2d
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83783s.pdf
+  * Winbond W83627HF
+    Prefix: 'w83627hf'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf
+  * Asus AS99127F
+    Prefix: 'as99127f'
+    Addresses scanned: I2C 0x28 - 0x2f
+    Datasheet: Unavailable from Asus
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Mark Studebaker <mdsxyz123@yahoo.com>
+
+Module parameters
+-----------------
+
+* init int
+  (default 1)
+  Use 'init=0' to bypass initializing the chip.
+  Try this if your computer crashes when you load the module.
+
+force_subclients=bus,caddr,saddr,saddr
+  This is used to force the i2c addresses for subclients of
+  a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b'
+  to force the subclients of chip 0x2d on bus 0 to i2c addresses
+  0x4a and 0x4b. This parameter is useful for certain Tyan boards.
+
+Description
+-----------
+
+This driver implements support for the Winbond W83781D, W83782D, W83783S,
+W83627HF chips, and the Asus AS99127F chips. We will refer to them
+collectively as W8378* chips.
+
+There is quite some difference between these chips, but they are similar
+enough that it was sensible to put them together in one driver.
+The W83627HF chip is assumed to be identical to the ISA W83782D.
+The Asus chips are similar to an I2C-only W83782D.
+
+Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+as99127f    7       3       0       3       0x31    0x12c3  yes     no
+as99127f rev.2 (type_name = as99127f)       0x31    0x5ca3  yes     no
+w83781d     7       3       0       3       0x10-1  0x5ca3  yes     yes
+w83627hf    9       3       2       3       0x21    0x5ca3  yes     yes(LPC)
+w83782d     9       3       2-4     3       0x30    0x5ca3  yes     yes
+w83783s     5-6     3       2       1-2     0x40    0x5ca3  yes     no
+
+Detection of these chips can sometimes be foiled because they can be in
+an internal state that allows no clean access. If you know the address
+of the chip, use a 'force' parameter; this will put them into a more
+well-behaved state first.
+
+The W8378* implements temperature sensors (three on the W83781D and W83782D,
+two on the W83783S), three fan rotation speed sensors, voltage sensors
+(seven on the W83781D, nine on the W83782D and six on the W83783S), VID
+lines, alarms with beep warnings, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. There is always one main
+temperature sensor, and one (W83783S) or two (W83781D and W83782D) other
+sensors. An alarm is triggered for the main sensor once when the
+Overtemperature Shutdown limit is crossed; it is triggered again as soon as
+it drops below the Hysteresis value. A more useful behavior
+can be found by setting the Hysteresis value to +127 degrees Celsius; in
+this case, alarms are issued during all the time when the actual temperature
+is above the Overtemperature Shutdown value. The driver sets the
+hysteresis value for temp1 to 127 at initialization.
+
+For the other temperature sensor(s), an alarm is triggered when the
+temperature gets higher then the Overtemperature Shutdown value; it stays
+on until the temperature falls below the Hysteresis value. But on the
+W83781D, there is only one alarm that functions for both other sensors!
+Temperatures are guaranteed within a range of -55 to +125 degrees. The
+main temperature sensors has a resolution of 1 degree; the other sensor(s)
+of 0.5 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8 for the
+W83781D; 1, 2, 4, 8, 16, 32, 64 or 128 for the others) to give
+the readings more range or accuracy. Not all RPM values can accurately
+be represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution
+of 0.016 volt.
+
+The VID lines encode the core voltage value: the voltage level your processor
+should work with. This is hardcoded by the mainboard and/or processor itself.
+It is a value in volts. When it is unconnected, you will often find the
+value 3.50 V here.
+
+The W83782D and W83783S temperature conversion machine understands about
+several kinds of temperature probes. You can program the so-called
+beta value in the sensor files. '1' is the PII/Celeron diode, '2' is the
+TN3904 transistor, and 3435 the default thermistor value. Other values
+are (not yet) supported.
+
+In addition to the alarms described above, there is a CHAS alarm on the
+chips which triggers if your computer case is open.
+
+When an alarm goes off, you can be warned by a beeping signal through
+your computer speaker. It is possible to enable all beeping globally,
+or only the beeping for some alarms.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The chips only update values each 1.5 seconds; reading them more often
+will do no harm, but will return 'old' values.
+
+AS99127F PROBLEMS
+-----------------
+The as99127f support was developed without the benefit of a datasheet.
+In most cases it is treated as a w83781d (although revision 2 of the
+AS99127F looks more like a w83782d).
+This support will be BETA until a datasheet is released.
+One user has reported problems with fans stopping
+occasionally.
+
+Note that the individual beep bits are inverted from the other chips.
+The driver now takes care of this so that user-space applications
+don't have to know about it.
+
+Known problems:
+       - Problems with diode/thermistor settings (supported?)
+       - One user reports fans stopping under high server load.
+       - Revision 2 seems to have 2 PWM registers but we don't know
+         how to handle them. More details below.
+
+These will not be fixed unless we get a datasheet.
+If you have problems, please lobby Asus to release a datasheet.
+Unfortunately several others have without success.
+Please do not send mail to us asking for better as99127f support.
+We have done the best we can without a datasheet.
+Please do not send mail to the author or the sensors group asking for
+a datasheet or ideas on how to convince Asus. We can't help.
+
+
+NOTES:
+-----
+  783s has no in1 so that in[2-6] are compatible with the 781d/782d.
+
+  783s pin is programmable for -5V or temp1; defaults to -5V,
+       no control in driver so temp1 doesn't work.
+
+  782d and 783s datasheets differ on which is pwm1 and which is pwm2.
+       We chose to follow 782d.
+
+  782d and 783s pin is programmable for fan3 input or pwm2 output;
+       defaults to fan3 input.
+       If pwm2 is enabled (with echo 255 1 > pwm2), then
+       fan3 will report 0.
+
+  782d has pwm1-2 for ISA, pwm1-4 for i2c. (pwm3-4 share pins with
+       the ISA pins)
+
+Data sheet updates:
+------------------
+       - PWM clock registers:
+
+               000: master /  512
+               001: master / 1024
+               010: master / 2048
+               011: master / 4096
+               100: master / 8192
+
+
+Answers from Winbond tech support
+---------------------------------
+>
+> 1) In the W83781D data sheet section 7.2 last paragraph, it talks about
+>    reprogramming the R-T table if the Beta of the thermistor is not
+>    3435K. The R-T table is described briefly in section 8.20.
+>    What formulas do I use to program a new R-T table for a given Beta?
+>
+       We are sorry that the calculation for R-T table value is
+confidential. If you have another Beta value of thermistor, we can help
+to calculate the R-T table for you. But you should give us real R-T
+Table which can be gotten by thermistor vendor. Therefore we will calculate
+them and obtain 32-byte data, and you can fill the 32-byte data to the
+register in Bank0.CR51 of W83781D.
+
+
+> 2) In the W83782D data sheet, it mentions that pins 38, 39, and 40 are
+>    programmable to be either thermistor or Pentium II diode inputs.
+>    How do I program them for diode inputs? I can't find any register
+>    to program these to be diode inputs.
+ --> You may program Bank0 CR[5Dh] and CR[59h] registers.
+
+       CR[5Dh]                 bit 1(VTIN1)    bit 2(VTIN2)   bit 3(VTIN3)
+
+       thermistor                0              0              0
+       diode                     1              1              1
+
+
+(error) CR[59h]                bit 4(VTIN1)    bit 2(VTIN2)   bit 3(VTIN3)
+(right) CR[59h]                bit 4(VTIN1)    bit 5(VTIN2)   bit 6(VTIN3)
+
+       PII thermal diode         1              1              1
+       2N3904  diode             0              0              0
+
+
+Asus Clones
+-----------
+
+We have no datasheets for the Asus clones (AS99127F and ASB100 Bach).
+Here are some very useful information that were given to us by Alex Van
+Kaam about how to detect these chips, and how to read their values. He
+also gives advice for another Asus chipset, the Mozart-2 (which we
+don't support yet). Thanks Alex!
+I reworded some parts and added personal comments.
+
+# Detection:
+
+AS99127F rev.1, AS99127F rev.2 and ASB100:
+- I2C address range: 0x29 - 0x2F
+- If register 0x58 holds 0x31 then we have an Asus (either ASB100 or
+  AS99127F)
+- Which one depends on register 0x4F (manufacturer ID):
+  0x06 or 0x94: ASB100
+  0x12 or 0xC3: AS99127F rev.1
+  0x5C or 0xA3: AS99127F rev.2
+  Note that 0x5CA3 is Winbond's ID (WEC), which let us think Asus get their
+  AS99127F rev.2 direct from Winbond. The other codes mean ATT and DVC,
+  respectively. ATT could stand for Asustek something (although it would be
+  very badly chosen IMHO), I don't know what DVC could stand for. Maybe
+  these codes simply aren't meant to be decoded that way.
+
+Mozart-2:
+- I2C address: 0x77
+- If register 0x58 holds 0x56 or 0x10 then we have a Mozart-2
+- Of the Mozart there are 3 types:
+  0x58=0x56, 0x4E=0x94, 0x4F=0x36: Asus ASM58 Mozart-2
+  0x58=0x56, 0x4E=0x94, 0x4F=0x06: Asus AS2K129R Mozart-2
+  0x58=0x10, 0x4E=0x5C, 0x4F=0xA3: Asus ??? Mozart-2
+  You can handle all 3 the exact same way :)
+
+# Temperature sensors:
+
+ASB100:
+- sensor 1: register 0x27
+- sensor 2 & 3 are the 2 LM75's on the SMBus
+- sensor 4: register 0x17
+Remark: I noticed that on Intel boards sensor 2 is used for the CPU
+  and 4 is ignored/stuck, on AMD boards sensor 4 is the CPU and sensor 2 is
+  either ignored or a socket temperature.
+
+AS99127F (rev.1 and 2 alike):
+- sensor 1: register 0x27
+- sensor 2 & 3 are the 2 LM75's on the SMBus
+Remark: Register 0x5b is suspected to be temperature type selector. Bit 1
+  would control temp1, bit 3 temp2 and bit 5 temp3.
+
+Mozart-2:
+- sensor 1: register 0x27
+- sensor 2: register 0x13
+
+# Fan sensors:
+
+ASB100, AS99127F (rev.1 and 2 alike):
+- 3 fans, identical to the W83781D
+
+Mozart-2:
+- 2 fans only, 1350000/RPM/div
+- fan 1: register 0x28,  divisor on register 0xA1 (bits 4-5)
+- fan 2: register 0x29,  divisor on register 0xA1 (bits 6-7)
+
+# Voltages:
+
+This is where there is a difference between AS99127F rev.1 and 2.
+Remark: The difference is similar to the difference between
+  W83781D and W83782D.
+
+ASB100:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=r(0x25)*(-0.016)*3.97
+in6=r(0x26)*(-0.016)*1.666
+
+AS99127F rev.1:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=r(0x25)*(-0.016)*3.97
+in6=r(0x26)*(-0.016)*1.503
+
+AS99127F rev.2:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=(r(0x25)*0.016-3.6)*5.14+3.6
+in6=(r(0x26)*0.016-3.6)*3.14+3.6
+
+Mozart-2:
+in0=r(0x20)*0.016
+in1=255
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*4
+in5=255
+in6=255
+
+
+# PWM
+
+Additional info about PWM on the AS99127F (may apply to other Asus
+chips as well) by Jean Delvare as of 2004-04-09:
+
+AS99127F revision 2 seems to have two PWM registers at 0x59 and 0x5A,
+and a temperature sensor type selector at 0x5B (which basically means
+that they swapped registers 0x59 and 0x5B when you compare with Winbond
+chips).
+Revision 1 of the chip also has the temperature sensor type selector at
+0x5B, but PWM registers have no effect.
+
+We don't know exactly how the temperature sensor type selection works.
+Looks like bits 1-0 are for temp1, bits 3-2 for temp2 and bits 5-4 for
+temp3, although it is possible that only the most significant bit matters
+each time. So far, values other than 0 always broke the readings.
+
+PWM registers seem to be split in two parts: bit 7 is a mode selector,
+while the other bits seem to define a value or threshold.
+
+When bit 7 is clear, bits 6-0 seem to hold a threshold value. If the value
+is below a given limit, the fan runs at low speed. If the value is above
+the limit, the fan runs at full speed. We have no clue as to what the limit
+represents. Note that there seem to be some inertia in this mode, speed
+changes may need some time to trigger. Also, an hysteresis mechanism is
+suspected since walking through all the values increasingly and then
+decreasingly led to slightly different limits.
+
+When bit 7 is set, bits 3-0 seem to hold a threshold value, while bits 6-4
+would not be significant. If the value is below a given limit, the fan runs
+at full speed, while if it is above the limit it runs at low speed (so this
+is the contrary of the other mode, in a way). Here again, we don't know
+what the limit is supposed to represent.
+
+One remarkable thing is that the fans would only have two or three
+different speeds (transitional states left apart), not a whole range as
+you usually get with PWM.
+
+As a conclusion, you can write 0x00 or 0x8F to the PWM registers to make
+fans run at low speed, and 0x7F or 0x80 to make them run at full speed.
+
+Please contact us if you can figure out how it is supposed to work. As
+long as we don't know more, the w83781d driver doesn't handle PWM on
+AS99127F chips at all.
+
+Additional info about PWM on the AS99127F rev.1 by Hector Martin:
+
+I've been fiddling around with the (in)famous 0x59 register and
+found out the following values do work as a form of coarse pwm:
+
+0x80 - seems to turn fans off after some time(1-2 minutes)... might be
+some form of auto-fan-control based on temp? hmm (Qfan? this mobo is an
+old ASUS, it isn't marketed as Qfan. Maybe some beta pre-attemp at Qfan
+that was dropped at the BIOS)
+0x81 - off
+0x82 - slightly "on-ner" than off, but my fans do not get to move. I can
+hear the high-pitched PWM sound that motors give off at too-low-pwm.
+0x83 - now they do move. Estimate about 70% speed or so.
+0x84-0x8f - full on
+
+Changing the high nibble doesn't seem to do much except the high bit
+(0x80) must be set for PWM to work, else the current pwm doesn't seem to
+change.
+
+My mobo is an ASUS A7V266-E. This behavior is similar to what I got
+with speedfan under Windows, where 0-15% would be off, 15-2x% (can't
+remember the exact value) would be 70% and higher would be full on.
diff --git a/Documentation/i2c/chips/w83l785ts b/Documentation/i2c/chips/w83l785ts
new file mode 100644 (file)
index 0000000..1841ced
--- /dev/null
@@ -0,0 +1,39 @@
+Kernel driver w83l785ts
+=======================
+
+Supported chips:
+  * Winbond W83L785TS-S
+    Prefix: 'w83l785ts'
+    Addresses scanned: I2C 0x2e
+    Datasheet: Publicly available at the Winbond USA website
+               http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83L785TS-S.pdf
+
+Authors:
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The W83L785TS-S is a digital temperature sensor. It senses the
+temperature of a single external diode. The high limit is
+theoretically defined as 85 or 100 degrees C through a combination
+of external resistors, so the user cannot change it. Values seen so
+far suggest that the two possible limits are actually 95 and 110
+degrees C. The datasheet is rather poor and obviously inaccurate
+on several points including this one.
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree. See the datasheet for details.
+
+The w83l785ts driver will not update its values more frequently than
+every other second; reading them more often will do no harm, but will
+return 'old' values.
+
+Known Issues
+------------
+
+On some systems (Asus), the BIOS is known to interfere with the driver
+and cause read errors. The driver will retry a given number of times
+(5 by default) and then give up, returning the old value (or 0 if
+there is no old value). It seems to work well enough so that you should
+not notice anything. Thanks to James Bolt for helping test this feature.
index 56404918eabc32b50ed67cbcd6caf1b99610b7d0..a7adbdd9ea8a51aa46298cd48bdd566b1f9566d3 100644 (file)
@@ -57,7 +57,7 @@ Technical changes:
   Documentation/i2c/sysfs-interface for the individual files. Also
   convert the units these files read and write to the specified ones.
   If you need to add a new type of file, please discuss it on the
-  sensors mailing list <sensors@stimpy.netroedge.com> by providing a
+  sensors mailing list <lm-sensors@lm-sensors.org> by providing a
   patch to the Documentation/i2c/sysfs-interface file.
 
 * [Attach] For I2C drivers, the attach function should make sure
diff --git a/Documentation/i2c/userspace-tools b/Documentation/i2c/userspace-tools
new file mode 100644 (file)
index 0000000..2622aac
--- /dev/null
@@ -0,0 +1,39 @@
+Introduction
+------------
+
+Most mainboards have sensor chips to monitor system health (like temperatures,
+voltages, fans speed). They are often connected through an I2C bus, but some
+are also connected directly through the ISA bus.
+
+The kernel drivers make the data from the sensor chips available in the /sys
+virtual filesystem. Userspace tools are then used to display or set or the
+data in a more friendly manner.
+
+Lm-sensors
+----------
+
+Core set of utilites that will allow you to obtain health information,
+setup monitoring limits etc. You can get them on their homepage
+http://www.lm-sensors.nu/ or as a package from your Linux distribution.
+
+If from website:
+Get lmsensors from project web site. Please note, you need only userspace
+part, so compile with "make user_install" target.
+
+General hints to get things working:
+
+0) get lm-sensors userspace utils
+1) compile all drivers in I2C section as modules in your kernel
+2) run sensors-detect script, it will tell you what modules you need to load.
+3) load them and run "sensors" command, you should see some results.
+4) fix sensors.conf, labels, limits, fan divisors
+5) if any more problems consult FAQ, or documentation
+
+Other utilites
+--------------
+
+If you want some graphical indicators of system health look for applications
+like: gkrellm, ksensors, xsensors, wmtemp, wmsensors, wmgtemp, ksysguardd,
+hardware-monitor
+
+If you are server administrator you can try snmpd or mrtgutils.
index ad27511e3c7d7c463f5fdb4ce02ea2d96bd4f0ce..f482dae81de3ec2a27b8ace0814e99d43150ca3e 100644 (file)
@@ -171,45 +171,31 @@ The following lists are used internally:
 
   normal_i2c: filled in by the module writer. 
      A list of I2C addresses which should normally be examined.
-   normal_i2c_range: filled in by the module writer.
-     A list of pairs of I2C addresses, each pair being an inclusive range of
-     addresses which should normally be examined.
    probe: insmod parameter. 
      A list of pairs. The first value is a bus number (-1 for any I2C bus), 
      the second is the address. These addresses are also probed, as if they 
      were in the 'normal' list.
-   probe_range: insmod parameter. 
-     A list of triples. The first value is a bus number (-1 for any I2C bus), 
-     the second and third are addresses.  These form an inclusive range of 
-     addresses that are also probed, as if they were in the 'normal' list.
    ignore: insmod parameter.
      A list of pairs. The first value is a bus number (-1 for any I2C bus), 
      the second is the I2C address. These addresses are never probed. 
      This parameter overrules 'normal' and 'probe', but not the 'force' lists.
-   ignore_range: insmod parameter. 
-     A list of triples. The first value is a bus number (-1 for any I2C bus), 
-     the second and third are addresses. These form an inclusive range of 
-     I2C addresses that are never probed.
-     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
    force: insmod parameter. 
      A list of pairs. The first value is a bus number (-1 for any I2C bus),
      the second is the I2C address. A device is blindly assumed to be on
      the given address, no probing is done. 
 
-Fortunately, as a module writer, you just have to define the `normal' 
-and/or `normal_range' parameters. The complete declaration could look
-like this:
+Fortunately, as a module writer, you just have to define the `normal_i2c' 
+parameter. The complete declaration could look like this:
 
-  /* Scan 0x20 to 0x2f, 0x37, and 0x40 to 0x4f */
-  static unsigned short normal_i2c[] = { 0x37,I2C_CLIENT_END }; 
-  static unsigned short normal_i2c_range[] = { 0x20, 0x2f, 0x40, 0x4f, 
-                                               I2C_CLIENT_END };
+  /* Scan 0x37, and 0x48 to 0x4f */
+  static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+                                         0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
 
   /* Magic definition of all other variables and things */
   I2C_CLIENT_INSMOD;
 
-Note that you *have* to call the two defined variables `normal_i2c' and
-`normal_i2c_range', without any prefix!
+Note that you *have* to call the defined variable `normal_i2c',
+without any prefix!
 
 
 Probing classes (sensors)
@@ -223,39 +209,17 @@ The following lists are used internally. They are all lists of integers.
 
    normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
      A list of I2C addresses which should normally be examined.
-   normal_i2c_range: filled in by the module writer. Terminated by 
-     SENSORS_I2C_END
-     A list of pairs of I2C addresses, each pair being an inclusive range of
-     addresses which should normally be examined.
    normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
      A list of ISA addresses which should normally be examined.
-   normal_isa_range: filled in by the module writer. Terminated by 
-     SENSORS_ISA_END
-     A list of triples. The first two elements are ISA addresses, being an
-     range of addresses which should normally be examined. The third is the
-     modulo parameter: only addresses which are 0 module this value relative
-     to the first address of the range are actually considered.
    probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
      A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
      the ISA bus, -1 for any I2C bus), the second is the address. These
      addresses are also probed, as if they were in the 'normal' list.
-   probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
-     values.
-     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
-     These form an inclusive range of addresses that are also probed, as
-     if they were in the 'normal' list.
    ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
      A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
      the ISA bus, -1 for any I2C bus), the second is the I2C address. These
      addresses are never probed. This parameter overrules 'normal' and 
      'probe', but not the 'force' lists.
-   ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
-      values.
-     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
-     These form an inclusive range of I2C addresses that are never probed.
-     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
 
 Also used is a list of pointers to sensors_force_data structures:
    force_data: insmod parameters. A list, ending with an element of which
@@ -269,16 +233,14 @@ Also used is a list of pointers to sensors_force_data structures:
 So we have a generic insmod variabled `force', and chip-specific variables
 `force_CHIPNAME'.
 
-Fortunately, as a module writer, you just have to define the `normal' 
-and/or `normal_range' parameters, and define what chip names are used. 
+Fortunately, as a module writer, you just have to define the `normal_i2c
+and `normal_isa' parameters, and define what chip names are used. 
 The complete declaration could look like this:
-  /* Scan i2c addresses 0x20 to 0x2f, 0x37, and 0x40 to 0x4f
-  static unsigned short normal_i2c[] = {0x37,SENSORS_I2C_END};
-  static unsigned short normal_i2c_range[] = {0x20,0x2f,0x40,0x4f,
-                                              SENSORS_I2C_END};
+  /* Scan i2c addresses 0x37, and 0x48 to 0x4f */
+  static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+                                         0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
   /* Scan ISA address 0x290 */
   static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
-  static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
 
   /* Define chips foo and bar, as well as all module parameters and things */
   SENSORS_INSMOD_2(foo,bar);
index a831d9ae5a5ef0ce6272fe08fe0d8e63e7c46ada..59d1166d41eeebc095528a84a24fa584ea0c953d 100644 (file)
@@ -30,7 +30,7 @@ Command line parameters
   device numbers (0xabcd or abcd, for 2.4 backward compatibility).
   You can use the 'all' keyword to ignore all devices.
   The '!' operator will cause the I/O-layer to _not_ ignore a device.
-  The order on the command line is not important.
+  The command line is parsed from left to right.
 
   For example, 
        cio_ignore=0.0.0023-0.0.0042,0.0.4711
@@ -72,13 +72,14 @@ Command line parameters
   /proc/cio_ignore; "add <device range>, <device range>, ..." will ignore the
   specified devices.
 
-  Note: Already known devices cannot be ignored.
+  Note: While already known devices can be added to the list of devices to be
+        ignored, there will be no effect on then. However, if such a device
+        disappears and then reappeares, it will then be ignored.
 
-  For example, if device 0.0.abcd is already known and all other devices
-  0.0.a000-0.0.afff are not known,
+  For example,
        "echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore"
-  will add 0.0.a000-0.0.abcc, 0.0.abce-0.0.accc and 0.0.af00-0.0.afff to the
-  list of ignored devices and skip 0.0.abcd.
+  will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored
+  devices.
 
   The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward
   compatibilty, by the device number in hexadecimal (0xabcd or abcd).
@@ -98,7 +99,8 @@ Command line parameters
 
   - /proc/s390dbf/cio_trace/hex_ascii
     Logs the calling of functions in the common I/O-layer and, if applicable, 
-    which subchannel they were called for.
+    which subchannel they were called for, as well as dumps of some data
+    structures (like irb in an error case).
 
   The level of logging can be changed to be more or less verbose by piping to 
   /proc/s390dbf/cio_*/level a number between 0 and 6; see the documentation on
diff --git a/Documentation/sgi-ioc4.txt b/Documentation/sgi-ioc4.txt
new file mode 100644 (file)
index 0000000..876c96a
--- /dev/null
@@ -0,0 +1,45 @@
+The SGI IOC4 PCI device is a bit of a strange beast, so some notes on
+it are in order.
+
+First, even though the IOC4 performs multiple functions, such as an
+IDE controller, a serial controller, a PS/2 keyboard/mouse controller,
+and an external interrupt mechanism, it's not implemented as a
+multifunction device.  The consequence of this from a software
+standpoint is that all these functions share a single IRQ, and
+they can't all register to own the same PCI device ID.  To make
+matters a bit worse, some of the register blocks (and even registers
+themselves) present in IOC4 are mixed-purpose between these several
+functions, meaning that there's no clear "owning" device driver.
+
+The solution is to organize the IOC4 driver into several independent
+drivers, "ioc4", "sgiioc4", and "ioc4_serial".  Note that there is no
+PS/2 controller driver as this functionality has never been wired up
+on a shipping IO card.
+
+ioc4
+====
+This is the core (or shim) driver for IOC4.  It is responsible for
+initializing the basic functionality of the chip, and allocating
+the PCI resources that are shared between the IOC4 functions.
+
+This driver also provides registration functions that the other
+IOC4 drivers can call to make their presence known.  Each driver
+needs to provide a probe and remove function, which are invoked
+by the core driver at appropriate times.  The interface of these
+IOC4 function probe and remove operations isn't precisely the same
+as PCI device probe and remove operations, but is logically the
+same operation.
+
+sgiioc4
+=======
+This is the IDE driver for IOC4.  Its name isn't very descriptive
+simply for historical reasons (it used to be the only IOC4 driver
+component).  There's not much to say about it other than it hooks
+up to the ioc4 driver via the appropriate registration, probe, and
+remove functions.
+
+ioc4_serial
+===========
+This is the serial driver for IOC4.  There's not much to say about it
+other than it hooks up to the ioc4 driver via the appropriate registration,
+probe, and remove functions.
index 71ef0498d5e03e3e334c3d9bdefdd1c502611291..104a994b8289fc056ac6685f8bd7720ce35289c5 100644 (file)
@@ -615,9 +615,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
   Module snd-hda-intel
   --------------------
 
-    Module for Intel HD Audio (ICH6, ICH6M, ICH7)
+    Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450,
+              VIA VT8251/VT8237A
 
     model      - force the model name
+    position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)
 
     Module supports up to 8 cards.
 
@@ -635,6 +637,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          5stack        5-jack in back, 2-jack in front
          5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
          w810          3-jack
+         z71v          3-jack (HP shared SPDIF)
+         asus          3-jack
+         uniwill       3-jack
+         F1734         2-jack
 
        CMI9880
          minimal       3-jack in back
@@ -642,6 +648,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          full          6-jack in back, 2-jack in front
          full_dig      6-jack in back, 2-jack in front, SPDIF I/O
          allout        5-jack in back, 2-jack in front, SPDIF out
+         auto          auto-config reading BIOS (default)
+
+    Note 2: If you get click noises on output, try the module option
+           position_fix=1 or 2.  position_fix=1 will use the SD_LPIB
+           register value without FIFO size correction as the current
+           DMA pointer.  position_fix=2 will make the driver to use
+           the position buffer instead of reading SD_LPIB register.
+           (Usually SD_LPLIB register is more accurate than the
+           position buffer.)
 
   Module snd-hdsp
   ---------------
@@ -660,7 +675,19 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
           module did formerly.  It will allocate the buffers in advance
           when any HDSP cards are found.  To make the buffer
           allocation sure, load snd-page-alloc module in the early
-          stage of boot sequence.
+          stage of boot sequence.  See "Early Buffer Allocation"
+         section.
+
+  Module snd-hdspm
+  ----------------
+
+    Module for RME HDSP MADI board.
+
+    precise_ptr                - Enable precise pointer, or disable.
+    line_outs_monitor  - Send playback streams to analog outs by default.
+    enable_monitor     - Enable Analog Out on Channel 63/64 by default.
+
+    See hdspm.txt for details.
 
   Module snd-ice1712
   ------------------
@@ -677,15 +704,19 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
                         * TerraTec EWS 88D
                         * TerraTec EWX 24/96
                         * TerraTec DMX 6Fire
+                       * TerraTec Phase 88
                         * Hoontech SoundTrack DSP 24
                         * Hoontech SoundTrack DSP 24 Value
                         * Hoontech SoundTrack DSP 24 Media 7.1
+                       * Event Electronics, EZ8
                         * Digigram VX442
+                       * Lionstracs, Mediastaton
 
     model       - Use the given board model, one of the following:
                  delta1010, dio2496, delta66, delta44, audiophile, delta410,
                  delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
-                 dmx6fire, dsp24, dsp24_value, dsp24_71, ez8
+                 dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
+                 phase88, mediastation
     omni       - Omni I/O support for MidiMan M-Audio Delta44/66
     cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
                      in msec resolution, default value is 500 (0.5 sec)
@@ -694,20 +725,46 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     is not used with all Envy24 based cards (for example in the MidiMan Delta
     serie).
 
+    Note: The supported board is detected by reading EEPROM or PCI
+         SSID (if EEPROM isn't available).  You can override the
+         model by passing "model" module option in case that the
+         driver isn't configured properly or you want to try another
+         type for testing.
+
   Module snd-ice1724
   ------------------
 
-    Module for Envy24HT (VT/ICE1724) based PCI sound cards.
+    Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
                        * MidiMan M Audio Revolution 7.1
                        * AMP Ltd AUDIO2000
-                       * TerraTec Aureon Sky-5.1, Space-7.1
+                       * TerraTec Aureon 5.1 Sky
+                       * TerraTec Aureon 7.1 Space
+                       * TerraTec Aureon 7.1 Universe
+                       * TerraTec Phase 22
+                       * TerraTec Phase 28
+                       * AudioTrak Prodigy 7.1
+                       * AudioTrak Prodigy 192
+                       * Pontis MS300
+                       * Albatron K8X800 Pro II 
+                       * Chaintech ZNF3-150
+                       * Chaintech ZNF3-250
+                       * Chaintech 9CJS
+                       * Chaintech AV-710
+                       * Shuttle SN25P
 
     model       - Use the given board model, one of the following:
-                 revo71, amp2000, prodigy71, aureon51, aureon71,
-                 k8x800
+                 revo71, amp2000, prodigy71, prodigy192, aureon51,
+                 aureon71, universe, k8x800, phase22, phase28, ms300,
+                 av710
 
     Module supports up to 8 cards and autoprobe.
 
+    Note: The supported board is detected by reading EEPROM or PCI
+         SSID (if EEPROM isn't available).  You can override the
+         model by passing "model" module option in case that the
+         driver isn't configured properly or you want to try another
+         type for testing.
+
   Module snd-intel8x0
   -------------------
 
@@ -1026,7 +1083,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
           module did formerly.  It will allocate the buffers in advance
           when any RME9652 cards are found.  To make the buffer
           allocation sure, load snd-page-alloc module in the early
-          stage of boot sequence.
+          stage of boot sequence.  See "Early Buffer Allocation"
+         section.
 
   Module snd-sa11xx-uda1341 (on arm only)
   ---------------------------------------
@@ -1211,16 +1269,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
   ------------------
 
     Module for AC'97 motherboards based on VIA 82C686A/686B, 8233,
-    8233A, 8233C, 8235 (south) bridge.
+    8233A, 8233C, 8235, 8237 (south) bridge.
 
     mpu_port   - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
                  [VIA686A/686B only]
     joystick   - Enable joystick (default off) [VIA686A/686B only]
     ac97_clock - AC'97 codec clock base (default 48000Hz)
     dxs_support        - support DXS channels,
-                 0 = auto (defalut), 1 = enable, 2 = disable,
-                 3 = 48k only, 4 = no VRA
-                 [VIA8233/C,8235 only]
+                 0 = auto (default), 1 = enable, 2 = disable,
+                 3 = 48k only, 4 = no VRA, 5 = enable any sample
+                 rate and different sample rates on different
+                 channels
+                 [VIA8233/C, 8235, 8237 only]
     ac97_quirk  - AC'97 workaround for strange hardware
                   See the description of intel8x0 module for details.
 
@@ -1232,18 +1292,23 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
           default value 1.4.  Then the interrupt number will be
           assigned under 15. You might also upgrade your BIOS.
     
-    Note: VIA8233/5 (not VIA8233A) can support DXS (direct sound)
+    Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
          channels as the first PCM.  On these channels, up to 4
-         streams can be played at the same time.
+         streams can be played at the same time, and the controller
+         can perform sample rate conversion with separate rates for
+         each channel.
          As default (dxs_support = 0), 48k fixed rate is chosen
          except for the known devices since the output is often
          noisy except for 48k on some mother boards due to the
          bug of BIOS.
-         Please try once dxs_support=1 and if it works on other
+         Please try once dxs_support=5 and if it works on other
          sample rates (e.g. 44.1kHz of mp3 playback), please let us
          know the PCI subsystem vendor/device id's (output of
          "lspci -nv").
-         If it doesn't work, try dxs_support=4.  If it still doesn't
+         If dxs_support=5 does not work, try dxs_support=4; if it
+         doesn't work too, try dxs_support=1.  (dxs_support=1 is
+         usually for old motherboards.  The correct implementated
+         board should work with 4 or 5.)  If it still doesn't
          work and the default setting is ok, dxs_support=3 is the
          right choice.  If the default setting doesn't work at all,
          try dxs_support=2 to disable the DXS channels.
@@ -1497,6 +1562,36 @@ Proc interfaces (/proc/asound)
           echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss
 
 
+Early Buffer Allocation
+=======================
+
+Some drivers (e.g. hdsp) require the large contiguous buffers, and
+sometimes it's too late to find such spaces when the driver module is
+actually loaded due to memory fragmentation.  You can pre-allocate the
+PCM buffers by loading snd-page-alloc module and write commands to its
+proc file in prior, for example, in the early boot stage like
+/etc/init.d/*.local scripts.
+
+Reading the proc file /proc/drivers/snd-page-alloc shows the current
+usage of page allocation.  In writing, you can send the following
+commands to the snd-page-alloc driver:
+
+  - add VENDOR DEVICE MASK SIZE BUFFERS
+
+    VENDOR and DEVICE are PCI vendor and device IDs.  They take
+    integer numbers (0x prefix is needed for the hex).
+    MASK is the PCI DMA mask.  Pass 0 if not restricted.
+    SIZE is the size of each buffer to allocate.  You can pass
+    k and m suffix for KB and MB.  The max number is 16MB.
+    BUFFERS is the number of buffers to allocate.  It must be greater
+    than 0.  The max number is 4.
+
+  - erase
+
+    This will erase the all pre-allocated buffers which are not in
+    use.
+
+
 Links
 =====
 
index 4a7df771b806c7f7728d4b72292b62478a3bcd37..1872e24442a47537d7b0497ab2ea17067dc64f16 100644 (file)
@@ -89,19 +89,22 @@ and use the interleaved 4 channel data.
 
 There are some control switchs affecting to the speaker connections:
 
-"Line-In As Rear"      - As mentioned above, the line-in jack is used
-       for the rear (3th and 4th channels) output.
-"Line-In As Bass"      - The line-in jack is used for the bass (5th
-       and 6th channels) output.
-"Mic As Center/LFE"    - The mic jack is used for the bass output.
-       If this switch is on, you cannot use a microphone as a capture
-       source, of course.
-
+"Line-In Mode" - an enum control to change the behavior of line-in
+       jack.  Either "Line-In", "Rear Output" or "Bass Output" can
+       be selected.  The last item is available only with model 039
+       or newer. 
+       When "Rear Output" is chosen, the surround channels 3 and 4
+       are output to line-in jack.
+"Mic-In Mode"  - an enum control to change the behavior of mic-in
+       jack.  Either "Mic-In" or "Center/LFE Output" can be
+       selected. 
+       When "Center/LFE Output" is chosen, the center and bass
+       channels (channels 5 and 6) are output to mic-in jack. 
 
 Digital I/O
 -----------
 
-The CM8x38 provides the excellent SPDIF capability with very chip
+The CM8x38 provides the excellent SPDIF capability with very cheap
 price (yes, that's the reason I bought the card :)
 
 The SPDIF playback and capture are done via the third PCM device
@@ -122,8 +125,9 @@ respectively, so you cannot playback both analog and digital streams
 simultaneously.
 
 To enable SPDIF output, you need to turn on "IEC958 Output Switch"
-control via mixer or alsactl.  Then you'll see the red light on from
-the card so you know that's working obviously :)
+control via mixer or alsactl ("IEC958" is the official name of
+so-called S/PDIF).  Then you'll see the red light on from the card so
+you know that's working obviously :)
 The SPDIF input is always enabled, so you can hear SPDIF input data
 from line-out with "IEC958 In Monitor" switch at any time (see
 below).
@@ -205,9 +209,10 @@ In addition to the standard SB mixer, CM8x38 provides more functions.
 MIDI CONTROLLER
 ---------------
 
-The MPU401-UART interface is enabled as default only for the first
-(CMIPCI) card.  You need to set module option "midi_port" properly
-for the 2nd (CMIPCI) card.
+The MPU401-UART interface is disabled as default.  You need to set
+module option "mpu_port" with a valid I/O port address to enable the
+MIDI support.  The valid I/O ports are 0x300, 0x310, 0x320 and 0x330.
+Choose the value which doesn't conflict with other cards.
 
 There is _no_ hardware wavetable function on this chip (except for
 OPL3 synth below).
@@ -229,9 +234,11 @@ I don't know why..
 Joystick and Modem
 ------------------
 
-The joystick and modem should be available by enabling the control
-switch "Joystick" and "Modem" respectively.  But I myself have never
-tested them yet.
+The legacy joystick is supported.  To enable the joystick support, pass
+joystick_port=1 module option.  The value 1 means the auto-detection.
+If the auto-detection fails, try to pass the exact I/O address.
+
+The modem is enabled dynamically via a card control switch "Modem".
 
 
 Debugging Information
index e789475304b6e03b8b8e5c60c72fd8f445f65a5b..db0b7d2dc477cfc01aa0bc10282c850e0c10ae9f 100644 (file)
           <listitem><para>create <function>probe()</function> callback.</para></listitem>
           <listitem><para>create <function>remove()</function> callback.</para></listitem>
           <listitem><para>create pci_driver table which contains the three pointers above.</para></listitem>
-          <listitem><para>create <function>init()</function> function just calling <function>pci_module_init()</function> to register the pci_driver table defined above.</para></listitem>
+          <listitem><para>create <function>init()</function> function just calling <function>pci_register_driver()</function> to register the pci_driver table defined above.</para></listitem>
           <listitem><para>create <function>exit()</function> function to call <function>pci_unregister_driver()</function> function.</para></listitem>
         </itemizedlist>
       </para>
   /* initialization of the module */
   static int __init alsa_card_mychip_init(void)
   {
-          return pci_module_init(&driver);
+          return pci_register_driver(&driver);
   }
 
   /* clean up the module */
 <![CDATA[
   static int __init alsa_card_mychip_init(void)
   {
-          return pci_module_init(&driver);
+          return pci_register_driver(&driver);
   }
 
   static void __exit alsa_card_mychip_exit(void)
diff --git a/Documentation/sound/alsa/emu10k1-jack.txt b/Documentation/sound/alsa/emu10k1-jack.txt
new file mode 100644 (file)
index 0000000..751d450
--- /dev/null
@@ -0,0 +1,74 @@
+This document is a guide to using the emu10k1 based devices with JACK for low
+latency, multichannel recording functionality.  All of my recent work to allow
+Linux users to use the full capabilities of their hardware has been inspired 
+by the kX Project.  Without their work I never would have discovered the true
+power of this hardware.
+
+       http://www.kxproject.com
+                                               - Lee Revell, 2005.03.30
+
+Low latency, multichannel audio with JACK and the emu10k1/emu10k2
+-----------------------------------------------------------------
+
+Until recently, emu10k1 users on Linux did not have access to the same low
+latency, multichannel features offered by the "kX ASIO" feature of their
+Windows driver.  As of ALSA 1.0.9 this is no more!
+
+For those unfamiliar with kX ASIO, this consists of 16 capture and 16 playback
+channels.  With a post 2.6.9 Linux kernel, latencies down to 64 (1.33 ms) or
+even 32 (0.66ms) frames should work well.
+
+The configuration is slightly more involved than on Windows, as you have to
+select the correct device for JACK to use.  Actually, for qjackctl users it's
+fairly self explanatory - select Duplex, then for capture and playback select
+the multichannel devices, set the in and out channels to 16, and the sample
+rate to 48000Hz.  The command line looks like this:
+
+/usr/local/bin/jackd -R -dalsa -r48000 -p64 -n2 -D -Chw:0,2 -Phw:0,3 -S
+
+This will give you 16 input ports and 16 output ports.
+
+The 16 output ports map onto the 16 FX buses (or the first 16 of 64, for the
+Audigy).  The mapping from FX bus to physical output is described in
+SB-Live-mixer.txt (or Audigy-mixer.txt).
+
+The 16 input ports are connected to the 16 physical inputs.  Contrary to
+popular belief, all emu10k1 cards are multichannel cards.  Which of these
+input channels have physical inputs connected to them depends on the card
+model.  Trial and error is highly recommended; the pinout diagrams
+for the card have been reverse engineered by some enterprising kX users and are 
+available on the internet.  Meterbridge is helpful here, and the kX forums are
+packed with useful information.
+
+Each input port will either correspond to a digital (SPDIF) input, an analog
+input, or nothing.  The one exception is the SBLive! 5.1.  On these devices,
+the second and third input ports are wired to the center/LFE output.  You will
+still see 16 capture channels, but only 14 are available for recording inputs.
+
+This chart, borrowed from kxfxlib/da_asio51.cpp, describes the mapping of JACK
+ports to FXBUS2 (multitrack recording input) and EXTOUT (physical output)
+channels.
+
+/*JACK (& ASIO) mappings on 10k1 5.1 SBLive cards:
+--------------------------------------------
+JACK           Epilog          FXBUS2(nr)
+--------------------------------------------
+capture_1      asio14          FXBUS2(0xe)
+capture_2      asio15          FXBUS2(0xf)
+capture_3      asio0           FXBUS2(0x0)     
+~capture_4     Center          EXTOUT(0x11)    // mapped to by Center
+~capture_5     LFE             EXTOUT(0x12)    // mapped to by LFE
+capture_6      asio3           FXBUS2(0x3)
+capture_7      asio4           FXBUS2(0x4)
+capture_8      asio5           FXBUS2(0x5)
+capture_9      asio6           FXBUS2(0x6)
+capture_10     asio7           FXBUS2(0x7)
+capture_11     asio8           FXBUS2(0x8)
+capture_12     asio9           FXBUS2(0x9)
+capture_13     asio10          FXBUS2(0xa)
+capture_14     asio11          FXBUS2(0xb)
+capture_15     asio12          FXBUS2(0xc)
+capture_16     asio13          FXBUS2(0xd)
+*/
+
+TODO: describe use of ld10k1/qlo10k1 in conjunction with JACK
diff --git a/Documentation/sound/alsa/hdspm.txt b/Documentation/sound/alsa/hdspm.txt
new file mode 100644 (file)
index 0000000..7a67ff7
--- /dev/null
@@ -0,0 +1,362 @@
+Software Interface ALSA-DSP MADI Driver 
+
+(translated from German, so no good English ;-), 
+2004 - winfried ritsch
+
+
+
+ Full functionality has been added to the driver. Since some of
+ the Controls and startup-options  are ALSA-Standard and only the
+ special Controls are described and discussed below.
+
+
+ hardware functionality:
+
+   
+   Audio transmission:
+
+     number of channels --  depends on transmission mode
+
+               The number of channels chosen is from 1..Nmax. The reason to
+               use for a lower number of channels is only resource allocation,
+               since unused DMA channels are disabled and less memory is
+               allocated. So also the throughput of the PCI system can be
+               scaled. (Only important for low performance boards).
+
+       Single Speed -- 1..64 channels 
+
+                (Note: Choosing the 56channel mode for transmission or as
+                receiver, only 56 are transmitted/received over the MADI, but
+                all 64 channels are available for the mixer, so channel count
+                for the driver)
+
+       Double Speed -- 1..32 channels
+
+                Note: Choosing the 56-channel mode for
+                transmission/receive-mode , only 28 are transmitted/received
+                over the MADI, but all 32 channels are available for the mixer,
+                so channel count for the driver
+
+
+       Quad Speed -- 1..16 channels 
+
+                Note: Choosing the 56-channel mode for
+                transmission/receive-mode , only 14 are transmitted/received
+                over the MADI, but all 16 channels are available for the mixer,
+                so channel count for the driver
+
+     Format -- signed 32 Bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
+
+     Sample Rates --
+
+       Single Speed -- 32000, 44100, 48000
+
+       Double Speed -- 64000, 88200, 96000 (untested)
+
+       Quad Speed -- 128000, 176400, 192000 (untested)
+
+     access-mode -- MMAP (memory mapped), Not interleaved
+     (PCM_NON-INTERLEAVED)
+
+     buffer-sizes -- 64,128,256,512,1024,2048,8192 Samples
+
+     fragments -- 2
+
+     Hardware-pointer -- 2 Modi
+
+
+                The Card supports the readout of the actual Buffer-pointer,
+                where DMA reads/writes. Since of the bulk mode of PCI it is only
+                64 Byte accurate. SO it is not really usable for the
+                ALSA-mid-level functions (here the buffer-ID gives a better
+                result), but if MMAP is used by the application. Therefore it
+                can be configured at load-time with the parameter
+                precise-pointer.
+
+
+                (Hint: Experimenting I found that the pointer is maximum 64 to
+                large never to small. So if you subtract 64 you always have a
+                safe pointer for writing, which is used on this mode inside
+                ALSA. In theory now you can get now a latency as low as 16
+                Samples, which is a quarter of the interrupt possibilities.)
+
+       Precise Pointer -- off
+                                       interrupt used for pointer-calculation
+
+       Precise Pointer -- on
+                                       hardware pointer used.
+
+   Controller:
+
+
+         Since DSP-MADI-Mixer has 8152 Fader, it does not make sense to
+         use the standard mixer-controls, since this would break most of
+         (especially graphic) ALSA-Mixer GUIs. So Mixer control has be
+         provided by a 2-dimensional controller using the
+         hwdep-interface. 
+
+     Also all 128+256 Peak and RMS-Meter can be accessed via the
+     hwdep-interface. Since it could be a performance problem always
+     copying and converting Peak and RMS-Levels even if you just need
+     one, I decided to export the hardware structure, so that of
+     needed some driver-guru can implement a memory-mapping of mixer
+     or peak-meters over ioctl, or also to do only copying and no
+     conversion. A test-application shows the usage of the controller.
+
+    Latency Controls --- not implemented !!!
+
+
+          Note: Within the windows-driver the latency is accessible of a
+          control-panel, but buffer-sizes are controlled with ALSA from
+          hwparams-calls and should not be changed in run-state, I did not
+          implement it here.
+
+
+    System Clock -- suspended !!!!
+
+        Name -- "System Clock Mode"
+
+        Access -- Read Write
+
+        Values -- "Master" "Slave"
+
+
+                 !!!! This is a hardware-function but is in conflict with the
+                 Clock-source controller, which is a kind of ALSA-standard. I
+                 makes sense to set the card to a special mode (master at some
+                 frequency or slave), since even not using an Audio-application
+                 a studio should have working synchronisations setup. So use
+                 Clock-source-controller instead !!!!
+
+    Clock Source  
+
+       Name -- "Sample Clock Source"
+
+       Access -- Read Write
+
+       Values -- "AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz",
+       "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz",
+       "Internal 96.0 kHz"
+
+                Choose between Master at a specific Frequency and so also the
+                Speed-mode or Slave (Autosync). Also see  "Preferred Sync Ref"
+
+
+       !!!! This is no pure hardware function but was implemented by
+       ALSA by some ALSA-drivers before, so I use it also. !!!
+
+
+    Preferred Sync Ref
+
+       Name -- "Preferred Sync Reference"
+
+       Access -- Read Write
+
+       Values -- "Word" "MADI"
+
+
+                Within the Auto-sync-Mode the preferred Sync Source can be
+                chosen. If it is not available another is used if possible.
+
+                Note: Since MADI has a much higher bit-rate than word-clock, the
+                card should synchronise better in MADI Mode. But since the
+                RME-PLL is very good, there are almost no problems with
+                word-clock too. I never found a difference.
+
+
+    TX 64 channel --- 
+
+       Name -- "TX 64 channels mode"
+
+       Access -- Read Write
+
+       Values -- 0 1
+
+                Using 64-channel-modus (1) or 56-channel-modus for
+                MADI-transmission (0).
+
+
+                Note: This control is for output only. Input-mode is detected
+                automatically from hardware sending MADI.
+
+
+    Clear TMS ---
+
+       Name -- "Clear Track Marker"
+
+       Access -- Read Write
+
+       Values -- 0 1
+
+
+                Don't use to lower 5 Audio-bits on AES as additional Bits.
+        
+
+    Safe Mode oder Auto Input --- 
+
+       Name -- "Safe Mode"
+
+       Access -- Read Write
+
+       Values -- 0 1
+
+       (default on)
+
+                If on (1), then if either the optical or coaxial connection
+                has a failure, there is a takeover to the working one, with no
+                sample failure. Its only useful if you use the second as a
+                backup connection.
+
+    Input --- 
+
+       Name -- "Input Select"
+
+       Access -- Read Write
+
+       Values -- optical coaxial
+
+
+                Choosing the Input, optical or coaxial. If Safe-mode is active,
+                this is the preferred Input.
+
+-------------- Mixer ----------------------
+
+    Mixer
+
+       Name -- "Mixer"
+
+       Access -- Read Write
+
+       Values - <channel-number 0-127> <Value 0-65535>
+
+
+                Here as a first value the channel-index is taken to get/set the
+                corresponding mixer channel, where 0-63 are the input to output
+                fader and 64-127 the playback to outputs fader. Value 0
+                is channel muted 0 and 32768 an amplification of  1.
+
+    Chn 1-64
+
+       fast mixer for the ALSA-mixer utils. The diagonal of the
+       mixer-matrix is implemented from playback to output.
+       
+
+    Line Out
+
+       Name  -- "Line Out"
+
+       Access -- Read Write
+
+       Values -- 0 1
+
+                Switching on and off the analog out, which has nothing to do
+                with mixing or routing. the analog outs reflects channel 63,64.
+
+
+--- information (only read access):
+    Sample Rate
+
+       Name -- "System Sample Rate"
+
+       Access -- Read-only
+
+                getting the sample rate.
+
+
+    External Rate measured
+
+       Name -- "External Rate"
+
+       Access -- Read only
+
+
+                Should be "Autosync Rate", but Name used is
+                ALSA-Scheme. External Sample frequency liked used on Autosync is
+                reported.
+
+
+    MADI Sync Status
+
+       Name -- "MADI Sync Lock Status"
+
+       Access -- Read
+
+       Values -- 0,1,2
+
+       MADI-Input is 0=Unlocked, 1=Locked, or 2=Synced.
+
+
+    Word Clock Sync Status
+
+       Name -- "Word Clock Lock Status"
+
+       Access -- Read
+
+       Values -- 0,1,2
+
+       Word Clock Input is 0=Unlocked, 1=Locked, or 2=Synced.
+
+    AutoSync
+
+       Name -- "AutoSync Reference"
+
+       Access -- Read
+
+       Values -- "WordClock", "MADI", "None"
+
+                Sync-Reference is either "WordClock", "MADI" or none.
+
+   RX 64ch --- noch nicht implementiert
+
+       MADI-Receiver is in 64 channel mode oder 56 channel mode.
+
+
+   AB_inp   --- not tested 
+
+                Used input for Auto-Input.
+
+
+   actual Buffer Position --- not implemented
+
+          !!! this is a ALSA internal function, so no control is used !!!
+
+
+
+Calling Parameter:
+
+   index int array (min = 1, max = 8), 
+     "Index value for RME HDSPM interface." card-index within ALSA
+
+     note: ALSA-standard
+
+   id string array (min = 1, max = 8), 
+     "ID string for RME HDSPM interface."
+
+     note: ALSA-standard
+
+   enable int array (min = 1, max = 8), 
+     "Enable/disable specific HDSPM sound-cards."
+
+     note: ALSA-standard
+
+   precise_ptr int array (min = 1, max = 8), 
+     "Enable precise pointer, or disable."
+
+     note: Use only when the application supports this (which is a special case).
+
+   line_outs_monitor int array (min = 1, max = 8), 
+     "Send playback streams to analog outs by default."
+
+
+         note: each playback channel is mixed to the same numbered output
+         channel (routed). This is against the ALSA-convention, where all
+         channels have to be muted on after loading the driver, but was
+         used before on other cards, so i historically use it again)
+
+
+
+   enable_monitor int array (min = 1, max = 8), 
+     "Enable Analog Out on Channel 63/64 by default."
+
+      note: here the analog output is enabled (but not routed).
\ No newline at end of file
index eace3046a8582b23beb0928fe28d698b9bf1194a..f937fbe1cacbc86ceb808a1d4ab1fe39f793a104 100644 (file)
@@ -1,19 +1,92 @@
-Any w1 device must be connected to w1 bus master device - for example
-ds9490 usb device or w1-over-GPIO or RS232 converter.
-Driver for w1 bus master must provide several functions(you can find
-them in struct w1_bus_master definition in w1.h) which then will be
-called by w1 core to send various commands over w1 bus(by default it is
-reset and search commands). When some device is found on the bus, w1 core
-checks if driver for it's family is loaded.
-If driver is loaded w1 core creates new w1_slave object and registers it
-in the system(creates some generic sysfs files(struct w1_family_ops in
-w1_family.h), notifies any registered listener and so on...).
-It is device driver's business to provide any communication method
-upstream.
-For example w1_therm driver(ds18?20 thermal sensor family driver)
-provides temperature reading function which is bound to ->rbin() method
-of the above w1_family_ops structure.
-w1_smem - driver for simple 64bit memory cell provides ID reading
-method.
+The 1-wire (w1) subsystem
+------------------------------------------------------------------
+The 1-wire bus is a simple master-slave bus that communicates via a single
+signal wire (plus ground, so two wires).
+
+Devices communicate on the bus by pulling the signal to ground via an open
+drain output and by sampling the logic level of the signal line.
+
+The w1 subsystem provides the framework for managing w1 masters and
+communication with slaves.
+
+All w1 slave devices must be connected to a w1 bus master device.
+
+Example w1 master devices:
+    DS9490 usb device
+    W1-over-GPIO
+    DS2482 (i2c to w1 bridge)
+    Emulated devices, such as a RS232 converter, parallel port adapter, etc
+
+
+What does the w1 subsystem do?
+------------------------------------------------------------------
+When a w1 master driver registers with the w1 subsystem, the following occurs:
+
+ - sysfs entries for that w1 master are created
+ - the w1 bus is periodically searched for new slave devices
+
+When a device is found on the bus, w1 core checks if driver for it's family is
+loaded. If so, the family driver is attached to the slave.
+If there is no driver for the family, a simple sysfs entry is created
+for the slave device.
+
+
+W1 device families
+------------------------------------------------------------------
+Slave devices are handled by a driver written for a family of w1 devices.
+
+A family driver populates a struct w1_family_ops (see w1_family.h) and
+registers with the w1 subsystem.
+
+Current family drivers:
+w1_therm - (ds18?20 thermal sensor family driver)
+    provides temperature reading function which is bound to ->rbin() method
+    of the above w1_family_ops structure.
+
+w1_smem - driver for simple 64bit memory cell provides ID reading method.
 
 You can call above methods by reading appropriate sysfs files.
+
+
+What does a w1 master driver need to implement?
+------------------------------------------------------------------
+
+The driver for w1 bus master must provide at minimum two functions.
+
+Emulated devices must provide the ability to set the output signal level
+(write_bit) and sample the signal level (read_bit).
+
+Devices that support the 1-wire natively must provide the ability to write and
+sample a bit (touch_bit) and reset the bus (reset_bus).
+
+Most hardware provides higher-level functions that offload w1 handling.
+See struct w1_bus_master definition in w1.h for details.
+
+
+w1 master sysfs interface
+------------------------------------------------------------------
+<xx-xxxxxxxxxxxxx> - a directory for a found device. The format is family-serial
+bus                - (standard) symlink to the w1 bus
+driver             - (standard) symlink to the w1 driver
+w1_master_attempts - the number of times a search was attempted
+w1_master_max_slave_count
+                   - the maximum slaves that may be attached to a master
+w1_master_name     - the name of the device (w1_bus_masterX)
+w1_master_search   - the number of searches left to do, -1=continual (default)
+w1_master_slave_count
+                   - the number of slaves found
+w1_master_slaves   - the names of the slaves, one per line
+w1_master_timeout  - the delay in seconds between searches
+
+If you have a w1 bus that never changes (you don't add or remove devices),
+you can set w1_master_search to a positive value to disable searches.
+
+
+w1 slave sysfs interface
+------------------------------------------------------------------
+bus                - (standard) symlink to the w1 bus
+driver             - (standard) symlink to the w1 driver
+name               - the device name, usually the same as the directory name
+w1_slave           - (optional) a binary file whose meaning depends on the
+                     family driver
+
index e3f0f3f157c9f664fe7ca27f6c9d9788abe4f6bd..4d44824884efc432892ddffbc48216f790e13a62 100644 (file)
@@ -194,7 +194,7 @@ S:  Maintained
 ADM1025 HARDWARE MONITOR DRIVER
 P:     Jean Delvare
 M:     khali@linux-fr.org
-L:     sensors@stimpy.netroedge.com
+L:     lm-sensors@lm-sensors.org
 S:     Maintained
 
 ADT746X FAN DRIVER
@@ -242,7 +242,7 @@ S:  Maintained
 ALI1563 I2C DRIVER
 P:     Rudolf Marek
 M:     r.marek@sh.cvut.cz
-L:     sensors@stimpy.netroedge.com
+L:     lm-sensors@lm-sensors.org
 S:     Maintained
 
 ALPHA PORT
@@ -265,6 +265,11 @@ P: Arnaldo Carvalho de Melo
 M:     acme@conectiva.com.br
 S:     Maintained
 
+ARC FRAMEBUFFER DRIVER
+P:     Jaya Kumar
+M:     jayalk@intworks.biz
+S:     Maintained
+
 ARM26 ARCHITECTURE
 P:     Ian Molton
 M:     spyro@f2s.com
@@ -997,7 +1002,7 @@ P: Greg Kroah-Hartman
 M:     greg@kroah.com
 P:     Jean Delvare
 M:     khali@linux-fr.org
-L:     sensors@stimpy.netroedge.com
+L:     lm-sensors@lm-sensors.org
 W:     http://www.lm-sensors.nu/
 S:     Maintained
 
@@ -1425,13 +1430,13 @@ S:      Supported
 LM83 HARDWARE MONITOR DRIVER
 P:     Jean Delvare
 M:     khali@linux-fr.org
-L:     sensors@stimpy.netroedge.com
+L:     lm-sensors@lm-sensors.org
 S:     Maintained
 
 LM90 HARDWARE MONITOR DRIVER
 P:     Jean Delvare
 M:     khali@linux-fr.org
-L:     sensors@stimpy.netroedge.com
+L:     lm-sensors@lm-sensors.org
 S:     Maintained
 
 LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks)
@@ -2070,7 +2075,7 @@ S:        Maintained
 SMSC47M1 HARDWARE MONITOR DRIVER
 P:     Jean Delvare
 M:     khali@linux-fr.org
-L:     sensors@stimpy.netroedge.com
+L:     lm-sensors@lm-sensors.org
 S:     Odd Fixes
 
 SMB FILESYSTEM
@@ -2609,7 +2614,7 @@ S:        Orphan
 W1 DALLAS'S 1-WIRE BUS
 P:     Evgeniy Polyakov
 M:     johnpol@2ka.mipt.ru
-L:     sensors@stimpy.netroedge.com
+L:     lm-sensors@lm-sensors.org
 S:     Maintained
 
 W83L51xD SD/MMC CARD INTERFACE DRIVER
@@ -2622,7 +2627,7 @@ S:        Maintained
 W83L785TS HARDWARE MONITOR DRIVER
 P:     Jean Delvare
 M:     khali@linux-fr.org
-L:     sensors@stimpy.netroedge.com
+L:     lm-sensors@lm-sensors.org
 S:     Odd Fixes
 
 WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
index 32c4b0e35b37768f7d75fa01194f1f9c3d0baac8..3de7f84b53c25e3cdd5f8d44da252336fb55645a 100644 (file)
@@ -73,7 +73,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
-       start_addr = addr = mm->free_area_cache;
+       if (len > mm->cached_hole_size) {
+               start_addr = addr = mm->free_area_cache;
+       } else {
+               start_addr = addr = TASK_UNMAPPED_BASE;
+               mm->cached_hole_size = 0;
+       }
 
 full_search:
        if (do_align)
@@ -90,6 +95,7 @@ full_search:
                         */
                        if (start_addr != TASK_UNMAPPED_BASE) {
                                start_addr = addr = TASK_UNMAPPED_BASE;
+                               mm->cached_hole_size = 0;
                                goto full_search;
                        }
                        return -ENOMEM;
@@ -101,6 +107,8 @@ full_search:
                        mm->free_area_cache = addr + len;
                        return addr;
                }
+               if (addr + mm->cached_hole_size < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
                addr = vma->vm_end;
                if (do_align)
                        addr = COLOUR_ALIGN(addr, pgoff);
index 41958f57c83864c4a8f62becaac334ea1173833e..79433159b5f05a7bbb3022c5a89b6555247f3090 100644 (file)
@@ -169,7 +169,6 @@ void __init mem_init(void)
                struct page *page = &mem_map[pfn];
 
                ClearPageReserved(page);
-               set_bit(PG_highmem, &page->flags);
                set_page_count(page, 1);
                __free_page(page);
                totalram_pages++;
index aa7064a75ee64d9c7b4feeb13514a224156cf3a3..43cd6220ee4905c2375cfb1cece6767c0d8fa28f 100644 (file)
@@ -48,7 +48,7 @@ cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
 $(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
                              $(obj)/vmlinux.bin $(obj)/tools/build FORCE
        $(call if_changed,image)
-       @echo 'Kernel: $@ is ready'
+       @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
 $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
index 6cd1ed311f02b87aeccce917954624f7e28dd675..d408afaf6495918b3591bbcda5dbcd5a95a34a36 100644 (file)
@@ -251,7 +251,7 @@ ENTRY(sys_call_table)
        .long sys_io_submit
        .long sys_io_cancel
        .long sys_fadvise64     /* 250 */
-       .long sys_ni_syscall
+       .long sys_set_zone_reclaim
        .long sys_exit_group
        .long sys_lookup_dcookie
        .long sys_epoll_create
index 00c63419c06f80f0af9ce17f4b7f78e18dd25df2..83c579e82a8137f24a6952efc461b4e434eb6158 100644 (file)
@@ -306,7 +306,7 @@ void die(const char * str, struct pt_regs * regs, long err)
        };
        static int die_counter;
 
-       if (die.lock_owner != _smp_processor_id()) {
+       if (die.lock_owner != raw_smp_processor_id()) {
                console_verbose();
                spin_lock_irq(&die.lock);
                die.lock_owner = smp_processor_id();
index 080639f262b1364479476e5f88065080388c2fa2..eb0cdfe9280fe11414239a640f9557279cfa2b23 100644 (file)
@@ -34,7 +34,7 @@ inline void __const_udelay(unsigned long xloops)
        xloops *= 4;
        __asm__("mull %0"
                :"=d" (xloops), "=&a" (d0)
-               :"1" (xloops),"0" (cpu_data[_smp_processor_id()].loops_per_jiffy * (HZ/4)));
+               :"1" (xloops),"0" (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
         __delay(++xloops);
 }
 
index 171fc925e1e4e7c699c6222b229914b320c987c3..3b099f32b9487a054db420509ad25591ea0d06eb 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -30,7 +30,7 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        return (pte_t *) pmd;
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -42,21 +42,6 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        return (pte_t *) pmd;
 }
 
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, struct page *page, pte_t * page_table, int write_access)
-{
-       pte_t entry;
-
-       add_mm_counter(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);
-       mk_pte_huge(entry);
-       set_pte(page_table, entry);
-}
-
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -69,77 +54,6 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
        return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-                       struct vm_area_struct *vma)
-{
-       pte_t *src_pte, *dst_pte, entry;
-       struct page *ptepage;
-       unsigned long addr = vma->vm_start;
-       unsigned long end = vma->vm_end;
-
-       while (addr < end) {
-               dst_pte = huge_pte_alloc(dst, addr);
-               if (!dst_pte)
-                       goto nomem;
-               src_pte = huge_pte_offset(src, addr);
-               entry = *src_pte;
-               ptepage = pte_page(entry);
-               get_page(ptepage);
-               set_pte(dst_pte, entry);
-               add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-               addr += HPAGE_SIZE;
-       }
-       return 0;
-
-nomem:
-       return -ENOMEM;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-                   struct page **pages, struct vm_area_struct **vmas,
-                   unsigned long *position, int *length, int i)
-{
-       unsigned long vpfn, vaddr = *position;
-       int remainder = *length;
-
-       WARN_ON(!is_vm_hugetlb_page(vma));
-
-       vpfn = vaddr/PAGE_SIZE;
-       while (vaddr < vma->vm_end && remainder) {
-
-               if (pages) {
-                       pte_t *pte;
-                       struct page *page;
-
-                       pte = huge_pte_offset(mm, vaddr);
-
-                       /* hugetlb should be locked, and hence, prefaulted */
-                       WARN_ON(!pte || pte_none(*pte));
-
-                       page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
-
-                       WARN_ON(!PageCompound(page));
-
-                       get_page(page);
-                       pages[i] = page;
-               }
-
-               if (vmas)
-                       vmas[i] = vma;
-
-               vaddr += PAGE_SIZE;
-               ++vpfn;
-               --remainder;
-               ++i;
-       }
-
-       *length = remainder;
-       *position = vaddr;
-
-       return i;
-}
-
 #if 0  /* This is just for testing */
 struct page *
 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
@@ -204,83 +118,15 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
 }
 #endif
 
-void unmap_hugepage_range(struct vm_area_struct *vma,
-               unsigned long start, unsigned long end)
+void hugetlb_clean_stale_pgtable(pte_t *pte)
 {
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long address;
-       pte_t pte, *ptep;
+       pmd_t *pmd = (pmd_t *) pte;
        struct page *page;
 
-       BUG_ON(start & (HPAGE_SIZE - 1));
-       BUG_ON(end & (HPAGE_SIZE - 1));
-
-       for (address = start; address < end; address += HPAGE_SIZE) {
-               ptep = huge_pte_offset(mm, address);
-               if (!ptep)
-                       continue;
-               pte = ptep_get_and_clear(mm, address, ptep);
-               if (pte_none(pte))
-                       continue;
-               page = pte_page(pte);
-               put_page(page);
-       }
-       add_mm_counter(mm ,rss, -((end - start) >> PAGE_SHIFT));
-       flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-       struct mm_struct *mm = current->mm;
-       unsigned long addr;
-       int ret = 0;
-
-       BUG_ON(vma->vm_start & ~HPAGE_MASK);
-       BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-       spin_lock(&mm->page_table_lock);
-       for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-               unsigned long idx;
-               pte_t *pte = huge_pte_alloc(mm, addr);
-               struct page *page;
-
-               if (!pte) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               if (!pte_none(*pte))
-                       continue;
-
-               idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-                       + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-               page = find_get_page(mapping, idx);
-               if (!page) {
-                       /* charge the fs quota first */
-                       if (hugetlb_get_quota(mapping)) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       page = alloc_huge_page();
-                       if (!page) {
-                               hugetlb_put_quota(mapping);
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-                       if (! ret) {
-                               unlock_page(page);
-                       } else {
-                               hugetlb_put_quota(mapping);
-                               free_huge_page(page);
-                               goto out;
-                       }
-               }
-               set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
-       }
-out:
-       spin_unlock(&mm->page_table_lock);
-       return ret;
+       page = pmd_page(*pmd);
+       pmd_clear(pmd);
+       dec_page_state(nr_page_table_pages);
+       page_cache_release(page);
 }
 
 /* x86_64 also uses this file */
@@ -294,7 +140,12 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
        struct vm_area_struct *vma;
        unsigned long start_addr;
 
-       start_addr = mm->free_area_cache;
+       if (len > mm->cached_hole_size) {
+               start_addr = mm->free_area_cache;
+       } else {
+               start_addr = TASK_UNMAPPED_BASE;
+               mm->cached_hole_size = 0;
+       }
 
 full_search:
        addr = ALIGN(start_addr, HPAGE_SIZE);
@@ -308,6 +159,7 @@ full_search:
                         */
                        if (start_addr != TASK_UNMAPPED_BASE) {
                                start_addr = TASK_UNMAPPED_BASE;
+                               mm->cached_hole_size = 0;
                                goto full_search;
                        }
                        return -ENOMEM;
@@ -316,6 +168,8 @@ full_search:
                        mm->free_area_cache = addr + len;
                        return addr;
                }
+               if (addr + mm->cached_hole_size < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
                addr = ALIGN(vma->vm_end, HPAGE_SIZE);
        }
 }
@@ -327,12 +181,17 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma, *prev_vma;
        unsigned long base = mm->mmap_base, addr = addr0;
+       unsigned long largest_hole = mm->cached_hole_size;
        int first_time = 1;
 
        /* don't allow allocations above current base */
        if (mm->free_area_cache > base)
                mm->free_area_cache = base;
 
+       if (len <= largest_hole) {
+               largest_hole = 0;
+               mm->free_area_cache  = base;
+       }
 try_again:
        /* make sure it can fit in the remaining address space */
        if (mm->free_area_cache < len)
@@ -353,13 +212,21 @@ try_again:
                 * vma->vm_start, use it:
                 */
                if (addr + len <= vma->vm_start &&
-                               (!prev_vma || (addr >= prev_vma->vm_end)))
+                           (!prev_vma || (addr >= prev_vma->vm_end))) {
                        /* remember the address as a hint for next time */
-                       return (mm->free_area_cache = addr);
-               else
+                       mm->cached_hole_size = largest_hole;
+                       return (mm->free_area_cache = addr);
+               } else {
                        /* pull free_area_cache down to the first hole */
-                       if (mm->free_area_cache == vma->vm_end)
+                       if (mm->free_area_cache == vma->vm_end) {
                                mm->free_area_cache = vma->vm_start;
+                               mm->cached_hole_size = largest_hole;
+                       }
+               }
+
+               /* remember the largest hole we saw so far */
+               if (addr + largest_hole < vma->vm_start)
+                       largest_hole = vma->vm_start - addr;
 
                /* try just below the current vma->vm_start */
                addr = (vma->vm_start - len) & HPAGE_MASK;
@@ -372,6 +239,7 @@ fail:
         */
        if (first_time) {
                mm->free_area_cache = base;
+               largest_hole = 0;
                first_time = 0;
                goto try_again;
        }
@@ -382,6 +250,7 @@ fail:
         * allocations.
         */
        mm->free_area_cache = TASK_UNMAPPED_BASE;
+       mm->cached_hole_size = ~0UL;
        addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
                        len, pgoff, flags);
 
@@ -389,6 +258,7 @@ fail:
         * Restore the topdown base:
         */
        mm->free_area_cache = base;
+       mm->cached_hole_size = ~0UL;
 
        return addr;
 }
index 7a7ea3737265284eceafdcdc82000f3c87d06690..8766c771bb45371ab1f67e94112616ba86521a9e 100644 (file)
@@ -269,7 +269,6 @@ void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
 {
        if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
                ClearPageReserved(page);
-               set_bit(PG_highmem, &page->flags);
                set_page_count(page, 1);
                __free_page(page);
                totalhigh_pages++;
index 992bcfff7913ceee485011a52dd362b9d68d346e..ce4dfa8b834dfec30367effa7b315a8be514f4e5 100644 (file)
@@ -50,6 +50,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
        bool
        default y
 
+config IA64_UNCACHED_ALLOCATOR
+       bool
+       select GENERIC_ALLOCATOR
+
 choice
        prompt "System type"
        default IA64_GENERIC
@@ -223,7 +227,7 @@ config IA64_SGI_SN_SIM
 
 config IA64_SGI_SN_XP
        tristate "Support communication between SGI SSIs"
-       depends on MSPEC
+       select IA64_UNCACHED_ALLOCATOR
        help
          An SGI machine can be divided into multiple Single System
          Images which act independently of each other and have
index 6ff7107fee4d6ecca4d5f32ae3cf9018abb5057b..a01bb02d074df7cd4ac60efea1985990d739747a 100644 (file)
@@ -588,6 +588,7 @@ CONFIG_SGI_MBCS=m
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_SERIAL_SGI_IOC4=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -787,6 +788,11 @@ CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_IPOIB=m
 # CONFIG_INFINIBAND_IPOIB_DEBUG is not set
 
+#
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+
 #
 # File systems
 #
index 2aea0f9e6e1dbdaae7b6ef02785c480ca2ba02b2..7be8096e056159df6ca56a1ff20da01438210c45 100644 (file)
@@ -657,6 +657,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_SERIAL_SGI_IOC4=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -975,6 +976,11 @@ CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_IPOIB=m
 # CONFIG_INFINIBAND_IPOIB_DEBUG is not set
 
+#
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+
 #
 # File systems
 #
index c1a02bbc252c7b0409d339460b2c25ea34dfcaee..4c73d8ba2e3df14b91db0eab8806c57408d4b4de 100644 (file)
@@ -20,6 +20,7 @@ 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
+obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)  += uncached.o
 mca_recovery-y                 += mca_drv.o mca_drv_asm.o
 
 # The gate DSO image is built using a special linker script.
index 4a3b1aac43e737e4082d36eb5eee0846628fc73a..179f230816edf52dd57a990a188465455d1f73fa 100644 (file)
@@ -409,6 +409,38 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
        }
 }
 
+/*
+ * Walk the EFI memory map to pull out leftover pages in the lower
+ * memory regions which do not end up in the regular memory map and
+ * stick them into the uncached allocator
+ *
+ * The regular walk function is significantly more complex than the
+ * uncached walk which means it really doesn't make sense to try and
+ * marge the two.
+ */
+void __init
+efi_memmap_walk_uc (efi_freemem_callback_t callback)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size, start, end;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+               if (md->attribute == EFI_MEMORY_UC) {
+                       start = PAGE_ALIGN(md->phys_addr);
+                       end = PAGE_ALIGN((md->phys_addr+(md->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK);
+                       if ((*callback)(start, end, NULL) < 0)
+                               return;
+               }
+       }
+}
+
+
 /*
  * Look for the PAL_CODE region reported by EFI and maps it using an
  * ITR to enable safe PAL calls in virtual mode.  See IA-64 Processor
index d99316c9be28977f4a814970d42f629c958cd54b..b1d5d3d5276c8424a41f96f2c1009f7d0d31cfab 100644 (file)
@@ -1579,7 +1579,7 @@ sys_call_table:
        data8 sys_keyctl
        data8 sys_ni_syscall
        data8 sys_ni_syscall                    // 1275
-       data8 sys_ni_syscall
+       data8 sys_set_zone_reclaim
        data8 sys_ni_syscall
        data8 sys_ni_syscall
        data8 sys_ni_syscall
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
new file mode 100644 (file)
index 0000000..490dfc9
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2001-2005 Silicon Graphics, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * A simple uncached page allocator using the generic allocator. This
+ * allocator first utilizes the spare (spill) pages found in the EFI
+ * memmap and will then start converting cached pages to uncached ones
+ * at a granule at a time. Node awareness is implemented by having a
+ * pool of pages per node.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/efi.h>
+#include <linux/genalloc.h>
+#include <asm/page.h>
+#include <asm/pal.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/atomic.h>
+#include <asm/tlbflush.h>
+#include <asm/sn/arch.h>
+
+#define DEBUG  0
+
+#if DEBUG
+#define dprintk                        printk
+#else
+#define dprintk(x...)          do { } while (0)
+#endif
+
+void __init efi_memmap_walk_uc (efi_freemem_callback_t callback);
+
+#define MAX_UNCACHED_GRANULES  5
+static int allocated_granules;
+
+struct gen_pool *uncached_pool[MAX_NUMNODES];
+
+
+static void uncached_ipi_visibility(void *data)
+{
+       int status;
+
+       status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
+       if ((status != PAL_VISIBILITY_OK) &&
+           (status != PAL_VISIBILITY_OK_REMOTE_NEEDED))
+               printk(KERN_DEBUG "pal_prefetch_visibility() returns %i on "
+                      "CPU %i\n", status, get_cpu());
+}
+
+
+static void uncached_ipi_mc_drain(void *data)
+{
+       int status;
+       status = ia64_pal_mc_drain();
+       if (status)
+               printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on "
+                      "CPU %i\n", status, get_cpu());
+}
+
+
+static unsigned long
+uncached_get_new_chunk(struct gen_pool *poolp)
+{
+       struct page *page;
+       void *tmp;
+       int status, i;
+       unsigned long addr, node;
+
+       if (allocated_granules >= MAX_UNCACHED_GRANULES)
+               return 0;
+
+       node = poolp->private;
+       page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO,
+                               IA64_GRANULE_SHIFT-PAGE_SHIFT);
+
+       dprintk(KERN_INFO "get_new_chunk page %p, addr %lx\n",
+               page, (unsigned long)(page-vmem_map) << PAGE_SHIFT);
+
+       /*
+        * Do magic if no mem on local node! XXX
+        */
+       if (!page)
+               return 0;
+       tmp = page_address(page);
+
+       /*
+        * There's a small race here where it's possible for someone to
+        * access the page through /dev/mem halfway through the conversion
+        * to uncached - not sure it's really worth bothering about
+        */
+       for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
+               SetPageUncached(&page[i]);
+
+       flush_tlb_kernel_range(tmp, tmp + IA64_GRANULE_SIZE);
+
+       status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
+
+       dprintk(KERN_INFO "pal_prefetch_visibility() returns %i on cpu %i\n",
+               status, get_cpu());
+
+       if (!status) {
+               status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1);
+               if (status)
+                       printk(KERN_WARNING "smp_call_function failed for "
+                              "uncached_ipi_visibility! (%i)\n", status);
+       }
+
+       if (ia64_platform_is("sn2"))
+               sn_flush_all_caches((unsigned long)tmp, IA64_GRANULE_SIZE);
+       else
+               flush_icache_range((unsigned long)tmp,
+                                  (unsigned long)tmp+IA64_GRANULE_SIZE);
+
+       ia64_pal_mc_drain();
+       status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1);
+       if (status)
+               printk(KERN_WARNING "smp_call_function failed for "
+                      "uncached_ipi_mc_drain! (%i)\n", status);
+
+       addr = (unsigned long)tmp - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
+
+       allocated_granules++;
+       return addr;
+}
+
+
+/*
+ * uncached_alloc_page
+ *
+ * Allocate 1 uncached page. Allocates on the requested node. If no
+ * uncached pages are available on the requested node, roundrobin starting
+ * with higher nodes.
+ */
+unsigned long
+uncached_alloc_page(int nid)
+{
+       unsigned long maddr;
+
+       maddr = gen_pool_alloc(uncached_pool[nid], PAGE_SIZE);
+
+       dprintk(KERN_DEBUG "uncached_alloc_page returns %lx on node %i\n",
+               maddr, nid);
+
+       /*
+        * If no memory is availble on our local node, try the
+        * remaining nodes in the system.
+        */
+       if (!maddr) {
+               int i;
+
+               for (i = MAX_NUMNODES - 1; i >= 0; i--) {
+                       if (i == nid || !node_online(i))
+                               continue;
+                       maddr = gen_pool_alloc(uncached_pool[i], PAGE_SIZE);
+                       dprintk(KERN_DEBUG "uncached_alloc_page alternate search "
+                               "returns %lx on node %i\n", maddr, i);
+                       if (maddr) {
+                               break;
+                       }
+               }
+       }
+
+       return maddr;
+}
+EXPORT_SYMBOL(uncached_alloc_page);
+
+
+/*
+ * uncached_free_page
+ *
+ * Free a single uncached page.
+ */
+void
+uncached_free_page(unsigned long maddr)
+{
+       int node;
+
+       node = nasid_to_cnodeid(NASID_GET(maddr));
+
+       dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node);
+
+       if ((maddr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
+               panic("uncached_free_page invalid address %lx\n", maddr);
+
+       gen_pool_free(uncached_pool[node], maddr, PAGE_SIZE);
+}
+EXPORT_SYMBOL(uncached_free_page);
+
+
+/*
+ * uncached_build_memmap,
+ *
+ * Called at boot time to build a map of pages that can be used for
+ * memory special operations.
+ */
+static int __init
+uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
+{
+       long length;
+       unsigned long vstart, vend;
+       int node;
+
+       length = end - start;
+       vstart = start + __IA64_UNCACHED_OFFSET;
+       vend = end + __IA64_UNCACHED_OFFSET;
+
+       dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
+
+       memset((char *)vstart, 0, length);
+
+       node = nasid_to_cnodeid(NASID_GET(start));
+
+       for (; vstart < vend ; vstart += PAGE_SIZE) {
+               dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart);
+               gen_pool_free(uncached_pool[node], vstart, PAGE_SIZE);
+       }
+
+       return 0;
+}
+
+
+static int __init uncached_init(void) {
+       int i;
+
+       for (i = 0; i < MAX_NUMNODES; i++) {
+               if (!node_online(i))
+                       continue;
+               uncached_pool[i] = gen_pool_create(0, IA64_GRANULE_SHIFT,
+                                                  &uncached_get_new_chunk, i);
+       }
+
+       efi_memmap_walk_uc(uncached_build_memmap);
+
+       return 0;
+}
+
+__initcall(uncached_init);
index df08ae7634b61d2efadf065e246c4bfb7f342b2c..e0a776a3044c89f5614de6e2284c6a338cda6170 100644 (file)
@@ -24,7 +24,7 @@
 
 unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT;
 
-static pte_t *
+pte_t *
 huge_pte_alloc (struct mm_struct *mm, unsigned long addr)
 {
        unsigned long taddr = htlbpage_to_page(addr);
@@ -43,7 +43,7 @@ huge_pte_alloc (struct mm_struct *mm, unsigned long addr)
        return pte;
 }
 
-static pte_t *
+pte_t *
 huge_pte_offset (struct mm_struct *mm, unsigned long addr)
 {
        unsigned long taddr = htlbpage_to_page(addr);
@@ -67,23 +67,6 @@ huge_pte_offset (struct mm_struct *mm, unsigned long addr)
 
 #define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; }
 
-static void
-set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma,
-             struct page *page, pte_t * page_table, int write_access)
-{
-       pte_t entry;
-
-       add_mm_counter(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);
-       mk_pte_huge(entry);
-       set_pte(page_table, entry);
-       return;
-}
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -99,68 +82,6 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
        return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-                       struct vm_area_struct *vma)
-{
-       pte_t *src_pte, *dst_pte, entry;
-       struct page *ptepage;
-       unsigned long addr = vma->vm_start;
-       unsigned long end = vma->vm_end;
-
-       while (addr < end) {
-               dst_pte = huge_pte_alloc(dst, addr);
-               if (!dst_pte)
-                       goto nomem;
-               src_pte = huge_pte_offset(src, addr);
-               entry = *src_pte;
-               ptepage = pte_page(entry);
-               get_page(ptepage);
-               set_pte(dst_pte, entry);
-               add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-               addr += HPAGE_SIZE;
-       }
-       return 0;
-nomem:
-       return -ENOMEM;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-                   struct page **pages, struct vm_area_struct **vmas,
-                   unsigned long *st, int *length, int i)
-{
-       pte_t *ptep, pte;
-       unsigned long start = *st;
-       unsigned long pstart;
-       int len = *length;
-       struct page *page;
-
-       do {
-               pstart = start & HPAGE_MASK;
-               ptep = huge_pte_offset(mm, start);
-               pte = *ptep;
-
-back1:
-               page = pte_page(pte);
-               if (pages) {
-                       page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT);
-                       get_page(page);
-                       pages[i] = page;
-               }
-               if (vmas)
-                       vmas[i] = vma;
-               i++;
-               len--;
-               start += PAGE_SIZE;
-               if (((start & HPAGE_MASK) == pstart) && len &&
-                               (start < vma->vm_end))
-                       goto back1;
-       } while (len && start < vma->vm_end);
-       *length = len;
-       *st = start;
-       return i;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm, unsigned long addr, int write)
 {
        struct page *page;
@@ -212,81 +133,6 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb,
        free_pgd_range(tlb, addr, end, floor, ceiling);
 }
 
-void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
-{
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long address;
-       pte_t *pte;
-       struct page *page;
-
-       BUG_ON(start & (HPAGE_SIZE - 1));
-       BUG_ON(end & (HPAGE_SIZE - 1));
-
-       for (address = start; address < end; address += HPAGE_SIZE) {
-               pte = huge_pte_offset(mm, address);
-               if (pte_none(*pte))
-                       continue;
-               page = pte_page(*pte);
-               put_page(page);
-               pte_clear(mm, address, pte);
-       }
-       add_mm_counter(mm, rss, - ((end - start) >> PAGE_SHIFT));
-       flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-       struct mm_struct *mm = current->mm;
-       unsigned long addr;
-       int ret = 0;
-
-       BUG_ON(vma->vm_start & ~HPAGE_MASK);
-       BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-       spin_lock(&mm->page_table_lock);
-       for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-               unsigned long idx;
-               pte_t *pte = huge_pte_alloc(mm, addr);
-               struct page *page;
-
-               if (!pte) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               if (!pte_none(*pte))
-                       continue;
-
-               idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-                       + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-               page = find_get_page(mapping, idx);
-               if (!page) {
-                       /* charge the fs quota first */
-                       if (hugetlb_get_quota(mapping)) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       page = alloc_huge_page();
-                       if (!page) {
-                               hugetlb_put_quota(mapping);
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-                       if (! ret) {
-                               unlock_page(page);
-                       } else {
-                               hugetlb_put_quota(mapping);
-                               page_cache_release(page);
-                               goto out;
-                       }
-               }
-               set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
-       }
-out:
-       spin_unlock(&mm->page_table_lock);
-       return ret;
-}
-
 unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
                unsigned long pgoff, unsigned long flags)
 {
index 2c3c4a8af553d181e5e772242e6df9442842f53a..cd7ed73f0e7ab73a87b37ea4d567810b511ecee9 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/cache.h>
 #include <linux/mmzone.h>
 #include <linux/nodemask.h>
+#include <asm/uncached.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
@@ -183,7 +184,7 @@ xpc_rsvd_page_init(void)
         * memory protections are never restricted.
         */
        if ((amos_page = xpc_vars->amos_page) == NULL) {
-               amos_page = (AMO_t *) mspec_kalloc_page(0);
+               amos_page = (AMO_t *) TO_AMO(uncached_alloc_page(0));
                if (amos_page == NULL) {
                        dev_err(xpc_part, "can't allocate page of AMOs\n");
                        return NULL;
@@ -200,7 +201,8 @@ xpc_rsvd_page_init(void)
                        if (ret != 0) {
                                dev_err(xpc_part, "can't change memory "
                                        "protections\n");
-                               mspec_kfree_page((unsigned long) amos_page);
+                               uncached_free_page(__IA64_UNCACHED_OFFSET |
+                                                  TO_PHYS((u64) amos_page));
                                return NULL;
                        }
                }
index 0d90ea58a0cb91223b611096ba99cfd444241511..64c133344afef7e90d6aefbdf6856f18c0760e36 100644 (file)
@@ -78,6 +78,9 @@ config PLAT_OAKS32R
 config PLAT_MAPPI2
        bool "Mappi-II(M3A-ZA36/M3A-ZA52)"
 
+config PLAT_MAPPI3
+       bool "Mappi-III(M3A-2170)"
+
 endchoice
 
 choice
@@ -134,6 +137,7 @@ config BUS_CLOCK
        int "Bus Clock [Hz] (integer)"
        default "70000000" if PLAT_MAPPI
        default "25000000" if PLAT_USRV
+       default "50000000" if PLAT_MAPPI3
        default "50000000" if PLAT_M32700UT
        default "50000000" if PLAT_OPSPUT
        default "33333333" if PLAT_OAKS32R
@@ -149,7 +153,7 @@ config CPU_LITTLE_ENDIAN
 
 config MEMORY_START
        hex "Physical memory start address (hex)"
-       default "08000000" if PLAT_MAPPI || PLAT_MAPPI2
+       default "08000000" if PLAT_MAPPI || PLAT_MAPPI2 || PLAT_MAPPI3
        default "08000000" if PLAT_USRV
        default "08000000" if PLAT_M32700UT
        default "08000000" if PLAT_OPSPUT
@@ -157,6 +161,7 @@ config MEMORY_START
 
 config MEMORY_SIZE
        hex "Physical memory size (hex)"
+       default "08000000" if PLAT_MAPPI3
        default "04000000" if PLAT_MAPPI || PLAT_MAPPI2
        default "02000000" if PLAT_USRV
        default "01000000" if PLAT_M32700UT
index bad5475eff90c17320b27aaad83f17dd3389ff81..8f9a57271f8345cfd61e43ec5968bdd086f6600a 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/config.h>
+#include <asm/processor.h>
 
 static void putc(char c);
 
@@ -38,16 +39,17 @@ static int puts(const char *s)
 
 static void putc(char c)
 {
-
-       while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+       while ((*BOOT_SIO0STS & 0x3) != 0x3)
+               cpu_relax();
        if (c == '\n') {
                *BOOT_SIO0TXB = '\r';
-               while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+               while ((*BOOT_SIO0STS & 0x3) != 0x3)
+                       cpu_relax();
        }
        *BOOT_SIO0TXB = c;
 }
-#else /* defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) */
-#ifdef CONFIG_MMU
+#else /* !(CONFIG_PLAT_M32700UT_Alpha) && !(CONFIG_PLAT_M32700UT) */
+#if defined(CONFIG_PLAT_MAPPI2)
 #define SIO0STS        (volatile unsigned short *)(0xa0efd000 + 14)
 #define SIO0TXB        (volatile unsigned short *)(0xa0efd000 + 30)
 #else
@@ -57,11 +59,12 @@ static void putc(char c)
 
 static void putc(char c)
 {
-
-       while ((*SIO0STS & 0x1) == 0) ;
+       while ((*SIO0STS & 0x1) == 0)
+               cpu_relax();
        if (c == '\n') {
                *SIO0TXB = '\r';
-               while ((*SIO0STS & 0x1) == 0) ;
+               while ((*SIO0STS & 0x1) == 0)
+                       cpu_relax();
        }
        *SIO0TXB = c;
 }
index 417c95ba87e96dd91c9393ed03afd1279d765564..853093093168e40bede4a8df4baa86dc0931af2f 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:44 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:20:11 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,15 @@ 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=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +69,7 @@ CONFIG_PLAT_M32700UT=y
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -268,7 +273,6 @@ CONFIG_NET=y
 #
 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
@@ -392,18 +396,6 @@ CONFIG_INPUT=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_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -413,6 +405,17 @@ CONFIG_SERIO_SERPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -464,6 +467,10 @@ CONFIG_DS1302=y
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -508,8 +515,14 @@ CONFIG_VIDEO_M32R_AR_M64278=y
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -542,10 +555,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
 # 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
 #
@@ -719,8 +728,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
index cfd690bf6d8abc25b24b5acae048d07540339463..6c6b6c37663816f3e59ac520be02527252f731a3 100644 (file)
@@ -10,6 +10,7 @@ obj-y := process.o entry.o traps.o align.o irq.o setup.o time.o \
 obj-$(CONFIG_SMP)              += smp.o smpboot.o
 obj-$(CONFIG_PLAT_MAPPI)       += setup_mappi.o io_mappi.o
 obj-$(CONFIG_PLAT_MAPPI2)      += setup_mappi2.o io_mappi2.o
+obj-$(CONFIG_PLAT_MAPPI3)      += setup_mappi3.o io_mappi3.o
 obj-$(CONFIG_PLAT_USRV)                += setup_usrv.o io_usrv.o
 obj-$(CONFIG_PLAT_M32700UT)    += setup_m32700ut.o io_m32700ut.o
 obj-$(CONFIG_PLAT_OPSPUT)      += setup_opsput.o io_opsput.o
@@ -17,4 +18,3 @@ obj-$(CONFIG_MODULES)         += module.o
 obj-$(CONFIG_PLAT_OAKS32R)     += setup_oaks32r.o io_oaks32r.o
 
 EXTRA_AFLAGS   := -traditional
-
index 371ba904e96860a5f62099020459e639c8ca4c6e..e545b065f7e98e1f80f2a8f876b751aedd999ccb 100644 (file)
@@ -3,8 +3,8 @@
  *
  *  Typical I/O routines for M32700UT board.
  *
- *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Takeo Takahashi
  *
  *  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
@@ -172,64 +172,21 @@ unsigned long _inl(unsigned long port)
 
 unsigned char _inb_p(unsigned long port)
 {
-       unsigned char  v;
-
-       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;
-       } else
-#endif
-               v = *(volatile unsigned char *)PORT2ADDR(port);
-
+       unsigned char v = _inb(port);
        delay();
        return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-       unsigned short  v;
-
-       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)
-               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;
-       } else
-#endif
-               v = *(volatile unsigned short *)PORT2ADDR(port);
-
+       unsigned short v = _inw(port);
        delay();
        return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-       unsigned long  v;
-
-       v = *(volatile unsigned long *)PORT2ADDR(port);
+       unsigned long v = _inl(port);
        delay();
        return (v);
 }
@@ -287,52 +244,19 @@ void _outl(unsigned long l, unsigned long port)
 
 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);
-       } else
-#endif
-               *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+       _outb(b, port);
        delay();
 }
 
 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;
-       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);
-       } else
-#endif
-               *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+       _outw(w, port);
        delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       _outl(l, port);
        delay();
 }
 
index 85688ffb52f93cd632041419c3634babc33e0b77..78033165fb5c7ecb489bb35a442654f8ce415ccc 100644 (file)
@@ -3,8 +3,8 @@
  *
  *  Typical I/O routines for Mappi board.
  *
- *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto
  */
 
 #include <linux/config.h>
@@ -130,57 +130,21 @@ unsigned long _inl(unsigned long port)
 
 unsigned char _inb_p(unsigned long port)
 {
-       unsigned char  v;
-
-       if (port >= 0x300 && port < 0x320)
-               v = _ne_inb(PORT2ADDR_NE(port));
-       else
-#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;
-       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
-               unsigned char b;
-               pcc_ioread(1, port, &b, sizeof(b), 1, 0);
-               return b;
-       } else
-#endif
-               v = *(volatile unsigned char *)PORT2ADDR(port);
-
+       unsigned char v = _inb(port);
        delay();
        return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-       unsigned short  v;
-
-       if (port >= 0x300 && port < 0x320)
-               v = _ne_inw(PORT2ADDR_NE(port));
-       else
-#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;
-       } else  if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
-               unsigned short w;
-               pcc_ioread(1, port, &w, sizeof(w), 1, 0);
-               return w;
-       } else
-#endif
-               v = *(volatile unsigned short *)PORT2ADDR(port);
-
+       unsigned short v = _inw(port);
        delay();
        return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-       unsigned long  v;
-
-       v = *(volatile unsigned long *)PORT2ADDR(port);
+       unsigned long v = _inl(port);
        delay();
        return (v);
 }
@@ -229,41 +193,19 @@ void _outl(unsigned long l, unsigned long port)
 
 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_M32R_PCC)
-       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-               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);
-       } else
-#endif
-               *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+       _outb(b, port);
        delay();
 }
 
 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_M32R_PCC)
-       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-               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);
-       } else
-#endif
-               *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+       _outw(w, port);
        delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       _outl(l, port);
        delay();
 }
 
index 4182cd4f97c8a77a60ca636de368677059cbf792..5c03504bf65375646880da8f8eadd973fabbbf24 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Typical I/O routines for Mappi2 board.
  *
- *  Copyright (c) 2001-2003  Hiroyuki Kondo, Hirokazu Takata,
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
  *                           Hitoshi Yamamoto, Mamoru Sakugawa
  */
 
@@ -25,7 +25,7 @@ extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
 extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
 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_MAPPI2_CFC */
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
 
 #define PORT2ADDR(port)      _port2addr(port)
 #define PORT2ADDR_NE(port)   _port2addr_ne(port)
@@ -169,64 +169,21 @@ unsigned long _inl(unsigned long port)
 
 unsigned char _inb_p(unsigned long port)
 {
-       unsigned char  v;
-
-       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;
-       } else
-#endif
-               v = *(volatile unsigned char *)PORT2ADDR(port);
-
+       unsigned char v = _inb(port);
        delay();
        return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-       unsigned short  v;
-
-       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)
-               v = *(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;
-       } else
-#endif
-               v = *(volatile unsigned short *)PORT2ADDR(port);
-
+       unsigned short v = _inw(port);
        delay();
        return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-       unsigned long  v;
-
-       v = *(volatile unsigned long *)PORT2ADDR(port);
+       unsigned long v = _inl(port);
        delay();
        return (v);
 }
@@ -284,52 +241,19 @@ void _outl(unsigned long l, unsigned long port)
 
 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);
-       } else
-#endif
-               *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+       _outb(b, port);
        delay();
 }
 
 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;
-       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);
-       } else
-#endif
-               *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+       _outw(w, port);
        delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       _outl(l, port);
        delay();
 }
 
diff --git a/arch/m32r/kernel/io_mappi3.c b/arch/m32r/kernel/io_mappi3.c
new file mode 100644 (file)
index 0000000..c80bde6
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi3.c
+ *
+ *  Typical I/O routines for Mappi3 board.
+ *
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+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_NE(port)   _port2addr_ne(port)
+#define PORT2ADDR_USB(port)  _port2addr_usb(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 *)0xb4002000;
+       case 0x1f1:     return (void *)0xb4012800;
+       case 0x1f2:     return (void *)0xb4012002;
+       case 0x1f3:     return (void *)0xb4012802;
+       case 0x1f4:     return (void *)0xb4012004;
+       case 0x1f5:     return (void *)0xb4012804;
+       case 0x1f6:     return (void *)0xb4012006;
+       case 0x1f7:     return (void *)0xb4012806;
+       case 0x3f6:     return (void *)0xb401200e;
+       default:        return (void *)&dummy_reg;
+       }
+}
+#endif
+
+static inline void *_port2addr_ne(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+
+static inline void *_port2addr_usb(unsigned long port)
+{
+       return (void *)(port + NONCACHE_OFFSET + 0x12000000);
+}
+static inline void delay(void)
+{
+       __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+static inline unsigned char _ne_inb(void *portp)
+{
+       return (unsigned char) *(volatile unsigned char *)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)
+{
+       unsigned char *buf = addr;
+
+       while (count--)
+               *buf++ = *(volatile unsigned char *)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)
+{
+       *(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;
+       } else
+#endif
+       return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+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);
+#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
+#endif
+       return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+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;
+       } else
+#endif
+       return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+       unsigned char v = _inb(port);
+       delay();
+       return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+       unsigned short v = _inw(port);
+       delay();
+       return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+       unsigned long v = _inl(port);
+       delay();
+       return (v);
+}
+
+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);
+       } else
+#endif
+               *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+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;
+       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);
+       } else
+#endif
+               *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+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);
+       } else
+#endif
+       *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+       _outb(b, port);
+       delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+       _outw(w, port);
+       delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+       _outl(l, port);
+       delay();
+}
+
+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);
+       }
+#endif
+       else {
+               unsigned char *buf = addr;
+               unsigned char *portp = PORT2ADDR(port);
+               while (count--)
+                       *buf++ = *(volatile unsigned char *)portp;
+       }
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+       unsigned short *buf = addr;
+       unsigned short *portp;
+
+       if (port >= LAN_IOSTART && port < LAN_IOEND) {
+               portp = PORT2ADDR_NE(port);
+               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);
+#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;
+       }
+}
+
+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;
+}
+
+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);
+#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);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while (count--)
+                       *(volatile unsigned char *)portp = *buf++;
+       }
+}
+
+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) {
+               portp = PORT2ADDR_NE(port);
+               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);
+#endif
+       } else {
+               portp = PORT2ADDR(port);
+               while (count--)
+                       *(volatile unsigned short *)portp = *buf++;
+       }
+}
+
+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++;
+}
index 286964794d5158bc58e666c0cbf8664a92781db4..9997dddd24d7ea8584bc5e66ae579b5249aca3e8 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Typical I/O routines for OAKS32R board.
  *
- *  Copyright (c) 2001-2004  Hiroyuki Kondo, Hirokazu Takata,
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
  *                           Hitoshi Yamamoto, Mamoru Sakugawa
  */
 
@@ -90,35 +90,21 @@ unsigned long _inl(unsigned long port)
 
 unsigned char _inb_p(unsigned long port)
 {
-       unsigned char  v;
-
-       if (port >= 0x300 && port < 0x320)
-               v = _ne_inb(PORT2ADDR_NE(port));
-       else
-               v = *(volatile unsigned char *)PORT2ADDR(port);
-
+       unsigned char v = _inb(port);
        delay();
        return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-       unsigned short  v;
-
-       if (port >= 0x300 && port < 0x320)
-               v = _ne_inw(PORT2ADDR_NE(port));
-       else
-               v = *(volatile unsigned short *)PORT2ADDR(port);
-
+       unsigned short v = _inw(port);
        delay();
        return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-       unsigned long  v;
-
-       v = *(volatile unsigned long *)PORT2ADDR(port);
+       unsigned long v = _inl(port);
        delay();
        return (v);
 }
@@ -146,27 +132,19 @@ void _outl(unsigned long l, unsigned long port)
 
 void _outb_p(unsigned char b, unsigned long port)
 {
-       if (port >= 0x300 && port < 0x320)
-               _ne_outb(b, PORT2ADDR_NE(port));
-       else
-               *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+       _outb(b, port);
        delay();
 }
 
 void _outw_p(unsigned short w, unsigned long port)
 {
-       if (port >= 0x300 && port < 0x320)
-               _ne_outw(w, PORT2ADDR_NE(port));
-       else
-               *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+       _outw(w, port);
        delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       _outl(l, port);
        delay();
 }
 
index aaf42f9f76dab13ce73e37c0e3d23de9482fa54e..e34951e8156fe227e431fcad50289edf638653df 100644 (file)
@@ -1,10 +1,10 @@
 /*
- *  linux/arch/m32r/kernel/io_mappi.c
+ *  linux/arch/m32r/kernel/io_opsput.c
  *
  *  Typical I/O routines for OPSPUT board.
  *
- *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Takeo Takahashi
  *
  *  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
@@ -98,7 +98,6 @@ unsigned char _inb(unsigned long port)
 {
        if (port >= LAN_IOSTART && port < LAN_IOEND)
                return _ne_inb(PORT2ADDR_NE(port));
-
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
        else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
                unsigned char b;
@@ -118,7 +117,6 @@ unsigned short _inw(unsigned long 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;
@@ -143,55 +141,21 @@ unsigned long _inl(unsigned long port)
 
 unsigned char _inb_p(unsigned long port)
 {
-       unsigned char  v;
-
-       if (port >= LAN_IOSTART && port < LAN_IOEND)
-               v = _ne_inb(PORT2ADDR_NE(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;
-       } else
-#endif
-               v = *(volatile unsigned char *)PORT2ADDR(port);
-
+       unsigned char v = _inb(port);
        delay();
        return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-       unsigned short  v;
-
-       if (port >= LAN_IOSTART && port < LAN_IOEND)
-               v = _ne_inw(PORT2ADDR_NE(port));
-       else
-#if defined(CONFIG_USB)
-       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;
-       } else
-#endif
-               v = *(volatile unsigned short *)PORT2ADDR(port);
-
+       unsigned short v = _inw(port);
        delay();
        return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-       unsigned long  v;
-
-       v = *(volatile unsigned long *)PORT2ADDR(port);
+       unsigned long v = _inl(port);
        delay();
        return (v);
 }
@@ -219,7 +183,6 @@ void _outw(unsigned short w, unsigned long port)
                *(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);
@@ -240,43 +203,19 @@ void _outl(unsigned long l, unsigned long port)
 
 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_PCMCIA) && defined(CONFIG_M32R_CFC)
-       if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-               pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
-       } else
-#endif
-               *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+       _outb(b, port);
        delay();
 }
 
 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_USB)
-       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);
-       } else
-#endif
-               *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+       _outw(w, port);
        delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       _outl(l, port);
        delay();
 }
 
index 27928a0b99edf875450bf196e39d7e5435c5ce18..9eb161dcc1042ea86a0154a7ec2bc324773578cc 100644 (file)
@@ -3,8 +3,8 @@
  *
  *  Typical I/O routines for uServer board.
  *
- *  Copyright (c) 2001 - 2003  Hiroyuki Kondo, Hirokazu Takata,
- *                             Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Takeo Takahashi
  *
  *  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
@@ -39,7 +39,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
 
 #define PORT2ADDR(port)        _port2addr(port)
 
-static __inline__ void *_port2addr(unsigned long port)
+static inline void *_port2addr(unsigned long port)
 {
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
        if (port >= UART0_IOSTART && port <= UART0_IOEND)
@@ -50,7 +50,7 @@ static __inline__ void *_port2addr(unsigned long port)
        return (void *)(port + NONCACHE_OFFSET);
 }
 
-static __inline__ void delay(void)
+static inline void delay(void)
 {
        __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
 }
@@ -87,39 +87,22 @@ unsigned long _inl(unsigned long port)
 
 unsigned char _inb_p(unsigned long port)
 {
-       unsigned char b;
-
-       if (port >= CFC_IOSTART && port <= CFC_IOEND) {
-               pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
-               return b;
-       } else {
-               b = *(volatile unsigned char *)PORT2ADDR(port);
-               delay();
-               return b;
-       }
+       unsigned char v = _inb(port);
+       delay();
+       return v;
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-       unsigned short w;
-
-       if (port >= CFC_IOSTART && port <= CFC_IOEND) {
-               pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
-               return w;
-       } else {
-               w = *(volatile unsigned short *)PORT2ADDR(port);
-               delay();
-               return w;
-       }
+       unsigned short v = _inw(port);
+       delay();
+       return v;
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-       unsigned long v;
-
-       v = *(volatile unsigned long *)PORT2ADDR(port);
+       unsigned long v = _inl(port);
        delay();
-
        return v;
 }
 
@@ -149,25 +132,19 @@ void _outl(unsigned long l, unsigned long port)
 
 void _outb_p(unsigned char b, unsigned long port)
 {
-       if (port >= CFC_IOSTART && port <= CFC_IOEND)
-               pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
-       else
-               *(volatile unsigned char *)PORT2ADDR(port) = b;
+       _outb(b, port);
        delay();
 }
 
 void _outw_p(unsigned short w, unsigned long port)
 {
-       if (port >= CFC_IOSTART && port <= CFC_IOEND)
-               pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
-       else
-               *(volatile unsigned short *)PORT2ADDR(port) = w;
+       _outw(w, port);
        delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-       *(volatile unsigned long *)PORT2ADDR(port) = l;
+       _outl(l, port);
        delay();
 }
 
index 4826cd6e40e8eef3bcdee95245fbec18db7868a5..ec5674727e7f148c0b42fc4224143223a726d9a6 100644 (file)
@@ -330,6 +330,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "Machine\t\t: Mappi Evaluation board\n");
 #elif CONFIG_PLAT_MAPPI2
        seq_printf(m, "Machine\t\t: Mappi-II Evaluation board\n");
+#elif CONFIG_PLAT_MAPPI3
+       seq_printf(m, "Machine\t\t: Mappi-III Evaluation board\n");
 #elif  CONFIG_PLAT_M32700UT
        seq_printf(m, "Machine\t\t: M32700UT Evaluation board\n");
 #elif  CONFIG_PLAT_OPSPUT
index 488aa87bab7666eeae74c6297ebcb73e0315ce4a..b014e2c1e524973a58f8adf7ecff122966446787 100644 (file)
@@ -78,13 +78,13 @@ static void shutdown_m32700ut_irq(unsigned int irq)
 
 static struct hw_interrupt_type m32700ut_irq_type =
 {
-       "M32700UT-IRQ",
-       startup_m32700ut_irq,
-       shutdown_m32700ut_irq,
-       enable_m32700ut_irq,
-       disable_m32700ut_irq,
-       mask_and_ack_m32700ut,
-       end_m32700ut_irq
+       .typename = "M32700UT-IRQ",
+       .startup = startup_m32700ut_irq,
+       .shutdown = shutdown_m32700ut_irq,
+       .enable = enable_m32700ut_irq,
+       .disable = disable_m32700ut_irq,
+       .ack = mask_and_ack_m32700ut,
+       .end = end_m32700ut_irq
 };
 
 /*
@@ -155,13 +155,13 @@ static void shutdown_m32700ut_pld_irq(unsigned int irq)
 
 static struct hw_interrupt_type m32700ut_pld_irq_type =
 {
-       "M32700UT-PLD-IRQ",
-       startup_m32700ut_pld_irq,
-       shutdown_m32700ut_pld_irq,
-       enable_m32700ut_pld_irq,
-       disable_m32700ut_pld_irq,
-       mask_and_ack_m32700ut_pld,
-       end_m32700ut_pld_irq
+       .typename = "M32700UT-PLD-IRQ",
+       .startup = startup_m32700ut_pld_irq,
+       .shutdown = shutdown_m32700ut_pld_irq,
+       .enable = enable_m32700ut_pld_irq,
+       .disable = disable_m32700ut_pld_irq,
+       .ack = mask_and_ack_m32700ut_pld,
+       .end = end_m32700ut_pld_irq
 };
 
 /*
@@ -224,13 +224,13 @@ static void shutdown_m32700ut_lanpld_irq(unsigned int irq)
 
 static struct hw_interrupt_type m32700ut_lanpld_irq_type =
 {
-       "M32700UT-PLD-LAN-IRQ",
-       startup_m32700ut_lanpld_irq,
-       shutdown_m32700ut_lanpld_irq,
-       enable_m32700ut_lanpld_irq,
-       disable_m32700ut_lanpld_irq,
-       mask_and_ack_m32700ut_lanpld,
-       end_m32700ut_lanpld_irq
+       .typename = "M32700UT-PLD-LAN-IRQ",
+       .startup = startup_m32700ut_lanpld_irq,
+       .shutdown = shutdown_m32700ut_lanpld_irq,
+       .enable = enable_m32700ut_lanpld_irq,
+       .disable = disable_m32700ut_lanpld_irq,
+       .ack = mask_and_ack_m32700ut_lanpld,
+       .end = end_m32700ut_lanpld_irq
 };
 
 /*
@@ -293,13 +293,13 @@ static void shutdown_m32700ut_lcdpld_irq(unsigned int irq)
 
 static struct hw_interrupt_type m32700ut_lcdpld_irq_type =
 {
-       "M32700UT-PLD-LCD-IRQ",
-       startup_m32700ut_lcdpld_irq,
-       shutdown_m32700ut_lcdpld_irq,
-       enable_m32700ut_lcdpld_irq,
-       disable_m32700ut_lcdpld_irq,
-       mask_and_ack_m32700ut_lcdpld,
-       end_m32700ut_lcdpld_irq
+       .typename = "M32700UT-PLD-LCD-IRQ",
+       .startup = startup_m32700ut_lcdpld_irq,
+       .shutdown = shutdown_m32700ut_lcdpld_irq,
+       .enable = enable_m32700ut_lcdpld_irq,
+       .disable = disable_m32700ut_lcdpld_irq,
+       .ack = mask_and_ack_m32700ut_lcdpld,
+       .end = end_m32700ut_lcdpld_irq
 };
 
 void __init init_IRQ(void)
index 1e74110f0670a19008d8632482f353c815b4f98d..aaf8e569b930267a45b4603fc351d58daae9f11e 100644 (file)
@@ -70,13 +70,13 @@ static void shutdown_mappi_irq(unsigned int irq)
 
 static struct hw_interrupt_type mappi_irq_type =
 {
-       "MAPPI-IRQ",
-       startup_mappi_irq,
-       shutdown_mappi_irq,
-       enable_mappi_irq,
-       disable_mappi_irq,
-       mask_and_ack_mappi,
-       end_mappi_irq
+       .typename = "MAPPI-IRQ",
+       .startup = startup_mappi_irq,
+       .shutdown = shutdown_mappi_irq,
+       .enable = enable_mappi_irq,
+       .disable = disable_mappi_irq,
+       .ack = mask_and_ack_mappi,
+       .end = end_mappi_irq
 };
 
 void __init init_IRQ(void)
index 1904d465a507cae133c8d9a919082422d4b9e83c..38d5e9a4142782ac201748ea4c3a0b52fae2865d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/m32r/kernel/setup_mappi.c
+ *  linux/arch/m32r/kernel/setup_mappi2.c
  *
  *  Setup routines for Renesas MAPPI-II(M3A-ZA36) Board
  *
@@ -79,13 +79,13 @@ static void shutdown_mappi2_irq(unsigned int irq)
 
 static struct hw_interrupt_type mappi2_irq_type =
 {
-       "MAPPI2-IRQ",
-       startup_mappi2_irq,
-       shutdown_mappi2_irq,
-       enable_mappi2_irq,
-       disable_mappi2_irq,
-       mask_and_ack_mappi2,
-       end_mappi2_irq
+       .typename = "MAPPI2-IRQ",
+       .startup = startup_mappi2_irq,
+       .shutdown = shutdown_mappi2_irq,
+       .enable = enable_mappi2_irq,
+       .disable = disable_mappi2_irq,
+       .ack = mask_and_ack_mappi2,
+       .end = end_mappi2_irq
 };
 
 void __init init_IRQ(void)
@@ -156,7 +156,6 @@ void __init init_IRQ(void)
        irq_desc[PLD_IRQ_CFIREQ].handler = &mappi2_irq_type;
        irq_desc[PLD_IRQ_CFIREQ].action = 0;
        irq_desc[PLD_IRQ_CFIREQ].depth = 1;     /* disable nested irq */
-//     icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
        icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
        disable_mappi2_irq(PLD_IRQ_CFIREQ);
 
@@ -167,7 +166,6 @@ void __init init_IRQ(void)
        irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
        irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
        icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
-//     icu_data[PLD_IRQ_CFC_INSERT].icucr = 0;
        disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
 
        /* ICUCR42: CFC Eject */
@@ -176,9 +174,7 @@ void __init init_IRQ(void)
        irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
        irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;  /* disable nested irq */
        icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
-//     icu_data[PLD_IRQ_CFC_EJECT].icucr = 0;
        disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
-
 #endif /* CONFIG_MAPPI2_CFC */
 }
 
diff --git a/arch/m32r/kernel/setup_mappi3.c b/arch/m32r/kernel/setup_mappi3.c
new file mode 100644 (file)
index 0000000..3d60a85
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ *  linux/arch/m32r/kernel/setup_mappi3.c
+ *
+ *  Setup routines for Renesas MAPPI-III(M3A-2170) Board
+ *
+ *  Copyright (c) 2001-2005   Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+       unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_mappi3_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       if ((irq == 0) ||(irq >= NR_IRQS))  {
+               printk("bad irq 0x%08x\n", irq);
+               return;
+       }
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+       outl(data, port);
+}
+
+static void enable_mappi3_irq(unsigned int irq)
+{
+       unsigned long port, data;
+
+       if ((irq == 0) ||(irq >= NR_IRQS))  {
+               printk("bad irq 0x%08x\n", irq);
+               return;
+       }
+       port = irq2port(irq);
+       data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+       outl(data, port);
+}
+
+static void mask_and_ack_mappi3(unsigned int irq)
+{
+       disable_mappi3_irq(irq);
+}
+
+static void end_mappi3_irq(unsigned int irq)
+{
+       enable_mappi3_irq(irq);
+}
+
+static unsigned int startup_mappi3_irq(unsigned int irq)
+{
+       enable_mappi3_irq(irq);
+       return (0);
+}
+
+static void shutdown_mappi3_irq(unsigned int irq)
+{
+       unsigned long port;
+
+       port = irq2port(irq);
+       outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi3_irq_type =
+{
+       .typename = "MAPPI3-IRQ",
+       .startup = startup_mappi3_irq,
+       .shutdown = shutdown_mappi3_irq,
+       .enable = enable_mappi3_irq,
+       .disable = disable_mappi3_irq,
+       .ack = mask_and_ack_mappi3,
+       .end = end_mappi3_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+       /* INT0 : LAN controller (SMC91111) */
+       irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT0].handler = &mappi3_irq_type;
+       irq_desc[M32R_IRQ_INT0].action = 0;
+       irq_desc[M32R_IRQ_INT0].depth = 1;
+       icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+       disable_mappi3_irq(M32R_IRQ_INT0);
+#endif  /* CONFIG_SMC91X */
+
+       /* MFT2 : system timer */
+       irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_MFT2].handler = &mappi3_irq_type;
+       irq_desc[M32R_IRQ_MFT2].action = 0;
+       irq_desc[M32R_IRQ_MFT2].depth = 1;
+       icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+       disable_mappi3_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+       /* SIO0_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_R].handler = &mappi3_irq_type;
+       irq_desc[M32R_IRQ_SIO0_R].action = 0;
+       irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+       icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+       disable_mappi3_irq(M32R_IRQ_SIO0_R);
+
+       /* SIO0_S : uart send data */
+       irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO0_S].handler = &mappi3_irq_type;
+       irq_desc[M32R_IRQ_SIO0_S].action = 0;
+       irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+       icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+       disable_mappi3_irq(M32R_IRQ_SIO0_S);
+       /* SIO1_R : uart receive data */
+       irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_R].handler = &mappi3_irq_type;
+       irq_desc[M32R_IRQ_SIO1_R].action = 0;
+       irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+       icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+       disable_mappi3_irq(M32R_IRQ_SIO1_R);
+
+       /* SIO1_S : uart send data */
+       irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_SIO1_S].handler = &mappi3_irq_type;
+       irq_desc[M32R_IRQ_SIO1_S].action = 0;
+       irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+       icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+       disable_mappi3_irq(M32R_IRQ_SIO1_S);
+#endif  /* CONFIG_M32R_USE_DBG_CONSOLE */
+
+#if defined(CONFIG_USB)
+       /* INT1 : USB Host controller interrupt */
+       irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+       irq_desc[M32R_IRQ_INT1].handler = &mappi3_irq_type;
+       irq_desc[M32R_IRQ_INT1].action = 0;
+       irq_desc[M32R_IRQ_INT1].depth = 1;
+       icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
+       disable_mappi3_irq(M32R_IRQ_INT1);
+#endif /* CONFIG_USB */
+
+       /* ICUCR40: CFC IREQ */
+       irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFIREQ].handler = &mappi3_irq_type;
+       irq_desc[PLD_IRQ_CFIREQ].action = 0;
+       irq_desc[PLD_IRQ_CFIREQ].depth = 1;     /* disable nested irq */
+       icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+       disable_mappi3_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 = &mappi3_irq_type;
+       irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+       irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
+       icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
+       disable_mappi3_irq(PLD_IRQ_CFC_INSERT);
+
+       /* ICUCR42: CFC Eject */
+       irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+       irq_desc[PLD_IRQ_CFC_EJECT].handler = &mappi3_irq_type;
+       irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+       irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;  /* disable nested irq */
+       icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+       disable_mappi3_irq(PLD_IRQ_CFC_EJECT);
+#endif /* CONFIG_M32R_CFC */
+}
+
+#define LAN_IOSTART     0x300
+#define LAN_IOEND       0x320
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = (LAN_IOSTART),
+               .end    = (LAN_IOEND),
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = M32R_IRQ_INT0,
+               .end    = M32R_IRQ_INT0,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+       platform_device_register(&smc91x_device);
+       return 0;
+}
+arch_initcall(platform_init);
index b04834526c9a8a6311ace7897b13bc90487360d7..d656640badc98f091bedb9b29004903fb445cb9d 100644 (file)
@@ -70,13 +70,13 @@ static void shutdown_oaks32r_irq(unsigned int irq)
 
 static struct hw_interrupt_type oaks32r_irq_type =
 {
-       "OAKS32R-IRQ",
-       startup_oaks32r_irq,
-       shutdown_oaks32r_irq,
-       enable_oaks32r_irq,
-       disable_oaks32r_irq,
-       mask_and_ack_mappi,
-       end_oaks32r_irq
+       .typename = "OAKS32R-IRQ",
+       .startup = startup_oaks32r_irq,
+       .shutdown = shutdown_oaks32r_irq,
+       .enable = enable_oaks32r_irq,
+       .disable = disable_oaks32r_irq,
+       .ack = mask_and_ack_mappi,
+       .end = end_oaks32r_irq
 };
 
 void __init init_IRQ(void)
index 84315e344c58007e6e2e1ec155b06b0b5256f35e..86f4cf2a86c3ba6b4eb25c81aad7983aea924e0f 100644 (file)
@@ -79,13 +79,13 @@ static void shutdown_opsput_irq(unsigned int irq)
 
 static struct hw_interrupt_type opsput_irq_type =
 {
-       "OPSPUT-IRQ",
-       startup_opsput_irq,
-       shutdown_opsput_irq,
-       enable_opsput_irq,
-       disable_opsput_irq,
-       mask_and_ack_opsput,
-       end_opsput_irq
+       .typename = "OPSPUT-IRQ",
+       .startup = startup_opsput_irq,
+       .shutdown = shutdown_opsput_irq,
+       .enable = enable_opsput_irq,
+       .disable = disable_opsput_irq,
+       .ack = mask_and_ack_opsput,
+       .end = end_opsput_irq
 };
 
 /*
@@ -156,13 +156,13 @@ static void shutdown_opsput_pld_irq(unsigned int irq)
 
 static struct hw_interrupt_type opsput_pld_irq_type =
 {
-       "OPSPUT-PLD-IRQ",
-       startup_opsput_pld_irq,
-       shutdown_opsput_pld_irq,
-       enable_opsput_pld_irq,
-       disable_opsput_pld_irq,
-       mask_and_ack_opsput_pld,
-       end_opsput_pld_irq
+       .typename = "OPSPUT-PLD-IRQ",
+       .startup = startup_opsput_pld_irq,
+       .shutdown = shutdown_opsput_pld_irq,
+       .enable = enable_opsput_pld_irq,
+       .disable = disable_opsput_pld_irq,
+       .ack = mask_and_ack_opsput_pld,
+       .end = end_opsput_pld_irq
 };
 
 /*
index fe417be5e3e95c5e4ec8c9958761e3847282b3ac..634741bf9d355c736463b4cb0df4ab4245449485 100644 (file)
@@ -70,13 +70,13 @@ static void shutdown_mappi_irq(unsigned int irq)
 
 static struct hw_interrupt_type mappi_irq_type =
 {
-       "M32700-IRQ",
-       startup_mappi_irq,
-       shutdown_mappi_irq,
-       enable_mappi_irq,
-       disable_mappi_irq,
-       mask_and_ack_mappi,
-       end_mappi_irq
+       .typename = "M32700-IRQ",
+       .startup = startup_mappi_irq,
+       .shutdown = shutdown_mappi_irq,
+       .enable = enable_mappi_irq,
+       .disable = disable_mappi_irq,
+       .ack = mask_and_ack_mappi,
+       .end = end_mappi_irq
 };
 
 /*
@@ -143,13 +143,13 @@ static void shutdown_m32700ut_pld_irq(unsigned int irq)
 
 static struct hw_interrupt_type m32700ut_pld_irq_type =
 {
-       "USRV-PLD-IRQ",
-       startup_m32700ut_pld_irq,
-       shutdown_m32700ut_pld_irq,
-       enable_m32700ut_pld_irq,
-       disable_m32700ut_pld_irq,
-       mask_and_ack_m32700ut_pld,
-       end_m32700ut_pld_irq
+       .typename = "USRV-PLD-IRQ",
+       .startup = startup_m32700ut_pld_irq,
+       .shutdown = shutdown_m32700ut_pld_irq,
+       .enable = enable_m32700ut_pld_irq,
+       .disable = disable_m32700ut_pld_irq,
+       .ack = mask_and_ack_m32700ut_pld,
+       .end = end_m32700ut_pld_irq
 };
 
 void __init init_IRQ(void)
index 1c002181df7ffb245267c499240b08120cafc3c5..3e607d90b5f45b71af6cd34a907ecece49c5ecc1 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:50 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:20:58 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -15,6 +15,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -27,13 +28,16 @@ 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=15
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
+# CONFIG_CPUSETS is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -43,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +70,7 @@ CONFIG_PLAT_M32700UT=y
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -271,7 +277,6 @@ CONFIG_NET=y
 #
 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
@@ -395,18 +400,6 @@ CONFIG_INPUT=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_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -416,6 +409,17 @@ CONFIG_SERIO_SERPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -467,6 +471,10 @@ CONFIG_DS1302=y
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -511,8 +519,14 @@ CONFIG_VIDEO_M32R_AR_M64278=y
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -545,10 +559,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
 # 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
 #
@@ -722,8 +732,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
index 805357f7bda1661dce5c7810e8d2d5ea52a08a7c..2d3e7cda8f461e5f8a35a51e61f6ada8a006268e 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:54 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:21:34 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,15 @@ 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=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +69,7 @@ CONFIG_PLAT_M32700UT=y
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -268,7 +273,6 @@ CONFIG_NET=y
 #
 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
@@ -392,18 +396,6 @@ CONFIG_INPUT=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_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -413,6 +405,17 @@ CONFIG_SERIO_SERPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -464,6 +467,10 @@ CONFIG_DS1302=y
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -508,8 +515,14 @@ CONFIG_VIDEO_M32R_AR_M64278=y
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -542,10 +555,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
 # 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
 #
@@ -719,8 +728,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
index 714aa6e7034cb41e349cb31ab0a4f2973a2b3472..a8425fba340b43a8cbe924bc35d71dd8177b7c16 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:57 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:21:46 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -26,13 +27,15 @@ 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=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +44,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -62,6 +66,7 @@ CONFIG_PLAT_MAPPI=y
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -202,7 +207,6 @@ CONFIG_NET=y
 #
 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
@@ -324,18 +328,6 @@ CONFIG_INPUT=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_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -345,6 +337,17 @@ CONFIG_SERIO_SERPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -393,6 +396,10 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -433,10 +440,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 # 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
 #
@@ -595,8 +598,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
index 956a8e2f98d67a8a4c66d3fc392aebeb61ee6119..1a7f3cd4224667cc82e71f2e1ca4de92d0e85c2a 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:02 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:21:52 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -17,6 +17,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,16 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 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_CPUSETS is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +48,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -66,6 +71,7 @@ CONFIG_PLAT_MAPPI=y
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -139,8 +145,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_REDBOOT_PARTS=y
 CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
 # CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
@@ -294,7 +300,6 @@ CONFIG_NET=y
 # Networking options
 #
 # CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -419,18 +424,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # 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_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -440,6 +433,17 @@ CONFIG_SERIO=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -488,6 +492,10 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -528,10 +536,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 # 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
 #
@@ -708,8 +712,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
index c9253e94efbd565d5424f0e349811eecf71a504f..38910fb766926078b6cb7bf38b0c37b8b3ce3b45 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:07 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:21:59 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -17,6 +17,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,15 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 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_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +69,7 @@ CONFIG_PLAT_MAPPI=y
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -135,8 +140,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_REDBOOT_PARTS=y
 CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
 # CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
@@ -290,7 +295,6 @@ CONFIG_NET=y
 # Networking options
 #
 # CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -415,18 +419,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # 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_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -436,6 +428,17 @@ CONFIG_SERIO=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -484,6 +487,10 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -524,10 +531,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 # 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
 #
@@ -704,8 +707,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
index c14791d27300d8e2a043f919aa49ea3b8bf0783d..56f287b658989cbf700afc53c4dd55b82080d2b5 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:10 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:22:02 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,15 @@ 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=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +69,7 @@ CONFIG_KMOD=y
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 CONFIG_PLAT_MAPPI2=y
+# CONFIG_PLAT_MAPPI3 is not set
 # CONFIG_CHIP_M32700 is not set
 # CONFIG_CHIP_M32102 is not set
 CONFIG_CHIP_VDEC2=y
@@ -264,7 +269,6 @@ CONFIG_NET=y
 #
 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
@@ -388,18 +392,6 @@ CONFIG_INPUT=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_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -409,6 +401,17 @@ CONFIG_SERIO_SERPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -459,6 +462,10 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -520,10 +527,6 @@ CONFIG_DUMMY_CONSOLE=y
 # 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
 #
@@ -697,8 +700,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/mappi3/defconfig.smp b/arch/m32r/mappi3/defconfig.smp
new file mode 100644 (file)
index 0000000..2eebe75
--- /dev/null
@@ -0,0 +1,751 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc5
+# Tue May 31 17:55:34 2005
+#
+CONFIG_M32R=y
+# CONFIG_UID16 is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# 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_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# 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
+CONFIG_BASE_SMALL=0
+
+#
+# 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_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_PLAT_MAPPI3=y
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=10000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_NOHIGHMEM=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+CONFIG_SMP=y
+# CONFIG_CHIP_M32700_TS1 is not set
+CONFIG_NR_CPUS=2
+# CONFIG_NUMA is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
+# CONFIG_TCIC is not set
+# CONFIG_M32R_PCC is not set
+# CONFIG_M32R_CFC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY 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 is not set
+# CONFIG_MTD_JEDECPROBE 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_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
+
+#
+# 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
+# CONFIG_MTD_BLOCK2MTD 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
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+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 is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+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_BLK_DEV_IDECS=y
+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
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# 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 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
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET 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=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP 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_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
+#
+# 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 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
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# 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
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# 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 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
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR 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
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# 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
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS 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_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+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
+
+#
+# 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_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC 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
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_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 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
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# 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/m32r/mappi3/dot.gdbinit b/arch/m32r/mappi3/dot.gdbinit
new file mode 100644 (file)
index 0000000..89c2218
--- /dev/null
@@ -0,0 +1,224 @@
+# .gdbinit file
+# $Id: dot.gdbinit,v 1.1 2005/04/11 02:21:08 sakugawa Exp $
+
+# setting
+set width 0d70
+set radix 0d16
+use_debug_dma
+
+# Initialize SDRAM controller for Mappi
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  set *(unsigned long *)0x00ef604c = 0x00000020
+  # TR
+  set *(unsigned long *)0x00ef6028 = 0x00051502
+  set *(unsigned long *)0x00ef6048 = 0x00051502
+  # ADR
+  set *(unsigned long *)0x00ef6020 = 0x08000004
+  set *(unsigned long *)0x00ef6040 = 0x0c000004
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010517
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+  set *(unsigned long *)0x00ef6044 = 0x00000001
+end
+
+# Initialize LAN controller for Mappi
+define lanc_init
+  # Set BSEL4
+  #set *(unsigned long *)0x00ef5004 = 0x0fff330f
+  #set *(unsigned long *)0x00ef5004 = 0x01113301
+
+#  set *(unsigned long *)0x00ef5004 = 0x02011101
+#  set *(unsigned long *)0x00ef5004 = 0x04441104
+end
+
+define clock_init
+  set *(unsigned long *)0x00ef4010 = 2
+  set *(unsigned long *)0x00ef4014 = 2
+  set *(unsigned long *)0x00ef4020 = 3
+  set *(unsigned long *)0x00ef4024 = 3
+  set *(unsigned long *)0x00ef4004 = 0x7
+#  shell sleep 0.1
+#  set *(unsigned long *)0x00ef4004 = 0x5
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+define port_init
+  set $sfrbase = 0x00ef0000
+  set *(unsigned short *)0x00ef1060 = 0x5555
+  set *(unsigned short *)0x00ef1062 = 0x5555
+  set *(unsigned short *)0x00ef1064 = 0x5555
+  set *(unsigned short *)0x00ef1066 = 0x5555
+  set *(unsigned short *)0x00ef1068 = 0x5555
+  set *(unsigned short *)0x00ef106a = 0x0000
+  set *(unsigned short *)0x00ef106e = 0x5555
+  set *(unsigned short *)0x00ef1070 = 0x5555
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  while ($i < 0d16 )
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb
+end
+
+# Cache ON
+define set_cache_type
+  set $mctype = (void*)0xfffffff8
+# chaos
+# set *(unsigned long *)($mctype) = 0x0000c000
+# m32102 i-cache only
+  set *(unsigned long *)($mctype) = 0x00008000
+# m32102 d-cache only
+#  set *(unsigned long *)($mctype) = 0x00004000
+end
+define cache_on
+  set $param = (void*)0x08001000
+  set *(unsigned long *)($param) = 0x60ff6102
+end
+
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set $task = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+
+  set $mests = *(unsigned long *)0xffff000c
+  set $mdeva = *(unsigned long *)0xffff0010
+  printf "MESTS[0x%08lX] MDEVA[0x%08lX]\n",$mests,$mdeva
+end
+
+
+# Setup all
+define setup
+  clock_init
+  shell sleep 0.1
+  port_init
+  sdram_init
+#  lanc_init
+#  dispc_init
+#  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+#  load busybox.mot
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08001000
+
+  ## MOUNT_ROOT_RDONLY
+  set {long}($param+0x00)=0
+  ## RAMDISK_FLAGS
+  #set {long}($param+0x04)=0
+  ## ORIG_ROOT_DEV
+  #set {long}($param+0x08)=0x00000100
+  ## LOADER_TYPE
+  #set {long}($param+0x0C)=0
+  ## INITRD_START
+  set {long}($param+0x10)=0x082a0000
+  ## INITRD_SIZE
+  set {long}($param+0x14)=0d6200000
+
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d100000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d50000000
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+
+ set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.2.6_04 nfsaddrs=192.168.0.102:192.168.0.1:192.168.0.1:255.255.255.0:mappi: \0"
+
+
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  debug_chaos
+  set *(unsigned long *)0x00f00000=0x08002000
+  set $pc=0x08002000
+  set $fp=0
+  del b
+  si
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+
+restart
+boot
index 9a97363b65244e735c55f10fd02d513795b9e2be..1743f23d49a320a8d1e0dec3b63942d8c8475e80 100644 (file)
@@ -1,10 +1,8 @@
 /*
- * linux/arch/i386/mm/extable.c
+ * linux/arch/m32r/mm/extable.c
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
 #include <asm/uaccess.h>
 
 int fixup_exception(struct pt_regs *regs)
@@ -19,4 +17,3 @@ int fixup_exception(struct pt_regs *regs)
 
        return 0;
 }
-
index f2da9be726e54291f092aca80e3efec4a82c9ab6..3f9fe519acb2413e62ccb26ac004c4ddcc616277 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:13 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:22:04 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -26,12 +27,14 @@ 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=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -40,6 +43,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -61,6 +65,7 @@ CONFIG_KMOD=y
 # CONFIG_PLAT_OPSPUT is not set
 CONFIG_PLAT_OAKS32R=y
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 # CONFIG_CHIP_M32700 is not set
 CONFIG_CHIP_M32102=y
 # CONFIG_CHIP_VDEC2 is not set
@@ -91,10 +96,6 @@ CONFIG_PREEMPT=y
 #
 # CONFIG_PCCARD is not set
 
-#
-# PC-card bridges
-#
-
 #
 # PCI Hotplug Support
 #
@@ -193,7 +194,6 @@ CONFIG_NET=y
 #
 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
@@ -310,18 +310,6 @@ CONFIG_INPUT=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_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -331,6 +319,17 @@ CONFIG_SERIO_SERPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -374,6 +373,10 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -414,10 +417,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 # 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
 #
@@ -574,8 +573,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
index a87e1ea4c301b801a1e2215ee2163f960eb7a10f..66adec6a701adeba82cdf8a5fd9e69c2ef755d44 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:41 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:22:06 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -15,6 +15,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -27,13 +28,15 @@ 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=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -43,6 +46,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -64,6 +68,7 @@ CONFIG_KMOD=y
 CONFIG_PLAT_OPSPUT=y
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 # CONFIG_CHIP_M32700 is not set
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -243,7 +248,6 @@ CONFIG_NET=y
 #
 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
@@ -367,18 +371,6 @@ CONFIG_INPUT=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_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -388,6 +380,17 @@ CONFIG_SERIO_SERPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -437,6 +440,10 @@ CONFIG_DS1302=y
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+
 #
 # I2C support
 #
@@ -477,10 +484,6 @@ CONFIG_DS1302=y
 # 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
 #
@@ -654,8 +657,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
index b027ce7efbc67c2246a6cc21c0ecb56b4d01ae7e..73843c5287782f3ef74a6adaec316445c8e20764 100644 (file)
@@ -232,7 +232,6 @@ void __init mem_init(void)
 #ifdef CONFIG_LIMITED_DMA
                set_page_address(page, lowmem_page_address(page));
 #endif
-               set_bit(PG_highmem, &page->flags);
                set_page_count(page, 1);
                __free_page(page);
                totalhigh_pages++;
index 54ce6da2264481c535fa7c39438902566d6fb27c..10162b187bcf000a04897bc45cebefbe4d87c3b0 100644 (file)
@@ -826,11 +826,6 @@ config MPC10X_BRIDGE
        depends on PCORE || POWERPMC250 || LOPEC || SANDPOINT
        default y
 
-config FSL_OCP
-       bool
-       depends on MPC10X_BRIDGE
-       default y
-
 config MPC10X_OPENPIC
        bool
        depends on POWERPMC250 || LOPEC || SANDPOINT
index 6ee602d8b6a08f1d2105332e4261e1a2c47516d0..9362193742aceecf5dd52110767f6cfb502acdd4 100644 (file)
@@ -58,9 +58,6 @@ SECTIONS
     *(.ramdisk)
     __ramdisk_end = .;
     . = ALIGN(4096);
-    __sysmap_begin = .;
-    *(.sysmap)
-    __sysmap_end = .;
     CONSTRUCTORS
   }
   _edata  =  .;
index 4eacbd8c772a7fb67833770ea4ab87884b952da5..03415238fabf67791bd084775aacf22997ff9370 100644 (file)
@@ -54,13 +54,10 @@ $(images)/ramdisk.image.gz:
        @echo '          RAM disk image must be provided separately'
        @/bin/false
 
-objcpxmon-$(CONFIG_XMON) := --add-section=.sysmap=System.map \
-       --set-section-flags=.sysmap=contents,alloc,load,readonly,data
 quiet_cmd_genimage = GEN     $@
       cmd_genimage = $(OBJCOPY) -R .comment       \
        --add-section=.image=$(images)/vmlinux.gz \
-       --set-section-flags=.image=contents,alloc,load,readonly,data \
-       $(objcpxmon-y) $< $@
+       --set-section-flags=.image=contents,alloc,load,readonly,data $< $@
 
 targets += image.o
 $(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE
index 9e6952781f1f03729c9500753ad07a0f79a08848..0f46756a903e3d38a5c1a539f4beed9dd986ce44 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/page.h>
 
 /* Information from the linker */
-extern char __sysmap_begin, __sysmap_end;
 
 extern int strcmp(const char *s1, const char *s2);
 extern char *avail_ram, *avail_high;
@@ -116,14 +115,8 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
                unsigned long progend)
 {
-       unsigned long sysmap_size;
        struct bi_record *rec;
 
-       /* Figure out the size of a possible System.map we're going to
-        * pass along.
-        * */
-       sysmap_size = (unsigned long)(&__sysmap_end) -
-               (unsigned long)(&__sysmap_begin);
 
        /* leave a 1MB gap then align to the next 1MB boundary */
        addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
@@ -147,15 +140,6 @@ void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
        rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
        rec = (struct bi_record *)((unsigned long)rec + rec->size);
 
-       if (sysmap_size) {
-               rec->tag = BI_SYSMAP;
-               rec->data[0] = (unsigned long)(&__sysmap_begin);
-               rec->data[1] = sysmap_size;
-               rec->size = sizeof(struct bi_record) + 2 *
-                       sizeof(unsigned long);
-               rec = (struct bi_record *)((unsigned long)rec + rec->size);
-       }
-
        rec->tag = BI_LAST;
        rec->size = sizeof(struct bi_record);
        rec = (struct bi_record *)((unsigned long)rec + rec->size);
index c28061ad5982eb7c89745a66f5b448a37f2b66ba..991b4cbb83c8953e14159d64e542f2fa98b5a75e 100644 (file)
@@ -203,7 +203,7 @@ $(obj)/zvmlinux: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
                $(obj)/dummy.o $(obj)/image.o
        $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
        $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
-               -R .stabstr -R .ramdisk -R .sysmap
+               -R .stabstr -R .ramdisk
 
 $(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
                $(images)/vmlinux.gz $(obj)/dummy.o
@@ -215,7 +215,7 @@ $(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
                $(obj)/dummy.o $(obj)/image.o
        $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
        $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
-               -R .stabstr -R .sysmap
+               -R .stabstr
 
 # Sort-of dummy rules, that let us format the image we want.
 zImage: $(images)/$(zimage-y) $(obj)/zvmlinux
diff --git a/arch/ppc/boot/utils/addSystemMap.c b/arch/ppc/boot/utils/addSystemMap.c
deleted file mode 100644 (file)
index 4654f89..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <byteswap.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-void xlate( char * inb, char * trb, unsigned len )
-{
-    unsigned i;
-    for (  i=0; i<len; ++i ) {
-       char c = *inb++;
-       char c1 = c >> 4;
-       char c2 = c & 0xf;
-       if ( c1 > 9 )
-           c1 = c1 + 'A' - 10;
-       else
-           c1 = c1 + '0';
-       if ( c2 > 9 )
-           c2 = c2 + 'A' - 10;
-       else
-           c2 = c2 + '0';
-       *trb++ = c1;
-       *trb++ = c2;
-    }
-    *trb = 0;
-}
-
-#define ElfHeaderSize  (64 * 1024)
-#define ElfPages  (ElfHeaderSize / 4096)
-#define KERNELBASE (0xc0000000)
-
-void get4k( /*istream *inf*/FILE *file, char *buf )
-{
-    unsigned j;
-    unsigned num = fread(buf, 1, 4096, file);
-    for (  j=num; j<4096; ++j )
-       buf[j] = 0;
-}
-
-void put4k( /*ostream *outf*/FILE *file, char *buf )
-{
-    fwrite(buf, 1, 4096, file);
-}
-
-int main(int argc, char **argv)
-{
-    char inbuf[4096];
-    FILE *ramDisk = NULL;
-    FILE *inputVmlinux = NULL;
-    FILE *outputVmlinux = NULL;
-    unsigned i = 0;
-    unsigned long ramFileLen = 0;
-    unsigned long ramLen = 0;
-    unsigned long roundR = 0;
-    unsigned long kernelLen = 0;
-    unsigned long actualKernelLen = 0;
-    unsigned long round = 0;
-    unsigned long roundedKernelLen = 0;
-    unsigned long ramStartOffs = 0;
-    unsigned long ramPages = 0;
-    unsigned long roundedKernelPages = 0;
-    if ( argc < 2 ) {
-       printf("Name of System Map file missing.\n");
-       exit(1);
-    }
-
-    if ( argc < 3 ) {
-       printf("Name of vmlinux file missing.\n");
-       exit(1);
-    }
-
-    if ( argc < 4 ) {
-       printf("Name of vmlinux output file missing.\n");
-       exit(1);
-    }
-
-    ramDisk = fopen(argv[1], "r");
-    if ( ! ramDisk ) {
-       printf("System Map file \"%s\" failed to open.\n", argv[1]);
-       exit(1);
-    }
-    inputVmlinux = fopen(argv[2], "r");
-    if ( ! inputVmlinux ) {
-       printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
-       exit(1);
-    }
-    outputVmlinux = fopen(argv[3], "w");
-    if ( ! outputVmlinux ) {
-       printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
-       exit(1);
-    }
-    fseek(ramDisk, 0, SEEK_END);
-    ramFileLen = ftell(ramDisk);
-    fseek(ramDisk, 0, SEEK_SET);
-    printf("%s file size = %ld\n", argv[1], ramFileLen);
-
-    ramLen = ramFileLen;
-
-    roundR = 4096 - (ramLen % 4096);
-    if ( roundR ) {
-       printf("Rounding System Map file up to a multiple of 4096, adding %ld\n", roundR);
-       ramLen += roundR;
-    }
-
-    printf("Rounded System Map size is %ld\n", ramLen);
-    fseek(inputVmlinux, 0, SEEK_END);
-    kernelLen = ftell(inputVmlinux);
-    fseek(inputVmlinux, 0, SEEK_SET);
-    printf("kernel file size = %ld\n", kernelLen);
-    if ( kernelLen == 0 ) {
-       printf("You must have a linux kernel specified as argv[2]\n");
-       exit(1);
-    }
-
-    actualKernelLen = kernelLen - ElfHeaderSize;
-
-    printf("actual kernel length (minus ELF header) = %ld\n", actualKernelLen);
-
-    round = actualKernelLen % 4096;
-    roundedKernelLen = actualKernelLen;
-    if ( round )
-       roundedKernelLen += (4096 - round);
-
-    printf("actual kernel length rounded up to a 4k multiple = %ld\n", roundedKernelLen);
-
-    ramStartOffs = roundedKernelLen;
-    ramPages = ramLen / 4096;
-
-    printf("System map pages to copy = %ld\n", ramPages);
-
-    // Copy 64K ELF header
-      for (i=0; i<(ElfPages); ++i) {
-         get4k( inputVmlinux, inbuf );
-         put4k( outputVmlinux, inbuf );
-      }
-
-
-
-    roundedKernelPages = roundedKernelLen / 4096;
-
-    fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
-
-    {
-       for ( i=0; i<roundedKernelPages; ++i ) {
-           get4k( inputVmlinux, inbuf );
-           if ( i == 0 ) {
-               unsigned long * p;
-               printf("Storing embedded_sysmap_start at 0x3c\n");
-               p = (unsigned long *)(inbuf + 0x3c);
-
-#if (BYTE_ORDER == __BIG_ENDIAN)
-               *p = ramStartOffs;
-#else
-               *p = bswap_32(ramStartOffs);
-#endif
-
-               printf("Storing embedded_sysmap_end at 0x44\n");
-               p = (unsigned long *)(inbuf + 0x44);
-#if (BYTE_ORDER == __BIG_ENDIAN)
-               *p = ramStartOffs + ramFileLen;
-#else
-               *p = bswap_32(ramStartOffs + ramFileLen);
-#endif
-           }
-           put4k( outputVmlinux, inbuf );
-       }
-    }
-
-    {
-       for ( i=0; i<ramPages; ++i ) {
-           get4k( ramDisk, inbuf );
-           put4k( outputVmlinux, inbuf );
-       }
-    }
-
-
-    fclose(ramDisk);
-    fclose(inputVmlinux);
-    fclose(outputVmlinux);
-    /* Set permission to executable */
-    chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-
-    return 0;
-
-}
-
diff --git a/arch/ppc/configs/mpc8548_cds_defconfig b/arch/ppc/configs/mpc8548_cds_defconfig
new file mode 100644 (file)
index 0000000..abe034f
--- /dev/null
@@ -0,0 +1,659 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc4
+# Tue May 24 22:36:27 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# 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_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# 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
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+# 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 is not set
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
+CONFIG_85xx=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Freescale 85xx options
+#
+# CONFIG_MPC8540_ADS is not set
+CONFIG_MPC8548_CDS=y
+# CONFIG_MPC8555_CDS is not set
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
+CONFIG_MPC8548=y
+
+#
+# Platform options
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+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
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON 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_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# 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
+#
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP 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=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_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=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_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
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# 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 is not set
+# 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 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
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# 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_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# 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
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_PARPORT_LIGHT 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_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_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM 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_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 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
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# 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_SENSORS_M41T00 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
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# 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
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR 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
+
+#
+# XFS support
+#
+# 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
+
+#
+# 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_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_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=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_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=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
index d44b7dc5390a0d64e7f58e3b71d70969de57c922..01c226008dbf2abb71ec55a6a41df0dc68c16d56 100644 (file)
@@ -918,6 +918,20 @@ struct cpu_spec    cpu_specs[] = {
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
        },
+       {       /* e500v2 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x80210000,
+               .cpu_name               = "e500v2",
+               /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_BIG_PHYS,
+               .cpu_user_features      = PPC_FEATURE_32 |
+                       PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+                       PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE,
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+               .num_pmcs               = 4,
+       },
 #endif
 #if !CLASSIC_PPC
        {       /* default match */
index 661523707e8c4c92790450e2256d8496163bf324..8377b6ca26da4039fabc0ba5dd46861edb4e9190 100644 (file)
 
 #ifdef CONFIG_BOOKE
 #include "head_booke.h"
+#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level)       \
+       mtspr   exc_level##_SPRG,r8;                    \
+       BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);          \
+       lwz     r0,GPR10-INT_FRAME_SIZE(r8);            \
+       stw     r0,GPR10(r11);                          \
+       lwz     r0,GPR11-INT_FRAME_SIZE(r8);            \
+       stw     r0,GPR11(r11);                          \
+       mfspr   r8,exc_level##_SPRG
+
        .globl  mcheck_transfer_to_handler
 mcheck_transfer_to_handler:
-       mtspr   MCHECK_SPRG,r8
-       BOOKE_LOAD_MCHECK_STACK
-       lwz     r0,GPR10-INT_FRAME_SIZE(r8)
-       stw     r0,GPR10(r11)
-       lwz     r0,GPR11-INT_FRAME_SIZE(r8)
-       stw     r0,GPR11(r11)
-       mfspr   r8,MCHECK_SPRG
+       TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
        b       transfer_to_handler_full
 
        .globl  crit_transfer_to_handler
 crit_transfer_to_handler:
-       mtspr   CRIT_SPRG,r8
-       BOOKE_LOAD_CRIT_STACK
-       lwz     r0,GPR10-INT_FRAME_SIZE(r8)
-       stw     r0,GPR10(r11)
-       lwz     r0,GPR11-INT_FRAME_SIZE(r8)
-       stw     r0,GPR11(r11)
-       mfspr   r8,CRIT_SPRG
+       TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
        /* fall through */
 #endif
 
@@ -783,99 +780,64 @@ exc_exit_restart_end:
  * time of the critical interrupt.
  *
  */
-       .globl  ret_from_crit_exc
-ret_from_crit_exc:
-       REST_NVGPRS(r1)
-       lwz     r3,_MSR(r1)
-       andi.   r3,r3,MSR_PR
-       LOAD_MSR_KERNEL(r10,MSR_KERNEL)
-       bne     user_exc_return
-
-       lwz     r0,GPR0(r1)
-       lwz     r2,GPR2(r1)
-       REST_4GPRS(3, r1)
-       REST_2GPRS(7, r1)
-
-       lwz     r10,_XER(r1)
-       lwz     r11,_CTR(r1)
-       mtspr   SPRN_XER,r10
-       mtctr   r11
-
-       PPC405_ERR77(0,r1)
-       stwcx.  r0,0,r1                 /* to clear the reservation */
-
-       lwz     r11,_LINK(r1)
-       mtlr    r11
-       lwz     r10,_CCR(r1)
-       mtcrf   0xff,r10
 #ifdef CONFIG_40x
-       /* avoid any possible TLB misses here by turning off MSR.DR, we
-        * assume the instructions here are mapped by a pinned TLB entry */
-       li      r10,MSR_IR
-       mtmsr   r10
-       isync
-       tophys(r1, r1)
+#define PPC_40x_TURN_OFF_MSR_DR                                                    \
+       /* avoid any possible TLB misses here by turning off MSR.DR, we     \
+        * assume the instructions here are mapped by a pinned TLB entry */ \
+       li      r10,MSR_IR;                                                 \
+       mtmsr   r10;                                                        \
+       isync;                                                              \
+       tophys(r1, r1);
+#else
+#define PPC_40x_TURN_OFF_MSR_DR
 #endif
-       lwz     r9,_DEAR(r1)
-       lwz     r10,_ESR(r1)
-       mtspr   SPRN_DEAR,r9
-       mtspr   SPRN_ESR,r10
-       lwz     r11,_NIP(r1)
-       lwz     r12,_MSR(r1)
-       mtspr   SPRN_CSRR0,r11
-       mtspr   SPRN_CSRR1,r12
-       lwz     r9,GPR9(r1)
-       lwz     r12,GPR12(r1)
-       lwz     r10,GPR10(r1)
-       lwz     r11,GPR11(r1)
-       lwz     r1,GPR1(r1)
-       PPC405_ERR77_SYNC
-       rfci
-       b       .               /* prevent prefetch past rfci */
+
+#define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi)    \
+       REST_NVGPRS(r1);                                                \
+       lwz     r3,_MSR(r1);                                            \
+       andi.   r3,r3,MSR_PR;                                           \
+       LOAD_MSR_KERNEL(r10,MSR_KERNEL);                                \
+       bne     user_exc_return;                                        \
+       lwz     r0,GPR0(r1);                                            \
+       lwz     r2,GPR2(r1);                                            \
+       REST_4GPRS(3, r1);                                              \
+       REST_2GPRS(7, r1);                                              \
+       lwz     r10,_XER(r1);                                           \
+       lwz     r11,_CTR(r1);                                           \
+       mtspr   SPRN_XER,r10;                                           \
+       mtctr   r11;                                                    \
+       PPC405_ERR77(0,r1);                                             \
+       stwcx.  r0,0,r1;                /* to clear the reservation */  \
+       lwz     r11,_LINK(r1);                                          \
+       mtlr    r11;                                                    \
+       lwz     r10,_CCR(r1);                                           \
+       mtcrf   0xff,r10;                                               \
+       PPC_40x_TURN_OFF_MSR_DR;                                        \
+       lwz     r9,_DEAR(r1);                                           \
+       lwz     r10,_ESR(r1);                                           \
+       mtspr   SPRN_DEAR,r9;                                           \
+       mtspr   SPRN_ESR,r10;                                           \
+       lwz     r11,_NIP(r1);                                           \
+       lwz     r12,_MSR(r1);                                           \
+       mtspr   exc_lvl_srr0,r11;                                       \
+       mtspr   exc_lvl_srr1,r12;                                       \
+       lwz     r9,GPR9(r1);                                            \
+       lwz     r12,GPR12(r1);                                          \
+       lwz     r10,GPR10(r1);                                          \
+       lwz     r11,GPR11(r1);                                          \
+       lwz     r1,GPR1(r1);                                            \
+       PPC405_ERR77_SYNC;                                              \
+       exc_lvl_rfi;                                                    \
+       b       .;              /* prevent prefetch past exc_lvl_rfi */
+
+       .globl  ret_from_crit_exc
+ret_from_crit_exc:
+       RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
 
 #ifdef CONFIG_BOOKE
-/*
- * Return from a machine check interrupt, similar to a critical
- * interrupt.
- */
        .globl  ret_from_mcheck_exc
 ret_from_mcheck_exc:
-       REST_NVGPRS(r1)
-       lwz     r3,_MSR(r1)
-       andi.   r3,r3,MSR_PR
-       LOAD_MSR_KERNEL(r10,MSR_KERNEL)
-       bne     user_exc_return
-
-       lwz     r0,GPR0(r1)
-       lwz     r2,GPR2(r1)
-       REST_4GPRS(3, r1)
-       REST_2GPRS(7, r1)
-
-       lwz     r10,_XER(r1)
-       lwz     r11,_CTR(r1)
-       mtspr   SPRN_XER,r10
-       mtctr   r11
-
-       stwcx.  r0,0,r1                 /* to clear the reservation */
-
-       lwz     r11,_LINK(r1)
-       mtlr    r11
-       lwz     r10,_CCR(r1)
-       mtcrf   0xff,r10
-       lwz     r9,_DEAR(r1)
-       lwz     r10,_ESR(r1)
-       mtspr   SPRN_DEAR,r9
-       mtspr   SPRN_ESR,r10
-       lwz     r11,_NIP(r1)
-       lwz     r12,_MSR(r1)
-       mtspr   SPRN_MCSRR0,r11
-       mtspr   SPRN_MCSRR1,r12
-       lwz     r9,GPR9(r1)
-       lwz     r12,GPR12(r1)
-       lwz     r10,GPR10(r1)
-       lwz     r11,GPR11(r1)
-       lwz     r1,GPR1(r1)
-       RFMCI
+       RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
 #endif /* CONFIG_BOOKE */
 
 /*
index 6f5d380e234503bb4e48aadc5549cfae9e25bb8e..23fb51819ba5128735dd7bb28edf5085c02b2da2 100644 (file)
@@ -291,8 +291,9 @@ label:
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
        li      r9, 0
@@ -479,8 +480,9 @@ label:
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
        li      r9, 0
@@ -578,8 +580,9 @@ label:
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
        li      r9, 0
index f213d12eec080be8de4435f8294f94dfdb0e1b83..9c50f9d2657c10d1e0dea4199f3f33149c9cb33f 100644 (file)
 #define CRIT_STACK_TOP         (exception_stack_top)
 
 #ifdef CONFIG_SMP
-#define BOOKE_LOAD_CRIT_STACK                          \
+#define BOOKE_LOAD_EXC_LEVEL_STACK(level)              \
        mfspr   r8,SPRN_PIR;                            \
        mulli   r8,r8,BOOKE_EXCEPTION_STACK_SIZE;       \
        neg     r8,r8;                                  \
-       addis   r8,r8,CRIT_STACK_TOP@ha;                \
-       addi    r8,r8,CRIT_STACK_TOP@l
-#define BOOKE_LOAD_MCHECK_STACK                                \
-       mfspr   r8,SPRN_PIR;                            \
-       mulli   r8,r8,BOOKE_EXCEPTION_STACK_SIZE;       \
-       neg     r8,r8;                                  \
-       addis   r8,r8,MCHECK_STACK_TOP@ha;              \
-       addi    r8,r8,MCHECK_STACK_TOP@l
+       addis   r8,r8,level##_STACK_TOP@ha;             \
+       addi    r8,r8,level##_STACK_TOP@l
 #else
-#define BOOKE_LOAD_CRIT_STACK                          \
-       lis     r8,CRIT_STACK_TOP@h;                    \
-       ori     r8,r8,CRIT_STACK_TOP@l
-#define BOOKE_LOAD_MCHECK_STACK                                \
-       lis     r8,MCHECK_STACK_TOP@h;                  \
-       ori     r8,r8,MCHECK_STACK_TOP@l
+#define BOOKE_LOAD_EXC_LEVEL_STACK(level)              \
+       lis     r8,level##_STACK_TOP@h;                 \
+       ori     r8,r8,level##_STACK_TOP@l
 #endif
 
 /*
- * 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 portion of the critical exception stack at low physical
- * addresses.
+ * Exception prolog for critical/machine check exceptions.  This is a
+ * little different from the normal exception prolog above since a
+ * critical/machine check 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 portion of the
+ * critical/machine check exception stack at low physical addresses.
  */
-
-#define CRITICAL_EXCEPTION_PROLOG                                           \
-       mtspr   CRIT_SPRG,r8;                                                \
-       BOOKE_LOAD_CRIT_STACK;          /* r8 points to the crit stack */    \
+#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
+       mtspr   exc_level##_SPRG,r8;                                         \
+       BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
        stw     r10,GPR10-INT_FRAME_SIZE(r8);                                \
        stw     r11,GPR11-INT_FRAME_SIZE(r8);                                \
        mfcr    r10;                    /* save CR in r10 for now          */\
-       mfspr   r11,SPRN_CSRR1;         /* check whether user or kernel    */\
+       mfspr   r11,exc_level_srr1;     /* check whether user or kernel    */\
        andi.   r11,r11,MSR_PR;                                              \
        mr      r11,r8;                                                      \
-       mfspr   r8,CRIT_SPRG;                                                \
+       mfspr   r8,exc_level##_SPRG;                                         \
        beq     1f;                                                          \
        /* COMING FROM USER MODE */                                          \
        mfspr   r11,SPRN_SPRG3;         /* if from user, start at top of   */\
        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,SPRN_CSRR0;                                              \
+       mfspr   r12,exc_level_srr0;                                          \
        stw     r1,GPR1(r11);                                                \
-       mfspr   r9,SPRN_CSRR1;                                               \
+       mfspr   r9,exc_level_srr1;                                           \
        stw     r1,0(r11);                                                   \
        mr      r1,r11;                                                      \
        rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
        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 stack.
- */
-#define MCHECK_EXCEPTION_PROLOG                                             \
-       mtspr   MCHECK_SPRG,r8;                                              \
-       BOOKE_LOAD_MCHECK_STACK;        /* r8 points to the mcheck stack   */\
-       stw     r10,GPR10-INT_FRAME_SIZE(r8);                                \
-       stw     r11,GPR11-INT_FRAME_SIZE(r8);                                \
-       mfcr    r10;                    /* save CR in r10 for now          */\
-       mfspr   r11,SPRN_MCSRR1;        /* check whether user or kernel    */\
-       andi.   r11,r11,MSR_PR;                                              \
-       mr      r11,r8;                                                      \
-       mfspr   r8,MCHECK_SPRG;                                              \
-       beq     1f;                                                          \
-       /* COMING FROM USER MODE */                                          \
-       mfspr   r11,SPRN_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,SPRN_MCSRR0;                                             \
-       stw     r1,GPR1(r11);                                                \
-       mfspr   r9,SPRN_MCSRR1;                                              \
-       stw     r1,0(r11);                                                   \
-       mr      r1,r11;                                                      \
-       rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
-       stw     r0,GPR0(r11);                                                \
-       SAVE_4GPRS(3, r11);                                                  \
-       SAVE_2GPRS(7, r11)
+#define CRITICAL_EXCEPTION_PROLOG \
+               EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
+#define MCHECK_EXCEPTION_PROLOG \
+               EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1)
 
 /*
  * Exception vectors.
@@ -237,7 +192,6 @@ label:
        EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
                          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
@@ -291,7 +245,7 @@ label:
        lwz     r9,GPR9(r11);                                                 \
        lwz     r12,GPR12(r11);                                               \
        mtspr   CRIT_SPRG,r8;                                                 \
-       BOOKE_LOAD_CRIT_STACK;          /* r8 points to the crit stack */     \
+       BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */  \
        lwz     r10,GPR10-INT_FRAME_SIZE(r8);                                 \
        lwz     r11,GPR11-INT_FRAME_SIZE(r8);                                 \
        mfspr   r8,CRIT_SPRG;                                                 \
index 5c20266e3b1fd80c45f88af83d0a3b3b475d5bd4..c42f753269396ff297e02669004e3c126a921f26 100644 (file)
@@ -41,7 +41,7 @@
 #include <asm/xmon.h>
 #include <asm/ocp.h>
 
-#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE)
 #include <asm/ppc_sys.h>
 #endif
 
@@ -61,8 +61,6 @@ extern void power4_idle(void);
 
 extern boot_infos_t *boot_infos;
 struct ide_machdep_calls ppc_ide_md;
-char *sysmap;
-unsigned long sysmap_size;
 
 /* Used with the BI_MEMSIZE bootinfo parameter to store the memory
    size value reported by the boot loader. */
@@ -249,7 +247,7 @@ int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "bogomips\t: %lu.%02lu\n",
                   lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
 
-#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE)
        if (cur_ppc_sys_spec->ppc_sys_name)
                seq_printf(m, "chipset\t\t: %s\n",
                        cur_ppc_sys_spec->ppc_sys_name);
@@ -578,11 +576,6 @@ void parse_bootinfo(struct bi_record *rec)
                case BI_CMD_LINE:
                        strlcpy(cmd_line, (void *)data, sizeof(cmd_line));
                        break;
-               case BI_SYSMAP:
-                       sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] :
-                                         (data[0]+KERNELBASE));
-                       sysmap_size = data[1];
-                       break;
 #ifdef CONFIG_BLK_DEV_INITRD
                case BI_INITRD:
                        initrd_start = data[0] + KERNELBASE;
index c65731e8bc657cb2edbcec90b8050ef813846803..2ca8ecfeefd978058bb65d6ca3d526d1e640a483 100644 (file)
@@ -81,8 +81,10 @@ void die(const char * str, struct pt_regs * fp, long err)
        console_verbose();
        spin_lock_irq(&die_lock);
 #ifdef CONFIG_PMAC_BACKLIGHT
-       set_backlight_enable(1);
-       set_backlight_level(BACKLIGHT_MAX);
+       if (_machine == _MACH_Pmac) {
+               set_backlight_enable(1);
+               set_backlight_level(BACKLIGHT_MAX);
+       }
 #endif
        printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
 #ifdef CONFIG_PREEMPT
index 694163d696d886244b6ea769ab8b19abed8b65a0..c450dc4b766e23b5588dccf0f57e42ea6e1ea22d 100644 (file)
@@ -130,7 +130,7 @@ void _raw_read_lock(rwlock_t *rw)
                while (!read_can_lock(rw)) {
                        if (--stuck == 0) {
                                printk("_read_lock(%p) CPU#%d lock %d\n",
-                                      rw, _smp_processor_id(), rw->lock);
+                                      rw, raw_smp_processor_id(), rw->lock);
                                stuck = INIT_STUCK;
                        }
                }
@@ -158,7 +158,7 @@ void _raw_write_lock(rwlock_t *rw)
                while (!write_can_lock(rw)) {
                        if (--stuck == 0) {
                                printk("write_lock(%p) CPU#%d lock %d)\n",
-                                      rw, _smp_processor_id(), rw->lock);
+                                      rw, raw_smp_processor_id(), rw->lock);
                                stuck = INIT_STUCK;
                        }
                }
index 36233bdcdf8ff7590b64941ef05430851a18a1d6..e07990efa046e238b8dcc4deadff38bb80afcf3d 100644 (file)
@@ -64,6 +64,8 @@ extern unsigned long total_lowmem;
 extern unsigned long __max_low_memory;
 #define MAX_LOW_MEM    CONFIG_LOWMEM_SIZE
 
+#define NUM_TLBCAMS    (16)
+
 struct tlbcam {
        u32     MAS0;
        u32     MAS1;
index 363c157e3617e8f375b0bbae6f31fd499f59cbff..334ef4150d9291165fc9a3e78f77756c742f8221 100644 (file)
@@ -96,9 +96,6 @@ extern struct task_struct *current_set[NR_CPUS];
 char *klimit = _end;
 struct mem_pieces phys_avail;
 
-extern char *sysmap;
-extern unsigned long sysmap_size;
-
 /*
  * this tells the system to map all of ram with the segregs
  * (i.e. page tables) instead of the bats.
@@ -442,12 +439,6 @@ void __init mem_init(void)
        if (agp_special_page)
                SetPageReserved(virt_to_page(agp_special_page));
 #endif
-       if ( sysmap )
-               for (addr = (unsigned long)sysmap;
-                    addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ;
-                    addr += PAGE_SIZE)
-                       SetPageReserved(virt_to_page(addr));
-
        for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
             addr += PAGE_SIZE) {
                if (!PageReserved(virt_to_page(addr)))
@@ -469,7 +460,6 @@ void __init mem_init(void)
                        struct page *page = mem_map + pfn;
 
                        ClearPageReserved(page);
-                       set_bit(PG_highmem, &page->flags);
                        set_page_count(page, 1);
                        __free_page(page);
                        totalhigh_pages++;
@@ -483,9 +473,7 @@ void __init mem_init(void)
               codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
               initpages<< (PAGE_SHIFT-10),
               (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
-       if (sysmap)
-               printk("System.map loaded at 0x%08x for debugger, size: %ld bytes\n",
-                       (unsigned int)sysmap, sysmap_size);
+
 #ifdef CONFIG_PPC_PMAC
        if (agp_special_page)
                printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);
@@ -535,9 +523,6 @@ set_phys_avail(unsigned long total_memory)
        if (rtas_data)
                mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
 #endif
-       /* remove the sysmap pages from the available memory */
-       if (sysmap)
-               mem_pieces_remove(&phys_avail, __pa(sysmap), sysmap_size, 1);
 #ifdef CONFIG_PPC_PMAC
        /* Because of some uninorth weirdness, we need a page of
         * memory as high as possible (it must be outside of the
index ffcdb46997dc3396463b55990f36b9dea2b17828..540f3292b2291f0c1e2cc78ccbdf87b5feac39b3 100644 (file)
@@ -43,6 +43,8 @@ extern int mem_init_done;
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 
+extern unsigned int num_tlbcam_entries;
+
 /* ...and now those things that may be slightly different between processor
  * architectures.  -- Dan
  */
index 5d2f3f66aefa6a695ed19fa9e069f61c03434dc9..81a3d7446d3718576505f4cd847c75c644bd33e2 100644 (file)
@@ -66,7 +66,6 @@ void setbat(int index, unsigned long virt, unsigned long phys,
 
 #ifdef HAVE_TLBCAM
 extern unsigned int tlbcam_index;
-extern unsigned int num_tlbcam_entries;
 extern unsigned long v_mapped_by_tlbcam(unsigned long va);
 extern unsigned long p_mapped_by_tlbcam(unsigned long pa);
 #else /* !HAVE_TLBCAM */
index e6348b5a1ddc6a56e81908fbd8a8e8434f471e44..37ece1542799cefdb069ff58e120fcfe5a89af86 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/ipic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -186,6 +185,26 @@ mpc834x_sys_init_IRQ(void)
        ipic_set_default_priority();
 }
 
+#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
+extern ulong   ds1374_get_rtc_time(void);
+extern int     ds1374_set_rtc_time(ulong);
+
+static int __init
+mpc834x_rtc_hookup(void)
+{
+       struct timespec tv;
+
+       ppc_md.get_rtc_time = ds1374_get_rtc_time;
+       ppc_md.set_rtc_time = ds1374_set_rtc_time;
+
+       tv.tv_nsec = 0;
+       tv.tv_sec = (ppc_md.get_rtc_time)();
+       do_settimeofday(&tv);
+
+       return 0;
+}
+late_initcall(mpc834x_rtc_hookup);
+#endif
 static __inline__ void
 mpc834x_sys_set_bat(void)
 {
index ff92e38e7da124ffe4bd698b3d3ed4f7988238ff..c5bc2821d99162c673aac9a2d1558d4e950a8502 100644 (file)
@@ -21,6 +21,11 @@ config MPC8540_ADS
        help
          This option enables support for the MPC 8540 ADS evaluation board.
 
+config MPC8548_CDS
+       bool "Freescale MPC8548 CDS"
+       help
+         This option enablese support for the MPC8548 CDS evaluation board.
+
 config MPC8555_CDS
        bool "Freescale MPC8555 CDS"
        help
@@ -53,6 +58,11 @@ config MPC8540
        depends on MPC8540_ADS
        default y
 
+config MPC8548
+       bool
+       depends on MPC8548_CDS
+       default y
+
 config MPC8555
        bool
        depends on MPC8555_CDS
index 854fbd298ba2afa43d7620bf3151b87603c69b43..efdf813108f2fb86c0e7bfff4f7b095db47ee8e2 100644 (file)
@@ -2,6 +2,7 @@
 # Makefile for the PowerPC 85xx linux kernel.
 #
 obj-$(CONFIG_MPC8540_ADS)      += mpc85xx_ads_common.o mpc8540_ads.o
+obj-$(CONFIG_MPC8548_CDS)      += mpc85xx_cds_common.o
 obj-$(CONFIG_MPC8555_CDS)      += mpc85xx_cds_common.o
 obj-$(CONFIG_MPC8560_ADS)      += mpc85xx_ads_common.o mpc8560_ads.o
 obj-$(CONFIG_SBC8560)          += sbc85xx.o sbc8560.o
index 583838ab02d8370a97d22640915a3fed84d1eaf6..a2ed611cd936877f836e381b23c14cf0193969a2 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -88,7 +87,7 @@ mpc8540ads_setup_arch(void)
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
        /* Invalidate the entry we stole earlier the serial ports
         * should be properly mapped */
-       invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+       invalidate_tlbcam_entry(num_tlbcam_entries - 1);
 #endif
 
        /* setup the board related information for the enet controllers */
@@ -150,7 +149,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                struct uart_port p;
 
                /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
-               settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+               settlbcam(num_tlbcam_entries - 1, binfo->bi_immr_base,
                          binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
                memset(&p, 0, sizeof (p));
index 761b8c7b25d27514ec7d305c855b45c2aa629b96..d87dfd5ce0a23d62fed242154763b70e99e56f17 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
index ba9f9f562c4587da3c8e0422be1d92f3166ee775..18e952d1767cd7a481f38a4c372e8af1b602c1ae 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -59,40 +58,8 @@ extern unsigned long total_memory;   /* in mm/init */
 unsigned char __res[sizeof (bd_t)];
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
 static u_char mpc85xx_ads_openpic_initsenses[] __initdata = {
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  0: L2 Cache */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  1: ECM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  2: DDR DRAM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  3: LBIU */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  4: DMA 0 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  5: DMA 1 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  6: DMA 2 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  7: DMA 3 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  8: PCI/PCI-X */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  9: RIO Inbound Port Write Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 10: RIO Doorbell Inbound */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 11: RIO Outbound Message */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 12: RIO Inbound Message */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 13: TSEC 0 Transmit */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 14: TSEC 0 Receive */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 15: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 16: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 17: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 18: TSEC 0 Receive/Transmit Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 19: TSEC 1 Transmit */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 20: TSEC 1 Receive */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 21: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 22: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 23: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 24: TSEC 1 Receive/Transmit Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 25: Fast Ethernet */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 26: DUART */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 27: I2C */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 28: Performance Monitor */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 29: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 30: CPM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 31: Unused */
+       MPC85XX_INTERNAL_IRQ_SENSES,
        0x0,                                            /* External  0: */
 #if defined(CONFIG_PCI)
        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 1: PCI slot 0 */
@@ -159,7 +126,7 @@ mpc85xx_ads_init_IRQ(void)
        /* Skip reserved space and internal sources */
        openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
        /* Map PIC IRQs 0-11 */
-       openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+       openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
 
        /* we let openpic interrupts starting from an offset, to
         * leave space for cascading interrupts underneath.
index e7cfa498568c25b03f891bd809a3342010c32f58..203b2ca61df896d6be9d466b05a95ca5169ee4ce 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/todc.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
 #include <asm/bootinfo.h>
@@ -73,40 +72,8 @@ static int cds_pci_slot = 2;
 static volatile u8 * cadmus;
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
 static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  0: L2 Cache */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  1: ECM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  2: DDR DRAM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  3: LBIU */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  4: DMA 0 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  5: DMA 1 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  6: DMA 2 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  7: DMA 3 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  8: PCI/PCI-X */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  9: RIO Inbound Port Write Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 10: RIO Doorbell Inbound */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 11: RIO Outbound Message */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 12: RIO Inbound Message */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 13: TSEC 0 Transmit */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 14: TSEC 0 Receive */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 15: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 16: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 17: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 18: TSEC 0 Receive/Transmit Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 19: TSEC 1 Transmit */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 20: TSEC 1 Receive */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 21: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 22: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 23: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 24: TSEC 1 Receive/Transmit Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 25: Fast Ethernet */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 26: DUART */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 27: I2C */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 28: Performance Monitor */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 29: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 30: CPM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 31: Unused */
+       MPC85XX_INTERNAL_IRQ_SENSES,
 #if defined(CONFIG_PCI)
        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 0: PCI1 slot */
        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 1: PCI1 slot */
@@ -182,7 +149,6 @@ void __init
 mpc85xx_cds_init_IRQ(void)
 {
        bd_t *binfo = (bd_t *) __res;
-       int i;
 
        /* Determine the Physical Address of the OpenPIC regs */
        phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
@@ -191,9 +157,13 @@ mpc85xx_cds_init_IRQ(void)
        OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
 
        /* Skip reserved space and internal sources */
+#ifdef CONFIG_MPC8548
+       openpic_set_sources(0, 48, OpenPIC_Addr + 0x10200);
+#else
        openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+#endif
        /* Map PIC IRQs 0-11 */
-       openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+       openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
 
        /* we let openpic interrupts starting from an offset, to
         * leave space for cascading interrupts underneath.
@@ -475,26 +445,52 @@ mpc85xx_cds_setup_arch(void)
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
        /* Invalidate the entry we stole earlier the serial ports
         * should be properly mapped */
-       invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+       invalidate_tlbcam_entry(num_tlbcam_entries - 1);
 #endif
 
        /* setup the board related information for the enet controllers */
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
-       pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-       pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-       pdata->phyid = 0;
-       /* fixup phy address */
-       pdata->phy_reg_addr += binfo->bi_immr_base;
-       memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+       if (pdata) {
+               pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+               pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+               pdata->phyid = 0;
+               /* fixup phy address */
+               pdata->phy_reg_addr += binfo->bi_immr_base;
+               memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+       }
 
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
-       pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-       pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-       pdata->phyid = 1;
-       /* fixup phy address */
-       pdata->phy_reg_addr += binfo->bi_immr_base;
-       memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+       if (pdata) {
+               pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+               pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+               pdata->phyid = 1;
+               /* fixup phy address */
+               pdata->phy_reg_addr += binfo->bi_immr_base;
+               memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+       }
+
+       pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1);
+       if (pdata) {
+               pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+               pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+               pdata->phyid = 0;
+               /* fixup phy address */
+               pdata->phy_reg_addr += binfo->bi_immr_base;
+               memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+       }
+
+       pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2);
+       if (pdata) {
+               pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+               pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+               pdata->phyid = 1;
+               /* fixup phy address */
+               pdata->phy_reg_addr += binfo->bi_immr_base;
+               memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+       }
 
+       ppc_sys_device_remove(MPC85xx_eTSEC3);
+       ppc_sys_device_remove(MPC85xx_eTSEC4);
 
 #ifdef CONFIG_BLK_DEV_INITRD
        if (initrd_start)
@@ -531,7 +527,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                struct uart_port p;
 
                /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
-               settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+               settlbcam(num_tlbcam_entries - 1, binfo->bi_immr_base,
                                binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
                memset(&p, 0, sizeof (p));
index 7b9e1543e17524e6301e4c45cd9d77b4a6b8967e..3dbdd73618ebd9ce31d7377e60b9a2d57ffa3e33 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -125,7 +124,7 @@ sbc8560_setup_arch(void)
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
        /* Invalidate the entry we stole earlier the serial ports
         * should be properly mapped */ 
-       invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+       invalidate_tlbcam_entry(num_tlbcam_entries - 1);
 #endif
 
        /* setup the board related information for the enet controllers */
@@ -176,7 +175,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
        /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
-       settlbcam(NUM_TLBCAMS - 1, UARTA_ADDR,
+       settlbcam(num_tlbcam_entries - 1, UARTA_ADDR,
                  UARTA_ADDR, 0x1000, _PAGE_IO, 0);
 #endif
 
index 2d638c1c1bd6f79847fb5d4109ca383c59ca65ee..4f6d1ddd6fb8073cc76d7923b3721e77ac80028a 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -59,40 +58,8 @@ unsigned long pci_dram_offset = 0;
 extern unsigned long total_memory;     /* in mm/init */
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
 static u_char sbc8560_openpic_initsenses[] __initdata = {
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  0: L2 Cache */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  1: ECM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  2: DDR DRAM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  3: LBIU */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  4: DMA 0 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  5: DMA 1 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  6: DMA 2 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  7: DMA 3 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  8: PCI/PCI-X */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  9: RIO Inbound Port Write Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 10: RIO Doorbell Inbound */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 11: RIO Outbound Message */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 12: RIO Inbound Message */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 13: TSEC 0 Transmit */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 14: TSEC 0 Receive */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 15: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 16: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 17: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 18: TSEC 0 Receive/Transmit Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 19: TSEC 1 Transmit */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 20: TSEC 1 Receive */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 21: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 22: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 23: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 24: TSEC 1 Receive/Transmit Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 25: Fast Ethernet */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 26: DUART */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 27: I2C */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 28: Performance Monitor */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 29: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 30: CPM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 31: Unused */
+       MPC85XX_INTERNAL_IRQ_SENSES,
        0x0,                            /* External  0: */
        0x0,                            /* External  1: */
 #if defined(CONFIG_PCI)
@@ -159,7 +126,7 @@ sbc8560_init_IRQ(void)
        /* Skip reserved space and internal sources */
        openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
        /* Map PIC IRQs 0-11 */
-       openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+       openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
 
        /* we let openpic interrupts starting from an offset, to 
         * leave space for cascading interrupts underneath.
index bc95836e417c512b88924b513104de64069397f2..9455bb6b45e933dfe220c62afe96a8bf4543b1ac 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -72,38 +71,7 @@ unsigned long pci_dram_offset = 0;
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
 static u8 gp3_openpic_initsenses[] __initdata = {
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  0: L2 Cache */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  1: ECM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  2: DDR DRAM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  3: LBIU */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  4: DMA 0 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  5: DMA 1 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  6: DMA 2 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  7: DMA 3 */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  8: PCI/PCI-X */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  9: RIO Inbound Port Write Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 10: RIO Doorbell Inbound */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 11: RIO Outbound Message */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 12: RIO Inbound Message */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 13: TSEC 0 Transmit */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 14: TSEC 0 Receive */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 15: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 16: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 17: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 18: TSEC 0 Receive/Transmit Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 19: TSEC 1 Transmit */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 20: TSEC 1 Receive */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 21: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 22: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 23: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 24: TSEC 1 Receive/Transmit Error */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 25: Fast Ethernet */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 26: DUART */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 27: I2C */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 28: Performance Monitor */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 29: Unused */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 30: CPM */
-       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 31: Unused */
+       MPC85XX_INTERNAL_IRQ_SENSES,
        0x0,                                            /* External  0: */
 #if defined(CONFIG_PCI)
        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 1: PCI slot 0 */
@@ -200,7 +168,6 @@ static struct irqaction cpm2_irqaction = {
 static void __init
 gp3_init_IRQ(void)
 {
-       int i;
        bd_t *binfo = (bd_t *) __res;
 
        /*
@@ -218,7 +185,7 @@ gp3_init_IRQ(void)
        openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
 
        /* Map PIC IRQs 0-11 */
-       openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+       openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
 
        /*
         * Let openpic interrupts starting from an offset, to
index 531bfa0e451214c10f9b3d68a1721794721cbd50..70e58f43f2b84b47043494c2e15c9b5a12ebb563 100644 (file)
@@ -81,6 +81,7 @@
 #include <linux/serial.h>
 #include <linux/tty.h> /* for linux/serial_core.h */
 #include <linux/serial_core.h>
+#include <linux/serial_8250.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/mpc10x.h>
 #include <asm/pci-bridge.h>
 #include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
 
 #include "sandpoint.h"
 
@@ -305,6 +307,24 @@ sandpoint_setup_arch(void)
        /* Lookup PCI host bridges */
        sandpoint_find_bridges();
 
+       if (strncmp (cur_ppc_sys_spec->ppc_sys_name, "8245", 4) == 0)
+       {
+               bd_t *bp = (bd_t *)__res;
+               struct plat_serial8250_port *pdata;
+               pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC10X_DUART);
+
+               if (pdata)
+               {
+                       pdata[0].uartclk = bp->bi_busfreq;
+                       pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
+
+                       /* this disables the 2nd serial port on the DUART
+                        * since the sandpoint does not have it connected */
+                       pdata[1].uartclk = 0;
+                       pdata[1].irq = 0;
+                       pdata[1].mapbase = 0;
+               }
+
        printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
        printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
 
index 96acf85800d47a493ca924ded205dcfb70af8779..dec5bf4f6879ff3956aa3b7cddfde7a2028595f4 100644 (file)
@@ -92,7 +92,7 @@ ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y)
 obj-$(CONFIG_SERIAL_TEXT_DEBUG)        += mv64x60_dbg.o
 endif
 obj-$(CONFIG_BOOTX_TEXT)       += btext.o
-obj-$(CONFIG_MPC10X_BRIDGE)     += mpc10x_common.o indirect_pci.o
+obj-$(CONFIG_MPC10X_BRIDGE)    += mpc10x_common.o indirect_pci.o ppc_sys.o
 obj-$(CONFIG_MPC10X_OPENPIC)   += open_pic.o
 obj-$(CONFIG_40x)              += dcr.o
 obj-$(CONFIG_BOOKE)            += dcr.o
@@ -107,6 +107,7 @@ obj-$(CONFIG_83xx)          += ipic.o ppc83xx_setup.o ppc_sys.o \
 ifeq ($(CONFIG_83xx),y)
 obj-$(CONFIG_PCI)              += indirect_pci.o pci_auto.o
 endif
+obj-$(CONFIG_MPC8548_CDS)      += todc_time.o
 obj-$(CONFIG_MPC8555_CDS)      += todc_time.o
 obj-$(CONFIG_PPC_MPC52xx)      += mpc52xx_setup.o mpc52xx_pic.o \
                                        mpc52xx_sys.o mpc52xx_devices.o ppc_sys.o
index fd93adfd464c6d51e437e9ff4fb32e57a30d0d05..8fc5f4154521587193e46a73e3eee852e6e3332d 100644 (file)
@@ -21,6 +21,9 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/serial_8250.h>
+#include <linux/fsl_devices.h>
+#include <linux/device.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
 #include <asm/open_pic.h>
 #include <asm/mpc10x.h>
-#include <asm/ocp.h>
-
-/* The OCP structure is fixed by code below, before OCP initialises.
-   paddr depends on where the board places the EUMB.
-    - fixed in mpc10x_bridge_init().
-   irq depends on two things:
-    > does the board use the EPIC at all? (PCORE does not).
-    > is the EPIC in serial or parallel mode?
-    - fixed in mpc10x_set_openpic().
-*/
+#include <asm/ppc_sys.h>
 
 #ifdef CONFIG_MPC10X_OPENPIC
 #ifdef CONFIG_EPIC_SERIAL_MODE
 #define MPC10X_I2C_IRQ (EPIC_IRQ_BASE + NUM_8259_INTERRUPTS)
 #define MPC10X_DMA0_IRQ (EPIC_IRQ_BASE + 1 + NUM_8259_INTERRUPTS)
 #define MPC10X_DMA1_IRQ (EPIC_IRQ_BASE + 2 + NUM_8259_INTERRUPTS)
+#define MPC10X_UART0_IRQ (EPIC_IRQ_BASE + 4 + NUM_8259_INTERRUPTS)
 #else
-#define MPC10X_I2C_IRQ OCP_IRQ_NA
-#define MPC10X_DMA0_IRQ OCP_IRQ_NA
-#define MPC10X_DMA1_IRQ OCP_IRQ_NA
+#define MPC10X_I2C_IRQ -1
+#define MPC10X_DMA0_IRQ -1
+#define MPC10X_DMA1_IRQ -1
+#define MPC10X_UART0_IRQ -1
 #endif
 
-
-struct ocp_def core_ocp[] = {
-       { .vendor       = OCP_VENDOR_INVALID
-       }
+static struct fsl_i2c_platform_data mpc10x_i2c_pdata = {
+       .device_flags           = 0,
 };
 
-static struct ocp_fs_i2c_data mpc10x_i2c_data = {
-       .flags          = 0
+static struct plat_serial8250_port serial_platform_data[] = {
+       [0] = {
+               .mapbase        = 0x4500,
+               .iotype         = UPIO_MEM,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+       },
+       [1] = {
+               .mapbase        = 0x4600,
+               .iotype         = UPIO_MEM,
+               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+       },
+       { },
 };
-static struct ocp_def mpc10x_i2c_ocp = {
-       .vendor         = OCP_VENDOR_MOTOROLA,
-       .function       = OCP_FUNC_IIC,
-       .index          = 0,
-       .additions      = &mpc10x_i2c_data
+
+struct platform_device ppc_sys_platform_devices[] = {
+       [MPC10X_IIC1] = {
+               .name   = "fsl-i2c",
+               .id     = 1,
+               .dev.platform_data = &mpc10x_i2c_pdata,
+               .num_resources = 2,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = MPC10X_EUMB_I2C_OFFSET,
+                               .end    = MPC10X_EUMB_I2C_OFFSET +
+                                           MPC10X_EUMB_I2C_SIZE - 1,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .flags  = IORESOURCE_IRQ
+                       },
+               },
+       },
+       [MPC10X_DMA0] = {
+               .name   = "fsl-dma",
+               .id     = 0,
+               .num_resources = 2,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = MPC10X_EUMB_DMA_OFFSET + 0x10,
+                               .end    = MPC10X_EUMB_DMA_OFFSET + 0x1f,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .flags  = IORESOURCE_IRQ,
+                       },
+               },
+       },
+       [MPC10X_DMA1] = {
+               .name   = "fsl-dma",
+               .id     = 1,
+               .num_resources = 2,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = MPC10X_EUMB_DMA_OFFSET + 0x20,
+                               .end    = MPC10X_EUMB_DMA_OFFSET + 0x2f,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .flags  = IORESOURCE_IRQ,
+                       },
+               },
+       },
+       [MPC10X_DMA1] = {
+               .name   = "fsl-dma",
+               .id     = 1,
+               .num_resources = 2,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = MPC10X_EUMB_DMA_OFFSET + 0x20,
+                               .end    = MPC10X_EUMB_DMA_OFFSET + 0x2f,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .flags  = IORESOURCE_IRQ,
+                       },
+               },
+       },
+       [MPC10X_DUART] = {
+               .name = "serial8250",
+               .id     = 0,
+               .dev.platform_data = serial_platform_data,
+       },
 };
 
-static struct ocp_def mpc10x_dma_ocp[2] = {
-{      .vendor         = OCP_VENDOR_MOTOROLA,
-       .function       = OCP_FUNC_DMA,
-       .index          = 0 },
-{      .vendor         = OCP_VENDOR_MOTOROLA,
-       .function       = OCP_FUNC_DMA,
-       .index          = 1 }
+/* We use the PCI ID to match on */
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+       {
+               .ppc_sys_name   = "8245",
+               .mask           = 0xFFFFFFFF,
+               .value          = MPC10X_BRIDGE_8245,
+               .num_devices    = 4,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1, MPC10X_DUART,
+               },
+       },
+       {
+               .ppc_sys_name   = "8240",
+               .mask           = 0xFFFFFFFF,
+               .value          = MPC10X_BRIDGE_8240,
+               .num_devices    = 3,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1,
+               },
+       },
+       {
+               .ppc_sys_name   = "107",
+               .mask           = 0xFFFFFFFF,
+               .value          = MPC10X_BRIDGE_107,
+               .num_devices    = 3,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1,
+               },
+       },
+       {       /* default match */
+               .ppc_sys_name   = "",
+               .mask           = 0x00000000,
+               .value          = 0x00000000,
+       },
 };
 
 /* Set resources to match bridge memory map */
@@ -132,7 +231,7 @@ mpc10x_bridge_init(struct pci_controller *hose,
                   uint new_map,
                   uint phys_eumb_base)
 {
-       int     host_bridge, picr1, picr1_bit;
+       int     host_bridge, picr1, picr1_bit, i;
        ulong   pci_config_addr, pci_config_data;
        u_char  pir, byte;
 
@@ -273,7 +372,7 @@ mpc10x_bridge_init(struct pci_controller *hose,
                        printk("Host bridge in Agent mode\n");
                        /* Read or Set LMBAR & PCSRBAR? */
                }
-               
+
                /* Set base addr of the 8240/107 EUMB.  */
                early_write_config_dword(hose,
                                         0,
@@ -287,17 +386,6 @@ mpc10x_bridge_init(struct pci_controller *hose,
                        ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET,
                                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]);
        }
 
 #ifdef CONFIG_MPC10X_STORE_GATHERING
@@ -306,6 +394,29 @@ mpc10x_bridge_init(struct pci_controller *hose,
        mpc10x_disable_store_gathering(hose);
 #endif
 
+       /* setup platform devices for MPC10x bridges */
+       identify_ppc_sys_by_id (host_bridge);
+
+       for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
+               unsigned int dev_id = cur_ppc_sys_spec->device_list[i];
+               ppc_sys_fixup_mem_resource(&ppc_sys_platform_devices[dev_id],
+                       phys_eumb_base);
+       }
+
+       /* IRQ's are determined at runtime */
+       ppc_sys_platform_devices[MPC10X_IIC1].resource[1].start = MPC10X_I2C_IRQ;
+       ppc_sys_platform_devices[MPC10X_IIC1].resource[1].end = MPC10X_I2C_IRQ;
+       ppc_sys_platform_devices[MPC10X_DMA0].resource[1].start = MPC10X_DMA0_IRQ;
+       ppc_sys_platform_devices[MPC10X_DMA0].resource[1].end = MPC10X_DMA0_IRQ;
+       ppc_sys_platform_devices[MPC10X_DMA1].resource[1].start = MPC10X_DMA1_IRQ;
+       ppc_sys_platform_devices[MPC10X_DMA1].resource[1].end = MPC10X_DMA1_IRQ;
+
+       serial_platform_data[0].mapbase += phys_eumb_base;
+       serial_platform_data[0].irq = MPC10X_UART0_IRQ;
+
+       serial_platform_data[1].mapbase += phys_eumb_base;
+       serial_platform_data[1].irq = MPC10X_UART0_IRQ + 1;
+
        /*
         * 8240 erratum 26, 8241/8245 erratum 29, 107 erratum 23: speculative
         * PCI reads may return stale data so turn off.
@@ -330,7 +441,7 @@ mpc10x_bridge_init(struct pci_controller *hose,
         * 8245 (Rev 2., dated 10/2003) says PICR2[0] is reserverd.
         */
        if (host_bridge == MPC10X_BRIDGE_8245) {
-               ulong   picr2;
+               u32     picr2;
 
                early_read_config_dword(hose, 0, PCI_DEVFN(0,0),
                        MPC10X_CFG_PICR2_REG, &picr2);
@@ -504,6 +615,8 @@ void __init mpc10x_set_openpic(void)
        openpic_set_sources(EPIC_IRQ_BASE, 3, OpenPIC_Addr + 0x11020);
        /* Skip reserved space and map Message Unit Interrupt (I2O) */
        openpic_set_sources(EPIC_IRQ_BASE + 3, 1, OpenPIC_Addr + 0x110C0);
+       /* Skip reserved space and map Serial Interupts */
+       openpic_set_sources(EPIC_IRQ_BASE + 4, 2, OpenPIC_Addr + 0x11120);
 
        openpic_init(NUM_8259_INTERRUPTS);
 }
index 1e658ef57e75d7853ae59b557a5f054ca5a58467..8af322dd476a6467cda34d4983d1e589d46f21a4 100644 (file)
@@ -40,6 +40,42 @@ static struct gianfar_platform_data mpc85xx_tsec2_pdata = {
        .phy_reg_addr = MPC85xx_ENET1_OFFSET,
 };
 
+static struct gianfar_platform_data mpc85xx_etsec1_pdata = {
+       .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+           FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+           FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+           FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+           FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+       .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec2_pdata = {
+       .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+           FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+           FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+           FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+           FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+       .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec3_pdata = {
+       .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+           FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+           FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+           FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+           FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+       .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec4_pdata = {
+       .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+           FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+           FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+           FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+           FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+       .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
 static struct gianfar_platform_data mpc85xx_fec_pdata = {
        .phy_reg_addr = MPC85xx_ENET1_OFFSET,
 };
@@ -48,6 +84,10 @@ static struct fsl_i2c_platform_data mpc85xx_fsl_i2c_pdata = {
        .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
 };
 
+static struct fsl_i2c_platform_data mpc85xx_fsl_i2c2_pdata = {
+       .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
 static struct plat_serial8250_port serial_platform_data[] = {
        [0] = {
                .mapbase        = 0x4500,
@@ -281,7 +321,6 @@ struct platform_device ppc_sys_platform_devices[] = {
                        },
                },
        },
-#ifdef CONFIG_CPM2
        [MPC85xx_CPM_FCC1] = {
                .name = "fsl-cpm-fcc",
                .id     = 1,
@@ -535,7 +574,151 @@ struct platform_device ppc_sys_platform_devices[] = {
                        },
                },
        },
-#endif /* CONFIG_CPM2 */
+       [MPC85xx_eTSEC1] = {
+               .name = "fsl-gianfar",
+               .id     = 1,
+               .dev.platform_data = &mpc85xx_etsec1_pdata,
+               .num_resources   = 4,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = MPC85xx_ENET1_OFFSET,
+                               .end    = MPC85xx_ENET1_OFFSET +
+                                               MPC85xx_ENET1_SIZE - 1,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .name   = "tx",
+                               .start  = MPC85xx_IRQ_TSEC1_TX,
+                               .end    = MPC85xx_IRQ_TSEC1_TX,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+                       {
+                               .name   = "rx",
+                               .start  = MPC85xx_IRQ_TSEC1_RX,
+                               .end    = MPC85xx_IRQ_TSEC1_RX,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+                       {
+                               .name   = "error",
+                               .start  = MPC85xx_IRQ_TSEC1_ERROR,
+                               .end    = MPC85xx_IRQ_TSEC1_ERROR,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+               },
+       },
+       [MPC85xx_eTSEC2] = {
+               .name = "fsl-gianfar",
+               .id     = 2,
+               .dev.platform_data = &mpc85xx_etsec2_pdata,
+               .num_resources   = 4,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = MPC85xx_ENET2_OFFSET,
+                               .end    = MPC85xx_ENET2_OFFSET +
+                                               MPC85xx_ENET2_SIZE - 1,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .name   = "tx",
+                               .start  = MPC85xx_IRQ_TSEC2_TX,
+                               .end    = MPC85xx_IRQ_TSEC2_TX,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+                       {
+                               .name   = "rx",
+                               .start  = MPC85xx_IRQ_TSEC2_RX,
+                               .end    = MPC85xx_IRQ_TSEC2_RX,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+                       {
+                               .name   = "error",
+                               .start  = MPC85xx_IRQ_TSEC2_ERROR,
+                               .end    = MPC85xx_IRQ_TSEC2_ERROR,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+               },
+       },
+       [MPC85xx_eTSEC3] = {
+               .name = "fsl-gianfar",
+               .id     = 3,
+               .dev.platform_data = &mpc85xx_etsec3_pdata,
+               .num_resources   = 4,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = MPC85xx_ENET3_OFFSET,
+                               .end    = MPC85xx_ENET3_OFFSET +
+                                               MPC85xx_ENET3_SIZE - 1,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .name   = "tx",
+                               .start  = MPC85xx_IRQ_TSEC3_TX,
+                               .end    = MPC85xx_IRQ_TSEC3_TX,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+                       {
+                               .name   = "rx",
+                               .start  = MPC85xx_IRQ_TSEC3_RX,
+                               .end    = MPC85xx_IRQ_TSEC3_RX,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+                       {
+                               .name   = "error",
+                               .start  = MPC85xx_IRQ_TSEC3_ERROR,
+                               .end    = MPC85xx_IRQ_TSEC3_ERROR,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+               },
+       },
+       [MPC85xx_eTSEC4] = {
+               .name = "fsl-gianfar",
+               .id     = 4,
+               .dev.platform_data = &mpc85xx_etsec4_pdata,
+               .num_resources   = 4,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = 0x27000,
+                               .end    = 0x27fff,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .name   = "tx",
+                               .start  = MPC85xx_IRQ_TSEC4_TX,
+                               .end    = MPC85xx_IRQ_TSEC4_TX,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+                       {
+                               .name   = "rx",
+                               .start  = MPC85xx_IRQ_TSEC4_RX,
+                               .end    = MPC85xx_IRQ_TSEC4_RX,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+                       {
+                               .name   = "error",
+                               .start  = MPC85xx_IRQ_TSEC4_ERROR,
+                               .end    = MPC85xx_IRQ_TSEC4_ERROR,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+               },
+       },
+       [MPC85xx_IIC2] = {
+               .name = "fsl-i2c",
+               .id     = 2,
+               .dev.platform_data = &mpc85xx_fsl_i2c2_pdata,
+               .num_resources   = 2,
+               .resource = (struct resource[]) {
+                       {
+                               .start  = 0x03100,
+                               .end    = 0x031ff,
+                               .flags  = IORESOURCE_MEM,
+                       },
+                       {
+                               .start  = MPC85xx_IRQ_IIC1,
+                               .end    = MPC85xx_IRQ_IIC1,
+                               .flags  = IORESOURCE_IRQ,
+                       },
+               },
+       },
 };
 
 static int __init mach_mpc85xx_fixup(struct platform_device *pdev)
index d806a92a9401bedbb9a8083470b4456b948dd248..6e3184ab354f4da230f362d471564f4979c9ef45 100644 (file)
@@ -110,6 +110,111 @@ struct ppc_sys_spec ppc_sys_specs[] = {
                        MPC85xx_CPM_USB,
                },
        },
+       /* SVRs on 8548 rev1.0 matches for 8548/8547/8545 */
+       {
+               .ppc_sys_name   = "8548E",
+               .mask           = 0xFFFF00F0,
+               .value          = 0x80390010,
+               .num_devices    = 13,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+                       MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+                       MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+                       MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+               },
+       },
+       {
+               .ppc_sys_name   = "8548",
+               .mask           = 0xFFFF00F0,
+               .value          = 0x80310010,
+               .num_devices    = 12,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+                       MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+                       MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+                       MPC85xx_PERFMON, MPC85xx_DUART,
+               },
+       },
+       {
+               .ppc_sys_name   = "8547E",
+               .mask           = 0xFFFF00F0,
+               .value          = 0x80390010,
+               .num_devices    = 13,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+                       MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+                       MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+                       MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+               },
+       },
+       {
+               .ppc_sys_name   = "8547",
+               .mask           = 0xFFFF00F0,
+               .value          = 0x80310010,
+               .num_devices    = 12,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+                       MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+                       MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+                       MPC85xx_PERFMON, MPC85xx_DUART,
+               },
+       },
+       {
+               .ppc_sys_name   = "8545E",
+               .mask           = 0xFFFF00F0,
+               .value          = 0x80390010,
+               .num_devices    = 11,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+                       MPC85xx_IIC1, MPC85xx_IIC2,
+                       MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+                       MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+               },
+       },
+       {
+               .ppc_sys_name   = "8545",
+               .mask           = 0xFFFF00F0,
+               .value          = 0x80310010,
+               .num_devices    = 10,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+                       MPC85xx_IIC1, MPC85xx_IIC2,
+                       MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+                       MPC85xx_PERFMON, MPC85xx_DUART,
+               },
+       },
+       {
+               .ppc_sys_name   = "8543E",
+               .mask           = 0xFFFF00F0,
+               .value          = 0x803A0010,
+               .num_devices    = 11,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+                       MPC85xx_IIC1, MPC85xx_IIC2,
+                       MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+                       MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+               },
+       },
+       {
+               .ppc_sys_name   = "8543",
+               .mask           = 0xFFFF00F0,
+               .value          = 0x80320010,
+               .num_devices    = 10,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+                       MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+                       MPC85xx_IIC1, MPC85xx_IIC2,
+                       MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+                       MPC85xx_PERFMON, MPC85xx_DUART,
+               },
+       },
        {       /* default match */
                .ppc_sys_name   = "",
                .mask           = 0x00000000,
index 000ba47c67cbacd5b1bde36148c2fe0328e9db04..b45d8268bf93e84619b1d44382d19688d11aa204 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/signal.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
index ea26da0d8b6b2353d2bd580320744ae8b076b2f0..7e272c51a4973e17e3deab27cb1f1754e086cfc7 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/signal.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
diff --git a/arch/ppc/syslib/ppc4xx_kgdb.c b/arch/ppc/syslib/ppc4xx_kgdb.c
deleted file mode 100644 (file)
index fe8668b..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#include <linux/config.h>
-#include <linux/types.h>
-#include <asm/ibm4xx.h>
-#include <linux/kernel.h>
-
-
-
-#define LSR_DR         0x01 /* Data ready */
-#define LSR_OE         0x02 /* Overrun */
-#define LSR_PE         0x04 /* Parity error */
-#define LSR_FE         0x08 /* Framing error */
-#define LSR_BI         0x10 /* Break */
-#define LSR_THRE       0x20 /* Xmit holding register empty */
-#define LSR_TEMT       0x40 /* Xmitter empty */
-#define LSR_ERR                0x80 /* Error */
-
-#include <platforms/4xx/ibm_ocp.h>
-
-extern struct NS16550* COM_PORTS[];
-#ifndef NULL
-#define NULL 0x00
-#endif
-
-static volatile struct NS16550 *kgdb_debugport = NULL;
-
-volatile struct NS16550 *
-NS16550_init(int chan)
-{
-       volatile struct NS16550 *com_port;
-       int quot;
-#ifdef BASE_BAUD
-       quot = BASE_BAUD / 9600;
-#else
-       quot = 0x000c; /* 0xc = 9600 baud (on a pc) */
-#endif
-
-       com_port = (struct NS16550 *) COM_PORTS[chan];
-
-       com_port->lcr = 0x00;
-       com_port->ier = 0xFF;
-       com_port->ier = 0x00;
-       com_port->lcr = com_port->lcr | 0x80; /* Access baud rate */
-       com_port->dll = ( quot & 0x00ff ); /* 0xc = 9600 baud */
-       com_port->dlm = ( quot & 0xff00 ) >> 8;
-       com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */
-       com_port->mcr = 0x00; /* RTS/DTR */
-       com_port->fcr = 0x07; /* Clear & enable FIFOs */
-
-       return( com_port );
-}
-
-
-void
-NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
-{
-       while ((com_port->lsr & LSR_THRE) == 0)
-               ;
-       com_port->thr = c;
-       return;
-}
-
-unsigned char
-NS16550_getc(volatile struct NS16550 *com_port)
-{
-       while ((com_port->lsr & LSR_DR) == 0)
-               ;
-       return (com_port->rbr);
-}
-
-unsigned char
-NS16550_tstc(volatile struct NS16550 *com_port)
-{
-       return ((com_port->lsr & LSR_DR) != 0);
-}
-
-
-#if defined(CONFIG_KGDB_TTYS0)
-#define KGDB_PORT 0
-#elif defined(CONFIG_KGDB_TTYS1)
-#define KGDB_PORT 1
-#elif defined(CONFIG_KGDB_TTYS2)
-#define KGDB_PORT 2
-#elif defined(CONFIG_KGDB_TTYS3)
-#define KGDB_PORT 3
-#else
-#error "invalid kgdb_tty port"
-#endif
-
-void putDebugChar( unsigned char c )
-{
-       if ( kgdb_debugport == NULL )
-               kgdb_debugport = NS16550_init(KGDB_PORT);
-       NS16550_putc( kgdb_debugport, c );
-}
-
-int getDebugChar( void )
-{
-       if (kgdb_debugport == NULL)
-               kgdb_debugport = NS16550_init(KGDB_PORT);
-
-       return(NS16550_getc(kgdb_debugport));
-}
-
-void kgdb_interruptible(int enable)
-{
-       return;
-}
-
-void putDebugString(char* str)
-{
-       while (*str != '\0') {
-               putDebugChar(*str);
-               str++;
-       }
-       putDebugChar('\r');
-       return;
-}
-
-void
-kgdb_map_scc(void)
-{
-       printk("kgdb init \n");
-       kgdb_debugport = NS16550_init(KGDB_PORT);
-}
index 843cf8873e60f35376b80e2cda72839ee99fb35a..602a86891f7fd826cf7b38ab92a899d23f21dc4d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 
-#include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/mpc83xx.h>
 #include <asm/mmu.h>
index f3277f469e78a2695422189e4a28ba5124878ccd..ca95d79a704e56a8c94de8c645e95852940e3996 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 
-#include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/mpc85xx.h>
 #include <asm/immap_85xx.h>
@@ -33,6 +32,8 @@
 
 #include <syslib/ppc85xx_setup.h>
 
+extern void abort(void);
+
 /* Return the amount of memory */
 unsigned long __init
 mpc85xx_find_end_of_memory(void)
@@ -133,7 +134,7 @@ mpc85xx_halt(void)
 
 #ifdef CONFIG_PCI
 
-#if defined(CONFIG_MPC8555_CDS)
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
 extern void mpc85xx_cds_enable_via(struct pci_controller *hose);
 extern void mpc85xx_cds_fixup_via(struct pci_controller *hose);
 #endif
@@ -308,14 +309,14 @@ mpc85xx_setup_hose(void)
 
        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 
-#if defined(CONFIG_MPC8555_CDS)
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
        /* Pre pciauto_bus_scan VIA init */
        mpc85xx_cds_enable_via(hose_a);
 #endif
 
        hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
 
-#if defined(CONFIG_MPC8555_CDS)
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
        /* Post pciauto_bus_scan VIA fixup */
        mpc85xx_cds_fixup_via(hose_a);
 #endif
index 8565f49b8b0b879fc0c743c6a7a4f69dbb6e94dc..be7869e394651eea0647e0234ef08798e6b33488 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
+#include <linux/kallsyms.h>
 #include <asm/ptrace.h>
 #include <asm/string.h>
 #include <asm/prom.h>
@@ -93,8 +94,7 @@ static void take_input(char *);
 static unsigned read_spr(int);
 static void write_spr(int, unsigned);
 static void super_regs(void);
-static void print_sysmap(void);
-static void sysmap_lookup(void);
+static void symbol_lookup(void);
 static void remove_bpts(void);
 static void insert_bpts(void);
 static struct bpt *at_breakpoint(unsigned pc);
@@ -103,7 +103,6 @@ static void cacheflush(void);
 #ifdef CONFIG_SMP
 static void cpu_cmd(void);
 #endif /* CONFIG_SMP */
-static int pretty_print_addr(unsigned long addr);
 static void csum(void);
 #ifdef CONFIG_BOOTX_TEXT
 static void vidcmds(void);
@@ -120,8 +119,6 @@ extern void longjmp(u_int *, int);
 
 extern void xmon_enter(void);
 extern void xmon_leave(void);
-extern char* xmon_find_symbol(unsigned long addr, unsigned long* saddr);
-extern unsigned long xmon_symbol_to_addr(char* symbol);
 
 static unsigned start_tb[NR_CPUS][2];
 static unsigned stop_tb[NR_CPUS][2];
@@ -148,7 +145,6 @@ Commands:\n\
   mm   move a block of memory\n\
   ms   set a block of memory\n\
   md   compare two blocks of memory\n\
-  M    print System.map\n\
   r    print registers\n\
   S    print special registers\n\
   t    print backtrace\n\
@@ -175,6 +171,35 @@ extern inline void __delay(unsigned int loops)
                                     "r" (loops) : "ctr");
 }
 
+/* Print an address in numeric and symbolic form (if possible) */
+static void xmon_print_symbol(unsigned long address, const char *mid,
+                             const char *after)
+{
+       char *modname;
+       const char *name = NULL;
+       unsigned long offset, size;
+       static char tmpstr[128];
+
+       printf("%.8lx", address);
+       if (setjmp(bus_error_jmp) == 0) {
+               debugger_fault_handler = handle_fault;
+               sync();
+               name = kallsyms_lookup(address, &size, &offset, &modname,
+                                      tmpstr);
+               sync();
+               /* wait a little while to see if we get a machine check */
+               __delay(200);
+       }
+       debugger_fault_handler = NULL;
+
+       if (name) {
+               printf("%s%s+%#lx/%#lx", mid, name, offset, size);
+               if (modname)
+                       printf(" [%s]", modname);
+       }
+       printf("%s", after);
+}
+
 static void get_tb(unsigned *p)
 {
        unsigned hi, lo, hiagain;
@@ -454,7 +479,7 @@ cmds(struct pt_regs *excp)
                        dump();
                        break;
                case 'l':
-                       sysmap_lookup();
+                       symbol_lookup();
                        break;
                case 'r':
                        if (excp != NULL)
@@ -466,9 +491,6 @@ cmds(struct pt_regs *excp)
                        else
                                excprint(excp);
                        break;
-               case 'M':
-                       print_sysmap();
-                       break;
                case 'S':
                        super_regs();
                        break;
@@ -825,20 +847,19 @@ backtrace(struct pt_regs *excp)
        for (; sp != 0; sp = stack[0]) {
                if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
                        break;
-               pretty_print_addr(stack[1]);
-               printf(" ");
+               printf("[%.8lx] ", stack);
+               xmon_print_symbol(stack[1], " ", "\n");
                if (stack[1] == (unsigned) &ret_from_except
                    || stack[1] == (unsigned) &ret_from_except_full
                    || stack[1] == (unsigned) &ret_from_syscall) {
                        if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
                                break;
-                       printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
+                       printf("exception:%x [%x] %x\n", regs.trap, sp+16,
                               regs.nip);
                        sp = regs.gpr[1];
                        if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
                                break;
                }
-               printf("\n");
        }
 }
 
@@ -859,11 +880,10 @@ excprint(struct pt_regs *fp)
 #ifdef CONFIG_SMP
        printf("cpu %d: ", smp_processor_id());
 #endif /* CONFIG_SMP */
-       printf("vector: %x at pc = ", fp->trap);
-       pretty_print_addr(fp->nip);
-       printf(", lr = ");
-       pretty_print_addr(fp->link);
-       printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
+       printf("vector: %x at pc=", fp->trap);
+       xmon_print_symbol(fp->nip, ": ", ", lr=");
+       xmon_print_symbol(fp->link, ": ", "\n");
+       printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
        trap = TRAP(fp);
        if (trap == 0x300 || trap == 0x600)
                printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
@@ -950,24 +970,6 @@ static unsigned int regno;
 extern char exc_prolog;
 extern char dec_exc;
 
-void
-print_sysmap(void)
-{
-       extern char *sysmap;
-       if ( sysmap ) {
-               printf("System.map: \n");
-               if( setjmp(bus_error_jmp) == 0 ) {
-                       debugger_fault_handler = handle_fault;
-                       sync();
-                       xmon_puts(sysmap);
-                       sync();
-               }
-               debugger_fault_handler = NULL;
-       }
-       else
-               printf("No System.map\n");
-}
-
 void
 super_regs(void)
 {
@@ -1738,7 +1740,7 @@ scanhex(unsigned *vp)
                printf("invalid register name '%%%s'\n", regname);
                return 0;
        } else if (c == '$') {
-               static char symname[64];
+               static char symname[128];
                int i;
                for (i=0; i<63; i++) {
                        c = inchar();
@@ -1749,7 +1751,14 @@ scanhex(unsigned *vp)
                        symname[i] = c;
                }
                symname[i++] = 0;
-               *vp = xmon_symbol_to_addr(symname);
+               *vp = 0;
+               if (setjmp(bus_error_jmp) == 0) {
+                       debugger_fault_handler = handle_fault;
+                       sync();
+                       *vp = kallsyms_lookup_name(symname);
+                       sync();
+               }
+               debugger_fault_handler = NULL;
                if (!(*vp)) {
                        printf("unknown symbol\n");
                        return 0;
@@ -1840,169 +1849,34 @@ take_input(char *str)
        lineptr = str;
 }
 
-void
-sysmap_lookup(void)
+static void
+symbol_lookup(void)
 {
        int type = inchar();
        unsigned addr;
-       static char tmp[64];
-       char* cur;
-
-       extern char *sysmap;
-       extern unsigned long sysmap_size;
-       if ( !sysmap || !sysmap_size )
-               return;
-
-       switch(type) {
-               case 'a':
-                       if (scanhex(&addr)) {
-                               pretty_print_addr(addr);
-                               printf("\n");
-                       }
-                       termch = 0;
-                       break;
-               case 's':
-                       getstring(tmp, 64);
-                       if( setjmp(bus_error_jmp) == 0 ) {
-                               debugger_fault_handler = handle_fault;
-                               sync();
-                               cur = sysmap;
-                               do {
-                                       cur = strstr(cur, tmp);
-                                       if (cur) {
-                                               static char res[64];
-                                               char *p, *d;
-                                               p = cur;
-                                               while(p > sysmap && *p != 10)
-                                                       p--;
-                                               if (*p == 10) p++;
-                                               d = res;
-                                               while(*p && p < (sysmap + sysmap_size) && *p != 10)
-                                                       *(d++) = *(p++);
-                                               *(d++) = 0;
-                                               printf("%s\n", res);
-                                               cur++;
-                                       }
-                               } while (cur);
-                               sync();
-                       }
-                       debugger_fault_handler = NULL;
-                       termch = 0;
-                       break;
-       }
-}
+       static char tmp[128];
 
-static int
-pretty_print_addr(unsigned long addr)
-{
-       char *sym;
-       unsigned long saddr;
-       
-       printf("%08x", addr);
-       sym = xmon_find_symbol(addr, &saddr);
-       if (sym)
-               printf(" (%s+0x%x)", sym, addr-saddr);
-       return (sym != 0);
-}
-
-char*
-xmon_find_symbol(unsigned long addr, unsigned long* saddr)
-{
-       static char rbuffer[64];
-       char *p, *ep, *limit;
-       unsigned long prev, next;
-       char* psym;
-
-       extern char *sysmap;
-       extern unsigned long sysmap_size;
-       if ( !sysmap || !sysmap_size )
-               return NULL;
-       
-       prev = 0;
-       psym = NULL;
-       p = sysmap;
-       limit = p + sysmap_size;
-       if( setjmp(bus_error_jmp) == 0 ) {
-               debugger_fault_handler = handle_fault;
-               sync();
-               do {
-                       next = simple_strtoul(p, &p, 16);
-                       if (next > addr && prev <= addr) {
-                               if (!psym)
-                                       goto bail;
-                               ep = rbuffer;
-                               p = psym;
-                               while(*p && p < limit && *p == 32)
-                                       p++;
-                               while(*p && p < limit && *p != 10 && (ep - rbuffer) < 63)
-                                       *(ep++) = *(p++);
-                               *(ep++) = 0;
-                               if (saddr)
-                                       *saddr = prev;
-                               debugger_fault_handler = NULL;
-                               return rbuffer;
-                       }
-                       prev = next;
-                       psym = p;
-                       while(*p && p < limit && *p != 10)
-                               p++;
-                       if (*p) p++;
-               } while(*p && p < limit && next);
-bail:
-               sync();
+       switch (type) {
+       case 'a':
+               if (scanhex(&addr))
+                       xmon_print_symbol(addr, ": ", "\n");
+               termch = 0;
+               break;
+       case 's':
+               getstring(tmp, 64);
+               if (setjmp(bus_error_jmp) == 0) {
+                       debugger_fault_handler = handle_fault;
+                       sync();
+                       addr = kallsyms_lookup_name(tmp);
+                       if (addr)
+                               printf("%s: %lx\n", tmp, addr);
+                       else
+                               printf("Symbol '%s' not found.\n", tmp);
+                       sync();
+               }
+               debugger_fault_handler = NULL;
+               termch = 0;
+               break;
        }
-       debugger_fault_handler = NULL;
-       return NULL;
 }
 
-unsigned long
-xmon_symbol_to_addr(char* symbol)
-{
-       char *p, *cur;
-       char *match = NULL;
-       int goodness = 0;
-       int result = 0;
-       
-       extern char *sysmap;
-       extern unsigned long sysmap_size;
-       if ( !sysmap || !sysmap_size )
-               return 0;
-
-       if( setjmp(bus_error_jmp) == 0 ) {
-               debugger_fault_handler = handle_fault;
-               sync();
-               cur = sysmap;
-               while(cur) {
-                       cur = strstr(cur, symbol);
-                       if (cur) {
-                               int gd = 1;
-
-                               /* best match if equal, better match if
-                                * begins with
-                                */
-                               if (cur == sysmap || *(cur-1) == ' ') {
-                                       gd++;
-                                       if (cur[strlen(symbol)] == 10)
-                                               gd++;
-                               }
-                               if (gd > goodness) {
-                                       match = cur;
-                                       goodness = gd;
-                                       if (gd == 3)
-                                               break;
-                               }
-                               cur++;
-                       }
-               }       
-               if (goodness) {
-                       p = match;
-                       while(p > sysmap && *p != 10)
-                               p--;
-                       if (*p == 10) p++;
-                       result = simple_strtoul(p, &p, 16);
-               }
-               sync();
-       }
-       debugger_fault_handler = NULL;
-       return result;
-}              
index 5cb343883e4d88649f8e8eaad39c67e856027d1e..0f1fa289744eaf8446a3c5d563e89611b9bfab24 100644 (file)
@@ -323,7 +323,7 @@ config EISA
        bool
 
 config PCI
-       bool
+       bool "support for PCI devices" if (EMBEDDED && PPC_ISERIES)
        default y
        help
          Find out whether your system includes a PCI bus. PCI is the name of
index 691f3008e69870d474fd45934edebc2b1a5eab11..33c752ceca4b963688d0133c002ad39cd9feff2c 100644 (file)
@@ -35,9 +35,9 @@ CROSS32AS     := $(AS) -a32
 CROSS32LD      := $(LD) -m elf32ppc
 CROSS32OBJCOPY := $(OBJCOPY)
 endif
-AS              := $(AS) -a64
-LD              := $(LD) -m elf64ppc
-CC             := $(CC) -m64
+override AS    += -a64
+override LD    += -m elf64ppc
+override CC    += -m64
 endif
 
 export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY
index f8f19637f73f1fa9e0ecc514989c4e005c2c9b77..90032b138902e560a7e28c6df668dbae4f681bd7 100644 (file)
@@ -12,7 +12,7 @@
 #include <asm/system.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItLpNaca.h>
 
 /* Array of LpEvent handler functions */
 LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
index c923a815760ec50f2b478f7f2857e175a0b0575a..cdea00d7707f641e0dcabc4559ce90de101052ba 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/LparData.h>
 
 static __inline__ int set_inUse( struct ItLpQueue * lpQueue )
 {
index 96d90b0c5119ea6cb11a332e1b47f2b63bb60ded..b5e167cf1a05e4a70428d00aed14bc090d6cf47b 100644 (file)
@@ -16,14 +16,13 @@ obj-y += vdso32/ vdso64/
 
 obj-$(CONFIG_PPC_OF) +=        of_device.o
 
-pci-obj-$(CONFIG_PPC_ISERIES)  += iSeries_pci.o iSeries_pci_reset.o
+pci-obj-$(CONFIG_PPC_ISERIES)  += iSeries_pci.o iSeries_irq.o \
+                               iSeries_VpdInfo.o
 pci-obj-$(CONFIG_PPC_MULTIPLATFORM)    += pci_dn.o pci_direct_iommu.o
 
 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 \
+obj-$(CONFIG_PPC_ISERIES) += 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
diff --git a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c
deleted file mode 100644 (file)
index 809c9bc..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001.
- *
- * This module handles PCI interrupt events sent by the iSeries Hypervisor.
-*/
-
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/bootmem.h>
-#include <linux/ide.h>
-
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/XmPciLpEvent.h>
-#include <asm/ppcdebug.h>
-
-static long Pci_Interrupt_Count;
-static long Pci_Event_Count;
-
-enum XmPciLpEvent_Subtype {
-       XmPciLpEvent_BusCreated    = 0,         // PHB has been created
-       XmPciLpEvent_BusError      = 1,         // PHB has failed
-       XmPciLpEvent_BusFailed     = 2,         // Msg to Secondary, Primary failed bus
-       XmPciLpEvent_NodeFailed    = 4,         // Multi-adapter bridge has failed
-       XmPciLpEvent_NodeRecovered = 5,         // Multi-adapter bridge has recovered
-       XmPciLpEvent_BusRecovered  = 12,        // PHB has been recovered
-       XmPciLpEvent_UnQuiesceBus  = 18,        // Secondary bus unqiescing
-       XmPciLpEvent_BridgeError   = 21,        // Bridge Error
-       XmPciLpEvent_SlotInterrupt = 22         // Slot interrupt
-};
-
-struct XmPciLpEvent_BusInterrupt {
-       HvBusNumber     busNumber;
-       HvSubBusNumber  subBusNumber;
-};
-
-struct XmPciLpEvent_NodeInterrupt {
-       HvBusNumber     busNumber;
-       HvSubBusNumber  subBusNumber;
-       HvAgentId       deviceId;
-};
-
-struct XmPciLpEvent {
-       struct HvLpEvent hvLpEvent;
-
-       union {
-               u64 alignData;                  // Align on an 8-byte boundary
-
-               struct {
-                       u32             fisr;
-                       HvBusNumber     busNumber;
-                       HvSubBusNumber  subBusNumber;
-                       HvAgentId       deviceId;
-               } slotInterrupt;
-
-               struct XmPciLpEvent_BusInterrupt busFailed;
-               struct XmPciLpEvent_BusInterrupt busRecovered;
-               struct XmPciLpEvent_BusInterrupt busCreated;
-
-               struct XmPciLpEvent_NodeInterrupt nodeFailed;
-               struct XmPciLpEvent_NodeInterrupt nodeRecovered;
-
-       } eventData;
-
-};
-
-static void intReceived(struct XmPciLpEvent *eventParm,
-               struct pt_regs *regsParm);
-
-static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
-               struct pt_regs *regsParm)
-{
-#ifdef CONFIG_PCI
-#if 0
-       PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n",
-                       eventParm->xType);
-#endif
-       ++Pci_Event_Count;
-
-       if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
-               switch (eventParm->xFlags.xFunction) {
-               case HvLpEvent_Function_Int:
-                       intReceived((struct XmPciLpEvent *)eventParm, regsParm);
-                       break;
-               case HvLpEvent_Function_Ack:
-                       printk(KERN_ERR
-                               "XmPciLpEvent.c: unexpected ack received\n");
-                       break;
-               default:
-                       printk(KERN_ERR
-                               "XmPciLpEvent.c: unexpected event function %d\n",
-                               (int)eventParm->xFlags.xFunction);
-                       break;
-               }
-       } else if (eventParm)
-               printk(KERN_ERR
-                       "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",
-                       (int)eventParm->xType);
-       else
-               printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
-#endif
-}
-
-static void intReceived(struct XmPciLpEvent *eventParm,
-               struct pt_regs *regsParm)
-{
-       int irq;
-
-       ++Pci_Interrupt_Count;
-#if 0
-       PPCDBG(PPCDBG_BUSWALK, "PCI: XmPciLpEvent.c: intReceived\n");
-#endif
-
-       switch (eventParm->hvLpEvent.xSubtype) {
-       case XmPciLpEvent_SlotInterrupt:
-               irq = eventParm->hvLpEvent.xCorrelationToken;
-               /* Dispatch the interrupt handlers for this irq */
-               ppc_irq_dispatch_handler(regsParm, irq);
-               HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
-                       eventParm->eventData.slotInterrupt.subBusNumber,
-                       eventParm->eventData.slotInterrupt.deviceId);
-               break;
-               /* Ignore error recovery events for now */
-       case XmPciLpEvent_BusCreated:
-               printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n",
-                       eventParm->eventData.busCreated.busNumber);
-               break;
-       case XmPciLpEvent_BusError:
-       case XmPciLpEvent_BusFailed:
-               printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n",
-                       eventParm->eventData.busFailed.busNumber);
-               break;
-       case XmPciLpEvent_BusRecovered:
-       case XmPciLpEvent_UnQuiesceBus:
-               printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n",
-                       eventParm->eventData.busRecovered.busNumber);
-               break;
-       case XmPciLpEvent_NodeFailed:
-       case XmPciLpEvent_BridgeError:
-               printk(KERN_INFO
-                       "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n",
-                       eventParm->eventData.nodeFailed.busNumber,
-                       eventParm->eventData.nodeFailed.subBusNumber,
-                       eventParm->eventData.nodeFailed.deviceId);
-               break;
-       case XmPciLpEvent_NodeRecovered:
-               printk(KERN_INFO
-                       "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n",
-                       eventParm->eventData.nodeRecovered.busNumber,
-                       eventParm->eventData.nodeRecovered.subBusNumber,
-                       eventParm->eventData.nodeRecovered.deviceId);
-               break;
-       default:
-               printk(KERN_ERR
-                       "XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
-                       eventParm->hvLpEvent.xSubtype);
-               break;
-       }
-}
-
-
-/* This should be called sometime prior to buswalk (init_IRQ would be good) */
-int XmPciLpEvent_init()
-{
-       int xRc;
-
-       PPCDBG(PPCDBG_BUSWALK,
-                       "XmPciLpEvent_init, Register Event type 0x%04X\n",
-                       HvLpEvent_Type_PciIo);
-
-       xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
-                       &XmPciLpEvent_handler);
-       if (xRc == 0) {
-               xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
-               if (xRc != 0)
-                       printk(KERN_ERR
-                               "XmPciLpEvent.c: open event path failed with rc 0x%x\n",
-                               xRc);
-       } else
-               printk(KERN_ERR
-                       "XmPciLpEvent.c: register handler failed with rc 0x%x\n",
-                       xRc);
-       return xRc;
-}
index 0094ac79a18c68d0935104092554877912292caf..abb9e5b5da03b81aa42c88b2ad635f7d1cc00914 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <asm/paca.h>
 #include <asm/lppaca.h>
-#include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/rtas.h>
 #include <asm/cputable.h>
index ce714c9271344f6f1e7df5ca71bb903928f16d5f..4da8e31b2b61da90c4bd93b49d630687049ad5d4 100644 (file)
 
 static struct dma_mapping_ops *get_dma_ops(struct device *dev)
 {
+#ifdef CONFIG_PCI
        if (dev->bus == &pci_bus_type)
                return &pci_dma_ops;
+#endif
 #ifdef CONFIG_IBMVIO
        if (dev->bus == &vio_bus_type)
                return &vio_dma_ops;
@@ -37,8 +39,10 @@ EXPORT_SYMBOL(dma_supported);
 
 int dma_set_mask(struct device *dev, u64 dma_mask)
 {
+#ifdef CONFIG_PCI
        if (dev->bus == &pci_bus_type)
                return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
+#endif
 #ifdef CONFIG_IBMVIO
        if (dev->bus == &vio_bus_type)
                return -EIO;
index d63d41f3eecf788b6107269d36df2097075a637f..af5272fedadf4d8f4a2705edd735479dd9d96751 100644 (file)
@@ -505,7 +505,7 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
        pte_t *ptep;
        unsigned long pa;
 
-       ptep = find_linux_pte(ioremap_mm.pgd, token);
+       ptep = find_linux_pte(init_mm.pgd, token);
        if (!ptep)
                return token;
        pa = pte_pfn(*ptep) << PAGE_SHIFT;
index 346dbf606b5dd910e1a3609d315d96a1a830fa00..02c8f4e3e4bc644f66dbdde07b31544d9063266b 100644 (file)
@@ -2121,10 +2121,6 @@ empty_zero_page:
 swapper_pg_dir:
        .space  4096
 
-       .globl  ioremap_dir
-ioremap_dir:
-       .space  4096
-
 #ifdef CONFIG_SMP
 /* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */
        .globl  stab_array
index a6f0ff2d023927f58b7282f7506168bc06d39bd0..d11c732daf816a2a7bed18c58e0a20fa52439c0e 100644 (file)
@@ -1,31 +1,31 @@
-/************************************************************************/
-/* File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb  2 2001. */
-/************************************************************************/
-/* This code gets the card location of the hardware                     */
-/* Copyright (C) 20yy  <Allan H Trautman> <IBM Corp>                    */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created, Feb 2, 2001                                               */
-/*   Ported to ppc64, August 20, 2001                                   */
-/* End Change Activity                                                  */
-/************************************************************************/
-#include <linux/config.h>
+/*
+ * File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb  2 2001.
+ *
+ * This code gets the card location of the hardware
+ * Copyright (C) 2001  <Allan H Trautman> <IBM Corp>
+ * Copyright (C) 2005  Stephen Rothwel, IBM Corp
+ *
+ * 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
+ *
+ * Change Activity:
+ *   Created, Feb 2, 2001
+ *   Ported to ppc64, August 20, 2001
+ * End Change Activity
+ */
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/mf.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/iSeries_pci.h>
-#include "pci.h"
 
 /*
  * Size of Bus VPD data
  */
 #define BUS_VPDSIZE      1024
+
 /*
  * Bus Vpd Tags
  */
-#define  VpdEndOfDataTag   0x78
 #define  VpdEndOfAreaTag   0x79
 #define  VpdIdStringTag    0x82
 #define  VpdVendorAreaTag  0x84
+
 /*
  * Mfg Area Tags
  */
-#define  VpdFruFlag       0x4647     // "FG"
 #define  VpdFruFrameId    0x4649     // "FI"
 #define  VpdSlotMapFormat 0x4D46     // "MF"
-#define  VpdAsmPartNumber 0x504E     // "PN"
-#define  VpdFruSerial     0x534E     // "SN"
 #define  VpdSlotMap       0x534D     // "SM"
 
 /*
@@ -79,74 +74,33 @@ struct SlotMapStruct {
        char CardLocation[3];
        char Parms[8];
        char Reserved[2];
-}; 
+};
 typedef struct SlotMapStruct SlotMap;
 #define SLOT_ENTRY_SIZE   16
 
-/*
- * Formats the device information.
- * - Pass in pci_dev* pointer to the device.
- * - Pass in buffer to place the data.  Danger here is the buffer must
- *   be as big as the client says it is.   Should be at least 128 bytes.
- * Return will the length of the string data put in the buffer.
- * Format:
- * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
- * controller
- */
-int iSeries_Device_Information(struct pci_dev *PciDev, char *buffer,
-               int BufferSize)
-{
-       struct iSeries_Device_Node *DevNode =
-               (struct iSeries_Device_Node *)PciDev->sysdata;
-       int len;
-
-       if (DevNode == NULL)
-               return sprintf(buffer,
-                               "PCI: iSeries_Device_Information DevNode is NULL");
-
-       if (BufferSize < 128)
-               return 0;
-
-       len = sprintf(buffer, "PCI: Bus%3d, Device%3d, Vendor %04X ",
-                       ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),
-                       PciDev->vendor);
-       len += sprintf(buffer + len, "Frame%3d, Card %4s  ",
-                       DevNode->FrameId, DevNode->CardLocation);
-#ifdef CONFIG_PCI
-       if (pci_class_name(PciDev->class >> 8) == 0)
-               len += sprintf(buffer + len, "0x%04X  ",
-                               (int)(PciDev->class >> 8));
-       else
-               len += sprintf(buffer + len, "%s",
-                               pci_class_name(PciDev->class >> 8));
-#endif
-       return len;
-}
-
 /*
  * Parse the Slot Area
  */
-void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
-               struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
+               HvAgentId agent, u8 *PhbId, char card[4])
 {
        int SlotMapLen = MapLen;
        SlotMap *SlotMapPtr = MapPtr;
 
        /*
-        * Parse Slot label until we find the one requrested
+        * Parse Slot label until we find the one requested
         */
        while (SlotMapLen > 0) {
-               if (SlotMapPtr->AgentId == DevNode->AgentId ) {
+               if (SlotMapPtr->AgentId == agent) {
                        /*
                         * If Phb wasn't found, grab the entry first one found.
                         */
-                       if (DevNode->PhbId == 0xff)
-                               DevNode->PhbId = SlotMapPtr->PhbId; 
+                       if (*PhbId == 0xff)
+                               *PhbId = SlotMapPtr->PhbId;
                        /* Found it, extract the data. */
-                       if (SlotMapPtr->PhbId == DevNode->PhbId ) {
-                               memcpy(&DevNode->CardLocation,
-                                               &SlotMapPtr->CardLocation, 3);
-                               DevNode->CardLocation[3]  = 0;
+                       if (SlotMapPtr->PhbId == *PhbId) {
+                               memcpy(card, &SlotMapPtr->CardLocation, 3);
+                               card[3]  = 0;
                                break;
                        }
                }
@@ -159,8 +113,9 @@ void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
 /*
  * Parse the Mfg Area
  */
-static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
-               struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
+               HvAgentId agent, u8 *PhbId,
+               u8 *frame, char card[4])
 {
        MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
        int MfgAreaLen = AreaLen;
@@ -171,7 +126,7 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
                int MfgTagLen = MfgAreaPtr->TagLength;
                /* Frame ID         (FI 4649020310 ) */
                if (MfgAreaPtr->Tag == VpdFruFrameId)           /* FI  */
-                       DevNode->FrameId = MfgAreaPtr->AreaData1;
+                       *frame = MfgAreaPtr->AreaData1;
                /* Slot Map Format  (MF 4D46020004 ) */
                else if (MfgAreaPtr->Tag == VpdSlotMapFormat)   /* MF  */
                        SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
@@ -183,10 +138,11 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
                        if (SlotMapFmt == 0x1004)
                                SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
                                                + MFG_ENTRY_SIZE + 1);
-                       else
+                       else
                                SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
                                                + MFG_ENTRY_SIZE);
-                       iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen, DevNode);
+                       iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen,
+                                       agent, PhbId, card);
                }
                /*
                 * Point to the next Mfg Area
@@ -194,19 +150,19 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
                 */
                MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
                                + MFG_ENTRY_SIZE);
-               MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); 
-       }       
+               MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
+       }
 }
 
 /*
  * Look for "BUS".. Data is not Null terminated.
  * PHBID of 0xFF indicates PHB was not found in VPD Data.
  */
-static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
+static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
 {
        u8 *PhbPtr = AreaPtr;
        int DataLen = AreaLength;
-       char PhbId = 0xFF;                   
+       char PhbId = 0xFF;
 
        while (DataLen > 0) {
                if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
@@ -216,7 +172,7 @@ static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
                                ++PhbPtr;
                        PhbId = (*PhbPtr & 0x0F);
                        break;
-               }
+               }
                ++PhbPtr;
                --DataLen;
        }
@@ -226,52 +182,90 @@ static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
 /*
  * Parse out the VPD Areas
  */
-static void iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
-               struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
+               HvAgentId agent, u8 *frame, char card[4])
 {
        u8 *TagPtr = VpdData;
        int DataLen = VpdDataLen - 3;
+       u8 PhbId;
 
        while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
-               int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);    
+               int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
                u8 *AreaData  = TagPtr + 3;
 
                if (*TagPtr == VpdIdStringTag)
-                       DevNode->PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
+                       PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
                else if (*TagPtr == VpdVendorAreaTag)
-                       iSeries_Parse_MfgArea(AreaData, AreaLen, DevNode);
+                       iSeries_Parse_MfgArea(AreaData, AreaLen,
+                                       agent, &PhbId, frame, card);
                /* Point to next Area. */
                TagPtr  = AreaData + AreaLen;
                DataLen -= AreaLen;
        }
-}    
+}
 
-void iSeries_Get_Location_Code(struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent,
+               u8 *frame, char card[4])
 {
        int BusVpdLen = 0;
-       u8 *BusVpdPtr = (u8 *)kmalloc(BUS_VPDSIZE, GFP_KERNEL);
+       u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
 
        if (BusVpdPtr == NULL) {
                printk("PCI: Bus VPD Buffer allocation failure.\n");
                return;
        }
-       BusVpdLen = HvCallPci_getBusVpd(ISERIES_BUS(DevNode),
-                                       ISERIES_HV_ADDR(BusVpdPtr),
+       BusVpdLen = HvCallPci_getBusVpd(bus, ISERIES_HV_ADDR(BusVpdPtr),
                                        BUS_VPDSIZE);
        if (BusVpdLen == 0) {
-               kfree(BusVpdPtr);
                printk("PCI: Bus VPD Buffer zero length.\n");
-               return;
+               goto out_free;
        }
        /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
        /* Make sure this is what I think it is */
        if (*BusVpdPtr != VpdIdStringTag) {     /* 0x82 */
                printk("PCI: Bus VPD Buffer missing starting tag.\n");
-               kfree(BusVpdPtr);
-               return;
+               goto out_free;
        }
-       iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode);
-       sprintf(DevNode->Location, "Frame%3d, Card %-4s", DevNode->FrameId,
-                       DevNode->CardLocation);
+       iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card);
+out_free:
        kfree(BusVpdPtr);
 }
+
+/*
+ * Prints the device information.
+ * - Pass in pci_dev* pointer to the device.
+ * - Pass in the device count
+ *
+ * Format:
+ * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
+ * controller
+ */
+void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
+{
+       struct iSeries_Device_Node *DevNode = PciDev->sysdata;
+       u16 bus;
+       u8 frame;
+       char card[4];
+       HvSubBusNumber subbus;
+       HvAgentId agent;
+
+       if (DevNode == NULL) {
+               printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n",
+                               count);
+               return;
+       }
+
+       bus = ISERIES_BUS(DevNode);
+       subbus = ISERIES_SUBBUS(DevNode);
+       agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
+                       ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
+       iSeries_Get_Location_Code(bus, agent, &frame, card);
+
+       printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s  ",
+                       count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor,
+                       frame, card);
+       if (pci_class_name(PciDev->class >> 8) == 0)
+               printk("0x%04X\n", (int)(PciDev->class >> 8));
+       else
+               printk("%s\n", pci_class_name(PciDev->class >> 8));
+}
index 4e1a47c8a8026a0a132d54c414848db56030e948..f8ff1bb054dcde7a0cabb1d1df94d6d419a8c939 100644 (file)
@@ -83,7 +83,7 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
        }
 }
 
-
+#ifdef CONFIG_PCI
 /*
  * This function compares the known tables to find an iommu_table
  * that has already been built for hardware TCEs.
@@ -159,6 +159,7 @@ void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn)
        else
                kfree(tbl);
 }
+#endif
 
 static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
 static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
index f831d259dbb7707715bad82a55af8a85ad7afe67..77376c1bd611326c44bfcd71e3681f9d1508b197 100644 (file)
@@ -1,27 +1,29 @@
-/************************************************************************/
-/* This module supports the iSeries PCI bus interrupt handling          */
-/* Copyright (C) 20yy  <Robert L Holtorf> <IBM Corp>                    */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created, December 13, 2000 by Wayne Holm                           */ 
-/* End Change Activity                                                  */
-/************************************************************************/
+/*
+ * This module supports the iSeries PCI bus interrupt handling
+ * Copyright (C) 20yy  <Robert L Holtorf> <IBM Corp>
+ * Copyright (C) 2004-2005 IBM Corporation
+ *
+ * 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
+ *
+ * Change Activity:
+ *   Created, December 13, 2000 by Wayne Holm
+ * End Change Activity
+ */
+#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/threads.h>
 #include <linux/string.h>
 #include <linux/bootmem.h>
 #include <linux/ide.h>
-
 #include <linux/irq.h>
 #include <linux/spinlock.h>
-#include <asm/ppcdebug.h>
 
+#include <asm/ppcdebug.h>
+#include <asm/iSeries/HvTypes.h>
+#include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/iSeries/HvCallXm.h>
 #include <asm/iSeries/iSeries_irq.h>
-#include <asm/iSeries/XmPciLpEvent.h>
-
-static unsigned int iSeries_startup_IRQ(unsigned int irq);
-static void iSeries_shutdown_IRQ(unsigned int irq);
-static void iSeries_enable_IRQ(unsigned int irq);
-static void iSeries_disable_IRQ(unsigned int irq);
-static void iSeries_end_IRQ(unsigned int irq);
-
-static hw_irq_controller iSeries_IRQ_handler = {
-       .typename = "iSeries irq controller",
-       .startup = iSeries_startup_IRQ,
-       .shutdown = iSeries_shutdown_IRQ,
-       .enable = iSeries_enable_IRQ,
-       .disable = iSeries_disable_IRQ,
-       .end = iSeries_end_IRQ
-};
 
 /* This maps virtual irq numbers to real irqs */
 unsigned int virt_irq_to_real_map[NR_IRQS];
@@ -62,37 +49,187 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
 /* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */
 static int next_virtual_irq = 2;
 
-/* This is called by init_IRQ.  set in ppc_md.init_IRQ by iSeries_setup.c */
-void __init iSeries_init_IRQ(void)
+static long Pci_Interrupt_Count;
+static long Pci_Event_Count;
+
+enum XmPciLpEvent_Subtype {
+       XmPciLpEvent_BusCreated         = 0,    // PHB has been created
+       XmPciLpEvent_BusError           = 1,    // PHB has failed
+       XmPciLpEvent_BusFailed          = 2,    // Msg to Secondary, Primary failed bus
+       XmPciLpEvent_NodeFailed         = 4,    // Multi-adapter bridge has failed
+       XmPciLpEvent_NodeRecovered      = 5,    // Multi-adapter bridge has recovered
+       XmPciLpEvent_BusRecovered       = 12,   // PHB has been recovered
+       XmPciLpEvent_UnQuiesceBus       = 18,   // Secondary bus unqiescing
+       XmPciLpEvent_BridgeError        = 21,   // Bridge Error
+       XmPciLpEvent_SlotInterrupt      = 22    // Slot interrupt
+};
+
+struct XmPciLpEvent_BusInterrupt {
+       HvBusNumber     busNumber;
+       HvSubBusNumber  subBusNumber;
+};
+
+struct XmPciLpEvent_NodeInterrupt {
+       HvBusNumber     busNumber;
+       HvSubBusNumber  subBusNumber;
+       HvAgentId       deviceId;
+};
+
+struct XmPciLpEvent {
+       struct HvLpEvent hvLpEvent;
+
+       union {
+               u64 alignData;                  // Align on an 8-byte boundary
+
+               struct {
+                       u32             fisr;
+                       HvBusNumber     busNumber;
+                       HvSubBusNumber  subBusNumber;
+                       HvAgentId       deviceId;
+               } slotInterrupt;
+
+               struct XmPciLpEvent_BusInterrupt busFailed;
+               struct XmPciLpEvent_BusInterrupt busRecovered;
+               struct XmPciLpEvent_BusInterrupt busCreated;
+
+               struct XmPciLpEvent_NodeInterrupt nodeFailed;
+               struct XmPciLpEvent_NodeInterrupt nodeRecovered;
+
+       } eventData;
+
+};
+
+static void intReceived(struct XmPciLpEvent *eventParm,
+               struct pt_regs *regsParm)
 {
-       /* Register PCI event handler and open an event path */
-       XmPciLpEvent_init();
+       int irq;
+
+       ++Pci_Interrupt_Count;
+
+       switch (eventParm->hvLpEvent.xSubtype) {
+       case XmPciLpEvent_SlotInterrupt:
+               irq = eventParm->hvLpEvent.xCorrelationToken;
+               /* Dispatch the interrupt handlers for this irq */
+               ppc_irq_dispatch_handler(regsParm, irq);
+               HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
+                       eventParm->eventData.slotInterrupt.subBusNumber,
+                       eventParm->eventData.slotInterrupt.deviceId);
+               break;
+               /* Ignore error recovery events for now */
+       case XmPciLpEvent_BusCreated:
+               printk(KERN_INFO "intReceived: system bus %d created\n",
+                       eventParm->eventData.busCreated.busNumber);
+               break;
+       case XmPciLpEvent_BusError:
+       case XmPciLpEvent_BusFailed:
+               printk(KERN_INFO "intReceived: system bus %d failed\n",
+                       eventParm->eventData.busFailed.busNumber);
+               break;
+       case XmPciLpEvent_BusRecovered:
+       case XmPciLpEvent_UnQuiesceBus:
+               printk(KERN_INFO "intReceived: system bus %d recovered\n",
+                       eventParm->eventData.busRecovered.busNumber);
+               break;
+       case XmPciLpEvent_NodeFailed:
+       case XmPciLpEvent_BridgeError:
+               printk(KERN_INFO
+                       "intReceived: multi-adapter bridge %d/%d/%d failed\n",
+                       eventParm->eventData.nodeFailed.busNumber,
+                       eventParm->eventData.nodeFailed.subBusNumber,
+                       eventParm->eventData.nodeFailed.deviceId);
+               break;
+       case XmPciLpEvent_NodeRecovered:
+               printk(KERN_INFO
+                       "intReceived: multi-adapter bridge %d/%d/%d recovered\n",
+                       eventParm->eventData.nodeRecovered.busNumber,
+                       eventParm->eventData.nodeRecovered.subBusNumber,
+                       eventParm->eventData.nodeRecovered.deviceId);
+               break;
+       default:
+               printk(KERN_ERR
+                       "intReceived: unrecognized event subtype 0x%x\n",
+                       eventParm->hvLpEvent.xSubtype);
+               break;
+       }
+}
+
+static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
+               struct pt_regs *regsParm)
+{
+#ifdef CONFIG_PCI
+       ++Pci_Event_Count;
+
+       if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
+               switch (eventParm->xFlags.xFunction) {
+               case HvLpEvent_Function_Int:
+                       intReceived((struct XmPciLpEvent *)eventParm, regsParm);
+                       break;
+               case HvLpEvent_Function_Ack:
+                       printk(KERN_ERR
+                               "XmPciLpEvent_handler: unexpected ack received\n");
+                       break;
+               default:
+                       printk(KERN_ERR
+                               "XmPciLpEvent_handler: unexpected event function %d\n",
+                               (int)eventParm->xFlags.xFunction);
+                       break;
+               }
+       } else if (eventParm)
+               printk(KERN_ERR
+                       "XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n",
+                       (int)eventParm->xType);
+       else
+               printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n");
+#endif
 }
 
 /*
- * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
- * It calculates the irq value for the slot.
- * Note that subBusNumber is always 0 (at the moment at least).
+ * This is called by init_IRQ.  set in ppc_md.init_IRQ by iSeries_setup.c
+ * It must be called before the bus walk.
  */
-int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
-               HvSubBusNumber subBusNumber, HvAgentId deviceId)
+void __init iSeries_init_IRQ(void)
 {
-       unsigned int realirq, virtirq;
-       u8 idsel = (deviceId >> 4);
-       u8 function = deviceId & 7;
-
-       virtirq = next_virtual_irq++;
-       realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
-       virt_irq_to_real_map[virtirq] = realirq;
+       /* Register PCI event handler and open an event path */
+       int xRc;
 
-       irq_desc[virtirq].handler = &iSeries_IRQ_handler;
-       return virtirq;
+       xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
+                       &XmPciLpEvent_handler);
+       if (xRc == 0) {
+               xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
+               if (xRc != 0)
+                       printk(KERN_ERR "iSeries_init_IRQ: open event path "
+                                       "failed with rc 0x%x\n", xRc);
+       } else
+               printk(KERN_ERR "iSeries_init_IRQ: register handler "
+                               "failed with rc 0x%x\n", xRc);
 }
 
 #define REAL_IRQ_TO_BUS(irq)   ((((irq) >> 6) & 0xff) + 1)
 #define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
 #define REAL_IRQ_TO_FUNC(irq)  ((irq) & 7)
 
+/*
+ * This will be called by device drivers (via enable_IRQ)
+ * to enable INTA in the bridge interrupt status register.
+ */
+static void iSeries_enable_IRQ(unsigned int irq)
+{
+       u32 bus, deviceId, function, mask;
+       const u32 subBus = 0;
+       unsigned int rirq = virt_irq_to_real_map[irq];
+
+       /* The IRQ has already been locked by the caller */
+       bus = REAL_IRQ_TO_BUS(rirq);
+       function = REAL_IRQ_TO_FUNC(rirq);
+       deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+
+       /* Unmask secondary INTA */
+       mask = 0x80000000;
+       HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
+       PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
+                       bus, subBus, deviceId, irq);
+}
+
 /* This is called by iSeries_activate_IRQs */
 static unsigned int iSeries_startup_IRQ(unsigned int irq)
 {
@@ -131,7 +268,7 @@ void __init iSeries_activate_IRQs()
                        desc->handler->startup(irq);
                        spin_unlock_irqrestore(&desc->lock, flags);
                }
-       }
+       }
 }
 
 /*  this is not called anywhere currently */
@@ -173,29 +310,7 @@ static void iSeries_disable_IRQ(unsigned int irq)
        mask = 0x80000000;
        HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
        PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
-              bus, subBus, deviceId, irq);
-}
-
-/*
- * This will be called by device drivers (via enable_IRQ)
- * to enable INTA in the bridge interrupt status register.
- */
-static void iSeries_enable_IRQ(unsigned int irq)
-{
-       u32 bus, deviceId, function, mask;
-       const u32 subBus = 0;
-       unsigned int rirq = virt_irq_to_real_map[irq];
-
-       /* The IRQ has already been locked by the caller */
-       bus = REAL_IRQ_TO_BUS(rirq);
-       function = REAL_IRQ_TO_FUNC(rirq);
-       deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
-
-       /* Unmask secondary INTA */
-       mask = 0x80000000;
-       HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
-       PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
-              bus, subBus, deviceId, irq);
+                       bus, subBus, deviceId, irq);
 }
 
 /*
@@ -207,3 +322,32 @@ static void iSeries_enable_IRQ(unsigned int irq)
 static void iSeries_end_IRQ(unsigned int irq)
 {
 }
+
+static hw_irq_controller iSeries_IRQ_handler = {
+       .typename = "iSeries irq controller",
+       .startup = iSeries_startup_IRQ,
+       .shutdown = iSeries_shutdown_IRQ,
+       .enable = iSeries_enable_IRQ,
+       .disable = iSeries_disable_IRQ,
+       .end = iSeries_end_IRQ
+};
+
+/*
+ * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
+ * It calculates the irq value for the slot.
+ * Note that subBusNumber is always 0 (at the moment at least).
+ */
+int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
+               HvSubBusNumber subBusNumber, HvAgentId deviceId)
+{
+       unsigned int realirq, virtirq;
+       u8 idsel = (deviceId >> 4);
+       u8 function = deviceId & 7;
+
+       virtirq = next_virtual_irq++;
+       realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
+       virt_irq_to_real_map[virtirq] = realirq;
+
+       irq_desc[virtirq].handler = &iSeries_IRQ_handler;
+       return virtirq;
+}
index bd4c2554f1a048272ecf4703172e6a02ebaf00a0..356e4fd9a94fecc763e90a13bb79860ba2880f7b 100644 (file)
@@ -38,9 +38,7 @@
 #include <asm/iommu.h>
 
 #include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/HvCallSm.h>
 #include <asm/iSeries/HvCallXm.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/iSeries_irq.h>
 #include <asm/iSeries/iSeries_pci.h>
 #include <asm/iSeries/mf.h>
@@ -225,10 +223,7 @@ static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus,
        node->DsaAddr.Dsa.busNumber = Bus;
        node->DsaAddr.Dsa.subBusNumber = SubBus;
        node->DsaAddr.Dsa.deviceId = 0x10;
-       node->AgentId = AgentId;
        node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
-       node->IoRetry = 0;
-       iSeries_Get_Location_Code(node);
        return node;
 }
 
@@ -302,7 +297,6 @@ void __init iSeries_pci_final_fixup(void)
 {
        struct pci_dev *pdev = NULL;
        struct iSeries_Device_Node *node;
-       char Buffer[256];
        int DeviceCount = 0;
 
        PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); 
@@ -324,9 +318,7 @@ void __init iSeries_pci_final_fixup(void)
                                        "pdev 0x%p <==> DevNode 0x%p\n",
                                        pdev, node);
                        allocate_device_bars(pdev);
-                       iSeries_Device_Information(pdev, Buffer,
-                                       sizeof(Buffer));
-                       printk("%d. %s\n", DeviceCount, Buffer);
+                       iSeries_Device_Information(pdev, DeviceCount);
                        iommu_devnode_init_iSeries(node);
                } else
                        printk("PCI: Device Tree not found for 0x%016lX\n",
@@ -499,7 +491,6 @@ static int scan_bridge_slot(HvBusNumber Bus,
 
                        ++DeviceCount;
                        node = build_device_node(Bus, SubBus, EADsIdSel, Function);
-                       node->Vendor = VendorId;
                        node->Irq = Irq;
                        node->LogicalSlot = BridgeInfo->logicalSlotNumber;
 
@@ -661,38 +652,34 @@ static struct pci_ops iSeries_pci_ops = {
  * Check Return Code
  * -> On Failure, print and log information.
  *    Increment Retry Count, if exceeds max, panic partition.
- * -> If in retry, print and log success 
  *
  * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
  * PCI: Device 23.90 ReadL Retry( 1)
  * PCI: Device 23.90 ReadL Retry Successful(1)
  */
 static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
-               u64 ret)
+               int *retry, u64 ret)
 {
        if (ret != 0)  {
                ++Pci_Error_Count;
-               ++DevNode->IoRetry;
+               (*retry)++;
                printk("PCI: %s: Device 0x%04X:%02X  I/O Error(%2d): 0x%04X\n",
                                TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
-                               DevNode->IoRetry, (int)ret);
+                               *retry, (int)ret);
                /*
                 * Bump the retry and check for retry count exceeded.
                 * If, Exceeded, panic the system.
                 */
-               if ((DevNode->IoRetry > Pci_Retry_Max) &&
+               if (((*retry) > Pci_Retry_Max) &&
                                (Pci_Error_Flag > 0)) {
                        mf_display_src(0xB6000103);
-                       panic_timeout = 0; 
+                       panic_timeout = 0;
                        panic("PCI: Hardware I/O Error, SRC B6000103, "
                                        "Automatic Reboot Disabled.\n");
                }
                return -1;      /* Retry Try */
        }
-       /* If retry was in progress, log success and rest retry count */
-       if (DevNode->IoRetry > 0)
-               DevNode->IoRetry = 0;
-       return 0; 
+       return 0;
 }
 
 /*
@@ -738,6 +725,7 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
+       int retry = 0;
        struct HvCallPci_LoadReturn ret;
        struct iSeries_Device_Node *DevNode =
                xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -757,7 +745,7 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
        do {
                ++Pci_Io_Read_Count;
                HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
-       } while (CheckReturnCode("RDB", DevNode, ret.rc) != 0);
+       } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
 
        return (u8)ret.value;
 }
@@ -767,6 +755,7 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
+       int retry = 0;
        struct HvCallPci_LoadReturn ret;
        struct iSeries_Device_Node *DevNode =
                xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -787,7 +776,7 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
                ++Pci_Io_Read_Count;
                HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
                                BarOffset, 0);
-       } while (CheckReturnCode("RDW", DevNode, ret.rc) != 0);
+       } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
 
        return swab16((u16)ret.value);
 }
@@ -797,6 +786,7 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
+       int retry = 0;
        struct HvCallPci_LoadReturn ret;
        struct iSeries_Device_Node *DevNode =
                xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -817,7 +807,7 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
                ++Pci_Io_Read_Count;
                HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
                                BarOffset, 0);
-       } while (CheckReturnCode("RDL", DevNode, ret.rc) != 0);
+       } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
 
        return swab32((u32)ret.value);
 }
@@ -834,6 +824,7 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
+       int retry = 0;
        u64 rc;
        struct iSeries_Device_Node *DevNode =
                xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -853,7 +844,7 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
        do {
                ++Pci_Io_Write_Count;
                rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
-       } while (CheckReturnCode("WWB", DevNode, rc) != 0);
+       } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Byte);
 
@@ -861,6 +852,7 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
+       int retry = 0;
        u64 rc;
        struct iSeries_Device_Node *DevNode =
                xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -880,7 +872,7 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
        do {
                ++Pci_Io_Write_Count;
                rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
-       } while (CheckReturnCode("WWW", DevNode, rc) != 0);
+       } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Word);
 
@@ -888,6 +880,7 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
 {
        u64 BarOffset;
        u64 dsa;
+       int retry = 0;
        u64 rc;
        struct iSeries_Device_Node *DevNode =
                xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -907,6 +900,6 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
        do {
                ++Pci_Io_Write_Count;
                rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
-       } while (CheckReturnCode("WWL", DevNode, rc) != 0);
+       } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Long);
diff --git a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c
deleted file mode 100644 (file)
index 0f785e4..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-#define PCIFR(...)
-/************************************************************************/
-/* File iSeries_pci_reset.c created by Allan Trautman on Mar 21 2001.   */
-/************************************************************************/
-/* This code supports the pci interface on the IBM iSeries systems.     */
-/* Copyright (C) 20yy  <Allan H Trautman> <IBM Corp>                    */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created, March 20, 2001                                            */
-/*   April 30, 2001, Added return codes on functions.                   */
-/*   September 10, 2001, Ported to ppc64.                               */
-/* End Change Activity                                                  */
-/************************************************************************/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/mf.h>
-#include <asm/pci.h>
-
-#include <asm/iSeries/iSeries_pci.h>
-#include "pci.h"
-
-/*
- * Interface to toggle the reset line
- * Time is in .1 seconds, need for seconds.
- */
-int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime,
-               int DelayTime)
-{
-       unsigned int AssertDelay, WaitDelay;
-       struct iSeries_Device_Node *DeviceNode =
-               (struct iSeries_Device_Node *)PciDev->sysdata;
-
-       if (DeviceNode == NULL) { 
-               printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",
-                               PciDev);
-               return -1;
-       }
-       /*
-        * Set defaults, Assert is .5 second, Wait is 3 seconds.
-        */
-       if (AssertTime == 0)
-               AssertDelay = 500;
-       else
-               AssertDelay = AssertTime * 100;
-
-       if (DelayTime == 0)
-               WaitDelay = 3000;
-       else
-               WaitDelay = DelayTime * 100;
-
-       /*
-        * Assert reset
-        */
-       DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
-                       0x00, DeviceNode->AgentId, 1);
-       if (DeviceNode->ReturnCode == 0) {
-               msleep(AssertDelay);                    /* Sleep for the time */
-               DeviceNode->ReturnCode =
-                       HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
-                                       0x00, DeviceNode->AgentId, 0);
-
-               /*
-                * Wait for device to reset
-                */
-               msleep(WaitDelay);
-       }
-       if (DeviceNode->ReturnCode == 0)
-               PCIFR("Slot 0x%04X.%02 Reset\n", ISERIES_BUS(DeviceNode),
-                               DeviceNode->AgentId);
-       else {
-               printk("PCI: Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
-                               ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
-                               DeviceNode->ReturnCode);
-               PCIFR("Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
-                               ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
-                               DeviceNode->ReturnCode);
-       }
-       return DeviceNode->ReturnCode;
-}
-EXPORT_SYMBOL(iSeries_Device_ToggleReset);
index 0cc58ddf48ded6bd265c43c067b2ffc1a1e1bdd3..356bd9931fcc923e7e3645557bc3392331f855b4 100644 (file)
@@ -28,8 +28,7 @@
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/HvCallXm.h>
 #include <asm/iSeries/IoHriMainStore.h>
-#include <asm/iSeries/LparData.h>
-#include <asm/iSeries/iSeries_proc.h>
+#include <asm/iSeries/IoHriProcessorVpd.h>
 
 static int __init iseries_proc_create(void)
 {
index 6d06eb550a3fb839077953caab8d6f82d96afe8a..b31962436fe36b4e795e1d2c15ae0c5c0e774456 100644 (file)
@@ -47,7 +47,7 @@
 #include <asm/paca.h>
 #include <asm/cache.h>
 #include <asm/sections.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/abs_addr.h>
 #include <asm/iSeries/HvCallHpt.h>
 #include <asm/iSeries/HvLpConfig.h>
 #include <asm/iSeries/HvCallEvent.h>
 #include <asm/iSeries/HvCallXm.h>
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/IoHriMainStore.h>
-#include <asm/iSeries/iSeries_proc.h>
 #include <asm/iSeries/mf.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/iSeries_irq.h>
+#include <asm/iSeries/IoHriProcessorVpd.h>
+#include <asm/iSeries/ItVpdAreas.h>
+#include <asm/iSeries/LparMap.h>
 
 extern void hvlog(char *fmt, ...);
 
@@ -74,7 +76,11 @@ extern void ppcdbg_initialize(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);
+#ifdef CONFIG_PCI
 extern void iSeries_pci_final_fixup(void);
+#else
+static void iSeries_pci_final_fixup(void) { }
+#endif
 
 /* Global Variables */
 static unsigned long procFreqHz;
@@ -874,6 +880,10 @@ static int set_spread_lpevents(char *str)
 }
 __setup("spread_lpevents=", set_spread_lpevents);
 
+#ifndef CONFIG_PCI
+void __init iSeries_init_IRQ(void) { }
+#endif
+
 void __init iSeries_early_setup(void)
 {
        iSeries_fixup_klimit();
index ba1f084d5462419d842df6ab2a56b46d3ae7e220..f74386e31638d38185755bcf9cb3ae6d8b2f725c 100644 (file)
@@ -38,9 +38,7 @@
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/paca.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/HvCall.h>
-#include <asm/iSeries/HvCallCfg.h>
 #include <asm/time.h>
 #include <asm/ppcdebug.h>
 #include <asm/machdep.h>
index f24ce2b872004ae4feb1f419eddb3c0866c1c440..bdf13b4dc1c832972733e907b6e68ab83704ff01 100644 (file)
@@ -42,6 +42,11 @@ static int (*idle_loop)(void);
 static unsigned long maxYieldTime = 0;
 static unsigned long minYieldTime = 0xffffffffffffffffUL;
 
+static inline void process_iSeries_events(void)
+{
+       asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
+}
+
 static void yield_shared_processor(void)
 {
        unsigned long tb;
@@ -292,7 +297,7 @@ static int native_idle(void)
                if (need_resched())
                        schedule();
 
-               if (cpu_is_offline(_smp_processor_id()) &&
+               if (cpu_is_offline(raw_smp_processor_id()) &&
                    system_state == SYSTEM_RUNNING)
                        cpu_die();
        }
index 4fd7f203c1e3e89bc122fe9c090cf675cfd6cb7c..d860467b8f096430456bb9842033e3d53c020e05 100644 (file)
@@ -52,7 +52,7 @@
 #include <asm/cache.h>
 #include <asm/prom.h>
 #include <asm/ptrace.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItLpQueue.h>
 #include <asm/machdep.h>
 #include <asm/paca.h>
 
index a8fd32df848b71ade564d51316ab93f35a4348c6..387923fcf9b06492a07b0b9e63c8748197de0e7b 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/iSeries/HvLpConfig.h>
 #include <asm/lppaca.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/hvcall.h>
 #include <asm/cputable.h>
 #include <asm/rtas.h>
 #include <asm/system.h>
 #include <asm/time.h>
+#include <asm/iSeries/ItExtVpdPanel.h>
 
 #define MODULE_VERS "1.6"
 #define MODULE_NAME "lparcfg"
index 5aca7e8005a80f9b5a188d04269347ac90c411b1..d98bebf7042faf990e63a8732c8dab4c91991033 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/iSeries/vio.h>
 #include <asm/iSeries/mf.h>
 #include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/ItSpCommArea.h>
 #include <asm/iSeries/ItLpQueue.h>
 
 /*
index cdfecbeb331f58d586edd4b85aa58212f859d872..aba89554d89df912f268e465fab3f74f5cb7e90f 100644 (file)
@@ -58,14 +58,6 @@ struct task_struct *last_task_used_math = NULL;
 struct task_struct *last_task_used_altivec = NULL;
 #endif
 
-struct mm_struct ioremap_mm = {
-       .pgd            = ioremap_dir,
-       .mm_users       = ATOMIC_INIT(2),
-       .mm_count       = ATOMIC_INIT(1),
-       .cpu_vm_mask    = CPU_MASK_ALL,
-       .page_table_lock = SPIN_LOCK_UNLOCKED,
-};
-
 /*
  * Make sure the floating-point register state in the
  * the thread_struct is up to date for task tsk.
index eb6538b58008b641f06cd7fab3ca815b4ae4ca3d..47727a6f734623c89a14d5b0d61593bdcacafa74 100644 (file)
@@ -884,6 +884,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
 {
        char *type = get_flat_dt_prop(node, "device_type", NULL);
        u32 *prop;
+       unsigned long size;
 
        /* We are scanning "cpu" nodes only */
        if (type == NULL || strcmp(type, "cpu") != 0)
@@ -929,6 +930,17 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
                cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
        }
 
+       /*
+        * Check for an SMT capable CPU and set the CPU feature. We do
+        * this by looking at the size of the ibm,ppc-interrupt-server#s
+        * property
+        */
+       prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
+                                      &size);
+       cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
+       if (prop && ((size / sizeof(u32)) > 1))
+               cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
+
        return 0;
 }
 
index 1c4c796b212b03ada36dae8130913bc95d1671ff..3c00f7bfc1b5736d43ab2011e3ac37aafe6da9cf 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/cache.h>
 #include <asm/prom.h>
 #include <asm/ptrace.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/machdep.h>
 #include <asm/rtas.h>
 #include <asm/ppcdebug.h>
index 67989055a9fee0b50d9f1b1928183bb66a02be4e..de02aedbe08085e5955a53f90dcaa924ecf53f94 100644 (file)
 #include <asm/time.h>
 #include <asm/rtas.h>
 
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/mf.h>
 #include <asm/machdep.h>
-#include <asm/iSeries/ItSpCommArea.h>
 
 extern int piranha_simulator;
 
index dce198d39328aefd6541efef430f6a6e71d9ca4f..8e439a8176421ac6009f7b569207afe07b9ae730 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/smp.h>
 #include <asm/elf.h>
 #include <asm/machdep.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/paca.h>
 #include <asm/ppcdebug.h>
 #include <asm/time.h>
@@ -57,6 +56,8 @@
 #include <asm/cache.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
+#include <asm/lmb.h>
+#include <asm/iSeries/ItLpNaca.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
index 9c8e317c598d0ed40e6fcd61c41d61abcd847a98..118436e8085ae79d31bb8de5ee28b8196c8a645a 100644 (file)
@@ -741,6 +741,7 @@ asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubu
 
 asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
 {
+#ifdef CONFIG_PCI
        struct pci_controller* hose;
        struct list_head *ln;
        struct pci_bus *bus = NULL;
@@ -786,7 +787,7 @@ asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
        case IOBASE_ISA_MEM:
                return -EINVAL;
        }
-
+#endif /* CONFIG_PCI */
        return -EOPNOTSUPP;
 }
 
index 79f2dc7a9833c481e91c8e3981d9db7b38335f23..0c0ba71ac0e8b79cd2a29b8fffd8d4f177ac006b 100644 (file)
@@ -41,20 +41,25 @@ static const struct vio_device_id *vio_match_device(
 static struct iommu_table *vio_build_iommu_table(struct vio_dev *);
 static int vio_num_address_cells;
 #endif
-static struct vio_dev *vio_bus_device; /* fake "parent" device */
-
 #ifdef CONFIG_PPC_ISERIES
-static struct vio_dev *__init vio_register_device_iseries(char *type,
-               uint32_t unit_num);
-
 static struct iommu_table veth_iommu_table;
 static struct iommu_table vio_iommu_table;
-
-static struct vio_dev _vio_dev  = {
+#endif
+static struct vio_dev vio_bus_device  = { /* fake "parent" device */
+       .name = vio_bus_device.dev.bus_id,
+       .type = "",
+#ifdef CONFIG_PPC_ISERIES
        .iommu_table = &vio_iommu_table,
-       .dev.bus = &vio_bus_type
+#endif
+       .dev.bus_id = "vio",
+       .dev.bus = &vio_bus_type,
 };
-struct device *iSeries_vio_dev = &_vio_dev.dev;
+
+#ifdef CONFIG_PPC_ISERIES
+static struct vio_dev *__init vio_register_device_iseries(char *type,
+               uint32_t unit_num);
+
+struct device *iSeries_vio_dev = &vio_bus_device.dev;
 EXPORT_SYMBOL(iSeries_vio_dev);
 
 #define device_is_compatible(a, b)     1
@@ -260,18 +265,10 @@ static int __init vio_bus_init(void)
        }
 
        /* the fake parent of all vio devices, just to give us a nice directory */
-       vio_bus_device = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
-       if (!vio_bus_device) {
-               return 1;
-       }
-       memset(vio_bus_device, 0, sizeof(struct vio_dev));
-       strcpy(vio_bus_device->dev.bus_id, "vio");
-
-       err = device_register(&vio_bus_device->dev);
+       err = device_register(&vio_bus_device.dev);
        if (err) {
                printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__,
                        err);
-               kfree(vio_bus_device);
                return err;
        }
 
@@ -326,7 +323,7 @@ static struct vio_dev * __devinit vio_register_device_common(
        viodev->unit_address = unit_address;
        viodev->iommu_table = iommu_table;
        /* init generic 'struct device' fields: */
-       viodev->dev.parent = &vio_bus_device->dev;
+       viodev->dev.parent = &vio_bus_device.dev;
        viodev->dev.bus = &vio_bus_type;
        viodev->dev.release = vio_dev_release;
 
@@ -636,5 +633,3 @@ struct bus_type vio_bus_type = {
        .name = "vio",
        .match = vio_bus_match,
 };
-
-EXPORT_SYMBOL(vio_bus_type);
index 2ed8ee075680557c88c2a4641fd0c9afa1225f85..2a6c4f01c45ed6d320581fdd62eaa2698ce155d9 100644 (file)
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItExtVpdPanel.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/HvCallCfg.h>
 #include <asm/iSeries/mf.h>
-#include <asm/iSeries/iSeries_proc.h>
 #include <asm/iSeries/vio.h>
 
 /* Status of the path to each other partition in the system.
@@ -365,7 +363,7 @@ void vio_set_hostlp(void)
         * while we're active
         */
        viopath_ourLp = HvLpConfig_getLpIndex();
-       viopath_hostLp = HvCallCfg_getHostingLpIndex(viopath_ourLp);
+       viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp);
 
        if (viopath_hostLp != HvLpIndexInvalid)
                vio_setHandler(viomajorsubtype_config, handleConfig);
@@ -487,7 +485,7 @@ int viopath_open(HvLpIndex remoteLp, int subtype, int numReq)
        unsigned long flags;
        int tempNumAllocated;
 
-       if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
+       if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
                return -EINVAL;
 
        subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
@@ -558,7 +556,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
        int numOpen;
        struct alloc_parms parms;
 
-       if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
+       if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
                return -EINVAL;
 
        subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
index bf7b5bbfc04e6338a286ff53ecca9b039b78bcf0..76fbfa9f706fb4c220036244b882290c56be22a6 100644 (file)
@@ -12,7 +12,7 @@ lib-$(CONFIG_SMP) += locks.o
 
 # e2a provides EBCDIC to ASCII conversions.
 ifdef CONFIG_PPC_ISERIES
-obj-$(CONFIG_PCI)      += e2a.o
+obj-y += e2a.o
 endif
 
 lib-$(CONFIG_DEBUG_KERNEL) += sstep.o
index 0a0f97008d02bc383e2b45aaf10cab443dea9561..1647b1c6f28e84453b314669bfda90c0a12b83f7 100644 (file)
@@ -195,7 +195,7 @@ void __init htab_initialize(void)
                memset((void *)table, 0, htab_size_bytes);
        }
 
-       mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
+       mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
 
        /* On U3 based machines, we need to reserve the DART area and
         * _NOT_ map it to avoid cache paradoxes as it's remapped non
@@ -310,10 +310,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 
                vsid = get_vsid(mm->context.id, ea);
                break;
-       case IO_REGION_ID:
-               mm = &ioremap_mm;
-               vsid = get_kernel_vsid(ea);
-               break;
        case VMALLOC_REGION_ID:
                mm = &init_mm;
                vsid = get_kernel_vsid(ea);
index d3bf86a5c1ad40a745ded13bdf9d9b6aa80da0c8..fdcfe97c75c1dbc388cec0fe261ce446e82ab3e3 100644 (file)
@@ -121,7 +121,7 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr
        return hugepte_offset(dir, addr);
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
        pud_t *pud;
 
@@ -134,7 +134,7 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
        return hugepte_offset(pud, addr);
 }
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
        pud_t *pud;
 
@@ -147,25 +147,6 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        return hugepte_alloc(mm, pud, addr);
 }
 
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
-                        unsigned long addr, struct page *page,
-                        pte_t *ptep, int write_access)
-{
-       pte_t entry;
-
-       add_mm_counter(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);
-
-       set_pte_at(mm, addr, ptep, entry);
-}
-
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -259,80 +240,6 @@ int prepare_hugepage_range(unsigned long addr, unsigned long len)
        return -EINVAL;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-                       struct vm_area_struct *vma)
-{
-       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) {
-               dst_pte = huge_pte_alloc(dst, addr);
-               if (!dst_pte)
-                       goto out;
-
-               src_pte = huge_pte_offset(src, addr);
-               entry = *src_pte;
-               
-               ptepage = pte_page(entry);
-               get_page(ptepage);
-               add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-               set_pte_at(dst, addr, dst_pte, entry);
-
-               addr += HPAGE_SIZE;
-       }
-
-       err = 0;
- out:
-       return err;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-                   struct page **pages, struct vm_area_struct **vmas,
-                   unsigned long *position, int *length, int i)
-{
-       unsigned long vpfn, vaddr = *position;
-       int remainder = *length;
-
-       WARN_ON(!is_vm_hugetlb_page(vma));
-
-       vpfn = vaddr/PAGE_SIZE;
-       while (vaddr < vma->vm_end && remainder) {
-               if (pages) {
-                       pte_t *pte;
-                       struct page *page;
-
-                       pte = huge_pte_offset(mm, vaddr);
-
-                       /* hugetlb should be locked, and hence, prefaulted */
-                       WARN_ON(!pte || pte_none(*pte));
-
-                       page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
-
-                       WARN_ON(!PageCompound(page));
-
-                       get_page(page);
-                       pages[i] = page;
-               }
-
-               if (vmas)
-                       vmas[i] = vma;
-
-               vaddr += PAGE_SIZE;
-               ++vpfn;
-               --remainder;
-               ++i;
-       }
-
-       *length = remainder;
-       *position = vaddr;
-
-       return i;
-}
-
 struct page *
 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
 {
@@ -363,89 +270,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
        return NULL;
 }
 
-void unmap_hugepage_range(struct vm_area_struct *vma,
-                         unsigned long start, unsigned long end)
-{
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long addr;
-       pte_t *ptep;
-       struct page *page;
-
-       WARN_ON(!is_vm_hugetlb_page(vma));
-       BUG_ON((start % HPAGE_SIZE) != 0);
-       BUG_ON((end % HPAGE_SIZE) != 0);
-
-       for (addr = start; addr < end; addr += HPAGE_SIZE) {
-               pte_t pte;
-
-               ptep = huge_pte_offset(mm, addr);
-               if (!ptep || pte_none(*ptep))
-                       continue;
-
-               pte = *ptep;
-               page = pte_page(pte);
-               pte_clear(mm, addr, ptep);
-
-               put_page(page);
-       }
-       add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
-       flush_tlb_pending();
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-       struct mm_struct *mm = current->mm;
-       unsigned long addr;
-       int ret = 0;
-
-       WARN_ON(!is_vm_hugetlb_page(vma));
-       BUG_ON((vma->vm_start % HPAGE_SIZE) != 0);
-       BUG_ON((vma->vm_end % HPAGE_SIZE) != 0);
-
-       spin_lock(&mm->page_table_lock);
-       for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-               unsigned long idx;
-               pte_t *pte = huge_pte_alloc(mm, addr);
-               struct page *page;
-
-               if (!pte) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               if (! pte_none(*pte))
-                       continue;
-
-               idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-                       + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-               page = find_get_page(mapping, idx);
-               if (!page) {
-                       /* charge the fs quota first */
-                       if (hugetlb_get_quota(mapping)) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       page = alloc_huge_page();
-                       if (!page) {
-                               hugetlb_put_quota(mapping);
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-                       if (! ret) {
-                               unlock_page(page);
-                       } else {
-                               hugetlb_put_quota(mapping);
-                               free_huge_page(page);
-                               goto out;
-                       }
-               }
-               set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
-       }
-out:
-       spin_unlock(&mm->page_table_lock);
-       return ret;
-}
-
 /* 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. */
@@ -468,7 +292,12 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                    && !is_hugepage_only_range(mm, addr,len))
                        return addr;
        }
-       start_addr = addr = mm->free_area_cache;
+       if (len > mm->cached_hole_size) {
+               start_addr = addr = mm->free_area_cache;
+       } else {
+               start_addr = addr = TASK_UNMAPPED_BASE;
+               mm->cached_hole_size = 0;
+       }
 
 full_search:
        vma = find_vma(mm, addr);
@@ -492,6 +321,8 @@ full_search:
                        mm->free_area_cache = addr + len;
                        return addr;
                }
+               if (addr + mm->cached_hole_size < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
                addr = vma->vm_end;
                vma = vma->vm_next;
        }
@@ -499,6 +330,7 @@ full_search:
        /* Make sure we didn't miss any holes */
        if (start_addr != TASK_UNMAPPED_BASE) {
                start_addr = addr = TASK_UNMAPPED_BASE;
+               mm->cached_hole_size = 0;
                goto full_search;
        }
        return -ENOMEM;
@@ -520,6 +352,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        struct vm_area_struct *vma, *prev_vma;
        struct mm_struct *mm = current->mm;
        unsigned long base = mm->mmap_base, addr = addr0;
+       unsigned long largest_hole = mm->cached_hole_size;
        int first_time = 1;
 
        /* requested length too big for entire address space */
@@ -540,6 +373,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                        return addr;
        }
 
+       if (len <= largest_hole) {
+               largest_hole = 0;
+               mm->free_area_cache = base;
+       }
 try_again:
        /* make sure it can fit in the remaining address space */
        if (mm->free_area_cache < len)
@@ -568,13 +405,21 @@ hugepage_recheck:
                 * vma->vm_start, use it:
                 */
                if (addr+len <= vma->vm_start &&
-                               (!prev_vma || (addr >= prev_vma->vm_end)))
+                         (!prev_vma || (addr >= prev_vma->vm_end))) {
                        /* remember the address as a hint for next time */
-                       return (mm->free_area_cache = addr);
-               else
+                       mm->cached_hole_size = largest_hole;
+                       return (mm->free_area_cache = addr);
+               } else {
                        /* pull free_area_cache down to the first hole */
-                       if (mm->free_area_cache == vma->vm_end)
+                       if (mm->free_area_cache == vma->vm_end) {
                                mm->free_area_cache = vma->vm_start;
+                               mm->cached_hole_size = largest_hole;
+                       }
+               }
+
+               /* remember the largest hole we saw so far */
+               if (addr + largest_hole < vma->vm_start)
+                       largest_hole = vma->vm_start - addr;
 
                /* try just below the current vma->vm_start */
                addr = vma->vm_start-len;
@@ -587,6 +432,7 @@ fail:
         */
        if (first_time) {
                mm->free_area_cache = base;
+               largest_hole = 0;
                first_time = 0;
                goto try_again;
        }
@@ -597,11 +443,13 @@ fail:
         * allocations.
         */
        mm->free_area_cache = TASK_UNMAPPED_BASE;
+       mm->cached_hole_size = ~0UL;
        addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
        /*
         * Restore the topdown base:
         */
        mm->free_area_cache = base;
+       mm->cached_hole_size = ~0UL;
 
        return addr;
 }
index cb8727f3267a1c252b1f4d3d7fe1e498a210d3b4..b6e75b891ac0fef5a2aa9dea4152b2c2ea2b998b 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/pgtable.h>
 #include <asm/semaphore.h>
 #include <asm/imalloc.h>
+#include <asm/cacheflush.h>
 
 static DECLARE_MUTEX(imlist_sem);
 struct vm_struct * imlist = NULL;
@@ -285,29 +286,32 @@ struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
        return area;
 }
 
-unsigned long im_free(void * addr)
+void im_free(void * addr)
 {
        struct vm_struct **p, *tmp;
-       unsigned long ret_size = 0;
   
        if (!addr)
-               return ret_size;
-       if ((PAGE_SIZE-1) & (unsigned long) addr) {
+               return;
+       if ((unsigned long) addr & ~PAGE_MASK) {
                printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__,                        addr);
-               return ret_size;
+               return;
        }
        down(&imlist_sem);
        for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
                if (tmp->addr == addr) {
-                       ret_size = tmp->size;
                        *p = tmp->next;
+
+                       /* XXX: do we need the lock? */
+                       spin_lock(&init_mm.page_table_lock);
+                       unmap_vm_area(tmp);
+                       spin_unlock(&init_mm.page_table_lock);
+
                        kfree(tmp);
                        up(&imlist_sem);
-                       return ret_size;
+                       return;
                }
        }
        up(&imlist_sem);
        printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
                        addr);
-       return ret_size;
 }
index 4b42aff74d7312e7f2cdad4aa58dcdaa13a04e1b..6fa1e6490b5747d9ece0de44a9ae4828156a4597 100644 (file)
@@ -73,9 +73,6 @@ static unsigned long phbs_io_bot = PHBS_IO_BASE;
 extern pgd_t swapper_pg_dir[];
 extern struct task_struct *current_set[NR_CPUS];
 
-extern pgd_t ioremap_dir[];
-pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir;
-
 unsigned long klimit = (unsigned long)_end;
 
 unsigned long _SDR1=0;
@@ -137,69 +134,6 @@ void iounmap(volatile void __iomem *addr)
 
 #else
 
-static void unmap_im_area_pte(pmd_t *pmd, unsigned long addr,
-                                 unsigned long end)
-{
-       pte_t *pte;
-
-       pte = pte_offset_kernel(pmd, addr);
-       do {
-               pte_t ptent = ptep_get_and_clear(&ioremap_mm, addr, pte);
-               WARN_ON(!pte_none(ptent) && !pte_present(ptent));
-       } while (pte++, addr += PAGE_SIZE, addr != end);
-}
-
-static inline void unmap_im_area_pmd(pud_t *pud, unsigned long addr,
-                                    unsigned long end)
-{
-       pmd_t *pmd;
-       unsigned long next;
-
-       pmd = pmd_offset(pud, addr);
-       do {
-               next = pmd_addr_end(addr, end);
-               if (pmd_none_or_clear_bad(pmd))
-                       continue;
-               unmap_im_area_pte(pmd, addr, next);
-       } while (pmd++, addr = next, addr != end);
-}
-
-static inline void unmap_im_area_pud(pgd_t *pgd, unsigned long addr,
-                                    unsigned long end)
-{
-       pud_t *pud;
-       unsigned long next;
-
-       pud = pud_offset(pgd, addr);
-       do {
-               next = pud_addr_end(addr, end);
-               if (pud_none_or_clear_bad(pud))
-                       continue;
-               unmap_im_area_pmd(pud, addr, next);
-       } while (pud++, addr = next, addr != end);
-}
-
-static void unmap_im_area(unsigned long addr, unsigned long end)
-{
-       struct mm_struct *mm = &ioremap_mm;
-       unsigned long next;
-       pgd_t *pgd;
-
-       spin_lock(&mm->page_table_lock);
-
-       pgd = pgd_offset_i(addr);
-       flush_cache_vunmap(addr, end);
-       do {
-               next = pgd_addr_end(addr, end);
-               if (pgd_none_or_clear_bad(pgd))
-                       continue;
-               unmap_im_area_pud(pgd, addr, next);
-       } while (pgd++, addr = next, addr != end);
-       flush_tlb_kernel_range(start, end);
-
-       spin_unlock(&mm->page_table_lock);
-}
-
 /*
  * map_io_page currently only called by __ioremap
  * map_io_page adds an entry to the ioremap page table
@@ -214,21 +148,21 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
        unsigned long vsid;
 
        if (mem_init_done) {
-               spin_lock(&ioremap_mm.page_table_lock);
-               pgdp = pgd_offset_i(ea);
-               pudp = pud_alloc(&ioremap_mm, pgdp, ea);
+               spin_lock(&init_mm.page_table_lock);
+               pgdp = pgd_offset_k(ea);
+               pudp = pud_alloc(&init_mm, pgdp, ea);
                if (!pudp)
                        return -ENOMEM;
-               pmdp = pmd_alloc(&ioremap_mm, pudp, ea);
+               pmdp = pmd_alloc(&init_mm, pudp, ea);
                if (!pmdp)
                        return -ENOMEM;
-               ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
+               ptep = pte_alloc_kernel(&init_mm, pmdp, ea);
                if (!ptep)
                        return -ENOMEM;
                pa = abs_to_phys(pa);
-               set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
+               set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
                                                          __pgprot(flags)));
-               spin_unlock(&ioremap_mm.page_table_lock);
+               spin_unlock(&init_mm.page_table_lock);
        } else {
                unsigned long va, vpn, hash, hpteg;
 
@@ -267,13 +201,9 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
 
        for (i = 0; i < size; i += PAGE_SIZE)
                if (map_io_page(ea+i, pa+i, flags))
-                       goto failure;
+                       return NULL;
 
        return (void __iomem *) (ea + (addr & ~PAGE_MASK));
- failure:
-       if (mem_init_done)
-               unmap_im_area(ea, ea + size);
-       return NULL;
 }
 
 
@@ -381,19 +311,14 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
  */
 void iounmap(volatile void __iomem *token)
 {
-       unsigned long address, size;
        void *addr;
 
        if (!mem_init_done)
                return;
        
        addr = (void *) ((unsigned long __force) token & PAGE_MASK);
-       
-       if ((size = im_free(addr)) == 0)
-               return;
 
-       address = (unsigned long)addr; 
-       unmap_im_area(address, address + size);
+       im_free(addr);
 }
 
 static int iounmap_subset_regions(unsigned long addr, unsigned long size)
index 3c0ccb2623aeba4e89e9b43c439bf0c4ceafe1cd..7f6e13a4b71eec0c23330aaca24dcc76aa6a5971 100644 (file)
@@ -2247,7 +2247,14 @@ scanhex(unsigned long *vp)
                        tmpstr[i] = c;
                }
                tmpstr[i++] = 0;
-               *vp = kallsyms_lookup_name(tmpstr);
+               *vp = 0;
+               if (setjmp(bus_error_jmp) == 0) {
+                       catch_memory_errors = 1;
+                       sync();
+                       *vp = kallsyms_lookup_name(tmpstr);
+                       sync();
+               }
+               catch_memory_errors = 0;
                if (!(*vp)) {
                        printf("unknown symbol '%s'\n", tmpstr);
                        return 0;
index 03d03c6d3cbbea2cdce5b15f5988717220882d5e..24a1e9f069a7f0adb9ac9aab34fa6613243c0cd3 100644 (file)
@@ -42,7 +42,6 @@ struct ioctl_trans ioctl_start[] = {
 #include "../../../fs/compat_ioctl.c"
 
 /* s390 only ioctls */
-#if defined(CONFIG_DASD) || defined(CONFIG_DASD_MODULE)
 COMPATIBLE_IOCTL(DASDAPIVER)
 COMPATIBLE_IOCTL(BIODASDDISABLE)
 COMPATIBLE_IOCTL(BIODASDENABLE)
@@ -59,16 +58,11 @@ COMPATIBLE_IOCTL(BIODASDPRRD)
 COMPATIBLE_IOCTL(BIODASDPSRD)
 COMPATIBLE_IOCTL(BIODASDGATTR)
 COMPATIBLE_IOCTL(BIODASDSATTR)
-#if defined(CONFIG_DASD_CMB) || defined(CONFIG_DASD_CMB_MODULE)
 COMPATIBLE_IOCTL(BIODASDCMFENABLE)
 COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
 COMPATIBLE_IOCTL(BIODASDREADALLCMB)
-#endif
-#endif
 
-#if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE)
 COMPATIBLE_IOCTL(TAPE390_DISPLAY)
-#endif
 
 /* s390 doesn't need handlers here */
 COMPATIBLE_IOCTL(TIOCGSERIAL)
index b804c55bd919ee37b44d01bf5c64543b97ece822..fc8bf5e285f6ccb187fcd81d6a810e4ffe713543 100644 (file)
@@ -345,10 +345,25 @@ iplstart:
        bno   .Lnoreset
         la    %r2,.Lreset              
         lhi   %r3,26
-        .long 0x83230008
+       diag  %r2,%r3,8
+       mvc   0x78(8),.Lrdrnewpsw              # set up IO interrupt psw
+.Lwaitrdrirq:
+       lpsw  .Lrdrwaitpsw
+.Lrdrint:
+       c     %r1,0xb8                         # compare subchannel number
+       bne   .Lwaitrdrirq
+       la    %r5,.Lirb
+       tsch  0(%r5)
 .Lnoreset:
+        b     .Lnoload
+
+       .align 8
+.Lrdrnewpsw:
+       .long  0x00080000,0x80000000+.Lrdrint
+.Lrdrwaitpsw:
+       .long  0x020a0000,0x80000000+.Lrdrint
 #endif
-       
+
 #
 # everything loaded, go for it
 #
@@ -517,10 +532,10 @@ startup:basr  %r13,0                     # get base
        l     %r2, .Lrcp2-.LPG1(%r13)   # try with Read SCP
        b     .Lservicecall-.LPG1(%r13)
 .Lprocsccb:
-       lh    %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
-       chi   %r1,0x00
-       jne   .Lscnd
-       l     %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
+       lhi   %r1,0
+       icm   %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+       jnz   .Lscnd
+       l     %r1,.Lscpincr2-PARMAREA+4(%r4) # otherwise use this one
 .Lscnd:
        xr    %r3,%r3                   # same logic
        ic    %r3,.Lscpa1-PARMAREA(%r4)
index 8366793bc371522117fe869159a3c8cd8f39add3..f525c0c212500fad80ad0b98e5f6c9a525f8a2a8 100644 (file)
@@ -344,10 +344,25 @@ iplstart:
        bno   .Lnoreset
         la    %r2,.Lreset              
         lhi   %r3,26
-        .long 0x83230008
+       diag  %r2,%r3,8
+       mvc   0x78(8),.Lrdrnewpsw              # set up IO interrupt psw
+.Lwaitrdrirq:
+       lpsw  .Lrdrwaitpsw
+.Lrdrint:
+       c     %r1,0xb8                         # compare subchannel number
+       bne   .Lwaitrdrirq
+       la    %r5,.Lirb
+       tsch  0(%r5)
 .Lnoreset:
+       b     .Lnoload
+
+       .align 8
+.Lrdrnewpsw:
+       .long  0x00080000,0x80000000+.Lrdrint
+.Lrdrwaitpsw:
+       .long  0x020a0000,0x80000000+.Lrdrint
 #endif
-       
+
 #
 # everything loaded, go for it
 #
@@ -518,9 +533,9 @@ startup:basr  %r13,0                     # get base
        l     %r2,.Lrcp2-.LPG1(%r13)    # try with Read SCP
        b     .Lservicecall-.LPG1(%r13)
 .Lprocsccb:
-       lh    %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
-       chi   %r1,0x00
-       jne   .Lscnd
+       lghi  %r1,0
+       icm   %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+       jnz   .Lscnd
        lg    %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
 .Lscnd:
        xr    %r3,%r3                   # same logic
index 8b90e9528b911b882f04b9e686e2f727d0dad419..ca34b6f34b38e9efc78fc2a418d8390d9174233f 100644 (file)
@@ -668,7 +668,10 @@ asmlinkage void space_switch_exception(struct pt_regs * regs, long int_code)
 
 asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
 {
-       die("Kernel stack overflow", regs, 0);
+       bust_spinlocks(1);
+       printk("Kernel stack overflow.\n");
+       show_regs(regs);
+       bust_spinlocks(0);
        panic("Corrupt kernel stack, can't continue.");
 }
 
index f5a5bc09b8fa736b337f61e4eed6f49d58b07327..2d5cb1385753249e1d9b282a5b947563f36dc520 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/uaccess.h>
 
 static char *sender = "VMRMSVM";
-module_param(sender, charp, 0);
+module_param(sender, charp, 0400);
 MODULE_PARM_DESC(sender,
                 "Guest name that may send SMSG messages (default VMRMSVM)");
 
index df5ac294c37906cd575a9bd482b2478cdfbd4805..917b2f32f260888b2a84b272303edce8d0b5c1b6 100644 (file)
@@ -79,6 +79,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
+       if (len <= mm->cached_hole_size) {
+               mm->cached_hole_size = 0;
+               mm->free_area_cache = TASK_UNMAPPED_BASE;
+       }
        if (flags & MAP_PRIVATE)
                addr = PAGE_ALIGN(mm->free_area_cache);
        else
@@ -95,6 +99,7 @@ full_search:
                         */
                        if (start_addr != TASK_UNMAPPED_BASE) {
                                start_addr = addr = TASK_UNMAPPED_BASE;
+                               mm->cached_hole_size = 0;
                                goto full_search;
                        }
                        return -ENOMEM;
@@ -106,6 +111,9 @@ full_search:
                        mm->free_area_cache = addr + len;
                        return addr;
                }
+               if (addr + mm->cached_hole_size < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
+
                addr = vma->vm_end;
                if (!(flags & MAP_PRIVATE))
                        addr = COLOUR_ALIGN(addr);
index 50b36037d86b01e51c0f4c1107c2e43588a62974..351714694d6d4b9b6f81d183e774f1fc47e0e215 100644 (file)
@@ -24,7 +24,7 @@ inline void __const_udelay(unsigned long xloops)
        __asm__("dmulu.l        %0, %2\n\t"
                "sts    mach, %0"
                : "=r" (xloops)
-               : "0" (xloops), "r" (cpu_data[_smp_processor_id()].loops_per_jiffy)
+               : "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy)
                : "macl", "mach");
        __delay(xloops * HZ);
 }
index 1f897bab2318a00efa6a1d9f845f2c107cb33eff..95bb1a6c60609fa7567d4fa0928a44e689c3fc6e 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
        pmd_t *pmd;
@@ -39,7 +39,7 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        return pte;
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
        pmd_t *pmd;
@@ -56,28 +56,34 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 
 #define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
 
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
-                        struct page *page, pte_t * page_table, int write_access)
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, pte_t entry)
 {
-       unsigned long i;
-       pte_t entry;
+       int i;
 
-       add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
+       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+               set_pte_at(mm, addr, ptep, entry);
+               ptep++;
+               addr += PAGE_SIZE;
+               pte_val(entry) += 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);
-       mk_pte_huge(entry);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep)
+{
+       pte_t entry;
+       int i;
 
-       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-               set_pte(page_table, entry);
-               page_table++;
+       entry = *ptep;
 
-               pte_val(entry) += PAGE_SIZE;
+       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+               pte_clear(mm, addr, ptep);
+               addr += PAGE_SIZE;
+               ptep++;
        }
+
+       return entry;
 }
 
 /*
@@ -92,79 +98,6 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
        return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-                           struct vm_area_struct *vma)
-{
-       pte_t *src_pte, *dst_pte, entry;
-       struct page *ptepage;
-       unsigned long addr = vma->vm_start;
-       unsigned long end = vma->vm_end;
-       int i;
-
-       while (addr < end) {
-               dst_pte = huge_pte_alloc(dst, addr);
-               if (!dst_pte)
-                       goto nomem;
-               src_pte = huge_pte_offset(src, addr);
-               BUG_ON(!src_pte || pte_none(*src_pte));
-               entry = *src_pte;
-               ptepage = pte_page(entry);
-               get_page(ptepage);
-               for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-                       set_pte(dst_pte, entry);
-                       pte_val(entry) += PAGE_SIZE;
-                       dst_pte++;
-               }
-               add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-               addr += HPAGE_SIZE;
-       }
-       return 0;
-
-nomem:
-       return -ENOMEM;
-}
-
-int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-                       struct page **pages, struct vm_area_struct **vmas,
-                       unsigned long *position, int *length, int i)
-{
-       unsigned long vaddr = *position;
-       int remainder = *length;
-
-       WARN_ON(!is_vm_hugetlb_page(vma));
-
-       while (vaddr < vma->vm_end && remainder) {
-               if (pages) {
-                       pte_t *pte;
-                       struct page *page;
-
-                       pte = huge_pte_offset(mm, vaddr);
-
-                       /* hugetlb should be locked, and hence, prefaulted */
-                       BUG_ON(!pte || pte_none(*pte));
-
-                       page = pte_page(*pte);
-
-                       WARN_ON(!PageCompound(page));
-
-                       get_page(page);
-                       pages[i] = page;
-               }
-
-               if (vmas)
-                       vmas[i] = vma;
-
-               vaddr += PAGE_SIZE;
-               --remainder;
-               ++i;
-       }
-
-       *length = remainder;
-       *position = vaddr;
-
-       return i;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm,
                              unsigned long address, int write)
 {
@@ -181,84 +114,3 @@ struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
 {
        return NULL;
 }
-
-void unmap_hugepage_range(struct vm_area_struct *vma,
-                         unsigned long start, unsigned long end)
-{
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long address;
-       pte_t *pte;
-       struct page *page;
-       int i;
-
-       BUG_ON(start & (HPAGE_SIZE - 1));
-       BUG_ON(end & (HPAGE_SIZE - 1));
-
-       for (address = start; address < end; address += HPAGE_SIZE) {
-               pte = huge_pte_offset(mm, address);
-               BUG_ON(!pte);
-               if (pte_none(*pte))
-                       continue;
-               page = pte_page(*pte);
-               put_page(page);
-               for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-                       pte_clear(mm, address+(i*PAGE_SIZE), pte);
-                       pte++;
-               }
-       }
-       add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
-       flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-       struct mm_struct *mm = current->mm;
-       unsigned long addr;
-       int ret = 0;
-
-       BUG_ON(vma->vm_start & ~HPAGE_MASK);
-       BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-       spin_lock(&mm->page_table_lock);
-       for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-               unsigned long idx;
-               pte_t *pte = huge_pte_alloc(mm, addr);
-               struct page *page;
-
-               if (!pte) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               if (!pte_none(*pte))
-                       continue;
-
-               idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-                       + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-               page = find_get_page(mapping, idx);
-               if (!page) {
-                       /* charge the fs quota first */
-                       if (hugetlb_get_quota(mapping)) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       page = alloc_huge_page();
-                       if (!page) {
-                               hugetlb_put_quota(mapping);
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-                       if (! ret) {
-                               unlock_page(page);
-                       } else {
-                               hugetlb_put_quota(mapping);
-                               free_huge_page(page);
-                               goto out;
-                       }
-               }
-               set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
-       }
-out:
-       spin_unlock(&mm->page_table_lock);
-       return ret;
-}
index bcad2aefa4eeaa3809ae1bbcf0c4316b40cff183..dcd9c8a8baf84426daea75ca0d968b3891a40e21 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
        pmd_t *pmd;
@@ -39,7 +39,7 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        return pte;
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
        pmd_t *pmd;
@@ -80,6 +80,20 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
        }
 }
 
+pte_t huge_ptep_get_and_clear(pte_t *ptep)
+{
+       pte_t entry;
+
+       entry = *ptep;
+
+       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+               pte_clear(pte);
+               pte++;
+       }
+
+       return entry;
+}
+
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
index a2dea69b2f072a1dcaa55674abb7cf22b4e1449f..ec2e05028a10d7ff7804ef912833942e1e0fd20a 100644 (file)
@@ -384,7 +384,6 @@ void map_high_region(unsigned long start_pfn, unsigned long end_pfn)
                struct page *page = pfn_to_page(tmp);
 
                ClearPageReserved(page);
-               set_bit(PG_highmem, &page->flags);
                set_page_count(page, 1);
                __free_page(page);
                totalhigh_pages++;
index 0077f02f4b374e34ced8a57e03490a6dd06c2165..5f8c822a2b4a4a3dbcdab26809d94a90679682d8 100644 (file)
@@ -84,6 +84,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
                        return addr;
        }
 
+       if (len <= mm->cached_hole_size) {
+               mm->cached_hole_size = 0;
+               mm->free_area_cache = TASK_UNMAPPED_BASE;
+       }
        start_addr = addr = mm->free_area_cache;
 
        task_size -= len;
@@ -103,6 +107,7 @@ full_search:
                if (task_size < addr) {
                        if (start_addr != TASK_UNMAPPED_BASE) {
                                start_addr = addr = TASK_UNMAPPED_BASE;
+                               mm->cached_hole_size = 0;
                                goto full_search;
                        }
                        return -ENOMEM;
@@ -114,6 +119,9 @@ full_search:
                        mm->free_area_cache = addr + len;
                        return addr;
                }
+               if (addr + mm->cached_hole_size < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
+
                addr = vma->vm_end;
                if (do_color_align)
                        addr = COLOUR_ALIGN(addr, pgoff);
index f6b4c784d53e05111fbda459f465c04d20c8cc43..e8808727617a146aea231267d4fafe7beb8e8132 100644 (file)
@@ -31,7 +31,7 @@ void __const_udelay(unsigned long n)
 {
        n *= 4;
 
-       n *= (cpu_data(_smp_processor_id()).udelay_val * (HZ/4));
+       n *= (cpu_data(raw_smp_processor_id()).udelay_val * (HZ/4));
        n >>= 32;
 
        __delay(n + 1);
index 5a1f831b2de1b0ef92032a0ed34dff5a8ff48fcb..625cbb336a239df14cfe2eff88776cbb028353f6 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/cacheflush.h>
 #include <asm/mmu_context.h>
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -41,7 +41,7 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
        return pte;
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -62,30 +62,34 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 
 #define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
 
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
-                        unsigned long addr,
-                        struct page *page, pte_t * page_table, int write_access)
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, pte_t entry)
 {
-       unsigned long i;
-       pte_t entry;
+       int i;
+
+       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+               set_pte_at(mm, addr, ptep, entry);
+               ptep++;
+               addr += PAGE_SIZE;
+               pte_val(entry) += PAGE_SIZE;
+       }
+}
 
-       add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep)
+{
+       pte_t entry;
+       int i;
 
-       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);
-       mk_pte_huge(entry);
+       entry = *ptep;
 
        for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-               set_pte_at(mm, addr, page_table, entry);
-               page_table++;
+               pte_clear(mm, addr, ptep);
                addr += PAGE_SIZE;
-
-               pte_val(entry) += PAGE_SIZE;
+               ptep++;
        }
+
+       return entry;
 }
 
 /*
@@ -100,79 +104,6 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
        return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-                           struct vm_area_struct *vma)
-{
-       pte_t *src_pte, *dst_pte, entry;
-       struct page *ptepage;
-       unsigned long addr = vma->vm_start;
-       unsigned long end = vma->vm_end;
-       int i;
-
-       while (addr < end) {
-               dst_pte = huge_pte_alloc(dst, addr);
-               if (!dst_pte)
-                       goto nomem;
-               src_pte = huge_pte_offset(src, addr);
-               BUG_ON(!src_pte || pte_none(*src_pte));
-               entry = *src_pte;
-               ptepage = pte_page(entry);
-               get_page(ptepage);
-               for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-                       set_pte_at(dst, addr, dst_pte, entry);
-                       pte_val(entry) += PAGE_SIZE;
-                       dst_pte++;
-                       addr += PAGE_SIZE;
-               }
-               add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-       }
-       return 0;
-
-nomem:
-       return -ENOMEM;
-}
-
-int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-                       struct page **pages, struct vm_area_struct **vmas,
-                       unsigned long *position, int *length, int i)
-{
-       unsigned long vaddr = *position;
-       int remainder = *length;
-
-       WARN_ON(!is_vm_hugetlb_page(vma));
-
-       while (vaddr < vma->vm_end && remainder) {
-               if (pages) {
-                       pte_t *pte;
-                       struct page *page;
-
-                       pte = huge_pte_offset(mm, vaddr);
-
-                       /* hugetlb should be locked, and hence, prefaulted */
-                       BUG_ON(!pte || pte_none(*pte));
-
-                       page = pte_page(*pte);
-
-                       WARN_ON(!PageCompound(page));
-
-                       get_page(page);
-                       pages[i] = page;
-               }
-
-               if (vmas)
-                       vmas[i] = vma;
-
-               vaddr += PAGE_SIZE;
-               --remainder;
-               ++i;
-       }
-
-       *length = remainder;
-       *position = vaddr;
-
-       return i;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm,
                              unsigned long address, int write)
 {
@@ -190,34 +121,6 @@ struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
        return NULL;
 }
 
-void unmap_hugepage_range(struct vm_area_struct *vma,
-                         unsigned long start, unsigned long end)
-{
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long address;
-       pte_t *pte;
-       struct page *page;
-       int i;
-
-       BUG_ON(start & (HPAGE_SIZE - 1));
-       BUG_ON(end & (HPAGE_SIZE - 1));
-
-       for (address = start; address < end; address += HPAGE_SIZE) {
-               pte = huge_pte_offset(mm, address);
-               BUG_ON(!pte);
-               if (pte_none(*pte))
-                       continue;
-               page = pte_page(*pte);
-               put_page(page);
-               for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-                       pte_clear(mm, address+(i*PAGE_SIZE), pte);
-                       pte++;
-               }
-       }
-       add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
-       flush_tlb_range(vma, start, end);
-}
-
 static void context_reload(void *__data)
 {
        struct mm_struct *mm = __data;
@@ -226,12 +129,8 @@ static void context_reload(void *__data)
                load_secondary_context(mm);
 }
 
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+void hugetlb_prefault_arch_hook(struct mm_struct *mm)
 {
-       struct mm_struct *mm = current->mm;
-       unsigned long addr;
-       int ret = 0;
-
        /* On UltraSPARC-III+ and later, configure the second half of
         * the Data-TLB for huge pages.
         */
@@ -261,50 +160,4 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
                }
                spin_unlock(&ctx_alloc_lock);
        }
-
-       BUG_ON(vma->vm_start & ~HPAGE_MASK);
-       BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-       spin_lock(&mm->page_table_lock);
-       for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-               unsigned long idx;
-               pte_t *pte = huge_pte_alloc(mm, addr);
-               struct page *page;
-
-               if (!pte) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               if (!pte_none(*pte))
-                       continue;
-
-               idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-                       + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-               page = find_get_page(mapping, idx);
-               if (!page) {
-                       /* charge the fs quota first */
-                       if (hugetlb_get_quota(mapping)) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       page = alloc_huge_page();
-                       if (!page) {
-                               hugetlb_put_quota(mapping);
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-                       if (! ret) {
-                               unlock_page(page);
-                       } else {
-                               hugetlb_put_quota(mapping);
-                               free_huge_page(page);
-                               goto out;
-                       }
-               }
-               set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
-       }
-out:
-       spin_unlock(&mm->page_table_lock);
-       return ret;
 }
index ec8e074c4eac18ce7179f898390c8a250ed645b4..06740582717e4427da136ed80b139b4aa40cbf05 100644 (file)
@@ -317,8 +317,10 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi
                unsigned long *kcmsg;
                compat_size_t cmlen;
 
-               if(kern_msg.msg_controllen > sizeof(ctl) &&
-                  kern_msg.msg_controllen <= 256) {
+               if (kern_msg.msg_controllen <= sizeof(compat_size_t))
+                       return -EINVAL;
+
+               if(kern_msg.msg_controllen > sizeof(ctl)) {
                        err = -ENOBUFS;
                        ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
                        if(!ctl_buf)
index c5292181a6642f601986102255691d1924b6a37b..b8e952c88fd1280f704737c95ef3e387ca055f64 100644 (file)
@@ -35,6 +35,11 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
+# Used in kernel/irq/manage.c and include/linux/irq.h
+config IRQ_RELEASE_METHOD
+       bool
+       default y
+
 menu "UML-specific options"
 
 config MODE_TT
index f2a0c40a9204d5efa76437a45bcec5aaa84fb02d..3f073902351fb28cc82ac95be4a8de3a9f1586f9 100644 (file)
@@ -122,7 +122,7 @@ endif
 CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \
        -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
        -DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE-y) \
-       -DKERNEL_STACK_SIZE=$(STACK_SIZE))
+       -DKERNEL_STACK_SIZE=$(STACK_SIZE) -DSUBARCH=$(SUBARCH))
 
 #The wrappers will select whether using "malloc" or the kernel allocator.
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
index 025d3be8aca4ae522e40b6aaa2a8623834805243..0f59736db329587d079b910279a035d409f4e884 100644 (file)
@@ -406,14 +406,12 @@ void line_disable(struct tty_struct *tty, int current_irq)
        if(line->driver->read_irq == current_irq)
                free_irq_later(line->driver->read_irq, tty);
        else {
-               free_irq_by_irq_and_dev(line->driver->read_irq, tty);
                free_irq(line->driver->read_irq, tty);
        }
 
        if(line->driver->write_irq == current_irq)
                free_irq_later(line->driver->write_irq, tty);
        else {
-               free_irq_by_irq_and_dev(line->driver->write_irq, tty);
                free_irq(line->driver->write_irq, tty);
        }
 
@@ -758,7 +756,6 @@ static void unregister_winch(struct tty_struct *tty)
         if(winch->pid != -1)
                 os_kill_process(winch->pid, 1);
 
-        free_irq_by_irq_and_dev(WINCH_IRQ, winch);
         free_irq(WINCH_IRQ, winch);
         list_del(&winch->list);
         kfree(winch);
index 4eeaf88c1e97ba3bac425ff55b5cc904b4ee6d29..5388a7428691a2c4c12791b0e5370cd0b31685ba 100644 (file)
@@ -146,7 +146,6 @@ 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);
index b5ee07472f79bb266822383c4c57c14a21481f7b..c41efd207fcc23b33cf35b09edd94d1c841893c8 100644 (file)
@@ -257,7 +257,6 @@ 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;
index a4fdf3584ad2c455e6165de1f88e5cc9a75ce62b..d269a80f4b0c665b70ef6f32422a53474efcb7af 100644 (file)
@@ -69,7 +69,6 @@ int xterm_fd(int socket, int *pid_out)
         * isn't set) this will hang... */
        wait_for_completion(&data->ready);
 
-       free_irq_by_irq_and_dev(XTERM_IRQ, data);
        free_irq(XTERM_IRQ, data);
 
        ret = data->new_fd;
index d44fb52825479fb8c00f67360c547c37473e1877..9f18061ef4c98d16915f7f040709340ed6740ad2 100644 (file)
@@ -124,14 +124,16 @@ void irq_unlock(unsigned long flags)
        spin_unlock_irqrestore(&irq_spinlock, flags);
 }
 
-/*  presently hw_interrupt_type must define (startup || enable) &&
- *  disable && end */
+/* hw_interrupt_type must define (startup || enable) &&
+ * (shutdown || disable) && end */
 static void dummy(unsigned int irq)
 {
 }
 
-static struct hw_interrupt_type SIGIO_irq_type = {
+/* This is used for everything else than the timer. */
+static struct hw_interrupt_type normal_irq_type = {
        .typename = "SIGIO",
+       .release = free_irq_by_irq_and_dev,
        .disable = dummy,
        .enable = dummy,
        .ack = dummy,
@@ -140,6 +142,7 @@ static struct hw_interrupt_type SIGIO_irq_type = {
 
 static struct hw_interrupt_type SIGVTALRM_irq_type = {
        .typename = "SIGVTALRM",
+       .release = free_irq_by_irq_and_dev,
        .shutdown = dummy, /* never called */
        .disable = dummy,
        .enable = dummy,
@@ -160,7 +163,7 @@ void __init init_IRQ(void)
                irq_desc[i].status = IRQ_DISABLED;
                irq_desc[i].action = NULL;
                irq_desc[i].depth = 1;
-               irq_desc[i].handler = &SIGIO_irq_type;
+               irq_desc[i].handler = &normal_irq_type;
                enable_irq(i);
        }
 }
index b3074cbaa479ac3de6c42242006d8e5c1f33cb42..c3ccaf24f3e0722cc4e3cc1a9ab8458fd8f41fdf 100644 (file)
@@ -85,8 +85,6 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
                                next = irq_fd->next;
                                if(irq_fd->freed){
                                        free_irq(irq_fd->irq, irq_fd->id);
-                                       free_irq_by_irq_and_dev(irq_fd->irq,
-                                                               irq_fd->id);
                                }
                        }
                }
index c22825f13e40fda8ab8a2b21d8cc5df6fc04f6d4..5597bd39e6b54a9f9d93ac914327c5eb1fb264ed 100644 (file)
@@ -53,7 +53,6 @@ static void setup_highmem(unsigned long highmem_start,
        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);
        }
index c3faea21a996316fa2012c9c1f215305ee20ff93..3fd2554e60b6e58ff35b7af3b4141421f69ef1f1 100644 (file)
@@ -3,10 +3,6 @@
 # Licensed under the GPL
 #
 
-extra-y := unmap_fin.o
-targets := unmap.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.o uaccess_user.o
@@ -16,14 +12,3 @@ obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
 USER_OBJS := gdb.o time.o tracer.o
 
 include arch/um/scripts/Makefile.rules
-
-UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS))
-UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
-
-#XXX: partially copied from arch/um/scripts/Makefile.rules
-$(obj)/unmap.o: c_flags = -Wp,-MD,$(depfile) $(UNMAP_CFLAGS)
-
-$(obj)/unmap_fin.o : $(obj)/unmap.o
-       $(LD) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) -print-file-name=libc.a)
-       $(OBJCOPY) $(obj)/unmap_tmp.o $@ -G switcheroo
-
diff --git a/arch/um/kernel/tt/unmap.c b/arch/um/kernel/tt/unmap.c
deleted file mode 100644 (file)
index 3f7aecd..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <sys/mman.h>
-
-int switcheroo(int fd, int prot, void *from, void *to, int size)
-{
-       if(munmap(to, size) < 0){
-               return(-1);
-       }
-       if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
-               return(-1);
-       }
-       if(munmap(from, size) < 0){
-               return(-1);
-       }
-       return(0);
-}
-
-/*
- * 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:
- */
index dd5355500bdccdc66423761a0dd69ce88baca6bd..61dfd4fef752a0810f24cdfdee20fa89aecc497b 100644 (file)
@@ -14,19 +14,10 @@ SECTIONS
   /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
    * is remapped.*/
   __binary_start = .;
-#ifdef MODE_TT
-  .thread_private : {
-    __start_thread_private = .;
-    errno = .;
-    . += 4;
-    arch/um/kernel/tt/unmap_fin.o (.data)
-    __end_thread_private = .;
-  }
-  . = ALIGN(4096);
-  .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
 
-  /* We want it only if we are in MODE_TT. In both cases, however, when MODE_TT
-   * is off the resulting binary segfaults.*/
+#ifdef MODE_TT
+  .remap_data : { arch/um/sys-SUBARCH/unmap_fin.o (.data .bss) }
+  .remap : { arch/um/sys-SUBARCH/unmap_fin.o (.text) }
 
   . = ALIGN(4096);             /* Init code and data */
 #endif
index 98346c71149346f31be5f367535eea9ee00ca242..7459d09c233e37f99b840b4454ea2d295fd5c72f 100644 (file)
@@ -10,6 +10,12 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 $(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \
        $(CFLAGS_$(notdir $@))
 
+# The stubs and unmap.o can't try to call mcount or update basic block data
+define unprofile
+       $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
+endef
+
+
 quiet_cmd_make_link = SYMLINK $@
 cmd_make_link       = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
 
diff --git a/arch/um/scripts/Makefile.unmap b/arch/um/scripts/Makefile.unmap
new file mode 100644 (file)
index 0000000..37a8f97
--- /dev/null
@@ -0,0 +1,22 @@
+clean-files += unmap_tmp.o unmap_fin.o unmap.o
+
+ifdef CONFIG_MODE_TT
+
+#Always build unmap_fin.o
+extra-y += unmap_fin.o
+#Do dependency tracking for unmap.o (it will be always built, but won't get the tracking unless we use this).
+targets += unmap.o
+
+#XXX: partially copied from arch/um/scripts/Makefile.rules
+$(obj)/unmap.o: _c_flags = $(call unprofile,$(CFLAGS))
+
+quiet_cmd_wrapld = LD      $@
+define cmd_wrapld
+       $(LD) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) -print-file-name=libc.a); \
+       $(OBJCOPY) $(obj)/unmap_tmp.o $@ -G switcheroo
+endef
+
+$(obj)/unmap_fin.o : $(obj)/unmap.o FORCE
+       $(call if_changed,wrapld)
+
+endif
index 4351e5605506edc13a059fadcf48c6abd1f9a3c8..095bcdb0b9cc1f0a40a012b3511456fcee0957a4 100644 (file)
@@ -17,3 +17,5 @@ highmem.c-dir = mm
 module.c-dir = kernel
 
 subdir- := util
+
+include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c
new file mode 100644 (file)
index 0000000..1368752
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mman.h>
+#include <asm/unistd.h>
+
+static int errno;
+
+static inline _syscall2(int,munmap,void *,start,size_t,len)
+static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
+int switcheroo(int fd, int prot, void *from, void *to, int size)
+{
+       if(munmap(to, size) < 0){
+               return(-1);
+       }
+       if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
+               return(-1);
+       }
+       if(munmap(from, size) < 0){
+               return(-1);
+       }
+       return(0);
+}
index 608466ad6b22309c802f2df4af9ffca71dc21d98..2bc6f6849010d0ca27a7aeaa414bcfd9421fa3b8 100644 (file)
@@ -29,3 +29,5 @@ thunk.S-dir = lib
 module.c-dir = kernel
 
 subdir- := util
+
+include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c
new file mode 100644 (file)
index 0000000..bc7094c
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mman.h>
+#include <asm/unistd.h>
+
+static int errno;
+
+static inline _syscall2(int,munmap,void *,start,size_t,len)
+static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
+int switcheroo(int fd, int prot, void *from, void *to, int size)
+{
+       if(munmap(to, size) < 0){
+               return(-1);
+       }
+       if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
+               return(-1);
+       }
+       if(munmap(from, size) < 0){
+               return(-1);
+       }
+       return(0);
+}
index 1965efc974dc4d1312717c9a948e927a456ae884..c12edf5d97f02a6e3c87e90a8f55d3b8c73618aa 100644 (file)
@@ -312,6 +312,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        current->mm->brk = ex.a_bss +
                (current->mm->start_brk = N_BSSADDR(ex));
        current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+       current->mm->cached_hole_size = 0;
 
        set_mm_counter(current->mm, rss, 0);
        current->mm->mmap = NULL;
index 99b522052d16d9cae2f3c07f11afd9c3cdfb59e9..c8131f342cfc6de02b41e447b66bdaaee5e83b5b 100644 (file)
@@ -46,7 +46,7 @@ struct elf_phdr;
 
 #define IA32_EMULATOR 1
 
-#define ELF_ET_DYN_BASE                (TASK_UNMAPPED_32 + 0x1000000)
+#define ELF_ET_DYN_BASE                (TASK_UNMAPPED_BASE + 0x1000000)
 
 #undef ELF_ARCH
 #define ELF_ARCH EM_386
@@ -307,9 +307,6 @@ 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 *);
 
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
index 761b6d35e338d05e44d2e325808af9b20d81d25e..dce8bab4306cdc3c73abd6ef91529040487360fb 100644 (file)
@@ -656,7 +656,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 
        switch (code) { 
        case ARCH_SET_GS:
-               if (addr >= TASK_SIZE
+               if (addr >= TASK_SIZE_OF(task))
                        return -EPERM; 
                cpu = get_cpu();
                /* handle small bases via the GDT because that's faster to 
@@ -682,7 +682,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
        case ARCH_SET_FS:
                /* Not strictly needed for fs, but do it for symmetry
                   with gs */
-               if (addr >= TASK_SIZE)
+               if (addr >= TASK_SIZE_OF(task))
                        return -EPERM; 
                cpu = get_cpu();
                /* handle small bases via the GDT because that's faster to 
index 525f6a128a279c0f559392af0b962de4101e46e8..bbf64b59a21e217b64085f7ce378d7fa332a4bab 100644 (file)
@@ -257,12 +257,12 @@ static int putreg(struct task_struct *child,
                        value &= 0xffff;
                        return 0;
                case offsetof(struct user_regs_struct,fs_base):
-                       if (value >= TASK_SIZE)
+                       if (value >= TASK_SIZE_OF(child))
                                return -EIO;
                        child->thread.fs = value;
                        return 0;
                case offsetof(struct user_regs_struct,gs_base):
-                       if (value >= TASK_SIZE)
+                       if (value >= TASK_SIZE_OF(child))
                                return -EIO;
                        child->thread.gs = value;
                        return 0;
@@ -279,7 +279,7 @@ static int putreg(struct task_struct *child,
                        break;
                case offsetof(struct user_regs_struct, rip):
                        /* Check if the new RIP address is canonical */
-                       if (value >= TASK_SIZE)
+                       if (value >= TASK_SIZE_OF(child))
                                return -EIO;
                        break;
        }
@@ -419,6 +419,8 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
                break;
 
        case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+       {
+               int dsize = test_tsk_thread_flag(child, TIF_IA32) ? 3 : 7;
                ret = -EIO;
                if ((addr & 7) ||
                    addr > sizeof(struct user) - 7)
@@ -430,22 +432,22 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
                        break;
                /* Disallows to set a breakpoint into the vsyscall */
                case offsetof(struct user, u_debugreg[0]):
-                       if (data >= TASK_SIZE-7) break;
+                       if (data >= TASK_SIZE_OF(child) - dsize) break;
                        child->thread.debugreg0 = data;
                        ret = 0;
                        break;
                case offsetof(struct user, u_debugreg[1]):
-                       if (data >= TASK_SIZE-7) break;
+                       if (data >= TASK_SIZE_OF(child) - dsize) break;
                        child->thread.debugreg1 = data;
                        ret = 0;
                        break;
                case offsetof(struct user, u_debugreg[2]):
-                       if (data >= TASK_SIZE-7) break;
+                       if (data >= TASK_SIZE_OF(child) - dsize) break;
                        child->thread.debugreg2 = data;
                        ret = 0;
                        break;
                case offsetof(struct user, u_debugreg[3]):
-                       if (data >= TASK_SIZE-7) break;
+                       if (data >= TASK_SIZE_OF(child) - dsize) break;
                        child->thread.debugreg3 = data;
                        ret = 0;
                        break;
@@ -469,6 +471,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
                  break;
                }
                break;
+       }
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
        case PTRACE_CONT:    /* restart after signal. */
 
index dbebd5ccba6b067531c0f7425d2bd17ef08c2bfd..cc7821c68851d5334b01359f8dd892a5266fdf0b 100644 (file)
@@ -68,13 +68,7 @@ out:
 static void find_start_end(unsigned long flags, unsigned long *begin,
                           unsigned long *end)
 {
-#ifdef CONFIG_IA32_EMULATION
-       if (test_thread_flag(TIF_IA32)) { 
-               *begin = TASK_UNMAPPED_32;
-               *end = IA32_PAGE_OFFSET; 
-       } else 
-#endif
-       if (flags & MAP_32BIT) { 
+       if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
                /* This is usually used needed to map code in small
                   model, so it needs to be in the first 31bit. Limit
                   it to that.  This means we need to move the
@@ -84,10 +78,10 @@ static void find_start_end(unsigned long flags, unsigned long *begin,
                   of playground for now. -AK */ 
                *begin = 0x40000000; 
                *end = 0x80000000;              
-       } else { 
-               *begin = TASK_UNMAPPED_64; 
+       } else {
+               *begin = TASK_UNMAPPED_BASE;
                *end = TASK_SIZE; 
-               }
+       }
 } 
 
 unsigned long
@@ -111,6 +105,11 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
+       if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32))
+           && len <= mm->cached_hole_size) {
+               mm->cached_hole_size = 0;
+               mm->free_area_cache = begin;
+       }
        addr = mm->free_area_cache;
        if (addr < begin) 
                addr = begin; 
@@ -126,6 +125,7 @@ full_search:
                         */
                        if (start_addr != begin) {
                                start_addr = addr = begin;
+                               mm->cached_hole_size = 0;
                                goto full_search;
                        }
                        return -ENOMEM;
@@ -137,6 +137,9 @@ full_search:
                        mm->free_area_cache = addr + len;
                        return addr;
                }
+               if (addr + mm->cached_hole_size < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
+
                addr = vma->vm_end;
        }
 }
index 6e2d66472eb1938f50aa45c2e0306b124f7885b1..aed61a668a1bebbf5b4661cd5fad774e03cca895 100644 (file)
@@ -34,7 +34,7 @@ void __delay(unsigned long loops)
 
 inline void __const_udelay(unsigned long xloops)
 {
-       __delay(((xloops * cpu_data[_smp_processor_id()].loops_per_jiffy) >> 32) * HZ);
+       __delay(((xloops * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) * HZ);
 }
 
 void __udelay(unsigned long usecs)
index 5d6b2114cc9a4e5d30b9736a339dad5bc03839fc..57d3ab15a5c737aeda66c83ed6756cae3c9924e5 100644 (file)
@@ -350,7 +350,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
         * (error_code & 4) == 0, and that the fault was not a
         * protection error (error_code & 1) == 0.
         */
-       if (unlikely(address >= TASK_SIZE)) {
+       if (unlikely(address >= TASK_SIZE64)) {
                if (!(error_code & 5) &&
                      ((address >= VMALLOC_START && address < VMALLOC_END) ||
                       (address >= MODULES_VADDR && address < MODULES_END))) {
index ed41d9036bfc374c261d3d800bea543f191e3b70..aed4a9b97c1459adff1aafb111b4cee41a46b19b 100644 (file)
@@ -58,4 +58,6 @@ source "drivers/mmc/Kconfig"
 
 source "drivers/infiniband/Kconfig"
 
+source "drivers/sn/Kconfig"
+
 endmenu
index 15681de688f4802b7619d98dd17b285dc500a4cf..3167be54feddec9f788d63f7fe17e362b84fedd1 100644 (file)
@@ -61,6 +61,6 @@ obj-$(CONFIG_EISA)            += eisa/
 obj-$(CONFIG_CPU_FREQ)         += cpufreq/
 obj-$(CONFIG_MMC)              += mmc/
 obj-$(CONFIG_INFINIBAND)       += infiniband/
-obj-$(CONFIG_BLK_DEV_SGIIOC4)  += sn/
+obj-$(CONFIG_SGI_IOC4)         += sn/
 obj-y                          += firmware/
 obj-$(CONFIG_CRYPTO)           += crypto/
index ad7ae7ab8920434626690cd12a9c5be4c651547a..141b4c237a509dc9dab28fb105644b6ec5529859 100644 (file)
@@ -26,11 +26,8 @@ static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };
 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_addr,
-       .normal_i2c_range       = ignore,
        .probe                  = ignore,
-       .probe_range            = ignore,
        .ignore                 = ignore,
-       .ignore_range           = ignore,
        .force                  = ignore,
 };
 
index ff64d333e95f58c68ac45f83832e41060ecb9d1c..c9d671cf7857dbc7101e99d469fa24eed711ac60 100644 (file)
@@ -171,7 +171,7 @@ static void acpi_processor_idle (void)
        int                     sleep_ticks = 0;
        u32                     t1, t2 = 0;
 
-       pr = processors[_smp_processor_id()];
+       pr = processors[raw_smp_processor_id()];
        if (!pr)
                return;
 
index 5d4517ccc422c392e308b83376b2d537fce67485..904b27caf697df2c0d14d1cab426212bad27bb25 100644 (file)
@@ -87,7 +87,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
        for (i = 0; i < MAX_NR_ZONES; i++) {
                struct zone *z = &pg->node_zones[i];
                for (cpu = 0; cpu < NR_CPUS; cpu++) {
-                       struct per_cpu_pageset *ps = &z->pageset[cpu];
+                       struct per_cpu_pageset *ps = zone_pcp(z,cpu);
                        numa_hit += ps->numa_hit;
                        numa_miss += ps->numa_miss;
                        numa_foreign += ps->numa_foreign;
index 5ed6515ae01fe0fee127d23fa18717b688a7eb24..7ccf871d3c9dd77178fa9ca46fb3e5def6c33a0e 100644 (file)
@@ -929,6 +929,10 @@ config SCx200_GPIO
 
          If compiled as a module, it will be called scx200_gpio.
 
+config GPIO_VR41XX
+       tristate "NEC VR4100 series General-purpose I/O Unit support"
+       depends on CPU_VR41XX
+
 config RAW_DRIVER
        tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
        help
index e3f5c32aac55d24312054b1a0bc32d8c2d84e4df..1aff819f3832d33f11fc9a60a21bf2b30d847b30 100644 (file)
@@ -80,6 +80,7 @@ obj-$(CONFIG_PPDEV) += ppdev.o
 obj-$(CONFIG_NWBUTTON) += nwbutton.o
 obj-$(CONFIG_NWFLASH) += nwflash.o
 obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
 obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
 
 obj-$(CONFIG_WATCHDOG) += watchdog/
index d7fb452af7f988a4d289acc4f3ebcb0c0bac5efb..0c81652eaba65cc7895cb740a00a4bfdcffbd79f 100644 (file)
@@ -641,7 +641,7 @@ int ipmi_create_user(unsigned int          if_num,
                return -ENOMEM;
 
        down_read(&interfaces_sem);
-       if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
+       if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
        {
                rv = -EINVAL;
                goto out_unlock;
index 257b8ee605e555d14dc5da5495d14e609b891bbe..e3085b22a365b7104fbb6e29483cdf7531121e36 100644 (file)
@@ -484,7 +484,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
        return virtr + wrote;
 }
 
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
 static ssize_t read_port(struct file * file, char __user * buf,
                         size_t count, loff_t *ppos)
 {
@@ -744,7 +744,7 @@ static struct file_operations null_fops = {
        .write          = write_null,
 };
 
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
 static struct file_operations port_fops = {
        .llseek         = memory_lseek,
        .read           = read_port,
@@ -804,7 +804,7 @@ static int memory_open(struct inode * inode, struct file * filp)
                case 3:
                        filp->f_op = &null_fops;
                        break;
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
                case 4:
                        filp->f_op = &port_fops;
                        break;
@@ -846,7 +846,7 @@ static const struct {
        {1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
        {2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
        {3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
        {4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
 #endif
        {5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
new file mode 100644 (file)
index 0000000..683278b
--- /dev/null
@@ -0,0 +1,743 @@
+/*
+ *  Driver for NEC VR4100 series General-purpose I/O Unit.
+ *
+ *  Copyright (C) 2002 MontaVista Software Inc.
+ *     Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
+MODULE_LICENSE("GPL");
+
+static int major;      /* default is dynamic major device number */
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+#define GIU_TYPE1_START                0x0b000100UL
+#define GIU_TYPE1_SIZE         0x20UL
+
+#define GIU_TYPE2_START                0x0f000140UL
+#define GIU_TYPE2_SIZE         0x20UL
+
+#define GIU_TYPE3_START                0x0f000140UL
+#define GIU_TYPE3_SIZE         0x28UL
+
+#define GIU_PULLUPDOWN_START   0x0b0002e0UL
+#define GIU_PULLUPDOWN_SIZE    0x04UL
+
+#define GIUIOSELL      0x00
+#define GIUIOSELH      0x02
+#define GIUPIODL       0x04
+#define GIUPIODH       0x06
+#define GIUINTSTATL    0x08
+#define GIUINTSTATH    0x0a
+#define GIUINTENL      0x0c
+#define GIUINTENH      0x0e
+#define GIUINTTYPL     0x10
+#define GIUINTTYPH     0x12
+#define GIUINTALSELL   0x14
+#define GIUINTALSELH   0x16
+#define GIUINTHTSELL   0x18
+#define GIUINTHTSELH   0x1a
+#define GIUPODATL      0x1c
+#define GIUPODATEN     0x1c
+#define GIUPODATH      0x1e
+ #define PIOEN0                0x0100
+ #define PIOEN1                0x0200
+#define GIUPODAT       0x1e
+#define GIUFEDGEINHL   0x20
+#define GIUFEDGEINHH   0x22
+#define GIUREDGEINHL   0x24
+#define GIUREDGEINHH   0x26
+
+#define GIUUSEUPDN     0x1e0
+#define GIUTERMUPDN    0x1e2
+
+#define GPIO_HAS_PULLUPDOWN_IO         0x0001
+#define GPIO_HAS_OUTPUT_ENABLE         0x0002
+#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
+
+static spinlock_t giu_lock;
+static struct resource *giu_resource1;
+static struct resource *giu_resource2;
+static unsigned long giu_flags;
+static unsigned int giu_nr_pins;
+
+static void __iomem *giu_base;
+
+#define giu_read(offset)               readw(giu_base + (offset))
+#define giu_write(offset, value)       writew((value), giu_base + (offset))
+
+#define GPIO_PIN_OF_IRQ(irq)   ((irq) - GIU_IRQ_BASE)
+#define GIUINT_HIGH_OFFSET     16
+#define GIUINT_HIGH_MAX                32
+
+static inline uint16_t giu_set(uint16_t offset, uint16_t set)
+{
+       uint16_t data;
+
+       data = giu_read(offset);
+       data |= set;
+       giu_write(offset, data);
+
+       return data;
+}
+
+static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
+{
+       uint16_t data;
+
+       data = giu_read(offset);
+       data &= ~clear;
+       giu_write(offset, data);
+
+       return data;
+}
+
+static unsigned int startup_giuint_low_irq(unsigned int irq)
+{
+       unsigned int pin;
+
+       pin = GPIO_PIN_OF_IRQ(irq);
+       giu_write(GIUINTSTATL, 1 << pin);
+       giu_set(GIUINTENL, 1 << pin);
+
+       return 0;
+}
+
+static void shutdown_giuint_low_irq(unsigned int irq)
+{
+       giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static void enable_giuint_low_irq(unsigned int irq)
+{
+       giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+#define disable_giuint_low_irq shutdown_giuint_low_irq
+
+static void ack_giuint_low_irq(unsigned int irq)
+{
+       unsigned int pin;
+
+       pin = GPIO_PIN_OF_IRQ(irq);
+       giu_clear(GIUINTENL, 1 << pin);
+       giu_write(GIUINTSTATL, 1 << pin);
+}
+
+static void end_giuint_low_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static struct hw_interrupt_type giuint_low_irq_type = {
+       .typename       = "GIUINTL",
+       .startup        = startup_giuint_low_irq,
+       .shutdown       = shutdown_giuint_low_irq,
+       .enable         = enable_giuint_low_irq,
+       .disable        = disable_giuint_low_irq,
+       .ack            = ack_giuint_low_irq,
+       .end            = end_giuint_low_irq,
+};
+
+static unsigned int startup_giuint_high_irq(unsigned int irq)
+{
+       unsigned int pin;
+
+       pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+       giu_write(GIUINTSTATH, 1 << pin);
+       giu_set(GIUINTENH, 1 << pin);
+
+       return 0;
+}
+
+static void shutdown_giuint_high_irq(unsigned int irq)
+{
+       giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void enable_giuint_high_irq(unsigned int irq)
+{
+       giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+#define disable_giuint_high_irq        shutdown_giuint_high_irq
+
+static void ack_giuint_high_irq(unsigned int irq)
+{
+       unsigned int pin;
+
+       pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+       giu_clear(GIUINTENH, 1 << pin);
+       giu_write(GIUINTSTATH, 1 << pin);
+}
+
+static void end_giuint_high_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static struct hw_interrupt_type giuint_high_irq_type = {
+       .typename       = "GIUINTH",
+       .startup        = startup_giuint_high_irq,
+       .shutdown       = shutdown_giuint_high_irq,
+       .enable         = enable_giuint_high_irq,
+       .disable        = disable_giuint_high_irq,
+       .ack            = ack_giuint_high_irq,
+       .end            = end_giuint_high_irq,
+};
+
+static int giu_get_irq(unsigned int irq, struct pt_regs *regs)
+{
+       uint16_t pendl, pendh, maskl, maskh;
+       int i;
+
+       pendl = giu_read(GIUINTSTATL);
+       pendh = giu_read(GIUINTSTATH);
+       maskl = giu_read(GIUINTENL);
+       maskh = giu_read(GIUINTENH);
+
+       maskl &= pendl;
+       maskh &= pendh;
+
+       if (maskl) {
+               for (i = 0; i < 16; i++) {
+                       if (maskl & (1 << i))
+                               return GIU_IRQ(i);
+               }
+       } else if (maskh) {
+               for (i = 0; i < 16; i++) {
+                       if (maskh & (1 << i))
+                               return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
+               }
+       }
+
+       printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+              maskl, pendl, maskh, pendh);
+
+       atomic_inc(&irq_err_count);
+
+       return -EINVAL;
+}
+
+void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
+{
+       uint16_t mask;
+
+       if (pin < GIUINT_HIGH_OFFSET) {
+               mask = 1 << pin;
+               if (trigger != IRQ_TRIGGER_LEVEL) {
+                       giu_set(GIUINTTYPL, mask);
+                       if (signal == IRQ_SIGNAL_HOLD)
+                               giu_set(GIUINTHTSELL, mask);
+                       else
+                               giu_clear(GIUINTHTSELL, mask);
+                       if (current_cpu_data.cputype == CPU_VR4133) {
+                               switch (trigger) {
+                               case IRQ_TRIGGER_EDGE_FALLING:
+                                       giu_set(GIUFEDGEINHL, mask);
+                                       giu_clear(GIUREDGEINHL, mask);
+                                       break;
+                               case IRQ_TRIGGER_EDGE_RISING:
+                                       giu_clear(GIUFEDGEINHL, mask);
+                                       giu_set(GIUREDGEINHL, mask);
+                                       break;
+                               default:
+                                       giu_set(GIUFEDGEINHL, mask);
+                                       giu_set(GIUREDGEINHL, mask);
+                                       break;
+                               }
+                       }
+               } else {
+                       giu_clear(GIUINTTYPL, mask);
+                       giu_clear(GIUINTHTSELL, mask);
+               }
+               giu_write(GIUINTSTATL, mask);
+       } else if (pin < GIUINT_HIGH_MAX) {
+               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+               if (trigger != IRQ_TRIGGER_LEVEL) {
+                       giu_set(GIUINTTYPH, mask);
+                       if (signal == IRQ_SIGNAL_HOLD)
+                               giu_set(GIUINTHTSELH, mask);
+                       else
+                               giu_clear(GIUINTHTSELH, mask);
+                       if (current_cpu_data.cputype == CPU_VR4133) {
+                               switch (trigger) {
+                               case IRQ_TRIGGER_EDGE_FALLING:
+                                       giu_set(GIUFEDGEINHH, mask);
+                                       giu_clear(GIUREDGEINHH, mask);
+                                       break;
+                               case IRQ_TRIGGER_EDGE_RISING:
+                                       giu_clear(GIUFEDGEINHH, mask);
+                                       giu_set(GIUREDGEINHH, mask);
+                                       break;
+                               default:
+                                       giu_set(GIUFEDGEINHH, mask);
+                                       giu_set(GIUREDGEINHH, mask);
+                                       break;
+                               }
+                       }
+               } else {
+                       giu_clear(GIUINTTYPH, mask);
+                       giu_clear(GIUINTHTSELH, mask);
+               }
+               giu_write(GIUINTSTATH, mask);
+       }
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
+
+void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
+{
+       uint16_t mask;
+
+       if (pin < GIUINT_HIGH_OFFSET) {
+               mask = 1 << pin;
+               if (level == IRQ_LEVEL_HIGH)
+                       giu_set(GIUINTALSELL, mask);
+               else
+                       giu_clear(GIUINTALSELL, mask);
+               giu_write(GIUINTSTATL, mask);
+       } else if (pin < GIUINT_HIGH_MAX) {
+               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+               if (level == IRQ_LEVEL_HIGH)
+                       giu_set(GIUINTALSELH, mask);
+               else
+                       giu_clear(GIUINTALSELH, mask);
+               giu_write(GIUINTSTATH, mask);
+       }
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
+
+gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
+{
+       uint16_t reg, mask;
+
+       if (pin >= giu_nr_pins)
+               return GPIO_DATA_INVAL;
+
+       if (pin < 16) {
+               reg = giu_read(GIUPIODL);
+               mask = (uint16_t)1 << pin;
+       } else if (pin < 32) {
+               reg = giu_read(GIUPIODH);
+               mask = (uint16_t)1 << (pin - 16);
+       } else if (pin < 48) {
+               reg = giu_read(GIUPODATL);
+               mask = (uint16_t)1 << (pin - 32);
+       } else {
+               reg = giu_read(GIUPODATH);
+               mask = (uint16_t)1 << (pin - 48);
+       }
+
+       if (reg & mask)
+               return GPIO_DATA_HIGH;
+
+       return GPIO_DATA_LOW;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
+
+int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
+{
+       uint16_t offset, mask, reg;
+       unsigned long flags;
+
+       if (pin >= giu_nr_pins)
+               return -EINVAL;
+
+       if (pin < 16) {
+               offset = GIUPIODL;
+               mask = (uint16_t)1 << pin;
+       } else if (pin < 32) {
+               offset = GIUPIODH;
+               mask = (uint16_t)1 << (pin - 16);
+       } else if (pin < 48) {
+               offset = GIUPODATL;
+               mask = (uint16_t)1 << (pin - 32);
+       } else {
+               offset = GIUPODATH;
+               mask = (uint16_t)1 << (pin - 48);
+       }
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       reg = giu_read(offset);
+       if (data == GPIO_DATA_HIGH)
+               reg |= mask;
+       else
+               reg &= ~mask;
+       giu_write(offset, reg);
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
+
+int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
+{
+       uint16_t offset, mask, reg;
+       unsigned long flags;
+
+       if (pin >= giu_nr_pins)
+               return -EINVAL;
+
+       if (pin < 16) {
+               offset = GIUIOSELL;
+               mask = (uint16_t)1 << pin;
+       } else if (pin < 32) {
+               offset = GIUIOSELH;
+               mask = (uint16_t)1 << (pin - 16);
+       } else {
+               if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
+                       offset = GIUPODATEN;
+                       mask = (uint16_t)1 << (pin - 32);
+               } else {
+                       switch (pin) {
+                       case 48:
+                               offset = GIUPODATH;
+                               mask = PIOEN0;
+                               break;
+                       case 49:
+                               offset = GIUPODATH;
+                               mask = PIOEN1;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       reg = giu_read(offset);
+       if (dir == GPIO_OUTPUT)
+               reg |= mask;
+       else
+               reg &= ~mask;
+       giu_write(offset, reg);
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
+
+int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
+{
+       uint16_t reg, mask;
+       unsigned long flags;
+
+       if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
+               return -EPERM;
+
+       if (pin >= 15)
+               return -EINVAL;
+
+       mask = (uint16_t)1 << pin;
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
+               reg = giu_read(GIUTERMUPDN);
+               if (pull == GPIO_PULL_UP)
+                       reg |= mask;
+               else
+                       reg &= ~mask;
+               giu_write(GIUTERMUPDN, reg);
+
+               reg = giu_read(GIUUSEUPDN);
+               reg |= mask;
+               giu_write(GIUUSEUPDN, reg);
+       } else {
+               reg = giu_read(GIUUSEUPDN);
+               reg &= ~mask;
+               giu_write(GIUUSEUPDN, reg);
+       }
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
+
+static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
+                         loff_t *ppos)
+{
+       unsigned int pin;
+       char value = '0';
+
+       pin = iminor(file->f_dentry->d_inode);
+       if (pin >= giu_nr_pins)
+               return -EBADF;
+
+       if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
+               value = '1';
+
+       if (len <= 0)
+               return -EFAULT;
+
+       if (put_user(value, buf))
+               return -EFAULT;
+
+       return 1;
+}
+
+static ssize_t gpio_write(struct file *file, const char __user *data,
+                          size_t len, loff_t *ppos)
+{
+       unsigned int pin;
+       size_t i;
+       char c;
+       int retval = 0;
+
+       pin = iminor(file->f_dentry->d_inode);
+       if (pin >= giu_nr_pins)
+               return -EBADF;
+
+       for (i = 0; i < len; i++) {
+               if (get_user(c, data + i))
+                       return -EFAULT;
+
+               switch (c) {
+               case '0':
+                       retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
+                       break;
+               case '1':
+                       retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
+                       break;
+               case 'D':
+                       printk(KERN_INFO "GPIO%d: pull down\n", pin);
+                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
+                       break;
+               case 'd':
+                       printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
+                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
+                       break;
+               case 'I':
+                       printk(KERN_INFO "GPIO%d: input\n", pin);
+                       retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
+                       break;
+               case 'O':
+                       printk(KERN_INFO "GPIO%d: output\n", pin);
+                       retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
+                       break;
+               case 'o':
+                       printk(KERN_INFO "GPIO%d: output disable\n", pin);
+                       retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
+                       break;
+               case 'P':
+                       printk(KERN_INFO "GPIO%d: pull up\n", pin);
+                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
+                       break;
+               case 'p':
+                       printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
+                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
+                       break;
+               default:
+                       break;
+               }
+
+               if (retval < 0)
+                       break;
+       }
+
+       return i;
+}
+
+static int gpio_open(struct inode *inode, struct file *file)
+{
+       unsigned int pin;
+
+       pin = iminor(inode);
+       if (pin >= giu_nr_pins)
+               return -EBADF;
+
+       return nonseekable_open(inode, file);
+}
+
+static int gpio_release(struct inode *inode, struct file *file)
+{
+       unsigned int pin;
+
+       pin = iminor(inode);
+       if (pin >= giu_nr_pins)
+               return -EBADF;
+
+       return 0;
+}
+
+static struct file_operations gpio_fops = {
+       .owner          = THIS_MODULE,
+       .read           = gpio_read,
+       .write          = gpio_write,
+       .open           = gpio_open,
+       .release        = gpio_release,
+};
+
+static int giu_probe(struct device *dev)
+{
+       unsigned long start, size, flags = 0;
+       unsigned int nr_pins = 0;
+       struct resource *res1, *res2 = NULL;
+       void *base;
+       int retval, i;
+
+       switch (current_cpu_data.cputype) {
+       case CPU_VR4111:
+       case CPU_VR4121:
+               start = GIU_TYPE1_START;
+               size = GIU_TYPE1_SIZE;
+               flags = GPIO_HAS_PULLUPDOWN_IO;
+               nr_pins = 50;
+               break;
+       case CPU_VR4122:
+       case CPU_VR4131:
+               start = GIU_TYPE2_START;
+               size = GIU_TYPE2_SIZE;
+               nr_pins = 36;
+               break;
+       case CPU_VR4133:
+               start = GIU_TYPE3_START;
+               size = GIU_TYPE3_SIZE;
+               flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+               nr_pins = 48;
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       res1 = request_mem_region(start, size, "GIU");
+       if (res1 == NULL)
+               return -EBUSY;
+
+       base = ioremap(start, size);
+       if (base == NULL) {
+               release_resource(res1);
+               return -ENOMEM;
+       }
+
+       if (flags & GPIO_HAS_PULLUPDOWN_IO) {
+               res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
+               if (res2 == NULL) {
+                       iounmap(base);
+                       release_resource(res1);
+                       return -EBUSY;
+               }
+       }
+
+       retval = register_chrdev(major, "GIU", &gpio_fops);
+       if (retval < 0) {
+               iounmap(base);
+               release_resource(res1);
+               release_resource(res2);
+               return retval;
+       }
+
+       if (major == 0) {
+               major = retval;
+               printk(KERN_INFO "GIU: major number %d\n", major);
+       }
+
+       spin_lock_init(&giu_lock);
+       giu_base = base;
+       giu_resource1 = res1;
+       giu_resource2 = res2;
+       giu_flags = flags;
+       giu_nr_pins = nr_pins;
+
+       giu_write(GIUINTENL, 0);
+       giu_write(GIUINTENH, 0);
+
+       for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
+               if (i < GIU_IRQ(GIUINT_HIGH_OFFSET))
+                       irq_desc[i].handler = &giuint_low_irq_type;
+               else
+                       irq_desc[i].handler = &giuint_high_irq_type;
+       }
+
+       return cascade_irq(GIUINT_IRQ, giu_get_irq);
+}
+
+static int giu_remove(struct device *dev)
+{
+       iounmap(giu_base);
+
+       release_resource(giu_resource1);
+       if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
+               release_resource(giu_resource2);
+
+       return 0;
+}
+
+static struct platform_device *giu_platform_device;
+
+static struct device_driver giu_device_driver = {
+       .name           = "GIU",
+       .bus            = &platform_bus_type,
+       .probe          = giu_probe,
+       .remove         = giu_remove,
+};
+
+static int __devinit vr41xx_giu_init(void)
+{
+       int retval;
+
+       giu_platform_device = platform_device_register_simple("GIU", -1, NULL, 0);
+       if (IS_ERR(giu_platform_device))
+               return PTR_ERR(giu_platform_device);
+
+       retval = driver_register(&giu_device_driver);
+       if (retval < 0)
+               platform_device_unregister(giu_platform_device);
+
+       return retval;
+}
+
+static void __devexit vr41xx_giu_exit(void)
+{
+       driver_unregister(&giu_device_driver);
+
+       platform_device_unregister(giu_platform_device);
+}
+
+module_init(vr41xx_giu_init);
+module_exit(vr41xx_giu_exit);
index c3d912cbbbc339435cc1a57aa2c29b5e6bbbb210..cc3a952401f2ea8354cf89ac5e43c151bd151cbe 100644 (file)
@@ -49,7 +49,7 @@ static int i2c_debug=0;
 /*
  * Generate a start condition on the i2c bus.
  *
- * returns after the start condition has occured
+ * returns after the start condition has occurred
  */
 static void pca_start(struct i2c_algo_pca_data *adap)
 {
@@ -62,9 +62,9 @@ static void pca_start(struct i2c_algo_pca_data *adap)
 }
 
 /*
- * Generate a repeated start condition on the i2c bus 
+ * Generate a repeated start condition on the i2c bus
  *
- * return after the repeated start condition has occured
+ * return after the repeated start condition has occurred
  */
 static void pca_repeated_start(struct i2c_algo_pca_data *adap)
 {
@@ -82,7 +82,7 @@ static void pca_repeated_start(struct i2c_algo_pca_data *adap)
  * returns after the stop condition has been generated
  *
  * STOPs do not generate an interrupt or set the SI flag, since the
- * part returns the the idle state (0xf8). Hence we don't need to
+ * part returns the idle state (0xf8). Hence we don't need to
  * pca_wait here.
  */
 static void pca_stop(struct i2c_algo_pca_data *adap)
index 35789bb7126a3b5da6f09f2a2735280b5b46df33..f2785499237bf10135f571c0ebfddb9b9e4e5474 100644 (file)
@@ -24,7 +24,6 @@
 
 /* Ported for SiByte SOCs by Broadcom Corporation.  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
index a0018de3bef499f5485049c53ebe3196b786299c..916ba5e40a96dd9810a0e4014cefb46541054475 100644 (file)
@@ -7,7 +7,7 @@ menu "I2C Hardware Bus support"
 
 config I2C_ALI1535
        tristate "ALI 1535"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the SMB
          Host controller on Acer Labs Inc. (ALI) M1535 South Bridges.  The SMB
@@ -31,7 +31,7 @@ config I2C_ALI1563
 
 config I2C_ALI15X3
        tristate "ALI 15x3"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the
          Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
@@ -41,7 +41,7 @@ config I2C_ALI15X3
 
 config I2C_AMD756
        tristate "AMD 756/766/768/8111 and nVidia nForce"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the AMD
          756/766/768 mainboard I2C interfaces.  The driver also includes
@@ -66,7 +66,7 @@ config I2C_AMD756_S4882
 
 config I2C_AMD8111
        tristate "AMD 8111"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the
          second (SMBus 2.0) AMD 8111 mainboard I2C interface.
@@ -109,7 +109,7 @@ config I2C_HYDRA
 
 config I2C_I801
        tristate "Intel 82801 (ICH)"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the Intel
          801 family of mainboard I2C interfaces.  Specifically, the following
@@ -130,7 +130,7 @@ config I2C_I801
 
 config I2C_I810
        tristate "Intel 810/815"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the Intel
@@ -183,7 +183,7 @@ config I2C_IOP3XX
 
 config I2C_ISA
        tristate "ISA Bus support"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        help
          If you say yes to this option, support will be included for i2c
          interfaces that are on the ISA bus.
@@ -248,12 +248,11 @@ config I2C_MPC
          will be called i2c-mpc.
 
 config I2C_NFORCE2
-       tristate "Nvidia Nforce2"
-       depends on I2C && PCI && EXPERIMENTAL
+       tristate "Nvidia nForce2, nForce3 and nForce4"
+       depends on I2C && PCI
        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.
+         nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-nforce2.
@@ -305,7 +304,7 @@ config I2C_PARPORT_LIGHT
 
 config I2C_PROSAVAGE
        tristate "S3/VIA (Pro)Savage"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the
@@ -388,7 +387,7 @@ config SCx200_ACB
 
 config I2C_SIS5595
        tristate "SiS 5595"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the 
          SiS5595 SMBus (a subset of I2C) interface.
@@ -398,7 +397,7 @@ config I2C_SIS5595
 
 config I2C_SIS630
        tristate "SiS 630/730"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the 
          SiS630 and SiS730 SMBus (a subset of I2C) interface.
@@ -408,7 +407,7 @@ config I2C_SIS630
 
 config I2C_SIS96X
        tristate "SiS 96x"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the SiS
          96x SMBus (a subset of I2C) interfaces.  Specifically, the following
@@ -419,6 +418,7 @@ config I2C_SIS96X
            648/961
            650/961
            735
+           745
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-sis96x.
@@ -449,7 +449,7 @@ config I2C_VIA
 
 config I2C_VIAPRO
        tristate "VIA 82C596/82C686/823x"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the VIA
          82C596/82C686/823x I2C interfaces.  Specifically, the following 
@@ -467,7 +467,7 @@ config I2C_VIAPRO
 
 config I2C_VOODOO3
        tristate "Voodoo 3"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on I2C && PCI
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the
index b00cd409822192ce6766aa68be4e5bb7637685dd..f634a0780cf04b400a24ffb134967394b91c5b47 100644 (file)
@@ -53,7 +53,6 @@
 
 /* Note: we assume there can only be one ALI1535, with one SMBus interface */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
index 5bd6a4a77c1eec67922b9e04025766d79f917823..0f781a1a3323bc3c49c000ef1820ba7773d601ca 100644 (file)
@@ -60,7 +60,6 @@
 
 /* Note: we assume there can only be one ALI15X3, with one SMBus interface */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
index eca5ed3738b857acd6c6bb66f0ee7118cb1ffc7f..6347ebc6fb53522c1a423b5b6b21cb3589c55524 100644 (file)
@@ -37,7 +37,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
index af22b401a38bb335ea615a5aa4dfabfb1e0d3b94..d6644481d2a097230d508e02fcd57248d84fb927 100644 (file)
@@ -8,7 +8,6 @@
  * the Free Software Foundation version 2.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
index 75831a20b0bd2e30d7c24c4a7fc9e72dc5afb4cf..a7ff112e49bf28b5c0aed2ae46a353a9f56bf0bf 100644 (file)
@@ -27,7 +27,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index 0a7720000a0c5df173b9a92984834384d78a61b8..6930b660e508d8c4e4d54ed08f5a45f00bc106d2 100644 (file)
@@ -25,7 +25,6 @@
 /* Partialy rewriten by Oleg I. Vdovikin for mmapped support of 
    for Alpha Processor Inc. UP-2000(+) boards */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
index e093829a0bf73164bfbf7bc0e9dbf55b7f7deaa8..b6f52f5a4138ed1de7f0f9203b7263a3cc7d55ec 100644 (file)
@@ -12,7 +12,6 @@
  * version 2 as published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
index 59c238c42e8c306402a7e21b813a583eeb2307a0..45e6efb1dcd1356dadb5fbb7a5e6a8ca2d0fbcec 100644 (file)
@@ -41,7 +41,6 @@
 
 /* Note: we assume there can only be one I801, with one SMBus interface */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
index ef358bd9c3dad94560022a7239fa80c18e19a62f..0ff7016e0629b6bf5622c8f0d9fb5c10b022f97e 100644 (file)
@@ -34,7 +34,6 @@
    i815                        1132           
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
index bb885215c08d6c16dc103249ab41e5380947d9db..93ca36dc777e3cd474a798ecbaaf5081aa760e5d 100644 (file)
@@ -695,7 +695,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
 
        dev->irq = iic_force_poll ? -1 : ocp->def->irq;
        if (dev->irq >= 0){
-               /* Disable interrupts until we finish intialization,
+               /* Disable interrupts until we finish initialization,
                   assumes level-sensitive IRQ setup...
                 */
                iic_interrupt_mode(dev, 0);
index d819a955d890ecdf5c5897d9a1c9b58fad13d3c4..2b3219d00e92546a2ac190fbd67feb062e8d1f6a 100644 (file)
@@ -22,7 +22,6 @@
 #ifndef __I2C_IBM_IIC_H_
 #define __I2C_IBM_IIC_H_
 
-#include <linux/config.h>
 #include <linux/i2c.h> 
 
 struct iic_regs {
index c961ba4cfb3252e8d61611099012a2004e720e84..6b682e903f09c6735abaedf7f75508b9177c3cc0 100644 (file)
@@ -85,7 +85,7 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
        u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
 
        /* 
-        * Everytime unit enable is asserted, GPOD needs to be cleared
+        * Every time unit enable is asserted, GPOD needs to be cleared
         * on IOP321 to avoid data corruption on the bus.
         */
 #ifdef CONFIG_ARCH_IOP321
index 0f54a2a0afa5f06d36795331edd74f6c9a3261b7..00e7f7157b75d98f46ef085f9d311517a546a726 100644 (file)
@@ -24,7 +24,6 @@
    the SMBus and the ISA bus very much easier. See lm78.c for an example
    of this. */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
index 702e3def1b81f63c6c829f88eec93c0a5fb3db54..5f5d2944808b8b4b531896aad492c5f6ac0d834a 100644 (file)
@@ -33,7 +33,6 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
index 21cd54d0230261f8294ca7a546733ab1ee7bfec8..ec943cad23147524c917c1fe5d93de97ad6e90c6 100644 (file)
  * 'enabled' to drive the GPIOs.
  */
 
-#include <linux/config.h>
-#ifdef CONFIG_I2C_DEBUG_BUS
-#define DEBUG  1
-#endif
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/device.h>
index 8c55eafc3a0979bd9519b13720fcb870a3dacfe8..f6f5ca31fdba0955a1826d3c3781762a415e6619 100644 (file)
  *       that is passed as the platform_data to this driver.
  */
 
-#include <linux/config.h>
-#ifdef CONFIG_I2C_DEBUG_BUS
-#define DEBUG  1
-#endif
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/device.h>
index 867d443e7133f03c1f8999e4fe25e38f76f9419f..363e545fc01f137adc85f0eb38c3d8cc900a8432 100644 (file)
@@ -46,7 +46,6 @@
     sound driver to be happy
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
index 6f33496d31c31e6c57d3d2479db4afb4dad23617..d41ca31dbcb2357cf4a37c2028aefae144c966be 100644 (file)
@@ -325,7 +325,7 @@ static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
        if (i2c->irq != OCP_IRQ_NA)
        {
                if ((result = request_irq(ocp->def->irq, mpc_i2c_isr,
-                                         0, "i2c-mpc", i2c)) < 0) {
+                                         SA_SHIRQ, "i2c-mpc", i2c)) < 0) {
                        printk(KERN_ERR
                               "i2c-mpc - failed to attach interrupt\n");
                        goto fail_irq;
@@ -333,6 +333,9 @@ static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
        } else
                i2c->irq = 0;
 
+       mpc_i2c_setclock(i2c);
+       ocp_set_drvdata(ocp, i2c);
+
        i2c->adap = mpc_ops;
        i2c_set_adapdata(&i2c->adap, i2c);
 
@@ -341,8 +344,6 @@ static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
                goto fail_add;
        }
 
-       mpc_i2c_setclock(i2c);
-       ocp_set_drvdata(ocp, i2c);
        return result;
 
       fail_add:
@@ -358,8 +359,8 @@ static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
 static void __devexit mpc_i2c_remove(struct ocp_device *ocp)
 {
        struct mpc_i2c *i2c = ocp_get_drvdata(ocp);
-       ocp_set_drvdata(ocp, NULL);
        i2c_del_adapter(&i2c->adap);
+       ocp_set_drvdata(ocp, NULL);
 
        if (ocp->def->irq != OCP_IRQ_NA)
                free_irq(i2c->irq, i2c);
@@ -424,12 +425,15 @@ static int fsl_i2c_probe(struct device *device)
 
        if (i2c->irq != 0)
                if ((result = request_irq(i2c->irq, mpc_i2c_isr,
-                                         0, "fsl-i2c", i2c)) < 0) {
+                                         SA_SHIRQ, "i2c-mpc", i2c)) < 0) {
                        printk(KERN_ERR
                               "i2c-mpc - failed to attach interrupt\n");
                        goto fail_irq;
                }
 
+       mpc_i2c_setclock(i2c);
+       dev_set_drvdata(device, i2c);
+
        i2c->adap = mpc_ops;
        i2c_set_adapdata(&i2c->adap, i2c);
        i2c->adap.dev.parent = &pdev->dev;
@@ -438,8 +442,6 @@ static int fsl_i2c_probe(struct device *device)
                goto fail_add;
        }
 
-       mpc_i2c_setclock(i2c);
-       dev_set_drvdata(device, i2c);
        return result;
 
       fail_add:
@@ -456,8 +458,8 @@ static int fsl_i2c_remove(struct device *device)
 {
        struct mpc_i2c *i2c = dev_get_drvdata(device);
 
-       dev_set_drvdata(device, NULL);
        i2c_del_adapter(&i2c->adap);
+       dev_set_drvdata(device, NULL);
 
        if (i2c->irq != 0)
                free_irq(i2c->irq, i2c);
index 6d13127c8c4e12d36e8ca5a9cd8118666a4c6d2c..74eb89aa935084819903ff54d79722d5c368574a 100644 (file)
@@ -37,7 +37,6 @@
 
 /* Note: we assume there can only be one nForce2, with two SMBus interfaces */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
index cb5e722301d81177b6c922660eccf62f9a60dfad..3e5eba9fcacbdb2955da82e0ab81ad7ba49baaeb 100644 (file)
@@ -24,7 +24,6 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ------------------------------------------------------------------------ */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
index e9560bab51c490e4217c8f8493860713495b0bb1..71a2502fe0690e8b3e42c0ff95827f08f0c7d442 100644 (file)
@@ -24,7 +24,6 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ------------------------------------------------------------------------ */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -131,7 +130,7 @@ static int parport_getsda(void *data)
 /* Encapsulate the functions above in the correct structure.
    Note that this is only a template, from which the real structures are
    copied. The attaching code will set getscl to NULL for adapters that
-   cannot read SCL back, and will also make the the data field point to
+   cannot read SCL back, and will also make the data field point to
    the parallel port structure. */
 static struct i2c_algo_bit_data parport_algo_data = {
        .setsda         = parport_setsda,
index 9c611134db9caa3a5623b31fe132e8cf474aaaa3..d9b4ddbad7e0471fde88ecf6ca51dbea35717162 100644 (file)
@@ -17,7 +17,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
index 646381b6b3bf9e277aaedf15b2e7f41a2ca25b62..1f80ba9da6f18baf729f38c01e83bb87ab266fe9 100644 (file)
@@ -28,7 +28,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
index 13d66289933b9b44c7492065d81f440ff25f50b4..83fd16d61ce547d7675e0aea450dd00c2b1ab7a6 100644 (file)
@@ -54,7 +54,6 @@
  *    (Additional documentation needed :(
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
index 9497b1b6852ffbe19645638b06e7cd8db27410ea..0ebec3c1a54ef7426edcf1e8fcdde7d1d724994c 100644 (file)
@@ -11,7 +11,6 @@
  * changed to eliminate RPXLite references.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
index fcfa51c1436b5689c6ed27fec76db2f65d9d65d6..a3b38257cc3d51e9f4d9ab826c03edd7173a4523 100644 (file)
@@ -20,6 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 
@@ -533,7 +534,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
 /* s3c24xx_i2c_xfer
  *
  * first port of call from the i2c bus code when an message needs
- * transfering across the i2c bus.
+ * transferring across the i2c bus.
 */
 
 static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
index 092d0323c6c6fa70d5b7c1a82d1acf48ad2a1fca..0c8518298e4da3da0df6188849c6b3881393dabf 100644 (file)
@@ -29,7 +29,6 @@
    it easier to add later.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
index e5dd90bdb04aaa41af9f6d419b0c89a44111be31..1c99536b673b7775d97ff39091f112aa84cca17e 100644 (file)
@@ -17,7 +17,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/i2c-algo-sibyte.h>
 #include <asm/sibyte/sb1250_regs.h>
index 425733b019b6d7368ef5d18aa6659d9a5c67ca23..2b5911cfb7b5061381e9d98f8b0fb1bb77cd79ee 100644 (file)
@@ -55,7 +55,6 @@
  * Add adapter resets
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
index 58df63df15400d84eab965d7161a068947a5512e..f58455e7689e57da7aff99a086a4f6846153b329 100644 (file)
@@ -48,7 +48,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
index 3cac6d43bce576208c402fb9494471f5b8ef0b3a..6484792e23a1aacf9402ab41413ecb16987581e6 100644 (file)
@@ -32,7 +32,6 @@
     We assume there can only be one SiS96x with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
index 19c805ead4d89668afd290997588632a5b05ba1c..00d94e886955eb9b4374e2d8bd07dcab1ba5d04b 100644 (file)
@@ -21,7 +21,6 @@
 
 #define DEBUG 1
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
index 2cbc4cd22366586f9f281fc45fdaee43732f62ad..040b8abeabba8b3a4c8bd67976f2c875769f5ec5 100644 (file)
@@ -21,7 +21,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
index 0bb60a636e166a0cc370e061fea12d60fb7994a8..6b5008005c6fc1e276e9bf766d5eeb9815a997bf 100644 (file)
@@ -33,7 +33,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
index 3edf0e34155e1543c2f23fb20d240812fe4ce31e..b675773b0cc1d19a9222b87fd319027b4bfef773 100644 (file)
@@ -27,7 +27,6 @@
 /* This interfaces to the I2C bus of the Voodoo3 to gain access to
     the BT869 and possibly other I2C devices. */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
index 1c4159a93623fdfb39eaf32634c925ad1006f709..a18bdd9aa7ba29b65fa6d699b74ea6595cfff848 100644 (file)
@@ -24,7 +24,6 @@
 
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
index 74d23cfce2a34066a0566a8e348ead38a98a2344..a0982da09803ed42c94fc6a37a119bc81b9dc75a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# I2C Sensor device configuration
+# I2C Sensor and "other" chip configuration
 #
 
 menu "Hardware Sensors Chip support"
@@ -11,7 +11,7 @@ config I2C_SENSOR
 
 config SENSORS_ADM1021
        tristate "Analog Devices ADM1021 and compatibles"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        select I2C_SENSOR
        help
          If you say yes here you get support for Analog Devices ADM1021 
@@ -29,6 +29,7 @@ config SENSORS_ADM1025
        help
          If you say yes here you get support for Analog Devices ADM1025
          and Philips NE1619 sensor chips.
+
          This driver can also be built as a module.  If so, the module
          will be called adm1025.
 
@@ -38,6 +39,8 @@ config SENSORS_ADM1026
        select I2C_SENSOR
        help
          If you say yes here you get support for Analog Devices ADM1026
+         sensor chip.
+
          This driver can also be built as a module.  If so, the module
          will be called adm1026.
 
@@ -48,9 +51,21 @@ config SENSORS_ADM1031
        help
          If you say yes here you get support for Analog Devices ADM1031 
          and ADM1030 sensor chips.
+
          This driver can also be built as a module.  If so, the module
          will be called adm1031.
 
+config SENSORS_ADM9240
+       tristate "Analog Devices ADM9240 and compatibles"
+       depends on I2C && EXPERIMENTAL
+       select I2C_SENSOR
+       help
+         If you say yes here you get support for Analog Devices ADM9240,
+         Dallas DS1780, National Semiconductor LM81 sensor chips.
+
+         This driver can also be built as a module.  If so, the module
+         will be called adm9240.
+
 config SENSORS_ASB100
        tristate "Asus ASB100 Bach"
        depends on I2C && EXPERIMENTAL
@@ -62,6 +77,19 @@ config SENSORS_ASB100
          This driver can also be built as a module.  If so, the module
          will be called asb100.
 
+config SENSORS_ATXP1
+       tristate "Attansic ATXP1 VID controller"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for the Attansic ATXP1 VID
+         controller.
+
+         If your board have such a chip, you are able to control your CPU
+         core and other voltages.
+
+         This driver can also be built as a module.  If so, the module
+         will be called atxp1.
+
 config SENSORS_DS1621
        tristate "Dallas Semiconductor DS1621 and DS1625"
        depends on I2C && EXPERIMENTAL
@@ -97,7 +125,7 @@ config SENSORS_FSCPOS
 
 config SENSORS_GL518SM
        tristate "Genesys Logic GL518SM"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        select I2C_SENSOR
        help
          If you say yes here you get support for Genesys Logic GL518SM
@@ -119,7 +147,7 @@ config SENSORS_GL520SM
 
 config SENSORS_IT87
        tristate "ITE IT87xx and compatibles"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        select I2C_SENSOR
        help
          If you say yes here you get support for ITE IT87xx sensor chips
@@ -143,7 +171,7 @@ config SENSORS_LM63
 
 config SENSORS_LM75
        tristate "National Semiconductor LM75 and compatibles"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor LM75
@@ -174,8 +202,7 @@ config SENSORS_LM78
        select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor LM78,
-         LM78-J and LM79.  This can also be built as a module which can be
-         inserted and removed while the kernel is running.
+         LM78-J and LM79.
 
          This driver can also be built as a module.  If so, the module
          will be called lm78.
@@ -208,7 +235,7 @@ config SENSORS_LM85
        select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor LM85
-         sensor chips and clones: ADT7463 and ADM1027.
+         sensor chips and clones: ADT7463, EMC6D100, EMC6D102 and ADM1027.
 
          This driver can also be built as a module.  If so, the module
          will be called lm85.
@@ -307,14 +334,14 @@ config SENSORS_SMSC47M1
        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.
+         LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 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
+       depends on I2C && PCI
        select I2C_SENSOR
        select I2C_ISA
        help
@@ -326,7 +353,7 @@ config SENSORS_VIA686A
 
 config SENSORS_W83781D
        tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        select I2C_SENSOR
        help
          If you say yes here you get support for the Winbond W8378x series
@@ -360,22 +387,47 @@ config SENSORS_W83627HF
          This driver can also be built as a module.  If so, the module
          will be called w83627hf.
 
+config SENSORS_W83627EHF
+       tristate "Winbond W83627EHF"
+       depends on I2C && EXPERIMENTAL
+       select I2C_SENSOR
+       select I2C_ISA
+       help
+         If you say yes here you get preliminary support for the hardware
+         monitoring functionality of the Winbond W83627EHF Super-I/O chip.
+         Only fan and temperature inputs are supported at the moment, while
+         the chip does much more than that.
+
+         This driver can also be built as a module.  If so, the module
+         will be called w83627ehf.
+
 endmenu
 
 menu "Other I2C Chip support"
        depends on I2C
 
 config SENSORS_DS1337
-       tristate "Dallas Semiconductor DS1337 Real Time Clock"
+       tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
        depends on I2C && EXPERIMENTAL
        select I2C_SENSOR
        help
          If you say yes here you get support for Dallas Semiconductor
-         DS1337 real-time clock chips. 
+         DS1337 and DS1339 real-time clock chips.
 
          This driver can also be built as a module.  If so, the module
          will be called ds1337.
 
+config SENSORS_DS1374
+       tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
+       depends on I2C && EXPERIMENTAL
+       select I2C_SENSOR
+       help
+         If you say yes here you get support for Dallas Semiconductor
+         DS1374 real-time clock chips.
+
+         This driver can also be built as a module.  If so, the module
+         will be called ds1374.
+
 config SENSORS_EEPROM
        tristate "EEPROM reader"
        depends on I2C && EXPERIMENTAL
@@ -399,6 +451,16 @@ config SENSORS_PCF8574
          This driver can also be built as a module.  If so, the module
          will be called pcf8574.
 
+config SENSORS_PCA9539
+       tristate "Philips PCA9539 16-bit I/O port"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for the Philips PCA9539
+         16-bit I/O port.
+
+         This driver can also be built as a module.  If so, the module
+         will be called pca9539.
+
 config SENSORS_PCF8591
        tristate "Philips PCF8591"
        depends on I2C && EXPERIMENTAL
@@ -431,6 +493,23 @@ config ISP1301_OMAP
          This driver can also be built as a module.  If so, the module
          will be called isp1301_omap.
 
+# NOTE:  This isn't really OMAP-specific, except for the current
+# interface location in  <include/asm-arm/arch-omap/tps65010.h>
+# and having mostly OMAP-specific board support
+config TPS65010
+       tristate "TPS6501x Power Management chips"
+       depends on I2C && ARCH_OMAP
+       default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+       help
+         If you say yes here you get support for the TPS6501x series of
+         Power Management chips.  These include voltage regulators,
+         lithium ion/polymer battery charging, and other features that
+         are often used in portable devices like cell phones and cameras.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps65010.
+
+
 config SENSORS_M41T00
        tristate "ST M41T00 RTC chip"
        depends on I2C && PPC32
@@ -440,4 +519,16 @@ config SENSORS_M41T00
          This driver can also be built as a module.  If so, the module
          will be called m41t00.
 
+config SENSORS_MAX6875
+       tristate "MAXIM MAX6875 Power supply supervisor"
+       depends on I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for the MAX6875
+         EEPROM-Programmable, Hex/Quad, Power-Suppy Sequencers/Supervisors.
+
+          This provides a interface to program the EEPROM and reset the chip.
+
+         This driver can also be built as a module.  If so, the module
+         will be called max6875.
+
 endmenu
index 65599161a172dfaef11207e33d135395af371a0a..b5e6d2f84f9777c3c43220e6675c9f6228f0e6e7 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Makefile for the kernel hardware sensors chip drivers.
+# Makefile for sensor and "other" I2C chip drivers.
 #
 
 # asb100, then w83781d go first, as they can override other drivers' addresses.
@@ -11,7 +11,10 @@ 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_ADM9240)  += adm9240.o
+obj-$(CONFIG_SENSORS_ATXP1)    += atxp1.o
 obj-$(CONFIG_SENSORS_DS1337)   += ds1337.o
+obj-$(CONFIG_SENSORS_DS1374)   += ds1374.o
 obj-$(CONFIG_SENSORS_DS1621)   += ds1621.o
 obj-$(CONFIG_SENSORS_EEPROM)   += eeprom.o
 obj-$(CONFIG_SENSORS_FSCHER)   += fscher.o
@@ -30,8 +33,10 @@ obj-$(CONFIG_SENSORS_LM87)   += lm87.o
 obj-$(CONFIG_SENSORS_LM90)     += lm90.o
 obj-$(CONFIG_SENSORS_LM92)     += lm92.o
 obj-$(CONFIG_SENSORS_MAX1619)  += max1619.o
+obj-$(CONFIG_SENSORS_MAX6875)  += max6875.o
 obj-$(CONFIG_SENSORS_M41T00)   += m41t00.o
 obj-$(CONFIG_SENSORS_PC87360)  += pc87360.o
+obj-$(CONFIG_SENSORS_PCA9539)  += pca9539.o
 obj-$(CONFIG_SENSORS_PCF8574)  += pcf8574.o
 obj-$(CONFIG_SENSORS_PCF8591)  += pcf8591.o
 obj-$(CONFIG_SENSORS_RTC8564)  += rtc8564.o
@@ -39,8 +44,11 @@ obj-$(CONFIG_SENSORS_SIS5595)        += sis5595.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
 obj-$(CONFIG_SENSORS_VIA686A)  += via686a.o
+obj-$(CONFIG_SENSORS_W83627EHF)        += w83627ehf.o
 obj-$(CONFIG_SENSORS_W83L785TS)        += w83l785ts.o
+
 obj-$(CONFIG_ISP1301_OMAP)     += isp1301_omap.o
+obj-$(CONFIG_TPS65010)         += tps65010.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
index 9058c3956710d38c5444e50876fbd31c6f4800b1..d2c774c32f45b942a92453eb110346fa028e7bd7 100644 (file)
@@ -19,7 +19,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -103,8 +102,6 @@ struct adm1021_data {
        u8      remote_temp_hyst;
        u8      remote_temp_input;
        u8      alarms;
-       /* special values for ADM1021 only */
-       u8      die_code;
         /* Special values for ADM1023 only */
        u8      remote_temp_prec;
        u8      remote_temp_os_prec;
@@ -156,7 +153,6 @@ static ssize_t show_##value(struct device *dev, struct device_attribute *attr, c
        return sprintf(buf, "%d\n", data->value);                       \
 }
 show2(alarms);
-show2(die_code);
 
 #define set(value, reg)        \
 static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)   \
@@ -183,7 +179,6 @@ static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remot
 static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
 static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote_temp_input, NULL);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-static DEVICE_ATTR(die_code, S_IRUGO, show_die_code, NULL);
 
 
 static int adm1021_attach_adapter(struct i2c_adapter *adapter)
@@ -307,8 +302,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
        device_create_file(&new_client->dev, &dev_attr_temp2_min);
        device_create_file(&new_client->dev, &dev_attr_temp2_input);
        device_create_file(&new_client->dev, &dev_attr_alarms);
-       if (data->type == adm1021)
-               device_create_file(&new_client->dev, &dev_attr_die_code);
 
        return 0;
 
@@ -371,8 +364,6 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
                data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
                data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
                data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0x7c;
-               if (data->type == adm1021)
-                       data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE);
                if (data->type == adm1023) {
                        data->remote_temp_prec = adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
                        data->remote_temp_os_prec = adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
index 111f0c86c9337d9f7733d127c5c399850066d13d..e452d0daf906e314f9b0a2444aa64a9b93803609 100644 (file)
@@ -45,7 +45,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -287,7 +286,9 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
        struct adm1025_data *data = adm1025_update_device(dev);
        return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
 }
+/* in1_ref is deprecated in favour of cpu0_vid, remove after 2005-11-11 */
 static DEVICE_ATTR(in1_ref, S_IRUGO, show_vid, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
 static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -437,7 +438,9 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
        device_create_file(&new_client->dev, &dev_attr_temp1_max);
        device_create_file(&new_client->dev, &dev_attr_temp2_max);
        device_create_file(&new_client->dev, &dev_attr_alarms);
+       /* in1_ref is deprecated, remove after 2005-11-11 */
        device_create_file(&new_client->dev, &dev_attr_in1_ref);
+       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
        device_create_file(&new_client->dev, &dev_attr_vrm);
 
        /* Pin 11 is either in4 (+12V) or VID4 */
index b15fafe8f1116340604f20d3dbde248d041d48bf..3c85fe150cd754831f989f88151a14b5e77482ae 100644 (file)
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
-#include <linux/i2c-sysfs.h>
 #include <linux/i2c-vid.h>
+#include <linux/hwmon-sysfs.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
@@ -1225,8 +1224,9 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, c
        struct adm1026_data *data = adm1026_update_device(dev);
        return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
 }
-
+/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
 static DEVICE_ATTR(vid, 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, struct device_attribute *attr, char *buf)
 {
@@ -1666,7 +1666,9 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
        device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
        device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
        device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
+       /* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
        device_create_file(&new_client->dev, &dev_attr_vid);
+       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
        device_create_file(&new_client->dev, &dev_attr_vrm);
        device_create_file(&new_client->dev, &dev_attr_alarms);
        device_create_file(&new_client->dev, &dev_attr_alarm_mask);
index 2163dba467c47a3dfb5282d255dada96ffe89d7f..9168e983ca1d53b4a946316e22da7a362ca89c8e 100644 (file)
@@ -440,7 +440,7 @@ pwm_reg(2);
 
 /*
  * That function checks the cases where the fan reading is not
- * relevent.  It is used to provide 0 as fan reading when the fan is
+ * relevant.  It is used to provide 0 as fan reading when the fan is
  * not supposed to run
  */
 static int trust_fan_readings(struct adm1031_data *data, int chan)
diff --git a/drivers/i2c/chips/adm9240.c b/drivers/i2c/chips/adm9240.c
new file mode 100644 (file)
index 0000000..5c68e9c
--- /dev/null
@@ -0,0 +1,791 @@
+/*
+ * adm9240.c   Part of lm_sensors, Linux kernel modules for hardware
+ *             monitoring
+ *
+ * Copyright (C) 1999  Frodo Looijaard <frodol@dds.nl>
+ *                     Philip Edelbrock <phil@netroedge.com>
+ * Copyright (C) 2003  Michiel Rook <michiel@grendelproject.nl>
+ * Copyright (C) 2005  Grant Coady <gcoady@gmail.com> with valuable
+ *                             guidance from Jean Delvare
+ *
+ * Driver supports     Analog Devices          ADM9240
+ *                     Dallas Semiconductor    DS1780
+ *                     National Semiconductor  LM81
+ *
+ * ADM9240 is the reference, DS1780 and LM81 are register compatibles
+ *
+ * Voltage     Six inputs are scaled by chip, VID also reported
+ * Temperature Chip temperature to 0.5'C, maximum and max_hysteris
+ * Fans                2 fans, low speed alarm, automatic fan clock divider
+ * Alarms      16-bit map of active alarms
+ * Analog Out  0..1250 mV output
+ *
+ * Chassis Intrusion: clear CI latch with 'echo 1 > chassis_clear'
+ *
+ * Test hardware: Intel SE440BX-2 desktop motherboard --Grant
+ *
+ * LM81 extended temp reading not implemented
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
+                                       I2C_CLIENT_END };
+
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_3(adm9240, ds1780, lm81);
+
+/* ADM9240 registers */
+#define ADM9240_REG_MAN_ID             0x3e
+#define ADM9240_REG_DIE_REV            0x3f
+#define ADM9240_REG_CONFIG             0x40
+
+#define ADM9240_REG_IN(nr)             (0x20 + (nr))   /* 0..5 */
+#define ADM9240_REG_IN_MAX(nr)         (0x2b + (nr) * 2)
+#define ADM9240_REG_IN_MIN(nr)         (0x2c + (nr) * 2)
+#define ADM9240_REG_FAN(nr)            (0x28 + (nr))   /* 0..1 */
+#define ADM9240_REG_FAN_MIN(nr)                (0x3b + (nr))
+#define ADM9240_REG_INT(nr)            (0x41 + (nr))
+#define ADM9240_REG_INT_MASK(nr)       (0x43 + (nr))
+#define ADM9240_REG_TEMP               0x27
+#define ADM9240_REG_TEMP_HIGH          0x39
+#define ADM9240_REG_TEMP_HYST          0x3a
+#define ADM9240_REG_ANALOG_OUT         0x19
+#define ADM9240_REG_CHASSIS_CLEAR      0x46
+#define ADM9240_REG_VID_FAN_DIV                0x47
+#define ADM9240_REG_I2C_ADDR           0x48
+#define ADM9240_REG_VID4               0x49
+#define ADM9240_REG_TEMP_CONF          0x4b
+
+/* generalised scaling with integer rounding */
+static inline int SCALE(long val, int mul, int div)
+{
+       if (val < 0)
+               return (val * mul - div / 2) / div;
+       else
+               return (val * mul + div / 2) / div;
+}
+
+/* adm9240 internally scales voltage measurements */
+static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 };
+
+static inline unsigned int IN_FROM_REG(u8 reg, int n)
+{
+       return SCALE(reg, nom_mv[n], 192);
+}
+
+static inline u8 IN_TO_REG(unsigned long val, int n)
+{
+       return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
+}
+
+/* temperature range: -40..125, 127 disables temperature alarm */
+static inline s8 TEMP_TO_REG(long val)
+{
+       return SENSORS_LIMIT(SCALE(val, 1, 1000), -40, 127);
+}
+
+/* two fans, each with low fan speed limit */
+static inline unsigned int FAN_FROM_REG(u8 reg, u8 div)
+{
+       if (!reg) /* error */
+               return -1;
+
+       if (reg == 255)
+               return 0;
+
+       return SCALE(1350000, 1, reg * div);
+}
+
+/* analog out 0..1250mV */
+static inline u8 AOUT_TO_REG(unsigned long val)
+{
+       return SENSORS_LIMIT(SCALE(val, 255, 1250), 0, 255);
+}
+
+static inline unsigned int AOUT_FROM_REG(u8 reg)
+{
+       return SCALE(reg, 1250, 255);
+}
+
+static int adm9240_attach_adapter(struct i2c_adapter *adapter);
+static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind);
+static void adm9240_init_client(struct i2c_client *client);
+static int adm9240_detach_client(struct i2c_client *client);
+static struct adm9240_data *adm9240_update_device(struct device *dev);
+
+/* driver data */
+static struct i2c_driver adm9240_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "adm9240",
+       .id             = I2C_DRIVERID_ADM9240,
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = adm9240_attach_adapter,
+       .detach_client  = adm9240_detach_client,
+};
+
+/* per client data */
+struct adm9240_data {
+       enum chips type;
+       struct i2c_client client;
+       struct semaphore update_lock;
+       char valid;
+       unsigned long last_updated_measure;
+       unsigned long last_updated_config;
+
+       u8 in[6];               /* ro   in0_input */
+       u8 in_max[6];           /* rw   in0_max */
+       u8 in_min[6];           /* rw   in0_min */
+       u8 fan[2];              /* ro   fan1_input */
+       u8 fan_min[2];          /* rw   fan1_min */
+       u8 fan_div[2];          /* rw   fan1_div, read-only accessor */
+       s16 temp;               /* ro   temp1_input, 9-bit sign-extended */
+       s8 temp_high;           /* rw   temp1_max */
+       s8 temp_hyst;           /* rw   temp1_max_hyst */
+       u16 alarms;             /* ro   alarms */
+       u8 aout;                /* rw   aout_output */
+       u8 vid;                 /* ro   vid */
+       u8 vrm;                 /* --   vrm set on startup, no accessor */
+};
+
+/* i2c byte read/write interface */
+static int adm9240_read_value(struct i2c_client *client, u8 reg)
+{
+       return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+       return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/*** sysfs accessors ***/
+
+/* temperature */
+#define show_temp(value, scale)                                        \
+static ssize_t show_##value(struct device *dev,                        \
+                           struct device_attribute *attr,      \
+                           char *buf)                          \
+{                                                              \
+       struct adm9240_data *data = adm9240_update_device(dev); \
+       return sprintf(buf, "%d\n", data->value * scale);       \
+}
+show_temp(temp_high, 1000);
+show_temp(temp_hyst, 1000);
+show_temp(temp, 500); /* 0.5'C per bit */
+
+#define set_temp(value, reg)                                   \
+static ssize_t set_##value(struct device *dev,                         \
+                          struct device_attribute *attr,       \
+                          const char *buf, size_t count)       \
+{                                                              \
+       struct i2c_client *client = to_i2c_client(dev);         \
+       struct adm9240_data *data = adm9240_update_device(dev); \
+       long temp = simple_strtoul(buf, NULL, 10);              \
+                                                               \
+       down(&data->update_lock);                               \
+       data->value = TEMP_TO_REG(temp);                        \
+       adm9240_write_value(client, reg, data->value);          \
+       up(&data->update_lock);                                 \
+       return count;                                           \
+}
+
+set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
+set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
+
+static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+               show_temp_high, set_temp_high);
+static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+               show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+
+/* voltage */
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
+}
+
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
+}
+
+static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
+}
+
+static ssize_t set_in_min(struct device *dev, const char *buf,
+               size_t count, int nr)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adm9240_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->in_min[nr] = IN_TO_REG(val, nr);
+       adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]);
+       up(&data->update_lock);
+       return count;
+}
+
+static ssize_t set_in_max(struct device *dev, const char *buf,
+               size_t count, int nr)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adm9240_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->in_max[nr] = IN_TO_REG(val, nr);
+       adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]);
+       up(&data->update_lock);
+       return count;
+}
+
+#define show_in_offset(offset)                                         \
+static ssize_t show_in##offset(struct device *dev,                     \
+                              struct device_attribute *attr,           \
+                              char *buf)                               \
+{                                                                      \
+       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,               \
+                                    struct device_attribute *attr,     \
+                                    char *buf)                         \
+{                                                                      \
+       return show_in_min(dev, buf, offset);                           \
+}                                                                      \
+static ssize_t show_in##offset##_max(struct device *dev,               \
+                                    struct device_attribute *attr,     \
+                                    char *buf)                         \
+{                                                                      \
+       return show_in_max(dev, buf, offset);                           \
+}                                                                      \
+static ssize_t                                                         \
+set_in##offset##_min(struct device *dev,                               \
+                    struct device_attribute *attr, const char *buf,    \
+                    size_t count)                                      \
+{                                                                      \
+       return set_in_min(dev, buf, count, offset);                     \
+}                                                                      \
+static ssize_t                                                         \
+set_in##offset##_max(struct device *dev,                               \
+                    struct device_attribute *attr, const char *buf,    \
+                    size_t count)                                      \
+{                                                                      \
+       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);           \
+static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,                        \
+               show_in##offset##_max, set_in##offset##_max);
+
+show_in_offset(0);
+show_in_offset(1);
+show_in_offset(2);
+show_in_offset(3);
+show_in_offset(4);
+show_in_offset(5);
+
+/* fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
+                               1 << data->fan_div[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+                               1 << data->fan_div[nr]));
+}
+
+static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%d\n", 1 << data->fan_div[nr]);
+}
+
+/* write new fan div, callers must hold data->update_lock */
+static void adm9240_write_fan_div(struct i2c_client *client, int nr,
+               u8 fan_div)
+{
+       u8 reg, old, shift = (nr + 2) * 2;
+
+       reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+       old = (reg >> shift) & 3;
+       reg &= ~(3 << shift);
+       reg |= (fan_div << shift);
+       adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg);
+       dev_dbg(&client->dev, "fan%d clock divider changed from %u "
+                       "to %u\n", nr + 1, 1 << old, 1 << fan_div);
+}
+
+/* 
+ * set fan speed low limit:
+ *
+ * - value is zero: disable fan speed low limit alarm
+ *
+ * - value is below fan speed measurement range: enable fan speed low
+ *   limit alarm to be asserted while fan speed too slow to measure
+ *
+ * - otherwise: select fan clock divider to suit fan speed low limit,
+ *   measurement code may adjust registers to ensure fan speed reading
+ */
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+               size_t count, int nr)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adm9240_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+       u8 new_div;
+
+       down(&data->update_lock);
+
+       if (!val) {
+               data->fan_min[nr] = 255;
+               new_div = data->fan_div[nr];
+
+               dev_dbg(&client->dev, "fan%u low limit set disabled\n",
+                               nr + 1);
+
+       } else if (val < 1350000 / (8 * 254)) {
+               new_div = 3;
+               data->fan_min[nr] = 254;
+
+               dev_dbg(&client->dev, "fan%u low limit set minimum %u\n",
+                               nr + 1, FAN_FROM_REG(254, 1 << new_div));
+
+       } else {
+               unsigned int new_min = 1350000 / val;
+
+               new_div = 0;
+               while (new_min > 192 && new_div < 3) {
+                       new_div++;
+                       new_min /= 2;
+               }
+               if (!new_min) /* keep > 0 */
+                       new_min++;
+
+               data->fan_min[nr] = new_min;
+
+               dev_dbg(&client->dev, "fan%u low limit set fan speed %u\n",
+                               nr + 1, FAN_FROM_REG(new_min, 1 << new_div));
+       }
+
+       if (new_div != data->fan_div[nr]) {
+               data->fan_div[nr] = new_div;
+               adm9240_write_fan_div(client, nr, new_div);
+       }
+       adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr),
+                       data->fan_min[nr]);
+
+       up(&data->update_lock);
+       return count;
+}
+
+#define show_fan_offset(offset)                                                \
+static ssize_t show_fan_##offset (struct device *dev,                  \
+                                 struct device_attribute *attr,        \
+                                 char *buf)                            \
+{                                                                      \
+return show_fan(dev, buf, offset - 1);                                 \
+}                                                                      \
+static ssize_t show_fan_##offset##_div (struct device *dev,            \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+return show_fan_div(dev, buf, offset - 1);                             \
+}                                                                      \
+static ssize_t show_fan_##offset##_min (struct device *dev,            \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+return show_fan_min(dev, buf, offset - 1);                             \
+}                                                                      \
+static ssize_t set_fan_##offset##_min (struct device *dev,             \
+                                      struct device_attribute *attr,   \
+                                      const char *buf, size_t count)   \
+{                                                                      \
+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##_div, S_IRUGO,                                 \
+               show_fan_##offset##_div, NULL);                         \
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,               \
+               show_fan_##offset##_min, set_fan_##offset##_min);
+
+show_fan_offset(1);
+show_fan_offset(2);
+
+/* alarms */
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%u\n", data->alarms);
+}
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+/* vid */
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+/* analog output */
+static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct adm9240_data *data = adm9240_update_device(dev);
+       return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
+}
+
+static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adm9240_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtol(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->aout = AOUT_TO_REG(val);
+       adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout);
+       up(&data->update_lock);
+       return count;
+}
+static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
+
+/* chassis_clear */
+static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned long val = simple_strtol(buf, NULL, 10);
+
+       if (val == 1) {
+               adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
+               dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
+       }
+       return count;
+}
+static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear);
+
+
+/*** sensor chip detect and driver install ***/
+
+static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *new_client;
+       struct adm9240_data *data;
+       int err = 0;
+       const char *name = "";
+       u8 man_id, die_rev;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               goto exit;
+
+       if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit;
+       }
+       memset(data, 0, sizeof(struct adm9240_data));
+
+       new_client = &data->client;
+       i2c_set_clientdata(new_client, data);
+       new_client->addr = address;
+       new_client->adapter = adapter;
+       new_client->driver = &adm9240_driver;
+       new_client->flags = 0;
+
+       if (kind == 0) {
+               kind = adm9240;
+       }
+
+       if (kind < 0) {
+
+               /* verify chip: reg address should match i2c address */
+               if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
+                               != address) {
+                       dev_err(&adapter->dev, "detect fail: address match, "
+                                       "0x%02x\n", address);
+                       goto exit_free;
+               }
+
+               /* check known chip manufacturer */
+               man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID);
+
+               if (man_id == 0x23) {
+                       kind = adm9240;
+               } else if (man_id == 0xda) {
+                       kind = ds1780;
+               } else if (man_id == 0x01) {
+                       kind = lm81;
+               } else {
+                       dev_err(&adapter->dev, "detect fail: unknown manuf, "
+                                       "0x%02x\n", man_id);
+                       goto exit_free;
+               }
+
+               /* successful detect, print chip info */
+               die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV);
+               dev_info(&adapter->dev, "found %s revision %u\n",
+                               man_id == 0x23 ? "ADM9240" :
+                               man_id == 0xda ? "DS1780" : "LM81", die_rev);
+       }
+
+       /* either forced or detected chip kind */
+       if (kind == adm9240) {
+               name = "adm9240";
+       } else if (kind == ds1780) {
+               name = "ds1780";
+       } else if (kind == lm81) {
+               name = "lm81";
+       }
+
+       /* fill in the remaining client fields and attach */
+       strlcpy(new_client->name, name, I2C_NAME_SIZE);
+       data->type = kind;
+       init_MUTEX(&data->update_lock);
+
+       if ((err = i2c_attach_client(new_client)))
+               goto exit_free;
+
+       adm9240_init_client(new_client);
+
+       /* populate sysfs filesystem */
+       device_create_file(&new_client->dev, &dev_attr_in0_input);
+       device_create_file(&new_client->dev, &dev_attr_in0_min);
+       device_create_file(&new_client->dev, &dev_attr_in0_max);
+       device_create_file(&new_client->dev, &dev_attr_in1_input);
+       device_create_file(&new_client->dev, &dev_attr_in1_min);
+       device_create_file(&new_client->dev, &dev_attr_in1_max);
+       device_create_file(&new_client->dev, &dev_attr_in2_input);
+       device_create_file(&new_client->dev, &dev_attr_in2_min);
+       device_create_file(&new_client->dev, &dev_attr_in2_max);
+       device_create_file(&new_client->dev, &dev_attr_in3_input);
+       device_create_file(&new_client->dev, &dev_attr_in3_min);
+       device_create_file(&new_client->dev, &dev_attr_in3_max);
+       device_create_file(&new_client->dev, &dev_attr_in4_input);
+       device_create_file(&new_client->dev, &dev_attr_in4_min);
+       device_create_file(&new_client->dev, &dev_attr_in4_max);
+       device_create_file(&new_client->dev, &dev_attr_in5_input);
+       device_create_file(&new_client->dev, &dev_attr_in5_min);
+       device_create_file(&new_client->dev, &dev_attr_in5_max);
+       device_create_file(&new_client->dev, &dev_attr_temp1_max);
+       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+       device_create_file(&new_client->dev, &dev_attr_temp1_input);
+       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_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_alarms);
+       device_create_file(&new_client->dev, &dev_attr_aout_output);
+       device_create_file(&new_client->dev, &dev_attr_chassis_clear);
+       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
+
+       return 0;
+exit_free:
+       kfree(new_client);
+exit:
+       return err;
+}
+
+static int adm9240_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!(adapter->class & I2C_CLASS_HWMON))
+               return 0;
+       return i2c_detect(adapter, &addr_data, adm9240_detect);
+}
+
+static int adm9240_detach_client(struct i2c_client *client)
+{
+       int err;
+
+       if ((err = i2c_detach_client(client))) {
+               dev_err(&client->dev, "Client deregistration failed, "
+                               "client not detached.\n");
+               return err;
+       }
+
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static void adm9240_init_client(struct i2c_client *client)
+{
+       struct adm9240_data *data = i2c_get_clientdata(client);
+       u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
+       u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
+
+       data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
+
+       dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
+                       data->vrm % 10);
+
+       if (conf & 1) { /* measurement cycle running: report state */
+
+               dev_info(&client->dev, "status: config 0x%02x mode %u\n",
+                               conf, mode);
+
+       } else { /* cold start: open limits before starting chip */
+               int i;
+
+               for (i = 0; i < 6; i++)
+               {
+                       adm9240_write_value(client,
+                                       ADM9240_REG_IN_MIN(i), 0);
+                       adm9240_write_value(client,
+                                       ADM9240_REG_IN_MAX(i), 255);
+               }
+               adm9240_write_value(client, ADM9240_REG_FAN_MIN(0), 255);
+               adm9240_write_value(client, ADM9240_REG_FAN_MIN(1), 255);
+               adm9240_write_value(client, ADM9240_REG_TEMP_HIGH, 127);
+               adm9240_write_value(client, ADM9240_REG_TEMP_HYST, 127);
+
+               /* start measurement cycle */
+               adm9240_write_value(client, ADM9240_REG_CONFIG, 1);
+
+               dev_info(&client->dev, "cold start: config was 0x%02x "
+                               "mode %u\n", conf, mode);
+       }
+}
+
+static struct adm9240_data *adm9240_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adm9240_data *data = i2c_get_clientdata(client);
+       int i;
+
+       down(&data->update_lock);
+
+       /* minimum measurement cycle: 1.75 seconds */
+       if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
+                       || !data->valid) {
+
+               for (i = 0; i < 6; i++) /* read voltages */
+               {
+                       data->in[i] = adm9240_read_value(client,
+                                       ADM9240_REG_IN(i));
+               }
+               data->alarms = adm9240_read_value(client,
+                                       ADM9240_REG_INT(0)) |
+                                       adm9240_read_value(client,
+                                       ADM9240_REG_INT(1)) << 8;
+
+               /* read temperature: assume temperature changes less than
+                * 0.5'C per two measurement cycles thus ignore possible
+                * but unlikely aliasing error on lsb reading. --Grant */
+               data->temp = ((adm9240_read_value(client,
+                                       ADM9240_REG_TEMP) << 8) |
+                                       adm9240_read_value(client,
+                                       ADM9240_REG_TEMP_CONF)) / 128;
+
+               for (i = 0; i < 2; i++) /* read fans */
+               {
+                       data->fan[i] = adm9240_read_value(client,
+                                       ADM9240_REG_FAN(i));
+
+                       /* adjust fan clock divider on overflow */
+                       if (data->valid && data->fan[i] == 255 &&
+                                       data->fan_div[i] < 3) {
+
+                               adm9240_write_fan_div(client, i,
+                                               ++data->fan_div[i]);
+
+                               /* adjust fan_min if active, but not to 0 */
+                               if (data->fan_min[i] < 255 &&
+                                               data->fan_min[i] >= 2)
+                                       data->fan_min[i] /= 2;
+                       }
+               }
+               data->last_updated_measure = jiffies;
+       }
+
+       /* minimum config reading cycle: 300 seconds */
+       if (time_after(jiffies, data->last_updated_config + (HZ * 300))
+                       || !data->valid) {
+
+               for (i = 0; i < 6; i++)
+               {
+                       data->in_min[i] = adm9240_read_value(client,
+                                       ADM9240_REG_IN_MIN(i));
+                       data->in_max[i] = adm9240_read_value(client,
+                                       ADM9240_REG_IN_MAX(i));
+               }
+               for (i = 0; i < 2; i++)
+               {
+                       data->fan_min[i] = adm9240_read_value(client,
+                                       ADM9240_REG_FAN_MIN(i));
+               }
+               data->temp_high = adm9240_read_value(client,
+                               ADM9240_REG_TEMP_HIGH);
+               data->temp_hyst = adm9240_read_value(client,
+                               ADM9240_REG_TEMP_HYST);
+
+               /* read fan divs and 5-bit VID */
+               i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+               data->fan_div[0] = (i >> 4) & 3;
+               data->fan_div[1] = (i >> 6) & 3;
+               data->vid = i & 0x0f;
+               data->vid |= (adm9240_read_value(client,
+                                       ADM9240_REG_VID4) & 1) << 4;
+               /* read analog out */
+               data->aout = adm9240_read_value(client,
+                               ADM9240_REG_ANALOG_OUT);
+
+               data->last_updated_config = jiffies;
+               data->valid = 1;
+       }
+       up(&data->update_lock);
+       return data;
+}
+
+static int __init sensors_adm9240_init(void)
+{
+       return i2c_add_driver(&adm9240_driver);
+}
+
+static void __exit sensors_adm9240_exit(void)
+{
+       i2c_del_driver(&adm9240_driver);
+}
+
+MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
+               "Grant Coady <gcoady@gmail.com> and others");
+MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_adm9240_init);
+module_exit(sensors_adm9240_exit);
+
index 4a47b4493e34aa8b567efcf818f89245a53b3182..70d996d6fe0a95c607c06afe6b0a8da01025a39e 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
 #include "lm75.h"
 
 /*
@@ -168,8 +169,6 @@ static int ASB100_PWM_FROM_REG(u8 reg)
        return reg * 16;
 }
 
-#define ALARMS_FROM_REG(val) (val)
-
 #define DIV_FROM_REG(val) (1 << (val))
 
 /* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
@@ -556,7 +555,7 @@ device_create_file(&client->dev, &dev_attr_vrm);
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct asb100_data *data = asb100_update_device(dev);
-       return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
+       return sprintf(buf, "%u\n", data->alarms);
 }
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
diff --git a/drivers/i2c/chips/atxp1.c b/drivers/i2c/chips/atxp1.c
new file mode 100644 (file)
index 0000000..5c6597a
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+    atxp1.c - kernel module for setting CPU VID and general purpose
+                     I/Os using the Attansic ATXP1 chip.
+
+    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.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
+MODULE_VERSION("0.6.2");
+MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
+
+#define ATXP1_VID      0x00
+#define ATXP1_CVID     0x01
+#define ATXP1_GPIO1    0x06
+#define ATXP1_GPIO2    0x0a
+#define ATXP1_VIDENA   0x20
+#define ATXP1_VIDMASK  0x1f
+#define ATXP1_GPIO1MASK        0x0f
+
+static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+SENSORS_INSMOD_1(atxp1);
+
+static int atxp1_attach_adapter(struct i2c_adapter * adapter);
+static int atxp1_detach_client(struct i2c_client * client);
+static struct atxp1_data * atxp1_update_device(struct device *dev);
+static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind);
+
+static struct i2c_driver atxp1_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "atxp1",
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = atxp1_attach_adapter,
+       .detach_client  = atxp1_detach_client,
+};
+
+struct atxp1_data {
+       struct i2c_client client;
+       struct semaphore update_lock;
+       unsigned long last_updated;
+       u8 valid;
+       struct {
+               u8 vid;         /* VID output register */
+               u8 cpu_vid; /* VID input from CPU */
+               u8 gpio1;   /* General purpose I/O register 1 */
+               u8 gpio2;   /* General purpose I/O register 2 */
+       } reg;
+       u8 vrm;                 /* Detected CPU VRM */
+};
+
+static struct atxp1_data * atxp1_update_device(struct device *dev)
+{
+       struct i2c_client *client;
+       struct atxp1_data *data;
+
+       client = to_i2c_client(dev);
+       data = i2c_get_clientdata(client);
+
+       down(&data->update_lock);
+
+       if ((jiffies - data->last_updated > HZ) ||
+           (jiffies < data->last_updated) ||
+           !data->valid) {
+
+               /* Update local register data */
+               data->reg.vid = i2c_smbus_read_byte_data(client, ATXP1_VID);
+               data->reg.cpu_vid = i2c_smbus_read_byte_data(client, ATXP1_CVID);
+               data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1);
+               data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2);
+
+               data->valid = 1;
+       }
+
+       up(&data->update_lock);
+
+       return(data);
+}
+
+/* sys file functions for cpu0_vid */
+static ssize_t atxp1_showvcore(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int size;
+       struct atxp1_data *data;
+
+       data = atxp1_update_device(dev);
+
+       size = sprintf(buf, "%d\n", vid_from_reg(data->reg.vid & ATXP1_VIDMASK, data->vrm));
+
+       return size;
+}
+
+static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct atxp1_data *data;
+       struct i2c_client *client;
+       char vid;
+       char cvid;
+       unsigned int vcore;
+
+       client = to_i2c_client(dev);
+       data = atxp1_update_device(dev);
+
+       vcore = simple_strtoul(buf, NULL, 10);
+       vcore /= 25;
+       vcore *= 25;
+
+       /* Calculate VID */
+       vid = vid_to_reg(vcore, data->vrm);
+
+       if (vid < 0) {
+               dev_err(dev, "VID calculation failed.\n");
+               return -1;
+       }
+
+       /* If output enabled, use control register value. Otherwise original CPU VID */
+       if (data->reg.vid & ATXP1_VIDENA)
+               cvid = data->reg.vid & ATXP1_VIDMASK;
+       else
+               cvid = data->reg.cpu_vid;
+
+       /* Nothing changed, aborting */
+       if (vid == cvid)
+               return count;
+
+       dev_info(dev, "Setting VCore to %d mV (0x%02x)\n", vcore, vid);
+
+       /* Write every 25 mV step to increase stability */
+       if (cvid > vid) {
+               for (; cvid >= vid; cvid--) {
+                       i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA);
+               }
+       }
+       else {
+               for (; cvid <= vid; cvid++) {
+                       i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA);
+               }
+       }
+
+       data->valid = 0;
+
+       return count;
+}
+
+/* CPU core reference voltage
+    unit: millivolt
+*/
+static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore, atxp1_storevcore);
+
+/* sys file functions for GPIO1 */
+static ssize_t atxp1_showgpio1(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int size;
+       struct atxp1_data *data;
+
+       data = atxp1_update_device(dev);
+
+       size = sprintf(buf, "0x%02x\n", data->reg.gpio1 & ATXP1_GPIO1MASK);
+
+       return size;
+}
+
+static ssize_t atxp1_storegpio1(struct device *dev, struct device_attribute *attr, const char*buf, size_t count)
+{
+       struct atxp1_data *data;
+       struct i2c_client *client;
+       unsigned int value;
+
+       client = to_i2c_client(dev);
+       data = atxp1_update_device(dev);
+
+       value = simple_strtoul(buf, NULL, 16);
+
+       value &= ATXP1_GPIO1MASK;
+
+       if (value != (data->reg.gpio1 & ATXP1_GPIO1MASK)) {
+               dev_info(dev, "Writing 0x%x to GPIO1.\n", value);
+
+               i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value);
+
+               data->valid = 0;
+       }
+
+       return count;
+}
+
+/* GPIO1 data register
+    unit: Four bit as hex (e.g. 0x0f)
+*/
+static DEVICE_ATTR(gpio1, S_IRUGO | S_IWUSR, atxp1_showgpio1, atxp1_storegpio1);
+
+/* sys file functions for GPIO2 */
+static ssize_t atxp1_showgpio2(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int size;
+       struct atxp1_data *data;
+
+       data = atxp1_update_device(dev);
+
+       size = sprintf(buf, "0x%02x\n", data->reg.gpio2);
+
+       return size;
+}
+
+static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct atxp1_data *data;
+       struct i2c_client *client;
+       unsigned int value;
+
+       client = to_i2c_client(dev);
+       data = atxp1_update_device(dev);
+
+       value = simple_strtoul(buf, NULL, 16) & 0xff;
+
+       if (value != data->reg.gpio2) {
+               dev_info(dev, "Writing 0x%x to GPIO1.\n", value);
+
+               i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value);
+
+               data->valid = 0;
+       }
+
+       return count;
+}
+
+/* GPIO2 data register
+    unit: Eight bit as hex (e.g. 0xff)
+*/
+static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
+
+
+static int atxp1_attach_adapter(struct i2c_adapter *adapter)
+{
+       return i2c_detect(adapter, &addr_data, &atxp1_detect);
+};
+
+static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client * new_client;
+       struct atxp1_data * data;
+       int err = 0;
+       u8 temp;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               goto exit;
+
+       if (!(data = kmalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       memset(data, 0, sizeof(struct atxp1_data));
+       new_client = &data->client;
+       i2c_set_clientdata(new_client, data);
+
+       new_client->addr = address;
+       new_client->adapter = adapter;
+       new_client->driver = &atxp1_driver;
+       new_client->flags = 0;
+
+       /* Detect ATXP1, checking if vendor ID registers are all zero */
+       if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) &&
+            (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) &&
+            (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) &&
+            (i2c_smbus_read_byte_data(new_client, 0xff) == 0) )) {
+
+               /* No vendor ID, now checking if registers 0x10,0x11 (non-existent)
+                * showing the same as register 0x00 */
+               temp = i2c_smbus_read_byte_data(new_client, 0x00);
+
+               if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) &&
+                        (i2c_smbus_read_byte_data(new_client, 0x11) == temp) ))
+                       goto exit_free;
+       }
+
+       /* Get VRM */
+       data->vrm = i2c_which_vrm();
+
+       if ((data->vrm != 90) && (data->vrm != 91)) {
+               dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
+                               data->vrm / 10, data->vrm % 10);
+               goto exit_free;
+       }
+
+       strncpy(new_client->name, "atxp1", I2C_NAME_SIZE);
+
+       data->valid = 0;
+
+       init_MUTEX(&data->update_lock);
+
+       err = i2c_attach_client(new_client);
+
+       if (err)
+       {
+               dev_err(&new_client->dev, "Attach client error.\n");
+               goto exit_free;
+       }
+
+       device_create_file(&new_client->dev, &dev_attr_gpio1);
+       device_create_file(&new_client->dev, &dev_attr_gpio2);
+       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
+
+       dev_info(&new_client->dev, "Using VRM: %d.%d\n",
+                        data->vrm / 10, data->vrm % 10);
+
+       return 0;
+
+exit_free:
+       kfree(data);
+exit:
+       return err;
+};
+
+static int atxp1_detach_client(struct i2c_client * client)
+{
+       int err;
+
+       err = i2c_detach_client(client);
+
+       if (err)
+               dev_err(&client->dev, "Failed to detach client.\n");
+       else
+               kfree(i2c_get_clientdata(client));
+
+       return err;
+};
+
+static int __init atxp1_init(void)
+{
+       return i2c_add_driver(&atxp1_driver);
+};
+
+static void __exit atxp1_exit(void)
+{
+       i2c_del_driver(&atxp1_driver);
+};
+
+module_init(atxp1_init);
+module_exit(atxp1_exit);
index 07f16c3fb084df6aba16f225a7a86f1f6e21be36..74ece8ac1c2355b214af3e4481eddf3c747a5fd6 100644 (file)
@@ -3,17 +3,16 @@
  *
  *  Copyright (C) 2005 James Chapman <jchapman@katalix.com>
  *
- *     based on linux/drivers/acron/char/pcf8583.c
+ *     based on linux/drivers/acorn/char/pcf8583.c
  *  Copyright (C) 2000 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
  * published by the Free Software Foundation.
  *
- * Driver for Dallas Semiconductor DS1337 real time clock chip
+ * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -69,13 +68,11 @@ static struct i2c_driver ds1337_driver = {
 struct ds1337_data {
        struct i2c_client client;
        struct list_head list;
-       int id;
 };
 
 /*
  * Internal variables
  */
-static int ds1337_id;
 static LIST_HEAD(ds1337_clients);
 
 static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
@@ -95,7 +92,6 @@ static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
  */
 static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
 {
-       struct ds1337_data *data = i2c_get_clientdata(client);
        int result;
        u8 buf[7];
        u8 val;
@@ -103,9 +99,7 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
        u8 offs = 0;
 
        if (!dt) {
-               dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
-                       __FUNCTION__);
-
+               dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
                return -EINVAL;
        }
 
@@ -119,98 +113,86 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
        msg[1].len = sizeof(buf);
        msg[1].buf = &buf[0];
 
-       result = client->adapter->algo->master_xfer(client->adapter,
-                                                   &msg[0], 2);
+       result = i2c_transfer(client->adapter, msg, 2);
 
-       dev_dbg(&client->adapter->dev,
-               "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
+       dev_dbg(&client->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
                __FUNCTION__, result, buf[0], buf[1], buf[2], buf[3],
                buf[4], buf[5], buf[6]);
 
-       if (result >= 0) {
-               dt->tm_sec = BCD_TO_BIN(buf[0]);
-               dt->tm_min = BCD_TO_BIN(buf[1]);
+       if (result == 2) {
+               dt->tm_sec = BCD2BIN(buf[0]);
+               dt->tm_min = BCD2BIN(buf[1]);
                val = buf[2] & 0x3f;
-               dt->tm_hour = BCD_TO_BIN(val);
-               dt->tm_wday = BCD_TO_BIN(buf[3]) - 1;
-               dt->tm_mday = BCD_TO_BIN(buf[4]);
+               dt->tm_hour = BCD2BIN(val);
+               dt->tm_wday = BCD2BIN(buf[3]) - 1;
+               dt->tm_mday = BCD2BIN(buf[4]);
                val = buf[5] & 0x7f;
-               dt->tm_mon = BCD_TO_BIN(val);
-               dt->tm_year = 1900 + BCD_TO_BIN(buf[6]);
+               dt->tm_mon = BCD2BIN(val) - 1;
+               dt->tm_year = BCD2BIN(buf[6]);
                if (buf[5] & 0x80)
                        dt->tm_year += 100;
 
-               dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, "
+               dev_dbg(&client->dev, "%s: secs=%d, mins=%d, "
                        "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
                        __FUNCTION__, dt->tm_sec, dt->tm_min,
                        dt->tm_hour, dt->tm_mday,
                        dt->tm_mon, dt->tm_year, dt->tm_wday);
-       } else {
-               dev_err(&client->adapter->dev, "ds1337[%d]: error reading "
-                       "data! %d\n", data->id, result);
-               result = -EIO;
+
+               return 0;
        }
 
-       return result;
+       dev_err(&client->dev, "error reading data! %d\n", result);
+       return -EIO;
 }
 
 static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt)
 {
-       struct ds1337_data *data = i2c_get_clientdata(client);
        int result;
        u8 buf[8];
        u8 val;
        struct i2c_msg msg[1];
 
        if (!dt) {
-               dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
-                       __FUNCTION__);
-
+               dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
                return -EINVAL;
        }
 
-       dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, hours=%d, "
+       dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
                "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__,
                dt->tm_sec, dt->tm_min, dt->tm_hour,
                dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday);
 
        buf[0] = 0;             /* reg offset */
-       buf[1] = BIN_TO_BCD(dt->tm_sec);
-       buf[2] = BIN_TO_BCD(dt->tm_min);
-       buf[3] = BIN_TO_BCD(dt->tm_hour) | (1 << 6);
-       buf[4] = BIN_TO_BCD(dt->tm_wday) + 1;
-       buf[5] = BIN_TO_BCD(dt->tm_mday);
-       buf[6] = BIN_TO_BCD(dt->tm_mon);
-       if (dt->tm_year >= 2000) {
-               val = dt->tm_year - 2000;
+       buf[1] = BIN2BCD(dt->tm_sec);
+       buf[2] = BIN2BCD(dt->tm_min);
+       buf[3] = BIN2BCD(dt->tm_hour) | (1 << 6);
+       buf[4] = BIN2BCD(dt->tm_wday) + 1;
+       buf[5] = BIN2BCD(dt->tm_mday);
+       buf[6] = BIN2BCD(dt->tm_mon) + 1;
+       val = dt->tm_year;
+       if (val >= 100) {
+               val -= 100;
                buf[6] |= (1 << 7);
-       } else {
-               val = dt->tm_year - 1900;
        }
-       buf[7] = BIN_TO_BCD(val);
+       buf[7] = BIN2BCD(val);
 
        msg[0].addr = client->addr;
        msg[0].flags = 0;
        msg[0].len = sizeof(buf);
        msg[0].buf = &buf[0];
 
-       result = client->adapter->algo->master_xfer(client->adapter,
-                                                   &msg[0], 1);
-       if (result < 0) {
-               dev_err(&client->adapter->dev, "ds1337[%d]: error "
-                       "writing data! %d\n", data->id, result);
-               result = -EIO;
-       } else {
-               result = 0;
-       }
+       result = i2c_transfer(client->adapter, msg, 1);
+       if (result == 1)
+               return 0;
 
-       return result;
+       dev_err(&client->dev, "error writing data! %d\n", result);
+       return -EIO;
 }
 
 static int ds1337_command(struct i2c_client *client, unsigned int cmd,
                          void *arg)
 {
-       dev_dbg(&client->adapter->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+       dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
 
        switch (cmd) {
        case DS1337_GET_DATE:
@@ -228,7 +210,7 @@ static int ds1337_command(struct i2c_client *client, unsigned int cmd,
  * Public API for access to specific device. Useful for low-level
  * RTC access from kernel code.
  */
-int ds1337_do_command(int id, int cmd, void *arg)
+int ds1337_do_command(int bus, int cmd, void *arg)
 {
        struct list_head *walk;
        struct list_head *tmp;
@@ -236,7 +218,7 @@ int ds1337_do_command(int id, int cmd, void *arg)
 
        list_for_each_safe(walk, tmp, &ds1337_clients) {
                data = list_entry(walk, struct ds1337_data, list);
-               if (data->id == id)
+               if (data->client.adapter->nr == bus)
                        return ds1337_command(&data->client, cmd, arg);
        }
 
@@ -346,7 +328,6 @@ static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
        ds1337_init_client(new_client);
 
        /* Add client to local list */
-       data->id = ds1337_id++;
        list_add(&data->list, &ds1337_clients);
 
        return 0;
@@ -398,5 +379,7 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
 MODULE_DESCRIPTION("DS1337 RTC driver");
 MODULE_LICENSE("GPL");
 
+EXPORT_SYMBOL_GPL(ds1337_do_command);
+
 module_init(ds1337_init);
 module_exit(ds1337_exit);
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
new file mode 100644 (file)
index 0000000..a445736
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * drivers/i2c/chips/ds1374.c
+ *
+ * I2C client/driver for the Maxim/Dallas DS1374 Real-Time Clock
+ *
+ * Author: Randy Vinson <rvinson@mvista.com>
+ *
+ * Based on the m41t00.c by Mark Greer <mgreer@mvista.com>
+ *
+ * 2005 (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.
+ */
+/*
+ * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
+ * interface and the SMBus interface of the i2c subsystem.
+ * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
+ * recommened in .../Documentation/i2c/writing-clients section
+ * "Sending and receiving", using SMBus level communication is preferred.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#define DS1374_REG_TOD0                0x00
+#define DS1374_REG_TOD1                0x01
+#define DS1374_REG_TOD2                0x02
+#define DS1374_REG_TOD3                0x03
+#define DS1374_REG_WDALM0      0x04
+#define DS1374_REG_WDALM1      0x05
+#define DS1374_REG_WDALM2      0x06
+#define DS1374_REG_CR          0x07
+#define DS1374_REG_SR          0x08
+#define DS1374_REG_SR_OSF      0x80
+#define DS1374_REG_TCR         0x09
+
+#define        DS1374_DRV_NAME         "ds1374"
+
+static DECLARE_MUTEX(ds1374_mutex);
+
+static struct i2c_driver ds1374_driver;
+static struct i2c_client *save_client;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+       .normal_i2c = normal_addr,
+       .probe = ignore,
+       .ignore = ignore,
+       .force = ignore,
+};
+
+static ulong ds1374_read_rtc(void)
+{
+       ulong time = 0;
+       int reg = DS1374_REG_WDALM0;
+
+       while (reg--) {
+               s32 tmp;
+               if ((tmp = i2c_smbus_read_byte_data(save_client, reg)) < 0) {
+                       dev_warn(&save_client->dev,
+                                "can't read from rtc chip\n");
+                       return 0;
+               }
+               time = (time << 8) | (tmp & 0xff);
+       }
+       return time;
+}
+
+static void ds1374_write_rtc(ulong time)
+{
+       int reg;
+
+       for (reg = DS1374_REG_TOD0; reg < DS1374_REG_WDALM0; reg++) {
+               if (i2c_smbus_write_byte_data(save_client, reg, time & 0xff)
+                   < 0) {
+                       dev_warn(&save_client->dev,
+                                "can't write to rtc chip\n");
+                       break;
+               }
+               time = time >> 8;
+       }
+}
+
+static void ds1374_check_rtc_status(void)
+{
+       s32 tmp;
+
+       tmp = i2c_smbus_read_byte_data(save_client, DS1374_REG_SR);
+       if (tmp < 0) {
+               dev_warn(&save_client->dev,
+                        "can't read status from rtc chip\n");
+               return;
+       }
+       if (tmp & DS1374_REG_SR_OSF) {
+               dev_warn(&save_client->dev,
+                        "oscillator discontinuity flagged, time unreliable\n");
+               tmp &= ~DS1374_REG_SR_OSF;
+               tmp = i2c_smbus_write_byte_data(save_client, DS1374_REG_SR,
+                                               tmp & 0xff);
+               if (tmp < 0)
+                       dev_warn(&save_client->dev,
+                                "can't clear discontinuity notification\n");
+       }
+}
+
+ulong ds1374_get_rtc_time(void)
+{
+       ulong t1, t2;
+       int limit = 10;         /* arbitrary retry limit */
+
+       down(&ds1374_mutex);
+
+       /*
+        * Since the reads are being performed one byte at a time using
+        * the SMBus vs a 4-byte i2c transfer, there is a chance that a
+        * carry will occur during the read. To detect this, 2 reads are
+        * performed and compared.
+        */
+       do {
+               t1 = ds1374_read_rtc();
+               t2 = ds1374_read_rtc();
+       } while (t1 != t2 && limit--);
+
+       up(&ds1374_mutex);
+
+       if (t1 != t2) {
+               dev_warn(&save_client->dev,
+                        "can't get consistent time from rtc chip\n");
+               t1 = 0;
+       }
+
+       return t1;
+}
+
+static void ds1374_set_tlet(ulong arg)
+{
+       ulong t1, t2;
+       int limit = 10;         /* arbitrary retry limit */
+
+       t1 = *(ulong *) arg;
+
+       down(&ds1374_mutex);
+
+       /*
+        * Since the writes are being performed one byte at a time using
+        * the SMBus vs a 4-byte i2c transfer, there is a chance that a
+        * carry will occur during the write. To detect this, the write
+        * value is read back and compared.
+        */
+       do {
+               ds1374_write_rtc(t1);
+               t2 = ds1374_read_rtc();
+       } while (t1 != t2 && limit--);
+
+       up(&ds1374_mutex);
+
+       if (t1 != t2)
+               dev_warn(&save_client->dev,
+                        "can't confirm time set from rtc chip\n");
+}
+
+ulong new_time;
+
+DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
+
+int ds1374_set_rtc_time(ulong nowtime)
+{
+       new_time = nowtime;
+
+       if (in_interrupt())
+               tasklet_schedule(&ds1374_tasklet);
+       else
+               ds1374_set_tlet((ulong) & new_time);
+
+       return 0;
+}
+
+/*
+ *****************************************************************************
+ *
+ *     Driver Interface
+ *
+ *****************************************************************************
+ */
+static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct i2c_client *client;
+       int rc;
+
+       client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (!client)
+               return -ENOMEM;
+
+       memset(client, 0, sizeof(struct i2c_client));
+       strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
+       client->flags = I2C_DF_NOTIFY;
+       client->addr = addr;
+       client->adapter = adap;
+       client->driver = &ds1374_driver;
+
+       if ((rc = i2c_attach_client(client)) != 0) {
+               kfree(client);
+               return rc;
+       }
+
+       save_client = client;
+
+       ds1374_check_rtc_status();
+
+       return 0;
+}
+
+static int ds1374_attach(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, ds1374_probe);
+}
+
+static int ds1374_detach(struct i2c_client *client)
+{
+       int rc;
+
+       if ((rc = i2c_detach_client(client)) == 0) {
+               kfree(i2c_get_clientdata(client));
+               tasklet_kill(&ds1374_tasklet);
+       }
+       return rc;
+}
+
+static struct i2c_driver ds1374_driver = {
+       .owner = THIS_MODULE,
+       .name = DS1374_DRV_NAME,
+       .id = I2C_DRIVERID_DS1374,
+       .flags = I2C_DF_NOTIFY,
+       .attach_adapter = ds1374_attach,
+       .detach_client = ds1374_detach,
+};
+
+static int __init ds1374_init(void)
+{
+       return i2c_add_driver(&ds1374_driver);
+}
+
+static void __exit ds1374_exit(void)
+{
+       i2c_del_driver(&ds1374_driver);
+}
+
+module_init(ds1374_init);
+module_exit(ds1374_exit);
+
+MODULE_AUTHOR("Randy Vinson <rvinson@mvista.com>");
+MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC I2C Client Driver");
+MODULE_LICENSE("GPL");
index 4ae15bd5dcfb360214b86596db736e95aed21227..5360d58804f6244e4de94a2b85b9b312cd36a409 100644 (file)
@@ -121,7 +121,7 @@ static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value)
 static void ds1621_init_client(struct i2c_client *client)
 {
        int reg = ds1621_read_value(client, DS1621_REG_CONF);
-       /* switch to continous conversion mode */
+       /* switch to continuous conversion mode */
        reg &= ~ DS1621_REG_CONFIG_1SHOT;
 
        /* setup output polarity */
@@ -303,7 +303,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
                data->temp_max = ds1621_read_value(client,
                                                    DS1621_REG_TEMP_MAX);
 
-               /* reset alarms if neccessary */
+               /* reset alarms if necessary */
                new_conf = data->conf;
                if (data->temp < data->temp_min)
                        new_conf &= ~DS1621_ALARM_TEMP_LOW;
index cbdfa2db6f7c90424028f5215f157bde45589af9..addf0adc24d406060c97371b7b90203911289450 100644 (file)
@@ -26,7 +26,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
index c3f37dbec11a249068742bb10ffb55f26429297f..da411741c2c579964e8b1ac857d370154a8a33f3 100644 (file)
@@ -26,7 +26,6 @@
  *  and Philip Edelbrock <phil@netroedge.com>
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 4316a15622517af2c89a1354ff3ca80dce6f749a..6bedf729dcf5c251b27c18676af66fab4b68793f 100644 (file)
@@ -36,7 +36,6 @@
  * 2004-01-31  Code review and approval. (Jean Delvare)
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 7f29a8aff1656792a46a75444dba89df70f05a91..354a262956725ebe8812908bf3a5341e593bc171 100644 (file)
@@ -145,7 +145,6 @@ static inline void notresponding(struct isp1301 *isp)
 static unsigned short normal_i2c[] = {
        ISP_BASE, ISP_BASE + 1,
        I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
 I2C_CLIENT_INSMOD;
 
index 007bdf9e7e2afdc8775e38dba804ad9ec9db9e5b..db20c9e47393a36bbd04b580ce92560ff6dcc331 100644 (file)
@@ -31,7 +31,6 @@
     type at module load time.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -39,6 +38,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
+#include <linux/hwmon-sysfs.h>
 #include <asm/io.h>
 
 
@@ -173,8 +173,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 ALARMS_FROM_REG(val) (val)
-
 #define PWM_TO_REG(val)   ((val) >> 1)
 #define PWM_FROM_REG(val) (((val)&0x7f) << 1)
 
@@ -241,27 +239,42 @@ static struct i2c_driver it87_driver = {
        .detach_client  = it87_detach_client,
 };
 
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
 }
 
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
 }
 
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
 }
 
-static ssize_t set_in_min(struct device *dev, const char *buf, 
-               size_t count, int nr)
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        unsigned long val = simple_strtoul(buf, NULL, 10);
@@ -273,9 +286,12 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
        up(&data->update_lock);
        return count;
 }
-static ssize_t set_in_max(struct device *dev, const char *buf, 
-               size_t count, int nr)
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        unsigned long val = simple_strtoul(buf, NULL, 10);
@@ -289,38 +305,14 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
 }
 
 #define show_in_offset(offset)                                 \
-static ssize_t                                                 \
-       show_in##offset (struct device *dev, struct device_attribute *attr, char *buf)          \
-{                                                              \
-       return show_in(dev, buf, offset);                       \
-}                                                              \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,         \
+               show_in, NULL, offset);
 
 #define limit_in_offset(offset)                                        \
-static ssize_t                                                 \
-       show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)    \
-{                                                              \
-       return show_in_min(dev, buf, offset);                   \
-}                                                              \
-static ssize_t                                                 \
-       show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)    \
-{                                                              \
-       return show_in_max(dev, buf, offset);                   \
-}                                                              \
-static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr,        \
-               const char *buf, size_t count)                  \
-{                                                              \
-       return set_in_min(dev, buf, count, offset);             \
-}                                                              \
-static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr,        \
-                       const char *buf, size_t count)          \
-{                                                              \
-       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);   \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,        \
-               show_in##offset##_max, set_in##offset##_max);
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+               show_in_min, set_in_min, offset);               \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+               show_in_max, set_in_max, offset);
 
 show_in_offset(0);
 limit_in_offset(0);
@@ -341,24 +333,39 @@ limit_in_offset(7);
 show_in_offset(8);
 
 /* 3 temperatures */
-static ssize_t show_temp(struct device *dev, char *buf, int nr)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
 }
-static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr]));
 }
-static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr]));
 }
-static ssize_t set_temp_max(struct device *dev, const char *buf, 
-               size_t count, int nr)
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
@@ -369,9 +376,12 @@ static ssize_t set_temp_max(struct device *dev, const char *buf,
        up(&data->update_lock);
        return count;
 }
-static ssize_t set_temp_min(struct device *dev, const char *buf, 
-               size_t count, int nr)
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
@@ -383,42 +393,23 @@ static ssize_t set_temp_min(struct device *dev, const char *buf,
        return count;
 }
 #define show_temp_offset(offset)                                       \
-static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf)       \
-{                                                                      \
-       return show_temp(dev, buf, offset - 1);                         \
-}                                                                      \
-static ssize_t                                                         \
-show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)                \
-{                                                                      \
-       return show_temp_max(dev, buf, offset - 1);                     \
-}                                                                      \
-static ssize_t                                                         \
-show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)                \
-{                                                                      \
-       return show_temp_min(dev, buf, offset - 1);                     \
-}                                                                      \
-static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr,             \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_temp_max(dev, buf, count, offset - 1);               \
-}                                                                      \
-static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr,             \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       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,              \
-               show_temp_##offset##_max, set_temp_##offset##_max);     \
-static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,              \
-               show_temp_##offset##_min, set_temp_##offset##_min);     
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,               \
+               show_temp, NULL, offset - 1);                           \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,       \
+               show_temp_max, set_temp_max, offset - 1);               \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,       \
+               show_temp_min, set_temp_min, offset - 1);
 
 show_temp_offset(1);
 show_temp_offset(2);
 show_temp_offset(3);
 
-static ssize_t show_sensor(struct device *dev, char *buf, int nr)
+static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        u8 reg = data->sensor; /* In case the value is updated while we use it */
        
@@ -428,9 +419,12 @@ static ssize_t show_sensor(struct device *dev, char *buf, int nr)
                return sprintf(buf, "2\n");  /* thermistor */
        return sprintf(buf, "0\n");      /* disabled */
 }
-static ssize_t set_sensor(struct device *dev, const char *buf, 
-               size_t count, int nr)
+static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
@@ -453,53 +447,67 @@ static ssize_t set_sensor(struct device *dev, const char *buf,
        return count;
 }
 #define show_sensor_offset(offset)                                     \
-static ssize_t show_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf)     \
-{                                                                      \
-       return show_sensor(dev, buf, offset - 1);                       \
-}                                                                      \
-static ssize_t set_sensor_##offset (struct device *dev, struct device_attribute *attr,                 \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_sensor(dev, buf, count, offset - 1);                 \
-}                                                                      \
-static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR,             \
-               show_sensor_##offset, set_sensor_##offset);
+static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR,      \
+               show_sensor, set_sensor, offset - 1);
 
 show_sensor_offset(1);
 show_sensor_offset(2);
 show_sensor_offset(3);
 
 /* 3 Fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], 
                                DIV_FROM_REG(data->fan_div[nr])));
 }
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf,"%d\n",
                FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])));
 }
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 }
-static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
+static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0);
 }
-static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+               char *buf)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct it87_data *data = it87_update_device(dev);
        return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);
 }
-static ssize_t set_fan_min(struct device *dev, const char *buf, 
-               size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
@@ -510,9 +518,12 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
        up(&data->update_lock);
        return count;
 }
-static ssize_t set_fan_div(struct device *dev, const char *buf, 
-               size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
@@ -550,9 +561,12 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
        up(&data->update_lock);
        return count;
 }
-static ssize_t set_pwm_enable(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_pwm_enable(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
@@ -581,9 +595,12 @@ static ssize_t set_pwm_enable(struct device *dev, const char *buf,
        up(&data->update_lock);
        return count;
 }
-static ssize_t set_pwm(struct device *dev, const char *buf,
-               size_t count, int nr)
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
 {
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
@@ -599,64 +616,23 @@ static ssize_t set_pwm(struct device *dev, const char *buf,
        return count;
 }
 
-#define show_fan_offset(offset)                                                \
-static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)        \
-{                                                                      \
-       return show_fan(dev, buf, offset - 1);                          \
-}                                                                      \
-static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)  \
-{                                                                      \
-       return show_fan_min(dev, buf, offset - 1);                      \
-}                                                                      \
-static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)  \
-{                                                                      \
-       return show_fan_div(dev, buf, offset - 1);                      \
-}                                                                      \
-static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr,              \
-       const char *buf, size_t count)                                  \
-{                                                                      \
-       return set_fan_min(dev, buf, count, offset - 1);                \
-}                                                                      \
-static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr,              \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       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,               \
-               show_fan_##offset##_min, set_fan_##offset##_min);       \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,               \
-               show_fan_##offset##_div, set_fan_##offset##_div);
+#define show_fan_offset(offset)                                        \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,                \
+               show_fan, NULL, offset - 1);                    \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+               show_fan_min, set_fan_min, offset - 1);         \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+               show_fan_div, set_fan_div, offset - 1);
 
 show_fan_offset(1);
 show_fan_offset(2);
 show_fan_offset(3);
 
 #define show_pwm_offset(offset)                                                \
-static ssize_t show_pwm##offset##_enable (struct device *dev, struct device_attribute *attr,           \
-       char *buf)                                                      \
-{                                                                      \
-       return show_pwm_enable(dev, buf, offset - 1);                   \
-}                                                                      \
-static ssize_t show_pwm##offset (struct device *dev, struct device_attribute *attr, char *buf)         \
-{                                                                      \
-       return show_pwm(dev, buf, offset - 1);                          \
-}                                                                      \
-static ssize_t set_pwm##offset##_enable (struct device *dev, struct device_attribute *attr,            \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_pwm_enable(dev, buf, count, offset - 1);             \
-}                                                                      \
-static ssize_t set_pwm##offset (struct device *dev, struct device_attribute *attr,                     \
-               const char *buf, size_t count)                          \
-{                                                                      \
-       return set_pwm(dev, buf, count, offset - 1);                    \
-}                                                                      \
-static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,            \
-               show_pwm##offset##_enable,                              \
-               set_pwm##offset##_enable);                              \
-static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,                     \
-               show_pwm##offset , set_pwm##offset );
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,     \
+               show_pwm_enable, set_pwm_enable, offset - 1);           \
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,              \
+               show_pwm, set_pwm, offset - 1);
 
 show_pwm_offset(1);
 show_pwm_offset(2);
@@ -666,7 +642,7 @@ show_pwm_offset(3);
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct it87_data *data = it87_update_device(dev);
-       return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
+       return sprintf(buf, "%u\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
@@ -864,60 +840,60 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
        it87_init_client(new_client, data);
 
        /* Register sysfs hooks */
-       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);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in4_input);
-       device_create_file(&new_client->dev, &dev_attr_in5_input);
-       device_create_file(&new_client->dev, &dev_attr_in6_input);
-       device_create_file(&new_client->dev, &dev_attr_in7_input);
-       device_create_file(&new_client->dev, &dev_attr_in8_input);
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in4_min);
-       device_create_file(&new_client->dev, &dev_attr_in5_min);
-       device_create_file(&new_client->dev, &dev_attr_in6_min);
-       device_create_file(&new_client->dev, &dev_attr_in7_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_in4_max);
-       device_create_file(&new_client->dev, &dev_attr_in5_max);
-       device_create_file(&new_client->dev, &dev_attr_in6_max);
-       device_create_file(&new_client->dev, &dev_attr_in7_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp3_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       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_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp3_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_type);
-       device_create_file(&new_client->dev, &dev_attr_temp2_type);
-       device_create_file(&new_client->dev, &dev_attr_temp3_type);
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan3_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       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_fan1_div);
-       device_create_file(&new_client->dev, &dev_attr_fan2_div);
-       device_create_file(&new_client->dev, &dev_attr_fan3_div);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_type.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_type.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
+       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
        device_create_file(&new_client->dev, &dev_attr_alarms);
        if (enable_pwm_interface) {
-               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_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, &sensor_dev_attr_pwm1_enable.dev_attr);
+               device_create_file(&new_client->dev, &sensor_dev_attr_pwm2_enable.dev_attr);
+               device_create_file(&new_client->dev, &sensor_dev_attr_pwm3_enable.dev_attr);
+               device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
+               device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
+               device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
        }
 
        if (data->type == it8712) {
@@ -954,7 +930,7 @@ static int it87_detach_client(struct i2c_client *client)
        return 0;
 }
 
-/* The SMBus locks itself, but ISA access must be locked explicitely! 
+/* The SMBus locks itself, but ISA access must be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
@@ -974,7 +950,7 @@ static int it87_read_value(struct i2c_client *client, u8 reg)
                return i2c_smbus_read_byte_data(client, reg);
 }
 
-/* The SMBus locks itself, but ISA access muse be locked explicitely! 
+/* The SMBus locks itself, but ISA access muse be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
index bc68e031392b399acdfbd2c2dda62fadacdf54cc..7c6f9ea5a254c53614e2269a89263a4aad96184f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lm63.c - driver for the National Semiconductor LM63 temperature sensor
  *          with integrated fan control
- * Copyright (C) 2004  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2005  Jean Delvare <khali@linux-fr.org>
  * Based on the lm90 driver.
  *
  * The LM63 is a sensor chip made by National Semiconductor. It measures
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
 
 /*
  * Addresses to scan
@@ -99,9 +99,9 @@ SENSORS_INSMOD_1(lm63);
  * Conversions and various macros
  * For tachometer counts, the LM63 uses 16-bit values.
  * For local temperature and high limit, remote critical limit and hysteresis
- * value, it uses signed 8-bit values with LSB = 1 degree Celcius.
+ * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
  * For remote temperature, low and high limits, it uses signed 11-bit values
- * with LSB = 0.125 degree Celcius, left-justified in 16-bit registers.
+ * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
  */
 
 #define FAN_FROM_REG(reg)      ((reg) == 0xFFFC || (reg) == 0 ? 0 : \
@@ -158,16 +158,16 @@ struct lm63_data {
 
        /* registers values */
        u8 config, config_fan;
-       u16 fan1_input;
-       u16 fan1_low;
+       u16 fan[2];     /* 0: input
+                          1: low limit */
        u8 pwm1_freq;
        u8 pwm1_value;
-       s8 temp1_input;
-       s8 temp1_high;
-       s16 temp2_input;
-       s16 temp2_high;
-       s16 temp2_low;
-       s8 temp2_crit;
+       s8 temp8[3];    /* 0: local input
+                          1: local high limit
+                          2: remote critical limit */
+       s16 temp11[3];  /* 0: remote input
+                          1: remote low limit
+                          2: remote high limit */
        u8 temp2_crit_hyst;
        u8 alarms;
 };
@@ -176,33 +176,33 @@ struct lm63_data {
  * Sysfs callback functions and files
  */
 
-#define show_fan(value) \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       struct lm63_data *data = lm63_update_device(dev); \
-       return sprintf(buf, "%d\n", FAN_FROM_REG(data->value)); \
+static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+                       char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm63_data *data = lm63_update_device(dev);
+       return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index]));
 }
-show_fan(fan1_input);
-show_fan(fan1_low);
 
-static ssize_t set_fan1_low(struct device *dev, struct device_attribute *attr, const char *buf,
-       size_t count)
+static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
+                      const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
        down(&data->update_lock);
-       data->fan1_low = FAN_TO_REG(val);
+       data->fan[1] = FAN_TO_REG(val);
        i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB,
-                                 data->fan1_low & 0xFF);
+                                 data->fan[1] & 0xFF);
        i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB,
-                                 data->fan1_low >> 8);
+                                 data->fan[1] >> 8);
        up(&data->update_lock);
        return count;
 }
 
-static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
+                        char *buf)
 {
        struct lm63_data *data = lm63_update_device(dev);
        return sprintf(buf, "%d\n", data->pwm1_value >= 2 * data->pwm1_freq ?
@@ -210,7 +210,8 @@ static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char
                       (2 * data->pwm1_freq));
 }
 
-static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
+                       const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
@@ -229,77 +230,83 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const
        return count;
 }
 
-static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *dummy,
+                               char *buf)
 {
        struct lm63_data *data = lm63_update_device(dev);
        return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
 }
 
-#define show_temp8(value) \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       struct lm63_data *data = lm63_update_device(dev); \
-       return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->value)); \
+static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
+                         char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm63_data *data = lm63_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index]));
 }
-#define show_temp11(value) \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       struct lm63_data *data = lm63_update_device(dev); \
-       return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->value)); \
+
+static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy,
+                        const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm63_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->temp8[1] = TEMP8_TO_REG(val);
+       i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]);
+       up(&data->update_lock);
+       return count;
 }
-show_temp8(temp1_input);
-show_temp8(temp1_high);
-show_temp11(temp2_input);
-show_temp11(temp2_high);
-show_temp11(temp2_low);
-show_temp8(temp2_crit);
-
-#define set_temp8(value, reg) \
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
-       size_t count) \
-{ \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct lm63_data *data = i2c_get_clientdata(client); \
-       long val = simple_strtol(buf, NULL, 10); \
- \
-       down(&data->update_lock); \
-       data->value = TEMP8_TO_REG(val); \
-       i2c_smbus_write_byte_data(client, reg, data->value); \
-       up(&data->update_lock); \
-       return count; \
+
+static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
+                          char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm63_data *data = lm63_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index]));
 }
-#define set_temp11(value, reg_msb, reg_lsb) \
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
-       size_t count) \
-{ \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct lm63_data *data = i2c_get_clientdata(client); \
-       long val = simple_strtol(buf, NULL, 10); \
- \
-       down(&data->update_lock); \
-       data->value = TEMP11_TO_REG(val); \
-       i2c_smbus_write_byte_data(client, reg_msb, data->value >> 8); \
-       i2c_smbus_write_byte_data(client, reg_lsb, data->value & 0xff); \
-       up(&data->update_lock); \
-       return count; \
+
+static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
+                         const char *buf, size_t count)
+{
+       static const u8 reg[4] = {
+               LM63_REG_REMOTE_LOW_MSB,
+               LM63_REG_REMOTE_LOW_LSB,
+               LM63_REG_REMOTE_HIGH_MSB,
+               LM63_REG_REMOTE_HIGH_LSB,
+       };
+
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm63_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+       int nr = attr->index;
+
+       down(&data->update_lock);
+       data->temp11[nr] = TEMP11_TO_REG(val);
+       i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
+                                 data->temp11[nr] >> 8);
+       i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
+                                 data->temp11[nr] & 0xff);
+       up(&data->update_lock);
+       return count;
 }
-set_temp8(temp1_high, LM63_REG_LOCAL_HIGH);
-set_temp11(temp2_high, LM63_REG_REMOTE_HIGH_MSB, LM63_REG_REMOTE_HIGH_LSB);
-set_temp11(temp2_low, LM63_REG_REMOTE_LOW_MSB, LM63_REG_REMOTE_LOW_LSB);
 
 /* Hysteresis register holds a relative value, while we want to present
    an absolute to user-space */
-static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
+                                   char *buf)
 {
        struct lm63_data *data = lm63_update_device(dev);
-       return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp2_crit)
+       return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2])
                       - TEMP8_FROM_REG(data->temp2_crit_hyst));
 }
 
 /* And now the other way around, user-space provides an absolute
    hysteresis value and we have to store a relative one */
-static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *attr, const char *buf,
-       size_t count)
+static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
+                                  const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct lm63_data *data = i2c_get_clientdata(client);
@@ -307,36 +314,37 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *
        long hyst;
 
        down(&data->update_lock);
-       hyst = TEMP8_FROM_REG(data->temp2_crit) - val;
+       hyst = TEMP8_FROM_REG(data->temp8[2]) - val;
        i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
                                  HYST_TO_REG(hyst));
        up(&data->update_lock);
        return count;
 }
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+                          char *buf)
 {
        struct lm63_data *data = lm63_update_device(dev);
        return sprintf(buf, "%u\n", data->alarms);
 }
 
-static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan1_input, NULL);
-static DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan1_low,
-       set_fan1_low);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
+       set_fan, 1);
 
 static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
 static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_high,
-       set_temp1_high);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
+       set_temp8, 1);
 
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp2_input, NULL);
-static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp2_low,
-       set_temp2_low);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp2_high,
-       set_temp2_high);
-static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp2_crit, NULL);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
+       set_temp11, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
+       set_temp11, 2);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2);
 static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
        set_temp2_crit_hyst);
 
@@ -430,17 +438,25 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* Register sysfs hooks */
        if (data->config & 0x04) { /* tachometer enabled */
-               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,
+                                  &sensor_dev_attr_fan1_input.dev_attr);
+               device_create_file(&new_client->dev,
+                                  &sensor_dev_attr_fan1_min.dev_attr);
        }
        device_create_file(&new_client->dev, &dev_attr_pwm1);
        device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_crit);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_input.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_input.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_min.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_max.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_max.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_crit.dev_attr);
        device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
        device_create_file(&new_client->dev, &dev_attr_alarms);
 
@@ -511,14 +527,14 @@ static struct lm63_data *lm63_update_device(struct device *dev)
        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
                if (data->config & 0x04) { /* tachometer enabled  */
                        /* order matters for fan1_input */
-                       data->fan1_input = i2c_smbus_read_byte_data(client,
-                                          LM63_REG_TACH_COUNT_LSB) & 0xFC;
-                       data->fan1_input |= i2c_smbus_read_byte_data(client,
-                                           LM63_REG_TACH_COUNT_MSB) << 8;
-                       data->fan1_low = (i2c_smbus_read_byte_data(client,
-                                         LM63_REG_TACH_LIMIT_LSB) & 0xFC)
-                                      | (i2c_smbus_read_byte_data(client,
-                                         LM63_REG_TACH_LIMIT_MSB) << 8);
+                       data->fan[0] = i2c_smbus_read_byte_data(client,
+                                      LM63_REG_TACH_COUNT_LSB) & 0xFC;
+                       data->fan[0] |= i2c_smbus_read_byte_data(client,
+                                       LM63_REG_TACH_COUNT_MSB) << 8;
+                       data->fan[1] = (i2c_smbus_read_byte_data(client,
+                                       LM63_REG_TACH_LIMIT_LSB) & 0xFC)
+                                    | (i2c_smbus_read_byte_data(client,
+                                       LM63_REG_TACH_LIMIT_MSB) << 8);
                }
 
                data->pwm1_freq = i2c_smbus_read_byte_data(client,
@@ -528,26 +544,26 @@ static struct lm63_data *lm63_update_device(struct device *dev)
                data->pwm1_value = i2c_smbus_read_byte_data(client,
                                   LM63_REG_PWM_VALUE);
 
-               data->temp1_input = i2c_smbus_read_byte_data(client,
-                                   LM63_REG_LOCAL_TEMP);
-               data->temp1_high = i2c_smbus_read_byte_data(client,
-                                  LM63_REG_LOCAL_HIGH);
+               data->temp8[0] = i2c_smbus_read_byte_data(client,
+                                LM63_REG_LOCAL_TEMP);
+               data->temp8[1] = i2c_smbus_read_byte_data(client,
+                                LM63_REG_LOCAL_HIGH);
 
                /* order matters for temp2_input */
-               data->temp2_input = i2c_smbus_read_byte_data(client,
-                                   LM63_REG_REMOTE_TEMP_MSB) << 8;
-               data->temp2_input |= i2c_smbus_read_byte_data(client,
-                                    LM63_REG_REMOTE_TEMP_LSB);
-               data->temp2_high = (i2c_smbus_read_byte_data(client,
-                                  LM63_REG_REMOTE_HIGH_MSB) << 8)
-                                | i2c_smbus_read_byte_data(client,
-                                  LM63_REG_REMOTE_HIGH_LSB);
-               data->temp2_low = (i2c_smbus_read_byte_data(client,
+               data->temp11[0] = i2c_smbus_read_byte_data(client,
+                                 LM63_REG_REMOTE_TEMP_MSB) << 8;
+               data->temp11[0] |= i2c_smbus_read_byte_data(client,
+                                  LM63_REG_REMOTE_TEMP_LSB);
+               data->temp11[1] = (i2c_smbus_read_byte_data(client,
                                  LM63_REG_REMOTE_LOW_MSB) << 8)
                                | i2c_smbus_read_byte_data(client,
                                  LM63_REG_REMOTE_LOW_LSB);
-               data->temp2_crit = i2c_smbus_read_byte_data(client,
-                                  LM63_REG_REMOTE_TCRIT);
+               data->temp11[2] = (i2c_smbus_read_byte_data(client,
+                                 LM63_REG_REMOTE_HIGH_MSB) << 8)
+                               | i2c_smbus_read_byte_data(client,
+                                 LM63_REG_REMOTE_HIGH_LSB);
+               data->temp8[2] = i2c_smbus_read_byte_data(client,
+                                LM63_REG_REMOTE_TCRIT);
                data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
                                        LM63_REG_REMOTE_TCRIT_HYST);
 
index 57c51ac37c04b121a66d09247bb8ddf15d513d68..5be164ed278ebaf236f9b65b98663b450cef8ba5 100644 (file)
@@ -18,7 +18,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 9d15cd5189f6bd45df09b0193c85210881f5f025..b98f449529976083b38c881f5cc9997050d500a7 100644 (file)
@@ -25,7 +25,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 21b195ff3871430916a55234d9b6f784b39486ef..29241469dcbac09d2617c365e7b5388fc6908308 100644 (file)
@@ -18,7 +18,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -671,7 +670,7 @@ static int lm78_detach_client(struct i2c_client *client)
        return 0;
 }
 
-/* The SMBus locks itself, but ISA access must be locked explicitely! 
+/* The SMBus locks itself, but ISA access must be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
@@ -690,7 +689,7 @@ static int lm78_read_value(struct i2c_client *client, u8 reg)
                return i2c_smbus_read_byte_data(client, reg);
 }
 
-/* The SMBus locks itself, but ISA access muse be locked explicitely! 
+/* The SMBus locks itself, but ISA access muse be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
index 404057b70e9003d74915f70def6bebe8da020bfb..8100595feb44640133c6ae6aa7308839f35c7711 100644 (file)
@@ -21,7 +21,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 4d6d7d21e14b2f53192fea59629f1cebadd77694..a49008b444c8ef483f3e6ec933578c3a9e57e240 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2005  Jean Delvare <khali@linux-fr.org>
  *
  * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
  * a sensor chip made by National Semiconductor. It reports up to four
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
 
 /*
  * Addresses to scan
@@ -81,7 +81,7 @@ SENSORS_INSMOD_1(lm83);
 
 /*
  * Conversions and various macros
- * The LM83 uses signed 8-bit values with LSB = 1 degree Celcius.
+ * The LM83 uses signed 8-bit values with LSB = 1 degree Celsius.
  */
 
 #define TEMP_FROM_REG(val)     ((val) * 1000)
@@ -94,21 +94,20 @@ static const u8 LM83_REG_R_TEMP[] = {
        LM83_REG_R_LOCAL_TEMP,
        LM83_REG_R_REMOTE1_TEMP,
        LM83_REG_R_REMOTE2_TEMP,
-       LM83_REG_R_REMOTE3_TEMP
-};
-
-static const u8 LM83_REG_R_HIGH[] = {
+       LM83_REG_R_REMOTE3_TEMP,
        LM83_REG_R_LOCAL_HIGH,
        LM83_REG_R_REMOTE1_HIGH,
        LM83_REG_R_REMOTE2_HIGH,
-       LM83_REG_R_REMOTE3_HIGH
+       LM83_REG_R_REMOTE3_HIGH,
+       LM83_REG_R_TCRIT,
 };
 
 static const u8 LM83_REG_W_HIGH[] = {
        LM83_REG_W_LOCAL_HIGH,
        LM83_REG_W_REMOTE1_HIGH,
        LM83_REG_W_REMOTE2_HIGH,
-       LM83_REG_W_REMOTE3_HIGH
+       LM83_REG_W_REMOTE3_HIGH,
+       LM83_REG_W_TCRIT,
 };
 
 /*
@@ -144,9 +143,9 @@ struct lm83_data {
        unsigned long last_updated; /* in jiffies */
 
        /* registers values */
-       s8 temp_input[4];
-       s8 temp_high[4];
-       s8 temp_crit;
+       s8 temp[9];     /* 0..3: input 1-4,
+                          4..7: high limit 1-4,
+                          8   : critical limit */
        u16 alarms; /* bitvector, combined */
 };
 
@@ -154,65 +153,55 @@ struct lm83_data {
  * Sysfs stuff
  */
 
-#define show_temp(suffix, value) \
-static ssize_t show_temp_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       struct lm83_data *data = lm83_update_device(dev); \
-       return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+                        char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm83_data *data = lm83_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
 }
-show_temp(input1, temp_input[0]);
-show_temp(input2, temp_input[1]);
-show_temp(input3, temp_input[2]);
-show_temp(input4, temp_input[3]);
-show_temp(high1, temp_high[0]);
-show_temp(high2, temp_high[1]);
-show_temp(high3, temp_high[2]);
-show_temp(high4, temp_high[3]);
-show_temp(crit, temp_crit);
-
-#define set_temp(suffix, value, reg) \
-static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
-       size_t count) \
-{ \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct lm83_data *data = i2c_get_clientdata(client); \
-       long val = simple_strtol(buf, NULL, 10); \
- \
-       down(&data->update_lock); \
-       data->value = TEMP_TO_REG(val); \
-       i2c_smbus_write_byte_data(client, reg, data->value); \
-       up(&data->update_lock); \
-       return count; \
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
+                       const char *buf, size_t count)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm83_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+       int nr = attr->index;
+
+       down(&data->update_lock);
+       data->temp[nr] = TEMP_TO_REG(val);
+       i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4],
+                                 data->temp[nr]);
+       up(&data->update_lock);
+       return count;
 }
-set_temp(high1, temp_high[0], LM83_REG_W_LOCAL_HIGH);
-set_temp(high2, temp_high[1], LM83_REG_W_REMOTE1_HIGH);
-set_temp(high3, temp_high[2], LM83_REG_W_REMOTE2_HIGH);
-set_temp(high4, temp_high[3], LM83_REG_W_REMOTE3_HIGH);
-set_temp(crit, temp_crit, LM83_REG_W_TCRIT);
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+                          char *buf)
 {
        struct lm83_data *data = lm83_update_device(dev);
        return sprintf(buf, "%d\n", data->alarms);
 }
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
-static DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input3, NULL);
-static DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input4, NULL);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_high1,
-    set_temp_high1);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2,
-    set_temp_high2);
-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(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 SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp,
+       set_temp, 4);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp,
+       set_temp, 5);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp,
+       set_temp, 6);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp,
+       set_temp, 7);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp,
+       set_temp, 8);
+static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 /*
@@ -323,18 +312,30 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
         */
 
        /* Register sysfs hooks */
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp3_input);
-       device_create_file(&new_client->dev, &dev_attr_temp4_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       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_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,
+                          &sensor_dev_attr_temp1_input.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_input.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp3_input.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp4_input.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_max.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_max.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp3_max.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp4_max.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_crit.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_crit.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp3_crit.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp4_crit.dev_attr);
        device_create_file(&new_client->dev, &dev_attr_alarms);
 
        return 0;
@@ -370,16 +371,11 @@ static struct lm83_data *lm83_update_device(struct device *dev)
                int nr;
 
                dev_dbg(&client->dev, "Updating lm83 data.\n");
-               for (nr = 0; nr < ; nr++) {
-                       data->temp_input[nr] =
+               for (nr = 0; nr < 9; nr++) {
+                       data->temp[nr] =
                            i2c_smbus_read_byte_data(client,
                            LM83_REG_R_TEMP[nr]);
-                       data->temp_high[nr] =
-                           i2c_smbus_read_byte_data(client,
-                           LM83_REG_R_HIGH[nr]);
                }
-               data->temp_crit =
-                   i2c_smbus_read_byte_data(client, LM83_REG_R_TCRIT);
                data->alarms =
                    i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1)
                    + (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2)
index b1976775b4ba89b7e18b03487c42f622c4d5ef60..b4d7fd41826478a241d50535a70bbbf0507c8de4 100644 (file)
@@ -23,7 +23,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -285,8 +284,6 @@ static int ZONE_TO_REG( int zone )
 /* i2c-vid.h defines vid_from_reg() */
 #define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
 
-#define ALARMS_FROM_REG(val) (val)
-
 /* Unlike some other drivers we DO NOT set initial limits.  Use
  * the config file to set limits.  Some users have reported
  * motherboards shutting down when we set limits in a previous
@@ -481,7 +478,7 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct lm85_data *data = lm85_update_device(dev);
-       return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+       return sprintf(buf, "%u\n", data->alarms);
 }
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
index 4372b61a08822f4c612f1d5bbf7bb949e2a54447..1921ed1af182df9f05dc68b114e7115f51009bea 100644 (file)
@@ -52,7 +52,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 9b127a07f56bcf6dc0b981a605bfd19cc8b85f99..a67dcadf7cb04381882b71185786fa1c945677d2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003-2004  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2005  Jean Delvare <khali@linux-fr.org>
  *
  * Based on the lm83 driver. The LM90 is a sensor chip made by National
  * Semiconductor. It reports up to two temperatures (its own plus up to
@@ -19,7 +19,7 @@
  * Complete datasheets can be obtained from National's website at:
  *   http://www.national.com/pf/LM/LM89.html
  *   http://www.national.com/pf/LM/LM99.html
- * Note that there is no way to differenciate between both chips.
+ * Note that there is no way to differentiate between both chips.
  *
  * This driver also supports the LM86, another sensor chip made by
  * National Semiconductor. It is exactly similar to the LM90 except it
@@ -39,7 +39,7 @@
  * chips made by Maxim. These chips are similar to the LM86. Complete
  * datasheet can be obtained at Maxim's website at:
  *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
- * Note that there is no easy way to differenciate between the three
+ * Note that there is no easy way to differentiate between the three
  * variants. The extra address and features of the MAX6659 are not
  * supported by this driver.
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
 
 /*
  * Addresses to scan
@@ -139,9 +139,9 @@ SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
 /*
  * Conversions and various macros
  * For local temperatures and limits, critical limits and the hysteresis
- * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celcius.
+ * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
  * For remote temperatures and limits, it uses signed 11-bit values with
- * LSB = 0.125 degree Celcius, left-justified in 16-bit registers.
+ * LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
  */
 
 #define TEMP1_FROM_REG(val)    ((val) * 1000)
@@ -206,9 +206,14 @@ struct lm90_data {
        int kind;
 
        /* registers values */
-       s8 temp_input1, temp_low1, temp_high1; /* local */
-       s16 temp_input2, temp_low2, temp_high2; /* remote, combined */
-       s8 temp_crit1, temp_crit2;
+       s8 temp8[5];    /* 0: local input
+                          1: local low limit
+                          2: local high limit
+                          3: local critical limit
+                          4: remote critical limit */
+       s16 temp11[3];  /* 0: remote input
+                          1: remote low limit
+                          2: remote high limit */
        u8 temp_hyst;
        u8 alarms; /* bitvector */
 };
@@ -217,75 +222,88 @@ struct lm90_data {
  * Sysfs stuff
  */
 
-#define show_temp(value, converter) \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       struct lm90_data *data = lm90_update_device(dev); \
-       return sprintf(buf, "%d\n", converter(data->value)); \
+static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
+                         char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm90_data *data = lm90_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp8[attr->index]));
+}
+
+static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
+                        const char *buf, size_t count)
+{
+       static const u8 reg[4] = {
+               LM90_REG_W_LOCAL_LOW,
+               LM90_REG_W_LOCAL_HIGH,
+               LM90_REG_W_LOCAL_CRIT,
+               LM90_REG_W_REMOTE_CRIT,
+       };
+
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm90_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+       int nr = attr->index;
+
+       down(&data->update_lock);
+       if (data->kind == adt7461)
+               data->temp8[nr] = TEMP1_TO_REG_ADT7461(val);
+       else
+               data->temp8[nr] = TEMP1_TO_REG(val);
+       i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]);
+       up(&data->update_lock);
+       return count;
 }
-show_temp(temp_input1, TEMP1_FROM_REG);
-show_temp(temp_input2, TEMP2_FROM_REG);
-show_temp(temp_low1, TEMP1_FROM_REG);
-show_temp(temp_low2, TEMP2_FROM_REG);
-show_temp(temp_high1, TEMP1_FROM_REG);
-show_temp(temp_high2, TEMP2_FROM_REG);
-show_temp(temp_crit1, TEMP1_FROM_REG);
-show_temp(temp_crit2, TEMP1_FROM_REG);
-
-#define set_temp1(value, reg) \
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
-       size_t count) \
-{ \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct lm90_data *data = i2c_get_clientdata(client); \
-       long val = simple_strtol(buf, NULL, 10); \
- \
-       down(&data->update_lock); \
-       if (data->kind == adt7461) \
-               data->value = TEMP1_TO_REG_ADT7461(val); \
-       else \
-               data->value = TEMP1_TO_REG(val); \
-       i2c_smbus_write_byte_data(client, reg, data->value); \
-       up(&data->update_lock); \
-       return count; \
+
+static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
+                          char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm90_data *data = lm90_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP2_FROM_REG(data->temp11[attr->index]));
 }
-#define set_temp2(value, regh, regl) \
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
-       size_t count) \
-{ \
-       struct i2c_client *client = to_i2c_client(dev); \
-       struct lm90_data *data = i2c_get_clientdata(client); \
-       long val = simple_strtol(buf, NULL, 10); \
- \
-       down(&data->update_lock); \
-       if (data->kind == adt7461) \
-               data->value = TEMP2_TO_REG_ADT7461(val); \
-       else \
-               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); \
-       up(&data->update_lock); \
-       return count; \
+
+static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
+                         const char *buf, size_t count)
+{
+       static const u8 reg[4] = {
+               LM90_REG_W_REMOTE_LOWH,
+               LM90_REG_W_REMOTE_LOWL,
+               LM90_REG_W_REMOTE_HIGHH,
+               LM90_REG_W_REMOTE_HIGHL,
+       };
+
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm90_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+       int nr = attr->index;
+
+       down(&data->update_lock);
+       if (data->kind == adt7461)
+               data->temp11[nr] = TEMP2_TO_REG_ADT7461(val);
+       else
+               data->temp11[nr] = TEMP2_TO_REG(val);
+       i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
+                                 data->temp11[nr] >> 8);
+       i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
+                                 data->temp11[nr] & 0xff);
+       up(&data->update_lock);
+       return count;
 }
-set_temp1(temp_low1, LM90_REG_W_LOCAL_LOW);
-set_temp2(temp_low2, LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL);
-set_temp1(temp_high1, LM90_REG_W_LOCAL_HIGH);
-set_temp2(temp_high2, LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL);
-set_temp1(temp_crit1, LM90_REG_W_LOCAL_CRIT);
-set_temp1(temp_crit2, LM90_REG_W_REMOTE_CRIT);
-
-#define show_temp_hyst(value, basereg) \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-       struct lm90_data *data = lm90_update_device(dev); \
-       return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->basereg) \
-                      - TEMP1_FROM_REG(data->temp_hyst)); \
+
+static ssize_t show_temphyst(struct device *dev, struct device_attribute *devattr,
+                            char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm90_data *data = lm90_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp8[attr->index])
+                      - TEMP1_FROM_REG(data->temp_hyst));
 }
-show_temp_hyst(temp_hyst1, temp_crit1);
-show_temp_hyst(temp_hyst2, temp_crit2);
 
-static ssize_t set_temp_hyst1(struct device *dev, struct device_attribute *attr, const char *buf,
-       size_t count)
+static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
+                           const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct lm90_data *data = i2c_get_clientdata(client);
@@ -293,36 +311,37 @@ static ssize_t set_temp_hyst1(struct device *dev, struct device_attribute *attr,
        long hyst;
 
        down(&data->update_lock);
-       hyst = TEMP1_FROM_REG(data->temp_crit1) - val;
+       hyst = TEMP1_FROM_REG(data->temp8[3]) - val;
        i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
                                  HYST_TO_REG(hyst));
        up(&data->update_lock);
        return count;
 }
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+                          char *buf)
 {
        struct lm90_data *data = lm90_update_device(dev);
        return sprintf(buf, "%d\n", data->alarms);
 }
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
-static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_low1,
-       set_temp_low1);
-static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_low2,
-       set_temp_low2);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_high1,
-       set_temp_high1);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2,
-       set_temp_high2);
-static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit1,
-       set_temp_crit1);
-static DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit2,
-       set_temp_crit2);
-static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst1,
-       set_temp_hyst1);
-static DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_hyst2, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8,
+       set_temp8, 1);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
+       set_temp11, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
+       set_temp8, 2);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
+       set_temp11, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8,
+       set_temp8, 3);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8,
+       set_temp8, 4);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
+       set_temphyst, 3);
+static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 /*
@@ -481,16 +500,26 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
        lm90_init_client(new_client);
 
        /* Register sysfs hooks */
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       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_temp1_crit_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_input.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_input.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_min.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_min.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_max.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_max.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_crit.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_crit.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_crit_hyst.dev_attr);
+       device_create_file(&new_client->dev,
+                          &sensor_dev_attr_temp2_crit_hyst.dev_attr);
        device_create_file(&new_client->dev, &dev_attr_alarms);
 
        return 0;
@@ -541,16 +570,16 @@ static struct lm90_data *lm90_update_device(struct device *dev)
                u8 oldh, newh;
 
                dev_dbg(&client->dev, "Updating lm90 data.\n");
-               data->temp_input1 = i2c_smbus_read_byte_data(client,
-                                   LM90_REG_R_LOCAL_TEMP);
-               data->temp_high1 = i2c_smbus_read_byte_data(client,
-                                  LM90_REG_R_LOCAL_HIGH);
-               data->temp_low1 = i2c_smbus_read_byte_data(client,
-                                 LM90_REG_R_LOCAL_LOW);
-               data->temp_crit1 = i2c_smbus_read_byte_data(client,
-                                  LM90_REG_R_LOCAL_CRIT);
-               data->temp_crit2 = i2c_smbus_read_byte_data(client,
-                                  LM90_REG_R_REMOTE_CRIT);
+               data->temp8[0] = i2c_smbus_read_byte_data(client,
+                                LM90_REG_R_LOCAL_TEMP);
+               data->temp8[1] = i2c_smbus_read_byte_data(client,
+                                LM90_REG_R_LOCAL_LOW);
+               data->temp8[2] = i2c_smbus_read_byte_data(client,
+                                LM90_REG_R_LOCAL_HIGH);
+               data->temp8[3] = i2c_smbus_read_byte_data(client,
+                                LM90_REG_R_LOCAL_CRIT);
+               data->temp8[4] = i2c_smbus_read_byte_data(client,
+                                LM90_REG_R_REMOTE_CRIT);
                data->temp_hyst = i2c_smbus_read_byte_data(client,
                                  LM90_REG_R_TCRIT_HYST);
 
@@ -570,13 +599,13 @@ static struct lm90_data *lm90_update_device(struct device *dev)
                 */
                oldh = i2c_smbus_read_byte_data(client,
                       LM90_REG_R_REMOTE_TEMPH);
-               data->temp_input2 = i2c_smbus_read_byte_data(client,
-                                   LM90_REG_R_REMOTE_TEMPL);
+               data->temp11[0] = i2c_smbus_read_byte_data(client,
+                                 LM90_REG_R_REMOTE_TEMPL);
                newh = i2c_smbus_read_byte_data(client,
                       LM90_REG_R_REMOTE_TEMPH);
                if (newh != oldh) {
-                       data->temp_input2 = i2c_smbus_read_byte_data(client,
-                                           LM90_REG_R_REMOTE_TEMPL);
+                       data->temp11[0] = i2c_smbus_read_byte_data(client,
+                                         LM90_REG_R_REMOTE_TEMPL);
 #ifdef DEBUG
                        oldh = i2c_smbus_read_byte_data(client,
                               LM90_REG_R_REMOTE_TEMPH);
@@ -586,16 +615,16 @@ static struct lm90_data *lm90_update_device(struct device *dev)
                                         "wrong.\n");
 #endif
                }
-               data->temp_input2 |= (newh << 8);
+               data->temp11[0] |= (newh << 8);
 
-               data->temp_high2 = (i2c_smbus_read_byte_data(client,
+               data->temp11[1] = (i2c_smbus_read_byte_data(client,
+                                  LM90_REG_R_REMOTE_LOWH) << 8) +
+                                  i2c_smbus_read_byte_data(client,
+                                  LM90_REG_R_REMOTE_LOWL);
+               data->temp11[2] = (i2c_smbus_read_byte_data(client,
                                   LM90_REG_R_REMOTE_HIGHH) << 8) +
                                   i2c_smbus_read_byte_data(client,
                                   LM90_REG_R_REMOTE_HIGHL);
-               data->temp_low2 = (i2c_smbus_read_byte_data(client,
-                                 LM90_REG_R_REMOTE_LOWH) << 8) +
-                                 i2c_smbus_read_byte_data(client,
-                                 LM90_REG_R_REMOTE_LOWL);
                data->alarms = i2c_smbus_read_byte_data(client,
                               LM90_REG_R_STATUS);
 
index e771566dffa8d6af6b926891ee8c90ee9b2d7af8..5e463c47bfbc70e66e8d23ab73a71aab193b31ee 100644 (file)
@@ -40,11 +40,8 @@ static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_addr,
-       .normal_i2c_range       = ignore,
        .probe                  = ignore,
-       .probe_range            = ignore,
        .ignore                 = ignore,
-       .ignore_range           = ignore,
        .force                  = ignore,
 };
 
index 30a196155fd983e53afe4e22f1b41d8f56d1b982..bf553dcd97d68f0e853586a67f675afed8b263f2 100644 (file)
@@ -26,7 +26,6 @@
  */
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
new file mode 100644 (file)
index 0000000..fe6b150
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+    max6875.c - driver for MAX6874/MAX6875
+
+    Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
+
+    Based on i2c/chips/eeprom.c
+
+    The MAX6875 has two EEPROM sections: config and user.
+    At reset, the config EEPROM is read into the registers.
+
+    This driver make 3 binary files available in sysfs:
+      reg_config    - direct access to the registers
+      eeprom_config - acesses configuration eeprom space
+      eeprom_user   - free for application use
+
+    In our application, we put device serial & model numbers in user eeprom.
+
+    Notes:
+      1) The datasheet says that register 0x44 / EEPROM 0x8044 should NOT
+         be overwritten, so the driver explicitly prevents that.
+      2) It's a good idea to keep the config (0x45) locked in config EEPROM.
+         You can temporarily enable config writes by changing register 0x45.
+
+    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 of the License.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {0x50, 0x52, I2C_CLIENT_END};
+static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(max6875);
+
+/* this param will prevent 'accidental' writes to the eeprom */
+static int allow_write = 0;
+module_param(allow_write, int, 0);
+MODULE_PARM_DESC(allow_write,
+                "Enable write access:\n"
+                "*0: Read only\n"
+                " 1: Read/Write access");
+
+/* The MAX6875 can only read/write 16 bytes at a time */
+#define SLICE_SIZE                     16
+#define SLICE_BITS                     4
+
+/* CONFIG EEPROM is at addresses 0x8000 - 0x8045, registers are at 0 - 0x45 */
+#define CONFIG_EEPROM_BASE             0x8000
+#define CONFIG_EEPROM_SIZE             0x0046
+#define CONFIG_EEPROM_SLICES           5
+
+/* USER EEPROM is at addresses 0x8100 - 0x82FF */
+#define USER_EEPROM_BASE               0x8100
+#define USER_EEPROM_SIZE               0x0200
+#define USER_EEPROM_SLICES             32
+
+/* MAX6875 commands */
+#define MAX6875_CMD_BLOCK_WRITE                0x83
+#define MAX6875_CMD_BLOCK_READ         0x84
+#define MAX6875_CMD_REBOOT             0x88
+
+enum max6875_area_type {
+       max6875_register_config=0,
+       max6875_eeprom_config,
+       max6875_eeprom_user,
+       max6857_max
+};
+
+struct eeprom_block {
+       enum max6875_area_type  type;
+       u8                      slices;
+       u32                     size;
+       u32                     valid;
+       u32                     base;
+       unsigned long           *updated;
+       u8                      *data;
+};
+
+/* Each client has this additional data */
+struct max6875_data {
+       struct i2c_client       client;
+       struct semaphore        update_lock;
+       struct eeprom_block     blocks[max6857_max];
+       /* the above structs point into the arrays below */
+       u8 data[USER_EEPROM_SIZE + (CONFIG_EEPROM_SIZE*2)];
+       unsigned long last_updated[USER_EEPROM_SLICES + (CONFIG_EEPROM_SLICES*2)];
+};
+
+static int max6875_attach_adapter(struct i2c_adapter *adapter);
+static int max6875_detect(struct i2c_adapter *adapter, int address, int kind);
+static int max6875_detach_client(struct i2c_client *client);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max6875_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "max6875",
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = max6875_attach_adapter,
+       .detach_client  = max6875_detach_client,
+};
+
+static int max6875_update_slice(struct i2c_client *client,
+                               struct eeprom_block *blk,
+                               int slice)
+{
+       struct max6875_data *data = i2c_get_clientdata(client);
+       int i, j, addr, count;
+       u8 rdbuf[SLICE_SIZE];
+       int retval = 0;
+
+       if (slice >= blk->slices)
+               return -1;
+
+       down(&data->update_lock);
+
+       if (!(blk->valid & (1 << slice)) ||
+           (jiffies - blk->updated[slice] > 300 * HZ) ||
+           (jiffies < blk->updated[slice])) {
+               dev_dbg(&client->dev, "Starting eeprom update, slice %u, base %u\n",
+                       slice, blk->base);
+
+               addr = blk->base + (slice << SLICE_BITS);
+               count = blk->size - (slice << SLICE_BITS);
+               if (count > SLICE_SIZE) {
+                       count = SLICE_SIZE;
+               }
+
+               /* Preset the read address */
+               if (addr < 0x100) {
+                       /* select the register */
+                       if (i2c_smbus_write_byte(client, addr & 0xFF)) {
+                               dev_dbg(&client->dev, "max6875 register select has failed!\n");
+                               retval = -1;
+                               goto exit;
+                       }
+               } else {
+                       /* select the eeprom */
+                       if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
+                               dev_dbg(&client->dev, "max6875 address set has failed!\n");
+                               retval = -1;
+                               goto exit;
+                       }
+               }
+
+               if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+                       if (i2c_smbus_read_i2c_block_data(client, MAX6875_CMD_BLOCK_READ,
+                                                         rdbuf) != SLICE_SIZE)
+                       {
+                               retval = -1;
+                               goto exit;
+                       }
+
+                       memcpy(&blk->data[slice << SLICE_BITS], rdbuf, count);
+               } else {
+                       for (i = 0; i < count; i++) {
+                               j = i2c_smbus_read_byte(client);
+                               if (j < 0)
+                               {
+                                       retval = -1;
+                                       goto exit;
+                               }
+                               blk->data[(slice << SLICE_BITS) + i] = (u8) j;
+                       }
+               }
+               blk->updated[slice] = jiffies;
+               blk->valid |= (1 << slice);
+       }
+       exit:
+       up(&data->update_lock);
+       return retval;
+}
+
+static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, size_t count,
+                           enum max6875_area_type area_type)
+{
+       struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+       struct max6875_data *data = i2c_get_clientdata(client);
+       struct eeprom_block *blk;
+       int slice;
+
+       blk = &data->blocks[area_type];
+
+       if (off > blk->size)
+               return 0;
+       if (off + count > blk->size)
+               count = blk->size - off;
+
+       /* Only refresh slices which contain requested bytes */
+       for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
+               max6875_update_slice(client, blk, slice);
+
+       memcpy(buf, &blk->data[off], count);
+
+       return count;
+}
+
+static ssize_t max6875_user_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+       return max6875_read(kobj, buf, off, count, max6875_eeprom_user);
+}
+
+static ssize_t max6875_config_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+       return max6875_read(kobj, buf, off, count, max6875_eeprom_config);
+}
+
+static ssize_t max6875_cfgreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+       return max6875_read(kobj, buf, off, count, max6875_register_config);
+}
+
+
+static ssize_t max6875_write(struct kobject *kobj, char *buf, loff_t off, size_t count,
+                            enum max6875_area_type area_type)
+{
+       struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+       struct max6875_data *data = i2c_get_clientdata(client);
+       struct eeprom_block *blk;
+       int slice, addr, retval;
+       ssize_t sent = 0;
+
+       blk = &data->blocks[area_type];
+
+       if (off > blk->size)
+               return 0;
+       if ((off + count) > blk->size)
+               count = blk->size - off;
+
+       if (down_interruptible(&data->update_lock))
+               return -EAGAIN;
+
+       /* writing to a register is done with i2c_smbus_write_byte_data() */
+       if (blk->type == max6875_register_config) {
+               for (sent = 0; sent < count; sent++) {
+                       addr = off + sent;
+                       if (addr == 0x44)
+                               continue;
+
+                       retval = i2c_smbus_write_byte_data(client, addr, buf[sent]);
+               }
+       } else {
+               int cmd, val;
+
+               /* We are writing to EEPROM */
+               for (sent = 0; sent < count; sent++) {
+                       addr = blk->base + off + sent;
+                       cmd = addr >> 8;
+                       val = (addr & 0xff) | (buf[sent] << 8); // reversed
+
+                       if (addr == 0x8044)
+                               continue;
+
+                       retval = i2c_smbus_write_word_data(client, cmd, val);
+
+                       if (retval) {
+                               goto error_exit;
+                       }
+
+                       /* A write takes up to 11 ms */
+                       msleep(11);
+               }
+       }
+
+       /* Invalidate the scratch buffer */
+       for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
+               blk->valid &= ~(1 << slice);
+
+       error_exit:
+       up(&data->update_lock);
+
+       return sent;
+}
+
+static ssize_t max6875_user_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+       return max6875_write(kobj, buf, off, count, max6875_eeprom_user);
+}
+
+static ssize_t max6875_config_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+       return max6875_write(kobj, buf, off, count, max6875_eeprom_config);
+}
+
+static ssize_t max6875_cfgreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+       return max6875_write(kobj, buf, off, count, max6875_register_config);
+}
+
+static struct bin_attribute user_eeprom_attr = {
+       .attr = {
+               .name = "eeprom_user",
+               .mode = S_IRUGO | S_IWUSR | S_IWGRP,
+               .owner = THIS_MODULE,
+       },
+       .size  = USER_EEPROM_SIZE,
+       .read  = max6875_user_read,
+       .write = max6875_user_write,
+};
+
+static struct bin_attribute config_eeprom_attr = {
+       .attr = {
+               .name = "eeprom_config",
+               .mode = S_IRUGO | S_IWUSR,
+               .owner = THIS_MODULE,
+       },
+       .size  = CONFIG_EEPROM_SIZE,
+       .read  = max6875_config_read,
+       .write = max6875_config_write,
+};
+
+static struct bin_attribute config_register_attr = {
+       .attr = {
+               .name = "reg_config",
+               .mode = S_IRUGO | S_IWUSR,
+               .owner = THIS_MODULE,
+       },
+       .size  = CONFIG_EEPROM_SIZE,
+       .read  = max6875_cfgreg_read,
+       .write = max6875_cfgreg_write,
+};
+
+static int max6875_attach_adapter(struct i2c_adapter *adapter)
+{
+       return i2c_detect(adapter, &addr_data, max6875_detect);
+}
+
+/* This function is called by i2c_detect */
+static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *new_client;
+       struct max6875_data *data;
+       int err = 0;
+
+       /* There are three ways we can read the EEPROM data:
+          (1) I2C block reads (faster, but unsupported by most adapters)
+          (2) Consecutive byte reads (100% overhead)
+          (3) Regular byte data reads (200% overhead)
+          The third method is not implemented by this driver because all
+          known adapters support at least the second. */
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA |
+                                    I2C_FUNC_SMBUS_BYTE |
+                                    I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+               goto exit;
+
+       /* OK. For now, we presume we have a valid client. We now create the
+          client structure, even though we cannot fill it completely yet.
+          But it allows us to access eeprom_{read,write}_value. */
+       if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit;
+       }
+       memset(data, 0, sizeof(struct max6875_data));
+
+       new_client = &data->client;
+       i2c_set_clientdata(new_client, data);
+       new_client->addr = address;
+       new_client->adapter = adapter;
+       new_client->driver = &max6875_driver;
+       new_client->flags = 0;
+
+       /* Setup the user section */
+       data->blocks[max6875_eeprom_user].type    = max6875_eeprom_user;
+       data->blocks[max6875_eeprom_user].slices  = USER_EEPROM_SLICES;
+       data->blocks[max6875_eeprom_user].size    = USER_EEPROM_SIZE;
+       data->blocks[max6875_eeprom_user].base    = USER_EEPROM_BASE;
+       data->blocks[max6875_eeprom_user].data    = data->data;
+       data->blocks[max6875_eeprom_user].updated = data->last_updated;
+
+       /* Setup the config section */
+       data->blocks[max6875_eeprom_config].type    = max6875_eeprom_config;
+       data->blocks[max6875_eeprom_config].slices  = CONFIG_EEPROM_SLICES;
+       data->blocks[max6875_eeprom_config].size    = CONFIG_EEPROM_SIZE;
+       data->blocks[max6875_eeprom_config].base    = CONFIG_EEPROM_BASE;
+       data->blocks[max6875_eeprom_config].data    = &data->data[USER_EEPROM_SIZE];
+       data->blocks[max6875_eeprom_config].updated = &data->last_updated[USER_EEPROM_SLICES];
+
+       /* Setup the register section */
+       data->blocks[max6875_register_config].type    = max6875_register_config;
+       data->blocks[max6875_register_config].slices  = CONFIG_EEPROM_SLICES;
+       data->blocks[max6875_register_config].size    = CONFIG_EEPROM_SIZE;
+       data->blocks[max6875_register_config].base    = 0;
+       data->blocks[max6875_register_config].data    = &data->data[USER_EEPROM_SIZE+CONFIG_EEPROM_SIZE];
+       data->blocks[max6875_register_config].updated = &data->last_updated[USER_EEPROM_SLICES+CONFIG_EEPROM_SLICES];
+
+       /* Init the data */
+       memset(data->data, 0xff, sizeof(data->data));
+
+       /* Fill in the remaining client fields */
+       strlcpy(new_client->name, "max6875", I2C_NAME_SIZE);
+       init_MUTEX(&data->update_lock);
+
+       /* Verify that the chip is really what we think it is */
+       if ((max6875_update_slice(new_client, &data->blocks[max6875_eeprom_config], 4) < 0) ||
+           (max6875_update_slice(new_client, &data->blocks[max6875_register_config], 4) < 0))
+               goto exit_kfree;
+
+       /* 0x41,0x42 must be zero and 0x40 must match in eeprom and registers */
+       if ((data->blocks[max6875_eeprom_config].data[0x41] != 0) ||
+           (data->blocks[max6875_eeprom_config].data[0x42] != 0) ||
+           (data->blocks[max6875_register_config].data[0x41] != 0) ||
+           (data->blocks[max6875_register_config].data[0x42] != 0) ||
+           (data->blocks[max6875_eeprom_config].data[0x40] !=
+            data->blocks[max6875_register_config].data[0x40]))
+               goto exit_kfree;
+
+       /* Tell the I2C layer a new client has arrived */
+       if ((err = i2c_attach_client(new_client)))
+               goto exit_kfree;
+
+       /* create the sysfs eeprom files with the correct permissions */
+       if (allow_write == 0) {
+               user_eeprom_attr.attr.mode &= ~S_IWUGO;
+               user_eeprom_attr.write = NULL;
+               config_eeprom_attr.attr.mode &= ~S_IWUGO;
+               config_eeprom_attr.write = NULL;
+               config_register_attr.attr.mode &= ~S_IWUGO;
+               config_register_attr.write = NULL;
+       }
+       sysfs_create_bin_file(&new_client->dev.kobj, &user_eeprom_attr);
+       sysfs_create_bin_file(&new_client->dev.kobj, &config_eeprom_attr);
+       sysfs_create_bin_file(&new_client->dev.kobj, &config_register_attr);
+
+       return 0;
+
+exit_kfree:
+       kfree(data);
+exit:
+       return err;
+}
+
+static int max6875_detach_client(struct i2c_client *client)
+{
+       int err;
+
+       err = i2c_detach_client(client);
+       if (err) {
+               dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+               return err;
+       }
+
+       kfree(i2c_get_clientdata(client));
+
+       return 0;
+}
+
+static int __init max6875_init(void)
+{
+       return i2c_add_driver(&max6875_driver);
+}
+
+static void __exit max6875_exit(void)
+{
+       i2c_del_driver(&max6875_driver);
+}
+
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("MAX6875 driver");
+MODULE_LICENSE("GPL");
+
+module_init(max6875_init);
+module_exit(max6875_exit);
index 65637b2cd170d4e334b385c6a55e8d1518fe6fb6..876c68f3af31e4e80fbc5263ad47e97b650ea4a5 100644 (file)
@@ -33,7 +33,6 @@
  *  the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F).
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
new file mode 100644 (file)
index 0000000..9f3ad45
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+    pca9539.c - 16-bit I/O port with interrupt and reset
+
+    Copyright (C) 2005 Ben Gardner <bgardner@wabtec.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 of the License.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
+static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(pca9539);
+
+enum pca9539_cmd
+{
+       PCA9539_INPUT_0         = 0,
+       PCA9539_INPUT_1         = 1,
+       PCA9539_OUTPUT_0        = 2,
+       PCA9539_OUTPUT_1        = 3,
+       PCA9539_INVERT_0        = 4,
+       PCA9539_INVERT_1        = 5,
+       PCA9539_DIRECTION_0     = 6,
+       PCA9539_DIRECTION_1     = 7,
+};
+
+static int pca9539_attach_adapter(struct i2c_adapter *adapter);
+static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pca9539_detach_client(struct i2c_client *client);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver pca9539_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "pca9539",
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = pca9539_attach_adapter,
+       .detach_client  = pca9539_detach_client,
+};
+
+struct pca9539_data {
+       struct i2c_client client;
+};
+
+/* following are the sysfs callback functions */
+static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
+       struct i2c_client *client = to_i2c_client(dev);
+       return sprintf(buf, "%d\n", i2c_smbus_read_byte_data(client,
+                                                            psa->index));
+}
+
+static ssize_t pca9539_store(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count)
+{
+       struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned long val = simple_strtoul(buf, NULL, 0);
+       if (val > 0xff)
+               return -EINVAL;
+       i2c_smbus_write_byte_data(client, psa->index, val);
+       return count;
+}
+
+/* Define the device attributes */
+
+#define PCA9539_ENTRY_RO(name, cmd_idx) \
+       static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9539_show, NULL, cmd_idx)
+
+#define PCA9539_ENTRY_RW(name, cmd_idx) \
+       static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9539_show, \
+                                 pca9539_store, cmd_idx)
+
+PCA9539_ENTRY_RO(input0, PCA9539_INPUT_0);
+PCA9539_ENTRY_RO(input1, PCA9539_INPUT_1);
+PCA9539_ENTRY_RW(output0, PCA9539_OUTPUT_0);
+PCA9539_ENTRY_RW(output1, PCA9539_OUTPUT_1);
+PCA9539_ENTRY_RW(invert0, PCA9539_INVERT_0);
+PCA9539_ENTRY_RW(invert1, PCA9539_INVERT_1);
+PCA9539_ENTRY_RW(direction0, PCA9539_DIRECTION_0);
+PCA9539_ENTRY_RW(direction1, PCA9539_DIRECTION_1);
+
+static struct attribute *pca9539_attributes[] = {
+       &sensor_dev_attr_input0.dev_attr.attr,
+       &sensor_dev_attr_input1.dev_attr.attr,
+       &sensor_dev_attr_output0.dev_attr.attr,
+       &sensor_dev_attr_output1.dev_attr.attr,
+       &sensor_dev_attr_invert0.dev_attr.attr,
+       &sensor_dev_attr_invert1.dev_attr.attr,
+       &sensor_dev_attr_direction0.dev_attr.attr,
+       &sensor_dev_attr_direction1.dev_attr.attr,
+       NULL
+};
+
+static struct attribute_group pca9539_defattr_group = {
+       .attrs = pca9539_attributes,
+};
+
+static int pca9539_attach_adapter(struct i2c_adapter *adapter)
+{
+       return i2c_detect(adapter, &addr_data, pca9539_detect);
+}
+
+/* This function is called by i2c_detect */
+static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *new_client;
+       struct pca9539_data *data;
+       int err = 0;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               goto exit;
+
+       /* OK. For now, we presume we have a valid client. We now create the
+          client structure, even though we cannot fill it completely yet. */
+       if (!(data = kmalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit;
+       }
+       memset(data, 0, sizeof(struct pca9539_data));
+
+       new_client = &data->client;
+       i2c_set_clientdata(new_client, data);
+       new_client->addr = address;
+       new_client->adapter = adapter;
+       new_client->driver = &pca9539_driver;
+       new_client->flags = 0;
+
+       /* Detection: the pca9539 only has 8 registers (0-7).
+          A read of 7 should succeed, but a read of 8 should fail. */
+       if ((i2c_smbus_read_byte_data(new_client, 7) < 0) ||
+           (i2c_smbus_read_byte_data(new_client, 8) >= 0))
+               goto exit_kfree;
+
+       strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE);
+
+       /* Tell the I2C layer a new client has arrived */
+       if ((err = i2c_attach_client(new_client)))
+               goto exit_kfree;
+
+       /* Register sysfs hooks (don't care about failure) */
+       sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group);
+
+       return 0;
+
+exit_kfree:
+       kfree(data);
+exit:
+       return err;
+}
+
+static int pca9539_detach_client(struct i2c_client *client)
+{
+       int err;
+
+       if ((err = i2c_detach_client(client))) {
+               dev_err(&client->dev, "Client deregistration failed.\n");
+               return err;
+       }
+
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static int __init pca9539_init(void)
+{
+       return i2c_add_driver(&pca9539_driver);
+}
+
+static void __exit pca9539_exit(void)
+{
+       i2c_del_driver(&pca9539_driver);
+}
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("PCA9539 driver");
+MODULE_LICENSE("GPL");
+
+module_init(pca9539_init);
+module_exit(pca9539_exit);
+
index 4956e9effd75ca93551da5cc388e7548f93b53f3..cfcf646540804c11780bb4d6503f74f075a4635c 100644 (file)
@@ -57,7 +57,7 @@ SENSORS_INSMOD_2(pcf8574, pcf8574a);
 struct pcf8574_data {
        struct i2c_client client;
 
-       u8 read, write;                 /* Register values */
+       u8 write;                       /* Remember last written value */
 };
 
 static int pcf8574_attach_adapter(struct i2c_adapter *adapter);
@@ -79,9 +79,7 @@ static struct i2c_driver pcf8574_driver = {
 static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct i2c_client *client = to_i2c_client(dev);
-       struct pcf8574_data *data = i2c_get_clientdata(client);
-       data->read = i2c_smbus_read_byte(client); 
-       return sprintf(buf, "%u\n", data->read);
+       return sprintf(buf, "%u\n", i2c_smbus_read_byte(client));
 }
 
 static DEVICE_ATTR(read, S_IRUGO, show_read, NULL);
index 5a9deddb626b318bfd9a9dfd46708961fff480fa..588fc2261a91e5f3695a8c4234ece5c9b364553f 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/string.h>
 #include <linux/rtc.h>         /* get the user-level API */
 #include <linux/init.h>
-#include <linux/init.h>
 
 #include "rtc8564.h"
 
@@ -66,11 +65,8 @@ static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_addr,
-       .normal_i2c_range       = ignore,
        .probe                  = ignore,
-       .probe_range            = ignore,
        .ignore                 = ignore,
-       .ignore_range           = ignore,
        .force                  = ignore,
 };
 
index c6650727a27de66a0a3ae9a11e9036ba82d07e3f..6bbfc8fb4f13247d61cedb2124a74b5df4589620 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
 #include <asm/io.h>
 
 
index 13d6d4a8bc7d0e906d09a2a20468dce111d1e457..897117a7213f0624a04e55deaaf46de38aaab88e 100644 (file)
@@ -372,14 +372,16 @@ static int smsc47m1_find(int *address)
         * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
         * 0x5F) and LPC47B27x (device id 0x51) have fan control.
         * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
-        * can do much more besides (device id 0x60, unsupported).
+        * can do much more besides (device id 0x60).
         */
        if (val == 0x51)
-               printk(KERN_INFO "smsc47m1: Found SMSC47B27x\n");
+               printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
        else if (val == 0x59)
-               printk(KERN_INFO "smsc47m1: Found SMSC47M10x/SMSC47M13x\n");
+               printk(KERN_INFO "smsc47m1: Found SMSC LPC47M10x/LPC47M13x\n");
        else if (val == 0x5F)
-               printk(KERN_INFO "smsc47m1: Found SMSC47M14x\n");
+               printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
+       else if (val == 0x60)
+               printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
        else {
                superio_exit();
                return -ENODEV;
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
new file mode 100644 (file)
index 0000000..c0ac01b
--- /dev/null
@@ -0,0 +1,1072 @@
+/*
+ * tps65010 - driver for tps6501x power management chips
+ *
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004-2005 David Brownell
+ *
+ * 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.
+ */
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/suspend.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+
+/*-------------------------------------------------------------------------*/
+
+#define        DRIVER_VERSION  "2 May 2005"
+#define        DRIVER_NAME     (tps65010_driver.name)
+
+MODULE_DESCRIPTION("TPS6501x Power Management Driver");
+MODULE_LICENSE("GPL");
+
+/* only two addresses possible */
+#define        TPS_BASE        0x48
+static unsigned short normal_i2c[] = {
+       TPS_BASE,
+       I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver tps65010_driver;
+
+/*-------------------------------------------------------------------------*/
+
+/* This driver handles a family of multipurpose chips, which incorporate
+ * voltage regulators, lithium ion/polymer battery charging, GPIOs, LEDs,
+ * and other features often needed in portable devices like cell phones
+ * or digital cameras.
+ *
+ * The tps65011 and tps65013 have different voltage settings compared
+ * to tps65010 and tps65012.  The tps65013 has a NO_CHG status/irq.
+ * All except tps65010 have "wait" mode, possibly defaulted so that
+ * battery-insert != device-on.
+ *
+ * We could distinguish between some models by checking VDCDC1.UVLO or
+ * other registers, unless they've been changed already after powerup
+ * as part of board setup by a bootloader.
+ */
+enum tps_model {
+       TPS_UNKNOWN = 0,
+       TPS65010,
+       TPS65011,
+       TPS65012,
+       TPS65013,
+};
+
+struct tps65010 {
+       struct i2c_client       client;
+       struct semaphore        lock;
+       int                     irq;
+       struct work_struct      work;
+       struct dentry           *file;
+       unsigned                charging:1;
+       unsigned                por:1;
+       unsigned                model:8;
+       u16                     vbus;
+       unsigned long           flags;
+#define        FLAG_VBUS_CHANGED       0
+#define        FLAG_IRQ_ENABLE         1
+
+       /* copies of last register state */
+       u8                      chgstatus, regstatus, chgconf;
+       u8                      nmask1, nmask2;
+
+       /* plus four GPIOs, probably used to switch power */
+};
+
+#define        POWER_POLL_DELAY        msecs_to_jiffies(800)
+
+/*-------------------------------------------------------------------------*/
+
+#if    defined(DEBUG) || defined(CONFIG_DEBUG_FS)
+
+static void dbg_chgstat(char *buf, size_t len, u8 chgstatus)
+{
+       snprintf(buf, len, "%02x%s%s%s%s%s%s%s%s\n",
+               chgstatus,
+               (chgstatus & TPS_CHG_USB) ? " USB" : "",
+               (chgstatus & TPS_CHG_AC) ? " AC" : "",
+               (chgstatus & TPS_CHG_THERM) ? " therm" : "",
+               (chgstatus & TPS_CHG_TERM) ? " done" :
+                       ((chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+                               ? " (charging)" : ""),
+               (chgstatus & TPS_CHG_TAPER_TMO) ? " taper_tmo" : "",
+               (chgstatus & TPS_CHG_CHG_TMO) ? " charge_tmo" : "",
+               (chgstatus & TPS_CHG_PRECHG_TMO) ? " prechg_tmo" : "",
+               (chgstatus & TPS_CHG_TEMP_ERR) ? " temp_err" : "");
+}
+
+static void dbg_regstat(char *buf, size_t len, u8 regstatus)
+{
+       snprintf(buf, len, "%02x %s%s%s%s%s%s%s%s\n",
+               regstatus,
+               (regstatus & TPS_REG_ONOFF) ? "off" : "(on)",
+               (regstatus & TPS_REG_COVER) ? " uncover" : "",
+               (regstatus & TPS_REG_UVLO) ? " UVLO" : "",
+               (regstatus & TPS_REG_NO_CHG) ? " NO_CHG" : "",
+               (regstatus & TPS_REG_PG_LD02) ? " ld01_bad" : "",
+               (regstatus & TPS_REG_PG_LD01) ? " ld01_bad" : "",
+               (regstatus & TPS_REG_PG_MAIN) ? " main_bad" : "",
+               (regstatus & TPS_REG_PG_CORE) ? " core_bad" : "");
+}
+
+static void dbg_chgconf(int por, char *buf, size_t len, u8 chgconfig)
+{
+       char *hibit;
+
+       if (por)
+               hibit = (chgconfig & TPS_CHARGE_POR)
+                               ? "POR=69ms" : "POR=1sec";
+       else
+               hibit = (chgconfig & TPS65013_AUA) ? "AUA" : "";
+
+       snprintf(buf, len, "%02x %s%s%s AC=%d%% USB=%dmA %sCharge\n",
+               chgconfig, hibit,
+               (chgconfig & TPS_CHARGE_RESET) ? " reset" : "",
+               (chgconfig & TPS_CHARGE_FAST) ? " fast" : "",
+               ({int p; switch ((chgconfig >> 3) & 3) {
+               case 3:         p = 100; break;
+               case 2:         p = 75; break;
+               case 1:         p = 50; break;
+               default:        p = 25; break;
+               }; p; }),
+               (chgconfig & TPS_VBUS_CHARGING)
+                       ? ((chgconfig & TPS_VBUS_500MA) ? 500 : 100)
+                       : 0,
+               (chgconfig & TPS_CHARGE_ENABLE) ? "" : "No");
+}
+
+#endif
+
+#ifdef DEBUG
+
+static void show_chgstatus(const char *label, u8 chgstatus)
+{
+       char buf [100];
+
+       dbg_chgstat(buf, sizeof buf, chgstatus);
+       pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+static void show_regstatus(const char *label, u8 regstatus)
+{
+       char buf [100];
+
+       dbg_regstat(buf, sizeof buf, regstatus);
+       pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+static void show_chgconfig(int por, const char *label, u8 chgconfig)
+{
+       char buf [100];
+
+       dbg_chgconf(por, buf, sizeof buf, chgconfig);
+       pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+#else
+
+static inline void show_chgstatus(const char *label, u8 chgstatus) { }
+static inline void show_regstatus(const char *label, u8 chgstatus) { }
+static inline void show_chgconfig(int por, const char *label, u8 chgconfig) { }
+
+#endif
+
+#ifdef CONFIG_DEBUG_FS
+
+static int dbg_show(struct seq_file *s, void *_)
+{
+       struct tps65010 *tps = s->private;
+       u8              value, v2;
+       unsigned        i;
+       char            buf[100];
+       const char      *chip;
+
+       switch (tps->model) {
+       case TPS65010:  chip = "tps65010"; break;
+       case TPS65011:  chip = "tps65011"; break;
+       case TPS65012:  chip = "tps65012"; break;
+       case TPS65013:  chip = "tps65013"; break;
+       default:        chip = NULL; break;
+       }
+       seq_printf(s, "driver  %s\nversion %s\nchip    %s\n\n",
+                       DRIVER_NAME, DRIVER_VERSION, chip);
+
+       down(&tps->lock);
+
+       /* FIXME how can we tell whether a battery is present?
+        * likely involves a charge gauging chip (like BQ26501).
+        */
+
+       seq_printf(s, "%scharging\n\n", tps->charging ? "" : "(not) ");
+
+
+       /* registers for monitoring battery charging and status; note
+        * that reading chgstat and regstat may ack IRQs...
+        */
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+       dbg_chgconf(tps->por, buf, sizeof buf, value);
+       seq_printf(s, "chgconfig %s", buf);
+
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS);
+       dbg_chgstat(buf, sizeof buf, value);
+       seq_printf(s, "chgstat   %s", buf);
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_MASK1);
+       dbg_chgstat(buf, sizeof buf, value);
+       seq_printf(s, "mask1     %s", buf);
+       /* ignore ackint1 */
+
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS);
+       dbg_regstat(buf, sizeof buf, value);
+       seq_printf(s, "regstat   %s", buf);
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_MASK2);
+       dbg_regstat(buf, sizeof buf, value);
+       seq_printf(s, "mask2     %s\n", buf);
+       /* ignore ackint2 */
+
+       (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
+
+
+       /* VMAIN voltage, enable lowpower, etc */
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC1);
+       seq_printf(s, "vdcdc1    %02x\n", value);
+
+       /* VCORE voltage, vibrator on/off */
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC2);
+       seq_printf(s, "vdcdc2    %02x\n", value);
+
+       /* both LD0s, and their lowpower behavior */
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_VREGS1);
+       seq_printf(s, "vregs1    %02x\n\n", value);
+
+
+       /* LEDs and GPIOs */
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_LED1_ON);
+       v2 = i2c_smbus_read_byte_data(&tps->client, TPS_LED1_PER);
+       seq_printf(s, "led1 %s, on=%02x, per=%02x, %d/%d msec\n",
+               (value & 0x80)
+                       ? ((v2 & 0x80) ? "on" : "off")
+                       : ((v2 & 0x80) ? "blink" : "(nPG)"),
+               value, v2,
+               (value & 0x7f) * 10, (v2 & 0x7f) * 100);
+
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_LED2_ON);
+       v2 = i2c_smbus_read_byte_data(&tps->client, TPS_LED2_PER);
+       seq_printf(s, "led2 %s, on=%02x, per=%02x, %d/%d msec\n",
+               (value & 0x80)
+                       ? ((v2 & 0x80) ? "on" : "off")
+                       : ((v2 & 0x80) ? "blink" : "off"),
+               value, v2,
+               (value & 0x7f) * 10, (v2 & 0x7f) * 100);
+
+       value = i2c_smbus_read_byte_data(&tps->client, TPS_DEFGPIO);
+       v2 = i2c_smbus_read_byte_data(&tps->client, TPS_MASK3);
+       seq_printf(s, "defgpio %02x mask3 %02x\n", value, v2);
+
+       for (i = 0; i < 4; i++) {
+               if (value & (1 << (4 +i)))
+                       seq_printf(s, "  gpio%d-out %s\n", i + 1,
+                               (value & (1 << i)) ? "low" : "hi ");
+               else
+                       seq_printf(s, "  gpio%d-in  %s %s %s\n", i + 1,
+                               (value & (1 << i)) ? "hi " : "low",
+                               (v2 & (1 << i)) ? "no-irq" : "irq",
+                               (v2 & (1 << (4 + i))) ? "rising" : "falling");
+       }
+
+       up(&tps->lock);
+       return 0;
+}
+
+static int dbg_tps_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dbg_show, inode->u.generic_ip);
+}
+
+static struct file_operations debug_fops = {
+       .open           = dbg_tps_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+#define        DEBUG_FOPS      &debug_fops
+
+#else
+#define        DEBUG_FOPS      NULL
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* handle IRQS in a task context, so we can use I2C calls */
+static void tps65010_interrupt(struct tps65010 *tps)
+{
+       u8 tmp = 0, mask, poll;
+
+       /* IRQs won't trigger irqs for certain events, but we can get
+        * others by polling (normally, with external power applied).
+        */
+       poll = 0;
+
+       /* regstatus irqs */
+       if (tps->nmask2) {
+               tmp = i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS);
+               mask = tmp ^ tps->regstatus;
+               tps->regstatus = tmp;
+               mask &= tps->nmask2;
+       } else
+               mask = 0;
+       if (mask) {
+               tps->regstatus =  tmp;
+               /* may need to shut something down ... */
+
+               /* "off" usually means deep sleep */
+               if (tmp & TPS_REG_ONOFF) {
+                       pr_info("%s: power off button\n", DRIVER_NAME);
+#if 0
+                       /* REVISIT:  this might need its own workqueue
+                        * plus tweaks including deadlock avoidance ...
+                        */
+                       software_suspend();
+#endif
+                       poll = 1;
+               }
+       }
+
+       /* chgstatus irqs */
+       if (tps->nmask1) {
+               tmp = i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS);
+               mask = tmp ^ tps->chgstatus;
+               tps->chgstatus = tmp;
+               mask &= tps->nmask1;
+       } else
+               mask = 0;
+       if (mask) {
+               unsigned        charging = 0;
+
+               show_chgstatus("chg/irq", tmp);
+               if (tmp & (TPS_CHG_USB|TPS_CHG_AC))
+                       show_chgconfig(tps->por, "conf", tps->chgconf);
+
+               /* Unless it was turned off or disabled, we charge any
+                * battery whenever there's power available for it
+                * and the charger hasn't been disabled.
+                */
+               if (!(tps->chgstatus & ~(TPS_CHG_USB|TPS_CHG_AC))
+                               && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+                               && (tps->chgconf & TPS_CHARGE_ENABLE)
+                               ) {
+                       if (tps->chgstatus & TPS_CHG_USB) {
+                               /* VBUS options are readonly until reconnect */
+                               if (mask & TPS_CHG_USB)
+                                       set_bit(FLAG_VBUS_CHANGED, &tps->flags);
+                               charging = 1;
+                       } else if (tps->chgstatus & TPS_CHG_AC)
+                               charging = 1;
+               }
+               if (charging != tps->charging) {
+                       tps->charging = charging;
+                       pr_info("%s: battery %scharging\n",
+                               DRIVER_NAME, charging ? "" :
+                               ((tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+                                       ? "NOT " : "dis"));
+               }
+       }
+
+       /* always poll to detect (a) power removal, without tps65013
+        * NO_CHG IRQ; or (b) restart of charging after stop.
+        */
+       if ((tps->model != TPS65013 || !tps->charging)
+                       && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)))
+               poll = 1;
+       if (poll)
+               (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
+
+       /* also potentially gpio-in rise or fall */
+}
+
+/* handle IRQs and polling using keventd for now */
+static void tps65010_work(void *_tps)
+{
+       struct tps65010         *tps = _tps;
+
+       down(&tps->lock);
+
+       tps65010_interrupt(tps);
+
+       if (test_and_clear_bit(FLAG_VBUS_CHANGED, &tps->flags)) {
+               int     status;
+               u8      chgconfig, tmp;
+
+               chgconfig = i2c_smbus_read_byte_data(&tps->client,
+                                       TPS_CHGCONFIG);
+               chgconfig &= ~(TPS_VBUS_500MA | TPS_VBUS_CHARGING);
+               if (tps->vbus == 500)
+                       chgconfig |= TPS_VBUS_500MA | TPS_VBUS_CHARGING;
+               else if (tps->vbus >= 100)
+                       chgconfig |= TPS_VBUS_CHARGING;
+
+               status = i2c_smbus_write_byte_data(&tps->client,
+                               TPS_CHGCONFIG, chgconfig);
+
+               /* vbus update fails unless VBUS is connected! */
+               tmp = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+               tps->chgconf = tmp;
+               show_chgconfig(tps->por, "update vbus", tmp);
+       }
+
+       if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags))
+               enable_irq(tps->irq);
+
+       up(&tps->lock);
+}
+
+static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs)
+{
+       struct tps65010         *tps = _tps;
+
+       disable_irq_nosync(irq);
+       set_bit(FLAG_IRQ_ENABLE, &tps->flags);
+       (void) schedule_work(&tps->work);
+       return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct tps65010 *the_tps;
+
+static int __exit tps65010_detach_client(struct i2c_client *client)
+{
+       struct tps65010         *tps;
+
+       tps = container_of(client, struct tps65010, client);
+#ifdef CONFIG_ARM
+       if (machine_is_omap_h2())
+               omap_free_gpio(58);
+       if (machine_is_omap_osk())
+               omap_free_gpio(OMAP_MPUIO(1));
+#endif
+       free_irq(tps->irq, tps);
+       debugfs_remove(tps->file);
+       if (i2c_detach_client(client) == 0)
+               kfree(tps);
+       the_tps = 0;
+       return 0;
+}
+
+static int tps65010_noscan(struct i2c_adapter *bus)
+{
+       /* pure paranoia, in case someone adds another i2c bus
+        * after our init section's gone...
+        */
+       return -ENODEV;
+}
+
+/* no error returns, they'd just make bus scanning stop */
+static int __init
+tps65010_probe(struct i2c_adapter *bus, int address, int kind)
+{
+       struct tps65010         *tps;
+       int                     status;
+
+       if (the_tps) {
+               dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME);
+               return 0;
+       }
+
+       tps = kmalloc(sizeof *tps, GFP_KERNEL);
+       if (!tps)
+               return 0;
+
+       memset(tps, 0, sizeof *tps);
+       init_MUTEX(&tps->lock);
+       INIT_WORK(&tps->work, tps65010_work, tps);
+       tps->irq = -1;
+       tps->client.addr = address;
+       i2c_set_clientdata(&tps->client, tps);
+       tps->client.adapter = bus;
+       tps->client.driver = &tps65010_driver;
+       strlcpy(tps->client.name, DRIVER_NAME, I2C_NAME_SIZE);
+
+       status = i2c_attach_client(&tps->client);
+       if (status < 0) {
+               dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
+                               DRIVER_NAME, address, status);
+fail1:
+               kfree(tps);
+               return 0;
+       }
+
+#ifdef CONFIG_ARM
+       if (machine_is_omap_h2()) {
+               tps->model = TPS65010;
+               omap_cfg_reg(W4_GPIO58);
+               tps->irq = OMAP_GPIO_IRQ(58);
+               omap_request_gpio(58);
+               omap_set_gpio_direction(58, 1);
+               omap_set_gpio_edge_ctrl(58, OMAP_GPIO_FALLING_EDGE);
+       }
+       if (machine_is_omap_osk()) {
+               tps->model = TPS65010;
+               // omap_cfg_reg(U19_1610_MPUIO1);
+               tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1));
+               omap_request_gpio(OMAP_MPUIO(1));
+               omap_set_gpio_direction(OMAP_MPUIO(1), 1);
+               omap_set_gpio_edge_ctrl(OMAP_MPUIO(1), OMAP_GPIO_FALLING_EDGE);
+       }
+       if (machine_is_omap_h3()) {
+               tps->model = TPS65013;
+
+               // FIXME set up this board's IRQ ...
+       }
+#else
+#define set_irq_type(num,trigger)      do{}while(0)
+#endif
+
+       if (tps->irq > 0) {
+               set_irq_type(tps->irq, IRQT_LOW);
+               status = request_irq(tps->irq, tps65010_irq,
+                       SA_SAMPLE_RANDOM, DRIVER_NAME, tps);
+               if (status < 0) {
+                       dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n",
+                                       tps->irq, status);
+                       i2c_detach_client(&tps->client);
+                       goto fail1;
+               }
+#ifdef CONFIG_ARM
+               /* annoying race here, ideally we'd have an option
+                * to claim the irq now and enable it later.
+                */
+               disable_irq(tps->irq);
+               set_bit(FLAG_IRQ_ENABLE, &tps->flags);
+#endif
+       } else
+               printk(KERN_WARNING "%s: IRQ not configured!\n",
+                               DRIVER_NAME);
+
+
+       switch (tps->model) {
+       case TPS65010:
+       case TPS65012:
+               tps->por = 1;
+               break;
+       case TPS_UNKNOWN:
+               printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME);
+               break;
+       /* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
+       }
+       tps->chgconf = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+       show_chgconfig(tps->por, "conf/init", tps->chgconf);
+
+       show_chgstatus("chg/init",
+               i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS));
+       show_regstatus("reg/init",
+               i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS));
+
+       pr_debug("%s: vdcdc1 0x%02x, vdcdc2 %02x, vregs1 %02x\n", DRIVER_NAME,
+               i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC1),
+               i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC2),
+               i2c_smbus_read_byte_data(&tps->client, TPS_VREGS1));
+       pr_debug("%s: defgpio 0x%02x, mask3 0x%02x\n", DRIVER_NAME,
+               i2c_smbus_read_byte_data(&tps->client, TPS_DEFGPIO),
+               i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
+
+       tps65010_driver.attach_adapter = tps65010_noscan;
+       the_tps = tps;
+
+#if    defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
+       /* USB hosts can't draw VBUS.  OTG devices could, later
+        * when OTG infrastructure enables it.  USB peripherals
+        * could be relying on VBUS while booting, though.
+        */
+       tps->vbus = 100;
+#endif
+
+       /* unmask the "interesting" irqs, then poll once to
+        * kickstart monitoring, initialize shadowed status
+        * registers, and maybe disable VBUS draw.
+        */
+       tps->nmask1 = ~0;
+       (void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK1, ~tps->nmask1);
+
+       tps->nmask2 = TPS_REG_ONOFF;
+       if (tps->model == TPS65013)
+               tps->nmask2 |= TPS_REG_NO_CHG;
+       (void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK2, ~tps->nmask2);
+
+       (void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK3, 0x0f
+               | i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
+
+       tps65010_work(tps);
+
+       tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
+                               tps, DEBUG_FOPS);
+       return 0;
+}
+
+static int __init tps65010_scan_bus(struct i2c_adapter *bus)
+{
+       if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EINVAL;
+       return i2c_probe(bus, &addr_data, tps65010_probe);
+}
+
+static struct i2c_driver tps65010_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "tps65010",
+       .id             = 888,          /* FIXME assign "official" value */
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = tps65010_scan_bus,
+       .detach_client  = __exit_p(tps65010_detach_client),
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Draw from VBUS:
+ *   0 mA -- DON'T DRAW (might supply power instead)
+ * 100 mA -- usb unit load (slowest charge rate)
+ * 500 mA -- usb high power (fast battery charge)
+ */
+int tps65010_set_vbus_draw(unsigned mA)
+{
+       unsigned long   flags;
+
+       if (!the_tps)
+               return -ENODEV;
+
+       /* assumes non-SMP */
+       local_irq_save(flags);
+       if (mA >= 500)
+               mA = 500;
+       else if (mA >= 100)
+               mA = 100;
+       else
+               mA = 0;
+       the_tps->vbus = mA;
+       if ((the_tps->chgstatus & TPS_CHG_USB)
+                       && test_and_set_bit(
+                               FLAG_VBUS_CHANGED, &the_tps->flags)) {
+               /* gadget drivers call this in_irq() */
+               (void) schedule_work(&the_tps->work);
+       }
+       local_irq_restore(flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(tps65010_set_vbus_draw);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_gpio_out_value parameter:
+ * gpio:  GPIO1, GPIO2, GPIO3 or GPIO4
+ * value: LOW or HIGH
+ */
+int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
+{
+       int      status;
+       unsigned defgpio;
+
+       if (!the_tps)
+               return -ENODEV;
+       if ((gpio < GPIO1) || (gpio > GPIO4))
+               return -EINVAL;
+
+       down(&the_tps->lock);
+
+       defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO);
+
+       /* Configure GPIO for output */
+       defgpio |= 1 << (gpio + 3);
+
+       /* Writing 1 forces a logic 0 on that GPIO and vice versa */
+       switch (value) {
+       case LOW:
+               defgpio |= 1 << (gpio - 1);    /* set GPIO low by writing 1 */
+               break;
+       /* case HIGH: */
+       default:
+               defgpio &= ~(1 << (gpio - 1)); /* set GPIO high by writing 0 */
+               break;
+       }
+
+       status = i2c_smbus_write_byte_data(&the_tps->client,
+               TPS_DEFGPIO, defgpio);
+
+       pr_debug("%s: gpio%dout = %s, defgpio 0x%02x\n", DRIVER_NAME,
+               gpio, value ? "high" : "low",
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO));
+
+       up(&the_tps->lock);
+       return status;
+}
+EXPORT_SYMBOL(tps65010_set_gpio_out_value);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_led parameter:
+ * led:  LED1 or LED2
+ * mode: ON, OFF or BLINK
+ */
+int tps65010_set_led(unsigned led, unsigned mode)
+{
+       int      status;
+       unsigned led_on, led_per, offs;
+
+       if (!the_tps)
+               return -ENODEV;
+
+       if(led == LED1)
+               offs = 0;
+       else {
+               offs = 2;
+               led = LED2;
+       }
+
+       down(&the_tps->lock);
+
+       dev_dbg (&the_tps->client.dev, "led%i_on   0x%02x\n", led,
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_ON + offs));
+
+       dev_dbg (&the_tps->client.dev, "led%i_per  0x%02x\n", led,
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs));
+
+       switch (mode) {
+       case OFF:
+               led_on  = 1 << 7;
+               led_per = 0 << 7;
+               break;
+       case ON:
+               led_on  = 1 << 7;
+               led_per = 1 << 7;
+               break;
+       case BLINK:
+               led_on  = 0x30 | (0 << 7);
+               led_per = 0x08 | (1 << 7);
+               break;
+       default:
+               printk(KERN_ERR "%s: Wrong mode parameter for tps65010_set_led()\n",
+                      DRIVER_NAME);
+               up(&the_tps->lock);
+               return -EINVAL;
+       }
+
+       status = i2c_smbus_write_byte_data(&the_tps->client,
+                       TPS_LED1_ON + offs, led_on);
+
+       if (status != 0) {
+               printk(KERN_ERR "%s: Failed to write led%i_on register\n",
+                      DRIVER_NAME, led);
+               up(&the_tps->lock);
+               return status;
+       }
+
+       dev_dbg (&the_tps->client.dev, "led%i_on   0x%02x\n", led,
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_ON + offs));
+
+       status = i2c_smbus_write_byte_data(&the_tps->client,
+                       TPS_LED1_PER + offs, led_per);
+
+       if (status != 0) {
+               printk(KERN_ERR "%s: Failed to write led%i_per register\n",
+                      DRIVER_NAME, led);
+               up(&the_tps->lock);
+               return status;
+       }
+
+       dev_dbg (&the_tps->client.dev, "led%i_per  0x%02x\n", led,
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs));
+
+       up(&the_tps->lock);
+
+       return status;
+}
+EXPORT_SYMBOL(tps65010_set_led);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_vib parameter:
+ * value: ON or OFF
+ */
+int tps65010_set_vib(unsigned value)
+{
+       int      status;
+       unsigned vdcdc2;
+
+       if (!the_tps)
+               return -ENODEV;
+
+       down(&the_tps->lock);
+
+       vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2);
+       vdcdc2 &= ~(1 << 1);
+       if (value)
+               vdcdc2 |= (1 << 1);
+       status = i2c_smbus_write_byte_data(&the_tps->client,
+               TPS_VDCDC2, vdcdc2);
+
+       pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off");
+
+       up(&the_tps->lock);
+       return status;
+}
+EXPORT_SYMBOL(tps65010_set_vib);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+int tps65010_set_low_pwr(unsigned mode)
+{
+       int      status;
+       unsigned vdcdc1;
+
+       if (!the_tps)
+               return -ENODEV;
+
+       down(&the_tps->lock);
+
+       pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME,
+               mode ? "enable" : "disable",
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+       vdcdc1 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1);
+
+       switch (mode) {
+       case OFF:
+               vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
+               break;
+       /* case ON: */
+       default:
+               vdcdc1 |= TPS_ENABLE_LP;  /* enable ENABLE_LP bit */
+               break;
+       }
+
+       status = i2c_smbus_write_byte_data(&the_tps->client,
+                       TPS_VDCDC1, vdcdc1);
+
+       if (status != 0)
+               printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
+                      DRIVER_NAME);
+       else
+               pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
+                       i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+       up(&the_tps->lock);
+
+       return status;
+}
+EXPORT_SYMBOL(tps65010_set_low_pwr);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_config_vregs1 parameter:
+ * value to be written to VREGS1 register
+ * Note: The complete register is written, set all bits you need
+ */
+int tps65010_config_vregs1(unsigned value)
+{
+       int      status;
+
+       if (!the_tps)
+               return -ENODEV;
+
+       down(&the_tps->lock);
+
+       pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
+                       i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
+
+       status = i2c_smbus_write_byte_data(&the_tps->client,
+                       TPS_VREGS1, value);
+
+       if (status != 0)
+               printk(KERN_ERR "%s: Failed to write vregs1 register\n",
+                       DRIVER_NAME);
+       else
+               pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
+                       i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
+
+       up(&the_tps->lock);
+
+       return status;
+}
+EXPORT_SYMBOL(tps65010_config_vregs1);
+
+/*-------------------------------------------------------------------------*/
+/* tps65013_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+
+/* FIXME: Assumes AC or USB power is present. Setting AUA bit is not
+       required if power supply is through a battery */
+
+int tps65013_set_low_pwr(unsigned mode)
+{
+       int      status;
+       unsigned vdcdc1, chgconfig;
+
+       if (!the_tps || the_tps->por)
+               return -ENODEV;
+
+       down(&the_tps->lock);
+
+       pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n",
+               DRIVER_NAME,
+               mode ? "enable" : "disable",
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG),
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+       chgconfig = i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG);
+       vdcdc1 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1);
+
+       switch (mode) {
+       case OFF:
+               chgconfig &= ~TPS65013_AUA; /* disable AUA bit */
+               vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
+               break;
+       /* case ON: */
+       default:
+               chgconfig |= TPS65013_AUA;  /* enable AUA bit */
+               vdcdc1 |= TPS_ENABLE_LP;  /* enable ENABLE_LP bit */
+               break;
+       }
+
+       status = i2c_smbus_write_byte_data(&the_tps->client,
+                       TPS_CHGCONFIG, chgconfig);
+       if (status != 0) {
+               printk(KERN_ERR "%s: Failed to write chconfig register\n",
+        DRIVER_NAME);
+               up(&the_tps->lock);
+               return status;
+       }
+
+       chgconfig = i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG);
+       the_tps->chgconf = chgconfig;
+       show_chgconfig(0, "chgconf", chgconfig);
+
+       status = i2c_smbus_write_byte_data(&the_tps->client,
+                       TPS_VDCDC1, vdcdc1);
+
+       if (status != 0)
+               printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
+        DRIVER_NAME);
+       else
+               pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
+                       i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+       up(&the_tps->lock);
+
+       return status;
+}
+EXPORT_SYMBOL(tps65013_set_low_pwr);
+
+/*-------------------------------------------------------------------------*/
+
+static int __init tps_init(void)
+{
+       u32     tries = 3;
+       int     status = -ENODEV;
+
+       printk(KERN_INFO "%s: version %s\n", DRIVER_NAME, DRIVER_VERSION);
+
+       /* some boards have startup glitches */
+       while (tries--) {
+               status = i2c_add_driver(&tps65010_driver);
+               if (the_tps)
+                       break;
+               i2c_del_driver(&tps65010_driver);
+               if (!tries) {
+                       printk(KERN_ERR "%s: no chip?\n", DRIVER_NAME);
+                       return -ENODEV;
+               }
+               pr_debug("%s: re-probe ...\n", DRIVER_NAME);
+               msleep(10);
+       }
+
+#if defined(CONFIG_ARM)
+       if (machine_is_omap_osk()) {
+
+               // FIXME: More should be placed in the initialization code
+               //        of the submodules (DSP, ethernet, power management,
+               //        board-osk.c). Careful: I2C is initialized "late".
+
+               /* Let LED1 (D9) blink */
+               tps65010_set_led(LED1, BLINK);
+
+               /* Disable LED 2 (D2) */
+               tps65010_set_led(LED2, OFF);
+
+               /* Set GPIO 1 HIGH to disable VBUS power supply;
+                * OHCI driver powers it up/down as needed.
+                */
+               tps65010_set_gpio_out_value(GPIO1, HIGH);
+
+               /* Set GPIO 2 low to turn on LED D3 */
+               tps65010_set_gpio_out_value(GPIO2, HIGH);
+
+               /* Set GPIO 3 low to take ethernet out of reset */
+               tps65010_set_gpio_out_value(GPIO3, LOW);
+
+               /* gpio4 for VDD_DSP */
+
+               /* Enable LOW_PWR */
+               tps65010_set_low_pwr(ON);
+
+               /* Switch VLDO2 to 3.0V for AIC23 */
+               tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V | TPS_LDO1_ENABLE);
+
+       } else if (machine_is_omap_h2()) {
+               /* gpio3 for SD, gpio4 for VDD_DSP */
+
+               /* Enable LOW_PWR */
+               tps65010_set_low_pwr(ON);
+       } else if (machine_is_omap_h3()) {
+               /* gpio4 for SD, gpio3 for VDD_DSP */
+#ifdef CONFIG_PM
+               /* Enable LOW_PWR */
+               tps65013_set_low_pwr(ON);
+#endif
+       }
+#endif
+
+       return status;
+}
+/* NOTE:  this MUST be initialized before the other parts of the system
+ * that rely on it ... but after the i2c bus on which this relies.
+ * That is, much earlier than on PC-type systems, which don't often use
+ * I2C as a core system bus.
+ */
+subsys_initcall(tps_init);
+
+static void __exit tps_exit(void)
+{
+       i2c_del_driver(&tps65010_driver);
+}
+module_exit(tps_exit);
+
index fefc24a9251ade9926f93bdc3f6e8c25584a6229..137d9b7cacd44561023593ab80ab23db78ae66c9 100644 (file)
@@ -1,12 +1,12 @@
 /*
     via686a.c - Part of lm_sensors, Linux kernel modules
                 for hardware monitoring
-                
+
     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
                         Kyösti Mälkki <kmalkki@cc.hut.fi>,
                        Mark Studebaker <mdsxyz123@yahoo.com>,
                        and Bob Dougherty <bobd@stanford.edu>
-    (Some conversion-factor data were contributed by Jonathan Teh Soon Yew 
+    (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
     <j.teh@iname.com> and Alex van Kaam <darkside@chello.nl>.)
 
     This program is free software; you can redistribute it and/or modify
     Warning - only supports a single device.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/delay.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
@@ -66,49 +64,46 @@ SENSORS_INSMOD_1(via686a);
 /* Many VIA686A constants specified below */
 
 /* Length of ISA address segment */
-#define VIA686A_EXTENT 0x80
-#define VIA686A_BASE_REG 0x70
-#define VIA686A_ENABLE_REG 0x74
+#define VIA686A_EXTENT         0x80
+#define VIA686A_BASE_REG       0x70
+#define VIA686A_ENABLE_REG     0x74
 
 /* The VIA686A registers */
 /* ins numbered 0-4 */
-#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
-#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
-#define VIA686A_REG_IN(nr)     (0x22 + (nr))
+#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
+#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
+#define VIA686A_REG_IN(nr)     (0x22 + (nr))
 
 /* fans numbered 1-2 */
-#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
-#define VIA686A_REG_FAN(nr)     (0x28 + (nr))
-
-/* the following values are as speced by VIA: */
-static const u8 regtemp[] = { 0x20, 0x21, 0x1f };
-static const u8 regover[] = { 0x39, 0x3d, 0x1d };
-static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
+#define VIA686A_REG_FAN_MIN(nr)        (0x3a + (nr))
+#define VIA686A_REG_FAN(nr)    (0x28 + (nr))
 
 /* temps numbered 1-3 */
-#define VIA686A_REG_TEMP(nr)           (regtemp[nr])
-#define VIA686A_REG_TEMP_OVER(nr)      (regover[nr])
-#define VIA686A_REG_TEMP_HYST(nr)      (reghyst[nr])
-#define VIA686A_REG_TEMP_LOW1  0x4b    // bits 7-6
-#define VIA686A_REG_TEMP_LOW23 0x49    // 2 = bits 5-4, 3 = bits 7-6
-
-#define VIA686A_REG_ALARM1 0x41
-#define VIA686A_REG_ALARM2 0x42
-#define VIA686A_REG_FANDIV 0x47
-#define VIA686A_REG_CONFIG 0x40
-/* The following register sets temp interrupt mode (bits 1-0 for temp1, 
+static const u8 VIA686A_REG_TEMP[]     = { 0x20, 0x21, 0x1f };
+static const u8 VIA686A_REG_TEMP_OVER[]        = { 0x39, 0x3d, 0x1d };
+static const u8 VIA686A_REG_TEMP_HYST[]        = { 0x3a, 0x3e, 0x1e };
+/* bits 7-6 */
+#define VIA686A_REG_TEMP_LOW1  0x4b
+/* 2 = bits 5-4, 3 = bits 7-6 */
+#define VIA686A_REG_TEMP_LOW23 0x49
+
+#define VIA686A_REG_ALARM1     0x41
+#define VIA686A_REG_ALARM2     0x42
+#define VIA686A_REG_FANDIV     0x47
+#define VIA686A_REG_CONFIG     0x40
+/* The following register sets temp interrupt mode (bits 1-0 for temp1,
  3-2 for temp2, 5-4 for temp3).  Modes are:
     00 interrupt stays as long as value is out-of-range
     01 interrupt is cleared once register is read (default)
     10 comparator mode- like 00, but ignores hysteresis
     11 same as 00 */
-#define VIA686A_REG_TEMP_MODE 0x4b
+#define VIA686A_REG_TEMP_MODE          0x4b
 /* We'll just assume that you want to set all 3 simultaneously: */
-#define VIA686A_TEMP_MODE_MASK 0x3F
-#define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
+#define VIA686A_TEMP_MODE_MASK         0x3F
+#define VIA686A_TEMP_MODE_CONTINUOUS   0x00
 
 /* Conversions. Limit checking is only done on the TO_REG
-   variants. 
+   variants.
 
 ********* VOLTAGE CONVERSIONS (Bob Dougherty) ********
  From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
@@ -121,7 +116,7 @@ static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
  That is:
  volts = (25*regVal+133)*factor
  regVal = (volts/factor-133)/25
- (These conversions were contributed by Jonathan Teh Soon Yew 
+ (These conversions were contributed by Jonathan Teh Soon Yew
  <j.teh@iname.com>) */
 static inline u8 IN_TO_REG(long val, int inNum)
 {
@@ -182,55 +177,55 @@ static inline u8 FAN_TO_REG(long rpm, int div)
       else
               return double(temp)*0.924-127.33;
 
- A fifth-order polynomial fits the unofficial data (provided by Alex van 
- Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable 
- numbers on my machine (ie. they agree with what my BIOS tells me).  
+ A fifth-order polynomial fits the unofficial data (provided by Alex van
+ Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable
+ numbers on my machine (ie. they agree with what my BIOS tells me).
  Here's the fifth-order fit to the 8-bit data:
- temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 - 
+ temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
         2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
 
- (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for 
+ (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
  finding my typos in this formula!)
 
- Alas, none of the elegant function-fit solutions will work because we 
- aren't allowed to use floating point in the kernel and doing it with 
- integers doesn't rpovide enough precision.  So we'll do boring old 
- look-up table stuff.  The unofficial data (see below) have effectively 
- 7-bit resolution (they are rounded to the nearest degree).  I'm assuming 
- that the transfer function of the device is monotonic and smooth, so a 
- smooth function fit to the data will allow us to get better precision.  
+ Alas, none of the elegant function-fit solutions will work because we
+ aren't allowed to use floating point in the kernel and doing it with
+ integers doesn't provide enough precision.  So we'll do boring old
+ look-up table stuff.  The unofficial data (see below) have effectively
+ 7-bit resolution (they are rounded to the nearest degree).  I'm assuming
+ that the transfer function of the device is monotonic and smooth, so a
+ smooth function fit to the data will allow us to get better precision.
  I used the 5th-order poly fit described above and solved for
- VIA register values 0-255.  I *10 before rounding, so we get tenth-degree 
- precision.  (I could have done all 1024 values for our 10-bit readings, 
- but the function is very linear in the useful range (0-80 deg C), so 
- we'll just use linear interpolation for 10-bit readings.)  So, tempLUT 
+ VIA register values 0-255.  I *10 before rounding, so we get tenth-degree
+ precision.  (I could have done all 1024 values for our 10-bit readings,
+ but the function is very linear in the useful range (0-80 deg C), so
+ we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
  is the temp at via register values 0-255: */
 static const long tempLUT[] =
-    { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
-           -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
-           -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
-           -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
-           -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
-           -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
-           -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
-           20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
-           88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
-           142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
-           193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
-           245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
-           299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
-           353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
-           409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
-           469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
-           538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
-           621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
-           728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
-           870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
-           1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
-           1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
+{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
+       -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
+       -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
+       -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
+       -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
+       -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
+       -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
+       20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
+       88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
+       142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
+       193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
+       245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
+       299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
+       353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
+       409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
+       469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
+       538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
+       621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
+       728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
+       870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
+       1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
+       1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
 };
 
-/* the original LUT values from Alex van Kaam <darkside@chello.nl> 
+/* the original LUT values from Alex van Kaam <darkside@chello.nl>
    (for via register values 12-240):
 {-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
 -30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
@@ -245,26 +240,26 @@ static const long tempLUT[] =
 
 
  Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
- an extra term for a good fit to these inverse data!) and then 
- solving for each temp value from -50 to 110 (the useable range for 
- this chip).  Here's the fit: 
- viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4 
+ an extra term for a good fit to these inverse data!) and then
+ solving for each temp value from -50 to 110 (the useable range for
+ this chip).  Here's the fit:
+ viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
  - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
  Note that n=161: */
 static const u8 viaLUT[] =
-    { 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
-           23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
-           41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
-           69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
-           103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
-           131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
-           158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
-           182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
-           200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
-           214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
-           225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
-           233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
-           239, 240
+{ 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
+       23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
+       41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
+       69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
+       103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
+       131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
+       158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
+       182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
+       200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+       214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
+       225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
+       233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+       239, 240
 };
 
 /* Converting temps to (8-bit) hyst and over registers
@@ -272,7 +267,7 @@ static const u8 viaLUT[] =
    The +50 is because the temps start at -50 */
 static inline u8 TEMP_TO_REG(long val)
 {
-       return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 : 
+       return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
                      (val < 0 ? val - 500 : val + 500) / 1000 + 50];
 }
 
@@ -291,11 +286,9 @@ static inline long TEMP_FROM_REG10(u16 val)
 
        /* do some linear interpolation */
        return (tempLUT[eightBits] * (4 - twoBits) +
-               tempLUT[eightBits + 1] * twoBits) * 25;
+               tempLUT[eightBits + 1] * twoBits) * 25;
 }
 
-#define ALARMS_FROM_REG(val) (val)
-
 #define DIV_FROM_REG(val) (1 << (val))
 #define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
 
@@ -358,28 +351,28 @@ static ssize_t show_in_max(struct device *dev, char *buf, int nr) {
        return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));
 }
 
-static ssize_t set_in_min(struct device *dev, const char *buf, 
+static ssize_t set_in_min(struct device *dev, const char *buf,
                size_t count, int nr) {
        struct i2c_client *client = to_i2c_client(dev);
        struct via686a_data *data = i2c_get_clientdata(client);
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
        down(&data->update_lock);
-       data->in_min[nr] = IN_TO_REG(val,nr);
-       via686a_write_value(client, VIA686A_REG_IN_MIN(nr), 
+       data->in_min[nr] = IN_TO_REG(val, nr);
+       via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
                        data->in_min[nr]);
        up(&data->update_lock);
        return count;
 }
-static ssize_t set_in_max(struct device *dev, const char *buf, 
+static ssize_t set_in_max(struct device *dev, const char *buf,
                size_t count, int nr) {
        struct i2c_client *client = to_i2c_client(dev);
        struct via686a_data *data = i2c_get_clientdata(client);
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
        down(&data->update_lock);
-       data->in_max[nr] = IN_TO_REG(val,nr);
-       via686a_write_value(client, VIA686A_REG_IN_MAX(nr), 
+       data->in_max[nr] = IN_TO_REG(val, nr);
+       via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
                        data->in_max[nr]);
        up(&data->update_lock);
        return count;
@@ -435,7 +428,7 @@ static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) {
        struct via686a_data *data = via686a_update_device(dev);
        return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
 }
-static ssize_t set_temp_over(struct device *dev, const char *buf, 
+static ssize_t set_temp_over(struct device *dev, const char *buf,
                size_t count, int nr) {
        struct i2c_client *client = to_i2c_client(dev);
        struct via686a_data *data = i2c_get_clientdata(client);
@@ -443,11 +436,12 @@ static ssize_t set_temp_over(struct device *dev, const char *buf,
 
        down(&data->update_lock);
        data->temp_over[nr] = TEMP_TO_REG(val);
-       via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]);
+       via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr],
+                           data->temp_over[nr]);
        up(&data->update_lock);
        return count;
 }
-static ssize_t set_temp_hyst(struct device *dev, const char *buf, 
+static ssize_t set_temp_hyst(struct device *dev, const char *buf,
                size_t count, int nr) {
        struct i2c_client *client = to_i2c_client(dev);
        struct via686a_data *data = i2c_get_clientdata(client);
@@ -455,7 +449,8 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf,
 
        down(&data->update_lock);
        data->temp_hyst[nr] = TEMP_TO_REG(val);
-       via686a_write_value(client, VIA686A_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
+       via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr],
+                           data->temp_hyst[nr]);
        up(&data->update_lock);
        return count;
 }
@@ -488,7 +483,7 @@ static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\
 static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,              \
                show_temp_##offset##_over, set_temp_##offset##_over);   \
 static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR,                 \
-               show_temp_##offset##_hyst, set_temp_##offset##_hyst);   
+               show_temp_##offset##_hyst, set_temp_##offset##_hyst);
 
 show_temp_offset(1);
 show_temp_offset(2);
@@ -497,19 +492,19 @@ show_temp_offset(3);
 /* 2 Fans */
 static ssize_t show_fan(struct device *dev, char *buf, int nr) {
        struct via686a_data *data = via686a_update_device(dev);
-       return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], 
+       return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
                                DIV_FROM_REG(data->fan_div[nr])) );
 }
 static ssize_t show_fan_min(struct device *dev, char *buf, int nr) {
        struct via686a_data *data = via686a_update_device(dev);
-       return sprintf(buf,"%d\n",
+       return sprintf(buf, "%d\n",
                FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
 }
 static ssize_t show_fan_div(struct device *dev, char *buf, int nr) {
        struct via686a_data *data = via686a_update_device(dev);
-       return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+       return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
 }
-static ssize_t set_fan_min(struct device *dev, const char *buf, 
+static ssize_t set_fan_min(struct device *dev, const char *buf,
                size_t count, int nr) {
        struct i2c_client *client = to_i2c_client(dev);
        struct via686a_data *data = i2c_get_clientdata(client);
@@ -521,7 +516,7 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
        up(&data->update_lock);
        return count;
 }
-static ssize_t set_fan_div(struct device *dev, const char *buf, 
+static ssize_t set_fan_div(struct device *dev, const char *buf,
                size_t count, int nr) {
        struct i2c_client *client = to_i2c_client(dev);
        struct via686a_data *data = i2c_get_clientdata(client);
@@ -572,7 +567,7 @@ show_fan_offset(2);
 /* Alarms */
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) {
        struct via686a_data *data = via686a_update_device(dev);
-       return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
+       return sprintf(buf, "%u\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
@@ -612,11 +607,12 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* 8231 requires multiple of 256, we enforce that on 686 as well */
-       if(force_addr)
+       if (force_addr)
                address = force_addr & 0xFF00;
 
-       if(force_addr) {
-               dev_warn(&adapter->dev,"forcing ISA address 0x%04X\n", address);
+       if (force_addr) {
+               dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
+                        address);
                if (PCIBIOS_SUCCESSFUL !=
                    pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
                        return -ENODEV;
@@ -625,17 +621,17 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
            pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
                return -ENODEV;
        if (!(val & 0x0001)) {
-               dev_warn(&adapter->dev,"enabling sensors\n");
+               dev_warn(&adapter->dev, "enabling sensors\n");
                if (PCIBIOS_SUCCESSFUL !=
                    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
-                                     val | 0x0001))
+                                         val | 0x0001))
                        return -ENODEV;
        }
 
        /* Reserve the ISA region */
        if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
-               dev_err(&adapter->dev,"region 0x%x already in use!\n",
-                      address);
+               dev_err(&adapter->dev, "region 0x%x already in use!\n",
+                       address);
                return -ENODEV;
        }
 
@@ -660,7 +656,7 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
        /* Tell the I2C layer a new client has arrived */
        if ((err = i2c_attach_client(new_client)))
                goto ERROR3;
-       
+
        /* Initialize the VIA686A chip */
        via686a_init_client(new_client);
 
@@ -699,9 +695,9 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
-      ERROR3:
+ERROR3:
        kfree(data);
-      ERROR0:
+ERROR0:
        release_region(address, VIA686A_EXTENT);
        return err;
 }
@@ -732,7 +728,7 @@ static void via686a_init_client(struct i2c_client *client)
        via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);
 
        /* Configure temp interrupt mode for continuous-interrupt operation */
-       via686a_write_value(client, VIA686A_REG_TEMP_MODE, 
+       via686a_write_value(client, VIA686A_REG_TEMP_MODE,
                            via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
                            !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
 }
@@ -764,15 +760,15 @@ static struct via686a_data *via686a_update_device(struct device *dev)
                }
                for (i = 0; i <= 2; i++) {
                        data->temp[i] = via686a_read_value(client,
-                                                VIA686A_REG_TEMP(i)) << 2;
+                                                VIA686A_REG_TEMP[i]) << 2;
                        data->temp_over[i] =
                            via686a_read_value(client,
-                                              VIA686A_REG_TEMP_OVER(i));
+                                              VIA686A_REG_TEMP_OVER[i]);
                        data->temp_hyst[i] =
                            via686a_read_value(client,
-                                              VIA686A_REG_TEMP_HYST(i));
+                                              VIA686A_REG_TEMP_HYST[i]);
                }
-               /* add in lower 2 bits 
+               /* add in lower 2 bits
                   temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
                   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
                   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
@@ -804,35 +800,36 @@ static struct via686a_data *via686a_update_device(struct device *dev)
 }
 
 static struct pci_device_id via686a_pci_ids[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
-       { 0, }
+       { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
+       { 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
 
 static int __devinit via686a_pci_probe(struct pci_dev *dev,
-                                      const struct pci_device_id *id)
+                                      const struct pci_device_id *id)
 {
-       u16 val;
-       int addr = 0;
-
-       if (PCIBIOS_SUCCESSFUL !=
-           pci_read_config_word(dev, VIA686A_BASE_REG, &val))
-               return -ENODEV;
-
-       addr = val & ~(VIA686A_EXTENT - 1);
-       if (addr == 0 && force_addr == 0) {
-               dev_err(&dev->dev,"base address not set - upgrade BIOS or use force_addr=0xaddr\n");
-               return -ENODEV;
-       }
-       if (force_addr)
-               addr = force_addr;      /* so detect will get called */
-
-       if (!addr) {
-               dev_err(&dev->dev,"No Via 686A sensors found.\n");
-               return -ENODEV;
-       }
-       normal_isa[0] = addr;
+       u16 val;
+       int addr = 0;
+
+       if (PCIBIOS_SUCCESSFUL !=
+           pci_read_config_word(dev, VIA686A_BASE_REG, &val))
+               return -ENODEV;
+
+       addr = val & ~(VIA686A_EXTENT - 1);
+       if (addr == 0 && force_addr == 0) {
+               dev_err(&dev->dev, "base address not set - upgrade BIOS "
+                       "or use force_addr=0xaddr\n");
+               return -ENODEV;
+       }
+       if (force_addr)
+               addr = force_addr;      /* so detect will get called */
+
+       if (!addr) {
+               dev_err(&dev->dev, "No Via 686A sensors found.\n");
+               return -ENODEV;
+       }
+       normal_isa[0] = addr;
 
        s_bridge = pci_dev_get(dev);
        if (i2c_add_driver(&via686a_driver)) {
@@ -848,14 +845,14 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
 }
 
 static struct pci_driver via686a_pci_driver = {
-       .name           = "via686a",
-       .id_table       = via686a_pci_ids,
-       .probe          = via686a_pci_probe,
+       .name           = "via686a",
+       .id_table       = via686a_pci_ids,
+       .probe          = via686a_pci_probe,
 };
 
 static int __init sm_via686a_init(void)
 {
-       return pci_register_driver(&via686a_pci_driver);
+       return pci_register_driver(&via686a_pci_driver);
 }
 
 static void __exit sm_via686a_exit(void)
@@ -869,8 +866,8 @@ static void __exit sm_via686a_exit(void)
 }
 
 MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
-              "Mark Studebaker <mdsxyz123@yahoo.com> "
-             "and Bob Dougherty <bobd@stanford.edu>");
+             "Mark Studebaker <mdsxyz123@yahoo.com> "
+             "and Bob Dougherty <bobd@stanford.edu>");
 MODULE_DESCRIPTION("VIA 686A Sensor device");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/i2c/chips/w83627ehf.c b/drivers/i2c/chips/w83627ehf.c
new file mode 100644 (file)
index 0000000..8a40b69
--- /dev/null
@@ -0,0 +1,846 @@
+/*
+    w83627ehf - Driver for the hardware monitoring functionality of
+                the Winbond W83627EHF Super-I/O chip
+    Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+
+    Shamelessly ripped from the w83627hf driver
+    Copyright (C) 2003  Mark Studebaker
+
+    Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
+    in testing and debugging this driver.
+
+    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.
+
+
+    Supports the following chips:
+
+    Chip        #vin    #fan    #pwm    #temp   chip_id man_id
+    w83627ehf   -       5       -       3       0x88    0x5ca3
+
+    This is a preliminary version of the driver, only supporting the
+    fan and temperature inputs. The chip does much more than that.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <asm/io.h>
+#include "lm75.h"
+
+/* Addresses to scan
+   The actual ISA address is read from Super-I/O configuration space */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(w83627ehf);
+
+/*
+ * Super-I/O constants and functions
+ */
+
+static int REG;                /* The register to read/write */
+static int VAL;                /* The value to read/write */
+
+#define W83627EHF_LD_HWM       0x0b
+
+#define SIO_REG_LDSEL          0x07    /* Logical device select */
+#define SIO_REG_DEVID          0x20    /* Device ID (2 bytes) */
+#define SIO_REG_ENABLE         0x30    /* Logical device enable */
+#define SIO_REG_ADDR           0x60    /* Logical device address (2 bytes) */
+
+#define SIO_W83627EHF_ID       0x8840
+#define SIO_ID_MASK            0xFFC0
+
+static inline void
+superio_outb(int reg, int val)
+{
+       outb(reg, REG);
+       outb(val, VAL);
+}
+
+static inline int
+superio_inb(int reg)
+{
+       outb(reg, REG);
+       return inb(VAL);
+}
+
+static inline void
+superio_select(int ld)
+{
+       outb(SIO_REG_LDSEL, REG);
+       outb(ld, VAL);
+}
+
+static inline void
+superio_enter(void)
+{
+       outb(0x87, REG);
+       outb(0x87, REG);
+}
+
+static inline void
+superio_exit(void)
+{
+       outb(0x02, REG);
+       outb(0x02, VAL);
+}
+
+/*
+ * ISA constants
+ */
+
+#define REGION_LENGTH          8
+#define ADDR_REG_OFFSET                5
+#define DATA_REG_OFFSET                6
+
+#define W83627EHF_REG_BANK             0x4E
+#define W83627EHF_REG_CONFIG           0x40
+#define W83627EHF_REG_CHIP_ID          0x49
+#define W83627EHF_REG_MAN_ID           0x4F
+
+static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
+static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
+
+#define W83627EHF_REG_TEMP1            0x27
+#define W83627EHF_REG_TEMP1_HYST       0x3a
+#define W83627EHF_REG_TEMP1_OVER       0x39
+static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
+static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
+static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
+static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
+
+/* Fan clock dividers are spread over the following five registers */
+#define W83627EHF_REG_FANDIV1          0x47
+#define W83627EHF_REG_FANDIV2          0x4B
+#define W83627EHF_REG_VBAT             0x5D
+#define W83627EHF_REG_DIODE            0x59
+#define W83627EHF_REG_SMI_OVT          0x4C
+
+/*
+ * Conversions
+ */
+
+static inline unsigned int
+fan_from_reg(u8 reg, unsigned int div)
+{
+       if (reg == 0 || reg == 255)
+               return 0;
+       return 1350000U / (reg * div);
+}
+
+static inline unsigned int
+div_from_reg(u8 reg)
+{
+       return 1 << reg;
+}
+
+static inline int
+temp1_from_reg(s8 reg)
+{
+       return reg * 1000;
+}
+
+static inline s8
+temp1_to_reg(int temp)
+{
+       if (temp <= -128000)
+               return -128;
+       if (temp >= 127000)
+               return 127;
+       if (temp < 0)
+               return (temp - 500) / 1000;
+       return (temp + 500) / 1000;
+}
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct w83627ehf_data {
+       struct i2c_client client;
+       struct semaphore lock;
+
+       struct semaphore update_lock;
+       char valid;             /* !=0 if following fields are valid */
+       unsigned long last_updated;     /* In jiffies */
+
+       /* Register values */
+       u8 fan[5];
+       u8 fan_min[5];
+       u8 fan_div[5];
+       u8 has_fan;             /* some fan inputs can be disabled */
+       s8 temp1;
+       s8 temp1_max;
+       s8 temp1_max_hyst;
+       s16 temp[2];
+       s16 temp_max[2];
+       s16 temp_max_hyst[2];
+};
+
+static inline int is_word_sized(u16 reg)
+{
+       return (((reg & 0xff00) == 0x100
+             || (reg & 0xff00) == 0x200)
+            && ((reg & 0x00ff) == 0x50
+             || (reg & 0x00ff) == 0x53
+             || (reg & 0x00ff) == 0x55));
+}
+
+/* We assume that the default bank is 0, thus the following two functions do
+   nothing for registers which live in bank 0. For others, they respectively
+   set the bank register to the correct value (before the register is
+   accessed), and back to 0 (afterwards). */
+static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg)
+{
+       if (reg & 0xff00) {
+               outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
+               outb_p(reg >> 8, client->addr + DATA_REG_OFFSET);
+       }
+}
+
+static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg)
+{
+       if (reg & 0xff00) {
+               outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
+               outb_p(0, client->addr + DATA_REG_OFFSET);
+       }
+}
+
+static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
+{
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       int res, word_sized = is_word_sized(reg);
+
+       down(&data->lock);
+
+       w83627ehf_set_bank(client, reg);
+       outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
+       res = inb_p(client->addr + DATA_REG_OFFSET);
+       if (word_sized) {
+               outb_p((reg & 0xff) + 1,
+                      client->addr + ADDR_REG_OFFSET);
+               res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET);
+       }
+       w83627ehf_reset_bank(client, reg);
+
+       up(&data->lock);
+
+       return res;
+}
+
+static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
+{
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       int word_sized = is_word_sized(reg);
+
+       down(&data->lock);
+
+       w83627ehf_set_bank(client, reg);
+       outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
+       if (word_sized) {
+               outb_p(value >> 8, client->addr + DATA_REG_OFFSET);
+               outb_p((reg & 0xff) + 1,
+                      client->addr + ADDR_REG_OFFSET);
+       }
+       outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
+       w83627ehf_reset_bank(client, reg);
+
+       up(&data->lock);
+       return 0;
+}
+
+/* This function assumes that the caller holds data->update_lock */
+static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
+{
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       u8 reg;
+
+       switch (nr) {
+       case 0:
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
+                   | ((data->fan_div[0] & 0x03) << 4);
+               w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
+                   | ((data->fan_div[0] & 0x04) << 3);
+               w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+               break;
+       case 1:
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
+                   | ((data->fan_div[1] & 0x03) << 6);
+               w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
+                   | ((data->fan_div[1] & 0x04) << 4);
+               w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+               break;
+       case 2:
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f)
+                   | ((data->fan_div[2] & 0x03) << 6);
+               w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg);
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f)
+                   | ((data->fan_div[2] & 0x04) << 5);
+               w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+               break;
+       case 3:
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc)
+                   | (data->fan_div[3] & 0x03);
+               w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f)
+                   | ((data->fan_div[3] & 0x04) << 5);
+               w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg);
+               break;
+       case 4:
+               reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73)
+                   | ((data->fan_div[4] & 0x03) << 3)
+                   | ((data->fan_div[4] & 0x04) << 5);
+               w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
+               break;
+       }
+}
+
+static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       int i;
+
+       down(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + HZ)
+        || !data->valid) {
+               /* Fan clock dividers */
+               i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
+               data->fan_div[0] = (i >> 4) & 0x03;
+               data->fan_div[1] = (i >> 6) & 0x03;
+               i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2);
+               data->fan_div[2] = (i >> 6) & 0x03;
+               i = w83627ehf_read_value(client, W83627EHF_REG_VBAT);
+               data->fan_div[0] |= (i >> 3) & 0x04;
+               data->fan_div[1] |= (i >> 4) & 0x04;
+               data->fan_div[2] |= (i >> 5) & 0x04;
+               if (data->has_fan & ((1 << 3) | (1 << 4))) {
+                       i = w83627ehf_read_value(client, W83627EHF_REG_DIODE);
+                       data->fan_div[3] = i & 0x03;
+                       data->fan_div[4] = ((i >> 2) & 0x03)
+                                        | ((i >> 5) & 0x04);
+               }
+               if (data->has_fan & (1 << 3)) {
+                       i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT);
+                       data->fan_div[3] |= (i >> 5) & 0x04;
+               }
+
+               /* Measured fan speeds and limits */
+               for (i = 0; i < 5; i++) {
+                       if (!(data->has_fan & (1 << i)))
+                               continue;
+
+                       data->fan[i] = w83627ehf_read_value(client,
+                                      W83627EHF_REG_FAN[i]);
+                       data->fan_min[i] = w83627ehf_read_value(client,
+                                          W83627EHF_REG_FAN_MIN[i]);
+
+                       /* If we failed to measure the fan speed and clock
+                          divider can be increased, let's try that for next
+                          time */
+                       if (data->fan[i] == 0xff
+                        && data->fan_div[i] < 0x07) {
+                               dev_dbg(&client->dev, "Increasing fan %d "
+                                       "clock divider from %u to %u\n",
+                                       i, div_from_reg(data->fan_div[i]),
+                                       div_from_reg(data->fan_div[i] + 1));
+                               data->fan_div[i]++;
+                               w83627ehf_write_fan_div(client, i);
+                               /* Preserve min limit if possible */
+                               if (data->fan_min[i] >= 2
+                                && data->fan_min[i] != 255)
+                                       w83627ehf_write_value(client,
+                                               W83627EHF_REG_FAN_MIN[i],
+                                               (data->fan_min[i] /= 2));
+                       }
+               }
+
+               /* Measured temperatures and limits */
+               data->temp1 = w83627ehf_read_value(client,
+                             W83627EHF_REG_TEMP1);
+               data->temp1_max = w83627ehf_read_value(client,
+                                 W83627EHF_REG_TEMP1_OVER);
+               data->temp1_max_hyst = w83627ehf_read_value(client,
+                                      W83627EHF_REG_TEMP1_HYST);
+               for (i = 0; i < 2; i++) {
+                       data->temp[i] = w83627ehf_read_value(client,
+                                       W83627EHF_REG_TEMP[i]);
+                       data->temp_max[i] = w83627ehf_read_value(client,
+                                           W83627EHF_REG_TEMP_OVER[i]);
+                       data->temp_max_hyst[i] = w83627ehf_read_value(client,
+                                                W83627EHF_REG_TEMP_HYST[i]);
+               }
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       up(&data->update_lock);
+       return data;
+}
+
+/*
+ * Sysfs callback functions
+ */
+
+#define show_fan_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, char *buf, int nr) \
+{ \
+       struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+       return sprintf(buf, "%d\n", \
+                      fan_from_reg(data->reg[nr], \
+                                   div_from_reg(data->fan_div[nr]))); \
+}
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+show_fan_div(struct device *dev, char *buf, int nr)
+{
+       struct w83627ehf_data *data = w83627ehf_update_device(dev);
+       return sprintf(buf, "%u\n",
+                      div_from_reg(data->fan_div[nr]));
+}
+
+static ssize_t
+store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       unsigned int val = simple_strtoul(buf, NULL, 10);
+       unsigned int reg;
+       u8 new_div;
+
+       down(&data->update_lock);
+       if (!val) {
+               /* No min limit, alarm disabled */
+               data->fan_min[nr] = 255;
+               new_div = data->fan_div[nr]; /* No change */
+               dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
+       } else if ((reg = 1350000U / val) >= 128 * 255) {
+               /* Speed below this value cannot possibly be represented,
+                  even with the highest divider (128) */
+               data->fan_min[nr] = 254;
+               new_div = 7; /* 128 == (1 << 7) */
+               dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
+                        "minimum\n", nr + 1, val, fan_from_reg(254, 128));
+       } else if (!reg) {
+               /* Speed above this value cannot possibly be represented,
+                  even with the lowest divider (1) */
+               data->fan_min[nr] = 1;
+               new_div = 0; /* 1 == (1 << 0) */
+               dev_warn(dev, "fan%u low limit %u above maximum %u, set to "
+                        "maximum\n", nr + 1, val, fan_from_reg(1, 1));
+       } else {
+               /* Automatically pick the best divider, i.e. the one such
+                  that the min limit will correspond to a register value
+                  in the 96..192 range */
+               new_div = 0;
+               while (reg > 192 && new_div < 7) {
+                       reg >>= 1;
+                       new_div++;
+               }
+               data->fan_min[nr] = reg;
+       }
+
+       /* Write both the fan clock divider (if it changed) and the new
+          fan min (unconditionally) */
+       if (new_div != data->fan_div[nr]) {
+               if (new_div > data->fan_div[nr])
+                       data->fan[nr] >>= (data->fan_div[nr] - new_div);
+               else
+                       data->fan[nr] <<= (new_div - data->fan_div[nr]);
+
+               dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
+                       nr + 1, div_from_reg(data->fan_div[nr]),
+                       div_from_reg(new_div));
+               data->fan_div[nr] = new_div;
+               w83627ehf_write_fan_div(client, nr);
+       }
+       w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
+                             data->fan_min[nr]);
+       up(&data->update_lock);
+
+       return count;
+}
+
+#define sysfs_fan_offset(offset) \
+static ssize_t \
+show_reg_fan_##offset(struct device *dev, struct device_attribute *attr, \
+                     char *buf) \
+{ \
+       return show_fan(dev, buf, offset-1); \
+} \
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+                  show_reg_fan_##offset, NULL);
+
+#define sysfs_fan_min_offset(offset) \
+static ssize_t \
+show_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \
+                          char *buf) \
+{ \
+       return show_fan_min(dev, buf, offset-1); \
+} \
+static ssize_t \
+store_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \
+                           const char *buf, size_t count) \
+{ \
+       return store_fan_min(dev, buf, count, offset-1); \
+} \
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+                  show_reg_fan##offset##_min, \
+                  store_reg_fan##offset##_min);
+
+#define sysfs_fan_div_offset(offset) \
+static ssize_t \
+show_reg_fan##offset##_div(struct device *dev, struct device_attribute *attr, \
+                          char *buf) \
+{ \
+       return show_fan_div(dev, buf, offset - 1); \
+} \
+static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
+                  show_reg_fan##offset##_div, NULL);
+
+sysfs_fan_offset(1);
+sysfs_fan_min_offset(1);
+sysfs_fan_div_offset(1);
+sysfs_fan_offset(2);
+sysfs_fan_min_offset(2);
+sysfs_fan_div_offset(2);
+sysfs_fan_offset(3);
+sysfs_fan_min_offset(3);
+sysfs_fan_div_offset(3);
+sysfs_fan_offset(4);
+sysfs_fan_min_offset(4);
+sysfs_fan_div_offset(4);
+sysfs_fan_offset(5);
+sysfs_fan_min_offset(5);
+sysfs_fan_div_offset(5);
+
+#define show_temp1_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, struct device_attribute *attr, \
+          char *buf) \
+{ \
+       struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+       return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
+}
+show_temp1_reg(temp1);
+show_temp1_reg(temp1_max);
+show_temp1_reg(temp1_max_hyst);
+
+#define store_temp1_reg(REG, reg) \
+static ssize_t \
+store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
+                 const char *buf, size_t count) \
+{ \
+       struct i2c_client *client = to_i2c_client(dev); \
+       struct w83627ehf_data *data = i2c_get_clientdata(client); \
+       u32 val = simple_strtoul(buf, NULL, 10); \
+ \
+       down(&data->update_lock); \
+       data->temp1_##reg = temp1_to_reg(val); \
+       w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
+                             data->temp1_##reg); \
+       up(&data->update_lock); \
+       return count; \
+}
+store_temp1_reg(OVER, max);
+store_temp1_reg(HYST, max_hyst);
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR,
+                  show_temp1_max, store_temp1_max);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR,
+                  show_temp1_max_hyst, store_temp1_max_hyst);
+
+#define show_temp_reg(reg) \
+static ssize_t \
+show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+       struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+       return sprintf(buf, "%d\n", \
+                      LM75_TEMP_FROM_REG(data->reg[nr])); \
+}
+show_temp_reg(temp);
+show_temp_reg(temp_max);
+show_temp_reg(temp_max_hyst);
+
+#define store_temp_reg(REG, reg) \
+static ssize_t \
+store_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+{ \
+       struct i2c_client *client = to_i2c_client(dev); \
+       struct w83627ehf_data *data = i2c_get_clientdata(client); \
+       u32 val = simple_strtoul(buf, NULL, 10); \
+ \
+       down(&data->update_lock); \
+       data->reg[nr] = LM75_TEMP_TO_REG(val); \
+       w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
+                             data->reg[nr]); \
+       up(&data->update_lock); \
+       return count; \
+}
+store_temp_reg(OVER, temp_max);
+store_temp_reg(HYST, temp_max_hyst);
+
+#define sysfs_temp_offset(offset) \
+static ssize_t \
+show_reg_temp##offset (struct device *dev, struct device_attribute *attr, \
+                      char *buf) \
+{ \
+       return show_temp(dev, buf, offset - 2); \
+} \
+static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+                  show_reg_temp##offset, NULL);
+
+#define sysfs_temp_reg_offset(reg, offset) \
+static ssize_t \
+show_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \
+                             char *buf) \
+{ \
+       return show_temp_##reg(dev, buf, offset - 2); \
+} \
+static ssize_t \
+store_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \
+                              const char *buf, size_t count) \
+{ \
+       return store_temp_##reg(dev, buf, count, offset - 2); \
+} \
+static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \
+                  show_reg_temp##offset##_##reg, \
+                  store_reg_temp##offset##_##reg);
+
+sysfs_temp_offset(2);
+sysfs_temp_reg_offset(max, 2);
+sysfs_temp_reg_offset(max_hyst, 2);
+sysfs_temp_offset(3);
+sysfs_temp_reg_offset(max, 3);
+sysfs_temp_reg_offset(max_hyst, 3);
+
+/*
+ * Driver and client management
+ */
+
+static struct i2c_driver w83627ehf_driver;
+
+static void w83627ehf_init_client(struct i2c_client *client)
+{
+       int i;
+       u8 tmp;
+
+       /* Start monitoring is needed */
+       tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG);
+       if (!(tmp & 0x01))
+               w83627ehf_write_value(client, W83627EHF_REG_CONFIG,
+                                     tmp | 0x01);
+
+       /* Enable temp2 and temp3 if needed */
+       for (i = 0; i < 2; i++) {
+               tmp = w83627ehf_read_value(client,
+                                          W83627EHF_REG_TEMP_CONFIG[i]);
+               if (tmp & 0x01)
+                       w83627ehf_write_value(client,
+                                             W83627EHF_REG_TEMP_CONFIG[i],
+                                             tmp & 0xfe);
+       }
+}
+
+static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *client;
+       struct w83627ehf_data *data;
+       int i, err = 0;
+
+       if (!i2c_is_isa_adapter(adapter))
+               return 0;
+
+       if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
+               err = -EBUSY;
+               goto exit;
+       }
+
+       if (!(data = kmalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit_release;
+       }
+       memset(data, 0, sizeof(struct w83627ehf_data));
+
+       client = &data->client;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
+       init_MUTEX(&data->lock);
+       client->adapter = adapter;
+       client->driver = &w83627ehf_driver;
+       client->flags = 0;
+
+       strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
+       data->valid = 0;
+       init_MUTEX(&data->update_lock);
+
+       /* Tell the i2c layer a new client has arrived */
+       if ((err = i2c_attach_client(client)))
+               goto exit_free;
+
+       /* Initialize the chip */
+       w83627ehf_init_client(client);
+
+       /* A few vars need to be filled upon startup */
+       for (i = 0; i < 5; i++)
+               data->fan_min[i] = w83627ehf_read_value(client,
+                                  W83627EHF_REG_FAN_MIN[i]);
+
+       /* It looks like fan4 and fan5 pins can be alternatively used
+          as fan on/off switches */
+       data->has_fan = 0x07; /* fan1, fan2 and fan3 */
+       i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
+       if (i & (1 << 2))
+               data->has_fan |= (1 << 3);
+       if (i & (1 << 0))
+               data->has_fan |= (1 << 4);
+
+       /* Register sysfs hooks */
+       device_create_file(&client->dev, &dev_attr_fan1_input);
+       device_create_file(&client->dev, &dev_attr_fan1_min);
+       device_create_file(&client->dev, &dev_attr_fan1_div);
+       device_create_file(&client->dev, &dev_attr_fan2_input);
+       device_create_file(&client->dev, &dev_attr_fan2_min);
+       device_create_file(&client->dev, &dev_attr_fan2_div);
+       device_create_file(&client->dev, &dev_attr_fan3_input);
+       device_create_file(&client->dev, &dev_attr_fan3_min);
+       device_create_file(&client->dev, &dev_attr_fan3_div);
+
+       if (data->has_fan & (1 << 3)) {
+               device_create_file(&client->dev, &dev_attr_fan4_input);
+               device_create_file(&client->dev, &dev_attr_fan4_min);
+               device_create_file(&client->dev, &dev_attr_fan4_div);
+       }
+       if (data->has_fan & (1 << 4)) {
+               device_create_file(&client->dev, &dev_attr_fan5_input);
+               device_create_file(&client->dev, &dev_attr_fan5_min);
+               device_create_file(&client->dev, &dev_attr_fan5_div);
+       }
+
+       device_create_file(&client->dev, &dev_attr_temp1_input);
+       device_create_file(&client->dev, &dev_attr_temp1_max);
+       device_create_file(&client->dev, &dev_attr_temp1_max_hyst);
+       device_create_file(&client->dev, &dev_attr_temp2_input);
+       device_create_file(&client->dev, &dev_attr_temp2_max);
+       device_create_file(&client->dev, &dev_attr_temp2_max_hyst);
+       device_create_file(&client->dev, &dev_attr_temp3_input);
+       device_create_file(&client->dev, &dev_attr_temp3_max);
+       device_create_file(&client->dev, &dev_attr_temp3_max_hyst);
+
+       return 0;
+
+exit_free:
+       kfree(data);
+exit_release:
+       release_region(address, REGION_LENGTH);
+exit:
+       return err;
+}
+
+static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!(adapter->class & I2C_CLASS_HWMON))
+               return 0;
+       return i2c_detect(adapter, &addr_data, w83627ehf_detect);
+}
+
+static int w83627ehf_detach_client(struct i2c_client *client)
+{
+       int err;
+
+       if ((err = i2c_detach_client(client))) {
+               dev_err(&client->dev, "Client deregistration failed, "
+                       "client not detached.\n");
+               return err;
+       }
+       release_region(client->addr, REGION_LENGTH);
+       kfree(i2c_get_clientdata(client));
+
+       return 0;
+}
+
+static struct i2c_driver w83627ehf_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "w83627ehf",
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = w83627ehf_attach_adapter,
+       .detach_client  = w83627ehf_detach_client,
+};
+
+static int __init w83627ehf_find(int sioaddr, int *address)
+{
+       u16 val;
+
+       REG = sioaddr;
+       VAL = sioaddr + 1;
+       superio_enter();
+
+       val = (superio_inb(SIO_REG_DEVID) << 8)
+           | superio_inb(SIO_REG_DEVID + 1);
+       if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) {
+               superio_exit();
+               return -ENODEV;
+       }
+
+       superio_select(W83627EHF_LD_HWM);
+       val = (superio_inb(SIO_REG_ADDR) << 8)
+           | superio_inb(SIO_REG_ADDR + 1);
+       *address = val & ~(REGION_LENGTH - 1);
+       if (*address == 0) {
+               superio_exit();
+               return -ENODEV;
+       }
+
+       /* Activate logical device if needed */
+       val = superio_inb(SIO_REG_ENABLE);
+       if (!(val & 0x01))
+               superio_outb(SIO_REG_ENABLE, val | 0x01);
+
+       superio_exit();
+       return 0;
+}
+
+static int __init sensors_w83627ehf_init(void)
+{
+       if (w83627ehf_find(0x2e, &normal_isa[0])
+        && w83627ehf_find(0x4e, &normal_isa[0]))
+               return -ENODEV;
+
+       return i2c_add_driver(&w83627ehf_driver);
+}
+
+static void __exit sensors_w83627ehf_exit(void)
+{
+       i2c_del_driver(&w83627ehf_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("W83627EHF driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83627ehf_init);
+module_exit(sensors_w83627ehf_exit);
index 4f1bff572c1c22345e5ad974be40f98817e2636b..bd87a42e068ae4d6ac0fd1763d61b3c32b1bb5d7 100644 (file)
@@ -264,7 +264,7 @@ static inline u8 DIV_TO_REG(long val)
 {
        int i;
        val = SENSORS_LIMIT(val, 1, 128) >> 1;
-       for (i = 0; i < 6; i++) {
+       for (i = 0; i < 7; i++) {
                if (val == 0)
                        break;
                val >>= 1;
index c3926d2d8ac6819787b726f8696124d6a9755943..0bb131ce09ebc931fdebf415c75c6c6f255f7e11 100644 (file)
     as99127f rev.2 (type_name = as99127f)      0x31    0x5ca3  yes     no
     w83781d    7       3       0       3       0x10-1  0x5ca3  yes     yes
     w83627hf   9       3       2       3       0x21    0x5ca3  yes     yes(LPC)
-    w83627thf  9       3       2       3       0x90    0x5ca3  no      yes(LPC)
     w83782d    9       3       2-4     3       0x30    0x5ca3  yes     yes
     w83783s    5-6     3       2       1-2     0x40    0x5ca3  yes     no
-    w83697hf   8       2       2       2       0x60    0x5ca3  no      yes(LPC)
 
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -53,7 +50,7 @@ static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
 static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_6(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf);
+SENSORS_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
                    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
@@ -173,7 +170,6 @@ FAN_TO_REG(long rpm, int div)
                                                : (val)) / 1000, 0, 0xff))
 #define TEMP_FROM_REG(val)             (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
 
-#define ALARMS_FROM_REG(val)           (val)
 #define PWM_FROM_REG(val)              (val)
 #define PWM_TO_REG(val)                        (SENSORS_LIMIT((val),0,255))
 #define BEEP_MASK_FROM_REG(val,type)   ((type) == as99127f ? \
@@ -193,7 +189,7 @@ DIV_TO_REG(long val, enum chips type)
        val = SENSORS_LIMIT(val, 1,
                            ((type == w83781d
                              || type == as99127f) ? 8 : 128)) >> 1;
-       for (i = 0; i < 6; i++) {
+       for (i = 0; i < 7; i++) {
                if (val == 0)
                        break;
                val >>= 1;
@@ -524,7 +520,7 @@ static ssize_t
 show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct w83781d_data *data = w83781d_update_device(dev);
-       return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+       return sprintf(buf, "%u\n", data->alarms);
 }
 
 static
@@ -1000,13 +996,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                err = -EINVAL;
                goto ERROR0;
        }
-       if (!is_isa && kind == w83697hf) {
-               dev_err(&adapter->dev,
-                       "Cannot force ISA-only chip for I2C address 0x%02x.\n",
-                       address);
-               err = -EINVAL;
-               goto ERROR0;
-       }
        
        if (is_isa)
                if (!request_region(address, W83781D_EXTENT,
@@ -1139,12 +1128,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                else if (val1 == 0x40 && vendid == winbond && !is_isa
                                && address == 0x2d)
                        kind = w83783s;
-               else if ((val1 == 0x21 || val1 == 0x90) && vendid == winbond)
+               else if (val1 == 0x21 && vendid == winbond)
                        kind = w83627hf;
                else if (val1 == 0x31 && !is_isa && address >= 0x28)
                        kind = as99127f;
-               else if (val1 == 0x60 && vendid == winbond && is_isa)
-                       kind = w83697hf;
                else {
                        if (kind == 0)
                                dev_warn(&new_client->dev, "Ignoring 'force' "
@@ -1163,14 +1150,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        } else if (kind == w83783s) {
                client_name = "w83783s";
        } else if (kind == w83627hf) {
-               if (val1 == 0x90)
-                       client_name = "w83627thf";
-               else
-                       client_name = "w83627hf";
+               client_name = "w83627hf";
        } else if (kind == as99127f) {
                client_name = "as99127f";
-       } else if (kind == w83697hf) {
-               client_name = "w83697hf";
        }
 
        /* Fill in the remaining client fields and put into the global list */
@@ -1208,7 +1190,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* Register sysfs hooks */
        device_create_file_in(new_client, 0);
-       if (kind != w83783s && kind != w83697hf)
+       if (kind != w83783s)
                device_create_file_in(new_client, 1);
        device_create_file_in(new_client, 2);
        device_create_file_in(new_client, 3);
@@ -1222,24 +1204,19 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 
        device_create_file_fan(new_client, 1);
        device_create_file_fan(new_client, 2);
-       if (kind != w83697hf)
-               device_create_file_fan(new_client, 3);
+       device_create_file_fan(new_client, 3);
 
        device_create_file_temp(new_client, 1);
        device_create_file_temp(new_client, 2);
-       if (kind != w83783s && kind != w83697hf)
+       if (kind != w83783s)
                device_create_file_temp(new_client, 3);
 
-       if (kind != w83697hf)
-               device_create_file_vid(new_client);
-
-       if (kind != w83697hf)
-               device_create_file_vrm(new_client);
+       device_create_file_vid(new_client);
+       device_create_file_vrm(new_client);
 
        device_create_file_fan_div(new_client, 1);
        device_create_file_fan_div(new_client, 2);
-       if (kind != w83697hf)
-               device_create_file_fan_div(new_client, 3);
+       device_create_file_fan_div(new_client, 3);
 
        device_create_file_alarms(new_client);
 
@@ -1258,7 +1235,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        if (kind != as99127f && kind != w83781d) {
                device_create_file_sensor(new_client, 1);
                device_create_file_sensor(new_client, 2);
-               if (kind != w83783s && kind != w83697hf)
+               if (kind != w83783s)
                        device_create_file_sensor(new_client, 3);
        }
 
@@ -1481,7 +1458,7 @@ w83781d_init_client(struct i2c_client *client)
                                else
                                        data->sens[i - 1] = 2;
                        }
-                       if ((type == w83783s || type == w83697hf) && (i == 2))
+                       if (type == w83783s && i == 2)
                                break;
                }
        }
@@ -1497,7 +1474,7 @@ w83781d_init_client(struct i2c_client *client)
                }
 
                /* Enable temp3 */
-               if (type != w83783s && type != w83697hf) {
+               if (type != w83783s) {
                        tmp = w83781d_read_value(client,
                                W83781D_REG_TEMP3_CONFIG);
                        if (tmp & 0x01) {
@@ -1538,8 +1515,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
                dev_dbg(dev, "Starting device update\n");
 
                for (i = 0; i <= 8; i++) {
-                       if ((data->type == w83783s || data->type == w83697hf)
-                           && (i == 1))
+                       if (data->type == w83783s && i == 1)
                                continue;       /* 783S has no in1 */
                        data->in[i] =
                            w83781d_read_value(client, W83781D_REG_IN(i));
@@ -1547,7 +1523,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
                            w83781d_read_value(client, W83781D_REG_IN_MIN(i));
                        data->in_max[i] =
                            w83781d_read_value(client, W83781D_REG_IN_MAX(i));
-                       if ((data->type != w83782d) && (data->type != w83697hf)
+                       if ((data->type != w83782d)
                            && (data->type != w83627hf) && (i == 6))
                                break;
                }
@@ -1583,7 +1559,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
                    w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
                data->temp_max_hyst_add[0] =
                    w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
-               if (data->type != w83783s && data->type != w83697hf) {
+               if (data->type != w83783s) {
                        data->temp_add[1] =
                            w83781d_read_value(client, W83781D_REG_TEMP(3));
                        data->temp_max_add[1] =
@@ -1594,26 +1570,18 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
                                               W83781D_REG_TEMP_HYST(3));
                }
                i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
-               if (data->type != w83697hf) {
-                       data->vid = i & 0x0f;
-                       data->vid |=
-                           (w83781d_read_value(client, W83781D_REG_CHIPID) &
-                            0x01)
-                           << 4;
-               }
+               data->vid = i & 0x0f;
+               data->vid |= (w83781d_read_value(client,
+                                       W83781D_REG_CHIPID) & 0x01) << 4;
                data->fan_div[0] = (i >> 4) & 0x03;
                data->fan_div[1] = (i >> 6) & 0x03;
-               if (data->type != w83697hf) {
-                       data->fan_div[2] = (w83781d_read_value(client,
-                                                              W83781D_REG_PIN)
-                                           >> 6) & 0x03;
-               }
+               data->fan_div[2] = (w83781d_read_value(client,
+                                       W83781D_REG_PIN) >> 6) & 0x03;
                if ((data->type != w83781d) && (data->type != as99127f)) {
                        i = w83781d_read_value(client, W83781D_REG_VBAT);
                        data->fan_div[0] |= (i >> 3) & 0x04;
                        data->fan_div[1] |= (i >> 4) & 0x04;
-                       if (data->type != w83697hf)
-                               data->fan_div[2] |= (i >> 5) & 0x04;
+                       data->fan_div[2] |= (i >> 5) & 0x04;
                }
                data->alarms =
                    w83781d_read_value(client,
index 74d4b58e42372dbd438de41bb5a1ab64875e3cca..4469d52aba4c6faefa0bc3047b379ad614eea6d3 100644 (file)
@@ -30,7 +30,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/init.h>
index a22e53badacbe95efa5e0451be2b8236a8d60cc5..51ce268998cd368fa065f048baee0f0f8956c111 100644 (file)
@@ -21,7 +21,6 @@
    All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
    SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com>                */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -239,7 +238,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        }
 
        /* detach any active clients. This must be done first, because
-        * it can fail; in which case we give upp. */
+        * it can fail; in which case we give up. */
        list_for_each_safe(item, _n, &adap->clients) {
                client = list_entry(item, struct i2c_client, list);
 
@@ -612,27 +611,16 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
 
-       if (client->adapter->algo->master_xfer) {
-               msg.addr   = client->addr;
-               msg.flags = client->flags & I2C_M_TEN;
-               msg.len = count;
-               msg.buf = (char *)buf;
+       msg.addr = client->addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.len = count;
+       msg.buf = (char *)buf;
        
-               dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
-                       count);
-       
-               down(&adap->bus_lock);
-               ret = adap->algo->master_xfer(adap,&msg,1);
-               up(&adap->bus_lock);
+       ret = i2c_transfer(adap, &msg, 1);
 
-               /* if everything went ok (i.e. 1 msg transmitted), return #bytes
-                * transmitted, else error code.
-                */
-               return (ret == 1 )? count : ret;
-       } else {
-               dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-               return -ENOSYS;
-       }
+       /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+          transmitted, else error code. */
+       return (ret == 1) ? count : ret;
 }
 
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
@@ -640,31 +628,18 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
        int ret;
-       if (client->adapter->algo->master_xfer) {
-               msg.addr   = client->addr;
-               msg.flags = client->flags & I2C_M_TEN;
-               msg.flags |= I2C_M_RD;
-               msg.len = count;
-               msg.buf = buf;
-
-               dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
-                       count);
-       
-               down(&adap->bus_lock);
-               ret = adap->algo->master_xfer(adap,&msg,1);
-               up(&adap->bus_lock);
-       
-               dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n",
-                       ret, count, client->addr);
-       
-               /* if everything went ok (i.e. 1 msg transmitted), return #bytes
-               * transmitted, else error code.
-               */
-               return (ret == 1 )? count : ret;
-       } else {
-               dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-               return -ENOSYS;
-       }
+
+       msg.addr = client->addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.flags |= I2C_M_RD;
+       msg.len = count;
+       msg.buf = buf;
+
+       ret = i2c_transfer(adap, &msg, 1);
+
+       /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+          transmitted, else error code. */
+       return (ret == 1) ? count : ret;
 }
 
 
@@ -742,18 +717,6 @@ int i2c_probe(struct i2c_adapter *adapter,
                                found = 1;
                        }
                }
-               for (i = 0;
-                    !found && (address_data->ignore_range[i] != I2C_CLIENT_END);
-                    i += 3) {
-                       if (((adap_id == address_data->ignore_range[i]) ||
-                           ((address_data->ignore_range[i]==ANY_I2C_BUS))) &&
-                           (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", adap_id,addr);
-                               found = 1;
-                       }
-               }
                if (found) 
                        continue;
 
@@ -769,17 +732,6 @@ int i2c_probe(struct i2c_adapter *adapter,
                        }
                }
 
-               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])) {
-                               found = 1;
-                               dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, "
-                                       "addr %04x\n", adap_id,addr);
-                       }
-               }
-
                for (i = 0;
                     !found && (address_data->probe[i] != I2C_CLIENT_END);
                     i += 2) {
@@ -791,18 +743,6 @@ int i2c_probe(struct i2c_adapter *adapter,
                                        "addr %04x\n", adap_id,addr);
                        }
                }
-               for (i = 0;
-                    !found && (address_data->probe_range[i] != I2C_CLIENT_END);
-                    i += 3) {
-                       if (((adap_id == address_data->probe_range[i]) ||
-                          (address_data->probe_range[i] == ANY_I2C_BUS)) &&
-                          (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", adap_id,addr);
-                       }
-               }
                if (!found) 
                        continue;
 
index 86c4d0149e825a1c560bc58008faee5390b8b8be..bc5d557e5dd93063ba7d6a18d2abde2569e482cd 100644 (file)
@@ -29,7 +29,6 @@
 /* The devfs code is contributed by Philipp Matthias Hahn 
    <pmhahn@titan.lahn.de> */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -214,7 +213,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
                                   sizeof(rdwr_arg)))
                        return -EFAULT;
 
-               /* Put an arbritrary limit on the number of messages that can
+               /* Put an arbitrary limit on the number of messages that can
                 * be sent at once */
                if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
                        return -EINVAL;
index 3ac0a535b4aa2a961bfbbbe4a4b133b294880cef..0273f124a4f723bafa7889a9bb36fc10b56a14a9 100644 (file)
@@ -672,8 +672,8 @@ config BLK_DEV_SVWKS
          chipsets.
 
 config BLK_DEV_SGIIOC4
-       tristate "Silicon Graphics IOC4 chipset support"
-       depends on IA64_SGI_SN2 || IA64_GENERIC
+       tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
+       depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
        help
          This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
          chipset, which has one channel and can support two devices.
index 4651a22bf12e96ee0789f456b97348eb8f4029c7..af526b671c4e1f7ee0d9b274b5f2d90603fe7637 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
-#include <linux/ioc4_common.h>
+#include <linux/ioc4.h>
 #include <asm/io.h>
 
 #include <linux/ide.h>
@@ -715,14 +715,34 @@ static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
 };
 
 int
-ioc4_ide_attach_one(struct pci_dev *dev, const struct pci_device_id *id)
+ioc4_ide_attach_one(struct ioc4_driver_data *idd)
 {
-       return pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
+       return pci_init_sgiioc4(idd->idd_pdev,
+                               &sgiioc4_chipsets[idd->idd_pci_id->driver_data]);
 }
 
+static struct ioc4_submodule ioc4_ide_submodule = {
+       .is_name = "IOC4_ide",
+       .is_owner = THIS_MODULE,
+       .is_probe = ioc4_ide_attach_one,
+/*     .is_remove = ioc4_ide_remove_one,       */
+};
+
+static int __devinit
+ioc4_ide_init(void)
+{
+       return ioc4_register_submodule(&ioc4_ide_submodule);
+}
+
+static void __devexit
+ioc4_ide_exit(void)
+{
+       ioc4_unregister_submodule(&ioc4_ide_submodule);
+}
+
+module_init(ioc4_ide_init);
+module_exit(ioc4_ide_exit);
 
 MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
 MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ioc4_ide_attach_one);
index 9b8ff396e6f82d58740e151729cd8cdb706973b7..e152d0fa0cdd25d4d4ac4de364eaf80b9502a0cc 100644 (file)
@@ -134,7 +134,7 @@ static int gameport_measure_speed(struct gameport *gameport)
        }
 
        gameport_close(gameport);
-       return (cpu_data[_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
+       return (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
 
 #else
 
index 0bdb47f08c2afa97d73d71885e70ff6dca0e1769..61400f04015e3cf98ace62a085e55f996b885f90 100644 (file)
 static int                     do_probe( struct i2c_adapter *adapter, int addr, int kind);
 
 /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
-static unsigned short          normal_i2c[] = { 0x49, 0x2c, I2C_CLIENT_END };
-static unsigned short          normal_i2c_range[] = { 0x48, 0x4f, 0x2c, 0x2f, I2C_CLIENT_END };
+static unsigned short          normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+                                                0x4c, 0x4d, 0x4e, 0x4f,
+                                                0x2c, 0x2d, 0x2e, 0x2f,
+                                                I2C_CLIENT_END };
 
 I2C_CLIENT_INSMOD;
 
index 90de9c146a5f583b683435df81f78907957687ca..d3efedf6a6ad8292d77bc3d5b0e70adff12ad3de 100644 (file)
@@ -7,6 +7,7 @@ dm-mod-objs     := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
 dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
 dm-snapshot-objs := dm-snap.o dm-exception-store.o
 dm-mirror-objs := dm-log.o dm-raid1.o
+md-mod-objs     := md.o bitmap.o
 raid6-objs     := raid6main.o raid6algos.o raid6recov.o raid6tables.o \
                   raid6int1.o raid6int2.o raid6int4.o \
                   raid6int8.o raid6int16.o raid6int32.o \
@@ -28,7 +29,7 @@ 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_MD)       += md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)       += dm-mod.o
 obj-$(CONFIG_DM_CRYPT)         += dm-crypt.o
 obj-$(CONFIG_DM_MULTIPATH)     += dm-multipath.o dm-round-robin.o
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
new file mode 100644 (file)
index 0000000..95980ad
--- /dev/null
@@ -0,0 +1,1586 @@
+/*
+ * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
+ *
+ * bitmap_create  - sets up the bitmap structure
+ * bitmap_destroy - destroys the bitmap structure
+ *
+ * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.:
+ * - added disk storage for bitmap
+ * - changes to allow various bitmap chunk sizes
+ * - added bitmap daemon (to asynchronously clear bitmap bits from disk)
+ */
+
+/*
+ * Still to do:
+ *
+ * flush after percent set rather than just time based. (maybe both).
+ * wait if count gets too high, wake when it drops to half.
+ * allow bitmap to be mirrored with superblock (before or after...)
+ * allow hot-add to re-instate a current device.
+ * allow hot-add of bitmap after quiessing device
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/buffer_head.h>
+#include <linux/raid/md.h>
+#include <linux/raid/bitmap.h>
+
+/* debug macros */
+
+#define DEBUG 0
+
+#if DEBUG
+/* these are for debugging purposes only! */
+
+/* define one and only one of these */
+#define INJECT_FAULTS_1 0 /* cause bitmap_alloc_page to fail always */
+#define INJECT_FAULTS_2 0 /* cause bitmap file to be kicked when first bit set*/
+#define INJECT_FAULTS_3 0 /* treat bitmap file as kicked at init time */
+#define INJECT_FAULTS_4 0 /* undef */
+#define INJECT_FAULTS_5 0 /* undef */
+#define INJECT_FAULTS_6 0
+
+/* if these are defined, the driver will fail! debug only */
+#define INJECT_FATAL_FAULT_1 0 /* fail kmalloc, causing bitmap_create to fail */
+#define INJECT_FATAL_FAULT_2 0 /* undef */
+#define INJECT_FATAL_FAULT_3 0 /* undef */
+#endif
+
+//#define DPRINTK PRINTK /* set this NULL to avoid verbose debug output */
+#define DPRINTK(x...) do { } while(0)
+
+#ifndef PRINTK
+#  if DEBUG > 0
+#    define PRINTK(x...) printk(KERN_DEBUG x)
+#  else
+#    define PRINTK(x...)
+#  endif
+#endif
+
+static inline char * bmname(struct bitmap *bitmap)
+{
+       return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
+}
+
+
+/*
+ * test if the bitmap is active
+ */
+int bitmap_active(struct bitmap *bitmap)
+{
+       unsigned long flags;
+       int res = 0;
+
+       if (!bitmap)
+               return res;
+       spin_lock_irqsave(&bitmap->lock, flags);
+       res = bitmap->flags & BITMAP_ACTIVE;
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+       return res;
+}
+
+#define WRITE_POOL_SIZE 256
+/* mempool for queueing pending writes on the bitmap file */
+static void *write_pool_alloc(unsigned int gfp_flags, void *data)
+{
+       return kmalloc(sizeof(struct page_list), gfp_flags);
+}
+
+static void write_pool_free(void *ptr, void *data)
+{
+       kfree(ptr);
+}
+
+/*
+ * just a placeholder - calls kmalloc for bitmap pages
+ */
+static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
+{
+       unsigned char *page;
+
+#if INJECT_FAULTS_1
+       page = NULL;
+#else
+       page = kmalloc(PAGE_SIZE, GFP_NOIO);
+#endif
+       if (!page)
+               printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
+       else
+               PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
+                       bmname(bitmap), page);
+       return page;
+}
+
+/*
+ * for now just a placeholder -- just calls kfree for bitmap pages
+ */
+static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
+{
+       PRINTK("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
+       kfree(page);
+}
+
+/*
+ * check a page and, if necessary, allocate it (or hijack it if the alloc fails)
+ *
+ * 1) check to see if this page is allocated, if it's not then try to alloc
+ * 2) if the alloc fails, set the page's hijacked flag so we'll use the
+ *    page pointer directly as a counter
+ *
+ * if we find our page, we increment the page's refcount so that it stays
+ * allocated while we're using it
+ */
+static int bitmap_checkpage(struct bitmap *bitmap, unsigned long page, int create)
+{
+       unsigned char *mappage;
+
+       if (page >= bitmap->pages) {
+               printk(KERN_ALERT
+                       "%s: invalid bitmap page request: %lu (> %lu)\n",
+                       bmname(bitmap), page, bitmap->pages-1);
+               return -EINVAL;
+       }
+
+
+       if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */
+               return 0;
+
+       if (bitmap->bp[page].map) /* page is already allocated, just return */
+               return 0;
+
+       if (!create)
+               return -ENOENT;
+
+       spin_unlock_irq(&bitmap->lock);
+
+       /* this page has not been allocated yet */
+
+       if ((mappage = bitmap_alloc_page(bitmap)) == NULL) {
+               PRINTK("%s: bitmap map page allocation failed, hijacking\n",
+                       bmname(bitmap));
+               /* failed - set the hijacked flag so that we can use the
+                * pointer as a counter */
+               spin_lock_irq(&bitmap->lock);
+               if (!bitmap->bp[page].map)
+                       bitmap->bp[page].hijacked = 1;
+               goto out;
+       }
+
+       /* got a page */
+
+       spin_lock_irq(&bitmap->lock);
+
+       /* recheck the page */
+
+       if (bitmap->bp[page].map || bitmap->bp[page].hijacked) {
+               /* somebody beat us to getting the page */
+               bitmap_free_page(bitmap, mappage);
+               return 0;
+       }
+
+       /* no page was in place and we have one, so install it */
+
+       memset(mappage, 0, PAGE_SIZE);
+       bitmap->bp[page].map = mappage;
+       bitmap->missing_pages--;
+out:
+       return 0;
+}
+
+
+/* if page is completely empty, put it back on the free list, or dealloc it */
+/* if page was hijacked, unmark the flag so it might get alloced next time */
+/* Note: lock should be held when calling this */
+static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
+{
+       char *ptr;
+
+       if (bitmap->bp[page].count) /* page is still busy */
+               return;
+
+       /* page is no longer in use, it can be released */
+
+       if (bitmap->bp[page].hijacked) { /* page was hijacked, undo this now */
+               bitmap->bp[page].hijacked = 0;
+               bitmap->bp[page].map = NULL;
+               return;
+       }
+
+       /* normal case, free the page */
+
+#if 0
+/* actually ... let's not.  We will probably need the page again exactly when
+ * memory is tight and we are flusing to disk
+ */
+       return;
+#else
+       ptr = bitmap->bp[page].map;
+       bitmap->bp[page].map = NULL;
+       bitmap->missing_pages++;
+       bitmap_free_page(bitmap, ptr);
+       return;
+#endif
+}
+
+
+/*
+ * bitmap file handling - read and write the bitmap file and its superblock
+ */
+
+/* copy the pathname of a file to a buffer */
+char *file_path(struct file *file, char *buf, int count)
+{
+       struct dentry *d;
+       struct vfsmount *v;
+
+       if (!buf)
+               return NULL;
+
+       d = file->f_dentry;
+       v = file->f_vfsmnt;
+
+       buf = d_path(d, v, buf, count);
+
+       return IS_ERR(buf) ? NULL : buf;
+}
+
+/*
+ * basic page I/O operations
+ */
+
+/* IO operations when bitmap is stored near all superblocks */
+static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index)
+{
+       /* choose a good rdev and read the page from there */
+
+       mdk_rdev_t *rdev;
+       struct list_head *tmp;
+       struct page *page = alloc_page(GFP_KERNEL);
+       sector_t target;
+
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+       do {
+               ITERATE_RDEV(mddev, rdev, tmp)
+                       if (rdev->in_sync && !rdev->faulty)
+                               goto found;
+               return ERR_PTR(-EIO);
+
+       found:
+               target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
+
+       } while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
+
+       page->index = index;
+       return page;
+}
+
+static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
+{
+       mdk_rdev_t *rdev;
+       struct list_head *tmp;
+
+       ITERATE_RDEV(mddev, rdev, tmp)
+               if (rdev->in_sync && !rdev->faulty)
+                       md_super_write(mddev, rdev,
+                                      (rdev->sb_offset<<1) + offset
+                                      + page->index * (PAGE_SIZE/512),
+                                      PAGE_SIZE,
+                                      page);
+
+       if (wait)
+               wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+       return 0;
+}
+
+/*
+ * write out a page to a file
+ */
+static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+{
+       int ret = -ENOMEM;
+
+       if (bitmap->file == NULL)
+               return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+
+       if (wait)
+               lock_page(page);
+       else {
+               if (TestSetPageLocked(page))
+                       return -EAGAIN; /* already locked */
+               if (PageWriteback(page)) {
+                       unlock_page(page);
+                       return -EAGAIN;
+               }
+       }
+
+       ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
+       if (!ret)
+               ret = page->mapping->a_ops->commit_write(NULL, page, 0,
+                       PAGE_SIZE);
+       if (ret) {
+               unlock_page(page);
+               return ret;
+       }
+
+       set_page_dirty(page); /* force it to be written out */
+
+       if (!wait) {
+               /* add to list to be waited for by daemon */
+               struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
+               item->page = page;
+               page_cache_get(page);
+               spin_lock(&bitmap->write_lock);
+               list_add(&item->list, &bitmap->complete_pages);
+               spin_unlock(&bitmap->write_lock);
+               md_wakeup_thread(bitmap->writeback_daemon);
+       }
+       return write_one_page(page, wait);
+}
+
+/* read a page from a file, pinning it into cache, and return bytes_read */
+static struct page *read_page(struct file *file, unsigned long index,
+                                       unsigned long *bytes_read)
+{
+       struct inode *inode = file->f_mapping->host;
+       struct page *page = NULL;
+       loff_t isize = i_size_read(inode);
+       unsigned long end_index = isize >> PAGE_CACHE_SHIFT;
+
+       PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE,
+                       (unsigned long long)index << PAGE_CACHE_SHIFT);
+
+       page = read_cache_page(inode->i_mapping, index,
+                       (filler_t *)inode->i_mapping->a_ops->readpage, file);
+       if (IS_ERR(page))
+               goto out;
+       wait_on_page_locked(page);
+       if (!PageUptodate(page) || PageError(page)) {
+               page_cache_release(page);
+               page = ERR_PTR(-EIO);
+               goto out;
+       }
+
+       if (index > end_index) /* we have read beyond EOF */
+               *bytes_read = 0;
+       else if (index == end_index) /* possible short read */
+               *bytes_read = isize & ~PAGE_CACHE_MASK;
+       else
+               *bytes_read = PAGE_CACHE_SIZE; /* got a full page */
+out:
+       if (IS_ERR(page))
+               printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
+                       (int)PAGE_CACHE_SIZE,
+                       (unsigned long long)index << PAGE_CACHE_SHIFT,
+                       PTR_ERR(page));
+       return page;
+}
+
+/*
+ * bitmap file superblock operations
+ */
+
+/* update the event counter and sync the superblock to disk */
+int bitmap_update_sb(struct bitmap *bitmap)
+{
+       bitmap_super_t *sb;
+       unsigned long flags;
+
+       if (!bitmap || !bitmap->mddev) /* no bitmap for this array */
+               return 0;
+       spin_lock_irqsave(&bitmap->lock, flags);
+       if (!bitmap->sb_page) { /* no superblock */
+               spin_unlock_irqrestore(&bitmap->lock, flags);
+               return 0;
+       }
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+       sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+       sb->events = cpu_to_le64(bitmap->mddev->events);
+       if (!bitmap->mddev->degraded)
+               sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+       kunmap(bitmap->sb_page);
+       return write_page(bitmap, bitmap->sb_page, 1);
+}
+
+/* print out the bitmap file superblock */
+void bitmap_print_sb(struct bitmap *bitmap)
+{
+       bitmap_super_t *sb;
+
+       if (!bitmap || !bitmap->sb_page)
+               return;
+       sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+       printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
+       printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));
+       printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));
+       printk(KERN_DEBUG "          uuid: %08x.%08x.%08x.%08x\n",
+                                       *(__u32 *)(sb->uuid+0),
+                                       *(__u32 *)(sb->uuid+4),
+                                       *(__u32 *)(sb->uuid+8),
+                                       *(__u32 *)(sb->uuid+12));
+       printk(KERN_DEBUG "        events: %llu\n",
+                       (unsigned long long) le64_to_cpu(sb->events));
+       printk(KERN_DEBUG "events cleared: %llu\n",
+                       (unsigned long long) le64_to_cpu(sb->events_cleared));
+       printk(KERN_DEBUG "         state: %08x\n", le32_to_cpu(sb->state));
+       printk(KERN_DEBUG "     chunksize: %d B\n", le32_to_cpu(sb->chunksize));
+       printk(KERN_DEBUG "  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
+       printk(KERN_DEBUG "     sync size: %llu KB\n",
+                       (unsigned long long)le64_to_cpu(sb->sync_size)/2);
+       kunmap(bitmap->sb_page);
+}
+
+/* read the superblock from the bitmap file and initialize some bitmap fields */
+static int bitmap_read_sb(struct bitmap *bitmap)
+{
+       char *reason = NULL;
+       bitmap_super_t *sb;
+       unsigned long chunksize, daemon_sleep;
+       unsigned long bytes_read;
+       unsigned long long events;
+       int err = -EINVAL;
+
+       /* page 0 is the superblock, read it... */
+       if (bitmap->file)
+               bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read);
+       else {
+               bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
+               bytes_read = PAGE_SIZE;
+       }
+       if (IS_ERR(bitmap->sb_page)) {
+               err = PTR_ERR(bitmap->sb_page);
+               bitmap->sb_page = NULL;
+               return err;
+       }
+
+       sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+
+       if (bytes_read < sizeof(*sb)) { /* short read */
+               printk(KERN_INFO "%s: bitmap file superblock truncated\n",
+                       bmname(bitmap));
+               err = -ENOSPC;
+               goto out;
+       }
+
+       chunksize = le32_to_cpu(sb->chunksize);
+       daemon_sleep = le32_to_cpu(sb->daemon_sleep);
+
+       /* verify that the bitmap-specific fields are valid */
+       if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
+               reason = "bad magic";
+       else if (sb->version != cpu_to_le32(BITMAP_MAJOR))
+               reason = "unrecognized superblock version";
+       else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
+               reason = "bitmap chunksize out of range (512B - 4MB)";
+       else if ((1 << ffz(~chunksize)) != chunksize)
+               reason = "bitmap chunksize not a power of 2";
+       else if (daemon_sleep < 1 || daemon_sleep > 15)
+               reason = "daemon sleep period out of range";
+       if (reason) {
+               printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
+                       bmname(bitmap), reason);
+               goto out;
+       }
+
+       /* keep the array size field of the bitmap superblock up to date */
+       sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);
+
+       if (!bitmap->mddev->persistent)
+               goto success;
+
+       /*
+        * if we have a persistent array superblock, compare the
+        * bitmap's UUID and event counter to the mddev's
+        */
+       if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) {
+               printk(KERN_INFO "%s: bitmap superblock UUID mismatch\n",
+                       bmname(bitmap));
+               goto out;
+       }
+       events = le64_to_cpu(sb->events);
+       if (events < bitmap->mddev->events) {
+               printk(KERN_INFO "%s: bitmap file is out of date (%llu < %llu) "
+                       "-- forcing full recovery\n", bmname(bitmap), events,
+                       (unsigned long long) bitmap->mddev->events);
+               sb->state |= BITMAP_STALE;
+       }
+success:
+       /* assign fields using values from superblock */
+       bitmap->chunksize = chunksize;
+       bitmap->daemon_sleep = daemon_sleep;
+       bitmap->flags |= sb->state;
+       bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+       err = 0;
+out:
+       kunmap(bitmap->sb_page);
+       if (err)
+               bitmap_print_sb(bitmap);
+       return err;
+}
+
+enum bitmap_mask_op {
+       MASK_SET,
+       MASK_UNSET
+};
+
+/* record the state of the bitmap in the superblock */
+static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
+                               enum bitmap_mask_op op)
+{
+       bitmap_super_t *sb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bitmap->lock, flags);
+       if (!bitmap || !bitmap->sb_page) { /* can't set the state */
+               spin_unlock_irqrestore(&bitmap->lock, flags);
+               return;
+       }
+       page_cache_get(bitmap->sb_page);
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+       sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+       switch (op) {
+               case MASK_SET: sb->state |= bits;
+                               break;
+               case MASK_UNSET: sb->state &= ~bits;
+                               break;
+               default: BUG();
+       }
+       kunmap(bitmap->sb_page);
+       page_cache_release(bitmap->sb_page);
+}
+
+/*
+ * general bitmap file operations
+ */
+
+/* calculate the index of the page that contains this bit */
+static inline unsigned long file_page_index(unsigned long chunk)
+{
+       return CHUNK_BIT_OFFSET(chunk) >> PAGE_BIT_SHIFT;
+}
+
+/* calculate the (bit) offset of this bit within a page */
+static inline unsigned long file_page_offset(unsigned long chunk)
+{
+       return CHUNK_BIT_OFFSET(chunk) & (PAGE_BITS - 1);
+}
+
+/*
+ * return a pointer to the page in the filemap that contains the given bit
+ *
+ * this lookup is complicated by the fact that the bitmap sb might be exactly
+ * 1 page (e.g., x86) or less than 1 page -- so the bitmap might start on page
+ * 0 or page 1
+ */
+static inline struct page *filemap_get_page(struct bitmap *bitmap,
+                                       unsigned long chunk)
+{
+       return bitmap->filemap[file_page_index(chunk) - file_page_index(0)];
+}
+
+
+static void bitmap_file_unmap(struct bitmap *bitmap)
+{
+       struct page **map, *sb_page;
+       unsigned long *attr;
+       int pages;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bitmap->lock, flags);
+       map = bitmap->filemap;
+       bitmap->filemap = NULL;
+       attr = bitmap->filemap_attr;
+       bitmap->filemap_attr = NULL;
+       pages = bitmap->file_pages;
+       bitmap->file_pages = 0;
+       sb_page = bitmap->sb_page;
+       bitmap->sb_page = NULL;
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+
+       while (pages--)
+               if (map[pages]->index != 0) /* 0 is sb_page, release it below */
+                       page_cache_release(map[pages]);
+       kfree(map);
+       kfree(attr);
+
+       if (sb_page)
+               page_cache_release(sb_page);
+}
+
+static void bitmap_stop_daemons(struct bitmap *bitmap);
+
+/* dequeue the next item in a page list -- don't call from irq context */
+static struct page_list *dequeue_page(struct bitmap *bitmap)
+{
+       struct page_list *item = NULL;
+       struct list_head *head = &bitmap->complete_pages;
+
+       spin_lock(&bitmap->write_lock);
+       if (list_empty(head))
+               goto out;
+       item = list_entry(head->prev, struct page_list, list);
+       list_del(head->prev);
+out:
+       spin_unlock(&bitmap->write_lock);
+       return item;
+}
+
+static void drain_write_queues(struct bitmap *bitmap)
+{
+       struct page_list *item;
+
+       while ((item = dequeue_page(bitmap))) {
+               /* don't bother to wait */
+               page_cache_release(item->page);
+               mempool_free(item, bitmap->write_pool);
+       }
+
+       wake_up(&bitmap->write_wait);
+}
+
+static void bitmap_file_put(struct bitmap *bitmap)
+{
+       struct file *file;
+       struct inode *inode;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bitmap->lock, flags);
+       file = bitmap->file;
+       bitmap->file = NULL;
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+
+       bitmap_stop_daemons(bitmap);
+
+       drain_write_queues(bitmap);
+
+       bitmap_file_unmap(bitmap);
+
+       if (file) {
+               inode = file->f_mapping->host;
+               spin_lock(&inode->i_lock);
+               atomic_set(&inode->i_writecount, 1); /* allow writes again */
+               spin_unlock(&inode->i_lock);
+               fput(file);
+       }
+}
+
+
+/*
+ * bitmap_file_kick - if an error occurs while manipulating the bitmap file
+ * then it is no longer reliable, so we stop using it and we mark the file
+ * as failed in the superblock
+ */
+static void bitmap_file_kick(struct bitmap *bitmap)
+{
+       char *path, *ptr = NULL;
+
+       bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
+       bitmap_update_sb(bitmap);
+
+       if (bitmap->file) {
+               path = kmalloc(PAGE_SIZE, GFP_KERNEL);
+               if (path)
+                       ptr = file_path(bitmap->file, path, PAGE_SIZE);
+
+               printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
+                      bmname(bitmap), ptr ? ptr : "");
+
+               kfree(path);
+       }
+
+       bitmap_file_put(bitmap);
+
+       return;
+}
+
+enum bitmap_page_attr {
+       BITMAP_PAGE_DIRTY = 1, // there are set bits that need to be synced
+       BITMAP_PAGE_CLEAN = 2, // there are bits that might need to be cleared
+       BITMAP_PAGE_NEEDWRITE=4, // there are cleared bits that need to be synced
+};
+
+static inline void set_page_attr(struct bitmap *bitmap, struct page *page,
+                               enum bitmap_page_attr attr)
+{
+       bitmap->filemap_attr[page->index] |= attr;
+}
+
+static inline void clear_page_attr(struct bitmap *bitmap, struct page *page,
+                               enum bitmap_page_attr attr)
+{
+       bitmap->filemap_attr[page->index] &= ~attr;
+}
+
+static inline unsigned long get_page_attr(struct bitmap *bitmap, struct page *page)
+{
+       return bitmap->filemap_attr[page->index];
+}
+
+/*
+ * bitmap_file_set_bit -- called before performing a write to the md device
+ * to set (and eventually sync) a particular bit in the bitmap file
+ *
+ * we set the bit immediately, then we record the page number so that
+ * when an unplug occurs, we can flush the dirty pages out to disk
+ */
+static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
+{
+       unsigned long bit;
+       struct page *page;
+       void *kaddr;
+       unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
+
+       if (!bitmap->filemap) {
+               return;
+       }
+
+       page = filemap_get_page(bitmap, chunk);
+       bit = file_page_offset(chunk);
+
+
+       /* make sure the page stays cached until it gets written out */
+       if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY))
+               page_cache_get(page);
+
+       /* set the bit */
+       kaddr = kmap_atomic(page, KM_USER0);
+       set_bit(bit, kaddr);
+       kunmap_atomic(kaddr, KM_USER0);
+       PRINTK("set file bit %lu page %lu\n", bit, page->index);
+
+       /* record page number so it gets flushed to disk when unplug occurs */
+       set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
+
+}
+
+/* this gets called when the md device is ready to unplug its underlying
+ * (slave) device queues -- before we let any writes go down, we need to
+ * sync the dirty pages of the bitmap file to disk */
+int bitmap_unplug(struct bitmap *bitmap)
+{
+       unsigned long i, attr, flags;
+       struct page *page;
+       int wait = 0;
+       int err;
+
+       if (!bitmap)
+               return 0;
+
+       /* look at each page to see if there are any set bits that need to be
+        * flushed out to disk */
+       for (i = 0; i < bitmap->file_pages; i++) {
+               spin_lock_irqsave(&bitmap->lock, flags);
+               if (!bitmap->filemap) {
+                       spin_unlock_irqrestore(&bitmap->lock, flags);
+                       return 0;
+               }
+               page = bitmap->filemap[i];
+               attr = get_page_attr(bitmap, page);
+               clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
+               clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+               if ((attr & BITMAP_PAGE_DIRTY))
+                       wait = 1;
+               spin_unlock_irqrestore(&bitmap->lock, flags);
+
+               if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE)) {
+                       err = write_page(bitmap, page, 0);
+                       if (err == -EAGAIN) {
+                               if (attr & BITMAP_PAGE_DIRTY)
+                                       err = write_page(bitmap, page, 1);
+                               else
+                                       err = 0;
+                       }
+                       if (err)
+                               return 1;
+               }
+       }
+       if (wait) { /* if any writes were performed, we need to wait on them */
+               if (bitmap->file) {
+                       spin_lock_irq(&bitmap->write_lock);
+                       wait_event_lock_irq(bitmap->write_wait,
+                                           list_empty(&bitmap->complete_pages), bitmap->write_lock,
+                                           wake_up_process(bitmap->writeback_daemon->tsk));
+                       spin_unlock_irq(&bitmap->write_lock);
+               } else
+                       wait_event(bitmap->mddev->sb_wait,
+                                  atomic_read(&bitmap->mddev->pending_writes)==0);
+       }
+       return 0;
+}
+
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+       unsigned long sectors, int in_sync);
+/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
+ * the in-memory bitmap from the on-disk bitmap -- also, sets up the
+ * memory mapping of the bitmap file
+ * Special cases:
+ *   if there's no bitmap file, or if the bitmap file had been
+ *   previously kicked from the array, we mark all the bits as
+ *   1's in order to cause a full resync.
+ */
+static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+{
+       unsigned long i, chunks, index, oldindex, bit;
+       struct page *page = NULL, *oldpage = NULL;
+       unsigned long num_pages, bit_cnt = 0;
+       struct file *file;
+       unsigned long bytes, offset, dummy;
+       int outofdate;
+       int ret = -ENOSPC;
+
+       chunks = bitmap->chunks;
+       file = bitmap->file;
+
+       BUG_ON(!file && !bitmap->offset);
+
+#if INJECT_FAULTS_3
+       outofdate = 1;
+#else
+       outofdate = bitmap->flags & BITMAP_STALE;
+#endif
+       if (outofdate)
+               printk(KERN_INFO "%s: bitmap file is out of date, doing full "
+                       "recovery\n", bmname(bitmap));
+
+       bytes = (chunks + 7) / 8;
+
+       num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE;
+
+       if (file && i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
+               printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
+                       bmname(bitmap),
+                       (unsigned long) i_size_read(file->f_mapping->host),
+                       bytes + sizeof(bitmap_super_t));
+               goto out;
+       }
+
+       ret = -ENOMEM;
+
+       bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
+       if (!bitmap->filemap)
+               goto out;
+
+       bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
+       if (!bitmap->filemap_attr)
+               goto out;
+
+       memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
+
+       oldindex = ~0L;
+
+       for (i = 0; i < chunks; i++) {
+               index = file_page_index(i);
+               bit = file_page_offset(i);
+               if (index != oldindex) { /* this is a new page, read it in */
+                       /* unmap the old page, we're done with it */
+                       if (oldpage != NULL)
+                               kunmap(oldpage);
+                       if (index == 0) {
+                               /*
+                                * if we're here then the superblock page
+                                * contains some bits (PAGE_SIZE != sizeof sb)
+                                * we've already read it in, so just use it
+                                */
+                               page = bitmap->sb_page;
+                               offset = sizeof(bitmap_super_t);
+                       } else if (file) {
+                               page = read_page(file, index, &dummy);
+                               offset = 0;
+                       } else {
+                               page = read_sb_page(bitmap->mddev, bitmap->offset, index);
+                               offset = 0;
+                       }
+                       if (IS_ERR(page)) { /* read error */
+                               ret = PTR_ERR(page);
+                               goto out;
+                       }
+
+                       oldindex = index;
+                       oldpage = page;
+                       kmap(page);
+
+                       if (outofdate) {
+                               /*
+                                * if bitmap is out of date, dirty the
+                                * whole page and write it out
+                                */
+                               memset(page_address(page) + offset, 0xff,
+                                       PAGE_SIZE - offset);
+                               ret = write_page(bitmap, page, 1);
+                               if (ret) {
+                                       kunmap(page);
+                                       /* release, page not in filemap yet */
+                                       page_cache_release(page);
+                                       goto out;
+                               }
+                       }
+
+                       bitmap->filemap[bitmap->file_pages++] = page;
+               }
+               if (test_bit(bit, page_address(page))) {
+                       /* if the disk bit is set, set the memory bit */
+                       bitmap_set_memory_bits(bitmap,
+                                       i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
+                       bit_cnt++;
+               }
+       }
+
+       /* everything went OK */
+       ret = 0;
+       bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
+
+       if (page) /* unmap the last page */
+               kunmap(page);
+
+       if (bit_cnt) { /* Kick recovery if any bits were set */
+               set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
+               md_wakeup_thread(bitmap->mddev->thread);
+       }
+
+out:
+       printk(KERN_INFO "%s: bitmap initialized from disk: "
+               "read %lu/%lu pages, set %lu bits, status: %d\n",
+               bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, ret);
+
+       return ret;
+}
+
+void bitmap_write_all(struct bitmap *bitmap)
+{
+       /* We don't actually write all bitmap blocks here,
+        * just flag them as needing to be written
+        */
+
+       unsigned long chunks = bitmap->chunks;
+       unsigned long bytes = (chunks+7)/8 + sizeof(bitmap_super_t);
+       unsigned long num_pages = (bytes + PAGE_SIZE-1) / PAGE_SIZE;
+       while (num_pages--)
+               bitmap->filemap_attr[num_pages] |= BITMAP_PAGE_NEEDWRITE;
+}
+
+
+static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
+{
+       sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
+       unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
+       bitmap->bp[page].count += inc;
+/*
+       if (page == 0) printk("count page 0, offset %llu: %d gives %d\n",
+                             (unsigned long long)offset, inc, bitmap->bp[page].count);
+*/
+       bitmap_checkfree(bitmap, page);
+}
+static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+                                           sector_t offset, int *blocks,
+                                           int create);
+
+/*
+ * bitmap daemon -- periodically wakes up to clean bits and flush pages
+ *                     out to disk
+ */
+
+int bitmap_daemon_work(struct bitmap *bitmap)
+{
+       unsigned long j;
+       unsigned long flags;
+       struct page *page = NULL, *lastpage = NULL;
+       int err = 0;
+       int blocks;
+       int attr;
+
+       if (bitmap == NULL)
+               return 0;
+       if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
+               return 0;
+       bitmap->daemon_lastrun = jiffies;
+
+       for (j = 0; j < bitmap->chunks; j++) {
+               bitmap_counter_t *bmc;
+               spin_lock_irqsave(&bitmap->lock, flags);
+               if (!bitmap->filemap) {
+                       /* error or shutdown */
+                       spin_unlock_irqrestore(&bitmap->lock, flags);
+                       break;
+               }
+
+               page = filemap_get_page(bitmap, j);
+
+               if (page != lastpage) {
+                       /* skip this page unless it's marked as needing cleaning */
+                       if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
+                               if (attr & BITMAP_PAGE_NEEDWRITE) {
+                                       page_cache_get(page);
+                                       clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+                               }
+                               spin_unlock_irqrestore(&bitmap->lock, flags);
+                               if (attr & BITMAP_PAGE_NEEDWRITE) {
+                                       switch (write_page(bitmap, page, 0)) {
+                                       case -EAGAIN:
+                                               set_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+                                               break;
+                                       case 0:
+                                               break;
+                                       default:
+                                               bitmap_file_kick(bitmap);
+                                       }
+                                       page_cache_release(page);
+                               }
+                               continue;
+                       }
+
+                       /* grab the new page, sync and release the old */
+                       page_cache_get(page);
+                       if (lastpage != NULL) {
+                               if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
+                                       clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+                                       spin_unlock_irqrestore(&bitmap->lock, flags);
+                                       err = write_page(bitmap, lastpage, 0);
+                                       if (err == -EAGAIN) {
+                                               err = 0;
+                                               set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+                                       }
+                               } else {
+                                       set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+                                       spin_unlock_irqrestore(&bitmap->lock, flags);
+                               }
+                               kunmap(lastpage);
+                               page_cache_release(lastpage);
+                               if (err)
+                                       bitmap_file_kick(bitmap);
+                       } else
+                               spin_unlock_irqrestore(&bitmap->lock, flags);
+                       lastpage = page;
+                       kmap(page);
+/*
+                       printk("bitmap clean at page %lu\n", j);
+*/
+                       spin_lock_irqsave(&bitmap->lock, flags);
+                       clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+               }
+               bmc = bitmap_get_counter(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
+                                       &blocks, 0);
+               if (bmc) {
+/*
+  if (j < 100) printk("bitmap: j=%lu, *bmc = 0x%x\n", j, *bmc);
+*/
+                       if (*bmc == 2) {
+                               *bmc=1; /* maybe clear the bit next time */
+                               set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+                       } else if (*bmc == 1) {
+                               /* we can clear the bit */
+                               *bmc = 0;
+                               bitmap_count_page(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
+                                                 -1);
+
+                               /* clear the bit */
+                               clear_bit(file_page_offset(j), page_address(page));
+                       }
+               }
+               spin_unlock_irqrestore(&bitmap->lock, flags);
+       }
+
+       /* now sync the final page */
+       if (lastpage != NULL) {
+               kunmap(lastpage);
+               spin_lock_irqsave(&bitmap->lock, flags);
+               if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
+                       clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+                       spin_unlock_irqrestore(&bitmap->lock, flags);
+                       err = write_page(bitmap, lastpage, 0);
+                       if (err == -EAGAIN) {
+                               set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+                               err = 0;
+                       }
+               } else {
+                       set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+                       spin_unlock_irqrestore(&bitmap->lock, flags);
+               }
+
+               page_cache_release(lastpage);
+       }
+
+       return err;
+}
+
+static void daemon_exit(struct bitmap *bitmap, mdk_thread_t **daemon)
+{
+       mdk_thread_t *dmn;
+       unsigned long flags;
+
+       /* if no one is waiting on us, we'll free the md thread struct
+        * and exit, otherwise we let the waiter clean things up */
+       spin_lock_irqsave(&bitmap->lock, flags);
+       if ((dmn = *daemon)) { /* no one is waiting, cleanup and exit */
+               *daemon = NULL;
+               spin_unlock_irqrestore(&bitmap->lock, flags);
+               kfree(dmn);
+               complete_and_exit(NULL, 0); /* do_exit not exported */
+       }
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+}
+
+static void bitmap_writeback_daemon(mddev_t *mddev)
+{
+       struct bitmap *bitmap = mddev->bitmap;
+       struct page *page;
+       struct page_list *item;
+       int err = 0;
+
+       if (signal_pending(current)) {
+               printk(KERN_INFO
+                      "%s: bitmap writeback daemon got signal, exiting...\n",
+                      bmname(bitmap));
+               err = -EINTR;
+               goto out;
+       }
+
+       PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
+       /* wait on bitmap page writebacks */
+       while ((item = dequeue_page(bitmap))) {
+               page = item->page;
+               mempool_free(item, bitmap->write_pool);
+               PRINTK("wait on page writeback: %p\n", page);
+               wait_on_page_writeback(page);
+               PRINTK("finished page writeback: %p\n", page);
+
+               err = PageError(page);
+               page_cache_release(page);
+               if (err) {
+                       printk(KERN_WARNING "%s: bitmap file writeback "
+                              "failed (page %lu): %d\n",
+                              bmname(bitmap), page->index, err);
+                       bitmap_file_kick(bitmap);
+                       goto out;
+               }
+       }
+ out:
+       wake_up(&bitmap->write_wait);
+       if (err) {
+               printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n",
+                      bmname(bitmap), err);
+               daemon_exit(bitmap, &bitmap->writeback_daemon);
+       }
+}
+
+static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+                               void (*func)(mddev_t *), char *name)
+{
+       mdk_thread_t *daemon;
+       unsigned long flags;
+       char namebuf[32];
+
+       spin_lock_irqsave(&bitmap->lock, flags);
+       *ptr = NULL;
+
+       if (!bitmap->file) /* no need for daemon if there's no backing file */
+               goto out_unlock;
+
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+
+#if INJECT_FATAL_FAULT_2
+       daemon = NULL;
+#else
+       sprintf(namebuf, "%%s_%s", name);
+       daemon = md_register_thread(func, bitmap->mddev, namebuf);
+#endif
+       if (!daemon) {
+               printk(KERN_ERR "%s: failed to start bitmap daemon\n",
+                       bmname(bitmap));
+               return -ECHILD;
+       }
+
+       spin_lock_irqsave(&bitmap->lock, flags);
+       *ptr = daemon;
+
+       md_wakeup_thread(daemon); /* start it running */
+
+       PRINTK("%s: %s daemon (pid %d) started...\n",
+               bmname(bitmap), name, daemon->tsk->pid);
+out_unlock:
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+       return 0;
+}
+
+static int bitmap_start_daemons(struct bitmap *bitmap)
+{
+       int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
+                                       bitmap_writeback_daemon, "bitmap_wb");
+       return err;
+}
+
+static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
+{
+       mdk_thread_t *daemon;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bitmap->lock, flags);
+       daemon = *ptr;
+       *ptr = NULL;
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+       if (daemon)
+               md_unregister_thread(daemon); /* destroy the thread */
+}
+
+static void bitmap_stop_daemons(struct bitmap *bitmap)
+{
+       /* the daemons can't stop themselves... they'll just exit instead... */
+       if (bitmap->writeback_daemon &&
+           current->pid != bitmap->writeback_daemon->tsk->pid)
+               bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
+}
+
+static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+                                           sector_t offset, int *blocks,
+                                           int create)
+{
+       /* If 'create', we might release the lock and reclaim it.
+        * The lock must have been taken with interrupts enabled.
+        * If !create, we don't release the lock.
+        */
+       sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
+       unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
+       unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT;
+       sector_t csize;
+
+       if (bitmap_checkpage(bitmap, page, create) < 0) {
+               csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
+               *blocks = csize - (offset & (csize- 1));
+               return NULL;
+       }
+       /* now locked ... */
+
+       if (bitmap->bp[page].hijacked) { /* hijacked pointer */
+               /* should we use the first or second counter field
+                * of the hijacked pointer? */
+               int hi = (pageoff > PAGE_COUNTER_MASK);
+               csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap) +
+                                         PAGE_COUNTER_SHIFT - 1);
+               *blocks = csize - (offset & (csize- 1));
+               return  &((bitmap_counter_t *)
+                         &bitmap->bp[page].map)[hi];
+       } else { /* page is allocated */
+               csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
+               *blocks = csize - (offset & (csize- 1));
+               return (bitmap_counter_t *)
+                       &(bitmap->bp[page].map[pageoff]);
+       }
+}
+
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
+{
+       if (!bitmap) return 0;
+       while (sectors) {
+               int blocks;
+               bitmap_counter_t *bmc;
+
+               spin_lock_irq(&bitmap->lock);
+               bmc = bitmap_get_counter(bitmap, offset, &blocks, 1);
+               if (!bmc) {
+                       spin_unlock_irq(&bitmap->lock);
+                       return 0;
+               }
+
+               switch(*bmc) {
+               case 0:
+                       bitmap_file_set_bit(bitmap, offset);
+                       bitmap_count_page(bitmap,offset, 1);
+                       blk_plug_device(bitmap->mddev->queue);
+                       /* fall through */
+               case 1:
+                       *bmc = 2;
+               }
+               if ((*bmc & COUNTER_MAX) == COUNTER_MAX) BUG();
+               (*bmc)++;
+
+               spin_unlock_irq(&bitmap->lock);
+
+               offset += blocks;
+               if (sectors > blocks)
+                       sectors -= blocks;
+               else sectors = 0;
+       }
+       return 0;
+}
+
+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+                    int success)
+{
+       if (!bitmap) return;
+       while (sectors) {
+               int blocks;
+               unsigned long flags;
+               bitmap_counter_t *bmc;
+
+               spin_lock_irqsave(&bitmap->lock, flags);
+               bmc = bitmap_get_counter(bitmap, offset, &blocks, 0);
+               if (!bmc) {
+                       spin_unlock_irqrestore(&bitmap->lock, flags);
+                       return;
+               }
+
+               if (!success && ! (*bmc & NEEDED_MASK))
+                       *bmc |= NEEDED_MASK;
+
+               (*bmc)--;
+               if (*bmc <= 2) {
+                       set_page_attr(bitmap,
+                                     filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
+                                     BITMAP_PAGE_CLEAN);
+               }
+               spin_unlock_irqrestore(&bitmap->lock, flags);
+               offset += blocks;
+               if (sectors > blocks)
+                       sectors -= blocks;
+               else sectors = 0;
+       }
+}
+
+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks)
+{
+       bitmap_counter_t *bmc;
+       int rv;
+       if (bitmap == NULL) {/* FIXME or bitmap set as 'failed' */
+               *blocks = 1024;
+               return 1; /* always resync if no bitmap */
+       }
+       spin_lock_irq(&bitmap->lock);
+       bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
+       rv = 0;
+       if (bmc) {
+               /* locked */
+               if (RESYNC(*bmc))
+                       rv = 1;
+               else if (NEEDED(*bmc)) {
+                       rv = 1;
+                       *bmc |= RESYNC_MASK;
+                       *bmc &= ~NEEDED_MASK;
+               }
+       }
+       spin_unlock_irq(&bitmap->lock);
+       return rv;
+}
+
+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted)
+{
+       bitmap_counter_t *bmc;
+       unsigned long flags;
+/*
+       if (offset == 0) printk("bitmap_end_sync 0 (%d)\n", aborted);
+*/     if (bitmap == NULL) {
+               *blocks = 1024;
+               return;
+       }
+       spin_lock_irqsave(&bitmap->lock, flags);
+       bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
+       if (bmc == NULL)
+               goto unlock;
+       /* locked */
+/*
+       if (offset == 0) printk("bitmap_end sync found 0x%x, blocks %d\n", *bmc, *blocks);
+*/
+       if (RESYNC(*bmc)) {
+               *bmc &= ~RESYNC_MASK;
+
+               if (!NEEDED(*bmc) && aborted)
+                       *bmc |= NEEDED_MASK;
+               else {
+                       if (*bmc <= 2) {
+                               set_page_attr(bitmap,
+                                             filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
+                                             BITMAP_PAGE_CLEAN);
+                       }
+               }
+       }
+ unlock:
+       spin_unlock_irqrestore(&bitmap->lock, flags);
+}
+
+void bitmap_close_sync(struct bitmap *bitmap)
+{
+       /* Sync has finished, and any bitmap chunks that weren't synced
+        * properly have been aborted.  It remains to us to clear the
+        * RESYNC bit wherever it is still on
+        */
+       sector_t sector = 0;
+       int blocks;
+       if (!bitmap) return;
+       while (sector < bitmap->mddev->resync_max_sectors) {
+               bitmap_end_sync(bitmap, sector, &blocks, 0);
+/*
+               if (sector < 500) printk("bitmap_close_sync: sec %llu blks %d\n",
+                                        (unsigned long long)sector, blocks);
+*/             sector += blocks;
+       }
+}
+
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+                                  unsigned long sectors, int in_sync)
+{
+       /* For each chunk covered by any of these sectors, set the
+        * counter to 1 and set resync_needed unless in_sync.  They should all
+        * be 0 at this point
+        */
+       while (sectors) {
+               int secs;
+               bitmap_counter_t *bmc;
+               spin_lock_irq(&bitmap->lock);
+               bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+               if (!bmc) {
+                       spin_unlock_irq(&bitmap->lock);
+                       return;
+               }
+               if (! *bmc) {
+                       struct page *page;
+                       *bmc = 1 | (in_sync? 0 : NEEDED_MASK);
+                       bitmap_count_page(bitmap, offset, 1);
+                       page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+                       set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+               }
+               spin_unlock_irq(&bitmap->lock);
+               if (sectors > secs)
+                       sectors -= secs;
+               else
+                       sectors = 0;
+       }
+}
+
+/*
+ * free memory that was allocated
+ */
+void bitmap_destroy(mddev_t *mddev)
+{
+       unsigned long k, pages;
+       struct bitmap_page *bp;
+       struct bitmap *bitmap = mddev->bitmap;
+
+       if (!bitmap) /* there was no bitmap */
+               return;
+
+       mddev->bitmap = NULL; /* disconnect from the md device */
+
+       /* release the bitmap file and kill the daemon */
+       bitmap_file_put(bitmap);
+
+       bp = bitmap->bp;
+       pages = bitmap->pages;
+
+       /* free all allocated memory */
+
+       mempool_destroy(bitmap->write_pool);
+
+       if (bp) /* deallocate the page memory */
+               for (k = 0; k < pages; k++)
+                       if (bp[k].map && !bp[k].hijacked)
+                               kfree(bp[k].map);
+       kfree(bp);
+       kfree(bitmap);
+}
+
+/*
+ * initialize the bitmap structure
+ * if this returns an error, bitmap_destroy must be called to do clean up
+ */
+int bitmap_create(mddev_t *mddev)
+{
+       struct bitmap *bitmap;
+       unsigned long blocks = mddev->resync_max_sectors;
+       unsigned long chunks;
+       unsigned long pages;
+       struct file *file = mddev->bitmap_file;
+       int err;
+
+       BUG_ON(sizeof(bitmap_super_t) != 256);
+
+       if (!file && !mddev->bitmap_offset) /* bitmap disabled, nothing to do */
+               return 0;
+
+       BUG_ON(file && mddev->bitmap_offset);
+
+       bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
+       if (!bitmap)
+               return -ENOMEM;
+
+       memset(bitmap, 0, sizeof(*bitmap));
+
+       spin_lock_init(&bitmap->lock);
+       bitmap->mddev = mddev;
+       mddev->bitmap = bitmap;
+
+       spin_lock_init(&bitmap->write_lock);
+       INIT_LIST_HEAD(&bitmap->complete_pages);
+       init_waitqueue_head(&bitmap->write_wait);
+       bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
+                               write_pool_free, NULL);
+       if (!bitmap->write_pool)
+               return -ENOMEM;
+
+       bitmap->file = file;
+       bitmap->offset = mddev->bitmap_offset;
+       if (file) get_file(file);
+       /* read superblock from bitmap file (this sets bitmap->chunksize) */
+       err = bitmap_read_sb(bitmap);
+       if (err)
+               return err;
+
+       bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
+                                       sizeof(bitmap->chunksize));
+
+       /* now that chunksize and chunkshift are set, we can use these macros */
+       chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) /
+                       CHUNK_BLOCK_RATIO(bitmap);
+       pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;
+
+       BUG_ON(!pages);
+
+       bitmap->chunks = chunks;
+       bitmap->pages = pages;
+       bitmap->missing_pages = pages;
+       bitmap->counter_bits = COUNTER_BITS;
+
+       bitmap->syncchunk = ~0UL;
+
+#if INJECT_FATAL_FAULT_1
+       bitmap->bp = NULL;
+#else
+       bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
+#endif
+       if (!bitmap->bp)
+               return -ENOMEM;
+       memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
+
+       bitmap->flags |= BITMAP_ACTIVE;
+
+       /* now that we have some pages available, initialize the in-memory
+        * bitmap from the on-disk bitmap */
+       err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
+       if (err)
+               return err;
+
+       printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
+               pages, bmname(bitmap));
+
+       /* kick off the bitmap daemons */
+       err = bitmap_start_daemons(bitmap);
+       if (err)
+               return err;
+       return bitmap_update_sb(bitmap);
+}
+
+/* the bitmap API -- for raid personalities */
+EXPORT_SYMBOL(bitmap_startwrite);
+EXPORT_SYMBOL(bitmap_endwrite);
+EXPORT_SYMBOL(bitmap_start_sync);
+EXPORT_SYMBOL(bitmap_end_sync);
+EXPORT_SYMBOL(bitmap_unplug);
+EXPORT_SYMBOL(bitmap_close_sync);
+EXPORT_SYMBOL(bitmap_daemon_work);
index 0dd6c2b5391b754a9aa4bc01e87d97c4c86672b3..d0a4bab220e5e6b5608e50810b3dead70e7be095 100644 (file)
@@ -704,8 +704,7 @@ 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);
+       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);
index b1941b887f46fd6f7f5a991cbb969778ecd31c61..8d740013d74d5eff047d99f02d1f93d7b65218bd 100644 (file)
@@ -217,8 +217,7 @@ static int linear_run (mddev_t *mddev)
        return 0;
 
 out:
-       if (conf)
-               kfree(conf);
+       kfree(conf);
        return 1;
 }
 
index d899204d3743372b68ae04f92f6cefd350db99e5..0c6b5b6baff60ded7fb24d2f71988711d723c604 100644 (file)
@@ -19,6 +19,9 @@
 
      Neil Brown <neilb@cse.unsw.edu.au>.
 
+   - persistent bitmap code
+     Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, 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, or (at your option)
@@ -33,6 +36,7 @@
 #include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/raid/md.h>
+#include <linux/raid/bitmap.h>
 #include <linux/sysctl.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
@@ -40,6 +44,8 @@
 
 #include <linux/init.h>
 
+#include <linux/file.h>
+
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
@@ -189,8 +195,7 @@ static mddev_t * mddev_find(dev_t unit)
                if (mddev->unit == unit) {
                        mddev_get(mddev);
                        spin_unlock(&all_mddevs_lock);
-                       if (new)
-                               kfree(new);
+                       kfree(new);
                        return mddev;
                }
 
@@ -218,6 +223,8 @@ static mddev_t * mddev_find(dev_t unit)
        INIT_LIST_HEAD(&new->all_mddevs);
        init_timer(&new->safemode_timer);
        atomic_set(&new->active, 1);
+       spin_lock_init(&new->write_lock);
+       init_waitqueue_head(&new->sb_wait);
 
        new->queue = blk_alloc_queue(GFP_KERNEL);
        if (!new->queue) {
@@ -320,6 +327,40 @@ static void free_disk_sb(mdk_rdev_t * rdev)
 }
 
 
+static int super_written(struct bio *bio, unsigned int bytes_done, int error)
+{
+       mdk_rdev_t *rdev = bio->bi_private;
+       if (bio->bi_size)
+               return 1;
+
+       if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags))
+               md_error(rdev->mddev, rdev);
+
+       if (atomic_dec_and_test(&rdev->mddev->pending_writes))
+               wake_up(&rdev->mddev->sb_wait);
+       return 0;
+}
+
+void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+                  sector_t sector, int size, struct page *page)
+{
+       /* write first size bytes of page to sector of rdev
+        * Increment mddev->pending_writes before returning
+        * and decrement it on completion, waking up sb_wait
+        * if zero is reached.
+        * If an error occurred, call md_error
+        */
+       struct bio *bio = bio_alloc(GFP_NOIO, 1);
+
+       bio->bi_bdev = rdev->bdev;
+       bio->bi_sector = sector;
+       bio_add_page(bio, page, size, 0);
+       bio->bi_private = rdev;
+       bio->bi_end_io = super_written;
+       atomic_inc(&mddev->pending_writes);
+       submit_bio((1<<BIO_RW)|(1<<BIO_RW_SYNC), bio);
+}
+
 static int bi_complete(struct bio *bio, unsigned int bytes_done, int error)
 {
        if (bio->bi_size)
@@ -329,7 +370,7 @@ static int bi_complete(struct bio *bio, unsigned int bytes_done, int error)
        return 0;
 }
 
-static int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+int sync_page_io(struct block_device *bdev, sector_t sector, int size,
                   struct page *page, int rw)
 {
        struct bio *bio = bio_alloc(GFP_NOIO, 1);
@@ -416,11 +457,8 @@ static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
                ret = 1;
 
 abort:
-       if (tmp1)
-               kfree(tmp1);
-       if (tmp2)
-               kfree(tmp2);
-
+       kfree(tmp1);
+       kfree(tmp2);
        return ret;
 }
 
@@ -569,6 +607,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
        mdp_disk_t *desc;
        mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
 
+       rdev->raid_disk = -1;
+       rdev->in_sync = 0;
        if (mddev->raid_disks == 0) {
                mddev->major_version = 0;
                mddev->minor_version = sb->minor_version;
@@ -599,16 +639,35 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                memcpy(mddev->uuid+12,&sb->set_uuid3, 4);
 
                mddev->max_disks = MD_SB_DISKS;
-       } else {
-               __u64 ev1;
-               ev1 = md_event(sb);
+
+               if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
+                   mddev->bitmap_file == NULL) {
+                       if (mddev->level != 1) {
+                               /* FIXME use a better test */
+                               printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+                               return -EINVAL;
+                       }
+                       mddev->bitmap_offset = (MD_SB_BYTES >> 9);
+               }
+
+       } else if (mddev->pers == NULL) {
+               /* Insist on good event counter while assembling */
+               __u64 ev1 = md_event(sb);
                ++ev1;
                if (ev1 < mddev->events) 
                        return -EINVAL;
-       }
+       } else if (mddev->bitmap) {
+               /* if adding to array with a bitmap, then we can accept an
+                * older device ... but not too old.
+                */
+               __u64 ev1 = md_event(sb);
+               if (ev1 < mddev->bitmap->events_cleared)
+                       return 0;
+       } else /* just a hot-add of a new device, leave raid_disk at -1 */
+               return 0;
+
        if (mddev->level != LEVEL_MULTIPATH) {
-               rdev->raid_disk = -1;
-               rdev->in_sync = rdev->faulty = 0;
+               rdev->faulty = 0;
                desc = sb->disks + rdev->desc_nr;
 
                if (desc->state & (1<<MD_DISK_FAULTY))
@@ -618,7 +677,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                        rdev->in_sync = 1;
                        rdev->raid_disk = desc->raid_disk;
                }
-       }
+       } else /* MULTIPATH are always insync */
+               rdev->in_sync = 1;
        return 0;
 }
 
@@ -683,6 +743,9 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
        sb->layout = mddev->layout;
        sb->chunk_size = mddev->chunk_size;
 
+       if (mddev->bitmap && mddev->bitmap_file == NULL)
+               sb->state |= (1<<MD_SB_BITMAP_PRESENT);
+
        sb->disks[0].state = (1<<MD_DISK_REMOVED);
        ITERATE_RDEV(mddev,rdev2,tmp) {
                mdp_disk_t *d;
@@ -780,7 +843,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-1);
+               sb_offset &= ~(sector_t)(4*2-1);
                /* convert from sectors to K */
                sb_offset /= 2;
                break;
@@ -860,6 +923,8 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 {
        struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
 
+       rdev->raid_disk = -1;
+       rdev->in_sync = 0;
        if (mddev->raid_disks == 0) {
                mddev->major_version = 1;
                mddev->patch_version = 0;
@@ -877,13 +942,30 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                memcpy(mddev->uuid, sb->set_uuid, 16);
 
                mddev->max_disks =  (4096-256)/2;
-       } else {
-               __u64 ev1;
-               ev1 = le64_to_cpu(sb->events);
+
+               if ((le32_to_cpu(sb->feature_map) & 1) &&
+                   mddev->bitmap_file == NULL ) {
+                       if (mddev->level != 1) {
+                               printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
+                               return -EINVAL;
+                       }
+                       mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
+               }
+       } else if (mddev->pers == NULL) {
+               /* Insist of good event counter while assembling */
+               __u64 ev1 = le64_to_cpu(sb->events);
                ++ev1;
                if (ev1 < mddev->events)
                        return -EINVAL;
-       }
+       } else if (mddev->bitmap) {
+               /* If adding to array with a bitmap, then we can accept an
+                * older device, but not too old.
+                */
+               __u64 ev1 = le64_to_cpu(sb->events);
+               if (ev1 < mddev->bitmap->events_cleared)
+                       return 0;
+       } else /* just a hot-add of a new device, leave raid_disk at -1 */
+               return 0;
 
        if (mddev->level != LEVEL_MULTIPATH) {
                int role;
@@ -891,14 +973,10 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
                switch(role) {
                case 0xffff: /* spare */
-                       rdev->in_sync = 0;
                        rdev->faulty = 0;
-                       rdev->raid_disk = -1;
                        break;
                case 0xfffe: /* faulty */
-                       rdev->in_sync = 0;
                        rdev->faulty = 1;
-                       rdev->raid_disk = -1;
                        break;
                default:
                        rdev->in_sync = 1;
@@ -906,7 +984,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                        rdev->raid_disk = role;
                        break;
                }
-       }
+       } else /* MULTIPATH are always insync */
+               rdev->in_sync = 1;
+
        return 0;
 }
 
@@ -933,6 +1013,11 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
        else
                sb->resync_offset = cpu_to_le64(0);
 
+       if (mddev->bitmap && mddev->bitmap_file == NULL) {
+               sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
+               sb->feature_map = cpu_to_le32(1);
+       }
+
        max_dev = 0;
        ITERATE_RDEV(mddev,rdev2,tmp)
                if (rdev2->desc_nr+1 > max_dev)
@@ -1196,8 +1281,11 @@ void md_print_devices(void)
        printk("md:     * <COMPLETE RAID STATE PRINTOUT> *\n");
        printk("md:     **********************************\n");
        ITERATE_MDDEV(mddev,tmp) {
-               printk("%s: ", mdname(mddev));
 
+               if (mddev->bitmap)
+                       bitmap_print_sb(mddev->bitmap);
+               else
+                       printk("%s: ", mdname(mddev));
                ITERATE_RDEV(mddev,rdev,tmp2)
                        printk("<%s>", bdevname(rdev->bdev,b));
                printk("\n");
@@ -1210,30 +1298,6 @@ void md_print_devices(void)
 }
 
 
-static int write_disk_sb(mdk_rdev_t * rdev)
-{
-       char b[BDEVNAME_SIZE];
-       if (!rdev->sb_loaded) {
-               MD_BUG();
-               return 1;
-       }
-       if (rdev->faulty) {
-               MD_BUG();
-               return 1;
-       }
-
-       dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
-               bdevname(rdev->bdev,b),
-              (unsigned long long)rdev->sb_offset);
-  
-       if (sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE))
-               return 0;
-
-       printk("md: write_disk_sb failed for device %s\n", 
-               bdevname(rdev->bdev,b));
-       return 1;
-}
-
 static void sync_sbs(mddev_t * mddev)
 {
        mdk_rdev_t *rdev;
@@ -1248,12 +1312,14 @@ static void sync_sbs(mddev_t * mddev)
 
 static void md_update_sb(mddev_t * mddev)
 {
-       int err, count = 100;
+       int err;
        struct list_head *tmp;
        mdk_rdev_t *rdev;
+       int sync_req;
 
-       mddev->sb_dirty = 0;
 repeat:
+       spin_lock(&mddev->write_lock);
+       sync_req = mddev->in_sync;
        mddev->utime = get_seconds();
        mddev->events ++;
 
@@ -1266,20 +1332,26 @@ repeat:
                MD_BUG();
                mddev->events --;
        }
+       mddev->sb_dirty = 2;
        sync_sbs(mddev);
 
        /*
         * do not write anything to disk if using
         * nonpersistent superblocks
         */
-       if (!mddev->persistent)
+       if (!mddev->persistent) {
+               mddev->sb_dirty = 0;
+               spin_unlock(&mddev->write_lock);
+               wake_up(&mddev->sb_wait);
                return;
+       }
+       spin_unlock(&mddev->write_lock);
 
        dprintk(KERN_INFO 
                "md: updating %s RAID superblock on device (in sync %d)\n",
                mdname(mddev),mddev->in_sync);
 
-       err = 0;
+       err = bitmap_update_sb(mddev->bitmap);
        ITERATE_RDEV(mddev,rdev,tmp) {
                char b[BDEVNAME_SIZE];
                dprintk(KERN_INFO "md: ");
@@ -1288,22 +1360,32 @@ repeat:
 
                dprintk("%s ", bdevname(rdev->bdev,b));
                if (!rdev->faulty) {
-                       err += write_disk_sb(rdev);
+                       md_super_write(mddev,rdev,
+                                      rdev->sb_offset<<1, MD_SB_BYTES,
+                                      rdev->sb_page);
+                       dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
+                               bdevname(rdev->bdev,b),
+                               (unsigned long long)rdev->sb_offset);
+
                } else
                        dprintk(")\n");
-               if (!err && mddev->level == LEVEL_MULTIPATH)
+               if (mddev->level == LEVEL_MULTIPATH)
                        /* only need to write one superblock... */
                        break;
        }
-       if (err) {
-               if (--count) {
-                       printk(KERN_ERR "md: errors occurred during superblock"
-                               " update, repeating\n");
-                       goto repeat;
-               }
-               printk(KERN_ERR \
-                       "md: excessive errors occurred during superblock update, exiting\n");
+       wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+       /* if there was a failure, sb_dirty was set to 1, and we re-write super */
+
+       spin_lock(&mddev->write_lock);
+       if (mddev->in_sync != sync_req|| mddev->sb_dirty == 1) {
+               /* have to write it out again */
+               spin_unlock(&mddev->write_lock);
+               goto repeat;
        }
+       mddev->sb_dirty = 0;
+       spin_unlock(&mddev->write_lock);
+       wake_up(&mddev->sb_wait);
+
 }
 
 /*
@@ -1607,12 +1689,19 @@ static int do_md_run(mddev_t * mddev)
 
        mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
 
-       err = mddev->pers->run(mddev);
+       /* before we start the array running, initialise the bitmap */
+       err = bitmap_create(mddev);
+       if (err)
+               printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
+                       mdname(mddev), err);
+       else
+               err = mddev->pers->run(mddev);
        if (err) {
                printk(KERN_ERR "md: pers->run() failed ...\n");
                module_put(mddev->pers->owner);
                mddev->pers = NULL;
-               return -EINVAL;
+               bitmap_destroy(mddev);
+               return err;
        }
        atomic_set(&mddev->writes_pending,0);
        mddev->safemode = 0;
@@ -1725,6 +1814,14 @@ static int do_md_stop(mddev_t * mddev, int ro)
                if (ro)
                        set_disk_ro(disk, 1);
        }
+
+       bitmap_destroy(mddev);
+       if (mddev->bitmap_file) {
+               atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
+               fput(mddev->bitmap_file);
+               mddev->bitmap_file = NULL;
+       }
+
        /*
         * Free resources if final stop
         */
@@ -1983,6 +2080,42 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
        return 0;
 }
 
+static int get_bitmap_file(mddev_t * mddev, void * arg)
+{
+       mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
+       char *ptr, *buf = NULL;
+       int err = -ENOMEM;
+
+       file = kmalloc(sizeof(*file), GFP_KERNEL);
+       if (!file)
+               goto out;
+
+       /* bitmap disabled, zero the first byte and copy out */
+       if (!mddev->bitmap || !mddev->bitmap->file) {
+               file->pathname[0] = '\0';
+               goto copy_out;
+       }
+
+       buf = kmalloc(sizeof(file->pathname), GFP_KERNEL);
+       if (!buf)
+               goto out;
+
+       ptr = file_path(mddev->bitmap->file, buf, sizeof(file->pathname));
+       if (!ptr)
+               goto out;
+
+       strcpy(file->pathname, ptr);
+
+copy_out:
+       err = 0;
+       if (copy_to_user(arg, file, sizeof(*file)))
+               err = -EFAULT;
+out:
+       kfree(buf);
+       kfree(file);
+       return err;
+}
+
 static int get_disk_info(mddev_t * mddev, void __user * arg)
 {
        mdu_disk_info_t info;
@@ -2078,11 +2211,25 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                                PTR_ERR(rdev));
                        return PTR_ERR(rdev);
                }
+               /* set save_raid_disk if appropriate */
+               if (!mddev->persistent) {
+                       if (info->state & (1<<MD_DISK_SYNC)  &&
+                           info->raid_disk < mddev->raid_disks)
+                               rdev->raid_disk = info->raid_disk;
+                       else
+                               rdev->raid_disk = -1;
+               } else
+                       super_types[mddev->major_version].
+                               validate_super(mddev, rdev);
+               rdev->saved_raid_disk = rdev->raid_disk;
+
                rdev->in_sync = 0; /* just to be sure */
                rdev->raid_disk = -1;
                err = bind_rdev_to_array(rdev, mddev);
                if (err)
                        export_rdev(rdev);
+
+               set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                if (mddev->thread)
                        md_wakeup_thread(mddev->thread);
                return err;
@@ -2256,6 +2403,49 @@ abort_export:
        return err;
 }
 
+/* similar to deny_write_access, but accounts for our holding a reference
+ * to the file ourselves */
+static int deny_bitmap_write_access(struct file * file)
+{
+       struct inode *inode = file->f_mapping->host;
+
+       spin_lock(&inode->i_lock);
+       if (atomic_read(&inode->i_writecount) > 1) {
+               spin_unlock(&inode->i_lock);
+               return -ETXTBSY;
+       }
+       atomic_set(&inode->i_writecount, -1);
+       spin_unlock(&inode->i_lock);
+
+       return 0;
+}
+
+static int set_bitmap_file(mddev_t *mddev, int fd)
+{
+       int err;
+
+       if (mddev->pers)
+               return -EBUSY;
+
+       mddev->bitmap_file = fget(fd);
+
+       if (mddev->bitmap_file == NULL) {
+               printk(KERN_ERR "%s: error: failed to get bitmap file\n",
+                       mdname(mddev));
+               return -EBADF;
+       }
+
+       err = deny_bitmap_write_access(mddev->bitmap_file);
+       if (err) {
+               printk(KERN_ERR "%s: error: bitmap file is already in use\n",
+                       mdname(mddev));
+               fput(mddev->bitmap_file);
+               mddev->bitmap_file = NULL;
+       } else
+               mddev->bitmap_offset = 0; /* file overrides offset */
+       return err;
+}
+
 /*
  * set_array_info is used two different ways
  * The original usage is when creating a new array.
@@ -2567,8 +2757,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
        /*
         * Commands querying/configuring an existing array:
         */
-       /* if we are initialised yet, only ADD_NEW_DISK or STOP_ARRAY is allowed */
-       if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY && cmd != RUN_ARRAY) {
+       /* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY,
+        * RUN_ARRAY, and SET_BITMAP_FILE are allowed */
+       if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
+                       && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE) {
                err = -ENODEV;
                goto abort_unlock;
        }
@@ -2582,6 +2774,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
                        err = get_array_info(mddev, argp);
                        goto done_unlock;
 
+               case GET_BITMAP_FILE:
+                       err = get_bitmap_file(mddev, (void *)arg);
+                       goto done_unlock;
+
                case GET_DISK_INFO:
                        err = get_disk_info(mddev, argp);
                        goto done_unlock;
@@ -2662,6 +2858,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
                        err = do_md_run (mddev);
                        goto done_unlock;
 
+               case SET_BITMAP_FILE:
+                       err = set_bitmap_file(mddev, (int)arg);
+                       goto done_unlock;
+
                default:
                        if (_IOC_TYPE(cmd) == MD_MAJOR)
                                printk(KERN_WARNING "md: %s(pid %d) used"
@@ -2773,8 +2973,9 @@ static int md_thread(void * arg)
        while (thread->run) {
                void (*run)(mddev_t *);
 
-               wait_event_interruptible(thread->wqueue,
-                                        test_bit(THREAD_WAKEUP, &thread->flags));
+               wait_event_interruptible_timeout(thread->wqueue,
+                                                test_bit(THREAD_WAKEUP, &thread->flags),
+                                                thread->timeout);
                if (current->flags & PF_FREEZE)
                        refrigerator(PF_FREEZE);
 
@@ -2820,6 +3021,7 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
        thread->run = run;
        thread->mddev = mddev;
        thread->name = name;
+       thread->timeout = MAX_SCHEDULE_TIMEOUT;
        ret = kernel_thread(md_thread, thread, 0);
        if (ret < 0) {
                kfree(thread);
@@ -2858,13 +3060,13 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
 
        if (!rdev || rdev->faulty)
                return;
-
+/*
        dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
                mdname(mddev),
                MAJOR(rdev->bdev->bd_dev), MINOR(rdev->bdev->bd_dev),
                __builtin_return_address(0),__builtin_return_address(1),
                __builtin_return_address(2),__builtin_return_address(3));
-
+*/
        if (!mddev->pers->error_handler)
                return;
        mddev->pers->error_handler(mddev,rdev);
@@ -3018,6 +3220,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
        struct list_head *tmp2;
        mdk_rdev_t *rdev;
        int i;
+       struct bitmap *bitmap;
 
        if (v == (void*)1) {
                seq_printf(seq, "Personalities : ");
@@ -3070,10 +3273,35 @@ static int md_seq_show(struct seq_file *seq, void *v)
                if (mddev->pers) {
                        mddev->pers->status (seq, mddev);
                        seq_printf(seq, "\n      ");
-                       if (mddev->curr_resync > 2)
+                       if (mddev->curr_resync > 2) {
                                status_resync (seq, mddev);
-                       else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
-                               seq_printf(seq, "       resync=DELAYED");
+                               seq_printf(seq, "\n      ");
+                       } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
+                               seq_printf(seq, "       resync=DELAYED\n      ");
+               } else
+                       seq_printf(seq, "\n       ");
+
+               if ((bitmap = mddev->bitmap)) {
+                       unsigned long chunk_kb;
+                       unsigned long flags;
+                       spin_lock_irqsave(&bitmap->lock, flags);
+                       chunk_kb = bitmap->chunksize >> 10;
+                       seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
+                               "%lu%s chunk",
+                               bitmap->pages - bitmap->missing_pages,
+                               bitmap->pages,
+                               (bitmap->pages - bitmap->missing_pages)
+                                       << (PAGE_SHIFT - 10),
+                               chunk_kb ? chunk_kb : bitmap->chunksize,
+                               chunk_kb ? "KB" : "B");
+                       if (bitmap->file) {
+                               seq_printf(seq, ", file: ");
+                               seq_path(seq, bitmap->file->f_vfsmnt,
+                                        bitmap->file->f_dentry," \t\n");
+                       }
+
+                       seq_printf(seq, "\n");
+                       spin_unlock_irqrestore(&bitmap->lock, flags);
                }
 
                seq_printf(seq, "\n");
@@ -3176,19 +3404,28 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
 }
 
 
-void md_write_start(mddev_t *mddev)
+/* md_write_start(mddev, bi)
+ * If we need to update some array metadata (e.g. 'active' flag
+ * in superblock) before writing, schedule a superblock update
+ * and wait for it to complete.
+ */
+void md_write_start(mddev_t *mddev, struct bio *bi)
 {
-       if (!atomic_read(&mddev->writes_pending)) {
-               mddev_lock_uninterruptible(mddev);
+       DEFINE_WAIT(w);
+       if (bio_data_dir(bi) != WRITE)
+               return;
+
+       atomic_inc(&mddev->writes_pending);
+       if (mddev->in_sync) {
+               spin_lock(&mddev->write_lock);
                if (mddev->in_sync) {
                        mddev->in_sync = 0;
-                       del_timer(&mddev->safemode_timer);
-                       md_update_sb(mddev);
+                       mddev->sb_dirty = 1;
+                       md_wakeup_thread(mddev->thread);
                }
-               atomic_inc(&mddev->writes_pending);
-               mddev_unlock(mddev);
-       } else
-               atomic_inc(&mddev->writes_pending);
+               spin_unlock(&mddev->write_lock);
+       }
+       wait_event(mddev->sb_wait, mddev->sb_dirty==0);
 }
 
 void md_write_end(mddev_t *mddev)
@@ -3201,37 +3438,6 @@ void md_write_end(mddev_t *mddev)
        }
 }
 
-static inline void md_enter_safemode(mddev_t *mddev)
-{
-       if (!mddev->safemode) return;
-       if (mddev->safemode == 2 &&
-           (atomic_read(&mddev->writes_pending) || mddev->in_sync ||
-                   mddev->recovery_cp != MaxSector))
-               return; /* avoid the lock */
-       mddev_lock_uninterruptible(mddev);
-       if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
-           !mddev->in_sync && mddev->recovery_cp == MaxSector) {
-               mddev->in_sync = 1;
-               md_update_sb(mddev);
-       }
-       mddev_unlock(mddev);
-
-       if (mddev->safemode == 1)
-               mddev->safemode = 0;
-}
-
-void md_handle_safemode(mddev_t *mddev)
-{
-       if (signal_pending(current)) {
-               printk(KERN_INFO "md: %s in immediate safe mode\n",
-                       mdname(mddev));
-               mddev->safemode = 2;
-               flush_signals(current);
-       }
-       md_enter_safemode(mddev);
-}
-
-
 static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
 
 #define SYNC_MARKS     10
@@ -3241,12 +3447,13 @@ static void md_do_sync(mddev_t *mddev)
        mddev_t *mddev2;
        unsigned int currspeed = 0,
                 window;
-       sector_t max_sectors,j;
+       sector_t max_sectors,j, io_sectors;
        unsigned long mark[SYNC_MARKS];
        sector_t mark_cnt[SYNC_MARKS];
        int last_mark,m;
        struct list_head *tmp;
        sector_t last_check;
+       int skipped = 0;
 
        /* just incase thread restarts... */
        if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
@@ -3312,7 +3519,7 @@ static void md_do_sync(mddev_t *mddev)
 
        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
+                * which defaults to physical size, but can be virtual size
                 */
                max_sectors = mddev->resync_max_sectors;
        else
@@ -3327,13 +3534,15 @@ static void md_do_sync(mddev_t *mddev)
               sysctl_speed_limit_max);
 
        is_mddev_idle(mddev); /* this also initializes IO event counters */
-       if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+       /* we don't use the checkpoint if there's a bitmap */
+       if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap)
                j = mddev->recovery_cp;
        else
                j = 0;
+       io_sectors = 0;
        for (m = 0; m < SYNC_MARKS; m++) {
                mark[m] = jiffies;
-               mark_cnt[m] = j;
+               mark_cnt[m] = io_sectors;
        }
        last_mark = 0;
        mddev->resync_mark = mark[last_mark];
@@ -3358,21 +3567,29 @@ static void md_do_sync(mddev_t *mddev)
        }
 
        while (j < max_sectors) {
-               int sectors;
+               sector_t sectors;
 
-               sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min);
-               if (sectors < 0) {
+               skipped = 0;
+               sectors = mddev->pers->sync_request(mddev, j, &skipped,
+                                           currspeed < sysctl_speed_limit_min);
+               if (sectors == 0) {
                        set_bit(MD_RECOVERY_ERR, &mddev->recovery);
                        goto out;
                }
-               atomic_add(sectors, &mddev->recovery_active);
+
+               if (!skipped) { /* actual IO requested */
+                       io_sectors += sectors;
+                       atomic_add(sectors, &mddev->recovery_active);
+               }
+
                j += sectors;
                if (j>1) mddev->curr_resync = j;
 
-               if (last_check + window > j || j == max_sectors)
+
+               if (last_check + window > io_sectors || j == max_sectors)
                        continue;
 
-               last_check = j;
+               last_check = io_sectors;
 
                if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) ||
                    test_bit(MD_RECOVERY_ERR, &mddev->recovery))
@@ -3386,7 +3603,7 @@ static void md_do_sync(mddev_t *mddev)
                        mddev->resync_mark = mark[next];
                        mddev->resync_mark_cnt = mark_cnt[next];
                        mark[next] = jiffies;
-                       mark_cnt[next] = j - atomic_read(&mddev->recovery_active);
+                       mark_cnt[next] = io_sectors - atomic_read(&mddev->recovery_active);
                        last_mark = next;
                }
 
@@ -3413,7 +3630,8 @@ static void md_do_sync(mddev_t *mddev)
                mddev->queue->unplug_fn(mddev->queue);
                cond_resched();
 
-               currspeed = ((unsigned long)(j-mddev->resync_mark_cnt))/2/((jiffies-mddev->resync_mark)/HZ +1) +1;
+               currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
+                       /((jiffies-mddev->resync_mark)/HZ +1) +1;
 
                if (currspeed > sysctl_speed_limit_min) {
                        if ((currspeed > sysctl_speed_limit_max) ||
@@ -3433,7 +3651,7 @@ static void md_do_sync(mddev_t *mddev)
        wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
 
        /* tell personality that we are finished */
-       mddev->pers->sync_request(mddev, max_sectors, 1);
+       mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
 
        if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
            mddev->curr_resync > 2 &&
@@ -3447,7 +3665,6 @@ static void md_do_sync(mddev_t *mddev)
                        mddev->recovery_cp = MaxSector;
        }
 
-       md_enter_safemode(mddev);
  skip:
        mddev->curr_resync = 0;
        wake_up(&resync_wait);
@@ -3484,20 +3701,48 @@ void md_check_recovery(mddev_t *mddev)
        struct list_head *rtmp;
 
 
-       dprintk(KERN_INFO "md: recovery thread got woken up ...\n");
+       if (mddev->bitmap)
+               bitmap_daemon_work(mddev->bitmap);
 
        if (mddev->ro)
                return;
+
+       if (signal_pending(current)) {
+               if (mddev->pers->sync_request) {
+                       printk(KERN_INFO "md: %s in immediate safe mode\n",
+                              mdname(mddev));
+                       mddev->safemode = 2;
+               }
+               flush_signals(current);
+       }
+
        if ( ! (
                mddev->sb_dirty ||
                test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
-               test_bit(MD_RECOVERY_DONE, &mddev->recovery)
+               test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
+               (mddev->safemode == 1) ||
+               (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
+                && !mddev->in_sync && mddev->recovery_cp == MaxSector)
                ))
                return;
+
        if (mddev_trylock(mddev)==0) {
                int spares =0;
+
+               spin_lock(&mddev->write_lock);
+               if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
+                   !mddev->in_sync && mddev->recovery_cp == MaxSector) {
+                       mddev->in_sync = 1;
+                       mddev->sb_dirty = 1;
+               }
+               if (mddev->safemode == 1)
+                       mddev->safemode = 0;
+               spin_unlock(&mddev->write_lock);
+
                if (mddev->sb_dirty)
                        md_update_sb(mddev);
+
+
                if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
                    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
                        /* resync/recovery still happening */
@@ -3515,6 +3760,14 @@ void md_check_recovery(mddev_t *mddev)
                                mddev->pers->spare_active(mddev);
                        }
                        md_update_sb(mddev);
+
+                       /* if array is no-longer degraded, then any saved_raid_disk
+                        * information must be scrapped
+                        */
+                       if (!mddev->degraded)
+                               ITERATE_RDEV(mddev,rdev,rtmp)
+                                       rdev->saved_raid_disk = -1;
+
                        mddev->recovery = 0;
                        /* flag recovery needed just to double check */
                        set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -3557,6 +3810,13 @@ void md_check_recovery(mddev_t *mddev)
                        set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
                        if (!spares)
                                set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+                       if (spares && mddev->bitmap && ! mddev->bitmap->file) {
+                               /* We are adding a device or devices to an array
+                                * which has the bitmap stored on all devices.
+                                * So make sure all bitmap pages get written
+                                */
+                               bitmap_write_all(mddev->bitmap);
+                       }
                        mddev->sync_thread = md_register_thread(md_do_sync,
                                                                mddev,
                                                                "%s_resync");
@@ -3624,6 +3884,8 @@ static int __init md_init(void)
                        " MD_SB_DISKS=%d\n",
                        MD_MAJOR_VERSION, MD_MINOR_VERSION,
                        MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
+       printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR,
+                       BITMAP_MINOR);
 
        if (register_blkdev(MAJOR_NR, "md"))
                return -1;
@@ -3739,7 +4001,6 @@ EXPORT_SYMBOL(md_error);
 EXPORT_SYMBOL(md_done_sync);
 EXPORT_SYMBOL(md_write_start);
 EXPORT_SYMBOL(md_write_end);
-EXPORT_SYMBOL(md_handle_safemode);
 EXPORT_SYMBOL(md_register_thread);
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
index 2ae2d709cb1582256699b7c915436a2476129966..2d2ca7fa0265261a71e2493e88b68403cc902c57 100644 (file)
@@ -533,8 +533,7 @@ static int multipath_run (mddev_t *mddev)
 out_free_conf:
        if (conf->pool)
                mempool_destroy(conf->pool);
-       if (conf->multipaths)
-               kfree(conf->multipaths);
+       kfree(conf->multipaths);
        kfree(conf);
        mddev->private = NULL;
 out:
index e7d934eca06f8de135d9cd5b545735422bc57790..e11dd14d0b43f4700f7a9779a0ed6d7676461aa4 100644 (file)
@@ -371,10 +371,8 @@ static int raid0_run (mddev_t *mddev)
        return 0;
 
 out_free_conf:
-       if (conf->strip_zone)
-               kfree(conf->strip_zone);
-       if (conf->devlist)
-               kfree (conf->devlist);
+       kfree(conf->strip_zone);
+       kfree(conf->devlist);
        kfree(conf);
        mddev->private = NULL;
 out:
@@ -386,11 +384,11 @@ 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);
+       kfree(conf->hash_table);
        conf->hash_table = NULL;
-       kfree (conf->strip_zone);
+       kfree(conf->strip_zone);
        conf->strip_zone = NULL;
-       kfree (conf);
+       kfree(conf);
        mddev->private = NULL;
 
        return 0;
index 1db5de52d37665e2ec1aa28c2f8678a5565fbb84..ff1dbec864af51d780e1135ae392c1f6962ae37c 100644 (file)
  * Fixes to reconstruction by Jakob Østergaard" <jakob@ostenfeld.dk>
  * Various fixes by Neil Brown <neilb@cse.unsw.edu.au>
  *
+ * Changes by Peter T. Breuer <ptb@it.uc3m.es> 31/1/2003 to support
+ * bitmapped intelligence in resync:
+ *
+ *      - bitmap marked during normal i/o
+ *      - bitmap used to skip nondirty blocks during sync
+ *
+ * Additions to bitmap code, (C) 2003-2004 Paul Clements, SteelEye Technology:
+ * - persistent bitmap code
+ *
  * 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)
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "dm-bio-list.h"
 #include <linux/raid/raid1.h>
+#include <linux/raid/bitmap.h>
+
+#define DEBUG 0
+#if DEBUG
+#define PRINTK(x...) printk(x)
+#else
+#define PRINTK(x...)
+#endif
 
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
@@ -287,9 +305,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
        /*
         * this branch is our 'one mirror IO has finished' event handler:
         */
-       if (!uptodate)
+       if (!uptodate) {
                md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
-       else
+               /* an I/O failed, we can't clear the bitmap */
+               set_bit(R1BIO_Degraded, &r1_bio->state);
+       } else
                /*
                 * Set R1BIO_Uptodate in our master bio, so that
                 * we will return a good error code for to the higher
@@ -309,6 +329,10 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
         * already.
         */
        if (atomic_dec_and_test(&r1_bio->remaining)) {
+               /* clear the bitmap if all writes complete successfully */
+               bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+                               r1_bio->sectors,
+                               !test_bit(R1BIO_Degraded, &r1_bio->state));
                md_write_end(r1_bio->mddev);
                raid_end_bio_io(r1_bio);
        }
@@ -458,7 +482,10 @@ static void unplug_slaves(mddev_t *mddev)
 
 static void raid1_unplug(request_queue_t *q)
 {
-       unplug_slaves(q->queuedata);
+       mddev_t *mddev = q->queuedata;
+
+       unplug_slaves(mddev);
+       md_wakeup_thread(mddev->thread);
 }
 
 static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -501,16 +528,16 @@ static void device_barrier(conf_t *conf, sector_t sect)
 {
        spin_lock_irq(&conf->resync_lock);
        wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
-                           conf->resync_lock, unplug_slaves(conf->mddev));
+                           conf->resync_lock, raid1_unplug(conf->mddev->queue));
        
        if (!conf->barrier++) {
                wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
-                                   conf->resync_lock, unplug_slaves(conf->mddev));
+                                   conf->resync_lock, raid1_unplug(conf->mddev->queue));
                if (conf->nr_pending)
                        BUG();
        }
        wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
-                           conf->resync_lock, unplug_slaves(conf->mddev));
+                           conf->resync_lock, raid1_unplug(conf->mddev->queue));
        conf->next_resync = sect;
        spin_unlock_irq(&conf->resync_lock);
 }
@@ -522,14 +549,20 @@ static int make_request(request_queue_t *q, struct bio * bio)
        mirror_info_t *mirror;
        r1bio_t *r1_bio;
        struct bio *read_bio;
-       int i, disks;
+       int i, targets = 0, disks;
        mdk_rdev_t *rdev;
+       struct bitmap *bitmap = mddev->bitmap;
+       unsigned long flags;
+       struct bio_list bl;
+
 
        /*
         * Register the new request and wait if the reconstruction
         * thread has put up a bar for new requests.
         * Continue immediately if no resync is active currently.
         */
+       md_write_start(mddev, bio); /* wait on superblock update early */
+
        spin_lock_irq(&conf->resync_lock);
        wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
        conf->nr_pending++;
@@ -552,7 +585,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
 
        r1_bio->master_bio = bio;
        r1_bio->sectors = bio->bi_size >> 9;
-
+       r1_bio->state = 0;
        r1_bio->mddev = mddev;
        r1_bio->sector = bio->bi_sector;
 
@@ -595,6 +628,13 @@ static int make_request(request_queue_t *q, struct bio * bio)
         * bios[x] to bio
         */
        disks = conf->raid_disks;
+#if 0
+       { static int first=1;
+       if (first) printk("First Write sector %llu disks %d\n",
+                         (unsigned long long)r1_bio->sector, disks);
+       first = 0;
+       }
+#endif
        rcu_read_lock();
        for (i = 0;  i < disks; i++) {
                if ((rdev=conf->mirrors[i].rdev) != NULL &&
@@ -605,13 +645,21 @@ static int make_request(request_queue_t *q, struct bio * bio)
                                r1_bio->bios[i] = NULL;
                        } else
                                r1_bio->bios[i] = bio;
+                       targets++;
                } else
                        r1_bio->bios[i] = NULL;
        }
        rcu_read_unlock();
 
-       atomic_set(&r1_bio->remaining, 1);
-       md_write_start(mddev);
+       if (targets < conf->raid_disks) {
+               /* array is degraded, we will not clear the bitmap
+                * on I/O completion (see raid1_end_write_request) */
+               set_bit(R1BIO_Degraded, &r1_bio->state);
+       }
+
+       atomic_set(&r1_bio->remaining, 0);
+
+       bio_list_init(&bl);
        for (i = 0; i < disks; i++) {
                struct bio *mbio;
                if (!r1_bio->bios[i])
@@ -627,14 +675,23 @@ static int make_request(request_queue_t *q, struct bio * bio)
                mbio->bi_private = r1_bio;
 
                atomic_inc(&r1_bio->remaining);
-               generic_make_request(mbio);
-       }
 
-       if (atomic_dec_and_test(&r1_bio->remaining)) {
-               md_write_end(mddev);
-               raid_end_bio_io(r1_bio);
+               bio_list_add(&bl, mbio);
        }
 
+       bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors);
+       spin_lock_irqsave(&conf->device_lock, flags);
+       bio_list_merge(&conf->pending_bio_list, &bl);
+       bio_list_init(&bl);
+
+       blk_plug_device(mddev->queue);
+       spin_unlock_irqrestore(&conf->device_lock, flags);
+
+#if 0
+       while ((bio = bio_list_pop(&bl)) != NULL)
+               generic_make_request(bio);
+#endif
+
        return 0;
 }
 
@@ -714,7 +771,7 @@ static void close_sync(conf_t *conf)
 {
        spin_lock_irq(&conf->resync_lock);
        wait_event_lock_irq(conf->wait_resume, !conf->barrier,
-                           conf->resync_lock,  unplug_slaves(conf->mddev));
+                           conf->resync_lock,  raid1_unplug(conf->mddev->queue));
        spin_unlock_irq(&conf->resync_lock);
 
        if (conf->barrier) BUG();
@@ -754,9 +811,12 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 {
        conf_t *conf = mddev->private;
        int found = 0;
-       int mirror;
+       int mirror = 0;
        mirror_info_t *p;
 
+       if (rdev->saved_raid_disk >= 0 &&
+           conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
+               mirror = rdev->saved_raid_disk;
        for (mirror=0; mirror < mddev->raid_disks; mirror++)
                if ( !(p=conf->mirrors+mirror)->rdev) {
 
@@ -773,6 +833,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
                        p->head_position = 0;
                        rdev->raid_disk = mirror;
                        found = 1;
+                       if (rdev->saved_raid_disk != mirror)
+                               conf->fullsync = 1;
                        p->rdev = rdev;
                        break;
                }
@@ -828,10 +890,11 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
         * or re-read if the read failed.
         * We don't do much here, just schedule handling by raid1d
         */
-       if (!uptodate)
+       if (!uptodate) {
                md_error(r1_bio->mddev,
                         conf->mirrors[r1_bio->read_disk].rdev);
-       else
+               set_bit(R1BIO_Degraded, &r1_bio->state);
+       } else
                set_bit(R1BIO_Uptodate, &r1_bio->state);
        rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
        reschedule_retry(r1_bio);
@@ -855,8 +918,10 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
                        mirror = i;
                        break;
                }
-       if (!uptodate)
+       if (!uptodate) {
                md_error(mddev, conf->mirrors[mirror].rdev);
+               set_bit(R1BIO_Degraded, &r1_bio->state);
+       }
        update_head_pos(mirror, r1_bio);
 
        if (atomic_dec_and_test(&r1_bio->remaining)) {
@@ -876,6 +941,9 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
 
        bio = r1_bio->bios[r1_bio->read_disk];
 
+/*
+       if (r1_bio->sector == 0) printk("First sync write startss\n");
+*/
        /*
         * schedule writes
         */
@@ -903,10 +971,12 @@ 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->bdev, wbio->bi_size >> 9);
+
                generic_make_request(wbio);
        }
 
        if (atomic_dec_and_test(&r1_bio->remaining)) {
+               /* if we're here, all write(s) have completed, so clean up */
                md_done_sync(mddev, r1_bio->sectors, 1);
                put_buf(r1_bio);
        }
@@ -931,11 +1001,30 @@ static void raid1d(mddev_t *mddev)
        mdk_rdev_t *rdev;
 
        md_check_recovery(mddev);
-       md_handle_safemode(mddev);
        
        for (;;) {
                char b[BDEVNAME_SIZE];
                spin_lock_irqsave(&conf->device_lock, flags);
+
+               if (conf->pending_bio_list.head) {
+                       bio = bio_list_get(&conf->pending_bio_list);
+                       blk_remove_plug(mddev->queue);
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       /* flush any pending bitmap writes to disk before proceeding w/ I/O */
+                       if (bitmap_unplug(mddev->bitmap) != 0)
+                               printk("%s: bitmap file write failed!\n", mdname(mddev));
+
+                       while (bio) { /* submit pending writes */
+                               struct bio *next = bio->bi_next;
+                               bio->bi_next = NULL;
+                               generic_make_request(bio);
+                               bio = next;
+                       }
+                       unplug = 1;
+
+                       continue;
+               }
+
                if (list_empty(head))
                        break;
                r1_bio = list_entry(head->prev, r1bio_t, retry_list);
@@ -1009,7 +1098,7 @@ static int init_resync(conf_t *conf)
  * that can be installed to exclude normal IO requests.
  */
 
-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
        conf_t *conf = mddev_to_conf(mddev);
        mirror_info_t *mirror;
@@ -1019,17 +1108,43 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
        int disk;
        int i;
        int write_targets = 0;
+       int sync_blocks;
 
        if (!conf->r1buf_pool)
+       {
+/*
+               printk("sync start - bitmap %p\n", mddev->bitmap);
+*/
                if (init_resync(conf))
-                       return -ENOMEM;
+                       return 0;
+       }
 
        max_sector = mddev->size << 1;
        if (sector_nr >= max_sector) {
+               /* If we aborted, we need to abort the
+                * sync on the 'current' bitmap chunk (there will
+                * only be one in raid1 resync.
+                * We can find the current addess in mddev->curr_resync
+                */
+               if (!conf->fullsync) {
+                       if (mddev->curr_resync < max_sector)
+                               bitmap_end_sync(mddev->bitmap,
+                                               mddev->curr_resync,
+                                               &sync_blocks, 1);
+                       bitmap_close_sync(mddev->bitmap);
+               }
+               if (mddev->curr_resync >= max_sector)
+                       conf->fullsync = 0;
                close_sync(conf);
                return 0;
        }
 
+       if (!conf->fullsync &&
+           !bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks)) {
+               /* We can skip this block, and probably several more */
+               *skipped = 1;
+               return sync_blocks;
+       }
        /*
         * If there is non-resync activity waiting for us then
         * put in a delay to throttle resync.
@@ -1068,6 +1183,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
 
        r1_bio->mddev = mddev;
        r1_bio->sector = sector_nr;
+       r1_bio->state = 0;
        set_bit(R1BIO_IsSync, &r1_bio->state);
        r1_bio->read_disk = disk;
 
@@ -1102,18 +1218,24 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
                bio->bi_bdev = conf->mirrors[i].rdev->bdev;
                bio->bi_private = r1_bio;
        }
+
+       if (write_targets + 1 < conf->raid_disks)
+               /* array degraded, can't clear bitmap */
+               set_bit(R1BIO_Degraded, &r1_bio->state);
+
        if (write_targets == 0) {
                /* There is nowhere to write, so all non-sync
                 * drives must be failed - so we are finished
                 */
-               int rv = max_sector - sector_nr;
-               md_done_sync(mddev, rv, 1);
+               sector_t rv = max_sector - sector_nr;
+               *skipped = 1;
                put_buf(r1_bio);
                rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
                return rv;
        }
 
        nr_sectors = 0;
+       sync_blocks = 0;
        do {
                struct page *page;
                int len = PAGE_SIZE;
@@ -1121,6 +1243,17 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
                        len = (max_sector - sector_nr) << 9;
                if (len == 0)
                        break;
+               if (!conf->fullsync) {
+                       if (sync_blocks == 0) {
+                               if (!bitmap_start_sync(mddev->bitmap,
+                                                      sector_nr, &sync_blocks))
+                                       break;
+                               if (sync_blocks < (PAGE_SIZE>>9))
+                                       BUG();
+                               if (len > (sync_blocks<<9)) len = sync_blocks<<9;
+                       }
+               }
+
                for (i=0 ; i < conf->raid_disks; i++) {
                        bio = r1_bio->bios[i];
                        if (bio->bi_end_io) {
@@ -1143,6 +1276,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
                }
                nr_sectors += len>>9;
                sector_nr += len>>9;
+               sync_blocks -= (len>>9);
        } while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
  bio_full:
        bio = r1_bio->bios[disk];
@@ -1231,6 +1365,9 @@ static int run(mddev_t *mddev)
        init_waitqueue_head(&conf->wait_idle);
        init_waitqueue_head(&conf->wait_resume);
 
+       bio_list_init(&conf->pending_bio_list);
+       bio_list_init(&conf->flushing_bio_list);
+
        if (!conf->working_disks) {
                printk(KERN_ERR "raid1: no operational mirrors for %s\n",
                        mdname(mddev));
@@ -1259,16 +1396,15 @@ static int run(mddev_t *mddev)
        conf->last_used = j;
 
 
-
-       {
-               mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1");
-               if (!mddev->thread) {
-                       printk(KERN_ERR 
-                               "raid1: couldn't allocate thread for %s\n", 
-                               mdname(mddev));
-                       goto out_free_conf;
-               }
+       mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1");
+       if (!mddev->thread) {
+               printk(KERN_ERR
+                      "raid1: couldn't allocate thread for %s\n",
+                      mdname(mddev));
+               goto out_free_conf;
        }
+       if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
        printk(KERN_INFO 
                "raid1: raid set %s active with %d out of %d mirrors\n",
                mdname(mddev), mddev->raid_disks - mddev->degraded, 
@@ -1291,10 +1427,8 @@ out_free_conf:
        if (conf) {
                if (conf->r1bio_pool)
                        mempool_destroy(conf->r1bio_pool);
-               if (conf->mirrors)
-                       kfree(conf->mirrors);
-               if (conf->poolinfo)
-                       kfree(conf->poolinfo);
+               kfree(conf->mirrors);
+               kfree(conf->poolinfo);
                kfree(conf);
                mddev->private = NULL;
        }
@@ -1311,10 +1445,8 @@ static int stop(mddev_t *mddev)
        blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
        if (conf->r1bio_pool)
                mempool_destroy(conf->r1bio_pool);
-       if (conf->mirrors)
-               kfree(conf->mirrors);
-       if (conf->poolinfo)
-               kfree(conf->poolinfo);
+       kfree(conf->mirrors);
+       kfree(conf->poolinfo);
        kfree(conf);
        mddev->private = NULL;
        return 0;
@@ -1349,17 +1481,26 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
         * We allocate a new r1bio_pool if we can.
         * Then raise a device barrier and wait until all IO stops.
         * Then resize conf->mirrors and swap in the new r1bio pool.
+        *
+        * At the same time, we "pack" the devices so that all the missing
+        * devices have the higher raid_disk numbers.
         */
        mempool_t *newpool, *oldpool;
        struct pool_info *newpoolinfo;
        mirror_info_t *newmirrors;
        conf_t *conf = mddev_to_conf(mddev);
+       int cnt;
 
-       int d;
+       int d, d2;
 
-       for (d= raid_disks; d < conf->raid_disks; d++)
-               if (conf->mirrors[d].rdev)
+       if (raid_disks < conf->raid_disks) {
+               cnt=0;
+               for (d= 0; d < conf->raid_disks; d++)
+                       if (conf->mirrors[d].rdev)
+                               cnt++;
+               if (cnt > raid_disks)
                        return -EBUSY;
+       }
 
        newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL);
        if (!newpoolinfo)
@@ -1384,14 +1525,18 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
        spin_lock_irq(&conf->resync_lock);
        conf->barrier++;
        wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
-                           conf->resync_lock, unplug_slaves(mddev));
+                           conf->resync_lock, raid1_unplug(mddev->queue));
        spin_unlock_irq(&conf->resync_lock);
 
        /* ok, everything is stopped */
        oldpool = conf->r1bio_pool;
        conf->r1bio_pool = newpool;
-       for (d=0; d < raid_disks && d < conf->raid_disks; d++)
-               newmirrors[d] = conf->mirrors[d];
+
+       for (d=d2=0; d < conf->raid_disks; d++)
+               if (conf->mirrors[d].rdev) {
+                       conf->mirrors[d].rdev->raid_disk = d2;
+                       newmirrors[d2++].rdev = conf->mirrors[d].rdev;
+               }
        kfree(conf->mirrors);
        conf->mirrors = newmirrors;
        kfree(conf->poolinfo);
@@ -1400,6 +1545,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
        mddev->degraded += (raid_disks - conf->raid_disks);
        conf->raid_disks = mddev->raid_disks = raid_disks;
 
+       conf->last_used = 0; /* just make sure it is in-range */
        spin_lock_irq(&conf->resync_lock);
        conf->barrier--;
        spin_unlock_irq(&conf->resync_lock);
index 3c37be6423d75a1a576cd545d80c0d76e25a246e..62ebb1bc72be24cc32ecc775c5bd71603d44e5c6 100644 (file)
@@ -700,6 +700,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
                return 0;
        }
 
+       md_write_start(mddev, bio);
+
        /*
         * Register the new request and wait if the reconstruction
         * thread has put up a bar for new requests.
@@ -774,7 +776,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
        rcu_read_unlock();
 
        atomic_set(&r10_bio->remaining, 1);
-       md_write_start(mddev);
+
        for (i = 0; i < conf->copies; i++) {
                struct bio *mbio;
                int d = r10_bio->devs[i].devnum;
@@ -1216,7 +1218,6 @@ static void raid10d(mddev_t *mddev)
        mdk_rdev_t *rdev;
 
        md_check_recovery(mddev);
-       md_handle_safemode(mddev);
 
        for (;;) {
                char b[BDEVNAME_SIZE];
@@ -1319,7 +1320,7 @@ static int init_resync(conf_t *conf)
  *
  */
 
-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
        conf_t *conf = mddev_to_conf(mddev);
        r10bio_t *r10_bio;
@@ -1333,7 +1334,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
 
        if (!conf->r10buf_pool)
                if (init_resync(conf))
-                       return -ENOMEM;
+                       return 0;
 
  skipped:
        max_sector = mddev->size << 1;
@@ -1341,15 +1342,15 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
                max_sector = mddev->resync_max_sectors;
        if (sector_nr >= max_sector) {
                close_sync(conf);
+               *skipped = 1;
                return sectors_skipped;
        }
        if (chunks_skipped >= conf->raid_disks) {
                /* if there has been nothing to do on any drive,
                 * then there is nothing to do at all..
                 */
-               sector_t sec = max_sector - sector_nr;
-               md_done_sync(mddev, sec, 1);
-               return sec + sectors_skipped;
+               *skipped = 1;
+               return (max_sector - sector_nr) + sectors_skipped;
        }
 
        /* make sure whole request will fit in a chunk - if chunks
@@ -1563,17 +1564,22 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
                }
        }
 
+       if (sectors_skipped)
+               /* pretend they weren't skipped, it makes
+                * no important difference in this case
+                */
+               md_done_sync(mddev, sectors_skipped, 1);
+
        return sectors_skipped + nr_sectors;
  giveup:
        /* There is nowhere to write, so all non-sync
         * drives must be failed, so try the next chunk...
         */
        {
-       int sec = max_sector - sector_nr;
+       sector_t sec = max_sector - sector_nr;
        sectors_skipped += sec;
        chunks_skipped ++;
        sector_nr = max_sector;
-       md_done_sync(mddev, sec, 1);
        goto skipped;
        }
 }
@@ -1731,8 +1737,7 @@ static int run(mddev_t *mddev)
 out_free_conf:
        if (conf->r10bio_pool)
                mempool_destroy(conf->r10bio_pool);
-       if (conf->mirrors)
-               kfree(conf->mirrors);
+       kfree(conf->mirrors);
        kfree(conf);
        mddev->private = NULL;
 out:
@@ -1748,8 +1753,7 @@ static int stop(mddev_t *mddev)
        blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
        if (conf->r10bio_pool)
                mempool_destroy(conf->r10bio_pool);
-       if (conf->mirrors)
-               kfree(conf->mirrors);
+       kfree(conf->mirrors);
        kfree(conf);
        mddev->private = NULL;
        return 0;
index 3cb11ac232fa8ca9ada29fb9cdb99e15cf1ba0f2..93a9726cc2d6793ed237bfa8d3f2a955da501667 100644 (file)
@@ -1411,6 +1411,8 @@ static int make_request (request_queue_t *q, struct bio * bi)
        sector_t logical_sector, last_sector;
        struct stripe_head *sh;
 
+       md_write_start(mddev, bi);
+
        if (bio_data_dir(bi)==WRITE) {
                disk_stat_inc(mddev->gendisk, writes);
                disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
@@ -1423,8 +1425,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
        last_sector = bi->bi_sector + (bi->bi_size>>9);
        bi->bi_next = NULL;
        bi->bi_phys_segments = 1;       /* over-loaded to count active stripes */
-       if ( bio_data_dir(bi) == WRITE )
-               md_write_start(mddev);
+
        for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
                DEFINE_WAIT(w);
                
@@ -1475,7 +1476,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
 }
 
 /* FIXME go_faster isn't used */
-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
        raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
        struct stripe_head *sh;
@@ -1498,8 +1499,8 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
         * nothing we can do.
         */
        if (mddev->degraded >= 1 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
-               int rv = (mddev->size << 1) - sector_nr;
-               md_done_sync(mddev, rv, 1);
+               sector_t rv = (mddev->size << 1) - sector_nr;
+               *skipped = 1;
                return rv;
        }
 
@@ -1546,7 +1547,6 @@ static void raid5d (mddev_t *mddev)
        PRINTK("+++ raid5d active\n");
 
        md_check_recovery(mddev);
-       md_handle_safemode(mddev);
 
        handled = 0;
        spin_lock_irq(&conf->device_lock);
index 908edd78a792b35740844a5048f507cb13f1285b..f62ea1a73d0d9d1b87f5f10d7b91a6f6d7f48b0d 100644 (file)
@@ -1570,6 +1570,8 @@ static int make_request (request_queue_t *q, struct bio * bi)
        sector_t logical_sector, last_sector;
        struct stripe_head *sh;
 
+       md_write_start(mddev, bi);
+
        if (bio_data_dir(bi)==WRITE) {
                disk_stat_inc(mddev->gendisk, writes);
                disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
@@ -1583,8 +1585,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
 
        bi->bi_next = NULL;
        bi->bi_phys_segments = 1;       /* over-loaded to count active stripes */
-       if ( bio_data_dir(bi) == WRITE )
-               md_write_start(mddev);
+
        for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
                DEFINE_WAIT(w);
 
@@ -1634,7 +1635,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
 }
 
 /* FIXME go_faster isn't used */
-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
        raid6_conf_t *conf = (raid6_conf_t *) mddev->private;
        struct stripe_head *sh;
@@ -1657,8 +1658,8 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
         * nothing we can do.
         */
        if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
-               int rv = (mddev->size << 1) - sector_nr;
-               md_done_sync(mddev, rv, 1);
+               sector_t rv = (mddev->size << 1) - sector_nr;
+               *skipped = 1;
                return rv;
        }
 
@@ -1705,7 +1706,6 @@ static void raid6d (mddev_t *mddev)
        PRINTK("+++ raid6d active\n");
 
        md_check_recovery(mddev);
-       md_handle_safemode(mddev);
 
        handled = 0;
        spin_lock_irq(&conf->device_lock);
index 80254caa444c9fc40bff4ebe3a8f4dd0bbf23878..48989eda2400a120e5fea0a7e74bc500309d10e5 100644 (file)
@@ -384,22 +384,14 @@ static unsigned short normal_i2c[] =
        I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1,
        I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver i2c_driver_adv7170;
index 95d0974b0ab53497a6163d537ec3614cf082f495..f898b65863741162d6269cf062d625e51660d3be 100644 (file)
@@ -434,22 +434,14 @@ static unsigned short normal_i2c[] =
        I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
        I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver i2c_driver_adv7175;
index cf0db2554a80d6632d8b87dcb3bf6650f8ebbe39..8733588f6db3db1905628cc1ba99a4c62c51ec9e 100644 (file)
@@ -500,22 +500,14 @@ static unsigned short normal_i2c[] = {
        I2C_BT819 >> 1,
        I2C_CLIENT_END,
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver i2c_driver_bt819;
index efe605a113a15fcfbb87db3f112ba70018068dfd..07f72f64c5f73c9776b44d1f09eac17a8c3c3e5d 100644 (file)
@@ -39,8 +39,8 @@
 MODULE_LICENSE("GPL");
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_BT832_ALT1>>1,I2C_BT832_ALT2>>1,I2C_CLIENT_END};
+static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
+                                      I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 /* ---------------------------------------------------------------------- */
index 72c7eb0f8c24f3f1d840fd3bad54c555d6eafdb7..a5d529ccf3ad174fb1aead3cac87e48f03dcebd2 100644 (file)
@@ -288,22 +288,14 @@ bt856_command (struct i2c_client *client,
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver i2c_driver_bt856;
index 7fbb8581a87da7c13e580cdd14e40e67421e4d23..09464d624a6b40b8f4f70dd3de571a47cad314ff 100644 (file)
@@ -147,7 +147,6 @@ static unsigned short normal_i2c[] = {
        I2C_MSP3400C_ALT  >> 1,
        I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* ----------------------------------------------------------------------- */
index ba69f09cbdd1f93e3bd6614b6b24072dad91e773..b8054da31ffd2f2036aa209acfe8bb5bdf43ed67 100644 (file)
@@ -64,7 +64,6 @@ static struct video_device saa_template;      /* Declared near bottom */
 
 /* Addresses to scan */
 static unsigned short normal_i2c[]      = { I2C_ADDRESS, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 static struct i2c_client client_template;
index d74caa139f0a733d190bb8cf8897bc82dc40d0bc..7ffa2e9a9bf3b78d2c66af08d11460d240cbf761 100644 (file)
@@ -132,7 +132,6 @@ static struct video_device saa_template;    /* Declared near bottom */
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 static struct i2c_client client_template;
index 64273b4385303e62e6f43fc1f8acfe6892d202db..22d055d8a695591d04b65107a6034488c462dcb5 100644 (file)
@@ -463,22 +463,14 @@ static unsigned short normal_i2c[] = {
        (I2C_SAA7110 >> 1) + 1,
        I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7110;
index 0a873112ae23db9a0a82a69056a1f733eb32f015..fcd897382fcfc0fe5dc1271db95a6ae0079634ca 100644 (file)
@@ -482,22 +482,14 @@ saa7111_command (struct i2c_client *client,
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7111;
index e73023695e58593659c01e52831f353e0fd4f2bd..2ba997f5ef1d50c20a785eadc3a2bfba2f3779f8 100644 (file)
@@ -820,22 +820,14 @@ saa7114_command (struct i2c_client *client,
  */
 static unsigned short normal_i2c[] =
     { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7114;
index 1db0226829806af405a786df5d0ae5e20f4beee7..42c2b565c9fed172168652142757e729e724517f 100644 (file)
@@ -22,7 +22,6 @@
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
index 5f0b224c3cb63718baad675ab50e59e1be3d8064..108e7a4a02734dbd9d1e803a0a40ab5ac2ad3691 100644 (file)
@@ -380,22 +380,14 @@ saa7185_command (struct i2c_client *client,
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7185;
index 376a4a439e9b52eaf729951e33b96cc09f2a53c9..07ba6d3ed08c861e8c316d4becc84c93600637e8 100644 (file)
@@ -74,7 +74,6 @@ static unsigned short normal_i2c[] = {
        I2C_TDA7432 >> 1,
        I2C_CLIENT_END,
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END, I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 /* Structure of address and subaddresses for the tda7432 */
index b5177c6f54f6a3349a25015f48d3ef01eb3e7eb6..c29bdfc3244e8f2562e9744d5f8d508f89a4b525 100644 (file)
@@ -43,7 +43,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 
 /* 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 };
 
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
index 4f1114c033a11d9d891f63c500e918ca32e15bbb..97b113e070f3c549179e31ff0ab719c6450d44f1 100644 (file)
@@ -44,7 +44,6 @@ static unsigned short normal_i2c[] =  {
     I2C_TDA9875 >> 1,
     I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* This is a superset of the TDA9875 */
index debef1910c3741077b1b3e049f8163c866c92fdd..7e6e6dd966a2f0de9aa00002c87edbed158bce36 100644 (file)
@@ -33,7 +33,6 @@ static unsigned short normal_i2c[] = {
        0x96 >>1,
        I2C_CLIENT_END,
 };
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* insmod options */
index 3ec39550bf467a6ba1f75552d4cc6b7862754f8e..b44db8a7b94dfed4ca0e6e3c1acd03ad9c4465d0 100644 (file)
@@ -43,7 +43,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 
 /* 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 };
 
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
index bd10710fd909af23b72cfb4c01c01fe1c0c04f50..48d4db7d507b1d77b14429abae83d2960bb1a9a9 100644 (file)
@@ -40,7 +40,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 
 /* 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 };
 
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
index 6b20aa902a8f69b41422feee7982aa84f72e20bc..51748c6578d1f83a97055bcb5417c1878eb6cb48 100644 (file)
@@ -34,19 +34,14 @@ static int this_adap;
 static struct i2c_client client_template;
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {0x60, 0x61, I2C_CLIENT_END};
-static unsigned short probe[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2]       = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
 
 static struct i2c_client_address_data addr_data = {
-       normal_i2c, normal_i2c_range, 
-       probe, probe_range, 
-       ignore, ignore_range, 
-       force
+       .normal_i2c     = normal_i2c,
+       .probe          = &ignore,
+       .ignore         = &ignore,
+       .force          = &ignore,
 };
 
 /* ---------------------------------------------------------------------- */
index 6212388edb75b0035b19761eb00bfec503b0a4ce..81882ddab859dd52c3db6ecfbfeac5c228b6a97f 100644 (file)
 /* standard i2c insmod options */
 static unsigned short normal_i2c[] = {
        0x4b, /* tda8290 */
-       I2C_CLIENT_END
-};
-static unsigned short normal_i2c_range[] = {
-       0x60, 0x6f,
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
        I2C_CLIENT_END
 };
 I2C_CLIENT_INSMOD;
@@ -225,9 +223,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
 static int tuner_probe(struct i2c_adapter *adap)
 {
        if (0 != addr) {
-               normal_i2c[0]       = addr;
-               normal_i2c_range[0] = addr;
-               normal_i2c_range[1] = addr;
+               normal_i2c[0] = addr;
+               normal_i2c[1] = I2C_CLIENT_END;
        }
        this_adap = 0;
 
index 80dc34f18c2c86196fa8c17b2afc4fc22540b69e..41b635e0d3c6a5b6d758e1b7254acd8995b0baeb 100644 (file)
@@ -148,7 +148,6 @@ static unsigned short normal_i2c[] = {
        I2C_TDA9874   >> 1,
        I2C_PIC16C54  >> 1,
        I2C_CLIENT_END };
-static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 static struct i2c_driver driver;
index e1443a0937e3c8cb5679515ca3284ee3f5258698..3d216973798c6755353d6f8d17aa31f1b112c54c 100644 (file)
@@ -482,7 +482,6 @@ static unsigned short normal_i2c[] = {
        0xa0 >> 1,
        I2C_CLIENT_END,
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 struct i2c_driver i2c_driver_tveeprom;
index 0fd6c9a709179b845c59730e9e5d399daf8e0f19..5dbd9f6bf353b4730309411e514a4ba0c77a6a54 100644 (file)
@@ -569,22 +569,14 @@ static unsigned short normal_i2c[] =
     { I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4,
        I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
        .normal_i2c             = normal_i2c,
-       .normal_i2c_range       = normal_i2c_range,
-       .probe                  = probe,
-       .probe_range            = probe_range,
-       .ignore                 = ignore,
-       .ignore_range           = ignore_range,
-       .force                  = force
+       .probe                  = &ignore,
+       .ignore                 = &ignore,
+       .force                  = &ignore,
 };
 
 static struct i2c_driver vpx3220_i2c_driver;
index 245b0058381ddd9e2494e4eb2550e215f021abf5..07a085ccbd5b5db673ac2eff7fcc929e6e3c8a20 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "ibmasm.h"
+#include "lowlevel.h"
 
 static void exec_next_command(struct service_processor *sp);
 static void free_command(struct kobject *kobj);
@@ -31,8 +32,9 @@ static struct kobj_type ibmasm_cmd_kobj_type = {
        .release = free_command,
 };
 
+static atomic_t command_count = ATOMIC_INIT(0);
 
-struct command *ibmasm_new_command(size_t buffer_size)
+struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size)
 {
        struct command *cmd;
 
@@ -55,11 +57,15 @@ struct command *ibmasm_new_command(size_t buffer_size)
 
        kobject_init(&cmd->kobj);
        cmd->kobj.ktype = &ibmasm_cmd_kobj_type;
+       cmd->lock = &sp->lock;
 
        cmd->status = IBMASM_CMD_PENDING;
        init_waitqueue_head(&cmd->wait);
        INIT_LIST_HEAD(&cmd->queue_node);
 
+       atomic_inc(&command_count);
+       dbg("command count: %d\n", atomic_read(&command_count));
+
        return cmd;
 }
 
@@ -68,6 +74,8 @@ static void free_command(struct kobject *kobj)
        struct command *cmd = to_command(kobj);
  
        list_del(&cmd->queue_node);
+       atomic_dec(&command_count);
+       dbg("command count: %d\n", atomic_read(&command_count));
        kfree(cmd->buffer);
        kfree(cmd);
 }
@@ -94,8 +102,14 @@ static struct command *dequeue_command(struct service_processor *sp)
 
 static inline void do_exec_command(struct service_processor *sp)
 {
+       char tsbuf[32];
+
+       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+
        if (ibmasm_send_i2o_message(sp)) {
                sp->current_command->status = IBMASM_CMD_FAILED;
+               wake_up(&sp->current_command->wait);
+               command_put(sp->current_command);
                exec_next_command(sp);
        }
 }
@@ -111,14 +125,16 @@ static inline void do_exec_command(struct service_processor *sp)
 void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
 {
        unsigned long flags;
+       char tsbuf[32];
+
+       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
 
        spin_lock_irqsave(&sp->lock, flags);
 
        if (!sp->current_command) {
-               command_get(cmd);
                sp->current_command = cmd;
+               command_get(sp->current_command);
                spin_unlock_irqrestore(&sp->lock, flags);
-
                do_exec_command(sp);
        } else {
                enqueue_command(sp, cmd);
@@ -129,9 +145,9 @@ void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
 static void exec_next_command(struct service_processor *sp)
 {
        unsigned long flags;
+       char tsbuf[32];
 
-       wake_up(&sp->current_command->wait);
-       command_put(sp->current_command);
+       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
 
        spin_lock_irqsave(&sp->lock, flags);
        sp->current_command = dequeue_command(sp);
@@ -169,7 +185,9 @@ void ibmasm_receive_command_response(struct service_processor *sp, void *respons
        if (!sp->current_command) 
                return; 
 
-       memcpy(cmd->buffer, response, min(size, cmd->buffer_size));
+       memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size));
        cmd->status = IBMASM_CMD_COMPLETE;
+       wake_up(&sp->current_command->wait);
+       command_put(sp->current_command);
        exec_next_command(sp);
 }
index 478a8d898fc1e4b5f9ac9f12edb66cbfe745466a..13c52f866e2e8c1b6cb9a9c815ed86981e5ed4e1 100644 (file)
@@ -33,7 +33,13 @@ void ibmasm_receive_message(struct service_processor *sp, void *message, int mes
        u32 size;
        struct dot_command_header *header = (struct dot_command_header *)message;
 
+       if (message_size == 0)
+               return;
+
        size = get_dot_command_size(message);
+       if (size == 0)
+               return;
+
        if (size > message_size)
                size = message_size;
 
@@ -67,7 +73,7 @@ int ibmasm_send_driver_vpd(struct service_processor *sp)
        u8 *vpd_data;
        int result = 0;
 
-       command = ibmasm_new_command(INIT_BUFFER_SIZE);
+       command = ibmasm_new_command(sp, INIT_BUFFER_SIZE);
        if (command == NULL)
                return -ENOMEM;
 
@@ -121,7 +127,7 @@ int ibmasm_send_os_state(struct service_processor *sp, int os_state)
        struct os_state_command *os_state_cmd;
        int result = 0;
 
-       cmd = ibmasm_new_command(sizeof(struct os_state_command));
+       cmd = ibmasm_new_command(sp, sizeof(struct os_state_command));
        if (cmd == NULL)
                return -ENOMEM;
 
index e100f34f158733b60322acb6aee4e282db162ce4..fe1e819235a49c18938a775d4f9d2fb75176abfc 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "ibmasm.h"
+#include "lowlevel.h"
 
 /*
  * ASM service processor event handling routines.
@@ -34,7 +35,6 @@
  * circular buffer.
  */
 
-
 static void wake_up_event_readers(struct service_processor *sp)
 {
        struct event_reader *reader;
@@ -63,7 +63,7 @@ void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int
        spin_lock_irqsave(&sp->lock, flags);
        /* copy the event into the next slot in the circular buffer */
        event = &buffer->events[buffer->next_index];
-       memcpy(event->data, data, data_size);
+       memcpy_fromio(event->data, data, data_size);
        event->data_size = data_size;
        event->serial_number = buffer->next_serial_number;
 
@@ -93,7 +93,10 @@ int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *rea
        unsigned int index;
        unsigned long flags;
 
-       if (wait_event_interruptible(reader->wait, event_available(buffer, reader)))
+       reader->cancelled = 0;
+
+       if (wait_event_interruptible(reader->wait,
+                       event_available(buffer, reader) || reader->cancelled))
                return -ERESTARTSYS;
 
        if (!event_available(buffer, reader))
@@ -116,6 +119,12 @@ int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *rea
        return event->data_size;
 }
 
+void ibmasm_cancel_next_event(struct event_reader *reader)
+{
+        reader->cancelled = 1;
+        wake_up_interruptible(&reader->wait);
+}
+
 void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader)
 {
        unsigned long flags;
@@ -131,8 +140,6 @@ void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_r
 {
        unsigned long flags;
 
-       wake_up_interruptible(&reader->wait);
-
        spin_lock_irqsave(&sp->lock, flags);
        list_del(&reader->node);
        spin_unlock_irqrestore(&sp->lock, flags);
@@ -164,6 +171,5 @@ int ibmasm_event_buffer_init(struct service_processor *sp)
 
 void ibmasm_event_buffer_exit(struct service_processor *sp)
 {
-       wake_up_event_readers(sp);
        kfree(sp->event_buffer);
 }
index ce09309174d68a3b2e38b3f8a47ecccf5f32e740..f295401fac21cb9f492fb3f75eb89e53dd4b6b4a 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/notifier.h>
 #include "ibmasm.h"
 #include "dot_command.h"
+#include "lowlevel.h"
 
 static int suspend_heartbeats = 0;
 
@@ -62,7 +63,7 @@ void ibmasm_unregister_panic_notifier(void)
 
 int ibmasm_heartbeat_init(struct service_processor *sp)
 {
-       sp->heartbeat = ibmasm_new_command(HEARTBEAT_BUFFER_SIZE);
+       sp->heartbeat = ibmasm_new_command(sp, HEARTBEAT_BUFFER_SIZE);
        if (sp->heartbeat == NULL)
                return -ENOMEM;
 
@@ -71,6 +72,12 @@ int ibmasm_heartbeat_init(struct service_processor *sp)
 
 void ibmasm_heartbeat_exit(struct service_processor *sp)
 {
+       char tsbuf[32];
+
+       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+       ibmasm_wait_for_response(sp->heartbeat, IBMASM_CMD_TIMEOUT_NORMAL);
+       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+       suspend_heartbeats = 1;
        command_put(sp->heartbeat);
 }
 
@@ -78,14 +85,16 @@ void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size
 {
        struct command *cmd = sp->heartbeat;
        struct dot_command_header *header = (struct dot_command_header *)cmd->buffer;
+       char tsbuf[32];
 
+       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
        if (suspend_heartbeats)
                return;
 
        /* return the received dot command to sender */
        cmd->status = IBMASM_CMD_PENDING;
        size = min(size, cmd->buffer_size);
-       memcpy(cmd->buffer, message, size);
+       memcpy_fromio(cmd->buffer, message, size);
        header->type = sp_write;
        ibmasm_exec_command(sp, cmd);
 }
index 6fec7fd8cd1aae3d83530aefaa33a83ffc6f51b3..ecce4ffd3e23f21877df72759efba566c30e1bfe 100644 (file)
 #include <linux/version.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/input.h>
 
 /* Driver identification */
 #define DRIVER_NAME    "ibmasm"
-#define DRIVER_VERSION  "0.4"
-#define DRIVER_AUTHOR   "Max Asbock"
+#define DRIVER_VERSION  "1.0"
+#define DRIVER_AUTHOR   "Max Asbock <masbock@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
 #define DRIVER_DESC     "IBM ASM Service Processor Driver"
 
 #define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME)
 #define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME)
 
+extern int ibmasm_debug;
+#define dbg(STR, ARGS...)                                      \
+       do {                                                    \
+               if (ibmasm_debug)                               \
+                       printk(KERN_DEBUG STR , ##ARGS);        \
+       } while (0)
+
+static inline char *get_timestamp(char *buf)
+{
+       struct timeval now;
+       do_gettimeofday(&now);
+       sprintf(buf, "%lu.%lu", now.tv_sec, now.tv_usec);
+       return buf;
+}
 
 #define IBMASM_CMD_PENDING     0       
 #define IBMASM_CMD_COMPLETE    1       
@@ -52,7 +67,7 @@
 #define IBMASM_CMD_TIMEOUT_NORMAL      45
 #define IBMASM_CMD_TIMEOUT_EXTRA       240
 
-#define IBMASM_CMD_MAX_BUFFER_SIZE     0x4000
+#define IBMASM_CMD_MAX_BUFFER_SIZE     0x8000
 
 #define REVERSE_HEARTBEAT_TIMEOUT      120
 
@@ -80,12 +95,17 @@ struct command {
        size_t                  buffer_size;
        int                     status;
        struct kobject          kobj;
+       spinlock_t              *lock;
 };
 #define to_command(c) container_of(c, struct command, kobj)
 
 static inline void command_put(struct command *cmd)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(cmd->lock, flags);
         kobject_put(&cmd->kobj);
+       spin_unlock_irqrestore(cmd->lock, flags);
 }
 
 static inline void command_get(struct command *cmd)
@@ -108,6 +128,7 @@ struct event_buffer {
 };
 
 struct event_reader {
+       int                     cancelled;
        unsigned int            next_serial_number;
        wait_queue_head_t       wait;
        struct list_head        node;
@@ -120,41 +141,11 @@ struct reverse_heartbeat {
        unsigned int            stopped;
 };
 
-
-/* remote console events */
-struct mouse_event {
-       long            x;
-       long            y;
-       unsigned char   buttons;
-       unsigned char   transitions;
-};
-
-struct keyboard_event {
-       unsigned long   key_code;
-       unsigned char   key_down;
+struct ibmasm_remote {
+       struct input_dev keybd_dev;
+       struct input_dev mouse_dev;
 };
 
-struct remote_event {
-       unsigned long   type;
-       union {
-               struct mouse_event      mouse;
-               struct keyboard_event   keyboard;
-       } data;
-};
-
-#define DRIVER_REMOTE_QUEUE_SIZE 240
-
-struct remote_queue {
-       struct remote_event     *start;
-       struct remote_event     *end;
-       struct remote_event     *reader;
-       struct remote_event     *writer;
-       unsigned int            size;
-       int                     open;
-       wait_queue_head_t       wait;
-};
-
-
 struct service_processor {
        struct list_head        node;
        spinlock_t              lock;
@@ -167,13 +158,13 @@ struct service_processor {
        char                    dirname[IBMASM_NAME_SIZE];
        char                    devname[IBMASM_NAME_SIZE];
        unsigned int            number;
-       struct remote_queue     remote_queue;
+       struct ibmasm_remote    *remote;
        int                     serial_line;
        struct device           *dev;
 };
 
 /* command processing */
-extern struct command *ibmasm_new_command(size_t buffer_size);
+extern struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
 extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
 extern void ibmasm_wait_for_response(struct command *cmd, int timeout);
 extern void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);
@@ -185,6 +176,7 @@ extern void ibmasm_receive_event(struct service_processor *sp, void *data,  unsi
 extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
 extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
 extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
+extern void ibmasm_cancel_next_event(struct event_reader *reader);
 
 /* heartbeat - from SP to OS */
 extern void ibmasm_register_panic_notifier(void);
@@ -208,11 +200,9 @@ extern int ibmasm_send_i2o_message(struct service_processor *sp);
 extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs);
 
 /* remote console */
-extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
-extern int ibmasm_init_remote_queue(struct service_processor *sp);
-extern void ibmasm_free_remote_queue(struct service_processor *sp);
-extern void ibmasm_advance_reader(struct remote_queue *q, unsigned int n);
-extern size_t ibmasm_events_available(struct remote_queue *q);
+extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp, struct pt_regs *regs);
+extern int ibmasm_init_remote_input_dev(struct service_processor *sp);
+extern void ibmasm_free_remote_input_dev(struct service_processor *sp);
 
 /* file system */
 extern int ibmasmfs_register(void);
index 866e867e68f2ac95f853747f443471c9f4c425f4..5c550fcac2c487f176ba6a2881d41d1449423a15 100644 (file)
@@ -37,9 +37,7 @@
  *    |   |-- event
  *    |   |-- reverse_heartbeat
  *    |   `-- remote_video
- *    |       |-- connected
  *    |       |-- depth
- *    |       |-- events
  *    |       |-- height
  *    |       `-- width
  *    .
@@ -50,9 +48,7 @@
  *        |-- event
  *        |-- reverse_heartbeat
  *        `-- remote_video
- *            |-- connected
  *            |-- depth
- *            |-- events
  *            |-- height
  *            `-- width
  *
  * remote_video/width: control remote display settings
  *     write: set value
  *     read: read value
- *
- * remote_video/connected
- *     read: return "1" if web browser VNC java applet is connected, 
- *             "0" otherwise
- *
- * remote_video/events
- *     read: sleep until a remote mouse or keyboard event occurs, then return
- *             then event.
  */
 
 #include <linux/fs.h>
@@ -333,7 +321,7 @@ static ssize_t command_file_write(struct file *file, const char __user *ubuff, s
        if (command_data->command)
                return -EAGAIN;
 
-       cmd = ibmasm_new_command(count);
+       cmd = ibmasm_new_command(command_data->sp, count);
        if (!cmd)
                return -ENOMEM;
 
@@ -374,6 +362,7 @@ static int event_file_open(struct inode *inode, struct file *file)
        ibmasm_event_reader_register(sp, &event_data->reader);
 
        event_data->sp = sp;
+       event_data->active = 0;
        file->private_data = event_data;
        return 0;
 }
@@ -391,7 +380,9 @@ static ssize_t event_file_read(struct file *file, char __user *buf, size_t count
 {
        struct ibmasmfs_event_data *event_data = file->private_data;
        struct event_reader *reader = &event_data->reader;
+       struct service_processor *sp = event_data->sp;
        int ret;
+       unsigned long flags;
 
        if (*offset < 0)
                return -EINVAL;
@@ -400,17 +391,32 @@ static ssize_t event_file_read(struct file *file, char __user *buf, size_t count
        if (*offset != 0)
                return 0;
 
-       ret = ibmasm_get_next_event(event_data->sp, reader);
+       spin_lock_irqsave(&sp->lock, flags);
+       if (event_data->active) {
+               spin_unlock_irqrestore(&sp->lock, flags);
+               return -EBUSY;
+       }
+       event_data->active = 1;
+       spin_unlock_irqrestore(&sp->lock, flags);
+
+       ret = ibmasm_get_next_event(sp, reader);
        if (ret <= 0)
-               return ret;
+               goto out;
 
-       if (count < reader->data_size)
-               return -EINVAL;
+       if (count < reader->data_size) {
+               ret = -EINVAL;
+               goto out;
+       }
 
-        if (copy_to_user(buf, reader->data, reader->data_size))
-               return -EFAULT;
+        if (copy_to_user(buf, reader->data, reader->data_size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+       ret = reader->data_size;
 
-       return reader->data_size;
+out:
+       event_data->active = 0;
+       return ret;
 }
 
 static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
@@ -424,7 +430,7 @@ static ssize_t event_file_write(struct file *file, const char __user *buf, size_
        if (*offset != 0)
                return 0;
 
-       wake_up_interruptible(&event_data->reader.wait);
+       ibmasm_cancel_next_event(&event_data->reader);
        return 0;
 }
 
@@ -575,75 +581,6 @@ static ssize_t remote_settings_file_write(struct file *file, const char __user *
        return count;
 }
 
-static int remote_event_file_open(struct inode *inode, struct file *file)
-{
-       struct service_processor *sp;
-       unsigned long flags;
-       struct remote_queue *q;
-       
-       file->private_data = inode->u.generic_ip;
-       sp = file->private_data;
-       q = &sp->remote_queue;
-
-       /* allow only one event reader */
-       spin_lock_irqsave(&sp->lock, flags);
-       if (q->open) {
-               spin_unlock_irqrestore(&sp->lock, flags);
-               return -EBUSY;
-       }
-       q->open = 1;
-       spin_unlock_irqrestore(&sp->lock, flags);
-
-       enable_mouse_interrupts(sp);
-       
-       return 0;
-}
-
-static int remote_event_file_close(struct inode *inode, struct file *file)
-{
-       struct service_processor *sp = file->private_data;
-
-       disable_mouse_interrupts(sp);
-       wake_up_interruptible(&sp->remote_queue.wait);
-       sp->remote_queue.open = 0;
-
-       return 0;
-}
-
-static ssize_t remote_event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
-{
-       struct service_processor *sp = file->private_data;
-       struct remote_queue *q = &sp->remote_queue;
-       size_t data_size;
-       struct remote_event *reader = q->reader;
-       size_t num_events;
-
-       if (*offset < 0)
-               return -EINVAL;
-       if (count == 0 || count > 1024)
-               return 0;
-       if (*offset != 0)
-               return 0;
-
-       if (wait_event_interruptible(q->wait, q->reader != q->writer))
-               return -ERESTARTSYS;
-
-       /* only get multiples of struct remote_event */
-       num_events = min((count/sizeof(struct remote_event)), ibmasm_events_available(q));
-       if (!num_events)
-               return 0;
-
-       data_size = num_events * sizeof(struct remote_event);
-
-       if (copy_to_user(buf, reader, data_size))
-               return -EFAULT;
-
-       ibmasm_advance_reader(q, num_events);
-
-       return data_size;
-}
-
-
 static struct file_operations command_fops = {
        .open =         command_file_open,
        .release =      command_file_close,
@@ -672,12 +609,6 @@ static struct file_operations remote_settings_fops = {
        .write =        remote_settings_file_write,
 };
 
-static struct file_operations remote_event_fops = {
-       .open =         remote_event_file_open,
-       .release =      remote_event_file_close,
-       .read =         remote_event_file_read,
-};
-
 
 static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root)
 {
@@ -703,7 +634,5 @@ static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root)
                ibmasmfs_create_file(sb, remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR);
                ibmasmfs_create_file(sb, remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR);
                ibmasmfs_create_file(sb, remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR);
-               ibmasmfs_create_file(sb, remote_dir, "connected", &remote_settings_fops, (void *)vnc_status(sp), S_IRUSR);
-               ibmasmfs_create_file(sb, remote_dir, "events", &remote_event_fops, (void *)sp, S_IRUSR);
        }
 }
index 5156de2759d864751bc8e9b4dcd12773070957a1..47949a2c7e94f752e737e4e7b0be00e6aee5ff39 100644 (file)
@@ -46,8 +46,8 @@ int ibmasm_send_i2o_message(struct service_processor *sp)
 
        message = get_i2o_message(sp->base_address, mfa);
 
-       memcpy(&message->header, &header, sizeof(struct i2o_header));
-       memcpy(&message->data, command->buffer, command_size);
+       memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
+       memcpy_toio(&message->data, command->buffer, command_size);
 
        set_mfa_inbound(sp->base_address, mfa);
 
@@ -59,23 +59,27 @@ 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 __iomem *base_address = sp->base_address;
+       char tsbuf[32];
 
        if (!sp_interrupt_pending(base_address))
                return IRQ_NONE;
 
+       dbg("respond to interrupt at %s\n", get_timestamp(tsbuf));
+
        if (mouse_interrupt_pending(sp)) {
-               ibmasm_handle_mouse_interrupt(sp);
-               mfa = get_mfa_outbound(base_address);
+               ibmasm_handle_mouse_interrupt(sp, regs);
                clear_mouse_interrupt(sp);
-               set_mfa_outbound(base_address, mfa);
-               return IRQ_HANDLED;
        }
 
        mfa = get_mfa_outbound(base_address);
        if (valid_mfa(mfa)) {
                struct i2o_message *msg = get_i2o_message(base_address, mfa);
                ibmasm_receive_message(sp, &msg->data, incoming_data_size(msg));
-       }
+       } else
+               dbg("didn't get a valid MFA\n");
+
        set_mfa_outbound(base_address, mfa);
+       dbg("finished interrupt at   %s\n", get_timestamp(tsbuf));
+
        return IRQ_HANDLED;
 }
index 777432ae764aadeadfb645967d687e4309b18400..1fdf03fd2da751181c1226d6441de7dab786b6e2 100644 (file)
 #include "lowlevel.h"
 #include "remote.h"
 
+int ibmasm_debug = 0;
+module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
+
 
 static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-       int err, result = -ENOMEM;
+       int result;
        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;
+       if ((result = pci_enable_device(pdev))) {
+               dev_err(&pdev->dev, "Failed to enable PCI device\n");
+               return result;
        }
+       if ((result = pci_request_regions(pdev, DRIVER_NAME))) {
+               dev_err(&pdev->dev, "Failed to allocate PCI resources\n");
+               goto error_resources;
+       }
+       /* vnc client won't work without bus-mastering */
+       pci_set_master(pdev);
 
        sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL);
        if (sp == NULL) {
@@ -76,6 +85,9 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
        }
        memset(sp, 0, sizeof(struct service_processor));
 
+       sp->lock = SPIN_LOCK_UNLOCKED;
+       INIT_LIST_HEAD(&sp->command_queue);
+
        pci_set_drvdata(pdev, (void *)sp);
        sp->dev = &pdev->dev;
        sp->number = pdev->bus->number;
@@ -101,15 +113,6 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
                goto error_ioremap;
        }
 
-       result = ibmasm_init_remote_queue(sp);
-       if (result) {
-               dev_err(sp->dev, "Failed to initialize remote queue\n");
-               goto error_remote_queue;
-       }
-
-       spin_lock_init(&sp->lock);
-       INIT_LIST_HEAD(&sp->command_queue);
-
        result = request_irq(sp->irq, ibmasm_interrupt_handler, SA_SHIRQ, sp->devname, (void*)sp);
        if (result) {
                dev_err(sp->dev, "Failed to register interrupt handler\n");
@@ -117,7 +120,12 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
        }
 
        enable_sp_interrupts(sp->base_address);
-       disable_mouse_interrupts(sp);
+
+       result = ibmasm_init_remote_input_dev(sp);
+       if (result) {
+               dev_err(sp->dev, "Failed to initialize remote queue\n");
+               goto error_send_message;
+       }
 
        result = ibmasm_send_driver_vpd(sp);
        if (result) {
@@ -133,30 +141,25 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
 
        ibmasm_register_uart(sp);
 
-       dev_printk(KERN_DEBUG, &pdev->dev, "WARNING: This software may not be supported or function\n");
-       dev_printk(KERN_DEBUG, &pdev->dev, "correctly on your IBM server. Please consult the IBM\n");
-       dev_printk(KERN_DEBUG, &pdev->dev, "ServerProven website\n");
-       dev_printk(KERN_DEBUG, &pdev->dev, "http://www.pc.ibm.com/ww/eserver/xseries/serverproven\n");
-       dev_printk(KERN_DEBUG, &pdev->dev, "for information on the specific driver level and support\n");
-       dev_printk(KERN_DEBUG, &pdev->dev, "statement for your IBM server.\n");
-
        return 0;
 
 error_send_message:
        disable_sp_interrupts(sp->base_address);
+       ibmasm_free_remote_input_dev(sp);
        free_irq(sp->irq, (void *)sp);
 error_request_irq:
-       ibmasm_free_remote_queue(sp);
-error_remote_queue:
        iounmap(sp->base_address);
 error_ioremap:
        ibmasm_heartbeat_exit(sp);
 error_heartbeat:
        ibmasm_event_buffer_exit(sp);
 error_eventbuffer:
+       pci_set_drvdata(pdev, NULL);
        kfree(sp);
 error_kmalloc:
-       pci_disable_device(pdev);
+        pci_release_regions(pdev);
+error_resources:
+        pci_disable_device(pdev);
 
        return result;
 }
@@ -165,16 +168,24 @@ static void __devexit ibmasm_remove_one(struct pci_dev *pdev)
 {
        struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
 
+       dbg("Unregistering UART\n");
        ibmasm_unregister_uart(sp);
-       ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN);
+       dbg("Sending OS down message\n");
+       if (ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN))
+               err("failed to get repsonse to 'Send OS State' command\n");
+       dbg("Disabling heartbeats\n");
+       ibmasm_heartbeat_exit(sp);
+       dbg("Disabling interrupts\n");
        disable_sp_interrupts(sp->base_address);
-       disable_mouse_interrupts(sp);
+       dbg("Freeing SP irq\n");
        free_irq(sp->irq, (void *)sp);
-       ibmasm_heartbeat_exit(sp);
-       ibmasm_free_remote_queue(sp);
+       dbg("Cleaning up\n");
+       ibmasm_free_remote_input_dev(sp);
        iounmap(sp->base_address);
        ibmasm_event_buffer_exit(sp);
+       pci_set_drvdata(pdev, NULL);
        kfree(sp);
+       pci_release_regions(pdev);
        pci_disable_device(pdev);
 }
 
index 93d9c1b2ad6f0de596adf483b8a57f19f9a2af6e..f8fdb2d5417ef3a31c15cb4d761c2319b0ad8011 100644 (file)
@@ -63,7 +63,7 @@ int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_
        int times_failed = 0;
        int result = 1;
 
-       cmd = ibmasm_new_command(sizeof rhb_dot_cmd);
+       cmd = ibmasm_new_command(sp, sizeof rhb_dot_cmd);
        if (!cmd)
                return -ENOMEM;
 
index 520c3f10c271e0cc928ae96e51cc032631b105d8..d3c48d23ee5110e2740975d320a7c9cf6d0410d4 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * IBM ASM Service Processor Device Driver
  *
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Authors: Max Asböck <amax@us.ibm.com>
+ *          Vernon Mauery <vernux@us.ibm.com>
  *
  */
 
 /* Remote mouse and keyboard event handling functions */
 
+#include <linux/pci.h>
 #include "ibmasm.h"
 #include "remote.h"
 
-int ibmasm_init_remote_queue(struct service_processor *sp)
-{
-       struct remote_queue *q = &sp->remote_queue;
-
-       disable_mouse_interrupts(sp);
+static int xmax = 1600;
+static int ymax = 1200;
 
-       q->open = 0;
-       q->size = 0;
 
-       q->start = kmalloc(DRIVER_REMOTE_QUEUE_SIZE * sizeof(struct remote_event), GFP_KERNEL);
-        if (q->start == 0)
-                return -ENOMEM;
+static unsigned short xlate_high[XLATE_SIZE] = {
+       [KEY_SYM_ENTER & 0xff] = KEY_ENTER,
+       [KEY_SYM_KPSLASH & 0xff] = KEY_KPSLASH,
+       [KEY_SYM_KPSTAR & 0xff] = KEY_KPASTERISK,
+       [KEY_SYM_KPMINUS & 0xff] = KEY_KPMINUS,
+       [KEY_SYM_KPDOT & 0xff] = KEY_KPDOT,
+       [KEY_SYM_KPPLUS & 0xff] = KEY_KPPLUS,
+       [KEY_SYM_KP0 & 0xff] = KEY_KP0,
+       [KEY_SYM_KP1 & 0xff] = KEY_KP1,
+       [KEY_SYM_KP2 & 0xff] = KEY_KP2, [KEY_SYM_KPDOWN & 0xff] = KEY_KP2,
+       [KEY_SYM_KP3 & 0xff] = KEY_KP3,
+       [KEY_SYM_KP4 & 0xff] = KEY_KP4, [KEY_SYM_KPLEFT & 0xff] = KEY_KP4,
+       [KEY_SYM_KP5 & 0xff] = KEY_KP5,
+       [KEY_SYM_KP6 & 0xff] = KEY_KP6, [KEY_SYM_KPRIGHT & 0xff] = KEY_KP6,
+       [KEY_SYM_KP7 & 0xff] = KEY_KP7,
+       [KEY_SYM_KP8 & 0xff] = KEY_KP8, [KEY_SYM_KPUP & 0xff] = KEY_KP8,
+       [KEY_SYM_KP9 & 0xff] = KEY_KP9,
+       [KEY_SYM_BK_SPC & 0xff] = KEY_BACKSPACE,
+       [KEY_SYM_TAB & 0xff] = KEY_TAB,
+       [KEY_SYM_CTRL & 0xff] = KEY_LEFTCTRL,
+       [KEY_SYM_ALT & 0xff] = KEY_LEFTALT,
+       [KEY_SYM_INSERT & 0xff] = KEY_INSERT,
+       [KEY_SYM_DELETE & 0xff] = KEY_DELETE,
+       [KEY_SYM_SHIFT & 0xff] = KEY_LEFTSHIFT,
+       [KEY_SYM_UARROW & 0xff] = KEY_UP,
+       [KEY_SYM_DARROW & 0xff] = KEY_DOWN,
+       [KEY_SYM_LARROW & 0xff] = KEY_LEFT,
+       [KEY_SYM_RARROW & 0xff] = KEY_RIGHT,
+       [KEY_SYM_ESCAPE & 0xff] = KEY_ESC,
+        [KEY_SYM_PAGEUP & 0xff] = KEY_PAGEUP,
+        [KEY_SYM_PAGEDOWN & 0xff] = KEY_PAGEDOWN,
+        [KEY_SYM_HOME & 0xff] = KEY_HOME,
+        [KEY_SYM_END & 0xff] = KEY_END,
+       [KEY_SYM_F1 & 0xff] = KEY_F1,
+       [KEY_SYM_F2 & 0xff] = KEY_F2,
+       [KEY_SYM_F3 & 0xff] = KEY_F3,
+       [KEY_SYM_F4 & 0xff] = KEY_F4,
+       [KEY_SYM_F5 & 0xff] = KEY_F5,
+       [KEY_SYM_F6 & 0xff] = KEY_F6,
+       [KEY_SYM_F7 & 0xff] = KEY_F7,
+       [KEY_SYM_F8 & 0xff] = KEY_F8,
+       [KEY_SYM_F9 & 0xff] = KEY_F9,
+       [KEY_SYM_F10 & 0xff] = KEY_F10,
+       [KEY_SYM_F11 & 0xff] = KEY_F11,
+       [KEY_SYM_F12 & 0xff] = KEY_F12,
+       [KEY_SYM_CAP_LOCK & 0xff] = KEY_CAPSLOCK,
+       [KEY_SYM_NUM_LOCK & 0xff] = KEY_NUMLOCK,
+       [KEY_SYM_SCR_LOCK & 0xff] = KEY_SCROLLLOCK,
+};
+static unsigned short xlate[XLATE_SIZE] = {
+       [NO_KEYCODE] = KEY_RESERVED,
+       [KEY_SYM_SPACE] = KEY_SPACE,
+       [KEY_SYM_TILDE] = KEY_GRAVE,        [KEY_SYM_BKTIC] = KEY_GRAVE,
+       [KEY_SYM_ONE] = KEY_1,              [KEY_SYM_BANG] = KEY_1,
+       [KEY_SYM_TWO] = KEY_2,              [KEY_SYM_AT] = KEY_2,
+       [KEY_SYM_THREE] = KEY_3,            [KEY_SYM_POUND] = KEY_3,
+       [KEY_SYM_FOUR] = KEY_4,             [KEY_SYM_DOLLAR] = KEY_4,
+       [KEY_SYM_FIVE] = KEY_5,             [KEY_SYM_PERCENT] = KEY_5,
+       [KEY_SYM_SIX] = KEY_6,              [KEY_SYM_CARAT] = KEY_6,
+       [KEY_SYM_SEVEN] = KEY_7,            [KEY_SYM_AMPER] = KEY_7,
+       [KEY_SYM_EIGHT] = KEY_8,            [KEY_SYM_STAR] = KEY_8,
+       [KEY_SYM_NINE] = KEY_9,             [KEY_SYM_LPAREN] = KEY_9,
+       [KEY_SYM_ZERO] = KEY_0,             [KEY_SYM_RPAREN] = KEY_0,
+       [KEY_SYM_MINUS] = KEY_MINUS,        [KEY_SYM_USCORE] = KEY_MINUS,
+       [KEY_SYM_EQUAL] = KEY_EQUAL,        [KEY_SYM_PLUS] = KEY_EQUAL,
+       [KEY_SYM_LBRKT] = KEY_LEFTBRACE,    [KEY_SYM_LCURLY] = KEY_LEFTBRACE,
+       [KEY_SYM_RBRKT] = KEY_RIGHTBRACE,   [KEY_SYM_RCURLY] = KEY_RIGHTBRACE,
+       [KEY_SYM_SLASH] = KEY_BACKSLASH,    [KEY_SYM_PIPE] = KEY_BACKSLASH,
+       [KEY_SYM_TIC] = KEY_APOSTROPHE,     [KEY_SYM_QUOTE] = KEY_APOSTROPHE,
+       [KEY_SYM_SEMIC] = KEY_SEMICOLON,    [KEY_SYM_COLON] = KEY_SEMICOLON,
+       [KEY_SYM_COMMA] = KEY_COMMA,        [KEY_SYM_LT] = KEY_COMMA,
+       [KEY_SYM_PERIOD] = KEY_DOT,         [KEY_SYM_GT] = KEY_DOT,
+       [KEY_SYM_BSLASH] = KEY_SLASH,       [KEY_SYM_QMARK] = KEY_SLASH,
+       [KEY_SYM_A] = KEY_A,                [KEY_SYM_a] = KEY_A,
+       [KEY_SYM_B] = KEY_B,                [KEY_SYM_b] = KEY_B,
+       [KEY_SYM_C] = KEY_C,                [KEY_SYM_c] = KEY_C,
+       [KEY_SYM_D] = KEY_D,                [KEY_SYM_d] = KEY_D,
+       [KEY_SYM_E] = KEY_E,                [KEY_SYM_e] = KEY_E,
+       [KEY_SYM_F] = KEY_F,                [KEY_SYM_f] = KEY_F,
+       [KEY_SYM_G] = KEY_G,                [KEY_SYM_g] = KEY_G,
+       [KEY_SYM_H] = KEY_H,                [KEY_SYM_h] = KEY_H,
+       [KEY_SYM_I] = KEY_I,                [KEY_SYM_i] = KEY_I,
+       [KEY_SYM_J] = KEY_J,                [KEY_SYM_j] = KEY_J,
+       [KEY_SYM_K] = KEY_K,                [KEY_SYM_k] = KEY_K,
+       [KEY_SYM_L] = KEY_L,                [KEY_SYM_l] = KEY_L,
+       [KEY_SYM_M] = KEY_M,                [KEY_SYM_m] = KEY_M,
+       [KEY_SYM_N] = KEY_N,                [KEY_SYM_n] = KEY_N,
+       [KEY_SYM_O] = KEY_O,                [KEY_SYM_o] = KEY_O,
+       [KEY_SYM_P] = KEY_P,                [KEY_SYM_p] = KEY_P,
+       [KEY_SYM_Q] = KEY_Q,                [KEY_SYM_q] = KEY_Q,
+       [KEY_SYM_R] = KEY_R,                [KEY_SYM_r] = KEY_R,
+       [KEY_SYM_S] = KEY_S,                [KEY_SYM_s] = KEY_S,
+       [KEY_SYM_T] = KEY_T,                [KEY_SYM_t] = KEY_T,
+       [KEY_SYM_U] = KEY_U,                [KEY_SYM_u] = KEY_U,
+       [KEY_SYM_V] = KEY_V,                [KEY_SYM_v] = KEY_V,
+       [KEY_SYM_W] = KEY_W,                [KEY_SYM_w] = KEY_W,
+       [KEY_SYM_X] = KEY_X,                [KEY_SYM_x] = KEY_X,
+       [KEY_SYM_Y] = KEY_Y,                [KEY_SYM_y] = KEY_Y,
+       [KEY_SYM_Z] = KEY_Z,                [KEY_SYM_z] = KEY_Z,
+};
 
-       q->end = q->start + DRIVER_REMOTE_QUEUE_SIZE;
-       q->reader = q->start;
-       q->writer = q->start;
-       q->size = DRIVER_REMOTE_QUEUE_SIZE;
-       init_waitqueue_head(&q->wait);
+static char remote_mouse_name[] = "ibmasm RSA I remote mouse";
+static char remote_keybd_name[] = "ibmasm RSA I remote keyboard";
 
-       return 0;
-}
-
-void ibmasm_free_remote_queue(struct service_processor *sp)
+static void print_input(struct remote_input *input)
 {
-       kfree(sp->remote_queue.start);
+       if (input->type == INPUT_TYPE_MOUSE) {
+               unsigned char buttons = input->mouse_buttons;
+               dbg("remote mouse movement: (x,y)=(%d,%d)%s%s%s%s\n",
+                       input->data.mouse.x, input->data.mouse.y,
+                       (buttons)?" -- buttons:":"",
+                       (buttons & REMOTE_BUTTON_LEFT)?"left ":"",
+                       (buttons & REMOTE_BUTTON_MIDDLE)?"middle ":"",
+                       (buttons & REMOTE_BUTTON_RIGHT)?"right":""
+                     );
+       } else {
+               dbg("remote keypress (code, flag, down):"
+                          "%d (0x%x) [0x%x] [0x%x]\n",
+                               input->data.keyboard.key_code,
+                               input->data.keyboard.key_code,
+                               input->data.keyboard.key_flag,
+                               input->data.keyboard.key_down
+                     );
+       }
 }
 
-void ibmasm_advance_reader(struct remote_queue *q, unsigned int n)
+static void send_mouse_event(struct input_dev *dev, struct pt_regs *regs,
+               struct remote_input *input)
 {
-       q->reader += n;
-       if (q->reader >= q->end)
-               q->reader -= q->size;
-}
+       unsigned char buttons = input->mouse_buttons;
 
-size_t ibmasm_events_available(struct remote_queue *q)
-{
-       ssize_t diff = q->writer - q->reader;
-       return (diff >= 0) ? diff : q->end - q->reader; 
+       input_regs(dev, regs);
+       input_report_abs(dev, ABS_X, input->data.mouse.x);
+       input_report_abs(dev, ABS_Y, input->data.mouse.y);
+       input_report_key(dev, BTN_LEFT, buttons & REMOTE_BUTTON_LEFT);
+       input_report_key(dev, BTN_MIDDLE, buttons & REMOTE_BUTTON_MIDDLE);
+       input_report_key(dev, BTN_RIGHT, buttons & REMOTE_BUTTON_RIGHT);
+       input_sync(dev);
 }
-       
 
-static int space_free(struct remote_queue *q)
+static void send_keyboard_event(struct input_dev *dev, struct pt_regs *regs,
+               struct remote_input *input)
 {
-       if (q->reader == q->writer)
-               return q->size - 1;
+       unsigned int key;
+       unsigned short code = input->data.keyboard.key_code;
 
-       return ( (q->reader + q->size - q->writer) % q->size ) - 1;
+       if (code & 0xff00)
+               key = xlate_high[code & 0xff];
+       else
+               key = xlate[code];
+       input_regs(dev, regs);
+       input_report_key(dev, key, (input->data.keyboard.key_down) ? 1 : 0);
+       input_sync(dev);
 }
 
-static void set_mouse_event(struct remote_input *input, struct mouse_event *mouse)
+void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
+               struct pt_regs *regs)
 {
-       static char last_buttons = 0;
+       unsigned long reader;
+       unsigned long writer;
+       struct remote_input input;
 
-       mouse->x = input->data.mouse.x;
-       mouse->y = input->data.mouse.y;
+       reader = get_queue_reader(sp);
+       writer = get_queue_writer(sp);
 
-       if (input->mouse_buttons == REMOTE_MOUSE_DOUBLE_CLICK) {
-               mouse->buttons = REMOTE_MOUSE_DOUBLE_CLICK;
-               last_buttons = 0;
-               return;
-       }
-       mouse->transitions = last_buttons ^ input->mouse_buttons;
-       mouse->buttons = input->mouse_buttons;
+       while (reader != writer) {
+               memcpy_fromio(&input, get_queue_entry(sp, reader),
+                               sizeof(struct remote_input));
 
-       last_buttons = input->mouse_buttons;
-}
+               print_input(&input);
+               if (input.type == INPUT_TYPE_MOUSE) {
+                       send_mouse_event(&sp->remote->mouse_dev, regs, &input);
+               } else if (input.type == INPUT_TYPE_KEYBOARD) {
+                       send_keyboard_event(&sp->remote->keybd_dev, regs, &input);
+               } else
+                       break;
 
-static void set_keyboard_event(struct remote_input *input, struct keyboard_event *keyboard)
-{
-       keyboard->key_code = input->data.keyboard.key_code;
-       keyboard->key_down = input->data.keyboard.key_down;
+               reader = advance_queue_reader(sp, reader);
+               writer = get_queue_writer(sp);
+       }
 }
 
-static int add_to_driver_queue(struct remote_queue *q, struct remote_input *input)
+int ibmasm_init_remote_input_dev(struct service_processor *sp)
 {
-       struct remote_event *event = q->writer;
+       /* set up the mouse input device */
+       struct ibmasm_remote *remote;
+       struct pci_dev *pdev = to_pci_dev(sp->dev);
+       int i;
 
-       if (space_free(q) < 1) {
-               return 1;
-       }
+       sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL);
+       if (!remote)
+               return -ENOMEM;
 
-       switch(input->type) {
-       case (INPUT_TYPE_MOUSE):
-               event->type = INPUT_TYPE_MOUSE;
-               set_mouse_event(input, &event->data.mouse);
-               break;
-       case (INPUT_TYPE_KEYBOARD):
-               event->type = INPUT_TYPE_KEYBOARD;
-               set_keyboard_event(input, &event->data.keyboard);
-               break;
-       default:
-               return 0;
-       }
-       event->type = input->type;
+       memset(remote, 0, sizeof(*remote));
 
-       q->writer++;
-       if (q->writer == q->end)
-               q->writer = q->start;
+       remote->mouse_dev.private = remote;
+       init_input_dev(&remote->mouse_dev);
+       remote->mouse_dev.id.vendor = pdev->vendor;
+       remote->mouse_dev.id.product = pdev->device;
+       remote->mouse_dev.evbit[0]  = BIT(EV_KEY) | BIT(EV_ABS);
+       remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
+               BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+       set_bit(BTN_TOUCH, remote->mouse_dev.keybit);
+       remote->mouse_dev.name = remote_mouse_name;
+       input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0);
+       input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0);
 
-       return 0;
-}
-       
+       remote->keybd_dev.private = remote;
+       init_input_dev(&remote->keybd_dev);
+       remote->keybd_dev.id.vendor = pdev->vendor;
+       remote->keybd_dev.id.product = pdev->device;
+       remote->keybd_dev.evbit[0]  = BIT(EV_KEY);
+       remote->keybd_dev.name = remote_keybd_name;
 
-void ibmasm_handle_mouse_interrupt(struct service_processor *sp)
-{
-       unsigned long reader;
-       unsigned long writer;
-       struct remote_input input;
+       for (i=0; i<XLATE_SIZE; i++) {
+               if (xlate_high[i])
+                       set_bit(xlate_high[i], remote->keybd_dev.keybit);
+               if (xlate[i])
+                       set_bit(xlate[i], remote->keybd_dev.keybit);
+       }
 
-       reader = get_queue_reader(sp);
-       writer = get_queue_writer(sp);
+       input_register_device(&remote->mouse_dev);
+       input_register_device(&remote->keybd_dev);
+       enable_mouse_interrupts(sp);
 
-       while (reader != writer) {
-               memcpy(&input, (void *)get_queue_entry(sp, reader), sizeof(struct remote_input));
+       printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
 
-               if (add_to_driver_queue(&sp->remote_queue, &input))
-                       break;
+       return 0;
+}
 
-               reader = advance_queue_reader(sp, reader);
-       }
-       wake_up_interruptible(&sp->remote_queue.wait);
+void ibmasm_free_remote_input_dev(struct service_processor *sp)
+{
+       disable_mouse_interrupts(sp);
+       input_unregister_device(&sp->remote->keybd_dev);
+       input_unregister_device(&sp->remote->mouse_dev);
+       kfree(sp->remote);
 }
+
index a8eb19f02d3f5010b8eadc5e3735018a85091023..b7076a8442d2be8cb4a0967d0a645f14626c4f00 100644 (file)
 
 
 /* mouse button states received from SP */
-#define REMOTE_MOUSE_DOUBLE_CLICK      0xF0
-#define REMOTE_MOUSE_BUTTON_LEFT       0x01
-#define REMOTE_MOUSE_BUTTON_MIDDLE     0x02
-#define REMOTE_MOUSE_BUTTON_RIGHT      0x04
+#define REMOTE_DOUBLE_CLICK    0xF0
+#define REMOTE_BUTTON_LEFT     0x01
+#define REMOTE_BUTTON_MIDDLE   0x02
+#define REMOTE_BUTTON_RIGHT    0x04
 
+/* size of keysym/keycode translation matricies */
+#define XLATE_SIZE 256
 
 struct mouse_input {
        unsigned short  y;
@@ -83,11 +85,13 @@ struct remote_input {
        unsigned char   pad3;
 };
 
-#define mouse_addr(sp)                 sp->base_address + CONDOR_MOUSE_DATA
-#define display_width(sp)      mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX
-#define display_height(sp)     mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY
-#define display_depth(sp)      mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS
-#define vnc_status(sp)         mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS
+#define mouse_addr(sp)                 (sp->base_address + CONDOR_MOUSE_DATA)
+#define display_width(sp)      (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX)
+#define display_height(sp)     (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY)
+#define display_depth(sp)      (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS)
+#define desktop_info(sp)       (mouse_addr(sp) + CONDOR_INPUT_DESKTOP_INFO)
+#define vnc_status(sp)         (mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS)
+#define isr_control(sp)                (mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
 
 #define mouse_interrupt_pending(sp)    readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
 #define clear_mouse_interrupt(sp)      writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
@@ -101,10 +105,10 @@ struct remote_input {
 #define get_queue_reader(sp)   readl(mouse_addr(sp) + CONDOR_MOUSE_Q_READER)
 #define set_queue_reader(sp, reader)   writel(reader, mouse_addr(sp) + CONDOR_MOUSE_Q_READER)
 
-#define queue_begin    mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN
+#define queue_begin    (mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN)
 
 #define get_queue_entry(sp, read_index) \
-       queue_begin + read_index * sizeof(struct remote_input)
+       ((void*)(queue_begin + read_index * sizeof(struct remote_input)))
 
 static inline int advance_queue_reader(struct service_processor *sp, unsigned long reader)
 {
@@ -116,4 +120,151 @@ static inline int advance_queue_reader(struct service_processor *sp, unsigned lo
        return reader;
 }
 
+#define NO_KEYCODE 0
+#define KEY_SYM_BK_SPC   0xFF08
+#define KEY_SYM_TAB      0xFF09
+#define KEY_SYM_ENTER    0xFF0D
+#define KEY_SYM_SCR_LOCK 0xFF14
+#define KEY_SYM_ESCAPE   0xFF1B
+#define KEY_SYM_HOME     0xFF50
+#define KEY_SYM_LARROW   0xFF51
+#define KEY_SYM_UARROW   0xFF52
+#define KEY_SYM_RARROW   0xFF53
+#define KEY_SYM_DARROW   0xFF54
+#define KEY_SYM_PAGEUP   0xFF55
+#define KEY_SYM_PAGEDOWN 0xFF56
+#define KEY_SYM_END      0xFF57
+#define KEY_SYM_INSERT   0xFF63
+#define KEY_SYM_NUM_LOCK 0xFF7F
+#define KEY_SYM_KPSTAR   0xFFAA
+#define KEY_SYM_KPPLUS   0xFFAB
+#define KEY_SYM_KPMINUS  0xFFAD
+#define KEY_SYM_KPDOT    0xFFAE
+#define KEY_SYM_KPSLASH  0xFFAF
+#define KEY_SYM_KPRIGHT  0xFF96
+#define KEY_SYM_KPUP     0xFF97
+#define KEY_SYM_KPLEFT   0xFF98
+#define KEY_SYM_KPDOWN   0xFF99
+#define KEY_SYM_KP0      0xFFB0
+#define KEY_SYM_KP1      0xFFB1
+#define KEY_SYM_KP2      0xFFB2
+#define KEY_SYM_KP3      0xFFB3
+#define KEY_SYM_KP4      0xFFB4
+#define KEY_SYM_KP5      0xFFB5
+#define KEY_SYM_KP6      0xFFB6
+#define KEY_SYM_KP7      0xFFB7
+#define KEY_SYM_KP8      0xFFB8
+#define KEY_SYM_KP9      0xFFB9
+#define KEY_SYM_F1       0xFFBE      // 1B 5B 5B 41
+#define KEY_SYM_F2       0xFFBF      // 1B 5B 5B 42
+#define KEY_SYM_F3       0xFFC0      // 1B 5B 5B 43
+#define KEY_SYM_F4       0xFFC1      // 1B 5B 5B 44
+#define KEY_SYM_F5       0xFFC2      // 1B 5B 5B 45
+#define KEY_SYM_F6       0xFFC3      // 1B 5B 31 37 7E
+#define KEY_SYM_F7       0xFFC4      // 1B 5B 31 38 7E
+#define KEY_SYM_F8       0xFFC5      // 1B 5B 31 39 7E
+#define KEY_SYM_F9       0xFFC6      // 1B 5B 32 30 7E
+#define KEY_SYM_F10      0xFFC7      // 1B 5B 32 31 7E
+#define KEY_SYM_F11      0xFFC8      // 1B 5B 32 33 7E
+#define KEY_SYM_F12      0xFFC9      // 1B 5B 32 34 7E
+#define KEY_SYM_SHIFT    0xFFE1
+#define KEY_SYM_CTRL     0xFFE3
+#define KEY_SYM_ALT      0xFFE9
+#define KEY_SYM_CAP_LOCK 0xFFE5
+#define KEY_SYM_DELETE   0xFFFF
+#define KEY_SYM_TILDE    0x60
+#define KEY_SYM_BKTIC    0x7E
+#define KEY_SYM_ONE      0x31
+#define KEY_SYM_BANG     0x21
+#define KEY_SYM_TWO      0x32
+#define KEY_SYM_AT       0x40
+#define KEY_SYM_THREE    0x33
+#define KEY_SYM_POUND    0x23
+#define KEY_SYM_FOUR     0x34
+#define KEY_SYM_DOLLAR   0x24
+#define KEY_SYM_FIVE     0x35
+#define KEY_SYM_PERCENT  0x25
+#define KEY_SYM_SIX      0x36
+#define KEY_SYM_CARAT    0x5E
+#define KEY_SYM_SEVEN    0x37
+#define KEY_SYM_AMPER    0x26
+#define KEY_SYM_EIGHT    0x38
+#define KEY_SYM_STAR     0x2A
+#define KEY_SYM_NINE     0x39
+#define KEY_SYM_LPAREN   0x28
+#define KEY_SYM_ZERO     0x30
+#define KEY_SYM_RPAREN   0x29
+#define KEY_SYM_MINUS    0x2D
+#define KEY_SYM_USCORE   0x5F
+#define KEY_SYM_EQUAL    0x2B
+#define KEY_SYM_PLUS     0x3D
+#define KEY_SYM_LBRKT    0x5B
+#define KEY_SYM_LCURLY   0x7B
+#define KEY_SYM_RBRKT    0x5D
+#define KEY_SYM_RCURLY   0x7D
+#define KEY_SYM_SLASH    0x5C
+#define KEY_SYM_PIPE     0x7C
+#define KEY_SYM_TIC      0x27
+#define KEY_SYM_QUOTE    0x22
+#define KEY_SYM_SEMIC    0x3B
+#define KEY_SYM_COLON    0x3A
+#define KEY_SYM_COMMA    0x2C
+#define KEY_SYM_LT       0x3C
+#define KEY_SYM_PERIOD   0x2E
+#define KEY_SYM_GT       0x3E
+#define KEY_SYM_BSLASH   0x2F
+#define KEY_SYM_QMARK    0x3F
+#define KEY_SYM_A        0x41
+#define KEY_SYM_B        0x42
+#define KEY_SYM_C        0x43
+#define KEY_SYM_D        0x44
+#define KEY_SYM_E        0x45
+#define KEY_SYM_F        0x46
+#define KEY_SYM_G        0x47
+#define KEY_SYM_H        0x48
+#define KEY_SYM_I        0x49
+#define KEY_SYM_J        0x4A
+#define KEY_SYM_K        0x4B
+#define KEY_SYM_L        0x4C
+#define KEY_SYM_M        0x4D
+#define KEY_SYM_N        0x4E
+#define KEY_SYM_O        0x4F
+#define KEY_SYM_P        0x50
+#define KEY_SYM_Q        0x51
+#define KEY_SYM_R        0x52
+#define KEY_SYM_S        0x53
+#define KEY_SYM_T        0x54
+#define KEY_SYM_U        0x55
+#define KEY_SYM_V        0x56
+#define KEY_SYM_W        0x57
+#define KEY_SYM_X        0x58
+#define KEY_SYM_Y        0x59
+#define KEY_SYM_Z        0x5A
+#define KEY_SYM_a        0x61
+#define KEY_SYM_b        0x62
+#define KEY_SYM_c        0x63
+#define KEY_SYM_d        0x64
+#define KEY_SYM_e        0x65
+#define KEY_SYM_f        0x66
+#define KEY_SYM_g        0x67
+#define KEY_SYM_h        0x68
+#define KEY_SYM_i        0x69
+#define KEY_SYM_j        0x6A
+#define KEY_SYM_k        0x6B
+#define KEY_SYM_l        0x6C
+#define KEY_SYM_m        0x6D
+#define KEY_SYM_n        0x6E
+#define KEY_SYM_o        0x6F
+#define KEY_SYM_p        0x70
+#define KEY_SYM_q        0x71
+#define KEY_SYM_r        0x72
+#define KEY_SYM_s        0x73
+#define KEY_SYM_t        0x74
+#define KEY_SYM_u        0x75
+#define KEY_SYM_v        0x76
+#define KEY_SYM_w        0x77
+#define KEY_SYM_x        0x78
+#define KEY_SYM_y        0x79
+#define KEY_SYM_z        0x7A
+#define KEY_SYM_SPACE    0x20
 #endif /* _IBMASM_REMOTE_H_ */
index b5e076043431aa69769503a41486c591aa7d23ea..80ec9aa575bb5df228428afb5d84ae42c3407c35 100644 (file)
@@ -2202,9 +2202,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (vortex_debug > 6) {
                printk(KERN_DEBUG "boomerang_start_xmit()\n");
-               if (vortex_debug > 3)
-                       printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
-                                  dev->name, vp->cur_tx);
+               printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
+                          dev->name, vp->cur_tx);
        }
 
        if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
index bab16bcc9ae5df82cc4197bf255926ae76acdc1d..6d76f3a99b175f533d06451a76f773f692f8cc8d 100644 (file)
@@ -225,9 +225,9 @@ void ei_tx_timeout(struct net_device *dev)
        unsigned long icucr;
 
        local_irq_save(flags);
-       icucr = inl(ICUCR1);
+       icucr = inl(M32R_ICU_CR1_PORTL);
        icucr |= M32R_ICUCR_ISMOD11;
-       outl(icucr, ICUCR1);
+       outl(icucr, M32R_ICU_CR1_PORTL);
        local_irq_restore(flags);
 #endif
        ei_local->stat.tx_errors++;
index 55720dc6ec43feb06b3b1edecb8aca6716cea578..745a14183634feb56d83e51685b10d549eb4e846 100644 (file)
@@ -62,7 +62,7 @@ static int task_exit_notify(struct notifier_block * self, unsigned long val, voi
        /* 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());
+       sync_buffer(raw_smp_processor_id());
        return 0;
 }
 
@@ -86,7 +86,7 @@ static int munmap_notify(struct notifier_block * self, unsigned long val, void *
                /* 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());
+               sync_buffer(raw_smp_processor_id());
                return 0;
        }
 
index 6375ebc85020556df3d837e3077c3df47a19b8c4..14e4124e15231f777cc9602db8a9f9289b50adba 100644 (file)
@@ -171,19 +171,21 @@ config PCMCIA_PROBE
 config M32R_PCC
        bool "M32R PCMCIA I/F"
        depends on M32R && CHIP_M32700 && PCMCIA
+       select PCCARD_NONSTATIC
        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)
+       depends on M32R && (PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_MAPPI3 || PLAT_OPSPUT)
+       select PCCARD_NONSTATIC
        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
+       default "1" if PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_MAPPI3 || PLAT_OPSPUT
        help
          Set the number of M32R CF slots.
 
index 581bfa95429e1c1a4f1092777e84a63a3395e80d..b1111c6bf062a55d726b7be28eb79af41eafe8f5 100644 (file)
@@ -24,9 +24,9 @@
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/bitops.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/bitops.h>
 #include <asm/system.h>
 
 #include <pcmcia/version.h>
@@ -444,7 +444,7 @@ static int _pcc_get_status(u_short sock, u_int *value)
                debug(3, "m32r_cfc: _pcc_get_status: "
                         "power off (CPCR=0x%08x)\n", status);
        }
-#elif defined(CONFIG_PLAT_MAPPI2)
+#elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
        if ( status ) {
                status = pcc_get(sock, (unsigned int)PLD_CPCR);
                if (status == 0) { /* power off */
@@ -452,18 +452,23 @@ static int _pcc_get_status(u_short sock, u_int *value)
                        pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); /* force buffer off for ZA-36 */
                        udelay(50);
                }
-               status = pcc_get(sock, (unsigned int)PLD_CFBUFCR);
-               if (status != 0) { /* buffer off */
-                       pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);
-                       udelay(50);
-                       pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);
-                       udelay(25); /* for IDE reset */
-                       pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);
-                       mdelay(2);  /* for IDE reset */
-               } else {
-                       *value |= SS_POWERON;
-                       *value |= SS_READY;
-               }
+               *value |= SS_POWERON;
+
+               pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);
+               udelay(50);
+               pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);
+               udelay(25); /* for IDE reset */
+               pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);
+               mdelay(2);  /* for IDE reset */
+
+               *value |= SS_READY;
+               *value |= SS_3VCARD;
+       } else {
+               /* disable CF power */
+               pcc_set(sock, (unsigned int)PLD_CPCR, 0);
+               udelay(100);
+               debug(3, "m32r_cfc: _pcc_get_status: "
+                        "power off (CPCR=0x%08x)\n", status);
        }
 #else
 #error no platform configuration
@@ -479,14 +484,13 @@ static int _pcc_get_socket(u_short sock, socket_state_t *state)
 {
 //     pcc_socket_t *t = &socket[sock];
 
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
        state->flags = 0;
        state->csc_mask = SS_DETECT;
        state->csc_mask |= SS_READY;
        state->io_irq = 0;
        state->Vcc = 33;        /* 3.3V fixed */
        state->Vpp = 33;
-#endif
+
        debug(3, "m32r_cfc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
                  "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
                  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
@@ -497,32 +501,17 @@ static int _pcc_get_socket(u_short sock, socket_state_t *state)
 
 static int _pcc_set_socket(u_short sock, socket_state_t *state)
 {
-#if defined(CONFIG_PLAT_MAPPI2)
-       u_long reg = 0;
-#endif
        debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
                  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
                  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
 
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
        if (state->Vcc) {
                if ((state->Vcc != 50) && (state->Vcc != 33))
                        return -EINVAL;
                /* accept 5V and 3.3V */
        }
-#elif defined(CONFIG_PLAT_MAPPI2)
-       if (state->Vcc) {
-               /*
-                * 5V only
-                */
-               if (state->Vcc == 50) {
-                       reg |= PCCSIGCR_VEN;
-               } else {
-                       return -EINVAL;
-               }
-       }
 #endif
-
        if (state->flags & SS_RESET) {
                debug(3, ":RESET\n");
                pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101);
@@ -788,7 +777,7 @@ static int __init init_m32r_pcc(void)
                return ret;
        }
 
-#if defined(CONFIG_PLAT_MAPPI2)
+#if defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
        pcc_set(0, (unsigned int)PLD_CFCR0, 0x0f0f);
        pcc_set(0, (unsigned int)PLD_CFCR1, 0x0200);
 #endif
@@ -825,7 +814,7 @@ static int __init init_m32r_pcc(void)
        for (i = 0 ; i < pcc_sockets ; i++) {
                socket[i].socket.dev.dev = &pcc_device.dev;
                socket[i].socket.ops = &pcc_operations;
-               socket[i].socket.resource_ops = &pccard_static_ops;
+               socket[i].socket.resource_ops = &pccard_nonstatic_ops;
                socket[i].socket.owner = THIS_MODULE;
                socket[i].number = i;
                ret = pcmcia_register_socket(&socket[i].socket);
index 17c1db7ae15589e446f607b25a444205c2569d49..8146e3bee2e8f1dab1784cae0e52f935268d3928 100644 (file)
 
 #define CFC_IOPORT_BASE                0x1000
 
-#if !defined(CONFIG_PLAT_USRV)
+#if defined(CONFIG_PLAT_MAPPI3)
+#define CFC_ATTR_MAPBASE       0x14014000
+#define CFC_IO_MAPBASE_BYTE    0xb4012000
+#define CFC_IO_MAPBASE_WORD    0xb4002000
+#elif !defined(CONFIG_PLAT_USRV)
 #define CFC_ATTR_MAPBASE        0x0c014000
 #define CFC_IO_MAPBASE_BYTE     0xac012000
 #define CFC_IO_MAPBASE_WORD     0xac002000
-#else  /* CONFIG_PLAT_USRV */
+#else
 #define CFC_ATTR_MAPBASE       0x04014000
 #define CFC_IO_MAPBASE_BYTE    0xa4012000
 #define CFC_IO_MAPBASE_WORD    0xa4002000
index 4a06c7d0e5e4950899007faebc31725caf900119..aac83ce6469cf8ef57e9926848993dd6a27f2c2a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.33 $
+ *   $Revision: 1.34 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *                           IBM Corporation
@@ -289,7 +289,7 @@ static int cio_ignore_read (char *page, char **start, off_t off,
        len = 0;
        for (devno = off; /* abuse the page variable
                           * as counter, see fs/proc/generic.c */
-            devno <= __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
+            devno < __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
                if (!test_bit(devno, bl_dev))
                        continue;
                len += sprintf(page + len, "0.0.%04lx", devno);
@@ -302,7 +302,7 @@ static int cio_ignore_read (char *page, char **start, off_t off,
                len += sprintf(page + len, "\n");
        }
 
-       if (devno <= __MAX_SUBCHANNELS)
+       if (devno < __MAX_SUBCHANNELS)
                *eof = 1;
        *start = (char *) (devno - off); /* number of checked entries */
        return len;
index 80b0c40c522b7023369c6498ad24165892b8ff55..ec81532eb8455b5af006f0d34f25f685e1f2b698 100644 (file)
@@ -1975,7 +1975,7 @@ __megaraid_reset(Scsi_Cmnd *cmd)
 static int
 megaraid_reset(Scsi_Cmnd *cmd)
 {
-       adapter = (adapter_t *)cmd->device->host->hostdata;
+       adapter_t *adapter = (adapter_t *)cmd->device->host->hostdata;
        int rc;
 
        spin_lock_irq(&adapter->lock);
index 6e44b46c9e9dd6fd72ca9a4fdb34d3465a2b445d..25fcef2c42deeb8a1cee6716d12c7e1ec2d19456 100644 (file)
@@ -753,7 +753,7 @@ config SERIAL_MPC52xx_CONSOLE_BAUD
 
 config SERIAL_ICOM
        tristate "IBM Multiport Serial Adapter"
-       depends on PPC_ISERIES || PPC_PSERIES
+       depends on PCI && (PPC_ISERIES || PPC_PSERIES)
        select SERIAL_CORE
        help
          This driver is for a family of multiport serial adapters
@@ -843,4 +843,13 @@ config SERIAL_JSM
           To compile this driver as a module, choose M here: the
           module will be called jsm.
 
+config SERIAL_SGI_IOC4
+       tristate "SGI IOC4 controller serial support"
+       depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC4
+       select SERIAL_CORE
+       help
+               If you have an SGI Altix with an IOC4 based Base IO card
+               and wish to use the serial ports on this card, say Y.
+               Otherwise, say N.
+
 endmenu
index 81b77d769b846b36612a811ed0289a2065604e99..8f1cdde7dbed7c57bf7daf379d3dfc529c5eb9a2 100644 (file)
@@ -51,4 +51,4 @@ obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4_serial.o
+obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
index b422c3abfba612830df57630e7cbb3c4682279ce..c4c8f4b44f53820a8a4ae3d3431f7c3da984b1ee 100644 (file)
@@ -134,12 +134,21 @@ void scc1_lineif(struct uart_cpm_port *pinfo)
 
 void scc2_lineif(struct uart_cpm_port *pinfo)
 {
+       /*
+        * STx GP3 uses the SCC2 secondary option pin assignment
+        * which this driver doesn't account for in the static
+        * pin assignments. This kind of board specific info
+        * really has to get out of the driver so boards can
+        * be supported in a sane fashion.
+        */
+#ifndef CONFIG_STX_GP3
        volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
        io->iop_pparb |= 0x008b0000;
        io->iop_pdirb |= 0x00880000;
        io->iop_psorb |= 0x00880000;
        io->iop_pdirb &= ~0x00030000;
        io->iop_psorb &= ~0x00030000;
+#endif
        cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
        cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
        pinfo->brg = 2;
index ba4e13a22a50951484dd23df491942d7109eb7a9..793c3a7cbe477c868f65d1ddf224cd64b629e889 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/serial_reg.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/ioc4_common.h>
+#include <linux/ioc4.h>
 #include <linux/serial_core.h>
 
 /*
                                 IOC4_SIO_IR_S3_TX_EXPLICIT)
 
 /* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES  */
-#define IOC4_OTHER_IR_ATA_INT           0x00000001  /* ATAPI intr pass-thru */
-#define IOC4_OTHER_IR_ATA_MEMERR        0x00000002  /* ATAPI DMA PCI error */
-#define IOC4_OTHER_IR_S0_MEMERR         0x00000004  /* Port 0 PCI error */
-#define IOC4_OTHER_IR_S1_MEMERR         0x00000008  /* Port 1 PCI error */
-#define IOC4_OTHER_IR_S2_MEMERR         0x00000010  /* Port 2 PCI error */
-#define IOC4_OTHER_IR_S3_MEMERR         0x00000020  /* Port 3 PCI error */
+#define IOC4_OTHER_IR_ATA_INT          0x00000001  /* ATAPI intr pass-thru */
+#define IOC4_OTHER_IR_ATA_MEMERR       0x00000002  /* ATAPI DMA PCI error */
+#define IOC4_OTHER_IR_S0_MEMERR                0x00000004  /* Port 0 PCI error */
+#define IOC4_OTHER_IR_S1_MEMERR                0x00000008  /* Port 1 PCI error */
+#define IOC4_OTHER_IR_S2_MEMERR                0x00000010  /* Port 2 PCI error */
+#define IOC4_OTHER_IR_S3_MEMERR                0x00000020  /* Port 3 PCI error */
+#define IOC4_OTHER_IR_KBD_INT          0x00000040  /* Keyboard/mouse */
+#define IOC4_OTHER_IR_RESERVED         0x007fff80  /* Reserved */
+#define IOC4_OTHER_IR_RT_INT           0x00800000  /* INT_OUT section output */
+#define IOC4_OTHER_IR_GEN_INT          0xff000000  /* Generic pins */
+
+#define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \
+                                 IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR)
 
 /* Bitmasks for IOC4_SIO_CR */
 #define IOC4_SIO_CR_CMD_PULSE_SHIFT              0  /* byte bus strobe shift */
@@ -274,70 +281,24 @@ struct ioc4_uartregs {
 #define i4u_dlm u2.dlm
 #define i4u_fcr u3.fcr
 
-/* PCI memory space register map addressed using pci_bar0 */
-struct ioc4_memregs {
-       struct ioc4_mem {
-               /* Miscellaneous IOC4  registers */
-               uint32_t pci_err_addr_l;
-               uint32_t pci_err_addr_h;
-               uint32_t sio_ir;
-               uint32_t other_ir;
-
-               /* These registers are read-only for general kernel code.  */
-               uint32_t sio_ies_ro;
-               uint32_t other_ies_ro;
-               uint32_t sio_iec_ro;
-               uint32_t other_iec_ro;
-               uint32_t sio_cr;
-               uint32_t misc_fill1;
-               uint32_t int_out;
-               uint32_t misc_fill2;
-               uint32_t gpcr_s;
-               uint32_t gpcr_c;
-               uint32_t gpdr;
-               uint32_t misc_fill3;
-               uint32_t gppr_0;
-               uint32_t gppr_1;
-               uint32_t gppr_2;
-               uint32_t gppr_3;
-               uint32_t gppr_4;
-               uint32_t gppr_5;
-               uint32_t gppr_6;
-               uint32_t gppr_7;
-       } ioc4_mem;
-
-       char misc_fill4[0x100 - 0x5C - 4];
-
-       /* ATA/ATAP registers */
-       uint32_t ata_notused[9];
-       char ata_fill1[0x140 - 0x120 - 4];
-       uint32_t ata_notused1[8];
-       char ata_fill2[0x200 - 0x15C - 4];
-
-       /* Keyboard and mouse registers */
-       uint32_t km_notused[5];;
-       char km_fill1[0x300 - 0x210 - 4];
-
-       /* Serial port registers used for DMA serial I/O */
-       struct ioc4_serial {
-               uint32_t sbbr01_l;
-               uint32_t sbbr01_h;
-               uint32_t sbbr23_l;
-               uint32_t sbbr23_h;
-
-               struct ioc4_serialregs port_0;
-               struct ioc4_serialregs port_1;
-               struct ioc4_serialregs port_2;
-               struct ioc4_serialregs port_3;
-               struct ioc4_uartregs uart_0;
-               struct ioc4_uartregs uart_1;
-               struct ioc4_uartregs uart_2;
-               struct ioc4_uartregs uart_3;
-       } ioc4_serial;
-};
+/* Serial port registers used for DMA serial I/O */
+struct ioc4_serial {
+       uint32_t sbbr01_l;
+       uint32_t sbbr01_h;
+       uint32_t sbbr23_l;
+       uint32_t sbbr23_h;
+
+       struct ioc4_serialregs port_0;
+       struct ioc4_serialregs port_1;
+       struct ioc4_serialregs port_2;
+       struct ioc4_serialregs port_3;
+       struct ioc4_uartregs uart_0;
+       struct ioc4_uartregs uart_1;
+       struct ioc4_uartregs uart_2;
+       struct ioc4_uartregs uart_3;
+} ioc4_serial;
 
 /* UART clock speed */
-#define IOC4_SER_XIN_CLK        IOC4_SER_XIN_CLK_66
 #define IOC4_SER_XIN_CLK_66     66666667
 #define IOC4_SER_XIN_CLK_33     33333333
 
@@ -412,8 +373,8 @@ enum sio_proto {
                                        | UART_LCR_WLEN7 | UART_LCR_WLEN8)
 #define LCR_MASK_STOP_BITS     (UART_LCR_STOP)
 
-#define PENDING(_p)    (readl(&(_p)->ip_mem->sio_ir) & _p->ip_ienb)
-#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir)
+#define PENDING(_p)    (readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb)
+#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw)
 
 /* Default to 4k buffers */
 #ifdef IOC4_1K_BUFFERS
@@ -447,7 +408,7 @@ struct ioc4_control {
  */
 #define MAX_IOC4_INTR_ENTS     (8 * sizeof(uint32_t))
 struct ioc4_soft {
-       struct ioc4_mem __iomem *is_ioc4_mem_addr;
+       struct ioc4_misc_regs __iomem *is_ioc4_misc_addr;
        struct ioc4_serial __iomem *is_ioc4_serial_addr;
 
        /* Each interrupt type has an entry in the array */
@@ -486,7 +447,7 @@ struct ioc4_port {
        struct ioc4_soft *ip_ioc4_soft;
 
        /* pci mem addresses */
-       struct ioc4_mem __iomem *ip_mem;
+       struct ioc4_misc_regs __iomem *ip_mem;
        struct ioc4_serial __iomem *ip_serial;
        struct ioc4_serialregs __iomem *ip_serial_regs;
        struct ioc4_uartregs __iomem *ip_uart_regs;
@@ -553,7 +514,7 @@ struct hooks {
        uint32_t intr_dma_error;
        uint32_t intr_clear;
        uint32_t intr_all;
-       char rs422_select_pin;
+       int rs422_select_pin;
 };
 
 static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = {
@@ -669,7 +630,7 @@ static void handle_intr(void *arg, uint32_t sio_ir);
 static inline void
 write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
 {
-       struct ioc4_mem __iomem *mem = ioc4_soft->is_ioc4_mem_addr;
+       struct ioc4_misc_regs __iomem *mem = ioc4_soft->is_ioc4_misc_addr;
        unsigned long flags;
 
        spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags);
@@ -678,11 +639,11 @@ write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
        case IOC4_SIO_INTR_TYPE:
                switch (which) {
                case IOC4_W_IES:
-                       writel(val, &mem->sio_ies_ro);
+                       writel(val, &mem->sio_ies.raw);
                        break;
 
                case IOC4_W_IEC:
-                       writel(val, &mem->sio_iec_ro);
+                       writel(val, &mem->sio_iec.raw);
                        break;
                }
                break;
@@ -690,11 +651,11 @@ write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
        case IOC4_OTHER_INTR_TYPE:
                switch (which) {
                case IOC4_W_IES:
-                       writel(val, &mem->other_ies_ro);
+                       writel(val, &mem->other_ies.raw);
                        break;
 
                case IOC4_W_IEC:
-                       writel(val, &mem->other_iec_ro);
+                       writel(val, &mem->other_iec.raw);
                        break;
                }
                break;
@@ -747,7 +708,8 @@ static int set_baud(struct ioc4_port *port, int baud)
  */
 static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
 {
-       struct ioc4_control *control = dev_get_drvdata(the_port->dev);
+       struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev);
+       struct ioc4_control *control = idd->idd_serial_data;
        int ii;
 
        if (control) {
@@ -782,7 +744,7 @@ static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
 static inline uint32_t
 pending_intrs(struct ioc4_soft *soft, int type)
 {
-       struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+       struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
        unsigned long flag;
        uint32_t intrs = 0;
 
@@ -793,11 +755,11 @@ pending_intrs(struct ioc4_soft *soft, int type)
 
        switch (type) {
        case IOC4_SIO_INTR_TYPE:
-               intrs = readl(&mem->sio_ir) & readl(&mem->sio_ies_ro);
+               intrs = readl(&mem->sio_ir.raw) & readl(&mem->sio_ies.raw);
                break;
 
        case IOC4_OTHER_INTR_TYPE:
-               intrs = readl(&mem->other_ir) & readl(&mem->other_ies_ro);
+               intrs = readl(&mem->other_ir.raw) & readl(&mem->other_ies.raw);
 
                /* Don't process any ATA interrupte */
                intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
@@ -826,7 +788,7 @@ static int inline port_init(struct ioc4_port *port)
 
        /* Wait until any pending bus activity for this port has ceased */
        do
-               sio_cr = readl(&port->ip_mem->sio_cr);
+               sio_cr = readl(&port->ip_mem->sio_cr.raw);
        while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
 
        /* Finish reset sequence */
@@ -899,7 +861,7 @@ static int inline port_init(struct ioc4_port *port)
        write_ireg(port->ip_ioc4_soft, hooks->intr_clear,
                       IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
        port->ip_ienb &= ~hooks->intr_clear;
-       writel(hooks->intr_clear, &port->ip_mem->sio_ir);
+       writel(hooks->intr_clear, &port->ip_mem->sio_ir.raw);
        return 0;
 }
 
@@ -918,23 +880,23 @@ static void handle_dma_error_intr(void *arg, uint32_t other_ir)
        spin_lock_irqsave(&port->ip_lock, flags);
 
        /* ACK the interrupt */
-       writel(hooks->intr_dma_error, &port->ip_mem->other_ir);
+       writel(hooks->intr_dma_error, &port->ip_mem->other_ir.raw);
 
-       if (readl(&port->ip_mem->pci_err_addr_l) & IOC4_PCI_ERR_ADDR_VLD) {
+       if (readl(&port->ip_mem->pci_err_addr_l.raw) & IOC4_PCI_ERR_ADDR_VLD) {
                printk(KERN_ERR
                        "PCI error address is 0x%lx, "
                                "master is serial port %c %s\n",
                     (((uint64_t)readl(&port->ip_mem->pci_err_addr_h)
                                                         << 32)
-                               | readl(&port->ip_mem->pci_err_addr_l))
+                               | readl(&port->ip_mem->pci_err_addr_l.raw))
                                        & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' +
-                    ((char)(readl(&port->ip_mem-> pci_err_addr_l) &
+                    ((char)(readl(&port->ip_mem->pci_err_addr_l.raw) &
                             IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
-                    (readl(&port->ip_mem->pci_err_addr_l)
+                    (readl(&port->ip_mem->pci_err_addr_l.raw)
                                & IOC4_PCI_ERR_ADDR_MST_TYP_MSK)
                                ? "RX" : "TX");
 
-               if (readl(&port->ip_mem->pci_err_addr_l)
+               if (readl(&port->ip_mem->pci_err_addr_l.raw)
                                                & IOC4_PCI_ERR_ADDR_MUL_ERR) {
                        printk(KERN_ERR
                                "Multiple errors occurred\n");
@@ -1018,26 +980,26 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
                                "other_ies = 0x%x\n",
                               (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" :
                               "other", this_ir,
-                              readl(&soft->is_ioc4_mem_addr->sio_ir),
-                              readl(&soft->is_ioc4_mem_addr->sio_ies_ro),
-                              readl(&soft->is_ioc4_mem_addr->other_ir),
-                              readl(&soft->is_ioc4_mem_addr->other_ies_ro));
+                              readl(&soft->is_ioc4_misc_addr->sio_ir.raw),
+                              readl(&soft->is_ioc4_misc_addr->sio_ies.raw),
+                              readl(&soft->is_ioc4_misc_addr->other_ir.raw),
+                              readl(&soft->is_ioc4_misc_addr->other_ies.raw));
                }
        }
 #ifdef DEBUG_INTERRUPTS
        {
-               struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+               struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
                spinlock_t *lp = &soft->is_ir_lock;
                unsigned long flag;
 
                spin_lock_irqsave(&soft->is_ir_lock, flag);
-               printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies_ro 0x%x "
-                               "other_ir 0x%x other_ies_ro 0x%x mask 0x%x\n",
+               printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x "
+                               "other_ir 0x%x other_ies 0x%x mask 0x%x\n",
                     __FUNCTION__, __LINE__,
-                    (void *)mem, readl(&mem->sio_ir),
-                    readl(&mem->sio_ies_ro),
-                    readl(&mem->other_ir),
-                    readl(&mem->other_ies_ro),
+                    (void *)mem, readl(&mem->sio_ir.raw),
+                    readl(&mem->sio_ies.raw),
+                    readl(&mem->other_ir.raw),
+                    readl(&mem->other_ies.raw),
                     IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
                spin_unlock_irqrestore(&soft->is_ir_lock, flag);
        }
@@ -1049,21 +1011,20 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
  * ioc4_attach_local - Device initialization.
  *                     Called at *_attach() time for each
  *                     IOC4 with serial ports in the system.
- * @control: ioc4_control ptr
- * @pdev: PCI handle for this device
- * @soft: soft struct for this device
- * @ioc4: ioc4 mem space
+ * @idd: Master module data for this IOC4
  */
-static int inline ioc4_attach_local(struct pci_dev *pdev,
-                       struct ioc4_control *control,
-                       struct ioc4_soft *soft, void __iomem *ioc4_mem,
-                       void __iomem *ioc4_serial)
+static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
 {
        struct ioc4_port *port;
        struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS];
        int port_number;
        uint16_t ioc4_revid_min = 62;
        uint16_t ioc4_revid;
+       struct pci_dev *pdev = idd->idd_pdev;
+       struct ioc4_control* control = idd->idd_serial_data;
+       struct ioc4_soft *soft = control->ic_soft;
+       void __iomem *ioc4_misc = idd->idd_misc_regs;
+       void __iomem *ioc4_serial = soft->is_ioc4_serial_addr;
 
        /* IOC4 firmware must be at least rev 62 */
        pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid);
@@ -1076,7 +1037,7 @@ static int inline ioc4_attach_local(struct pci_dev *pdev,
                                ioc4_revid, ioc4_revid_min);
                return -EPERM;
        }
-       BUG_ON(ioc4_mem == NULL);
+       BUG_ON(ioc4_misc == NULL);
        BUG_ON(ioc4_serial == NULL);
 
        /* Create port structures for each port */
@@ -1100,10 +1061,18 @@ static int inline ioc4_attach_local(struct pci_dev *pdev,
                port->ip_ioc4_soft = soft;
                port->ip_pdev = pdev;
                port->ip_ienb = 0;
-               port->ip_pci_bus_speed = IOC4_SER_XIN_CLK;
+               /* Use baud rate calculations based on detected PCI
+                * bus speed.  Simply test whether the PCI clock is
+                * running closer to 66MHz or 33MHz.
+                */
+               if (idd->count_period/IOC4_EXTINT_COUNT_DIVISOR < 20) {
+                       port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_66;
+               } else {
+                       port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_33;
+               }
                port->ip_baud = 9600;
                port->ip_control = control;
-               port->ip_mem = ioc4_mem;
+               port->ip_mem = ioc4_misc;
                port->ip_serial = ioc4_serial;
 
                /* point to the right hook */
@@ -1604,14 +1573,12 @@ static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto)
        switch (proto) {
        case PROTO_RS232:
                /* Clear the appropriate GIO pin */
-               writel(0, (&port->ip_mem->gppr_0 +
-                                 hooks->rs422_select_pin));
+               writel(0, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
                break;
 
        case PROTO_RS422:
                /* Set the appropriate GIO pin */
-               writel(1, (&port->ip_mem->gppr_0 +
-                                 hooks->rs422_select_pin));
+               writel(1, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
                break;
 
        default:
@@ -1885,7 +1852,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
                if (sio_ir & hooks->intr_delta_dcd) {
                        /* ACK the interrupt */
                        writel(hooks->intr_delta_dcd,
-                               &port->ip_mem->sio_ir);
+                               &port->ip_mem->sio_ir.raw);
 
                        shadow = readl(&port->ip_serial_regs->shadow);
 
@@ -1907,7 +1874,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
                if (sio_ir & hooks->intr_delta_cts) {
                        /* ACK the interrupt */
                        writel(hooks->intr_delta_cts,
-                                       &port->ip_mem->sio_ir);
+                                       &port->ip_mem->sio_ir.raw);
 
                        shadow = readl(&port->ip_serial_regs->shadow);
 
@@ -1928,7 +1895,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
                if (sio_ir & hooks->intr_rx_timer) {
                        /* ACK the interrupt */
                        writel(hooks->intr_rx_timer,
-                               &port->ip_mem->sio_ir);
+                               &port->ip_mem->sio_ir.raw);
 
                        if ((port->ip_notify & N_DATA_READY)
                                        && (port->ip_port)) {
@@ -1974,7 +1941,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
 
                        /* ACK the interrupt */
                        writel(hooks->intr_tx_explicit,
-                                       &port->ip_mem->sio_ir);
+                                       &port->ip_mem->sio_ir.raw);
 
                        if (port->ip_notify & N_OUTPUT_LOWAT)
                                ioc4_cb_output_lowat(port);
@@ -2634,7 +2601,8 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
 {
        struct ioc4_port *port;
        struct uart_port *the_port;
-       struct ioc4_control *control = pci_get_drvdata(pdev);
+       struct ioc4_driver_data *idd = pci_get_drvdata(pdev);
+       struct ioc4_control *control = idd->idd_serial_data;
        int ii;
 
        DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
@@ -2680,55 +2648,29 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
 
 /**
  * ioc4_serial_attach_one - register attach function
- *             called per card found from ioc4_serial_detect as part
- *             of module_init().
- * @pdev: handle for this card
- * @pci_id: pci id for this card
+ *             called per card found from IOC4 master module.
+ * @idd: Master module data for this IOC4
  */
 int
-ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ioc4_serial_attach_one(struct ioc4_driver_data *idd)
 {
-       struct ioc4_mem __iomem *mem;
-       unsigned long tmp_addr, tmp_addr1;
+       unsigned long tmp_addr1;
        struct ioc4_serial __iomem *serial;
        struct ioc4_soft *soft;
        struct ioc4_control *control;
-       int tmp, ret = 0;
+       int ret = 0;
 
 
-       DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, pdev, pci_id));
-
-       /* Map in the ioc4 memory */
-       tmp_addr = pci_resource_start(pdev, 0);
-       if (!tmp_addr) {
-               printk(KERN_WARNING
-                        "ioc4 (%p) : unable to get PIO mapping for "
-                               "MEM space\n", (void *)pdev);
-               return -ENODEV;
-       }
-       if (!request_region(tmp_addr, sizeof(struct ioc4_mem), "sioc4_mem")) {
-               printk(KERN_ALERT
-                       "ioc4 (%p): unable to get request region for "
-                       "MEM space\n", (void *)pdev);
-               return -ENODEV;
-       }
-       mem = ioremap(tmp_addr, sizeof(struct ioc4_mem));
-       if (!mem) {
-               printk(KERN_WARNING
-                        "ioc4 (%p) : unable to remap ioc4 memory\n",
-                               (void *)pdev);
-               ret = -ENODEV;
-               goto out1;
-       }
+       DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id));
 
        /* request serial registers */
-       tmp_addr1 = pci_resource_start(pdev, 0) + IOC4_SERIAL_OFFSET;
+       tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
 
        if (!request_region(tmp_addr1, sizeof(struct ioc4_serial),
                                        "sioc4_uart")) {
                printk(KERN_WARNING
                        "ioc4 (%p): unable to get request region for "
-                               "uart space\n", (void *)pdev);
+                               "uart space\n", (void *)idd->idd_pdev);
                ret = -ENODEV;
                goto out1;
        }
@@ -2736,12 +2678,12 @@ ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
        if (!serial) {
                printk(KERN_WARNING
                         "ioc4 (%p) : unable to remap ioc4 serial register\n",
-                               (void *)pdev);
+                               (void *)idd->idd_pdev);
                ret = -ENODEV;
                goto out2;
        }
        DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
-                               __FUNCTION__, (void *)mem, (void *)serial));
+                               __FUNCTION__, (void *)idd->idd_misc_regs, (void *)serial));
 
        /* Get memory for the new card */
        control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS,
@@ -2754,59 +2696,56 @@ ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
                goto out2;
        }
        memset(control, 0, sizeof(struct ioc4_control));
-       pci_set_drvdata(pdev, control);
+       idd->idd_serial_data = control;
 
        /* Allocate the soft structure */
        soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
        if (!soft) {
                printk(KERN_WARNING
                       "ioc4 (%p): unable to get memory for the soft struct\n",
-                      (void *)pdev);
+                      (void *)idd->idd_pdev);
                ret = -ENOMEM;
                goto out3;
        }
        memset(soft, 0, sizeof(struct ioc4_soft));
 
        spin_lock_init(&soft->is_ir_lock);
-       soft->is_ioc4_mem_addr = mem;
+       soft->is_ioc4_misc_addr = idd->idd_misc_regs;
        soft->is_ioc4_serial_addr = serial;
 
        /* Init the IOC4 */
-       pci_read_config_dword(pdev, PCI_COMMAND, &tmp);
-       pci_write_config_dword(pdev, PCI_COMMAND,
-                              tmp | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
-
-       writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, &mem->sio_cr);
+       writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT,
+              &idd->idd_misc_regs->sio_cr.raw);
 
        /* Enable serial port mode select generic PIO pins as outputs */
        writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL
                | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL,
-               &mem->gpcr_s);
+               &idd->idd_misc_regs->gpcr_s.raw);
 
-       /* Clear and disable all interrupts */
+       /* Clear and disable all serial interrupts */
        write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
-       writel(~0, &mem->sio_ir);
-       write_ireg(soft, ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR),
-                       IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
-       writel(~(IOC4_OTHER_IR_ATA_MEMERR | IOC4_OTHER_IR_ATA_MEMERR),
-                                       &mem->other_ir);
+       writel(~0, &idd->idd_misc_regs->sio_ir.raw);
+       write_ireg(soft, IOC4_OTHER_IR_SER_MEMERR, IOC4_W_IEC,
+                  IOC4_OTHER_INTR_TYPE);
+       writel(IOC4_OTHER_IR_SER_MEMERR, &idd->idd_misc_regs->other_ir.raw);
        control->ic_soft = soft;
-       if (!request_irq(pdev->irq, ioc4_intr, SA_SHIRQ,
+
+       /* Hook up interrupt handler */
+       if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ,
                                "sgi-ioc4serial", (void *)soft)) {
-               control->ic_irq = pdev->irq;
+               control->ic_irq = idd->idd_pdev->irq;
        } else {
                printk(KERN_WARNING
                    "%s : request_irq fails for IRQ 0x%x\n ",
-                       __FUNCTION__, pdev->irq);
+                       __FUNCTION__, idd->idd_pdev->irq);
        }
-       if ((ret = ioc4_attach_local(pdev, control, soft,
-                               soft->is_ioc4_mem_addr,
-                               soft->is_ioc4_serial_addr)))
+       ret = ioc4_attach_local(idd);
+       if (ret)
                goto out4;
 
        /* register port with the serial core */
 
-       if ((ret = ioc4_serial_core_attach(pdev)))
+       if ((ret = ioc4_serial_core_attach(idd->idd_pdev)))
                goto out4;
 
        return ret;
@@ -2819,7 +2758,6 @@ out3:
 out2:
        release_region(tmp_addr1, sizeof(struct ioc4_serial));
 out1:
-       release_region(tmp_addr, sizeof(struct ioc4_mem));
 
        return ret;
 }
@@ -2828,11 +2766,10 @@ out1:
 /**
  * ioc4_serial_remove_one - detach function
  *
- * @pdev: handle for this card
+ * @idd: IOC4 master module data for this IOC4
  */
 
-#if 0
-void ioc4_serial_remove_one(struct pci_dev *pdev)
+int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
 {
        int ii;
        struct ioc4_control *control;
@@ -2840,7 +2777,7 @@ void ioc4_serial_remove_one(struct pci_dev *pdev)
        struct ioc4_port *port;
        struct ioc4_soft *soft;
 
-       control = pci_get_drvdata(pdev);
+       control = idd->idd_serial_data;
 
        for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
                the_port = &control->ic_port[ii].icp_uart_port;
@@ -2867,10 +2804,17 @@ void ioc4_serial_remove_one(struct pci_dev *pdev)
                kfree(soft);
        }
        kfree(control);
-       pci_set_drvdata(pdev, NULL);
-       uart_unregister_driver(&ioc4_uart);
+       idd->idd_serial_data = NULL;
+
+       return 0;
 }
-#endif
+
+static struct ioc4_submodule ioc4_serial_submodule = {
+       .is_name = "IOC4_serial",
+       .is_owner = THIS_MODULE,
+       .is_probe = ioc4_serial_attach_one,
+       .is_remove = ioc4_serial_remove_one,
+};
 
 /**
  * ioc4_serial_init - module init
@@ -2886,12 +2830,20 @@ int ioc4_serial_init(void)
                        __FUNCTION__);
                return ret;
        }
-       return 0;
+
+       /* register with IOC4 main module */
+       return ioc4_register_submodule(&ioc4_serial_submodule);
+}
+
+static void __devexit ioc4_serial_exit(void)
+{
+       ioc4_unregister_submodule(&ioc4_serial_submodule);
+       uart_unregister_driver(&ioc4_uart);
 }
 
+module_init(ioc4_serial_init);
+module_exit(ioc4_serial_exit);
+
 MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
 MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ioc4_serial_init);
-EXPORT_SYMBOL(ioc4_serial_attach_one);
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
new file mode 100644 (file)
index 0000000..13b8d24
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Miscellaneous SN-specific devices
+#
+
+menu "SN Devices"
+
+config SGI_IOC4
+       tristate "SGI IOC4 Base IO support"
+       depends on (IA64_GENERIC || IA64_SGI_SN2) && MMTIMER
+       default m
+       ---help---
+       This option enables basic support for the SGI IOC4-based Base IO
+       controller card.  This option does not enable any specific
+       functions on such a card, but provides necessary infrastructure
+       for other drivers to utilize.
+
+       If you have an SGI Altix with an IOC4-based
+       I/O controller say Y.  Otherwise say N.
+
+endmenu
index 631e54958448fe64f641353119c78aa482a7fb02..c2a2841853727d0cf02baa87e0d260ffac1114de 100644 (file)
@@ -3,4 +3,4 @@
 #
 #
 
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4.o
+obj-$(CONFIG_SGI_IOC4) += ioc4.o
index d9e4ee280e5f73edeed60879fd27348bb64d9ea1..ea75b3d0612b596819fba49a6d17c8e24939e941 100644 (file)
  * Copyright (C) 2005 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
-/*
- * This file contains a shim driver for the IOC4 IDE and serial drivers.
+/* This file contains the master driver module for use by SGI IOC4 subdrivers.
+ *
+ * It allocates any resources shared between multiple subdevices, and
+ * provides accessor functions (where needed) and the like for those
+ * resources.  It also provides a mechanism for the subdevice modules
+ * to support loading and unloading.
+ *
+ * Non-shared resources (e.g. external interrupt A_INT_OUT register page
+ * alias, serial port and UART registers) are handled by the subdevice
+ * modules themselves.
+ *
+ * This is all necessary because IOC4 is not implemented as a multi-function
+ * PCI device, but an amalgamation of disparate registers for several
+ * types of device (ATA, serial, external interrupts).  The normal
+ * resource management in the kernel doesn't have quite the right interfaces
+ * to handle this situation (e.g. multiple modules can't claim the same
+ * PCI ID), thus this IOC4 master module.
  */
 
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/ioc4_common.h>
-#include <linux/ide.h>
+#include <linux/ioc4.h>
+#include <linux/mmtimer.h>
+#include <linux/rtc.h>
+#include <linux/rwsem.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/shub_mmr.h>
 
+/***************
+ * Definitions *
+ ***************/
 
-static int __devinit
-ioc4_probe_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+/* Tweakable values */
+
+/* PCI bus speed detection/calibration */
+#define IOC4_CALIBRATE_COUNT 63        /* Calibration cycle period */
+#define IOC4_CALIBRATE_CYCLES 256      /* Average over this many cycles */
+#define IOC4_CALIBRATE_DISCARD 2       /* Discard first few cycles */
+#define IOC4_CALIBRATE_LOW_MHZ 25      /* Lower bound on bus speed sanity */
+#define IOC4_CALIBRATE_HIGH_MHZ 75     /* Upper bound on bus speed sanity */
+#define IOC4_CALIBRATE_DEFAULT_MHZ 66  /* Assumed if sanity check fails */
+
+/************************
+ * Submodule management *
+ ************************/
+
+static LIST_HEAD(ioc4_devices);
+static DECLARE_RWSEM(ioc4_devices_rwsem);
+
+static LIST_HEAD(ioc4_submodules);
+static DECLARE_RWSEM(ioc4_submodules_rwsem);
+
+/* Register an IOC4 submodule */
+int
+ioc4_register_submodule(struct ioc4_submodule *is)
+{
+       struct ioc4_driver_data *idd;
+
+       down_write(&ioc4_submodules_rwsem);
+       list_add(&is->is_list, &ioc4_submodules);
+       up_write(&ioc4_submodules_rwsem);
+
+       /* Initialize submodule for each IOC4 */
+       if (!is->is_probe)
+               return 0;
+
+       down_read(&ioc4_devices_rwsem);
+       list_for_each_entry(idd, &ioc4_devices, idd_list) {
+               if (is->is_probe(idd)) {
+                       printk(KERN_WARNING
+                              "%s: IOC4 submodule %s probe failed "
+                              "for pci_dev %s",
+                              __FUNCTION__, module_name(is->is_owner),
+                              pci_name(idd->idd_pdev));
+               }
+       }
+       up_read(&ioc4_devices_rwsem);
+
+       return 0;
+}
+
+/* Unregister an IOC4 submodule */
+void
+ioc4_unregister_submodule(struct ioc4_submodule *is)
+{
+       struct ioc4_driver_data *idd;
+
+       down_write(&ioc4_submodules_rwsem);
+       list_del(&is->is_list);
+       up_write(&ioc4_submodules_rwsem);
+
+       /* Remove submodule for each IOC4 */
+       if (!is->is_remove)
+               return;
+
+       down_read(&ioc4_devices_rwsem);
+       list_for_each_entry(idd, &ioc4_devices, idd_list) {
+               if (is->is_remove(idd)) {
+                       printk(KERN_WARNING
+                              "%s: IOC4 submodule %s remove failed "
+                              "for pci_dev %s.\n",
+                              __FUNCTION__, module_name(is->is_owner),
+                              pci_name(idd->idd_pdev));
+               }
+       }
+       up_read(&ioc4_devices_rwsem);
+}
+
+/*********************
+ * Device management *
+ *********************/
+
+#define IOC4_CALIBRATE_LOW_LIMIT \
+       (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_LOW_MHZ)
+#define IOC4_CALIBRATE_HIGH_LIMIT \
+       (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_HIGH_MHZ)
+#define IOC4_CALIBRATE_DEFAULT \
+       (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_DEFAULT_MHZ)
+
+#define IOC4_CALIBRATE_END \
+       (IOC4_CALIBRATE_CYCLES + IOC4_CALIBRATE_DISCARD)
+
+#define IOC4_INT_OUT_MODE_TOGGLE 0x7   /* Toggle INT_OUT every COUNT+1 ticks */
+
+/* Determines external interrupt output clock period of the PCI bus an
+ * IOC4 is attached to.  This value can be used to determine the PCI
+ * bus speed.
+ *
+ * IOC4 has a design feature that various internal timers are derived from
+ * the PCI bus clock.  This causes IOC4 device drivers to need to take the
+ * bus speed into account when setting various register values (e.g. INT_OUT
+ * register COUNT field, UART divisors, etc).  Since this information is
+ * needed by several subdrivers, it is determined by the main IOC4 driver,
+ * even though the following code utilizes external interrupt registers
+ * to perform the speed calculation.
+ */
+static void
+ioc4_clock_calibrate(struct ioc4_driver_data *idd)
+{
+       extern unsigned long sn_rtc_cycles_per_second;
+       union ioc4_int_out int_out;
+       union ioc4_gpcr gpcr;
+       unsigned int state, last_state = 1;
+       uint64_t start = 0, end, period;
+       unsigned int count = 0;
+
+       /* Enable output */
+       gpcr.raw = 0;
+       gpcr.fields.dir = IOC4_GPCR_DIR_0;
+       gpcr.fields.int_out_en = 1;
+       writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw);
+
+       /* Reset to power-on state */
+       writel(0, &idd->idd_misc_regs->int_out.raw);
+       mmiowb();
+
+       printk(KERN_INFO
+              "%s: Calibrating PCI bus speed "
+              "for pci_dev %s ... ", __FUNCTION__, pci_name(idd->idd_pdev));
+       /* Set up square wave */
+       int_out.raw = 0;
+       int_out.fields.count = IOC4_CALIBRATE_COUNT;
+       int_out.fields.mode = IOC4_INT_OUT_MODE_TOGGLE;
+       int_out.fields.diag = 0;
+       writel(int_out.raw, &idd->idd_misc_regs->int_out.raw);
+       mmiowb();
+
+       /* Check square wave period averaged over some number of cycles */
+       do {
+               int_out.raw = readl(&idd->idd_misc_regs->int_out.raw);
+               state = int_out.fields.int_out;
+               if (!last_state && state) {
+                       count++;
+                       if (count == IOC4_CALIBRATE_END) {
+                               end = rtc_time();
+                               break;
+                       } else if (count == IOC4_CALIBRATE_DISCARD)
+                               start = rtc_time();
+               }
+               last_state = state;
+       } while (1);
+
+       /* Calculation rearranged to preserve intermediate precision.
+        * Logically:
+        * 1. "end - start" gives us number of RTC cycles over all the
+        *    square wave cycles measured.
+        * 2. Divide by number of square wave cycles to get number of
+        *    RTC cycles per square wave cycle.
+        * 3. Divide by 2*(int_out.fields.count+1), which is the formula
+        *    by which the IOC4 generates the square wave, to get the
+        *    number of RTC cycles per IOC4 INT_OUT count.
+        * 4. Divide by sn_rtc_cycles_per_second to get seconds per
+        *    count.
+        * 5. Multiply by 1E9 to get nanoseconds per count.
+        */
+       period = ((end - start) * 1000000000) /
+           (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1)
+            * sn_rtc_cycles_per_second);
+
+       /* Bounds check the result. */
+       if (period > IOC4_CALIBRATE_LOW_LIMIT ||
+           period < IOC4_CALIBRATE_HIGH_LIMIT) {
+               printk("failed. Assuming PCI clock ticks are %d ns.\n",
+                      IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
+               period = IOC4_CALIBRATE_DEFAULT;
+       } else {
+               printk("succeeded. PCI clock ticks are %ld ns.\n",
+                      period / IOC4_EXTINT_COUNT_DIVISOR);
+       }
+
+       /* Remember results.  We store the extint clock period rather
+        * than the PCI clock period so that greater precision is
+        * retained.  Divide by IOC4_EXTINT_COUNT_DIVISOR to get
+        * PCI clock period.
+        */
+       idd->count_period = period;
+}
+
+/* Adds a new instance of an IOC4 card */
+static int
+ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 {
+       struct ioc4_driver_data *idd;
+       struct ioc4_submodule *is;
+       uint32_t pcmd;
        int ret;
 
+       /* Enable IOC4 and take ownership of it */
        if ((ret = pci_enable_device(pdev))) {
                printk(KERN_WARNING
-                        "%s: Failed to enable device with "
-                               "pci_dev 0x%p... returning\n",
-                               __FUNCTION__, (void *)pdev);
-               return ret;
+                      "%s: Failed to enable IOC4 device for pci_dev %s.\n",
+                      __FUNCTION__, pci_name(pdev));
+               goto out;
        }
        pci_set_master(pdev);
 
-       /* attach each sub-device */
-       ret = ioc4_ide_attach_one(pdev, pci_id);
-       if (ret)
-               return ret;
-       return ioc4_serial_attach_one(pdev, pci_id);
+       /* Set up per-IOC4 data */
+       idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL);
+       if (!idd) {
+               printk(KERN_WARNING
+                      "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
+                      __FUNCTION__, pci_name(pdev));
+               ret = -ENODEV;
+               goto out_idd;
+       }
+       idd->idd_pdev = pdev;
+       idd->idd_pci_id = pci_id;
+
+       /* Map IOC4 misc registers.  These are shared between subdevices
+        * so the main IOC4 module manages them.
+        */
+       idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0);
+       if (!idd->idd_bar0) {
+               printk(KERN_WARNING
+                      "%s: Unable to find IOC4 misc resource "
+                      "for pci_dev %s.\n",
+                      __FUNCTION__, pci_name(idd->idd_pdev));
+               ret = -ENODEV;
+               goto out_pci;
+       }
+       if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
+                           "ioc4_misc")) {
+               printk(KERN_WARNING
+                      "%s: Unable to request IOC4 misc region "
+                      "for pci_dev %s.\n",
+                      __FUNCTION__, pci_name(idd->idd_pdev));
+               ret = -ENODEV;
+               goto out_pci;
+       }
+       idd->idd_misc_regs = ioremap(idd->idd_bar0,
+                                    sizeof(struct ioc4_misc_regs));
+       if (!idd->idd_misc_regs) {
+               printk(KERN_WARNING
+                      "%s: Unable to remap IOC4 misc region "
+                      "for pci_dev %s.\n",
+                      __FUNCTION__, pci_name(idd->idd_pdev));
+               ret = -ENODEV;
+               goto out_misc_region;
+       }
+
+       /* Failsafe portion of per-IOC4 initialization */
+
+       /* Initialize IOC4 */
+       pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
+       pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
+                              pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+
+       /* Determine PCI clock */
+       ioc4_clock_calibrate(idd);
+
+       /* Disable/clear all interrupts.  Need to do this here lest
+        * one submodule request the shared IOC4 IRQ, but interrupt
+        * is generated by a different subdevice.
+        */
+       /* Disable */
+       writel(~0, &idd->idd_misc_regs->other_iec.raw);
+       writel(~0, &idd->idd_misc_regs->sio_iec);
+       /* Clear (i.e. acknowledge) */
+       writel(~0, &idd->idd_misc_regs->other_ir.raw);
+       writel(~0, &idd->idd_misc_regs->sio_ir);
+
+       /* Track PCI-device specific data */
+       idd->idd_serial_data = NULL;
+       pci_set_drvdata(idd->idd_pdev, idd);
+       down_write(&ioc4_devices_rwsem);
+       list_add(&idd->idd_list, &ioc4_devices);
+       up_write(&ioc4_devices_rwsem);
+
+       /* Add this IOC4 to all submodules */
+       down_read(&ioc4_submodules_rwsem);
+       list_for_each_entry(is, &ioc4_submodules, is_list) {
+               if (is->is_probe && is->is_probe(idd)) {
+                       printk(KERN_WARNING
+                              "%s: IOC4 submodule 0x%s probe failed "
+                              "for pci_dev %s.\n",
+                              __FUNCTION__, module_name(is->is_owner),
+                              pci_name(idd->idd_pdev));
+               }
+       }
+       up_read(&ioc4_submodules_rwsem);
+
+       return 0;
+
+out_misc_region:
+       release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+out_pci:
+       kfree(idd);
+out_idd:
+       pci_disable_device(pdev);
+out:
+       return ret;
 }
 
-/* pci device struct */
-static struct pci_device_id ioc4_s_id_table[] = {
+/* Removes a particular instance of an IOC4 card. */
+static void
+ioc4_remove(struct pci_dev *pdev)
+{
+       struct ioc4_submodule *is;
+       struct ioc4_driver_data *idd;
+
+       idd = pci_get_drvdata(pdev);
+
+       /* Remove this IOC4 from all submodules */
+       down_read(&ioc4_submodules_rwsem);
+       list_for_each_entry(is, &ioc4_submodules, is_list) {
+               if (is->is_remove && is->is_remove(idd)) {
+                       printk(KERN_WARNING
+                              "%s: IOC4 submodule 0x%s remove failed "
+                              "for pci_dev %s.\n",
+                              __FUNCTION__, module_name(is->is_owner),
+                              pci_name(idd->idd_pdev));
+               }
+       }
+       up_read(&ioc4_submodules_rwsem);
+
+       /* Release resources */
+       iounmap(idd->idd_misc_regs);
+       if (!idd->idd_bar0) {
+               printk(KERN_WARNING
+                      "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
+                      "Device removal may be incomplete.\n",
+                      __FUNCTION__, pci_name(idd->idd_pdev));
+       }
+       release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+
+       /* Disable IOC4 and relinquish */
+       pci_disable_device(pdev);
+
+       /* Remove and free driver data */
+       down_write(&ioc4_devices_rwsem);
+       list_del(&idd->idd_list);
+       up_write(&ioc4_devices_rwsem);
+       kfree(idd);
+}
+
+static struct pci_device_id ioc4_id_table[] = {
        {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
         PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
        {0}
 };
-MODULE_DEVICE_TABLE(pci, ioc4_s_id_table);
 
-static struct pci_driver __devinitdata ioc4_s_driver = {
-       .name   = "IOC4",
-       .id_table = ioc4_s_id_table,
-       .probe  = ioc4_probe_one,
+static struct pci_driver __devinitdata ioc4_driver = {
+       .name = "IOC4",
+       .id_table = ioc4_id_table,
+       .probe = ioc4_probe,
+       .remove = ioc4_remove,
 };
 
-static int __devinit ioc4_detect(void)
+MODULE_DEVICE_TABLE(pci, ioc4_id_table);
+
+/*********************
+ * Module management *
+ *********************/
+
+/* Module load */
+static int __devinit
+ioc4_init(void)
 {
-       ioc4_serial_init();
+       return pci_register_driver(&ioc4_driver);
+}
 
-       return pci_register_driver(&ioc4_s_driver);
+/* Module unload */
+static void __devexit
+ioc4_exit(void)
+{
+       pci_unregister_driver(&ioc4_driver);
 }
-module_init(ioc4_detect);
 
-MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
-MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+module_init(ioc4_init);
+module_exit(ioc4_exit);
+
+MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. <bcasavan@sgi.com>");
+MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card");
 MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc4_register_submodule);
+EXPORT_SYMBOL(ioc4_unregister_submodule);
index 6be8fbec0a0e2e1d454bc1513df3eba8fa49d248..04d3120f72368e1186fc64bbe97b082a23394daa 100644 (file)
@@ -322,6 +322,22 @@ config FB_FM2
          This is the frame buffer device driver for the Amiga FrameMaster
          card from BSC (exhibited 1992 but not shipped as a CBM product).
 
+config FB_ARC
+       tristate "Arc Monochrome LCD board support"
+       depends on FB && X86
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       select FB_SOFT_CURSOR
+       help
+         This enables support for the Arc Monochrome LCD board. The board
+         is based on the KS-108 lcd controller and is typically a matrix
+         of 2*n chips. This driver was tested with a 128x64 panel. This
+         driver supports it for use with x86 SBCs through a 16 bit GPIO
+         interface (8 bit data, 8 bit control). If you anticpate using
+         this driver, say Y or M; otherwise say N. You must specify the
+         GPIO IO address to be used for setting control and data.
+
 config FB_ATARI
        bool "Atari native chipset support"
        depends on (FB = y) && ATARI && BROKEN
index bd8dc0ffe723d9070b054af1e74703b053d3da75..b018df4e95c84377c13ffda88e03dde02f26e467 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_FB_MACMODES)      += macmodes.o
 # Hardware specific drivers go first
 obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
+obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
 obj-$(CONFIG_FB_CYBER)            += cyberfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
new file mode 100644 (file)
index 0000000..d28457e
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
+ *
+ * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
+ * http://www.intworks.biz/arclcd
+ *
+ * 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.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This driver was written to be used with the Arc LCD board. Arc uses a
+ * set of KS108 chips that control individual 64x64 LCD matrices. The board
+ * can be paneled in a variety of setups such as 2x1=128x64, 4x4=256x256 and
+ * so on. The interface between the board and the host is TTL based GPIO. The
+ * GPIO requirements are 8 writable data lines and 4+n lines for control. On a
+ * GPIO-less system, the board can be tested by connecting the respective sigs
+ * up to a parallel port connector. The driver requires the IO addresses for
+ * data and control GPIO at load time. It is unable to probe for the
+ * existence of the LCD so it must be told at load time whether it should
+ * be enabled or not.
+ *
+ * Todo:
+ * - testing with 4x4
+ * - testing with interrupt hw
+ *
+ * General notes:
+ * - User must set tuhold. It's in microseconds. According to the 108 spec,
+ *   the hold time is supposed to be at least 1 microsecond.
+ * - User must set num_cols=x num_rows=y, eg: x=2 means 128
+ * - User must set arcfb_enable=1 to enable it
+ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/arcfb.h>
+
+#include <asm/uaccess.h>
+
+#define floor8(a) (a&(~0x07))
+#define floorXres(a,xres) (a&(~(xres - 1)))
+#define iceil8(a) (((int)((a+7)/8))*8)
+#define ceil64(a) (a|0x3F)
+#define ceilXres(a,xres) (a|(xres - 1))
+
+/* ks108 chipset specific defines and code */
+
+#define KS_SET_DPY_START_LINE  0xC0
+#define KS_SET_PAGE_NUM        0xB8
+#define KS_SET_X               0x40
+#define KS_CEHI                0x01
+#define KS_CELO                0x00
+#define KS_SEL_CMD             0x08
+#define KS_SEL_DATA            0x00
+#define KS_DPY_ON              0x3F
+#define KS_DPY_OFF             0x3E
+#define KS_INTACK              0x40
+#define KS_CLRINT              0x02
+
+struct arcfb_par {
+       unsigned long dio_addr;
+       unsigned long cio_addr;
+       unsigned long c2io_addr;
+       atomic_t ref_count;
+       unsigned char cslut[9];
+       struct fb_info *info;
+       unsigned int irq;
+       spinlock_t lock;
+};
+
+static struct fb_fix_screeninfo arcfb_fix __initdata = {
+       .id =           "arcfb",
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_MONO01,
+       .xpanstep =     0,
+       .ypanstep =     1,
+       .ywrapstep =    0,
+       .accel =        FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo arcfb_var __initdata = {
+       .xres           = 128,
+       .yres           = 64,
+       .xres_virtual   = 128,
+       .yres_virtual   = 64,
+       .bits_per_pixel = 1,
+       .nonstd         = 1,
+};
+
+static unsigned long num_cols;
+static unsigned long num_rows;
+static unsigned long dio_addr;
+static unsigned long cio_addr;
+static unsigned long c2io_addr;
+static unsigned long splashval;
+static unsigned long tuhold;
+static unsigned int nosplash;
+static unsigned int arcfb_enable;
+static unsigned int irq;
+
+static DECLARE_WAIT_QUEUE_HEAD(arcfb_waitq);
+
+static void ks108_writeb_ctl(struct arcfb_par *par,
+                               unsigned int chipindex, unsigned char value)
+{
+       unsigned char chipselval = par->cslut[chipindex];
+
+       outb(chipselval|KS_CEHI|KS_SEL_CMD, par->cio_addr);
+       outb(value, par->dio_addr);
+       udelay(tuhold);
+       outb(chipselval|KS_CELO|KS_SEL_CMD, par->cio_addr);
+}
+
+static void ks108_writeb_mainctl(struct arcfb_par *par, unsigned char value)
+{
+
+       outb(value, par->cio_addr);
+       udelay(tuhold);
+}
+
+static unsigned char ks108_readb_ctl2(struct arcfb_par *par)
+{
+       return inb(par->c2io_addr);
+}
+
+static void ks108_writeb_data(struct arcfb_par *par,
+                               unsigned int chipindex, unsigned char value)
+{
+       unsigned char chipselval = par->cslut[chipindex];
+
+       outb(chipselval|KS_CEHI|KS_SEL_DATA, par->cio_addr);
+       outb(value, par->dio_addr);
+       udelay(tuhold);
+       outb(chipselval|KS_CELO|KS_SEL_DATA, par->cio_addr);
+}
+
+static void ks108_set_start_line(struct arcfb_par *par,
+                               unsigned int chipindex, unsigned char y)
+{
+       ks108_writeb_ctl(par, chipindex, KS_SET_DPY_START_LINE|y);
+}
+
+static void ks108_set_yaddr(struct arcfb_par *par,
+                               unsigned int chipindex, unsigned char y)
+{
+       ks108_writeb_ctl(par, chipindex, KS_SET_PAGE_NUM|y);
+}
+
+static void ks108_set_xaddr(struct arcfb_par *par,
+                               unsigned int chipindex, unsigned char x)
+{
+       ks108_writeb_ctl(par, chipindex, KS_SET_X|x);
+}
+
+static void ks108_clear_lcd(struct arcfb_par *par, unsigned int chipindex)
+{
+       int i,j;
+
+       for (i = 0; i <= 8; i++) {
+               ks108_set_yaddr(par, chipindex, i);
+               ks108_set_xaddr(par, chipindex, 0);
+               for (j = 0; j < 64; j++) {
+                       ks108_writeb_data(par, chipindex,
+                               (unsigned char) splashval);
+               }
+       }
+}
+
+/* main arcfb functions */
+
+static int arcfb_open(struct fb_info *info, int user)
+{
+       struct arcfb_par *par = info->par;
+
+       atomic_inc(&par->ref_count);
+       return 0;
+}
+
+static int arcfb_release(struct fb_info *info, int user)
+{
+       struct arcfb_par *par = info->par;
+       int count = atomic_read(&par->ref_count);
+
+       if (!count)
+               return -EINVAL;
+       atomic_dec(&par->ref_count);
+       return 0;
+}
+
+static int arcfb_pan_display(struct fb_var_screeninfo *var,
+                               struct fb_info *info)
+{
+       int i;
+       struct arcfb_par *par = info->par;
+
+       if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 64)
+               && (info->var.yres <= 64)) {
+               for (i = 0; i < num_cols; i++) {
+                       ks108_set_start_line(par, i, var->yoffset);
+               }
+               info->var.yoffset = var->yoffset;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static irqreturn_t arcfb_interrupt(int vec, void *dev_instance,
+               struct pt_regs *regs)
+{
+       struct fb_info *info = dev_instance;
+       unsigned char ctl2status;
+       struct arcfb_par *par = info->par;
+
+       ctl2status = ks108_readb_ctl2(par);
+
+       if (!(ctl2status & KS_INTACK)) /* not arc generated interrupt */
+               return IRQ_NONE;
+
+       ks108_writeb_mainctl(par, KS_CLRINT);
+
+       spin_lock(&par->lock);
+        if (waitqueue_active(&arcfb_waitq)) {
+                wake_up(&arcfb_waitq);
+        }
+       spin_unlock(&par->lock);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * here we handle a specific page on the lcd. the complexity comes from
+ * the fact that the fb is laidout in 8xX vertical columns. we extract
+ * each write of 8 vertical pixels. then we shift out as we move along
+ * X. That's what rightshift does. bitmask selects the desired input bit.
+ */
+static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
+               unsigned int left, unsigned int right, unsigned int distance)
+{
+       unsigned char *src;
+       unsigned int xindex, yindex, chipindex, linesize;
+       int i, count;
+       unsigned char val;
+       unsigned char bitmask, rightshift;
+
+       xindex = left >> 6;
+       yindex = upper >> 6;
+       chipindex = (xindex + (yindex*num_cols));
+
+       ks108_set_yaddr(par, chipindex, upper/8);
+
+       linesize = par->info->var.xres/8;
+       src = par->info->screen_base + (left/8) + (upper * linesize);
+       ks108_set_xaddr(par, chipindex, left);
+
+       bitmask=1;
+       rightshift=0;
+       while (left <= right) {
+               val = 0;
+               for (i = 0; i < 8; i++) {
+                       if ( i > rightshift) {
+                               val |= (*(src + (i*linesize)) & bitmask)
+                                               << (i - rightshift);
+                       } else {
+                               val |= (*(src + (i*linesize)) & bitmask)
+                                                >> (rightshift - i);
+                       }
+               }
+               ks108_writeb_data(par, chipindex, val);
+               left++;
+               count++;
+               if (bitmask == 0x80) {
+                       bitmask = 1;
+                       src++;
+                       rightshift=0;
+               } else {
+                       bitmask <<= 1;
+                       rightshift++;
+               }
+       }
+}
+
+/*
+ * here we handle the entire vertical page of the update. we write across
+ * lcd chips. update_page uses the upper/left values to decide which
+ * chip to select for the right. upper is needed for setting the page
+ * desired for the write.
+ */
+static void arcfb_lcd_update_vert(struct arcfb_par *par, unsigned int top,
+               unsigned int bottom, unsigned int left, unsigned int right)
+{
+       unsigned int distance, upper, lower;
+
+       distance = (bottom - top) + 1;
+       upper = top;
+       lower = top + 7;
+
+       while (distance > 0) {
+               distance -= 8;
+               arcfb_lcd_update_page(par, upper, left, right, 8);
+               upper = lower + 1;
+               lower = upper + 7;
+       }
+}
+
+/*
+ * here we handle horizontal blocks for the update. update_vert will
+ * handle spaning multiple pages. we break out each horizontal
+ * block in to individual blocks no taller than 64 pixels.
+ */
+static void arcfb_lcd_update_horiz(struct arcfb_par *par, unsigned int left,
+                       unsigned int right, unsigned int top, unsigned int h)
+{
+       unsigned int distance, upper, lower;
+
+       distance = h;
+       upper = floor8(top);
+       lower = min(upper + distance - 1, ceil64(upper));
+
+       while (distance > 0) {
+               distance -= ((lower - upper) + 1 );
+               arcfb_lcd_update_vert(par, upper, lower, left, right);
+               upper = lower + 1;
+               lower = min(upper + distance - 1, ceil64(upper));
+       }
+}
+
+/*
+ * here we start the process of spliting out the fb update into
+ * individual blocks of pixels. we end up spliting into 64x64 blocks
+ * and finally down to 64x8 pages.
+ */
+static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
+                       unsigned int dy, unsigned int w, unsigned int h)
+{
+       unsigned int left, right, distance, y;
+
+       /* align the request first */
+       y = floor8(dy);
+       h += dy - y;
+       h = iceil8(h);
+
+       distance = w;
+       left = dx;
+       right = min(left + w - 1, ceil64(left));
+
+       while (distance > 0) {
+               arcfb_lcd_update_horiz(par, left, right, y, h);
+               distance -= ((right - left) + 1);
+               left = right + 1;
+               right = min(left + distance - 1, ceil64(left));
+       }
+}
+
+void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+       struct arcfb_par *par = info->par;
+
+       cfb_fillrect(info, rect);
+
+       /* update the physical lcd */
+       arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+       struct arcfb_par *par = info->par;
+
+       cfb_copyarea(info, area);
+
+       /* update the physical lcd */
+       arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
+}
+
+void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct arcfb_par *par = info->par;
+
+       cfb_imageblit(info, image);
+
+       /* update the physical lcd */
+       arcfb_lcd_update(par, image->dx, image->dy, image->width,
+                               image->height);
+}
+
+static int arcfb_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg,
+                         struct fb_info *info)
+{
+       void __user *argp = (void __user *)arg;
+       struct arcfb_par *par = info->par;
+       unsigned long flags;
+
+       switch (cmd) {
+               case FBIO_WAITEVENT:
+               {
+                       DEFINE_WAIT(wait);
+                       /* illegal to wait on arc if no irq will occur */
+                       if (!par->irq)
+                               return -EINVAL;
+
+                       /* wait until the Arc has generated an interrupt
+                        * which will wake us up */
+                       spin_lock_irqsave(&par->lock, flags);
+                       prepare_to_wait(&arcfb_waitq, &wait,
+                                       TASK_INTERRUPTIBLE);
+                       spin_unlock_irqrestore(&par->lock, flags);
+                       schedule();
+                       finish_wait(&arcfb_waitq, &wait);
+               }
+               case FBIO_GETCONTROL2:
+               {
+                       unsigned char ctl2;
+
+                       ctl2 = ks108_readb_ctl2(info->par);
+                       if (copy_to_user(argp, &ctl2, sizeof(ctl2)))
+                               return -EFAULT;
+                       return 0;
+               }
+               default:
+                       return -EINVAL;
+       }
+}
+
+/*
+ * this is the access path from userspace. they can seek and write to
+ * the fb. it's inefficient for them to do anything less than 64*8
+ * writes since we update the lcd in each write() anyway.
+ */
+static ssize_t arcfb_write(struct file *file, const char *buf, size_t count,
+                               loff_t *ppos)
+{
+       /* modded from epson 1355 */
+
+       struct inode *inode;
+       int fbidx;
+       struct fb_info *info;
+       unsigned long p;
+       int err=-EINVAL;
+       unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
+       struct arcfb_par *par;
+       unsigned int xres;
+
+       p = *ppos;
+       inode = file->f_dentry->d_inode;
+       fbidx = iminor(inode);
+       info = registered_fb[fbidx];
+       par = info->par;
+
+       if (!info || !info->screen_base)
+               return -ENODEV;
+
+       xres = info->var.xres;
+       fbmemlength = (xres * info->var.yres)/8;
+
+       if (p > fbmemlength)
+               return -ENOSPC;
+
+       err = 0;
+       if ((count + p) > fbmemlength) {
+               count = fbmemlength - p;
+               err = -ENOSPC;
+       }
+
+       if (count) {
+               char *base_addr;
+
+               base_addr = info->screen_base;
+               count -= copy_from_user(base_addr + p, buf, count);
+               *ppos += count;
+               err = -EFAULT;
+       }
+
+
+       bitppos = p*8;
+       startpos = floorXres(bitppos, xres);
+       endpos = ceilXres((bitppos + (count*8)), xres);
+       bitcount = endpos - startpos;
+
+       x = startpos % xres;
+       y = startpos / xres;
+       w = xres;
+       h = bitcount / xres;
+       arcfb_lcd_update(par, x, y, w, h);
+
+       if (count)
+               return count;
+       return err;
+}
+
+static void arcfb_platform_release(struct device *device)
+{
+}
+
+static struct fb_ops arcfb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_open        = arcfb_open,
+       .fb_write       = arcfb_write,
+       .fb_release     = arcfb_release,
+       .fb_pan_display = arcfb_pan_display,
+       .fb_fillrect    = arcfb_fillrect,
+       .fb_copyarea    = arcfb_copyarea,
+       .fb_imageblit   = arcfb_imageblit,
+       .fb_cursor      = soft_cursor,
+       .fb_ioctl       = arcfb_ioctl,
+};
+
+static int __init arcfb_probe(struct device *device)
+{
+       struct platform_device *dev = to_platform_device(device);
+       struct fb_info *info;
+       int retval = -ENOMEM;
+       int videomemorysize;
+       unsigned char *videomemory;
+       struct arcfb_par *par;
+       int i;
+
+       videomemorysize = (((64*64)*num_cols)*num_rows)/8;
+
+       /* We need a flat backing store for the Arc's
+          less-flat actual paged framebuffer */
+       if (!(videomemory = vmalloc(videomemorysize)))
+               return retval;
+
+       memset(videomemory, 0, videomemorysize);
+
+       info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
+       if (!info)
+               goto err;
+
+       info->screen_base = (char __iomem *)videomemory;
+       info->fbops = &arcfb_ops;
+
+       info->var = arcfb_var;
+       info->fix = arcfb_fix;
+       par = info->par;
+       par->info = info;
+
+       if (!dio_addr || !cio_addr || !c2io_addr) {
+               printk(KERN_WARNING "no IO addresses supplied\n");
+               goto err1;
+       }
+       par->dio_addr = dio_addr;
+       par->cio_addr = cio_addr;
+       par->c2io_addr = c2io_addr;
+       par->cslut[0] = 0x00;
+       par->cslut[1] = 0x06;
+       info->flags = FBINFO_FLAG_DEFAULT;
+       spin_lock_init(&par->lock);
+       retval = register_framebuffer(info);
+       if (retval < 0)
+               goto err1;
+       dev_set_drvdata(&dev->dev, info);
+       if (irq) {
+               par->irq = irq;
+               if (request_irq(par->irq, &arcfb_interrupt, SA_SHIRQ,
+                               "arcfb", info)) {
+                       printk(KERN_INFO
+                               "arcfb: Failed req IRQ %d\n", par->irq);
+                       goto err1;
+               }
+       }
+       printk(KERN_INFO
+              "fb%d: Arc frame buffer device, using %dK of video memory\n",
+              info->node, videomemorysize >> 10);
+
+       /* this inits the lcd but doesn't clear dirty pixels */
+       for (i = 0; i < num_cols * num_rows; i++) {
+               ks108_writeb_ctl(par, i, KS_DPY_OFF);
+               ks108_set_start_line(par, i, 0);
+               ks108_set_yaddr(par, i, 0);
+               ks108_set_xaddr(par, i, 0);
+               ks108_writeb_ctl(par, i, KS_DPY_ON);
+       }
+
+       /* if we were told to splash the screen, we just clear it */
+       if (!nosplash) {
+               for (i = 0; i < num_cols * num_rows; i++) {
+                       printk(KERN_INFO "fb%d: splashing lcd %d\n",
+                               info->node, i);
+                       ks108_set_start_line(par, i, 0);
+                       ks108_clear_lcd(par, i);
+               }
+       }
+
+       return 0;
+err1:
+       framebuffer_release(info);
+err:
+       vfree(videomemory);
+       return retval;
+}
+
+static int arcfb_remove(struct device *device)
+{
+       struct fb_info *info = dev_get_drvdata(device);
+
+       if (info) {
+               unregister_framebuffer(info);
+               vfree(info->screen_base);
+               framebuffer_release(info);
+       }
+       return 0;
+}
+
+static struct device_driver arcfb_driver = {
+       .name   = "arcfb",
+       .bus    = &platform_bus_type,
+       .probe  = arcfb_probe,
+       .remove = arcfb_remove,
+};
+
+static struct platform_device arcfb_device = {
+       .name   = "arcfb",
+       .id     = 0,
+       .dev    = {
+               .release = arcfb_platform_release,
+       }
+};
+
+static int __init arcfb_init(void)
+{
+       int ret;
+
+       if (!arcfb_enable)
+               return -ENXIO;
+
+       ret = driver_register(&arcfb_driver);
+       if (!ret) {
+               ret = platform_device_register(&arcfb_device);
+               if (ret)
+                       driver_unregister(&arcfb_driver);
+       }
+       return ret;
+
+}
+
+static void __exit arcfb_exit(void)
+{
+       platform_device_unregister(&arcfb_device);
+       driver_unregister(&arcfb_driver);
+}
+
+module_param(num_cols, ulong, 0);
+MODULE_PARM_DESC(num_cols, "Num horiz panels, eg: 2 = 128 bit wide");
+module_param(num_rows, ulong, 0);
+MODULE_PARM_DESC(num_rows, "Num vert panels, eg: 1 = 64 bit high");
+module_param(nosplash, uint, 0);
+MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
+module_param(arcfb_enable, uint, 0);
+MODULE_PARM_DESC(arcfb_enable, "Enable communication with Arc board");
+module_param(dio_addr, ulong, 0);
+MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
+module_param(cio_addr, ulong, 0);
+MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
+module_param(c2io_addr, ulong, 0);
+MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
+module_param(splashval, ulong, 0);
+MODULE_PARM_DESC(splashval, "Splash pattern: 0xFF is black, 0x00 is green");
+module_param(tuhold, ulong, 0);
+MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Arc board");
+module_param(irq, uint, 0);
+MODULE_PARM_DESC(irq, "IRQ for the Arc board");
+
+module_init(arcfb_init);
+module_exit(arcfb_exit);
+
+MODULE_DESCRIPTION("fbdev driver for Arc monochrome LCD board");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
+
index ab98f225fe3ee5246d62dc79bf5228099d81baa6..95e72550d43ff4b373ec3615b57b9399ce574a76 100644 (file)
@@ -423,9 +423,6 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
        pmu_register_sleep_notifier(&chips_sleep_notifier);
 #endif /* CONFIG_PMAC_PBOOK */
 
-       /* Clear the entire framebuffer */
-       memset(p->screen_base, 0, 0x100000);
-
        pci_set_drvdata(dp, p);
        return 0;
 }
index ccf55811d24fd058ecc3a958cf9f8c54ee58621b..e4b91a4b936c9c9125d42eb799973fab6b7aec83 100644 (file)
@@ -153,6 +153,15 @@ config FONT_6x11
          Small console font with Macintosh-style high-half glyphs.  Some Mac
          framebuffer drivers don't support this one at all.
 
+config FONT_7x14
+       bool "console 7x14 font (not supported by all drivers)" if FONTS
+       depends on FRAMEBUFFER_CONSOLE
+       default y if !SPARC32 && !SPARC64 && !FONTS
+       help
+         Console font with characters just a bit smaller than the default.
+         If the standard 8x16 font is a little too big for you, say Y.
+         Otherwise, say N.
+
 config FONT_PEARL_8x8
        bool "Pearl (old m68k) console 8x8 font" if FONTS
        depends on FRAMEBUFFER_CONSOLE
@@ -187,5 +196,13 @@ config FONT_SUN12x22
          big letters (like the letters used in the SPARC PROM). If the
          standard font is unreadable for you, say Y, otherwise say N.
 
+config FONT_10x18
+       bool "console 10x18 font (not supported by all drivers)"
+       depends on FONTS
+       help
+         This is a high resolution console font for machines with very
+         big letters. It fits between the sun 12x22 and the normal 8x16 font.
+         If other fonts are too big or too small for you, say Y, otherwise say N.
+
 endmenu
 
index 33516447f9f2eb4687e82662cc9bb18e93651b2b..b562f6bb9d316d64addc4acc4934e83257bda83f 100644 (file)
@@ -10,6 +10,8 @@ font-objs-$(CONFIG_FONT_SUN12x22)  += font_sun12x22.o
 font-objs-$(CONFIG_FONT_8x8)       += font_8x8.o
 font-objs-$(CONFIG_FONT_8x16)      += font_8x16.o
 font-objs-$(CONFIG_FONT_6x11)      += font_6x11.o
+font-objs-$(CONFIG_FONT_7x14)      += font_7x14.o
+font-objs-$(CONFIG_FONT_10x18)     += font_10x18.o
 font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
 font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
 font-objs-$(CONFIG_FONT_MINI_4x6)  += font_mini_4x6.o
index b28a4b0e395e6ecb62efbf197bc375ae745d25b0..3c731577fed628796423193ca9d99c7be4967671 100644 (file)
@@ -107,13 +107,6 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
                      const unsigned short *s, int count, int yy, int xx,
                      int fg, int bg)
 {
-       void (*move_unaligned)(struct fb_info *info, struct fb_pixmap *buf,
-                              u8 *dst, u32 d_pitch, u8 *src, u32 idx,
-                              u32 height, u32 shift_high, u32 shift_low,
-                              u32 mod);
-       void (*move_aligned)(struct fb_info *info, struct fb_pixmap *buf,
-                            u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-                            u32 height);
        unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
        unsigned int width = (vc->vc_font.width + 7) >> 3;
        unsigned int cellsize = vc->vc_font.height * width;
@@ -141,13 +134,6 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
        image.height = vc->vc_font.height;
        image.depth = 1;
 
-       if (info->pixmap.outbuf && info->pixmap.inbuf) {
-               move_aligned = fb_iomove_buf_aligned;
-               move_unaligned = fb_iomove_buf_unaligned;
-       } else {
-               move_aligned = fb_sysmove_buf_aligned;
-               move_unaligned = fb_sysmove_buf_unaligned;
-       }
        while (count) {
                if (count > maxcnt)
                        cnt = k = maxcnt;
@@ -171,9 +157,9 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
                                        src = buf;
                                }
 
-                               move_unaligned(info, &info->pixmap, dst, pitch,
-                                              src, idx, image.height,
-                                              shift_high, shift_low, mod);
+                               fb_pad_unaligned_buffer(dst, pitch, src, idx,
+                                               image.height, shift_high,
+                                               shift_low, mod);
                                shift_low += mod;
                                dst += (shift_low >= 8) ? width : width - 1;
                                shift_low &= 7;
@@ -189,8 +175,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
                                        src = buf;
                                }
 
-                               move_aligned(info, &info->pixmap, dst, pitch,
-                                            src, idx, image.height);
+                               fb_pad_aligned_buffer(dst, pitch, src, idx, image.height);
                                dst += width;
                        }
                }
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
new file mode 100644 (file)
index 0000000..ff0af96
--- /dev/null
@@ -0,0 +1,5146 @@
+/********************************
+ * adapted from font_sun12x22.c *
+ * by Jurriaan Kalkman 06-2005  *
+ ********************************/
+
+#include <linux/font.h>
+
+#define FONTDATAMAX 9216
+
+static unsigned char fontdata_10x18[FONTDATAMAX] = {
+
+       /* 0 0x00 '^@' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 1 0x01 '^A' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3f, 0x80, /* 0011111110 */
+       0x40, 0x40, /* 0100000001 */
+       0x5b, 0x40, /* 0101101101 */
+       0x40, 0x40, /* 0100000001 */
+       0x44, 0x40, /* 0100010001 */
+       0x44, 0x40, /* 0100010001 */
+       0x51, 0x40, /* 0101000101 */
+       0x4e, 0x40, /* 0100111001 */
+       0x40, 0x40, /* 0100000001 */
+       0x3f, 0x80, /* 0011111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 2 0x02 '^B' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3f, 0x80, /* 0011111110 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x64, 0xc0, /* 0110010011 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x7b, 0xc0, /* 0111101111 */
+       0x7b, 0xc0, /* 0111101111 */
+       0x6e, 0xc0, /* 0110111011 */
+       0x71, 0xc0, /* 0111000111 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x3f, 0x80, /* 0011111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 3 0x03 '^C' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x11, 0x00, /* 0001000100 */
+       0x3b, 0x80, /* 0011101110 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x3f, 0x80, /* 0011111110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x04, 0x00, /* 0000010000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 4 0x04 '^D' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x3f, 0x80, /* 0011111110 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x04, 0x00, /* 0000010000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 5 0x05 '^E' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x31, 0x80, /* 0011000110 */
+       0x7b, 0xc0, /* 0111101111 */
+       0x35, 0x80, /* 0011010110 */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 6 0x06 '^F' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x3f, 0x80, /* 0011111110 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x35, 0x80, /* 0011010110 */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 7 0x07 '^G' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 8 0x08 '^H' */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xf3, 0xc0, /* 1111001111 */
+       0xe1, 0xc0, /* 1110000111 */
+       0xe1, 0xc0, /* 1110000111 */
+       0xc0, 0xc0, /* 1100000011 */
+       0xc0, 0xc0, /* 1100000011 */
+       0xe1, 0xc0, /* 1110000111 */
+       0xe1, 0xc0, /* 1110000111 */
+       0xf3, 0xc0, /* 1111001111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+
+       /* 9 0x09 '^I' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x12, 0x00, /* 0001001000 */
+       0x12, 0x00, /* 0001001000 */
+       0x21, 0x00, /* 0010000100 */
+       0x21, 0x00, /* 0010000100 */
+       0x12, 0x00, /* 0001001000 */
+       0x12, 0x00, /* 0001001000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 10 0x0a '^J' */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xf3, 0xc0, /* 1111001111 */
+       0xed, 0xc0, /* 1110110111 */
+       0xed, 0xc0, /* 1110110111 */
+       0xde, 0xc0, /* 1101111011 */
+       0xde, 0xc0, /* 1101111011 */
+       0xed, 0xc0, /* 1110110111 */
+       0xed, 0xc0, /* 1110110111 */
+       0xf3, 0xc0, /* 1111001111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+
+       /* 11 0x0b '^K' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x03, 0xc0, /* 0000001111 */
+       0x06, 0xc0, /* 0000011011 */
+       0x0c, 0xc0, /* 0000110011 */
+       0x3c, 0x00, /* 0011110000 */
+       0x66, 0x00, /* 0110011000 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc3, 0x00, /* 1100001100 */
+       0x66, 0x00, /* 0110011000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 12 0x0c '^L' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x33, 0x00, /* 0011001100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 13 0x0d '^M' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0f, 0x80, /* 0000111110 */
+       0x08, 0x80, /* 0000100010 */
+       0x0f, 0x80, /* 0000111110 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x38, 0x00, /* 0011100000 */
+       0x78, 0x00, /* 0111100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 14 0x0e '^N' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x80, /* 0001111110 */
+       0x10, 0x80, /* 0001000010 */
+       0x1f, 0x80, /* 0001111110 */
+       0x10, 0x80, /* 0001000010 */
+       0x10, 0x80, /* 0001000010 */
+       0x10, 0x80, /* 0001000010 */
+       0x10, 0x80, /* 0001000010 */
+       0x13, 0x80, /* 0001001110 */
+       0x17, 0x80, /* 0001011110 */
+       0x73, 0x00, /* 0111001100 */
+       0xf0, 0x00, /* 1111000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 15 0x0f '^O' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x04, 0x00, /* 0000010000 */
+       0x24, 0x80, /* 0010010010 */
+       0x15, 0x00, /* 0001010100 */
+       0x55, 0x40, /* 0101010101 */
+       0x3f, 0x80, /* 0011111110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x3f, 0x80, /* 0011111110 */
+       0x55, 0x40, /* 0101010101 */
+       0x15, 0x00, /* 0001010100 */
+       0x24, 0x80, /* 0010010010 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 16 0x10 '^P' */
+       0x00, 0x80, /* 0000000010 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x80, /* 0000001110 */
+       0x07, 0x80, /* 0000011110 */
+       0x0f, 0x80, /* 0000111110 */
+       0x1f, 0x80, /* 0001111110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0xff, 0x80, /* 1111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x1f, 0x80, /* 0001111110 */
+       0x0f, 0x80, /* 0000111110 */
+       0x07, 0x80, /* 0000011110 */
+       0x03, 0x80, /* 0000001110 */
+       0x01, 0x80, /* 0000000110 */
+       0x00, 0x80, /* 0000000010 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 17 0x11 '^Q' */
+       0x40, 0x00, /* 0100000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x70, 0x00, /* 0111000000 */
+       0x78, 0x00, /* 0111100000 */
+       0x7c, 0x00, /* 0111110000 */
+       0x7e, 0x00, /* 0111111000 */
+       0x7f, 0x00, /* 0111111100 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x00, /* 0111111100 */
+       0x7e, 0x00, /* 0111111000 */
+       0x7c, 0x00, /* 0111110000 */
+       0x78, 0x00, /* 0111100000 */
+       0x70, 0x00, /* 0111000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x40, 0x00, /* 0100000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 18 0x12 '^R' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x7f, 0x80, /* 0111111110 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 19 0x13 '^S' */
+       0x00, 0x00, /* 0000000000 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 20 0x14 '^T' */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x39, 0x80, /* 0011100110 */
+       0x79, 0x80, /* 0111100110 */
+       0x79, 0x80, /* 0111100110 */
+       0x79, 0x80, /* 0111100110 */
+       0x39, 0x80, /* 0011100110 */
+       0x19, 0x80, /* 0001100110 */
+       0x19, 0x80, /* 0001100110 */
+       0x19, 0x80, /* 0001100110 */
+       0x19, 0x80, /* 0001100110 */
+       0x19, 0x80, /* 0001100110 */
+       0x19, 0x80, /* 0001100110 */
+       0x39, 0xc0, /* 0011100111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 21 0x15 '^U' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 22 0x16 '^V' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 23 0x17 '^W' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x7f, 0x80, /* 0111111110 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 24 0x18 '^X' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x7f, 0x80, /* 0111111110 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 25 0x19 '^Y' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 26 0x1a '^Z' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x04, 0x00, /* 0000010000 */
+       0x06, 0x00, /* 0000011000 */
+       0x07, 0x00, /* 0000011100 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x07, 0x00, /* 0000011100 */
+       0x06, 0x00, /* 0000011000 */
+       0x04, 0x00, /* 0000010000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 27 0x1b '^[' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x08, 0x00, /* 0000100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x38, 0x00, /* 0011100000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x38, 0x00, /* 0011100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 28 0x1c '^\' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 29 0x1d '^]' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x12, 0x00, /* 0001001000 */
+       0x33, 0x00, /* 0011001100 */
+       0x73, 0x80, /* 0111001110 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x73, 0x80, /* 0111001110 */
+       0x33, 0x00, /* 0011001100 */
+       0x12, 0x00, /* 0001001000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 30 0x1e '^^' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x04, 0x00, /* 0000010000 */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x3f, 0x80, /* 0011111110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 31 0x1f '^_' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x3f, 0x80, /* 0011111110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x04, 0x00, /* 0000010000 */
+       0x04, 0x00, /* 0000010000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 32 0x20 ' ' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 33 0x21 '!' */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 34 0x22 '"' */
+       0x00, 0x00, /* 0000000000 */
+       0x63, 0x00, /* 0110001100 */
+       0xf7, 0x80, /* 1111011110 */
+       0xf7, 0x80, /* 1111011110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x63, 0x00, /* 0110001100 */
+       0x42, 0x00, /* 0100001000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 35 0x23 '#' */
+       0x00, 0x00, /* 0000000000 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 36 0x24 '$' */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x6f, 0x80, /* 0110111110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6c, 0x80, /* 0110110010 */
+       0x3c, 0x00, /* 0011110000 */
+       0x0f, 0x00, /* 0000111100 */
+       0x0d, 0x80, /* 0000110110 */
+       0x4d, 0x80, /* 0100110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x7f, 0x00, /* 0111111100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 37 0x25 '%' */
+       0x00, 0x00, /* 0000000000 */
+       0x31, 0x80, /* 0011000110 */
+       0x7b, 0x00, /* 0111101100 */
+       0x7b, 0x00, /* 0111101100 */
+       0x36, 0x00, /* 0011011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x37, 0x80, /* 0011011110 */
+       0x37, 0x80, /* 0011011110 */
+       0x63, 0x00, /* 0110001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 38 0x26 '&' */
+       0x00, 0x00, /* 0000000000 */
+       0x07, 0x00, /* 0000011100 */
+       0x0f, 0x80, /* 0000111110 */
+       0x19, 0x80, /* 0001100110 */
+       0x19, 0x80, /* 0001100110 */
+       0x0f, 0x80, /* 0000111110 */
+       0x1e, 0x00, /* 0001111000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x76, 0x00, /* 0111011000 */
+       0x66, 0x40, /* 0110011001 */
+       0x63, 0xc0, /* 0110001111 */
+       0x63, 0x80, /* 0110001110 */
+       0x63, 0x00, /* 0110001100 */
+       0x3f, 0x80, /* 0011111110 */
+       0x1c, 0xc0, /* 0001110011 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 39 0x27 ''' */
+       0x00, 0x00, /* 0000000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x78, 0x00, /* 0111100000 */
+       0x78, 0x00, /* 0111100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x20, 0x00, /* 0010000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 40 0x28 '(' */
+       0x00, 0x00, /* 0000000000 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x03, 0x00, /* 0000001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 41 0x29 ')' */
+       0x00, 0x00, /* 0000000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 42 0x2a '*' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x4c, 0x80, /* 0100110010 */
+       0x6d, 0x80, /* 0110110110 */
+       0x3f, 0x00, /* 0011111100 */
+       0x7f, 0x80, /* 0111111110 */
+       0x3f, 0x00, /* 0011111100 */
+       0x6d, 0x80, /* 0110110110 */
+       0x4c, 0x80, /* 0100110010 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 43 0x2b '+' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 44 0x2c ',' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x78, 0x00, /* 0111100000 */
+       0x78, 0x00, /* 0111100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x40, 0x00, /* 0100000000 */
+
+       /* 45 0x2d '-' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 46 0x2e '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 47 0x2f '/' */
+       0x00, 0x00, /* 0000000000 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 48 0x30 '0' */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x23, 0x00, /* 0010001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x63, 0x80, /* 0110001110 */
+       0x65, 0x80, /* 0110010110 */
+       0x65, 0x80, /* 0110010110 */
+       0x69, 0x80, /* 0110100110 */
+       0x69, 0x80, /* 0110100110 */
+       0x71, 0x80, /* 0111000110 */
+       0x61, 0x00, /* 0110000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 49 0x31 '1' */
+       0x00, 0x00, /* 0000000000 */
+       0x04, 0x00, /* 0000010000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 50 0x32 '2' */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x63, 0x80, /* 0110001110 */
+       0x41, 0x80, /* 0100000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x80, /* 0011000010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 51 0x33 '3' */
+       0x00, 0x00, /* 0000000000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x47, 0x00, /* 0100011100 */
+       0x03, 0x00, /* 0000001100 */
+       0x07, 0x00, /* 0000011100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x07, 0x00, /* 0000011100 */
+       0x03, 0x00, /* 0000001100 */
+       0x01, 0x80, /* 0000000110 */
+       0x41, 0x80, /* 0100000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 52 0x34 '4' */
+       0x00, 0x00, /* 0000000000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x66, 0x00, /* 0110011000 */
+       0x66, 0x00, /* 0110011000 */
+       0xc6, 0x00, /* 1100011000 */
+       0xc6, 0x00, /* 1100011000 */
+       0xff, 0x80, /* 1111111110 */
+       0xff, 0x80, /* 1111111110 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 53 0x35 '5' */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x7e, 0x00, /* 0111111000 */
+       0x67, 0x00, /* 0110011100 */
+       0x03, 0x80, /* 0000001110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x41, 0x80, /* 0100000110 */
+       0x63, 0x00, /* 0110001100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 54 0x36 '6' */
+       0x00, 0x00, /* 0000000000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x6e, 0x00, /* 0110111000 */
+       0x7f, 0x00, /* 0111111100 */
+       0x73, 0x80, /* 0111001110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x71, 0x00, /* 0111000100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 55 0x37 '7' */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x80, /* 0001111110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x61, 0x80, /* 0110000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 56 0x38 '8' */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x23, 0x00, /* 0010001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x31, 0x00, /* 0011000100 */
+       0x1a, 0x00, /* 0001101000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x16, 0x00, /* 0001011000 */
+       0x23, 0x00, /* 0010001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x31, 0x00, /* 0011000100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 57 0x39 '9' */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x17, 0x00, /* 0001011100 */
+       0x23, 0x80, /* 0010001110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x3d, 0x80, /* 0011110110 */
+       0x19, 0x80, /* 0001100110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 58 0x3a ':' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 59 0x3b ';' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x20, 0x00, /* 0010000000 */
+
+       /* 60 0x3c '<' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x03, 0x00, /* 0000001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 61 0x3d '=' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 62 0x3e '>' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x03, 0x00, /* 0000001100 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 63 0x3f '?' */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x3b, 0x80, /* 0011101110 */
+       0x21, 0x80, /* 0010000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 64 0x40 '@' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x65, 0x80, /* 0110010110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6f, 0x80, /* 0110111110 */
+       0x60, 0x00, /* 0110000000 */
+       0x31, 0x80, /* 0011000110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x0f, 0x00, /* 0000111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 65 0x41 'A' */
+       0x00, 0x00, /* 0000000000 */
+       0x04, 0x00, /* 0000010000 */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x19, 0x80, /* 0001100110 */
+       0x31, 0x80, /* 0011000110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x31, 0x80, /* 0011000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x60, 0xc0, /* 0110000011 */
+       0x60, 0xc0, /* 0110000011 */
+       0xf1, 0xc0, /* 1111000111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 66 0x42 'B' */
+       0x00, 0x00, /* 0000000000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x62, 0x00, /* 0110001000 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x66, 0x00, /* 0110011000 */
+       0x7e, 0x00, /* 0111111000 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x63, 0x00, /* 0110001100 */
+       0xfe, 0x00, /* 1111111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 67 0x43 'C' */
+       0x00, 0x00, /* 0000000000 */
+       0x0f, 0x00, /* 0000111100 */
+       0x11, 0x80, /* 0001000110 */
+       0x20, 0x80, /* 0010000010 */
+       0x20, 0x00, /* 0010000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x20, 0x00, /* 0010000000 */
+       0x30, 0x80, /* 0011000010 */
+       0x19, 0x00, /* 0001100100 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 68 0x44 'D' */
+       0x00, 0x00, /* 0000000000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x67, 0x00, /* 0110011100 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x00, /* 0110000100 */
+       0x66, 0x00, /* 0110011000 */
+       0xf8, 0x00, /* 1111100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 69 0x45 'E' */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x31, 0x00, /* 0011000100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x31, 0x00, /* 0011000100 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x80, /* 0011000010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 70 0x46 'F' */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x31, 0x00, /* 0011000100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x31, 0x00, /* 0011000100 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x78, 0x00, /* 0111100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 71 0x47 'G' */
+       0x00, 0x00, /* 0000000000 */
+       0x0f, 0x00, /* 0000111100 */
+       0x11, 0x80, /* 0001000110 */
+       0x20, 0x80, /* 0010000010 */
+       0x20, 0x00, /* 0010000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x67, 0xc0, /* 0110011111 */
+       0x61, 0x80, /* 0110000110 */
+       0x21, 0x80, /* 0010000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x19, 0x80, /* 0001100110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 72 0x48 'H' */
+       0x00, 0x00, /* 0000000000 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 73 0x49 'I' */
+       0x00, 0x00, /* 0000000000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 74 0x4a 'J' */
+       0x00, 0x00, /* 0000000000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x08, 0x00, /* 0000100000 */
+       0x70, 0x00, /* 0111000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 75 0x4b 'K' */
+       0x00, 0x00, /* 0000000000 */
+       0xf1, 0x80, /* 1111000110 */
+       0x63, 0x00, /* 0110001100 */
+       0x66, 0x00, /* 0110011000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x78, 0x00, /* 0111100000 */
+       0x70, 0x00, /* 0111000000 */
+       0x70, 0x00, /* 0111000000 */
+       0x78, 0x00, /* 0111100000 */
+       0x78, 0x00, /* 0111100000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x66, 0x00, /* 0110011000 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x80, /* 0110000110 */
+       0xf0, 0xc0, /* 1111000011 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 76 0x4c 'L' */
+       0x00, 0x00, /* 0000000000 */
+       0x78, 0x00, /* 0111100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x80, /* 0011000010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 77 0x4d 'M' */
+       0x00, 0x00, /* 0000000000 */
+       0xe0, 0xc0, /* 1110000011 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x73, 0x80, /* 0111001110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 78 0x4e 'N' */
+       0x00, 0x00, /* 0000000000 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x71, 0x80, /* 0111000110 */
+       0x79, 0x80, /* 0111100110 */
+       0x79, 0x80, /* 0111100110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x67, 0x80, /* 0110011110 */
+       0x67, 0x80, /* 0110011110 */
+       0x63, 0x80, /* 0110001110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 79 0x4f 'O' */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x17, 0x00, /* 0001011100 */
+       0x23, 0x00, /* 0010001100 */
+       0x21, 0x80, /* 0010000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x21, 0x00, /* 0010000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x1a, 0x00, /* 0001101000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 80 0x50 'P' */
+       0x00, 0x00, /* 0000000000 */
+       0xfe, 0x00, /* 1111111000 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x63, 0x00, /* 0110001100 */
+       0x7e, 0x00, /* 0111111000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0xf0, 0x00, /* 1111000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 81 0x51 'Q' */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x13, 0x00, /* 0001001100 */
+       0x23, 0x00, /* 0010001100 */
+       0x21, 0x80, /* 0010000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x3b, 0x00, /* 0011101100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x26, 0x00, /* 0010011000 */
+       0x03, 0x80, /* 0000001110 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 82 0x52 'R' */
+       0x00, 0x00, /* 0000000000 */
+       0xfe, 0x00, /* 1111111000 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x00, /* 0110000100 */
+       0x7e, 0x00, /* 0111111000 */
+       0x78, 0x00, /* 0111100000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x6e, 0x00, /* 0110111000 */
+       0x67, 0x00, /* 0110011100 */
+       0x63, 0x80, /* 0110001110 */
+       0x61, 0xc0, /* 0110000111 */
+       0xf0, 0xc0, /* 1111000011 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 83 0x53 'S' */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x03, 0x00, /* 0000001100 */
+       0x01, 0x80, /* 0000000110 */
+       0x41, 0x80, /* 0100000110 */
+       0x63, 0x00, /* 0110001100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 84 0x54 'T' */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x4c, 0x80, /* 0100110010 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 85 0x55 'U' */
+       0x00, 0x00, /* 0000000000 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x00, /* 0111001100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 86 0x56 'V' */
+       0x00, 0x00, /* 0000000000 */
+       0xe1, 0xc0, /* 1110000111 */
+       0xc0, 0xc0, /* 1100000011 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x12, 0x00, /* 0001001000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 87 0x57 'W' */
+       0x00, 0x00, /* 0000000000 */
+       0xe1, 0xc0, /* 1110000111 */
+       0xc0, 0xc0, /* 1100000011 */
+       0xc0, 0xc0, /* 1100000011 */
+       0xc0, 0xc0, /* 1100000011 */
+       0xe0, 0xc0, /* 1110000011 */
+       0x61, 0x80, /* 0110000110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x77, 0x00, /* 0111011100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 88 0x58 'X' */
+       0x00, 0x00, /* 0000000000 */
+       0xf7, 0x80, /* 1111011110 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0xf7, 0x80, /* 1111011110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 89 0x59 'Y' */
+       0x00, 0x00, /* 0000000000 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 90 0x5a 'Z' */
+       0x00, 0x00, /* 0000000000 */
+       0x3f, 0x80, /* 0011111110 */
+       0x21, 0x80, /* 0010000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x80, /* 0011000010 */
+       0x3f, 0x80, /* 0011111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 91 0x5b '[' */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x1f, 0x00, /* 0001111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 92 0x5c '\' */
+       0x00, 0x00, /* 0000000000 */
+       0xc0, 0x00, /* 1100000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x00, 0xc0, /* 0000000011 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 93 0x5d ']' */
+       0x00, 0x00, /* 0000000000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 94 0x5e '^' */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 95 0x5f '_' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 96 0x60 '`' */
+       0x04, 0x00, /* 0000010000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 97 0x61 'a' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x21, 0x80, /* 0010000110 */
+       0x07, 0x80, /* 0000011110 */
+       0x39, 0x80, /* 0011100110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x3d, 0xc0, /* 0011110111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 98 0x62 'b' */
+       0x20, 0x00, /* 0010000000 */
+       0x60, 0x00, /* 0110000000 */
+       0xe0, 0x00, /* 1110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x66, 0x00, /* 0110011000 */
+       0x6f, 0x00, /* 0110111100 */
+       0x73, 0x80, /* 0111001110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x71, 0x80, /* 0111000110 */
+       0x7b, 0x00, /* 0111101100 */
+       0x4e, 0x00, /* 0100111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 99 0x63 'c' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x37, 0x00, /* 0011011100 */
+       0x23, 0x00, /* 0010001100 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x71, 0x00, /* 0111000100 */
+       0x33, 0x00, /* 0011001100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 100 0x64 'd' */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x80, /* 0000001110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x0d, 0x80, /* 0000110110 */
+       0x37, 0x80, /* 0011011110 */
+       0x23, 0x80, /* 0010001110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x35, 0x80, /* 0011010110 */
+       0x19, 0xc0, /* 0001100111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 101 0x65 'e' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x19, 0x80, /* 0001100110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 102 0x66 'f' */
+       0x07, 0x00, /* 0000011100 */
+       0x09, 0x80, /* 0000100110 */
+       0x09, 0x80, /* 0000100110 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x7f, 0x00, /* 0111111100 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 103 0x67 'g' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1c, 0x80, /* 0001110010 */
+       0x37, 0x80, /* 0011011110 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x36, 0x00, /* 0011011000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x60, 0x00, /* 0110000000 */
+       0x7f, 0x00, /* 0111111100 */
+       0x3f, 0x80, /* 0011111110 */
+       0x21, 0x80, /* 0010000110 */
+       0x40, 0x80, /* 0100000010 */
+       0x7f, 0x00, /* 0111111100 */
+       0x3e, 0x00, /* 0011111000 */
+
+       /* 104 0x68 'h' */
+       0x10, 0x00, /* 0001000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x70, 0x00, /* 0111000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x37, 0x00, /* 0011011100 */
+       0x3b, 0x80, /* 0011101110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x7b, 0xc0, /* 0111101111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 105 0x69 'i' */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 106 0x6a 'j' */
+       0x00, 0x00, /* 0000000000 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x07, 0x80, /* 0000011110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x41, 0x80, /* 0100000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x71, 0x80, /* 0111000110 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1c, 0x00, /* 0001110000 */
+
+       /* 107 0x6b 'k' */
+       0x60, 0x00, /* 0110000000 */
+       0xe0, 0x00, /* 1110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x63, 0x80, /* 0110001110 */
+       0x66, 0x00, /* 0110011000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x78, 0x00, /* 0111100000 */
+       0x70, 0x00, /* 0111000000 */
+       0x78, 0x00, /* 0111100000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x6e, 0x00, /* 0110111000 */
+       0x67, 0x00, /* 0110011100 */
+       0xf3, 0x80, /* 1111001110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 108 0x6c 'l' */
+       0x3c, 0x00, /* 0011110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 109 0x6d 'm' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xdb, 0x80, /* 1101101110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0xed, 0xc0, /* 1110110111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 110 0x6e 'n' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x6f, 0x00, /* 0110111100 */
+       0x7b, 0x80, /* 0111101110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x7b, 0xc0, /* 0111101111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 111 0x6f 'o' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x66, 0x00, /* 0110011000 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xe1, 0x80, /* 1110000110 */
+       0x73, 0x00, /* 0111001100 */
+       0x3c, 0x00, /* 0011110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 112 0x70 'p' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xde, 0x00, /* 1101111000 */
+       0x76, 0x00, /* 0111011000 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x71, 0x80, /* 0111000110 */
+       0x7b, 0x00, /* 0111101100 */
+       0x7e, 0x00, /* 0111111000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0xf0, 0x00, /* 1111000000 */
+
+       /* 113 0x71 'q' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0xc0, /* 0000111011 */
+       0x1b, 0x80, /* 0001101110 */
+       0x33, 0x80, /* 0011001110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x71, 0x80, /* 0111000110 */
+       0x3b, 0x80, /* 0011101110 */
+       0x1f, 0x80, /* 0001111110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0xc0, /* 0000001111 */
+
+       /* 114 0x72 'r' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x73, 0x00, /* 0111001100 */
+       0x35, 0x80, /* 0011010110 */
+       0x39, 0x80, /* 0011100110 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x78, 0x00, /* 0111100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 115 0x73 's' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x00, /* 0110000100 */
+       0x70, 0x00, /* 0111000000 */
+       0x38, 0x00, /* 0011100000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x07, 0x00, /* 0000011100 */
+       0x43, 0x00, /* 0100001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x7e, 0x00, /* 0111111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 116 0x74 't' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x1c, 0x80, /* 0001110010 */
+       0x0f, 0x00, /* 0000111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 117 0x75 'u' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xf7, 0x80, /* 1111011110 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x77, 0x00, /* 0111011100 */
+       0x3d, 0x80, /* 0011110110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 118 0x76 'v' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xf1, 0xc0, /* 1111000111 */
+       0x60, 0xc0, /* 0110000011 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x19, 0x80, /* 0001100110 */
+       0x1b, 0x00, /* 0001101100 */
+       0x0f, 0x00, /* 0000111100 */
+       0x0f, 0x00, /* 0000111100 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 119 0x77 'w' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xe3, 0xc0, /* 1110001111 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0x6b, 0x00, /* 0110101100 */
+       0x6b, 0x00, /* 0110101100 */
+       0x7e, 0x00, /* 0111111000 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 120 0x78 'x' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xf7, 0x80, /* 1111011110 */
+       0x63, 0x00, /* 0110001100 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x36, 0x00, /* 0011011000 */
+       0x66, 0x00, /* 0110011000 */
+       0x63, 0x00, /* 0110001100 */
+       0xf7, 0x80, /* 1111011110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 121 0x79 'y' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x61, 0x80, /* 0110000110 */
+       0x33, 0x00, /* 0011001100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x78, 0x00, /* 0111100000 */
+       0x70, 0x00, /* 0111000000 */
+
+       /* 122 0x7a 'z' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x61, 0x80, /* 0110000110 */
+       0x43, 0x00, /* 0100001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x60, 0x80, /* 0110000010 */
+       0x61, 0x80, /* 0110000110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 123 0x7b '{' */
+       0x07, 0x00, /* 0000011100 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x70, 0x00, /* 0111000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x07, 0x00, /* 0000011100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 124 0x7c '|' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 125 0x7d '}' */
+       0x38, 0x00, /* 0011100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x03, 0x80, /* 0000001110 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x38, 0x00, /* 0011100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 126 0x7e '~' */
+       0x00, 0x00, /* 0000000000 */
+       0x18, 0x80, /* 0001100010 */
+       0x3d, 0x80, /* 0011110110 */
+       0x6f, 0x00, /* 0110111100 */
+       0x46, 0x00, /* 0100011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 127 0x7f '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x12, 0x00, /* 0001001000 */
+       0x21, 0x00, /* 0010000100 */
+       0x40, 0x80, /* 0100000010 */
+       0x40, 0x80, /* 0100000010 */
+       0x40, 0x80, /* 0100000010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 128 0x80 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x21, 0x80, /* 0010000110 */
+       0x40, 0x80, /* 0100000010 */
+       0x40, 0x00, /* 0100000000 */
+       0x40, 0x00, /* 0100000000 */
+       0x40, 0x00, /* 0100000000 */
+       0x40, 0x00, /* 0100000000 */
+       0x40, 0x00, /* 0100000000 */
+       0x40, 0x00, /* 0100000000 */
+       0x60, 0x80, /* 0110000010 */
+       0x31, 0x00, /* 0011000100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x08, 0x00, /* 0000100000 */
+       0x04, 0x00, /* 0000010000 */
+       0x02, 0x00, /* 0000001000 */
+       0x02, 0x00, /* 0000001000 */
+       0x1c, 0x00, /* 0001110000 */
+
+       /* 129 0x81 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7b, 0x80, /* 0111101110 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x3b, 0x00, /* 0011101100 */
+       0x1c, 0x80, /* 0001110010 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 130 0x82 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x01, 0x00, /* 0000000100 */
+       0x02, 0x00, /* 0000001000 */
+       0x04, 0x00, /* 0000010000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x19, 0x80, /* 0001100110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 131 0x83 '.' */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x31, 0x80, /* 0011000110 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x21, 0x80, /* 0010000110 */
+       0x07, 0x80, /* 0000011110 */
+       0x39, 0x80, /* 0011100110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x3d, 0xc0, /* 0011110111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 132 0x84 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x21, 0x80, /* 0010000110 */
+       0x07, 0x80, /* 0000011110 */
+       0x39, 0x80, /* 0011100110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x3d, 0xc0, /* 0011110111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 133 0x85 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x21, 0x80, /* 0010000110 */
+       0x07, 0x80, /* 0000011110 */
+       0x39, 0x80, /* 0011100110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x3d, 0xc0, /* 0011110111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 134 0x86 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x21, 0x80, /* 0010000110 */
+       0x07, 0x80, /* 0000011110 */
+       0x39, 0x80, /* 0011100110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x3d, 0xc0, /* 0011110111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 135 0x87 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x20, 0x80, /* 0010000010 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x70, 0x80, /* 0111000010 */
+       0x30, 0x80, /* 0011000010 */
+       0x1f, 0x00, /* 0001111100 */
+       0x04, 0x00, /* 0000010000 */
+       0x02, 0x00, /* 0000001000 */
+       0x01, 0x00, /* 0000000100 */
+       0x0e, 0x00, /* 0000111000 */
+
+       /* 136 0x88 '.' */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x31, 0x80, /* 0011000110 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x19, 0x80, /* 0001100110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 137 0x89 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x19, 0x80, /* 0001100110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 138 0x8a '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x19, 0x80, /* 0001100110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 139 0x8b '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x36, 0x00, /* 0011011000 */
+       0x36, 0x00, /* 0011011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 140 0x8c '.' */
+       0x08, 0x00, /* 0000100000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x36, 0x00, /* 0011011000 */
+       0x63, 0x00, /* 0110001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 141 0x8d '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 142 0x8e '.' */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x04, 0x00, /* 0000010000 */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x19, 0x00, /* 0001100100 */
+       0x19, 0x00, /* 0001100100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 143 0x8f '.' */
+       0x04, 0x00, /* 0000010000 */
+       0x0a, 0x00, /* 0000101000 */
+       0x0a, 0x00, /* 0000101000 */
+       0x04, 0x00, /* 0000010000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x19, 0x00, /* 0001100100 */
+       0x19, 0x00, /* 0001100100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 144 0x90 '.' */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x00, /* 0011000000 */
+       0x31, 0x00, /* 0011000100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x31, 0x00, /* 0011000100 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x80, /* 0011000010 */
+       0x30, 0x80, /* 0011000010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 145 0x91 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3b, 0x80, /* 0011101110 */
+       0x6c, 0xc0, /* 0110110011 */
+       0x4c, 0xc0, /* 0100110011 */
+       0x0c, 0xc0, /* 0000110011 */
+       0x3f, 0xc0, /* 0011111111 */
+       0x6c, 0x00, /* 0110110000 */
+       0xcc, 0x00, /* 1100110000 */
+       0xcc, 0x00, /* 1100110000 */
+       0xee, 0xc0, /* 1110111011 */
+       0x7b, 0x80, /* 0111101110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 146 0x92 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x07, 0xc0, /* 0000011111 */
+       0x0e, 0x40, /* 0000111001 */
+       0x0e, 0x40, /* 0000111001 */
+       0x0e, 0x00, /* 0000111000 */
+       0x16, 0x00, /* 0001011000 */
+       0x16, 0x80, /* 0001011010 */
+       0x17, 0x80, /* 0001011110 */
+       0x16, 0x80, /* 0001011010 */
+       0x3e, 0x00, /* 0011111000 */
+       0x26, 0x00, /* 0010011000 */
+       0x26, 0x00, /* 0010011000 */
+       0x46, 0x40, /* 0100011001 */
+       0x46, 0x40, /* 0100011001 */
+       0xef, 0xc0, /* 1110111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 147 0x93 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x08, 0x00, /* 0000100000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x36, 0x00, /* 0011011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x66, 0x00, /* 0110011000 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xe1, 0x80, /* 1110000110 */
+       0x73, 0x00, /* 0111001100 */
+       0x3c, 0x00, /* 0011110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 148 0x94 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x66, 0x00, /* 0110011000 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xe1, 0x80, /* 1110000110 */
+       0x73, 0x00, /* 0111001100 */
+       0x3c, 0x00, /* 0011110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 149 0x95 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x06, 0x00, /* 0000011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x66, 0x00, /* 0110011000 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xe1, 0x80, /* 1110000110 */
+       0x73, 0x00, /* 0111001100 */
+       0x3c, 0x00, /* 0011110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 150 0x96 '.' */
+       0x08, 0x00, /* 0000100000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x36, 0x00, /* 0011011000 */
+       0x63, 0x00, /* 0110001100 */
+       0x00, 0x00, /* 0000000000 */
+       0xf7, 0x80, /* 1111011110 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x77, 0x00, /* 0111011100 */
+       0x3d, 0x80, /* 0011110110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 151 0x97 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0xf7, 0x80, /* 1111011110 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x77, 0x00, /* 0111011100 */
+       0x3d, 0x80, /* 0011110110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 152 0x98 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x61, 0x80, /* 0110000110 */
+       0x33, 0x00, /* 0011001100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x78, 0x00, /* 0111100000 */
+       0x70, 0x00, /* 0111000000 */
+
+       /* 153 0x99 '.' */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x0c, 0x00, /* 0000110000 */
+       0x17, 0x00, /* 0001011100 */
+       0x23, 0x00, /* 0010001100 */
+       0x21, 0x80, /* 0010000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x21, 0x00, /* 0010000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x1a, 0x00, /* 0001101000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 154 0x9a '.' */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0xf1, 0xc0, /* 1111000111 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0x60, 0x80, /* 0110000010 */
+       0x71, 0x00, /* 0111000100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 155 0x9b '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x1f, 0x80, /* 0001111110 */
+       0x36, 0x80, /* 0011011010 */
+       0x26, 0x00, /* 0010011000 */
+       0x66, 0x00, /* 0110011000 */
+       0x66, 0x00, /* 0110011000 */
+       0x66, 0x00, /* 0110011000 */
+       0x66, 0x00, /* 0110011000 */
+       0x76, 0x00, /* 0111011000 */
+       0x36, 0x80, /* 0011011010 */
+       0x1f, 0x80, /* 0001111110 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 156 0x9c '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x3b, 0x00, /* 0011101100 */
+       0x33, 0x00, /* 0011001100 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x7e, 0x00, /* 0111111000 */
+       0x7e, 0x00, /* 0111111000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x7c, 0x80, /* 0111110010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x43, 0x00, /* 0100001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 157 0x9d '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x40, 0x80, /* 0100000010 */
+       0x40, 0x80, /* 0100000010 */
+       0x21, 0x00, /* 0010000100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 158 0x9e '.' */
+       0x00, 0x00, /* 0000000000 */
+       0xbf, 0x00, /* 1011111100 */
+       0x40, 0x80, /* 0100000010 */
+       0x40, 0x80, /* 0100000010 */
+       0x7f, 0x00, /* 0111111100 */
+       0x40, 0x00, /* 0100000000 */
+       0x48, 0x00, /* 0100100000 */
+       0x48, 0x00, /* 0100100000 */
+       0x5e, 0x00, /* 0101111000 */
+       0x48, 0x00, /* 0100100000 */
+       0x48, 0x00, /* 0100100000 */
+       0x48, 0x00, /* 0100100000 */
+       0x48, 0x80, /* 0100100010 */
+       0x47, 0x00, /* 0100011100 */
+       0xe0, 0x00, /* 1110000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 159 0x9f '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x03, 0x00, /* 0000001100 */
+       0x04, 0x80, /* 0000010010 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x09, 0x00, /* 0000100100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x48, 0x00, /* 0100100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x08, 0x00, /* 0000100000 */
+       0x90, 0x00, /* 1001000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 160 0xa0 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x21, 0x80, /* 0010000110 */
+       0x07, 0x80, /* 0000011110 */
+       0x39, 0x80, /* 0011100110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x3d, 0xc0, /* 0011110111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 161 0xa1 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x03, 0x00, /* 0000001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 162 0xa2 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x66, 0x00, /* 0110011000 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xc1, 0x80, /* 1100000110 */
+       0xe1, 0x80, /* 1110000110 */
+       0x73, 0x00, /* 0111001100 */
+       0x3c, 0x00, /* 0011110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 163 0xa3 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0xf7, 0x80, /* 1111011110 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x77, 0x00, /* 0111011100 */
+       0x3d, 0x80, /* 0011110110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 164 0xa4 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x38, 0x80, /* 0011100010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x47, 0x00, /* 0100011100 */
+       0x00, 0x00, /* 0000000000 */
+       0x6f, 0x00, /* 0110111100 */
+       0x7b, 0x80, /* 0111101110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x7b, 0xc0, /* 0111101111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 165 0xa5 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x38, 0x80, /* 0011100010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x47, 0x00, /* 0100011100 */
+       0x00, 0x00, /* 0000000000 */
+       0xe3, 0xc0, /* 1110001111 */
+       0x71, 0x80, /* 0111000110 */
+       0x79, 0x80, /* 0111100110 */
+       0x79, 0x80, /* 0111100110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x67, 0x80, /* 0110011110 */
+       0x63, 0x80, /* 0110001110 */
+       0x61, 0x80, /* 0110000110 */
+       0xf0, 0xc0, /* 1111000011 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 166 0xa6 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x63, 0x00, /* 0110001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x0f, 0x00, /* 0000111100 */
+       0x33, 0x00, /* 0011001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x67, 0x00, /* 0110011100 */
+       0x3b, 0x80, /* 0011101110 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 167 0xa7 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x21, 0x80, /* 0010000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x00, /* 0110000100 */
+       0x33, 0x00, /* 0011001100 */
+       0x1c, 0x00, /* 0001110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 168 0xa8 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x00, 0x00, /* 0000000000 */
+       0x06, 0x00, /* 0000011000 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x80, /* 0110000010 */
+       0x73, 0x80, /* 0111001110 */
+       0x3f, 0x00, /* 0011111100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 169 0xa9 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 170 0xaa '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 171 0xab '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x20, 0x00, /* 0010000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x20, 0x00, /* 0010000000 */
+       0x20, 0x80, /* 0010000010 */
+       0x21, 0x00, /* 0010000100 */
+       0x22, 0x00, /* 0010001000 */
+       0x74, 0x00, /* 0111010000 */
+       0x08, 0x00, /* 0000100000 */
+       0x17, 0x00, /* 0001011100 */
+       0x28, 0x80, /* 0010100010 */
+       0x43, 0x00, /* 0100001100 */
+       0x04, 0x00, /* 0000010000 */
+       0x08, 0x00, /* 0000100000 */
+       0x0f, 0x80, /* 0000111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 172 0xac '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x20, 0x00, /* 0010000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x20, 0x00, /* 0010000000 */
+       0x20, 0x80, /* 0010000010 */
+       0x21, 0x00, /* 0010000100 */
+       0x22, 0x00, /* 0010001000 */
+       0x74, 0x00, /* 0111010000 */
+       0x09, 0x00, /* 0000100100 */
+       0x13, 0x00, /* 0001001100 */
+       0x25, 0x00, /* 0010010100 */
+       0x49, 0x00, /* 0100100100 */
+       0x1f, 0x80, /* 0001111110 */
+       0x01, 0x00, /* 0000000100 */
+       0x01, 0x00, /* 0000000100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 173 0xad '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 174 0xae '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0d, 0x80, /* 0000110110 */
+       0x1b, 0x00, /* 0001101100 */
+       0x36, 0x00, /* 0011011000 */
+       0x6c, 0x00, /* 0110110000 */
+       0xd8, 0x00, /* 1101100000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x36, 0x00, /* 0011011000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x0d, 0x80, /* 0000110110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 175 0xaf '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x36, 0x00, /* 0011011000 */
+       0x1b, 0x00, /* 0001101100 */
+       0x0d, 0x80, /* 0000110110 */
+       0x06, 0xc0, /* 0000011011 */
+       0x0d, 0x80, /* 0000110110 */
+       0x1b, 0x00, /* 0001101100 */
+       0x36, 0x00, /* 0011011000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 176 0xb0 '.' */
+       0xc3, 0x00, /* 1100001100 */
+       0x41, 0x00, /* 0100000100 */
+       0x18, 0x40, /* 0001100001 */
+       0x10, 0x40, /* 0001000001 */
+       0xc3, 0x00, /* 1100001100 */
+       0x41, 0x00, /* 0100000100 */
+       0x18, 0x40, /* 0001100001 */
+       0x10, 0x40, /* 0001000001 */
+       0xc3, 0x00, /* 1100001100 */
+       0x41, 0x00, /* 0100000100 */
+       0x18, 0x40, /* 0001100001 */
+       0x10, 0x40, /* 0001000001 */
+       0xc3, 0x00, /* 1100001100 */
+       0x41, 0x00, /* 0100000100 */
+       0x18, 0x40, /* 0001100001 */
+       0x10, 0x40, /* 0001000001 */
+       0xc3, 0x00, /* 1100001100 */
+       0x41, 0x00, /* 0100000100 */
+
+       /* 177 0xb1 '.' */
+       0x11, 0x00, /* 0001000100 */
+       0xbb, 0x80, /* 1011101110 */
+       0x11, 0x00, /* 0001000100 */
+       0x44, 0x40, /* 0100010001 */
+       0xee, 0xc0, /* 1110111011 */
+       0x44, 0x40, /* 0100010001 */
+       0x11, 0x00, /* 0001000100 */
+       0xbb, 0x80, /* 1011101110 */
+       0x11, 0x00, /* 0001000100 */
+       0x44, 0x40, /* 0100010001 */
+       0xee, 0xc0, /* 1110111011 */
+       0x44, 0x40, /* 0100010001 */
+       0x11, 0x00, /* 0001000100 */
+       0xbb, 0x80, /* 1011101110 */
+       0x11, 0x00, /* 0001000100 */
+       0x44, 0x40, /* 0100010001 */
+       0xee, 0xc0, /* 1110111011 */
+       0x44, 0x40, /* 0100010001 */
+
+       /* 178 0xb2 '.' */
+       0x3c, 0xc0, /* 0011110011 */
+       0xbe, 0xc0, /* 1011111011 */
+       0xe7, 0x80, /* 1110011110 */
+       0xef, 0x80, /* 1110111110 */
+       0x3c, 0xc0, /* 0011110011 */
+       0xbe, 0xc0, /* 1011111011 */
+       0xe7, 0x80, /* 1110011110 */
+       0xef, 0x80, /* 1110111110 */
+       0x3c, 0xc0, /* 0011110011 */
+       0xbe, 0xc0, /* 1011111011 */
+       0xe7, 0x80, /* 1110011110 */
+       0xef, 0x80, /* 1110111110 */
+       0x3c, 0xc0, /* 0011110011 */
+       0xbe, 0xc0, /* 1011111011 */
+       0xe7, 0x80, /* 1110011110 */
+       0xef, 0x80, /* 1110111110 */
+       0x3c, 0xc0, /* 0011110011 */
+       0xbe, 0xc0, /* 1011111011 */
+
+       /* 179 0xb3 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 180 0xb4 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 181 0xb5 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 182 0xb6 '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0xfb, 0x00, /* 1111101100 */
+       0xfb, 0x00, /* 1111101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 183 0xb7 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0x00, /* 1111111100 */
+       0xff, 0x00, /* 1111111100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 184 0xb8 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 185 0xb9 '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0xfb, 0x00, /* 1111101100 */
+       0xfb, 0x00, /* 1111101100 */
+       0x03, 0x00, /* 0000001100 */
+       0xfb, 0x00, /* 1111101100 */
+       0xfb, 0x00, /* 1111101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 186 0xba '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 187 0xbb '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0x00, /* 1111111100 */
+       0xff, 0x00, /* 1111111100 */
+       0x03, 0x00, /* 0000001100 */
+       0xfb, 0x00, /* 1111101100 */
+       0xfb, 0x00, /* 1111101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 188 0xbc '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0xfb, 0x00, /* 1111101100 */
+       0xfb, 0x00, /* 1111101100 */
+       0x03, 0x00, /* 0000001100 */
+       0xff, 0x00, /* 1111111100 */
+       0xff, 0x00, /* 1111111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 189 0xbd '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0xff, 0x00, /* 1111111100 */
+       0xff, 0x00, /* 1111111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 190 0xbe '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 191 0xbf '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 192 0xc0 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 193 0xc1 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 194 0xc2 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 195 0xc3 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 196 0xc4 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 197 0xc5 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 198 0xc6 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 199 0xc7 '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 200 0xc8 '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x18, 0x00, /* 0001100000 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 201 0xc9 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x18, 0x00, /* 0001100000 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 202 0xca '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0xfb, 0xc0, /* 1111101111 */
+       0xfb, 0xc0, /* 1111101111 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 203 0xcb '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0xfb, 0xc0, /* 1111101111 */
+       0xfb, 0xc0, /* 1111101111 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 204 0xcc '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x18, 0x00, /* 0001100000 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x1b, 0xc0, /* 0001101111 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 205 0xcd '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 206 0xce '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0xfb, 0xc0, /* 1111101111 */
+       0xfb, 0xc0, /* 1111101111 */
+       0x00, 0x00, /* 0000000000 */
+       0xfb, 0xc0, /* 1111101111 */
+       0xfb, 0xc0, /* 1111101111 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 207 0xcf '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 208 0xd0 '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 209 0xd1 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 210 0xd2 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 211 0xd3 '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 212 0xd4 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 213 0xd5 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 214 0xd6 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 215 0xd7 '.' */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+       0x1b, 0x00, /* 0001101100 */
+
+       /* 216 0xd8 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 217 0xd9 '.' */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0xfc, 0x00, /* 1111110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 218 0xda '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+
+       /* 219 0xdb '.' */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+
+       /* 220 0xdc '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+
+       /* 221 0xdd '.' */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+       0xf8, 0x00, /* 1111100000 */
+
+       /* 222 0xde '.' */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+       0x07, 0xc0, /* 0000011111 */
+
+       /* 223 0xdf '.' */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0xff, 0xc0, /* 1111111111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 224 0xe0 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1c, 0x80, /* 0001110010 */
+       0x35, 0x80, /* 0011010110 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x63, 0x00, /* 0110001100 */
+       0x37, 0x80, /* 0011011110 */
+       0x1c, 0x80, /* 0001110010 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 225 0xe1 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x63, 0x00, /* 0110001100 */
+       0x6f, 0x00, /* 0110111100 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x63, 0x00, /* 0110001100 */
+       0x6e, 0x00, /* 0110111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 226 0xe2 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 227 0xe3 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 228 0xe4 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0x80, /* 1111111110 */
+       0x60, 0x00, /* 0110000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x80, /* 0011000010 */
+       0x61, 0x80, /* 0110000110 */
+       0xff, 0x80, /* 1111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 229 0xe5 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1f, 0xc0, /* 0001111111 */
+       0x36, 0x00, /* 0011011000 */
+       0x63, 0x00, /* 0110001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x33, 0x00, /* 0011001100 */
+       0x3e, 0x00, /* 0011111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 230 0xe6 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x73, 0x80, /* 0111001110 */
+       0x6d, 0x80, /* 0110110110 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0xc0, 0x00, /* 1100000000 */
+
+       /* 231 0xe7 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x01, 0x80, /* 0000000110 */
+       0x36, 0x40, /* 0011011001 */
+       0x5e, 0x00, /* 0101111000 */
+       0x8c, 0x00, /* 1000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 232 0xe8 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x33, 0x00, /* 0011001100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 233 0xe9 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x1f, 0x00, /* 0001111100 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x60, 0xc0, /* 0110000011 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x7f, 0xc0, /* 0111111111 */
+       0x60, 0xc0, /* 0110000011 */
+       0x31, 0x80, /* 0011000110 */
+       0x31, 0x80, /* 0011000110 */
+       0x1f, 0x00, /* 0001111100 */
+       0x0e, 0x00, /* 0000111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 234 0xea '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0xc0, 0xc0, /* 1100000011 */
+       0xc0, 0xc0, /* 1100000011 */
+       0xc0, 0xc0, /* 1100000011 */
+       0x61, 0x80, /* 0110000110 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0xf3, 0xc0, /* 1111001111 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 235 0xeb '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x07, 0x00, /* 0000011100 */
+       0x1f, 0x80, /* 0001111110 */
+       0x30, 0xc0, /* 0011000011 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x3e, 0x00, /* 0011111000 */
+       0x66, 0x00, /* 0110011000 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc3, 0x00, /* 1100001100 */
+       0xc3, 0x00, /* 1100001100 */
+       0x66, 0x00, /* 0110011000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 236 0xec '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x33, 0x00, /* 0011001100 */
+       0x6d, 0x80, /* 0110110110 */
+       0xcc, 0xc0, /* 1100110011 */
+       0xcc, 0xc0, /* 1100110011 */
+       0xcc, 0xc0, /* 1100110011 */
+       0xcc, 0xc0, /* 1100110011 */
+       0x6d, 0x80, /* 0110110110 */
+       0x33, 0x00, /* 0011001100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 237 0xed '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x01, 0x80, /* 0000000110 */
+       0x01, 0x80, /* 0000000110 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x37, 0x00, /* 0011011100 */
+       0x6d, 0x80, /* 0110110110 */
+       0xcc, 0xc0, /* 1100110011 */
+       0xcc, 0xc0, /* 1100110011 */
+       0xcc, 0xc0, /* 1100110011 */
+       0xcc, 0xc0, /* 1100110011 */
+       0x6d, 0x80, /* 0110110110 */
+       0x3b, 0x00, /* 0011101100 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x60, 0x00, /* 0110000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 238 0xee '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x03, 0x80, /* 0000001110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x3f, 0x80, /* 0011111110 */
+       0x3f, 0x80, /* 0011111110 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x18, 0x00, /* 0001100000 */
+       0x18, 0x00, /* 0001100000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x03, 0x80, /* 0000001110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 239 0xef '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x61, 0x80, /* 0110000110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 240 0xf0 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 241 0xf1 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 242 0xf2 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xe0, 0x00, /* 1110000000 */
+       0x38, 0x00, /* 0011100000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x03, 0x80, /* 0000001110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x38, 0x00, /* 0011100000 */
+       0xe0, 0x00, /* 1110000000 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0x00, /* 1111111100 */
+       0xff, 0x00, /* 1111111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 243 0xf3 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x03, 0x80, /* 0000001110 */
+       0x0e, 0x00, /* 0000111000 */
+       0x38, 0x00, /* 0011100000 */
+       0xe0, 0x00, /* 1110000000 */
+       0x38, 0x00, /* 0011100000 */
+       0x0e, 0x00, /* 0000111000 */
+       0x03, 0x80, /* 0000001110 */
+       0x00, 0x00, /* 0000000000 */
+       0xff, 0x80, /* 1111111110 */
+       0xff, 0x80, /* 1111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 244 0xf4 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x30, 0x00, /* 0011000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 245 0xf5 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x03, 0x00, /* 0000001100 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 246 0xf6 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 247 0xf7 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x38, 0x00, /* 0011100000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x06, 0xc0, /* 0000011011 */
+       0x03, 0x80, /* 0000001110 */
+       0x38, 0x00, /* 0011100000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x06, 0xc0, /* 0000011011 */
+       0x03, 0x80, /* 0000001110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 248 0xf8 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x33, 0x00, /* 0011001100 */
+       0x33, 0x00, /* 0011001100 */
+       0x1e, 0x00, /* 0001111000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 249 0xf9 '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 250 0xfa '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 251 0xfb '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0f, 0xc0, /* 0000111111 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0xcc, 0x00, /* 1100110000 */
+       0x6c, 0x00, /* 0110110000 */
+       0x3c, 0x00, /* 0011110000 */
+       0x1c, 0x00, /* 0001110000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 252 0xfc '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x27, 0x00, /* 0010011100 */
+       0x7b, 0x00, /* 0111101100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x31, 0x00, /* 0011000100 */
+       0x7b, 0x80, /* 0111101110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 253 0xfd '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x1e, 0x00, /* 0001111000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x63, 0x00, /* 0110001100 */
+       0x43, 0x00, /* 0100001100 */
+       0x06, 0x00, /* 0000011000 */
+       0x0c, 0x00, /* 0000110000 */
+       0x18, 0x00, /* 0001100000 */
+       0x30, 0x80, /* 0011000010 */
+       0x7f, 0x80, /* 0111111110 */
+       0x7f, 0x80, /* 0111111110 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 254 0xfe '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x3f, 0x00, /* 0011111100 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+       /* 255 0xff '.' */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+       0x00, 0x00, /* 0000000000 */
+
+};
+
+
+struct font_desc font_10x18 = {
+       FONT10x18_IDX,
+       "10x18",
+       10,
+       18,
+       fontdata_10x18,
+#ifdef __sparc__
+       5
+#else
+       -1
+#endif
+};
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
new file mode 100644 (file)
index 0000000..1fa7fcf
--- /dev/null
@@ -0,0 +1,4118 @@
+/**************************************/
+/* this file adapted from font_8x16.c */
+/* by Jurriaan Kalkman 05-2005        */
+/**************************************/
+
+#include <linux/font.h>
+
+#define FONTDATAMAX 3584
+
+static unsigned char fontdata_7x14[FONTDATAMAX] = {
+
+       /* 0 0x00 '^@' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 1 0x01 '^A' */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0x82, /* 1000001 */
+       0xaa, /* 1010101 */
+       0x82, /* 1000001 */
+       0x82, /* 1000001 */
+       0xba, /* 1011101 */
+       0x92, /* 1001001 */
+       0x82, /* 1000001 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 2 0x02 '^B' */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0xfe, /* 1111111 */
+       0xd6, /* 1101011 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xc6, /* 1100011 */
+       0xee, /* 1110111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 3 0x03 '^C' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x6c, /* 0110110 */
+       0x7c, /* 0111110 */
+       0xfe, /* 1111111 */
+       0x7c, /* 0111110 */
+       0x38, /* 0011100 */
+       0x18, /* 0001100 */
+       0x10, /* 0001000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 4 0x04 '^D' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x7c, /* 0111110 */
+       0xfe, /* 1111111 */
+       0x7c, /* 0111110 */
+       0x38, /* 0011100 */
+       0x10, /* 0001000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 5 0x05 '^E' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x38, /* 0011100 */
+       0x38, /* 0011100 */
+       0xee, /* 1110111 */
+       0xee, /* 1110111 */
+       0xee, /* 1110111 */
+       0x10, /* 0001000 */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 6 0x06 '^F' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x7c, /* 0111110 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0x7c, /* 0111110 */
+       0x10, /* 0001000 */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 7 0x07 '^G' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x3c, /* 0011110 */
+       0x3c, /* 0011110 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 8 0x08 '^H' */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xe6, /* 1110011 */
+       0xc2, /* 1100001 */
+       0xc2, /* 1100001 */
+       0xe6, /* 1110011 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+
+       /* 9 0x09 '^I' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x44, /* 0100010 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 10 0x0a '^J' */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xc6, /* 1100011 */
+       0x92, /* 1001001 */
+       0xba, /* 1011101 */
+       0x92, /* 1001001 */
+       0xc6, /* 1100011 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+
+       /* 11 0x0b '^K' */
+       0x00, /* 0000000 */
+       0x1e, /* 0001111 */
+       0x0e, /* 0000111 */
+       0x1a, /* 0001101 */
+       0x1a, /* 0001101 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 12 0x0c '^L' */
+       0x00, /* 0000000 */
+       0x3c, /* 0011110 */
+       0x66, /* 0110011 */
+       0x66, /* 0110011 */
+       0x66, /* 0110011 */
+       0x66, /* 0110011 */
+       0x3c, /* 0011110 */
+       0x18, /* 0001100 */
+       0x7e, /* 0111111 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 13 0x0d '^M' */
+       0x00, /* 0000000 */
+       0x3e, /* 0011111 */
+       0x36, /* 0011011 */
+       0x3e, /* 0011111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x70, /* 0111000 */
+       0xf0, /* 1111000 */
+       0xe0, /* 1110000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 14 0x0e '^N' */
+       0x00, /* 0000000 */
+       0x7e, /* 0111111 */
+       0x66, /* 0110011 */
+       0x7e, /* 0111111 */
+       0x66, /* 0110011 */
+       0x66, /* 0110011 */
+       0x66, /* 0110011 */
+       0x66, /* 0110011 */
+       0x6e, /* 0110111 */
+       0xee, /* 1110111 */
+       0xec, /* 1110110 */
+       0xc0, /* 1100000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 15 0x0f '^O' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x10, /* 0001000 */
+       0x10, /* 0001000 */
+       0xd6, /* 1101011 */
+       0x38, /* 0011100 */
+       0xee, /* 1110111 */
+       0x38, /* 0011100 */
+       0xd6, /* 1101011 */
+       0x10, /* 0001000 */
+       0x10, /* 0001000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 16 0x10 '^P' */
+       0x00, /* 0000000 */
+       0x80, /* 1000000 */
+       0xc0, /* 1100000 */
+       0xe0, /* 1110000 */
+       0xf0, /* 1111000 */
+       0xfc, /* 1111110 */
+       0xf0, /* 1111000 */
+       0xe0, /* 1110000 */
+       0xc0, /* 1100000 */
+       0x80, /* 1000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 17 0x11 '^Q' */
+       0x00, /* 0000000 */
+       0x04, /* 0000010 */
+       0x0c, /* 0000110 */
+       0x1c, /* 0001110 */
+       0x3c, /* 0011110 */
+       0xfc, /* 1111110 */
+       0x3c, /* 0011110 */
+       0x1c, /* 0001110 */
+       0x0c, /* 0000110 */
+       0x04, /* 0000010 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 18 0x12 '^R' */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x3c, /* 0011110 */
+       0x7e, /* 0111111 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x7e, /* 0111111 */
+       0x3c, /* 0011110 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 19 0x13 '^S' */
+       0x00, /* 0000000 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 20 0x14 '^T' */
+       0x00, /* 0000000 */
+       0x7e, /* 0111111 */
+       0xd4, /* 1101010 */
+       0xd4, /* 1101010 */
+       0xd4, /* 1101010 */
+       0x74, /* 0111010 */
+       0x14, /* 0001010 */
+       0x14, /* 0001010 */
+       0x14, /* 0001010 */
+       0x14, /* 0001010 */
+       0x16, /* 0001011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 21 0x15 '^U' */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0x60, /* 0110000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0x18, /* 0001100 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 22 0x16 '^V' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xfc, /* 1111110 */
+       0xfc, /* 1111110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 23 0x17 '^W' */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x3c, /* 0011110 */
+       0x7e, /* 0111111 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x7e, /* 0111111 */
+       0x3c, /* 0011110 */
+       0x18, /* 0001100 */
+       0x7e, /* 0111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 24 0x18 '^X' */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x3c, /* 0011110 */
+       0x7e, /* 0111111 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 25 0x19 '^Y' */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x7e, /* 0111111 */
+       0x3c, /* 0011110 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 26 0x1a '^Z' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0xfc, /* 1111110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 27 0x1b '^[' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xfc, /* 1111110 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 28 0x1c '^\' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 29 0x1d '^]' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x28, /* 0010100 */
+       0x6c, /* 0110110 */
+       0xfe, /* 1111111 */
+       0x6c, /* 0110110 */
+       0x28, /* 0010100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 30 0x1e '^^' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x78, /* 0111100 */
+       0xfc, /* 1111110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 31 0x1f '^_' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xfc, /* 1111110 */
+       0x78, /* 0111100 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 32 0x20 ' ' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 33 0x21 '!' */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x3c, /* 0011110 */
+       0x3c, /* 0011110 */
+       0x3c, /* 0011110 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 34 0x22 '"' */
+       0x00, /* 0000000 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x28, /* 0010100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 35 0x23 '#' */
+       0x00, /* 0000000 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 36 0x24 '$' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xc4, /* 1100010 */
+       0xc0, /* 1100000 */
+       0x78, /* 0111100 */
+       0x0c, /* 0000110 */
+       0x8c, /* 1000110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+
+       /* 37 0x25 '%' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xc0, /* 1100000 */
+       0xc4, /* 1100010 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xcc, /* 1100110 */
+       0x8c, /* 1000110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 38 0x26 '&' */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0x78, /* 0111100 */
+       0xde, /* 1101111 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xdc, /* 1101110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 39 0x27 ''' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 40 0x28 '(' */
+       0x00, /* 0000000 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x0c, /* 0000110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 41 0x29 ')' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 42 0x2a '*' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0xfe, /* 1111111 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 43 0x2b '+' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x10, /* 0001000 */
+       0x10, /* 0001000 */
+       0x7c, /* 0111110 */
+       0x10, /* 0001000 */
+       0x10, /* 0001000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 44 0x2c ',' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 45 0x2d '-' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 46 0x2e '.' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 47 0x2f '/' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x04, /* 0000010 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xc0, /* 1100000 */
+       0x80, /* 1000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 48 0x30 '0' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xdc, /* 1101110 */
+       0xec, /* 1110110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 49 0x31 '1' */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x38, /* 0011100 */
+       0x78, /* 0111100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 50 0x32 '2' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 51 0x33 '3' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x38, /* 0011100 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 52 0x34 '4' */
+       0x00, /* 0000000 */
+       0x0c, /* 0000110 */
+       0x1c, /* 0001110 */
+       0x3c, /* 0011110 */
+       0x6c, /* 0110110 */
+       0xcc, /* 1100110 */
+       0xfe, /* 1111111 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 53 0x35 '5' */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xf8, /* 1111100 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 54 0x36 '6' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xf8, /* 1111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 55 0x37 '7' */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 56 0x38 '8' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 57 0x39 '9' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x7c, /* 0111110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x70, /* 0111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 58 0x3a ':' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 59 0x3b ';' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 60 0x3c '<' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x04, /* 0000010 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x0c, /* 0000110 */
+       0x04, /* 0000010 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 61 0x3d '=' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 62 0x3e '>' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x40, /* 0100000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x40, /* 0100000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 63 0x3f '?' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 64 0x40 '@' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xdc, /* 1101110 */
+       0xdc, /* 1101110 */
+       0xd8, /* 1101100 */
+       0xc0, /* 1100000 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 65 0x41 'A' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 66 0x42 'B' */
+       0x00, /* 0000000 */
+       0xf8, /* 1111100 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x78, /* 0111100 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xf8, /* 1111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 67 0x43 'C' */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0xc4, /* 1100010 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc4, /* 1100010 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 68 0x44 'D' */
+       0x00, /* 0000000 */
+       0xf0, /* 1111000 */
+       0xd8, /* 1101100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xd8, /* 1101100 */
+       0xf0, /* 1111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 69 0x45 'E' */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0x6c, /* 0110110 */
+       0x64, /* 0110010 */
+       0x68, /* 0110100 */
+       0x78, /* 0111100 */
+       0x68, /* 0110100 */
+       0x60, /* 0110000 */
+       0x64, /* 0110010 */
+       0x6c, /* 0110110 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 70 0x46 'F' */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0x64, /* 0110010 */
+       0x60, /* 0110000 */
+       0x68, /* 0110100 */
+       0x78, /* 0111100 */
+       0x68, /* 0110100 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x70, /* 0111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 71 0x47 'G' */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0xc4, /* 1100010 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xdc, /* 1101110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x6c, /* 0110110 */
+       0x34, /* 0011010 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 72 0x48 'H' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 73 0x49 'I' */
+       0x00, /* 0000000 */
+       0x3c, /* 0011110 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x3c, /* 0011110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 74 0x4a 'J' */
+       0x00, /* 0000000 */
+       0x1c, /* 0001110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 75 0x4b 'K' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xd8, /* 1101100 */
+       0xf0, /* 1111000 */
+       0xf0, /* 1111000 */
+       0xd8, /* 1101100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 76 0x4c 'L' */
+       0x00, /* 0000000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc4, /* 1100010 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 77 0x4d 'M' */
+       0x00, /* 0000000 */
+       0xc6, /* 1100011 */
+       0xee, /* 1110111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xd6, /* 1101011 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 78 0x4e 'N' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xec, /* 1110110 */
+       0xec, /* 1110110 */
+       0xfc, /* 1111110 */
+       0xdc, /* 1101110 */
+       0xdc, /* 1101110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 79 0x4f 'O' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 80 0x50 'P' */
+       0x00, /* 0000000 */
+       0xf8, /* 1111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xf8, /* 1111100 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 81 0x51 'Q' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xdc, /* 1101110 */
+       0x78, /* 0111100 */
+       0x18, /* 0001100 */
+       0x1c, /* 0001110 */
+       0x00, /* 0000000 */
+
+       /* 82 0x52 'R' */
+       0x00, /* 0000000 */
+       0xf8, /* 1111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xf8, /* 1111100 */
+       0xd8, /* 1101100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 83 0x53 'S' */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0xc4, /* 1100010 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0x60, /* 0110000 */
+       0x38, /* 0011100 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x8c, /* 1000110 */
+       0xf8, /* 1111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 84 0x54 'T' */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xfc, /* 1111110 */
+       0xb4, /* 1011010 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 85 0x55 'U' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 86 0x56 'V' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 87 0x57 'W' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xfc, /* 1111110 */
+       0x48, /* 0100100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 88 0x58 'X' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 89 0x59 'Y' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 90 0x5a 'Z' */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0x8c, /* 1000110 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xc4, /* 1100010 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 91 0x5b '[' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 92 0x5c '\' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x80, /* 1000000 */
+       0xc0, /* 1100000 */
+       0xe0, /* 1110000 */
+       0x70, /* 0111000 */
+       0x38, /* 0011100 */
+       0x1c, /* 0001110 */
+       0x0c, /* 0000110 */
+       0x04, /* 0000010 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 93 0x5d ']' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 94 0x5e '^' */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0xc6, /* 1100011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 95 0x5f '_' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+
+       /* 96 0x60 '`' */
+       0x00, /* 0000000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 97 0x61 'a' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0x0c, /* 0000110 */
+       0x7c, /* 0111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 98 0x62 'b' */
+       0x00, /* 0000000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xf0, /* 1111000 */
+       0xd8, /* 1101100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xf8, /* 1111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 99 0x63 'c' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 100 0x64 'd' */
+       0x00, /* 0000000 */
+       0x1c, /* 0001110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x3c, /* 0011110 */
+       0x6c, /* 0110110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 101 0x65 'e' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 102 0x66 'f' */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x64, /* 0110010 */
+       0x60, /* 0110000 */
+       0xf0, /* 1111000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0xf0, /* 1111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 103 0x67 'g' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x76, /* 0111011 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x7c, /* 0111110 */
+       0x0c, /* 0000110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+
+       /* 104 0x68 'h' */
+       0x00, /* 0000000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xd8, /* 1101100 */
+       0xec, /* 1110110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 105 0x69 'i' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x70, /* 0111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 106 0x6a 'j' */
+       0x00, /* 0000000 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x00, /* 0000000 */
+       0x1c, /* 0001110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+
+       /* 107 0x6b 'k' */
+       0x00, /* 0000000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0xd8, /* 1101100 */
+       0xf0, /* 1111000 */
+       0xf0, /* 1111000 */
+       0xd8, /* 1101100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 108 0x6c 'l' */
+       0x00, /* 0000000 */
+       0x70, /* 0111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 109 0x6d 'm' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xec, /* 1110110 */
+       0xfe, /* 1111111 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 110 0x6e 'n' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xb8, /* 1011100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 111 0x6f 'o' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 112 0x70 'p' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xb8, /* 1011100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xf8, /* 1111100 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+
+       /* 113 0x71 'q' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x74, /* 0111010 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x7c, /* 0111110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+
+       /* 114 0x72 'r' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xb8, /* 1011100 */
+       0xec, /* 1110110 */
+       0xcc, /* 1100110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 115 0x73 's' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 116 0x74 't' */
+       0x00, /* 0000000 */
+       0x10, /* 0001000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xfc, /* 1111110 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x36, /* 0011011 */
+       0x1c, /* 0001110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 117 0x75 'u' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 118 0x76 'v' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 119 0x77 'w' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0xfe, /* 1111111 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 120 0x78 'x' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 121 0x79 'y' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x7c, /* 0111110 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0xf0, /* 1111000 */
+
+       /* 122 0x7a 'z' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 123 0x7b '{' */
+       0x00, /* 0000000 */
+       0x1c, /* 0001110 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xe0, /* 1110000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x1c, /* 0001110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 124 0x7c '|' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 125 0x7d '}' */
+       0x00, /* 0000000 */
+       0x70, /* 0111000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x0e, /* 0000111 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x70, /* 0111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 126 0x7e '~' */
+       0x00, /* 0000000 */
+       0xec, /* 1110110 */
+       0xb8, /* 1011100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 127 0x7f '\7f' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 128 0x80 '\80' */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0xc4, /* 1100010 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc4, /* 1100010 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0x18, /* 0001100 */
+       0x70, /* 0111000 */
+       0x00, /* 0000000 */
+
+       /* 129 0x81 '\81' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 130 0x82 '\82' */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 131 0x83 '\83' */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0x0c, /* 0000110 */
+       0x7c, /* 0111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 132 0x84 '\84' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0x0c, /* 0000110 */
+       0x7c, /* 0111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 133 0x85 '\85' */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0x0c, /* 0000110 */
+       0x7c, /* 0111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 134 0x86 '\86' */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0x0c, /* 0000110 */
+       0x7c, /* 0111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 135 0x87 '\87' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xe0, /* 1110000 */
+
+       /* 136 0x88 '\88' */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 137 0x89 '\89' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 138 0x8a '\8a' */
+       0xc0, /* 1100000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 139 0x8b '\8b' */
+       0x00, /* 0000000 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x3c, /* 0011110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 140 0x8c '\8c' */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x70, /* 0111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 141 0x8d '\8d' */
+       0xc0, /* 1100000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x70, /* 0111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 142 0x8e '\8e' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 143 0x8f '\8f' */
+       0x30, /* 0011000 */
+       0x48, /* 0100100 */
+       0x48, /* 0100100 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 144 0x90 '\90' */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0xc4, /* 1100010 */
+       0xd0, /* 1101000 */
+       0xf0, /* 1111000 */
+       0xd0, /* 1101000 */
+       0xc4, /* 1100010 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 145 0x91 '\91' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xec, /* 1110110 */
+       0x36, /* 0011011 */
+       0x36, /* 0011011 */
+       0x7e, /* 0111111 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0x6e, /* 0110111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 146 0x92 '\92' */
+       0x00, /* 0000000 */
+       0x3e, /* 0011111 */
+       0x6c, /* 0110110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xfe, /* 1111111 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xce, /* 1100111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 147 0x93 '\93' */
+       0x10, /* 0001000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 148 0x94 '\94' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 149 0x95 '\95' */
+       0xc0, /* 1100000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 150 0x96 '\96' */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 151 0x97 '\97' */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 152 0x98 '\98' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x7c, /* 0111110 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x70, /* 0111000 */
+
+       /* 153 0x99 '\99' */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 154 0x9a '\9a' */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 155 0x9b '\9b' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x7c, /* 0111110 */
+       0xcc, /* 1100110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0x7c, /* 0111110 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 156 0x9c '\9c' */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x64, /* 0110010 */
+       0x60, /* 0110000 */
+       0xf0, /* 1111000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0xe6, /* 1110011 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 157 0x9d '\9d' */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0xfc, /* 1111110 */
+       0x30, /* 0011000 */
+       0xfc, /* 1111110 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 158 0x9e '\9e' */
+       0xf8, /* 1111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xf8, /* 1111100 */
+       0xc4, /* 1100010 */
+       0xcc, /* 1100110 */
+       0xde, /* 1101111 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xc6, /* 1100011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 159 0x9f '\9f' */
+       0x1c, /* 0001110 */
+       0x36, /* 0011011 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xfc, /* 1111110 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xb0, /* 1011000 */
+       0xe0, /* 1110000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 160 0xa0 ' ' */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0x0c, /* 0000110 */
+       0x7c, /* 0111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 161 0xa1 '¡' */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x00, /* 0000000 */
+       0x70, /* 0111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 162 0xa2 '¢' */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 163 0xa3 '£' */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 164 0xa4 '¤' */
+       0x00, /* 0000000 */
+       0x76, /* 0111011 */
+       0xdc, /* 1101110 */
+       0x00, /* 0000000 */
+       0xb8, /* 1011100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 165 0xa5 '¥' */
+       0x76, /* 0111011 */
+       0xdc, /* 1101110 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xec, /* 1110110 */
+       0xec, /* 1110110 */
+       0xfc, /* 1111110 */
+       0xdc, /* 1101110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 166 0xa6 '¦' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 167 0xa7 '§' */
+       0x00, /* 0000000 */
+       0x70, /* 0111000 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0x70, /* 0111000 */
+       0x00, /* 0000000 */
+       0xf8, /* 1111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 168 0xa8 '¨' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xc0, /* 1100000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 169 0xa9 '©' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 170 0xaa 'ª' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 171 0xab '«' */
+       0x60, /* 0110000 */
+       0xe0, /* 1110000 */
+       0x62, /* 0110001 */
+       0x66, /* 0110011 */
+       0x6c, /* 0110110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xc0, /* 1100000 */
+       0xb8, /* 1011100 */
+       0x4c, /* 0100110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x7c, /* 0111110 */
+
+       /* 172 0xac '¬' */
+       0x60, /* 0110000 */
+       0xe0, /* 1110000 */
+       0x62, /* 0110001 */
+       0x66, /* 0110011 */
+       0x6c, /* 0110110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x6c, /* 0110110 */
+       0xdc, /* 1101110 */
+       0xb4, /* 1011010 */
+       0x7e, /* 0111111 */
+       0x0c, /* 0000110 */
+       0x0c, /* 0000110 */
+       0x00, /* 0000000 */
+
+       /* 173 0xad '­' */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0x78, /* 0111100 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 174 0xae '®' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x36, /* 0011011 */
+       0x6c, /* 0110110 */
+       0xd8, /* 1101100 */
+       0x6c, /* 0110110 */
+       0x36, /* 0011011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 175 0xaf '¯' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xd8, /* 1101100 */
+       0x6c, /* 0110110 */
+       0x36, /* 0011011 */
+       0x6c, /* 0110110 */
+       0xd8, /* 1101100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 176 0xb0 '°' */
+       0x88, /* 1000100 */
+       0x22, /* 0010001 */
+       0x88, /* 1000100 */
+       0x22, /* 0010001 */
+       0x88, /* 1000100 */
+       0x22, /* 0010001 */
+       0x88, /* 1000100 */
+       0x22, /* 0010001 */
+       0x88, /* 1000100 */
+       0x22, /* 0010001 */
+       0x88, /* 1000100 */
+       0x22, /* 0010001 */
+       0x88, /* 1000100 */
+       0x22, /* 0010001 */
+
+       /* 177 0xb1 '±' */
+       0x54, /* 0101010 */
+       0xaa, /* 1010101 */
+       0x54, /* 0101010 */
+       0xaa, /* 1010101 */
+       0x54, /* 0101010 */
+       0xaa, /* 1010101 */
+       0x54, /* 0101010 */
+       0xaa, /* 1010101 */
+       0x54, /* 0101010 */
+       0xaa, /* 1010101 */
+       0x54, /* 0101010 */
+       0xaa, /* 1010101 */
+       0x54, /* 0101010 */
+       0xaa, /* 1010101 */
+
+       /* 178 0xb2 '²' */
+       0xee, /* 1110111 */
+       0xba, /* 1011101 */
+       0xee, /* 1110111 */
+       0xba, /* 1011101 */
+       0xee, /* 1110111 */
+       0xba, /* 1011101 */
+       0xee, /* 1110111 */
+       0xba, /* 1011101 */
+       0xee, /* 1110111 */
+       0xba, /* 1011101 */
+       0xee, /* 1110111 */
+       0xba, /* 1011101 */
+       0xee, /* 1110111 */
+       0xba, /* 1011101 */
+
+       /* 179 0xb3 '³' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 180 0xb4 '´' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xf0, /* 1111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 181 0xb5 'µ' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xf0, /* 1111000 */
+       0x30, /* 0011000 */
+       0xf0, /* 1111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 182 0xb6 '¶' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xec, /* 1110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 183 0xb7 '·' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 184 0xb8 '¸' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xf0, /* 1111000 */
+       0x30, /* 0011000 */
+       0xf0, /* 1111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 185 0xb9 '¹' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xec, /* 1110110 */
+       0x0c, /* 0000110 */
+       0xec, /* 1110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 186 0xba 'º' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 187 0xbb '»' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x0c, /* 0000110 */
+       0xec, /* 1110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 188 0xbc '¼' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xec, /* 1110110 */
+       0x0c, /* 0000110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 189 0xbd '½' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 190 0xbe '¾' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xf0, /* 1111000 */
+       0x30, /* 0011000 */
+       0xf0, /* 1111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 191 0xbf '¿' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xf0, /* 1111000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 192 0xc0 'À' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x3e, /* 0011111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 193 0xc1 'Á' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 194 0xc2 'Â' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 195 0xc3 'Ã' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x3e, /* 0011111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 196 0xc4 'Ä' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 197 0xc5 'Å' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xfe, /* 1111111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 198 0xc6 'Æ' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x3e, /* 0011111 */
+       0x30, /* 0011000 */
+       0x3e, /* 0011111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 199 0xc7 'Ç' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6e, /* 0110111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 200 0xc8 'È' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6e, /* 0110111 */
+       0x60, /* 0110000 */
+       0x7e, /* 0111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 201 0xc9 'É' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x7e, /* 0111111 */
+       0x60, /* 0110000 */
+       0x6e, /* 0110111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 202 0xca 'Ê' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xee, /* 1110111 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 203 0xcb 'Ë' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0xee, /* 1110111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 204 0xcc 'Ì' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6e, /* 0110111 */
+       0x60, /* 0110000 */
+       0x6e, /* 0110111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 205 0xcd 'Í' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 206 0xce 'Î' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xee, /* 1110111 */
+       0x00, /* 0000000 */
+       0xee, /* 1110111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 207 0xcf 'Ï' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 208 0xd0 'Ð' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 209 0xd1 'Ñ' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 210 0xd2 'Ò' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 211 0xd3 'Ó' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x7e, /* 0111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 212 0xd4 'Ô' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x3e, /* 0011111 */
+       0x30, /* 0011000 */
+       0x3e, /* 0011111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 213 0xd5 'Õ' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x3e, /* 0011111 */
+       0x30, /* 0011000 */
+       0x3e, /* 0011111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 214 0xd6 'Ö' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x7e, /* 0111111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 215 0xd7 '×' */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xfe, /* 1111111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+
+       /* 216 0xd8 'Ø' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xfe, /* 1111111 */
+       0x30, /* 0011000 */
+       0xfe, /* 1111111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 217 0xd9 'Ù' */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xf0, /* 1111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 218 0xda 'Ú' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x3e, /* 0011111 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 219 0xdb 'Û' */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+
+       /* 220 0xdc 'Ü' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+
+       /* 221 0xdd 'Ý' */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+       0xe0, /* 1110000 */
+
+       /* 222 0xde 'Þ' */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+       0x1e, /* 0001111 */
+
+       /* 223 0xdf 'ß' */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 224 0xe0 'à' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x76, /* 0111011 */
+       0xdc, /* 1101110 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0xdc, /* 1101110 */
+       0x76, /* 0111011 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 225 0xe1 'á' */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xd8, /* 1101100 */
+       0xcc, /* 1100110 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 226 0xe2 'â' */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 227 0xe3 'ã' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfe, /* 1111111 */
+       0xfe, /* 1111111 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 228 0xe4 'ä' */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 229 0xe5 'å' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x7e, /* 0111111 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0x70, /* 0111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 230 0xe6 'æ' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xf8, /* 1111100 */
+       0xc0, /* 1100000 */
+       0xc0, /* 1100000 */
+       0x80, /* 1000000 */
+
+       /* 231 0xe7 'ç' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x76, /* 0111011 */
+       0xdc, /* 1101110 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 232 0xe8 'è' */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x30, /* 0011000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x30, /* 0011000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 233 0xe9 'é' */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xfc, /* 1111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 234 0xea 'ê' */
+       0x00, /* 0000000 */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0xc6, /* 1100011 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0xee, /* 1110111 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 235 0xeb 'ë' */
+       0x00, /* 0000000 */
+       0x3c, /* 0011110 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x7c, /* 0111110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x78, /* 0111100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 236 0xec 'ì' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 237 0xed 'í' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x06, /* 0000011 */
+       0x0c, /* 0000110 */
+       0x7c, /* 0111110 */
+       0xd6, /* 1101011 */
+       0xd6, /* 1101011 */
+       0xe6, /* 1110011 */
+       0x7c, /* 0111110 */
+       0x60, /* 0110000 */
+       0xc0, /* 1100000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 238 0xee 'î' */
+       0x00, /* 0000000 */
+       0x1c, /* 0001110 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x7c, /* 0111110 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x1c, /* 0001110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 239 0xef 'ï' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0xcc, /* 1100110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 240 0xf0 'ð' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 241 0xf1 'ñ' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0xfc, /* 1111110 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 242 0xf2 'ò' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x0c, /* 0000110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 243 0xf3 'ó' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x60, /* 0110000 */
+       0xc0, /* 1100000 */
+       0x60, /* 0110000 */
+       0x30, /* 0011000 */
+       0x18, /* 0001100 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 244 0xf4 'ô' */
+       0x00, /* 0000000 */
+       0x1c, /* 0001110 */
+       0x36, /* 0011011 */
+       0x36, /* 0011011 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+
+       /* 245 0xf5 'õ' */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0x70, /* 0111000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 246 0xf6 'ö' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 247 0xf7 '÷' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x76, /* 0111011 */
+       0xdc, /* 1101110 */
+       0x00, /* 0000000 */
+       0x76, /* 0111011 */
+       0xdc, /* 1101110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 248 0xf8 'ø' */
+       0x38, /* 0011100 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x38, /* 0011100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 249 0xf9 'ù' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 250 0xfa 'ú' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x30, /* 0011000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 251 0xfb 'û' */
+       0x1e, /* 0001111 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0x18, /* 0001100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0xd8, /* 1101100 */
+       0x78, /* 0111100 */
+       0x38, /* 0011100 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 252 0xfc 'ü' */
+       0xd8, /* 1101100 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x6c, /* 0110110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 253 0xfd 'ý' */
+       0x78, /* 0111100 */
+       0xcc, /* 1100110 */
+       0x18, /* 0001100 */
+       0x30, /* 0011000 */
+       0x64, /* 0110010 */
+       0xfc, /* 1111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 254 0xfe 'þ' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x7c, /* 0111110 */
+       0x7c, /* 0111110 */
+       0x7c, /* 0111110 */
+       0x7c, /* 0111110 */
+       0x7c, /* 0111110 */
+       0x7c, /* 0111110 */
+       0x7c, /* 0111110 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+       /* 255 0xff 'ÿ' */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+       0x00, /* 0000000 */
+
+};
+
+
+struct font_desc font_7x14 = {
+       FONT7x14_IDX,
+       "7x14",
+       7,
+       14,
+       fontdata_7x14,
+       0
+};
index 05215d0c3e0951707c46747524d9bcf21e4c509a..c7bd967ea1000ed91ec4f73a73dbec2d0e8c7fbb 100644 (file)
@@ -29,24 +29,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 1 0x01 '^A' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x1f, 0xc0, /* 000111111100 */
+       0x30, 0x60, /* 001100000110 */
+       0x65, 0x30, /* 011001010011 */
+       0x6d, 0xb0, /* 011011011011 */
+       0x60, 0x30, /* 011000000011 */
+       0x62, 0x30, /* 011000100011 */
+       0x62, 0x30, /* 011000100011 */
+       0x60, 0x30, /* 011000000011 */
+       0x6f, 0xb0, /* 011011111011 */
+       0x67, 0x30, /* 011001110011 */
+       0x30, 0x60, /* 001100000110 */
+       0x1f, 0xc0, /* 000111111100 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -54,24 +53,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 2 0x02 '^B' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x1f, 0xc0, /* 000111111100 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x7a, 0xf0, /* 011110101111 */
+       0x72, 0x70, /* 011100100111 */
+       0x7f, 0xf0, /* 011111111111 */
+       0x7d, 0xf0, /* 011111011111 */
+       0x7d, 0xf0, /* 011111011111 */
+       0x7f, 0xf0, /* 011111111111 */
+       0x70, 0x70, /* 011100000111 */
+       0x78, 0xf0, /* 011110001111 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x1f, 0xc0, /* 000111111100 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -79,24 +77,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 3 0x03 '^C' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x19, 0x80, /* 000110011000 */
        0x3f, 0xc0, /* 001111111100 */
+       0x7f, 0xe0, /* 011111111110 */
        0x3f, 0xc0, /* 001111111100 */
        0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x1f, 0x80, /* 000111111000 */
+       0x1f, 0x80, /* 000111111000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x06, 0x00, /* 000001100000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -104,24 +101,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 4 0x04 '^D' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x02, 0x00, /* 000000100000 */
+       0x07, 0x00, /* 000001110000 */
+       0x0f, 0x80, /* 000011111000 */
+       0x0f, 0x80, /* 000011111000 */
+       0x1f, 0xc0, /* 000111111100 */
+       0x1f, 0xc0, /* 000111111100 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x1f, 0xc0, /* 000111111100 */
+       0x1f, 0xc0, /* 000111111100 */
+       0x0f, 0x80, /* 000011111000 */
+       0x0f, 0x80, /* 000011111000 */
+       0x07, 0x00, /* 000001110000 */
+       0x02, 0x00, /* 000000100000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -129,24 +125,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 5 0x05 '^E' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x02, 0x00, /* 000000100000 */
+       0x07, 0x00, /* 000001110000 */
+       0x07, 0x00, /* 000001110000 */
+       0x02, 0x00, /* 000000100000 */
+       0x18, 0xc0, /* 000110001100 */
+       0x3d, 0xe0, /* 001111011110 */
+       0x3d, 0xe0, /* 001111011110 */
+       0x1a, 0xc0, /* 000110101100 */
+       0x02, 0x00, /* 000000100000 */
+       0x07, 0x00, /* 000001110000 */
+       0x0f, 0x80, /* 000011111000 */
+       0x1f, 0xc0, /* 000111111100 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -154,23 +149,22 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 6 0x06 '^F' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x06, 0x00, /* 000001100000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x1f, 0x80, /* 000111111000 */
+       0x1f, 0x80, /* 000111111000 */
        0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x36, 0xc0, /* 001101101100 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x1f, 0x80, /* 000111111000 */
        0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -179,24 +173,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 7 0x07 '^G' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x06, 0x00, /* 000001100000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x1f, 0x80, /* 000111111000 */
+       0x1f, 0x80, /* 000111111000 */
        0x3f, 0xc0, /* 001111111100 */
        0x3f, 0xc0, /* 001111111100 */
+       0x1f, 0x80, /* 000111111000 */
+       0x1f, 0x80, /* 000111111000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x06, 0x00, /* 000001100000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -204,49 +197,47 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 8 0x08 '^H' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xf9, 0xf0, /* 111110011111 */
+       0xf0, 0xf0, /* 111100001111 */
+       0xf0, 0xf0, /* 111100001111 */
+       0xe0, 0x70, /* 111000000111 */
+       0xe0, 0x70, /* 111000000111 */
+       0xc0, 0x30, /* 110000000011 */
+       0xc0, 0x30, /* 110000000011 */
+       0xe0, 0x70, /* 111000000111 */
+       0xe0, 0x70, /* 111000000111 */
+       0xf0, 0xf0, /* 111100001111 */
+       0xf0, 0xf0, /* 111100001111 */
+       0xf9, 0xf0, /* 111110011111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
 
        /* 9 0x09 '^I' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x06, 0x00, /* 000001100000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x06, 0x00, /* 000001100000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -254,74 +245,71 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 10 0x0a '^J' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xf9, 0xf0, /* 111110011111 */
+       0xf0, 0xf0, /* 111100001111 */
+       0xf0, 0xf0, /* 111100001111 */
+       0xe6, 0x70, /* 111001100111 */
+       0xe6, 0x70, /* 111001100111 */
+       0xcf, 0x30, /* 110011110011 */
+       0xcf, 0x30, /* 110011110011 */
+       0xe6, 0x70, /* 111001100111 */
+       0xe6, 0x70, /* 111001100111 */
+       0xf0, 0xf0, /* 111100001111 */
+       0xf0, 0xf0, /* 111100001111 */
+       0xf9, 0xf0, /* 111110011111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
 
        /* 11 0x0b '^K' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x0f, 0xe0, /* 000011111110 */
+       0x0f, 0xe0, /* 000011111110 */
+       0x01, 0xe0, /* 000000011110 */
+       0x03, 0x60, /* 000000110110 */
+       0x06, 0x60, /* 000001100110 */
+       0x1e, 0x00, /* 000111100000 */
+       0x33, 0x00, /* 001100110000 */
+       0x33, 0x00, /* 001100110000 */
+       0x61, 0x80, /* 011000011000 */
+       0x61, 0x80, /* 011000011000 */
+       0x33, 0x00, /* 001100110000 */
+       0x33, 0x00, /* 001100110000 */
+       0x1e, 0x00, /* 000111100000 */
+       0x0c, 0x00, /* 000011000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
 
        /* 12 0x0c '^L' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x06, 0x00, /* 000001100000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x19, 0x80, /* 000110011000 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x19, 0x80, /* 000110011000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
        0x3f, 0xc0, /* 001111111100 */
        0x3f, 0xc0, /* 001111111100 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -329,149 +317,143 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 13 0x0d '^M' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x0f, 0xe0, /* 000011111110 */
+       0x0c, 0x60, /* 000011000110 */
+       0x0c, 0x60, /* 000011000110 */
+       0x0f, 0xe0, /* 000011111110 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x3c, 0x00, /* 001111000000 */
+       0x7c, 0x00, /* 011111000000 */
+       0x78, 0x00, /* 011110000000 */
+       0x30, 0x00, /* 001100000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
 
        /* 14 0x0e '^N' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x1f, 0xe0, /* 000111111110 */
+       0x18, 0x60, /* 000110000110 */
+       0x18, 0x60, /* 000110000110 */
+       0x1f, 0xe0, /* 000111111110 */
+       0x18, 0x60, /* 000110000110 */
+       0x18, 0x60, /* 000110000110 */
+       0x18, 0x60, /* 000110000110 */
+       0x18, 0x60, /* 000110000110 */
+       0x18, 0x60, /* 000110000110 */
+       0x18, 0x60, /* 000110000110 */
+       0x19, 0xe0, /* 000110011110 */
+       0x1b, 0xe0, /* 000110111110 */
+       0x1b, 0xc0, /* 000110111100 */
+       0x79, 0x80, /* 011110011000 */
+       0xf8, 0x00, /* 111110000000 */
+       0xf0, 0x00, /* 111100000000 */
+       0x60, 0x00, /* 011000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
 
        /* 15 0x0f '^O' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x18, 0xc0, /* 000110001100 */
+       0x0d, 0x80, /* 000011011000 */
+       0x6d, 0xb0, /* 011011011011 */
+       0x3d, 0xe0, /* 001111011110 */
        0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-
-       /* 16 0x10 '^P' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
+       0x3d, 0xe0, /* 001111011110 */
+       0x6d, 0xb0, /* 011011011011 */
+       0x0d, 0x80, /* 000011011000 */
+       0x18, 0xc0, /* 000110001100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+
+       /* 16 0x10 '^P' */
        0x00, 0x00, /* 000000000000 */
+       0x00, 0x20, /* 000000000010 */
+       0x00, 0x60, /* 000000000110 */
+       0x00, 0xe0, /* 000000001110 */
+       0x01, 0xe0, /* 000000011110 */
+       0x03, 0xe0, /* 000000111110 */
+       0x07, 0xe0, /* 000001111110 */
+       0x0f, 0xe0, /* 000011111110 */
+       0x1f, 0xe0, /* 000111111110 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x1f, 0xe0, /* 000111111110 */
+       0x0f, 0xe0, /* 000011111110 */
+       0x07, 0xe0, /* 000001111110 */
+       0x03, 0xe0, /* 000000111110 */
+       0x01, 0xe0, /* 000000011110 */
+       0x00, 0xe0, /* 000000001110 */
+       0x00, 0x60, /* 000000000110 */
+       0x00, 0x20, /* 000000000010 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
 
        /* 17 0x11 '^Q' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x40, 0x00, /* 010000000000 */
+       0x60, 0x00, /* 011000000000 */
+       0x70, 0x00, /* 011100000000 */
+       0x78, 0x00, /* 011110000000 */
+       0x7c, 0x00, /* 011111000000 */
+       0x7e, 0x00, /* 011111100000 */
+       0x7f, 0x00, /* 011111110000 */
+       0x7f, 0x80, /* 011111111000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x7f, 0x80, /* 011111111000 */
+       0x7f, 0x00, /* 011111110000 */
+       0x7e, 0x00, /* 011111100000 */
+       0x7c, 0x00, /* 011111000000 */
+       0x78, 0x00, /* 011110000000 */
+       0x70, 0x00, /* 011100000000 */
+       0x60, 0x00, /* 011000000000 */
+       0x40, 0x00, /* 010000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
 
        /* 18 0x12 '^R' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x04, 0x00, /* 000001000000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x3f, 0x80, /* 001111111000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x3f, 0x80, /* 001111111000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x04, 0x00, /* 000001000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -551,99 +533,95 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 22 0x16 '^V' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-
-       /* 23 0x17 '^W' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
 
-       /* 24 0x18 '^X' */
-       /* FIXME */
+       /* 23 0x17 '^W' */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x04, 0x00, /* 000001000000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x3f, 0x80, /* 001111111000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x3f, 0x80, /* 001111111000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x04, 0x00, /* 000001000000 */
        0x00, 0x00, /* 000000000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+
+       /* 24 0x18 '^X' */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-
-       /* 25 0x19 '^Y' */
-       /* FIXME */
+       0x04, 0x00, /* 000001000000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x3f, 0x80, /* 001111111000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+
+       /* 25 0x19 '^Y' */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x3f, 0x80, /* 001111111000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x04, 0x00, /* 000001000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -651,24 +629,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 26 0x1a '^Z' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+       0x08, 0x00, /* 000010000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x38, 0x00, /* 001110000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0xff, 0xe0, /* 111111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x38, 0x00, /* 001110000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x08, 0x00, /* 000010000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -676,24 +653,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 27 0x1b '^[' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+       0x01, 0x00, /* 000000010000 */
+       0x01, 0x80, /* 000000011000 */
+       0x01, 0xc0, /* 000000011100 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xf0, /* 011111111111 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x01, 0xc0, /* 000000011100 */
+       0x01, 0x80, /* 000000011000 */
+       0x01, 0x00, /* 000000010000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -701,24 +677,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 28 0x1c '^\' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x3f, 0xe0, /* 001111111110 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -726,24 +701,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 29 0x1d '^]' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+       0x09, 0x00, /* 000010010000 */
+       0x19, 0x80, /* 000110011000 */
+       0x39, 0xc0, /* 001110011100 */
+       0x7f, 0xe0, /* 011111111110 */
+       0xff, 0xf0, /* 111111111111 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x39, 0xc0, /* 001110011100 */
+       0x19, 0x80, /* 000110011000 */
+       0x09, 0x00, /* 000010010000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -751,24 +725,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 30 0x1e '^^' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+       0x04, 0x00, /* 000001000000 */
+       0x04, 0x00, /* 000001000000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x3f, 0x80, /* 001111111000 */
+       0x3f, 0x80, /* 001111111000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -776,24 +749,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 31 0x1f '^_' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x3f, 0x80, /* 001111111000 */
+       0x3f, 0x80, /* 001111111000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x04, 0x00, /* 000001000000 */
+       0x04, 0x00, /* 000001000000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -3081,29 +3053,28 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 127 0x7f '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0xff, 0xf0, /* 111111111111 */
+       0xff, 0xf0, /* 111111111111 */
+       0x00, 0x00, /* 000000000000 */
 
        /* 128 0x80 '.' */
        0x00, 0x00, /* 000000000000 */
@@ -3826,24 +3797,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 158 0x9e '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x7f, 0x80, /* 011111111000 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0x60, /* 001100000110 */
+       0x30, 0x60, /* 001100000110 */
+       0x30, 0x60, /* 001100000110 */
+       0x30, 0xc0, /* 001100001100 */
+       0x37, 0x80, /* 001101111000 */
+       0x30, 0x00, /* 001100000000 */
+       0x33, 0x00, /* 001100110000 */
+       0x37, 0x80, /* 001101111000 */
+       0x33, 0x00, /* 001100110000 */
+       0x33, 0x00, /* 001100110000 */
+       0x33, 0x30, /* 001100110011 */
+       0x31, 0xe0, /* 001100011110 */
+       0x78, 0xc0, /* 011110001100 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -3851,28 +3821,27 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 159 0x9f '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x00, 0xc0, /* 000000001100 */
+       0x01, 0xe0, /* 000000011110 */
+       0x03, 0x30, /* 000000110011 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x7f, 0xc0, /* 011111111100 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0xcc, 0x00, /* 110011000000 */
+       0x78, 0x00, /* 011110000000 */
+       0x30, 0x00, /* 001100000000 */
        0x00, 0x00, /* 000000000000 */
 
        /* 160 0xa0 '.' */
@@ -4092,24 +4061,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 169 0xa9 '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x3f, 0xc0, /* 001111111100 */
        0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5413,24 +5381,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 224 0xe0 '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+       0x0f, 0x60, /* 000011110110 */
+       0x13, 0xe0, /* 000100111110 */
+       0x21, 0xc0, /* 001000011100 */
+       0x60, 0xc0, /* 011000001100 */
+       0x60, 0xc0, /* 011000001100 */
+       0x60, 0xc0, /* 011000001100 */
+       0x60, 0xc0, /* 011000001100 */
+       0x70, 0x80, /* 011100001000 */
+       0x39, 0xc0, /* 001110011100 */
+       0x1f, 0x60, /* 000111110110 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5462,24 +5429,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 226 0xe2 '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x3f, 0xe0, /* 001111111110 */
+       0x30, 0x60, /* 001100000110 */
+       0x30, 0x60, /* 001100000110 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5487,49 +5453,47 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 227 0xe3 '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-
-       /* 228 0xe4 '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+
+       /* 228 0xe4 '.' */
        0x00, 0x00, /* 000000000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x60, 0x60, /* 011000000110 */
+       0x30, 0x60, /* 001100000110 */
+       0x30, 0x00, /* 001100000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x60, /* 001100000110 */
+       0x60, 0x60, /* 011000000110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5537,24 +5501,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 229 0xe5 '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x07, 0xe0, /* 000001111110 */
+       0x0f, 0xe0, /* 000011111110 */
+       0x13, 0x80, /* 000100111000 */
+       0x21, 0xc0, /* 001000011100 */
+       0x60, 0xc0, /* 011000001100 */
+       0x60, 0xc0, /* 011000001100 */
+       0x60, 0xc0, /* 011000001100 */
+       0x60, 0xc0, /* 011000001100 */
+       0x70, 0x80, /* 011100001000 */
+       0x39, 0x00, /* 001110010000 */
+       0x1e, 0x00, /* 000111100000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5586,24 +5549,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 231 0xe7 '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x19, 0x80, /* 000110011000 */
        0x3f, 0xc0, /* 001111111100 */
+       0x66, 0x60, /* 011001100110 */
+       0x66, 0x60, /* 011001100110 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5611,24 +5573,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 232 0xe8 '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x19, 0x80, /* 000110011000 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x19, 0x80, /* 000110011000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5636,24 +5597,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 233 0xe9 '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x0f, 0x00, /* 000011110000 */
+       0x1f, 0x80, /* 000111111000 */
+       0x30, 0xc0, /* 001100001100 */
+       0x60, 0x60, /* 011000000110 */
+       0x60, 0x60, /* 011000000110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x60, 0x60, /* 011000000110 */
+       0x60, 0x60, /* 011000000110 */
+       0x30, 0xc0, /* 001100001100 */
+       0x1f, 0x80, /* 000111111000 */
+       0x0f, 0x00, /* 000011110000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5661,24 +5621,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 234 0xea '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x1f, 0x00, /* 000111110000 */
+       0x31, 0x80, /* 001100011000 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x60, 0x60, /* 011000000110 */
+       0x60, 0x60, /* 011000000110 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x19, 0x80, /* 000110011000 */
+       0x19, 0x80, /* 000110011000 */
+       0xd9, 0xb0, /* 110110011011 */
+       0x79, 0xe0, /* 011110011110 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5686,24 +5645,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 235 0xeb '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x07, 0x80, /* 000001111000 */
+       0x0c, 0xc0, /* 000011001100 */
+       0x18, 0x60, /* 000110000110 */
+       0x18, 0x00, /* 000110000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x06, 0x00, /* 000001100000 */
+       0x03, 0x00, /* 000000110000 */
+       0x0f, 0x80, /* 000011111000 */
+       0x11, 0xc0, /* 000100011100 */
+       0x20, 0xe0, /* 001000001110 */
+       0x60, 0x60, /* 011000000110 */
+       0x60, 0x60, /* 011000000110 */
+       0x70, 0x40, /* 011100000100 */
+       0x38, 0x80, /* 001110001000 */
+       0x1f, 0x00, /* 000111110000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5711,74 +5669,71 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 236 0xec '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x39, 0xc0, /* 001110011100 */
+       0x6f, 0x60, /* 011011110110 */
+       0x66, 0x60, /* 011001100110 */
+       0xc6, 0x30, /* 110001100011 */
+       0xc6, 0x30, /* 110001100011 */
+       0x66, 0x60, /* 011001100110 */
+       0x6f, 0x60, /* 011011110110 */
+       0x39, 0xc0, /* 001110011100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-
-       /* 237 0xed '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+
+       /* 237 0xed '.' */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x00, 0xc0, /* 000000001100 */
+       0x00, 0xc0, /* 000000001100 */
+       0x01, 0x80, /* 000000011000 */
+       0x01, 0x80, /* 000000011000 */
+       0x3b, 0xc0, /* 001110111100 */
+       0x6f, 0x60, /* 011011110110 */
+       0x66, 0x60, /* 011001100110 */
+       0xc6, 0x30, /* 110001100011 */
+       0xc6, 0x30, /* 110001100011 */
+       0x66, 0x60, /* 011001100110 */
+       0x6f, 0x60, /* 011011110110 */
+       0x3d, 0xc0, /* 001111011100 */
+       0x18, 0x00, /* 000110000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x30, 0x00, /* 001100000000 */
+       0x30, 0x00, /* 001100000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
 
        /* 238 0xee '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x01, 0xc0, /* 000000011100 */
+       0x03, 0x00, /* 000000110000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x1f, 0xc0, /* 000111111100 */
+       0x18, 0x00, /* 000110000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x03, 0x00, /* 000000110000 */
+       0x01, 0xc0, /* 000000011100 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5786,24 +5741,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 239 0xef '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x0f, 0x00, /* 000011110000 */
+       0x1f, 0x80, /* 000111111000 */
+       0x39, 0xc0, /* 001110011100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
+       0x30, 0xc0, /* 001100001100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5811,24 +5765,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 240 0xf0 '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5860,24 +5813,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 242 0xf2 '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x60, 0x00, /* 011000000000 */
+       0x38, 0x00, /* 001110000000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x03, 0x80, /* 000000111000 */
+       0x00, 0xe0, /* 000000001110 */
+       0x00, 0xe0, /* 000000001110 */
+       0x03, 0x80, /* 000000111000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x38, 0x00, /* 001110000000 */
+       0x60, 0x00, /* 011000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5885,24 +5837,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 243 0xf3 '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x00, 0x60, /* 000000000110 */
+       0x01, 0xc0, /* 000000011100 */
+       0x07, 0x00, /* 000001110000 */
+       0x1c, 0x00, /* 000111000000 */
+       0x70, 0x00, /* 011100000000 */
+       0x70, 0x00, /* 011100000000 */
+       0x1c, 0x00, /* 000111000000 */
+       0x07, 0x00, /* 000001110000 */
+       0x01, 0xc0, /* 000000011100 */
+       0x00, 0x60, /* 000000000110 */
        0x00, 0x00, /* 000000000000 */
+       0x7f, 0xe0, /* 011111111110 */
+       0x7f, 0xe0, /* 011111111110 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -5910,54 +5861,52 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 244 0xf4 '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x03, 0x80, /* 000000111000 */
+       0x07, 0xc0, /* 000001111100 */
+       0x0c, 0x60, /* 000011000110 */
+       0x0c, 0x60, /* 000011000110 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
+       0x0c, 0x00, /* 000011000000 */
 
        /* 245 0xf5 '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x1c, 0x00, /* 000111000000 */
+       0x3e, 0x00, /* 001111100000 */
+       0x63, 0x00, /* 011000110000 */
+       0x63, 0x00, /* 011000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
+       0x03, 0x00, /* 000000110000 */
 
        /* 246 0xf6 '.' */
        0x00, 0x00, /* 000000000000 */
@@ -5984,24 +5933,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 247 0xf7 '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x38, 0x00, /* 001110000000 */
+       0x6c, 0x00, /* 011011000000 */
+       0x06, 0x30, /* 000001100011 */
+       0x03, 0x60, /* 000000110110 */
+       0x39, 0xc0, /* 001110011100 */
+       0x6c, 0x00, /* 011011000000 */
+       0x06, 0x30, /* 000001100011 */
+       0x03, 0x60, /* 000000110110 */
+       0x01, 0xc0, /* 000000011100 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -6033,44 +5981,31 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
 
        /* 249 0xf9 '.' */
-       /* FIXME */
-       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-
-       /* 250 0xfa '.' */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x1c, 0x00, /* 000111000000 */
+       0x3e, 0x00, /* 001111100000 */
+       0x3e, 0x00, /* 001111100000 */
+       0x3e, 0x00, /* 001111100000 */
+       0x1c, 0x00, /* 000111000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+
+       /* 250 0xfa '.' */
        0x00, 0x00, /* 000000000000 */
-       0x06, 0x00, /* 000001100000 */
-       0x0f, 0x00, /* 000011110000 */
-       0x0f, 0x00, /* 000011110000 */
-       0x06, 0x00, /* 000001100000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -6080,51 +6015,61 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-
-       /* 251 0xfb '.' */
-       /* FIXME */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+       0x18, 0x00, /* 000110000000 */
+       0x3c, 0x00, /* 001111000000 */
+       0x3c, 0x00, /* 001111000000 */
+       0x18, 0x00, /* 000110000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
+
+       /* 251 0xfb '.' */
        0x00, 0x00, /* 000000000000 */
+       0x07, 0xe0, /* 000001111110 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x06, 0x00, /* 000001100000 */
+       0xc6, 0x00, /* 110001100000 */
+       0x66, 0x00, /* 011001100000 */
+       0x36, 0x00, /* 001101100000 */
+       0x1e, 0x00, /* 000111100000 */
+       0x0e, 0x00, /* 000011100000 */
+       0x06, 0x00, /* 000001100000 */
+       0x02, 0x00, /* 000000100000 */
        0x00, 0x00, /* 000000000000 */
 
        /* 252 0xfc '.' */
-       /* FIXME */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x13, 0x80, /* 000100111000 */
+       0x3d, 0xc0, /* 001111011100 */
+       0x18, 0xc0, /* 000110001100 */
+       0x18, 0xc0, /* 000110001100 */
+       0x18, 0xc0, /* 000110001100 */
+       0x18, 0xc0, /* 000110001100 */
+       0x3d, 0xe0, /* 001111011110 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
+       0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
-       0x3f, 0xc0, /* 001111111100 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
index 465d678230ae84adefdd7a8ba1386a61a8258652..e79b297026490531dc39fdd4767f7ca319aa4772 100644 (file)
@@ -36,6 +36,10 @@ static struct font_desc *fonts[] = {
 #undef NO_FONTS
     &font_vga_6x11,
 #endif
+#ifdef CONFIG_FONT_7x14
+#undef NO_FONTS
+    &font_7x14,
+#endif
 #ifdef CONFIG_FONT_SUN8x16
 #undef NO_FONTS
     &font_sun_8x16,
@@ -44,6 +48,10 @@ static struct font_desc *fonts[] = {
 #undef NO_FONTS
     &font_sun_12x22,
 #endif
+#ifdef CONFIG_FONT_10x18
+#undef NO_FONTS
+    &font_10x18,
+#endif
 #ifdef CONFIG_FONT_ACORN_8x8
 #undef NO_FONTS
     &font_acorn_8x8,
index bcf59b28a14f33953bfc4fc10060ec340d479346..d27fa91e58869edf4e834b7d7a5b43ae01f8292c 100644 (file)
@@ -95,6 +95,7 @@ static unsigned long vgacon_uni_pagedir[2];
 /* Description of the hardware situation */
 static unsigned long   vga_vram_base;          /* Base of video memory */
 static unsigned long   vga_vram_end;           /* End of video memory */
+static int             vga_vram_size;          /* Size of video memory */
 static u16             vga_video_port_reg;     /* Video register select port */
 static u16             vga_video_port_val;     /* Video register value port */
 static unsigned int    vga_video_num_columns;  /* Number of text columns */
@@ -288,6 +289,7 @@ static const char __init *vgacon_startup(void)
 
        vga_vram_base = VGA_MAP_MEM(vga_vram_base);
        vga_vram_end = VGA_MAP_MEM(vga_vram_end);
+       vga_vram_size = vga_vram_end - vga_vram_base;
 
        /*
         *      Find out if there is a graphics card present.
@@ -504,9 +506,13 @@ static int vgacon_switch(struct vc_data *c)
         */
        vga_video_num_columns = c->vc_cols;
        vga_video_num_lines = c->vc_rows;
+
+       /* We can only copy out the size of the video buffer here,
+        * otherwise we get into VGA BIOS */
+
        if (!vga_is_gfx)
                scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
-                           c->vc_screenbuf_size);
+                           c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
        return 0;               /* Redrawing not needed */
 }
 
@@ -961,7 +967,6 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
        if (!lines)             /* Turn scrollback off */
                c->vc_visible_origin = c->vc_origin;
        else {
-               int vram_size = vga_vram_end - vga_vram_base;
                int margin = c->vc_size_row * 4;
                int ul, we, p, st;
 
@@ -971,7 +976,7 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
                        we = vga_rolled_over + c->vc_size_row;
                } else {
                        ul = 0;
-                       we = vram_size;
+                       we = vga_vram_size;
                }
                p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
                    lines * c->vc_size_row;
@@ -1012,9 +1017,13 @@ static void vgacon_save_screen(struct vc_data *c)
                c->vc_x = ORIG_X;
                c->vc_y = ORIG_Y;
        }
+
+       /* We can't copy in more then the size of the video buffer,
+        * or we'll be copying in VGA BIOS */
+
        if (!vga_is_gfx)
                scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
-                           c->vc_screenbuf_size);
+                           c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
 }
 
 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
index 8cef020d1801e9f075cd74a60db45f5318b04321..2222de6ad8446b8d77ec879cf04ecface133fa83 100644 (file)
@@ -76,70 +76,22 @@ int fb_get_color_depth(struct fb_var_screeninfo *var)
 EXPORT_SYMBOL(fb_get_color_depth);
 
 /*
- * Drawing helpers.
+ * Data padding functions.
  */
-void fb_iomove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
-                          u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-                          u32 height)
+void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
 {
        int i;
 
        for (i = height; i--; ) {
-               buf->outbuf(info, dst, src, s_pitch);
+               memcpy(dst, src, s_pitch);
                src += s_pitch;
                dst += d_pitch;
        }
 }
+EXPORT_SYMBOL(fb_pad_aligned_buffer);
 
-void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
-                           u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-                           u32 height)
-{
-       int i, j;
-
-       for (i = height; i--; ) {
-               for (j = 0; j < s_pitch; j++)
-                       dst[j] = src[j];
-               src += s_pitch;
-               dst += d_pitch;
-       }
-}
-
-void fb_iomove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
-                            u8 *dst, u32 d_pitch, u8 *src, u32 idx,
-                            u32 height, u32 shift_high, u32 shift_low,
-                            u32 mod)
-{
-       u8 mask = (u8) (0xfff << shift_high), tmp;
-       int i, j;
-
-       for (i = height; i--; ) {
-               for (j = 0; j < idx; j++) {
-                       tmp = buf->inbuf(info, dst+j);
-                       tmp &= mask;
-                       tmp |= *src >> shift_low;
-                       buf->outbuf(info, dst+j, &tmp, 1);
-                       tmp = *src << shift_high;
-                       buf->outbuf(info, dst+j+1, &tmp, 1);
-                       src++;
-               }
-               tmp = buf->inbuf(info, dst+idx);
-               tmp &= mask;
-               tmp |= *src >> shift_low;
-               buf->outbuf(info, dst+idx, &tmp, 1);
-               if (shift_high < mod) {
-                       tmp = *src << shift_high;
-                       buf->outbuf(info, dst+idx+1, &tmp, 1);
-               }       
-               src++;
-               dst += d_pitch;
-       }
-}
-
-void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
-                             u8 *dst, u32 d_pitch, u8 *src, u32 idx,
-                             u32 height, u32 shift_high, u32 shift_low,
-                             u32 mod)
+void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
+                               u32 shift_high, u32 shift_low, u32 mod)
 {
        u8 mask = (u8) (0xfff << shift_high), tmp;
        int i, j;
@@ -166,6 +118,7 @@ void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
                dst += d_pitch;
        }
 }
+EXPORT_SYMBOL(fb_pad_unaligned_buffer);
 
 /*
  * we need to lock this section since fb_cursor
@@ -1081,7 +1034,7 @@ register_framebuffer(struct fb_info *fb_info)
                        fb_info->pixmap.size = FBPIXMAPSIZE;
                        fb_info->pixmap.buf_align = 1;
                        fb_info->pixmap.scan_align = 1;
-                       fb_info->pixmap.access_align = 4;
+                       fb_info->pixmap.access_align = 32;
                        fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
                }
        }       
@@ -1357,10 +1310,6 @@ EXPORT_SYMBOL(fb_set_var);
 EXPORT_SYMBOL(fb_blank);
 EXPORT_SYMBOL(fb_pan_display);
 EXPORT_SYMBOL(fb_get_buffer_offset);
-EXPORT_SYMBOL(fb_iomove_buf_unaligned);
-EXPORT_SYMBOL(fb_iomove_buf_aligned);
-EXPORT_SYMBOL(fb_sysmove_buf_unaligned);
-EXPORT_SYMBOL(fb_sysmove_buf_aligned);
 EXPORT_SYMBOL(fb_set_suspend);
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
index a9a618f2aa6a25316522c16f8649d13ba52eec34..7513fb9b19cf739cc41afaf888efb0edae722587 100644 (file)
@@ -1885,6 +1885,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
        memset(info->pixmap.addr, 0, 8*1024);
        info->pixmap.size = 8*1024;
        info->pixmap.buf_align = 8;
+       info->pixmap.access_align = 32;
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
        if ((err = i810_allocate_pci_resource(par, entry))) {
index 25f9a9a65c24938c23ebd3e0fb9ad164022baacd..298bc9cd99e7f59772a8d551307ec3b9d77032d4 100644 (file)
@@ -214,7 +214,7 @@ static struct fb_ops intel_fb_ops = {
 
 /* PCI driver module table */
 static struct pci_driver intelfb_driver = {
-       .name =         "Intel(R) " SUPPORTED_CHIPSETS " Framebuffer Driver",
+       .name =         "intelfb",
        .id_table =     intelfb_pci_table,
        .probe =        intelfb_pci_register,
        .remove =       __devexit_p(intelfb_pci_unregister)
@@ -238,12 +238,15 @@ static int noregister   = 0;
 static int probeonly    = 0;
 static int idonly       = 0;
 static int bailearly    = 0;
+static int voffset     = 48;
 static char *mode       = NULL;
 
 module_param(accel, bool, S_IRUGO);
 MODULE_PARM_DESC(accel, "Enable console acceleration");
 module_param(vram, int, S_IRUGO);
 MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
+module_param(voffset, int, S_IRUGO);
+MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
 module_param(hwcursor, bool, S_IRUGO);
 MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
 module_param(mtrr, bool, S_IRUGO);
@@ -503,6 +506,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct agp_bridge_data *bridge;
        int aperture_bar = 0;
        int mmio_bar = 1;
+       int offset;
 
        DBG_MSG("intelfb_pci_register\n");
 
@@ -659,17 +663,21 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
+       if (MB(voffset) < stolen_size)
+               offset = (stolen_size >> 12);
+       else
+               offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
+
        /* set the mem offsets - set them after the already used pages */
        if (dinfo->accel) {
-               dinfo->ring.offset = (stolen_size >> 12)
-                       + gtt_info.current_memory;
+               dinfo->ring.offset = offset + gtt_info.current_memory;
        }
        if (dinfo->hwcursor) {
-               dinfo->cursor.offset = (stolen_size >> 12) +
+               dinfo->cursor.offset = offset +
                        + gtt_info.current_memory + (dinfo->ring.size >> 12);
        }
        if (dinfo->fbmem_gart) {
-               dinfo->fb.offset = (stolen_size >> 12) +
+               dinfo->fb.offset = offset +
                        + gtt_info.current_memory + (dinfo->ring.size >> 12)
                        + (dinfo->cursor.size >> 12);
        }
@@ -1083,6 +1091,7 @@ intelfb_set_fbinfo(struct intelfb_info *dinfo)
 
        info->pixmap.size = 64*1024;
        info->pixmap.buf_align = 8;
+       info->pixmap.access_align = 32;
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
        if (intelfb_init_var(dinfo))
@@ -1293,7 +1302,7 @@ intelfb_set_par(struct fb_info *info)
 
        intelfb_blank(FB_BLANK_POWERDOWN, info);
 
-       if (dinfo->accel)
+       if (ACCEL(dinfo, info))
                intelfbhw_2d_stop(dinfo);
 
        memcpy(hw, &dinfo->save_state, sizeof(*hw));
@@ -1309,7 +1318,7 @@ intelfb_set_par(struct fb_info *info)
 
        update_dinfo(dinfo, &info->var);
 
-       if (dinfo->accel)
+       if (ACCEL(dinfo, info))
                intelfbhw_2d_start(dinfo);
 
        intelfb_pan_display(&info->var, info);
index e529841cd83d2823899998bcc61b3c9bee79d81c..67f85344f0cc3d3e70edd617e76080788ddfef04 100644 (file)
@@ -1230,7 +1230,6 @@ static int maven_shutdown_client(struct i2c_client* clnt) {
 }
 
 static unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { MAVEN_I2CID, MAVEN_I2CID, I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 static struct i2c_driver maven_driver;
index 47733f58153bd4d8bb856dcc69d98e4e86492a95..b2e6b240786917d9c1cae810a76729d3ff2c0686 100644 (file)
@@ -516,9 +516,9 @@ static struct backlight_controller nvidia_backlight_controller = {
 static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
                                       u16 bg, u16 fg, u32 w, u32 h)
 {
+       u32 *data = (u32 *) data8;
        int i, j, k = 0;
        u32 b, tmp;
-       u32 *data = (u32 *) data8;
 
        w = (w + 1) & ~1;
 
@@ -890,11 +890,11 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
        struct nvidia_par *par = info->par;
        u8 data[MAX_CURS * MAX_CURS / 8];
-       u16 fg, bg;
        int i, set = cursor->set;
+       u16 fg, bg;
 
        if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
-               return soft_cursor(info, cursor);
+               return -ENXIO;
 
        NVShowHideCursor(par, 0);
 
@@ -931,21 +931,18 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
                if (src) {
                        switch (cursor->rop) {
                        case ROP_XOR:
-                               for (i = 0; i < s_pitch * cursor->image.height;
-                                    i++)
+                               for (i = 0; i < s_pitch * cursor->image.height; i++)
                                        src[i] = dat[i] ^ msk[i];
                                break;
                        case ROP_COPY:
                        default:
-                               for (i = 0; i < s_pitch * cursor->image.height;
-                                    i++)
+                               for (i = 0; i < s_pitch * cursor->image.height; i++)
                                        src[i] = dat[i] & msk[i];
                                break;
                        }
 
-                       fb_sysmove_buf_aligned(info, &info->pixmap, data,
-                                              d_pitch, src, s_pitch,
-                                              cursor->image.height);
+                       fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+                                               cursor->image.height);
 
                        bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
                            ((info->cmap.green[bg_idx] & 0xf8) << 2) |
@@ -1348,6 +1345,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
 
        info->pixmap.scan_align = 4;
        info->pixmap.buf_align = 4;
+       info->pixmap.access_align = 32;
        info->pixmap.size = 8 * 1024;
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
index 8e024aad1b5733a30c39019cebe80e46d2a37459..e0dad948467b32cc921f742f5abbefb5d28b4674 100644 (file)
@@ -5,7 +5,7 @@
  *  Based on code written by:
  *           Sven Luther, <luther@dpt-info.u-strasbg.fr>
  *           Alan Hourihane, <alanh@fairlite.demon.co.uk>
- *           Russel King, <rmk@arm.linux.org.uk>
+ *           Russell King, <rmk@arm.linux.org.uk>
  *  Based on linux/drivers/video/skeletonfb.c:
  *     Copyright (C) 1997 Geert Uytterhoeven
  *  Based on linux/driver/video/pm2fb.c:
index b0c886de04043c1ad872377e3739a0f48f3d34a2..6a9e183be41b7f53f0ce74afc18abfa03fcac1cc 100644 (file)
@@ -1582,12 +1582,11 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
        struct riva_par *par = (struct riva_par *) info->par;
        u8 data[MAX_CURS * MAX_CURS/8];
-       u16 fg, bg;
        int i, set = cursor->set;
+       u16 fg, bg;
 
-       if (cursor->image.width > MAX_CURS ||
-           cursor->image.height > MAX_CURS)
-               return soft_cursor(info, cursor);
+       if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+               return -ENXIO;
 
        par->riva.ShowHideCursor(&par->riva, 0);
 
@@ -1625,21 +1624,18 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
                if (src) {
                        switch (cursor->rop) {
                        case ROP_XOR:
-                               for (i = 0; i < s_pitch * cursor->image.height;
-                                    i++)
+                               for (i = 0; i < s_pitch * cursor->image.height; i++)
                                        src[i] = dat[i] ^ msk[i];
                                break;
                        case ROP_COPY:
                        default:
-                               for (i = 0; i < s_pitch * cursor->image.height;
-                                    i++)
+                               for (i = 0; i < s_pitch * cursor->image.height; i++)
                                        src[i] = dat[i] & msk[i];
                                break;
                        }
 
-                       fb_sysmove_buf_aligned(info, &info->pixmap, data,
-                                              d_pitch, src, s_pitch,
-                                              cursor->image.height);
+                       fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+                                               cursor->image.height);
 
                        bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
                                ((info->cmap.green[bg_idx] & 0xf8) << 2) |
@@ -1727,6 +1723,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
 
        info->pixmap.size = 8 * 1024;
        info->pixmap.buf_align = 4;
+       info->pixmap.access_align = 32;
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
        info->var.yres_virtual = -1;
        NVTRACE_LEAVE();
index b637c389e4f480945c5c9f8b0775605496bd6d25..789de13f461f689280e2b94c78b50c18387bfe0f 100644 (file)
@@ -493,7 +493,7 @@ s1d13xxxfb_fetch_hw_state(struct fb_info *info)
 }
 
 
-static int __devexit
+static int
 s1d13xxxfb_remove(struct device *dev)
 {
        struct fb_info *info = dev_get_drvdata(dev);
index 03d74e8ee06777f8991591a61bc2812c2843c775..8fadcdae6f426216200ed6659dd3cfbca031e57f 100644 (file)
@@ -1897,7 +1897,7 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
                info->pixmap.size = 8*1024;
                info->pixmap.scan_align = 4;
                info->pixmap.buf_align = 4;
-               info->pixmap.access_align = 4;
+               info->pixmap.access_align = 32;
 
                fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
                info->flags |= FBINFO_HWACCEL_COPYAREA |
index 13a4511539a15b548e0e065eb37fa2f158d9c715..229c4bc350798c45f103a475f11f80a5e3f16dfe 100644 (file)
@@ -58,17 +58,10 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
        } else 
                memcpy(src, image->data, dsize);
        
-       if (info->pixmap.outbuf)
-               fb_iomove_buf_aligned(info, &info->pixmap, dst, d_pitch, src,
-                                 s_pitch, image->height);
-       else
-               fb_sysmove_buf_aligned(info, &info->pixmap, dst, d_pitch, src,
-                                  s_pitch, image->height);
-
+       fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height);
        image->data = dst;
        info->fbops->fb_imageblit(info, image);
        kfree(src);
-
        return 0;
 }
 
index 3027841f9c2466eb17b4b0bcb779dc11029fdc2d..f3069b01e248efa1eaf86e00fec16ff6047fc048 100644 (file)
@@ -271,7 +271,7 @@ static int __init vesafb_probe(struct device *device)
 
        if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
                printk(KERN_WARNING
-                      "vesafb: abort, cannot reserve video memory at 0x%lx\n",
+                      "vesafb: cannot reserve video memory at 0x%lx\n",
                        vesafb_fix.smem_start);
                /* We cannot make this fatal. Sometimes this comes from magic
                   spaces our resource handlers simply don't know about */
@@ -279,13 +279,13 @@ static int __init vesafb_probe(struct device *device)
 
        info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
        if (!info) {
-               release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len);
+               release_mem_region(vesafb_fix.smem_start, size_total);
                return -ENOMEM;
        }
        info->pseudo_palette = info->par;
        info->par = NULL;
 
-        info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
+       info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
        if (!info->screen_base) {
                printk(KERN_ERR
                       "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
@@ -386,7 +386,7 @@ static int __init vesafb_probe(struct device *device)
        request_region(0x3c0, 32, "vesafb");
 
        if (mtrr) {
-               int temp_size = size_total;
+               unsigned int temp_size = size_total;
                /* Find the largest power-of-two */
                while (temp_size & (temp_size - 1))
                        temp_size &= (temp_size - 1);
index 2ab65c902fe58a3c151bf7421a3d78c5553cf7a6..4f120796273ee033b2cb694c2664b594833fd28a 100644 (file)
@@ -3,9 +3,9 @@ menu "Dallas's 1-wire bus"
 config W1
        tristate "Dallas's 1-wire support"
        ---help---
-         Dallas's 1-wire bus is usefull to connect slow 1-pin devices 
+         Dallas's 1-wire bus is usefull to connect slow 1-pin devices
          such as iButtons and thermal sensors.
-         
+
          If you want W1 support, you should say Y here.
 
          This W1 support can also be built as a module.  If so, the module
@@ -17,8 +17,8 @@ config W1_MATROX
        help
          Say Y here if you want to communicate with your 1-wire devices
          using Matrox's G400 GPIO pins.
-         
-         This support is also available as a module.  If so, the module 
+
+         This support is also available as a module.  If so, the module
          will be called matrox_w1.ko.
 
 config W1_DS9490
@@ -27,17 +27,17 @@ config W1_DS9490
        help
          Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
 
-         This support is also available as a module.  If so, the module 
+         This support is also available as a module.  If so, the module
          will be called ds9490r.ko.
 
-config W1_DS9490_BRIDGE
+config W1_DS9490R_BRIDGE
        tristate "DS9490R USB <-> W1 transport layer for 1-wire"
        depends on W1_DS9490
        help
          Say Y here if you want to communicate with your 1-wire devices
          using DS9490R USB bridge.
 
-         This support is also available as a module.  If so, the module 
+         This support is also available as a module.  If so, the module
          will be called ds_w1_bridge.ko.
 
 config W1_THERM
@@ -51,7 +51,7 @@ config W1_SMEM
        tristate "Simple 64bit memory family implementation"
        depends on W1
        help
-         Say Y here if you want to connect 1-wire 
+         Say Y here if you want to connect 1-wire
          simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
 
 endmenu
index 0baaeb5fd630e134f33f75e7ed1247fd9132224d..7bddd8ac7d7f7a615c3fe5e71b1078e244875719 100644 (file)
@@ -83,11 +83,11 @@ static u8 ds9490r_read_byte(unsigned long data)
        return byte;
 }
 
-static void ds9490r_write_block(unsigned long data, u8 *buf, int len)
+static void ds9490r_write_block(unsigned long data, const u8 *buf, int len)
 {
        struct ds_device *dev = (struct ds_device *)data;
 
-       ds_write_block(dev, buf, len);
+       ds_write_block(dev, (u8 *)buf, len);
 }
 
 static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
index e565416458eadce0d2425e7e63c025cece6f35a7..0b03f8f93f634e3459c946287bbed20089900173 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     matrox_w1.c
+ *     matrox_w1.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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 @@ static struct pci_driver matrox_w1_pci_driver = {
        .remove = __devexit_p(matrox_w1_remove),
 };
 
-/* 
+/*
  * Matrox G400 DDC registers.
  */
 
@@ -177,8 +177,8 @@ static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_devi
 
        dev->bus_master = (struct w1_bus_master *)(dev + 1);
 
-       /* 
-        * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c 
+       /*
+        * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c
         */
 
        dev->phys_addr = pci_resource_start(pdev, 1);
index 24a192e3b8b40695bcc957e796408873a76ecfe9..b460927ec32ad78432660372a7fa20ab49dedfef 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1.c
+ *     w1.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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,6 +59,19 @@ static pid_t control_thread;
 static int control_needs_exit;
 static DECLARE_COMPLETION(w1_control_complete);
 
+/* stuff for the default family */
+static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+       return(sprintf(buf, "%s\n", sl->name));
+}
+static struct w1_family_ops w1_default_fops = {
+       .rname = &w1_famdefault_read_name,
+};
+static struct w1_family w1_default_family = {
+       .fops = &w1_default_fops,
+};
+
 static int w1_master_match(struct device *dev, struct device_driver *drv)
 {
        return 1;
@@ -99,6 +112,20 @@ static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
        return sprintf(buf, "No family registered.\n");
 }
 
+static struct device_attribute w1_slave_attribute =
+       __ATTR(name, S_IRUGO, w1_default_read_name, NULL);
+
+static struct bin_attribute w1_slave_bin_attribute = {
+       .attr = {
+               .name = "w1_slave",
+               .mode = S_IRUGO,
+               .owner = THIS_MODULE,
+       },
+       .size = W1_SLAVE_DATA_SIZE,
+       .read = &w1_default_read_bin,
+};
+
+
 static struct bus_type w1_bus_type = {
        .name = "w1",
        .match = w1_master_match,
@@ -119,34 +146,49 @@ struct device w1_device = {
        .release = &w1_master_release
 };
 
-static struct device_attribute w1_slave_attribute = {
-       .attr = {
-                       .name = "name",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE
-       },
-       .show = &w1_default_read_name,
-};
-
-static struct device_attribute w1_slave_attribute_val = {
-       .attr = {
-                       .name = "value",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE
-       },
-       .show = &w1_default_read_name,
-};
-
 static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct w1_master *md = container_of (dev, struct w1_master, dev);
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
        ssize_t count;
-       
+
        if (down_interruptible (&md->mutex))
                return -EBUSY;
 
        count = sprintf(buf, "%s\n", md->name);
-       
+
+       up(&md->mutex);
+
+       return count;
+}
+
+static ssize_t w1_master_attribute_store_search(struct device * dev,
+                                               struct device_attribute *attr,
+                                               const char * buf, size_t count)
+{
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
+
+       if (down_interruptible (&md->mutex))
+               return -EBUSY;
+
+       md->search_count = simple_strtol(buf, NULL, 0);
+
+       up(&md->mutex);
+
+       return count;
+}
+
+static ssize_t w1_master_attribute_show_search(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buf)
+{
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       ssize_t count;
+
+       if (down_interruptible (&md->mutex))
+               return -EBUSY;
+
+       count = sprintf(buf, "%d\n", md->search_count);
+
        up(&md->mutex);
 
        return count;
@@ -156,12 +198,12 @@ static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct devic
 {
        struct w1_master *md = container_of(dev, struct w1_master, dev);
        ssize_t count;
-       
+
        if (down_interruptible(&md->mutex))
                return -EBUSY;
 
        count = sprintf(buf, "0x%p\n", md->bus_master);
-       
+
        up(&md->mutex);
        return count;
 }
@@ -177,12 +219,12 @@ static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, stru
 {
        struct w1_master *md = container_of(dev, struct w1_master, dev);
        ssize_t count;
-       
+
        if (down_interruptible(&md->mutex))
                return -EBUSY;
 
        count = sprintf(buf, "%d\n", md->max_slave_count);
-       
+
        up(&md->mutex);
        return count;
 }
@@ -191,12 +233,12 @@ static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct devi
 {
        struct w1_master *md = container_of(dev, struct w1_master, dev);
        ssize_t count;
-       
+
        if (down_interruptible(&md->mutex))
                return -EBUSY;
 
        count = sprintf(buf, "%lu\n", md->attempts);
-       
+
        up(&md->mutex);
        return count;
 }
@@ -205,18 +247,17 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
 {
        struct w1_master *md = container_of(dev, struct w1_master, dev);
        ssize_t count;
-       
+
        if (down_interruptible(&md->mutex))
                return -EBUSY;
 
        count = sprintf(buf, "%d\n", md->slave_count);
-       
+
        up(&md->mutex);
        return count;
 }
 
 static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
-
 {
        struct w1_master *md = container_of(dev, struct w1_master, dev);
        int c = PAGE_SIZE;
@@ -233,7 +274,7 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device
                list_for_each_safe(ent, n, &md->slist) {
                        sl = list_entry(ent, struct w1_slave, w1_slave_entry);
 
-                       c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
+                       c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
                }
        }
 
@@ -242,73 +283,52 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device
        return PAGE_SIZE - c;
 }
 
-static struct device_attribute w1_master_attribute_slaves = {
-       .attr = {
-                       .name = "w1_master_slaves",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE,
-       },
-       .show = &w1_master_attribute_show_slaves,
-};
-static struct device_attribute w1_master_attribute_slave_count = {
-       .attr = {
-                       .name = "w1_master_slave_count",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE
-       },
-       .show = &w1_master_attribute_show_slave_count,
-};
-static struct device_attribute w1_master_attribute_attempts = {
-       .attr = {
-                       .name = "w1_master_attempts",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE
-       },
-       .show = &w1_master_attribute_show_attempts,
-};
-static struct device_attribute w1_master_attribute_max_slave_count = {
-       .attr = {
-                       .name = "w1_master_max_slave_count",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE
-       },
-       .show = &w1_master_attribute_show_max_slave_count,
-};
-static struct device_attribute w1_master_attribute_timeout = {
-       .attr = {
-                       .name = "w1_master_timeout",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE
-       },
-       .show = &w1_master_attribute_show_timeout,
-};
-static struct device_attribute w1_master_attribute_pointer = {
-       .attr = {
-                       .name = "w1_master_pointer",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE
-       },
-       .show = &w1_master_attribute_show_pointer,
-};
-static struct device_attribute w1_master_attribute_name = {
-       .attr = {
-                       .name = "w1_master_name",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE
-       },
-       .show = &w1_master_attribute_show_name,
+#define W1_MASTER_ATTR_RO(_name, _mode)                                \
+       struct device_attribute w1_master_attribute_##_name =   \
+               __ATTR(w1_master_##_name, _mode,                \
+                      w1_master_attribute_show_##_name, NULL)
+
+#define W1_MASTER_ATTR_RW(_name, _mode)                                \
+       struct device_attribute w1_master_attribute_##_name =   \
+               __ATTR(w1_master_##_name, _mode,                \
+                      w1_master_attribute_show_##_name,        \
+                      w1_master_attribute_store_##_name)
+
+static W1_MASTER_ATTR_RO(name, S_IRUGO);
+static W1_MASTER_ATTR_RO(slaves, S_IRUGO);
+static W1_MASTER_ATTR_RO(slave_count, S_IRUGO);
+static W1_MASTER_ATTR_RO(max_slave_count, S_IRUGO);
+static W1_MASTER_ATTR_RO(attempts, S_IRUGO);
+static W1_MASTER_ATTR_RO(timeout, S_IRUGO);
+static W1_MASTER_ATTR_RO(pointer, S_IRUGO);
+static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO);
+
+static struct attribute *w1_master_default_attrs[] = {
+       &w1_master_attribute_name.attr,
+       &w1_master_attribute_slaves.attr,
+       &w1_master_attribute_slave_count.attr,
+       &w1_master_attribute_max_slave_count.attr,
+       &w1_master_attribute_attempts.attr,
+       &w1_master_attribute_timeout.attr,
+       &w1_master_attribute_pointer.attr,
+       &w1_master_attribute_search.attr,
+       NULL
 };
 
-static struct bin_attribute w1_slave_bin_attribute = {
-       .attr = {
-                       .name = "w1_slave",
-                       .mode = S_IRUGO,
-                       .owner = THIS_MODULE,
-       },
-       .size = W1_SLAVE_DATA_SIZE,
-       .read = &w1_default_read_bin,
+static struct attribute_group w1_master_defattr_group = {
+       .attrs = w1_master_default_attrs,
 };
 
+int w1_create_master_attributes(struct w1_master *master)
+{
+       return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
+}
+
+void w1_destroy_master_attributes(struct w1_master *master)
+{
+       sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
+}
+
 static int __w1_attach_slave_device(struct w1_slave *sl)
 {
        int err;
@@ -319,13 +339,13 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
        sl->dev.release = &w1_slave_release;
 
        snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id),
-                 "%02x-%012llx",
-                 (unsigned int) sl->reg_num.family,
-                 (unsigned long long) sl->reg_num.id);
-       snprintf (&sl->name[0], sizeof(sl->name),
-                 "%02x-%012llx",
-                 (unsigned int) sl->reg_num.family,
-                 (unsigned long long) sl->reg_num.id);
+                "%02x-%012llx",
+                (unsigned int) sl->reg_num.family,
+                (unsigned long long) sl->reg_num.id);
+       snprintf(&sl->name[0], sizeof(sl->name),
+                "%02x-%012llx",
+                (unsigned int) sl->reg_num.family,
+                (unsigned long long) sl->reg_num.id);
 
        dev_dbg(&sl->dev, "%s: registering %s.\n", __func__,
                &sl->dev.bus_id[0]);
@@ -333,48 +353,36 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
        err = device_register(&sl->dev);
        if (err < 0) {
                dev_err(&sl->dev,
-                        "Device registration [%s] failed. err=%d\n",
-                        sl->dev.bus_id, err);
+                       "Device registration [%s] failed. err=%d\n",
+                       sl->dev.bus_id, err);
                return err;
        }
 
        memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
        memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
-       memcpy(&sl->attr_val, &w1_slave_attribute_val, sizeof(sl->attr_val));
-       
+
        sl->attr_bin.read = sl->family->fops->rbin;
        sl->attr_name.show = sl->family->fops->rname;
-       sl->attr_val.show = sl->family->fops->rval;
-       sl->attr_val.attr.name = sl->family->fops->rvalname;
 
        err = device_create_file(&sl->dev, &sl->attr_name);
        if (err < 0) {
                dev_err(&sl->dev,
-                        "sysfs file creation for [%s] failed. err=%d\n",
-                        sl->dev.bus_id, err);
-               device_unregister(&sl->dev);
-               return err;
-       }
-
-       err = device_create_file(&sl->dev, &sl->attr_val);
-       if (err < 0) {
-               dev_err(&sl->dev,
-                        "sysfs file creation for [%s] failed. err=%d\n",
-                        sl->dev.bus_id, err);
-               device_remove_file(&sl->dev, &sl->attr_name);
+                       "sysfs file creation for [%s] failed. err=%d\n",
+                       sl->dev.bus_id, err);
                device_unregister(&sl->dev);
                return err;
        }
 
-       err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
-       if (err < 0) {
-               dev_err(&sl->dev,
-                        "sysfs file creation for [%s] failed. err=%d\n",
-                        sl->dev.bus_id, err);
-               device_remove_file(&sl->dev, &sl->attr_name);
-               device_remove_file(&sl->dev, &sl->attr_val);
-               device_unregister(&sl->dev);
-               return err;
+       if ( sl->attr_bin.read ) {
+               err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
+               if (err < 0) {
+                       dev_err(&sl->dev,
+                               "sysfs file creation for [%s] failed. err=%d\n",
+                               sl->dev.bus_id, err);
+                       device_remove_file(&sl->dev, &sl->attr_name);
+                       device_unregister(&sl->dev);
+                       return err;
+               }
        }
 
        list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
@@ -410,12 +418,10 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
        spin_lock(&w1_flock);
        f = w1_family_registered(rn->family);
        if (!f) {
-               spin_unlock(&w1_flock);
+               f= &w1_default_family;
                dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
                          rn->family, rn->family,
                          (unsigned long long)rn->id, rn->crc);
-               kfree(sl);
-               return -ENODEV;
        }
        __w1_family_get(f);
        spin_unlock(&w1_flock);
@@ -445,7 +451,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 static void w1_slave_detach(struct w1_slave *sl)
 {
        struct w1_netlink_msg msg;
-       
+
        dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
 
        while (atomic_read(&sl->refcnt)) {
@@ -456,12 +462,15 @@ static void w1_slave_detach(struct w1_slave *sl)
                        flush_signals(current);
        }
 
-       sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+       if ( sl->attr_bin.read ) {
+               sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+       }
        device_remove_file(&sl->dev, &sl->attr_name);
-       device_remove_file(&sl->dev, &sl->attr_val);
        device_unregister(&sl->dev);
        w1_family_put(sl->family);
 
+       sl->master->slave_count--;
+
        memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
        msg.type = W1_SLAVE_REMOVE;
        w1_netlink_send(sl->master, &msg);
@@ -471,8 +480,8 @@ static struct w1_master *w1_search_master(unsigned long data)
 {
        struct w1_master *dev;
        int found = 0;
-       
-       spin_lock_irq(&w1_mlock);
+
+       spin_lock_bh(&w1_mlock);
        list_for_each_entry(dev, &w1_masters, w1_master_entry) {
                if (dev->bus_master->data == data) {
                        found = 1;
@@ -480,12 +489,26 @@ static struct w1_master *w1_search_master(unsigned long data)
                        break;
                }
        }
-       spin_unlock_irq(&w1_mlock);
+       spin_unlock_bh(&w1_mlock);
 
        return (found)?dev:NULL;
 }
 
-void w1_slave_found(unsigned long data, u64 rn)
+void w1_reconnect_slaves(struct w1_family *f)
+{
+       struct w1_master *dev;
+
+       spin_lock_bh(&w1_mlock);
+       list_for_each_entry(dev, &w1_masters, w1_master_entry) {
+               dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
+                               dev->name, f->fid);
+               set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+       }
+       spin_unlock_bh(&w1_mlock);
+}
+
+
+static void w1_slave_found(unsigned long data, u64 rn)
 {
        int slave_count;
        struct w1_slave *sl;
@@ -500,7 +523,7 @@ void w1_slave_found(unsigned long data, u64 rn)
                                data);
                return;
        }
-       
+
        tmp = (struct w1_reg_num *) &rn;
 
        slave_count = 0;
@@ -513,8 +536,7 @@ void w1_slave_found(unsigned long data, u64 rn)
                    sl->reg_num.crc == tmp->crc) {
                        set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
                        break;
-               }
-               else if (sl->reg_num.family == tmp->family) {
+               } else if (sl->reg_num.family == tmp->family) {
                        family_found = 1;
                        break;
                }
@@ -528,30 +550,43 @@ void w1_slave_found(unsigned long data, u64 rn)
                rn && ((le64_to_cpu(rn) >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
                w1_attach_slave_device(dev, tmp);
        }
-                       
+
        atomic_dec(&dev->refcnt);
 }
 
-void w1_search(struct w1_master *dev)
+/**
+ * Performs a ROM Search & registers any devices found.
+ * The 1-wire search is a simple binary tree search.
+ * For each bit of the address, we read two bits and write one bit.
+ * The bit written will put to sleep all devies that don't match that bit.
+ * When the two reads differ, the direction choice is obvious.
+ * When both bits are 0, we must choose a path to take.
+ * When we can scan all 64 bits without having to choose a path, we are done.
+ *
+ * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com
+ *
+ * @dev        The master device to search
+ * @cb         Function to call when a device is found
+ */
+void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
 {
-       u64 last, rn, tmp;
-       int i, count = 0;
-       int last_family_desc, last_zero, last_device;
-       int search_bit, id_bit, comp_bit, desc_bit;
+       u64 last_rn, rn, tmp64;
+       int i, slave_count = 0;
+       int last_zero, last_device;
+       int search_bit, desc_bit;
+       u8  triplet_ret = 0;
 
-       search_bit = id_bit = comp_bit = 0;
-       rn = tmp = last = 0;
-       last_device = last_zero = last_family_desc = 0;
+       search_bit = 0;
+       rn = last_rn = 0;
+       last_device = 0;
+       last_zero = -1;
 
        desc_bit = 64;
 
-       while (!(id_bit && comp_bit) && !last_device
-               && count++ < dev->max_slave_count) {
-               last = rn;
+       while ( !last_device && (slave_count++ < dev->max_slave_count) ) {
+               last_rn = rn;
                rn = 0;
 
-               last_family_desc = 0;
-
                /*
                 * Reset bus and all 1-wire device state machines
                 * so they can respond to our requests.
@@ -563,94 +598,46 @@ void w1_search(struct w1_master *dev)
                        break;
                }
 
-#if 1
+               /* Start the search */
                w1_write_8(dev, W1_SEARCH);
                for (i = 0; i < 64; ++i) {
-                       /*
-                        * Read 2 bits from bus.
-                        * All who don't sleep must send ID bit and COMPLEMENT ID bit.
-                        * They actually are ANDed between all senders.
-                        */
-                       id_bit = w1_touch_bit(dev, 1);
-                       comp_bit = w1_touch_bit(dev, 1);
-
-                       if (id_bit && comp_bit)
-                               break;
-
-                       if (id_bit == 0 && comp_bit == 0) {
-                               if (i == desc_bit)
-                                       search_bit = 1;
-                               else if (i > desc_bit)
-                                       search_bit = 0;
-                               else
-                                       search_bit = ((last >> i) & 0x1);
-
-                               if (search_bit == 0) {
-                                       last_zero = i;
-                                       if (last_zero < 9)
-                                               last_family_desc = last_zero;
-                               }
-
-                       }
+                       /* Determine the direction/search bit */
+                       if (i == desc_bit)
+                               search_bit = 1;   /* took the 0 path last time, so take the 1 path */
+                       else if (i > desc_bit)
+                               search_bit = 0;   /* take the 0 path on the next branch */
                        else
-                               search_bit = id_bit;
+                               search_bit = ((last_rn >> i) & 0x1);
 
-                       tmp = search_bit;
-                       rn |= (tmp << i);
+                       /** Read two bits and write one bit */
+                       triplet_ret = w1_triplet(dev, search_bit);
 
-                       /*
-                        * Write 1 bit to bus
-                        * and make all who don't have "search_bit" in "i"'th position
-                        * in it's registration number sleep.
-                        */
-                       if (dev->bus_master->touch_bit)
-                               w1_touch_bit(dev, search_bit);
-                       else
-                               w1_write_bit(dev, search_bit);
+                       /* quit if no device responded */
+                       if ( (triplet_ret & 0x03) == 0x03 )
+                               break;
 
-               }
-#endif
+                       /* If both directions were valid, and we took the 0 path... */
+                       if (triplet_ret == 0)
+                               last_zero = i;
 
-               if (desc_bit == last_zero)
-                       last_device = 1;
+                       /* extract the direction taken & update the device number */
+                       tmp64 = (triplet_ret >> 2);
+                       rn |= (tmp64 << i);
+               }
 
-               desc_bit = last_zero;
-       
-               w1_slave_found(dev->bus_master->data, rn);
+               if ( (triplet_ret & 0x03) != 0x03 ) {
+                       if ( (desc_bit == last_zero) || (last_zero < 0))
+                               last_device = 1;
+                       desc_bit = last_zero;
+                       cb(dev->bus_master->data, rn);
+               }
        }
 }
 
-int w1_create_master_attributes(struct w1_master *dev)
-{
-       if (    device_create_file(&dev->dev, &w1_master_attribute_slaves) < 0 ||
-               device_create_file(&dev->dev, &w1_master_attribute_slave_count) < 0 ||
-               device_create_file(&dev->dev, &w1_master_attribute_attempts) < 0 ||
-               device_create_file(&dev->dev, &w1_master_attribute_max_slave_count) < 0 ||
-               device_create_file(&dev->dev, &w1_master_attribute_timeout) < 0||
-               device_create_file(&dev->dev, &w1_master_attribute_pointer) < 0||
-               device_create_file(&dev->dev, &w1_master_attribute_name) < 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-void w1_destroy_master_attributes(struct w1_master *dev)
+static int w1_control(void *data)
 {
-       device_remove_file(&dev->dev, &w1_master_attribute_slaves);
-       device_remove_file(&dev->dev, &w1_master_attribute_slave_count);
-       device_remove_file(&dev->dev, &w1_master_attribute_attempts);
-       device_remove_file(&dev->dev, &w1_master_attribute_max_slave_count);
-       device_remove_file(&dev->dev, &w1_master_attribute_timeout);
-       device_remove_file(&dev->dev, &w1_master_attribute_pointer);
-       device_remove_file(&dev->dev, &w1_master_attribute_name);
-}
-
-
-int w1_control(void *data)
-{
-       struct w1_slave *sl;
-       struct w1_master *dev;
-       struct list_head *ent, *ment, *n, *mn;
+       struct w1_slave *sl, *sln;
+       struct w1_master *dev, *n;
        int err, have_to_wait = 0;
 
        daemonize("w1_control");
@@ -665,10 +652,8 @@ int w1_control(void *data)
                if (signal_pending(current))
                        flush_signals(current);
 
-               list_for_each_safe(ment, mn, &w1_masters) {
-                       dev = list_entry(ment, struct w1_master, w1_master_entry);
-
-                       if (!control_needs_exit && !dev->need_exit)
+               list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) {
+                       if (!control_needs_exit && !dev->flags)
                                continue;
                        /*
                         * Little race: we can create thread but not set the flag.
@@ -679,12 +664,8 @@ int w1_control(void *data)
                                continue;
                        }
 
-                       spin_lock(&w1_mlock);
-                       list_del(&dev->w1_master_entry);
-                       spin_unlock(&w1_mlock);
-
                        if (control_needs_exit) {
-                               dev->need_exit = 1;
+                               set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
 
                                err = kill_proc(dev->kpid, SIGTERM, 1);
                                if (err)
@@ -693,24 +674,42 @@ int w1_control(void *data)
                                                 dev->kpid);
                        }
 
-                       wait_for_completion(&dev->dev_exited);
-
-                       list_for_each_safe(ent, n, &dev->slist) {
-                               sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+                       if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+                               wait_for_completion(&dev->dev_exited);
+                               spin_lock_bh(&w1_mlock);
+                               list_del(&dev->w1_master_entry);
+                               spin_unlock_bh(&w1_mlock);
 
-                               if (!sl)
-                                       dev_warn(&dev->dev,
-                                                 "%s: slave entry is NULL.\n",
-                                                 __func__);
-                               else {
+                               list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
                                        list_del(&sl->w1_slave_entry);
 
                                        w1_slave_detach(sl);
                                        kfree(sl);
                                }
+                               w1_destroy_master_attributes(dev);
+                               atomic_dec(&dev->refcnt);
+                               continue;
+                       }
+
+                       if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
+                               dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
+                               down(&dev->mutex);
+                               list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+                                       if (sl->family->fid == W1_FAMILY_DEFAULT) {
+                                               struct w1_reg_num rn;
+                                               list_del(&sl->w1_slave_entry);
+                                               w1_slave_detach(sl);
+
+                                               memcpy(&rn, &sl->reg_num, sizeof(rn));
+
+                                               kfree(sl);
+
+                                               w1_attach_slave_device(dev, &rn);
+                                       }
+                               }
+                               clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+                               up(&dev->mutex);
                        }
-                       w1_destroy_master_attributes(dev);
-                       atomic_dec(&dev->refcnt);
                }
        }
 
@@ -720,51 +719,50 @@ int w1_control(void *data)
 int w1_process(void *data)
 {
        struct w1_master *dev = (struct w1_master *) data;
-       struct list_head *ent, *n;
-       struct w1_slave *sl;
+       struct w1_slave *sl, *sln;
 
        daemonize("%s", dev->name);
        allow_signal(SIGTERM);
 
-       while (!dev->need_exit) {
+       while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
                try_to_freeze(PF_FREEZE);
                msleep_interruptible(w1_timeout * 1000);
 
                if (signal_pending(current))
                        flush_signals(current);
 
-               if (dev->need_exit)
+               if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags))
                        break;
 
                if (!dev->initialized)
                        continue;
 
+               if (dev->search_count == 0)
+                       continue;
+
                if (down_interruptible(&dev->mutex))
                        continue;
 
-               list_for_each_safe(ent, n, &dev->slist) {
-                       sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+               list_for_each_entry(sl, &dev->slist, w1_slave_entry)
+                       clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 
-                       if (sl)
-                               clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
-               }
-               
                w1_search_devices(dev, w1_slave_found);
 
-               list_for_each_safe(ent, n, &dev->slist) {
-                       sl = list_entry(ent, struct w1_slave, w1_slave_entry);
-
-                       if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
+               list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+                       if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
                                list_del (&sl->w1_slave_entry);
 
                                w1_slave_detach (sl);
                                kfree (sl);
 
                                dev->slave_count--;
-                       }
-                       else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
+                       } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
                                sl->ttl = dev->slave_ttl;
                }
+
+               if (dev->search_count > 0)
+                       dev->search_count--;
+
                up(&dev->mutex);
        }
 
@@ -774,7 +772,7 @@ int w1_process(void *data)
        return 0;
 }
 
-int w1_init(void)
+static int w1_init(void)
 {
        int retval;
 
@@ -814,18 +812,14 @@ err_out_exit_init:
        return retval;
 }
 
-void w1_fini(void)
+static void w1_fini(void)
 {
        struct w1_master *dev;
-       struct list_head *ent, *n;
 
-       list_for_each_safe(ent, n, &w1_masters) {
-               dev = list_entry(ent, struct w1_master, w1_master_entry);
+       list_for_each_entry(dev, &w1_masters, w1_master_entry)
                __w1_remove_master_device(dev);
-       }
 
        control_needs_exit = 1;
-
        wait_for_completion(&w1_control_complete);
 
        driver_unregister(&w1_driver);
index abbddaf3f8e287eb3329eb6c6b58360980103bf1..4f0a986e33e3f6332a688c35c1c2923ac1530ccd 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1.h
+ *     w1.h
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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
@@ -74,36 +74,86 @@ struct w1_slave
        int                     ttl;
 
        struct w1_master        *master;
-       struct w1_family        *family;
-       struct device           dev;
-       struct completion       dev_released;
+       struct w1_family        *family;
+       struct device           dev;
+       struct completion       dev_released;
 
-       struct bin_attribute    attr_bin;
-       struct device_attribute attr_name, attr_val;
+       struct bin_attribute    attr_bin;
+       struct device_attribute attr_name;
 };
 
 typedef void (* w1_slave_found_callback)(unsigned long, u64);
 
+
+/**
+ * Note: read_bit and write_bit are very low level functions and should only
+ * be used with hardware that doesn't really support 1-wire operations,
+ * like a parallel/serial port.
+ * Either define read_bit and write_bit OR define, at minimum, touch_bit and
+ * reset_bus.
+ */
 struct w1_bus_master
 {
-       unsigned long           data;
-
-       u8                      (*read_bit)(unsigned long);
-       void                    (*write_bit)(unsigned long, u8);
-       
-       u8                      (*read_byte)(unsigned long);
-       void                    (*write_byte)(unsigned long, u8);
-       
-       u8                      (*read_block)(unsigned long, u8 *, int);
-       void                    (*write_block)(unsigned long, u8 *, int);
-       
-       u8                      (*touch_bit)(unsigned long, u8);
-  
-       u8                      (*reset_bus)(unsigned long);
-
-       void                    (*search)(unsigned long, w1_slave_found_callback);
+       /** the first parameter in all the functions below */
+       unsigned long   data;
+
+       /**
+        * Sample the line level
+        * @return the level read (0 or 1)
+        */
+       u8              (*read_bit)(unsigned long);
+
+       /** Sets the line level */
+       void            (*write_bit)(unsigned long, u8);
+
+       /**
+        * touch_bit is the lowest-level function for devices that really
+        * support the 1-wire protocol.
+        * touch_bit(0) = write-0 cycle
+        * touch_bit(1) = write-1 / read cycle
+        * @return the bit read (0 or 1)
+        */
+       u8              (*touch_bit)(unsigned long, u8);
+
+       /**
+        * Reads a bytes. Same as 8 touch_bit(1) calls.
+        * @return the byte read
+        */
+       u8              (*read_byte)(unsigned long);
+
+       /**
+        * Writes a byte. Same as 8 touch_bit(x) calls.
+        */
+       void            (*write_byte)(unsigned long, u8);
+
+       /**
+        * Same as a series of read_byte() calls
+        * @return the number of bytes read
+        */
+       u8              (*read_block)(unsigned long, u8 *, int);
+
+       /** Same as a series of write_byte() calls */
+       void            (*write_block)(unsigned long, const u8 *, int);
+
+       /**
+        * Combines two reads and a smart write for ROM searches
+        * @return bit0=Id bit1=comp_id bit2=dir_taken
+        */
+       u8              (*triplet)(unsigned long, u8);
+
+       /**
+        * long write-0 with a read for the presence pulse detection
+        * @return -1=Error, 0=Device present, 1=No device present
+        */
+       u8              (*reset_bus)(unsigned long);
+
+       /** Really nice hardware can handles the ROM searches */
+       void            (*search)(unsigned long, w1_slave_found_callback);
 };
 
+#define W1_MASTER_NEED_EXIT            0
+#define W1_MASTER_NEED_RECONNECT       1
+
 struct w1_master
 {
        struct list_head        w1_master_entry;
@@ -115,30 +165,31 @@ struct w1_master
        int                     slave_ttl;
        int                     initialized;
        u32                     id;
+       int                     search_count;
 
        atomic_t                refcnt;
 
        void                    *priv;
        int                     priv_size;
 
-       int                     need_exit;
+       long                    flags;
+
        pid_t                   kpid;
-       struct semaphore        mutex;
+       struct semaphore        mutex;
 
        struct device_driver    *driver;
-       struct device           dev;
-       struct completion       dev_released;
-       struct completion       dev_exited;
+       struct device           dev;
+       struct completion       dev_released;
+       struct completion       dev_exited;
 
        struct w1_bus_master    *bus_master;
 
        u32                     seq, groups;
-       struct sock             *nls;
+       struct sock             *nls;
 };
 
 int w1_create_master_attributes(struct w1_master *);
-void w1_destroy_master_attributes(struct w1_master *);
-void w1_search(struct w1_master *dev);
+void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
 
 #endif /* __KERNEL__ */
 
index d1d56eca1061c7c112fba35a7a39c0c294b72fcb..02eee57d3c0cd2c46e394faf1617251944778e42 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_family.c
+ *     w1_family.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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
 
 DEFINE_SPINLOCK(w1_flock);
 static LIST_HEAD(w1_families);
+extern void w1_reconnect_slaves(struct w1_family *f);
 
 static int w1_check_family(struct w1_family *f)
 {
-       if (!f->fops->rname || !f->fops->rbin || !f->fops->rval || !f->fops->rvalname)
+       if (!f->fops->rname || !f->fops->rbin)
                return -EINVAL;
 
        return 0;
@@ -60,9 +61,10 @@ int w1_register_family(struct w1_family *newf)
                newf->need_exit = 0;
                list_add_tail(&newf->family_entry, &w1_families);
        }
-
        spin_unlock(&w1_flock);
 
+       w1_reconnect_slaves(newf);
+
        return ret;
 }
 
index 07fa49412a90005fecbac0ea882284b5ead45ec3..b26da01bbc384c3b8b8fd627735e63e4d9cba96b 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_family.h
+ *     w1_family.h
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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
 #include <asm/atomic.h>
 
 #define W1_FAMILY_DEFAULT      0
-#define W1_FAMILY_THERM                0x10
-#define W1_FAMILY_SMEM         0x01
+#define W1_FAMILY_SMEM_01      0x01
+#define W1_FAMILY_SMEM_81      0x81
+#define W1_THERM_DS18S20       0x10
+#define W1_THERM_DS1822        0x22
+#define W1_THERM_DS18B20       0x28
 
 #define MAXNAMELEN             32
 
@@ -36,18 +39,15 @@ struct w1_family_ops
 {
        ssize_t (* rname)(struct device *, struct device_attribute *, char *);
        ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t);
-       
-       ssize_t (* rval)(struct device *, struct device_attribute *, char *);
-       unsigned char rvalname[MAXNAMELEN];
 };
 
 struct w1_family
 {
        struct list_head        family_entry;
        u8                      fid;
-       
+
        struct w1_family_ops    *fops;
-       
+
        atomic_t                refcnt;
        u8                      need_exit;
 };
index 5f0bafbbd575362d475259daf1b487d5d1dad64f..35e85d961702cb92664c65b0261f53199d5f4b9f 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_int.c
+ *     w1_int.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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
@@ -39,8 +39,9 @@ extern spinlock_t w1_mlock;
 
 extern int w1_process(void *);
 
-struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
-             struct device_driver *driver, struct device *device)
+static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
+                                      struct device_driver *driver,
+                                      struct device *device)
 {
        struct w1_master *dev;
        int err;
@@ -60,14 +61,15 @@ struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
 
        dev->bus_master = (struct w1_bus_master *)(dev + 1);
 
-       dev->owner              = THIS_MODULE;
-       dev->max_slave_count    = slave_count;
-       dev->slave_count        = 0;
-       dev->attempts           = 0;
-       dev->kpid               = -1;
-       dev->initialized        = 0;
-       dev->id                 = id;
+       dev->owner              = THIS_MODULE;
+       dev->max_slave_count    = slave_count;
+       dev->slave_count        = 0;
+       dev->attempts           = 0;
+       dev->kpid               = -1;
+       dev->initialized        = 0;
+       dev->id                 = id;
        dev->slave_ttl          = slave_ttl;
+        dev->search_count      = -1; /* continual scan */
 
        atomic_set(&dev->refcnt, 2);
 
@@ -105,7 +107,7 @@ struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
        return dev;
 }
 
-void w1_free_dev(struct w1_master *dev)
+static void w1_free_dev(struct w1_master *dev)
 {
        device_unregister(&dev->dev);
        if (dev->nls && dev->nls->sk_socket)
@@ -120,6 +122,13 @@ int w1_add_master_device(struct w1_bus_master *master)
        int retval = 0;
        struct w1_netlink_msg msg;
 
+        /* validate minimum functionality */
+        if (!(master->touch_bit && master->reset_bus) &&
+            !(master->write_bit && master->read_bit)) {
+               printk(KERN_ERR "w1_add_master_device: invalid function set\n");
+               return(-EINVAL);
+        }
+
        dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
        if (!dev)
                return -ENOMEM;
@@ -153,7 +162,7 @@ int w1_add_master_device(struct w1_bus_master *master)
        return 0;
 
 err_out_kill_thread:
-       dev->need_exit = 1;
+       set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
        if (kill_proc(dev->kpid, SIGTERM, 1))
                dev_err(&dev->dev,
                         "Failed to send signal to w1 kernel thread %d.\n",
@@ -171,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev)
        int err;
        struct w1_netlink_msg msg;
 
-       dev->need_exit = 1;
+       set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
        err = kill_proc(dev->kpid, SIGTERM, 1);
        if (err)
                dev_err(&dev->dev,
@@ -197,10 +206,8 @@ void __w1_remove_master_device(struct w1_master *dev)
 void w1_remove_master_device(struct w1_bus_master *bm)
 {
        struct w1_master *dev = NULL;
-       struct list_head *ent, *n;
 
-       list_for_each_safe(ent, n, &w1_masters) {
-               dev = list_entry(ent, struct w1_master, w1_master_entry);
+       list_for_each_entry(dev, &w1_masters, w1_master_entry) {
                if (!dev->initialized)
                        continue;
 
index fdb531e87faa9ee93cf3f54bbf5c0b57b62a062d..4274082d22629192e6379059496d631ecf4458bb 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_int.h
+ *     w1_int.h
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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
@@ -27,8 +27,6 @@
 
 #include "w1.h"
 
-struct w1_master * w1_alloc_dev(u32, int, int, struct device_driver *, struct device *);
-void w1_free_dev(struct w1_master *dev);
 int w1_add_master_device(struct w1_bus_master *);
 void w1_remove_master_device(struct w1_bus_master *);
 void __w1_remove_master_device(struct w1_master *);
index 02796b5a39f6d8ce8462b01a96aebe0272a427db..00f032220173863c3603dbc0d5f66ca005f9adb0 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_io.c
+ *     w1_io.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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
@@ -55,15 +55,29 @@ void w1_delay(unsigned long tm)
        udelay(tm * w1_delay_parm);
 }
 
+static void w1_write_bit(struct w1_master *dev, int bit);
+static u8 w1_read_bit(struct w1_master *dev);
+
+/**
+ * Generates a write-0 or write-1 cycle and samples the level.
+ */
 u8 w1_touch_bit(struct w1_master *dev, int bit)
 {
        if (dev->bus_master->touch_bit)
                return dev->bus_master->touch_bit(dev->bus_master->data, bit);
-       else
+       else if (bit)
                return w1_read_bit(dev);
+       else {
+               w1_write_bit(dev, 0);
+               return(0);
+       }
 }
 
-void w1_write_bit(struct w1_master *dev, int bit)
+/**
+ * Generates a write-0 or write-1 cycle.
+ * Only call if dev->bus_master->touch_bit is NULL
+ */
+static void w1_write_bit(struct w1_master *dev, int bit)
 {
        if (bit) {
                dev->bus_master->write_bit(dev->bus_master->data, 0);
@@ -78,6 +92,12 @@ void w1_write_bit(struct w1_master *dev, int bit)
        }
 }
 
+/**
+ * Writes 8 bits.
+ *
+ * @param dev     the master device
+ * @param byte    the byte to write
+ */
 void w1_write_8(struct w1_master *dev, u8 byte)
 {
        int i;
@@ -86,10 +106,15 @@ void w1_write_8(struct w1_master *dev, u8 byte)
                dev->bus_master->write_byte(dev->bus_master->data, byte);
        else
                for (i = 0; i < 8; ++i)
-                       w1_write_bit(dev, (byte >> i) & 0x1);
+                       w1_touch_bit(dev, (byte >> i) & 0x1);
 }
 
-u8 w1_read_bit(struct w1_master *dev)
+
+/**
+ * Generates a write-1 cycle and samples the level.
+ * Only call if dev->bus_master->touch_bit is NULL
+ */
+static u8 w1_read_bit(struct w1_master *dev)
 {
        int result;
 
@@ -104,6 +129,53 @@ u8 w1_read_bit(struct w1_master *dev)
        return result & 0x1;
 }
 
+/**
+ * Does a triplet - used for searching ROM addresses.
+ * Return bits:
+ *  bit 0 = id_bit
+ *  bit 1 = comp_bit
+ *  bit 2 = dir_taken
+ * If both bits 0 & 1 are set, the search should be restarted.
+ *
+ * @param dev     the master device
+ * @param bdir    the bit to write if both id_bit and comp_bit are 0
+ * @return        bit fields - see above
+ */
+u8 w1_triplet(struct w1_master *dev, int bdir)
+{
+       if ( dev->bus_master->triplet )
+               return(dev->bus_master->triplet(dev->bus_master->data, bdir));
+       else {
+               u8 id_bit   = w1_touch_bit(dev, 1);
+               u8 comp_bit = w1_touch_bit(dev, 1);
+               u8 retval;
+
+               if ( id_bit && comp_bit )
+                       return(0x03);  /* error */
+
+               if ( !id_bit && !comp_bit ) {
+                       /* Both bits are valid, take the direction given */
+                       retval = bdir ? 0x04 : 0;
+               } else {
+                       /* Only one bit is valid, take that direction */
+                       bdir = id_bit;
+                       retval = id_bit ? 0x05 : 0x02;
+               }
+
+               if ( dev->bus_master->touch_bit )
+                       w1_touch_bit(dev, bdir);
+               else
+                       w1_write_bit(dev, bdir);
+               return(retval);
+       }
+}
+
+/**
+ * Reads 8 bits.
+ *
+ * @param dev     the master device
+ * @return        the byte read
+ */
 u8 w1_read_8(struct w1_master * dev)
 {
        int i;
@@ -113,12 +185,20 @@ u8 w1_read_8(struct w1_master * dev)
                res = dev->bus_master->read_byte(dev->bus_master->data);
        else
                for (i = 0; i < 8; ++i)
-                       res |= (w1_read_bit(dev) << i);
+                       res |= (w1_touch_bit(dev,1) << i);
 
        return res;
 }
 
-void w1_write_block(struct w1_master *dev, u8 *buf, int len)
+/**
+ * Writes a series of bytes.
+ *
+ * @param dev     the master device
+ * @param buf     pointer to the data to write
+ * @param len     the number of bytes to write
+ * @return        the byte read
+ */
+void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
 {
        int i;
 
@@ -129,6 +209,14 @@ void w1_write_block(struct w1_master *dev, u8 *buf, int len)
                        w1_write_8(dev, buf[i]);
 }
 
+/**
+ * Reads a series of bytes.
+ *
+ * @param dev     the master device
+ * @param buf     pointer to the buffer to fill
+ * @param len     the number of bytes to read
+ * @return        the number of bytes read
+ */
 u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
 {
        int i;
@@ -145,9 +233,15 @@ u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
        return ret;
 }
 
+/**
+ * Issues a reset bus sequence.
+ *
+ * @param  dev The bus master pointer
+ * @return     0=Device present, 1=No device present or error
+ */
 int w1_reset_bus(struct w1_master *dev)
 {
-       int result = 0;
+       int result;
 
        if (dev->bus_master->reset_bus)
                result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
@@ -180,12 +274,11 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
        if (dev->bus_master->search)
                dev->bus_master->search(dev->bus_master->data, cb);
        else
-               w1_search(dev);
+               w1_search(dev, cb);
 }
 
-EXPORT_SYMBOL(w1_write_bit);
+EXPORT_SYMBOL(w1_touch_bit);
 EXPORT_SYMBOL(w1_write_8);
-EXPORT_SYMBOL(w1_read_bit);
 EXPORT_SYMBOL(w1_read_8);
 EXPORT_SYMBOL(w1_reset_bus);
 EXPORT_SYMBOL(w1_calc_crc8);
index 6c573005a7125a2ba741fa4d2517c27d8292b030..af5829778aaa1fe9c72148386c97555066d39ed5 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_io.h
+ *     w1_io.h
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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
 
 void w1_delay(unsigned long);
 u8 w1_touch_bit(struct w1_master *, int);
-void w1_write_bit(struct w1_master *, int);
+u8 w1_triplet(struct w1_master *dev, int bdir);
 void w1_write_8(struct w1_master *, u8);
-u8 w1_read_bit(struct w1_master *);
 u8 w1_read_8(struct w1_master *);
 int w1_reset_bus(struct w1_master *);
 u8 w1_calc_crc8(u8 *, int);
-void w1_write_block(struct w1_master *, u8 *, int);
+void w1_write_block(struct w1_master *, const u8 *, int);
 u8 w1_read_block(struct w1_master *, u8 *, int);
 void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb);
 
index a6bf6f44dce23300e5cf53aa4a6a7b76e0c35064..fe6bdf43380f1cd95fea955ec583f4aceaa780fa 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_log.h
+ *     w1_log.h
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * 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
index ea1b530abad0a10cf22d5203286a7bf5a14564f7..8615756946dfa988891d81ecc6be5b94d8ee496a 100644 (file)
@@ -33,13 +33,13 @@ enum w1_netlink_message_types {
        W1_MASTER_REMOVE,
 };
 
-struct w1_netlink_msg 
+struct w1_netlink_msg
 {
        __u8                            type;
        __u8                            reserved[3];
        union
        {
-               struct w1_reg_num       id;
+               struct w1_reg_num       id;
                __u64                   w1_id;
                struct
                {
index 674eb75a9bad1d21a70b6d7cee56cf469df989e2..70d2d469963cfe8e57be5b242c31ae1bec525a69 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_smem.c
+ *     w1_smem.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the smems of the GNU General Public License as published by
@@ -37,14 +37,11 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
 
 static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *);
-static ssize_t w1_smem_read_val(struct device *, struct device_attribute *attr, char *);
 static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
 
 static struct w1_family_ops w1_smem_fops = {
        .rname = &w1_smem_read_name,
        .rbin = &w1_smem_read_bin,
-       .rval = &w1_smem_read_val,
-       .rvalname = "id",
 };
 
 static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf)
@@ -54,23 +51,10 @@ static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *at
        return sprintf(buf, "%s\n", sl->name);
 }
 
-static ssize_t w1_smem_read_val(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-       int i;
-       ssize_t count = 0;
-       
-       for (i = 0; i < 8; ++i)
-               count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
-       count += sprintf(buf + count, "\n");
-
-       return count;
-}
-
 static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
-                                               struct w1_slave, dev);
+                                          struct w1_slave, dev);
        int i;
 
        atomic_inc(&sl->refcnt);
@@ -90,7 +74,7 @@ static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, siz
        for (i = 0; i < 8; ++i)
                count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
        count += sprintf(buf + count, "\n");
-       
+
 out:
        up(&sl->master->mutex);
 out_dec:
@@ -99,19 +83,37 @@ out_dec:
        return count;
 }
 
-static struct w1_family w1_smem_family = {
-       .fid = W1_FAMILY_SMEM,
+static struct w1_family w1_smem_family_01 = {
+       .fid = W1_FAMILY_SMEM_01,
+       .fops = &w1_smem_fops,
+};
+
+static struct w1_family w1_smem_family_81 = {
+       .fid = W1_FAMILY_SMEM_81,
        .fops = &w1_smem_fops,
 };
 
 static int __init w1_smem_init(void)
 {
-       return w1_register_family(&w1_smem_family);
+       int err;
+
+       err = w1_register_family(&w1_smem_family_01);
+       if (err)
+               return err;
+       
+       err = w1_register_family(&w1_smem_family_81);
+       if (err) {
+               w1_unregister_family(&w1_smem_family_01);
+               return err;
+       }
+
+       return 0;
 }
 
 static void __exit w1_smem_fini(void)
 {
-       w1_unregister_family(&w1_smem_family);
+       w1_unregister_family(&w1_smem_family_01);
+       w1_unregister_family(&w1_smem_family_81);
 }
 
 module_init(w1_smem_init);
index 70310f7a722e49583ec126765648ee18a1de604d..165526c9360ad5a99a642e5e91c92ac762b24b0c 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *     w1_therm.c
+ *     w1_therm.c
  *
  * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- * 
+ *
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the therms of the GNU General Public License as published by
@@ -38,19 +38,56 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
 
 static u8 bad_roms[][9] = {
-                               {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, 
+                               {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
                                {}
                        };
 
 static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *);
-static ssize_t w1_therm_read_temp(struct device *, struct device_attribute *attr, char *);
 static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
 
 static struct w1_family_ops w1_therm_fops = {
        .rname = &w1_therm_read_name,
        .rbin = &w1_therm_read_bin,
-       .rval = &w1_therm_read_temp,
-       .rvalname = "temp1_input",
+};
+
+static struct w1_family w1_therm_family_DS18S20 = {
+       .fid = W1_THERM_DS18S20,
+       .fops = &w1_therm_fops,
+};
+
+static struct w1_family w1_therm_family_DS18B20 = {
+       .fid = W1_THERM_DS18B20,
+       .fops = &w1_therm_fops,
+};
+static struct w1_family w1_therm_family_DS1822 = {
+       .fid = W1_THERM_DS1822,
+       .fops = &w1_therm_fops,
+};
+
+struct w1_therm_family_converter
+{
+       u8                      broken;
+       u16                     reserved;
+       struct w1_family        *f;
+       int                     (*convert)(u8 rom[9]);
+};
+
+static inline int w1_DS18B20_convert_temp(u8 rom[9]);
+static inline int w1_DS18S20_convert_temp(u8 rom[9]);
+
+static struct w1_therm_family_converter w1_therm_families[] = {
+       {
+               .f              = &w1_therm_family_DS18S20,
+               .convert        = w1_DS18S20_convert_temp
+       },
+       {
+               .f              = &w1_therm_family_DS1822,
+               .convert        = w1_DS18B20_convert_temp
+       },
+       {
+               .f              = &w1_therm_family_DS18B20,
+               .convert        = w1_DS18B20_convert_temp
+       },
 };
 
 static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf)
@@ -60,9 +97,19 @@ static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *a
        return sprintf(buf, "%s\n", sl->name);
 }
 
-static inline int w1_convert_temp(u8 rom[9])
+static inline int w1_DS18B20_convert_temp(u8 rom[9])
+{
+       int t = (rom[1] << 8) | rom[0];
+       t /= 16;
+       return t;
+}
+
+static inline int w1_DS18S20_convert_temp(u8 rom[9])
 {
        int t, h;
+
+       if (!rom[7])
+               return 0;
        
        if (rom[1] == 0)
                t = ((s32)rom[0] >> 1)*1000;
@@ -77,11 +124,15 @@ static inline int w1_convert_temp(u8 rom[9])
        return t;
 }
 
-static ssize_t w1_therm_read_temp(struct device *dev, struct device_attribute *attr, char *buf)
+static inline int w1_convert_temp(u8 rom[9], u8 fid)
 {
-       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+       int i;
+
+       for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+               if (w1_therm_families[i].f->fid == fid)
+                       return w1_therm_families[i].convert(rom);
 
-       return sprintf(buf, "%d\n", w1_convert_temp(sl->rom));
+       return 0;
 }
 
 static int w1_therm_check_rom(u8 rom[9])
@@ -98,7 +149,7 @@ static int w1_therm_check_rom(u8 rom[9])
 static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
        struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
-                                               struct w1_slave, dev);
+                                          struct w1_slave, dev);
        struct w1_master *dev = sl->master;
        u8 rom[9], crc, verdict;
        int i, max_trying = 10;
@@ -133,7 +184,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
                        unsigned int tm = 750;
 
                        memcpy(&match[1], (u64 *) & sl->reg_num, 8);
-                       
+
                        w1_write_block(dev, match, 9);
 
                        w1_write_8(dev, W1_CONVERT_TEMP);
@@ -146,7 +197,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
 
                        if (!w1_reset_bus (dev)) {
                                w1_write_block(dev, match, 9);
-                               
+
                                w1_write_8(dev, W1_READ_SCRATCHPAD);
                                if ((count = w1_read_block(dev, rom, 9)) != 9) {
                                        dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
@@ -176,7 +227,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
        for (i = 0; i < 9; ++i)
                count += sprintf(buf + count, "%02x ", sl->rom[i]);
        
-       count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom));
+       count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
 out:
        up(&dev->mutex);
 out_dec:
@@ -186,19 +237,26 @@ out_dec:
        return count;
 }
 
-static struct w1_family w1_therm_family = {
-       .fid = W1_FAMILY_THERM,
-       .fops = &w1_therm_fops,
-};
-
 static int __init w1_therm_init(void)
 {
-       return w1_register_family(&w1_therm_family);
+       int err, i;
+
+       for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) {
+               err = w1_register_family(w1_therm_families[i].f);
+               if (err)
+                       w1_therm_families[i].broken = 1;
+       }
+
+       return 0;
 }
 
 static void __exit w1_therm_fini(void)
 {
-       w1_unregister_family(&w1_therm_family);
+       int i;
+
+       for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+               if (!w1_therm_families[i].broken)
+                       w1_unregister_family(w1_therm_families[i].f);
 }
 
 module_init(w1_therm_init);
index c7b2b8890188599e09f19c255fa9ec1014342e2e..9c09641ce907284242ac477223810a9edfb24ee3 100644 (file)
@@ -185,6 +185,19 @@ int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
 int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
 void autofs4_catatonic_mode(struct autofs_sb_info *);
 
+static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+{
+       int res = 0;
+
+       while (d_mountpoint(*dentry)) {
+               int followed = follow_down(mnt, dentry);
+               if (!followed)
+                       break;
+               res = 1;
+       }
+       return res;
+}
+
 static inline int simple_positive(struct dentry *dentry)
 {
        return dentry->d_inode && !d_unhashed(dentry);
index 500425e24fba9178c13db5550a7f9271256249d4..feb6ac427d058b8a1c02b420bbe6ad81ffd581aa 100644 (file)
@@ -56,12 +56,9 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
        mntget(mnt);
        dget(dentry);
 
-       if (!follow_down(&mnt, &dentry))
+       if (!autofs4_follow_mount(&mnt, &dentry))
                goto done;
 
-       while (d_mountpoint(dentry) && follow_down(&mnt, &dentry))
-               ;
-
        /* This is an autofs submount, we can't expire it */
        if (is_autofs4_dentry(dentry))
                goto done;
index 3765c047f157e76f4e1e760460db22e71c3744a0..2a771ec66956f92615de35694dc512f0144aedba 100644 (file)
@@ -205,7 +205,11 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
                struct vfsmount *fp_mnt = mntget(mnt);
                struct dentry *fp_dentry = dget(dentry);
 
-               while (follow_down(&fp_mnt, &fp_dentry) && d_mountpoint(fp_dentry));
+               if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
+                       dput(fp_dentry);
+                       mntput(fp_mnt);
+                       return -ENOENT;
+               }
 
                fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
                status = PTR_ERR(fp);
@@ -302,7 +306,14 @@ static int try_to_fill_dentry(struct dentry *dentry,
                
                DPRINTK("expire done status=%d", status);
                
-               return 0;
+               /*
+                * If the directory still exists the mount request must
+                * continue otherwise it can't be followed at the right
+                * time during the walk.
+                */
+               status = d_invalidate(dentry);
+               if (status != -EBUSY)
+                       return 0;
        }
 
        DPRINTK("dentry=%p %.*s ino=%p",
index 5a40d36e5a5101f178a92703b818487925db882d..fa2348dcd6718732c3f8bfb4ad2ecfe52c323aad 100644 (file)
@@ -191,6 +191,13 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
        }
 
        if ( !wq ) {
+               /* Can't wait for an expire if there's no mount */
+               if (notify == NFY_NONE && !d_mountpoint(dentry)) {
+                       kfree(name);
+                       up(&sbi->wq_sem);
+                       return -ENOENT;
+               }
+
                /* Create a new wait queue */
                wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
                if ( !wq ) {
index 009b8920c1fff5fe796bc08f42d06c1917636c66..dd9baabaf0166afff7a55c5692f48660553b9bfa 100644 (file)
@@ -316,6 +316,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        current->mm->brk = ex.a_bss +
                (current->mm->start_brk = N_BSSADDR(ex));
        current->mm->free_area_cache = current->mm->mmap_base;
+       current->mm->cached_hole_size = 0;
 
        set_mm_counter(current->mm, rss, 0);
        current->mm->mmap = NULL;
index f8f6b6b76179da87bfca266adadf360b10f2e91a..7976a238f0a3d60bb4c4a0d1fba0b3ad5183ad08 100644 (file)
@@ -775,6 +775,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
           change some of these later */
        set_mm_counter(current->mm, rss, 0);
        current->mm->free_area_cache = current->mm->mmap_base;
+       current->mm->cached_hole_size = 0;
        retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
                                 executable_stack);
        if (retval < 0) {
index 7e9e409feaa744d13e471c1209318a0a9ef138d3..0befa724ab98db16d6174b7bc1884137c97a2ea0 100644 (file)
@@ -528,7 +528,7 @@ static void free_more_memory(void)
        for_each_pgdat(pgdat) {
                zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
                if (*zones)
-                       try_to_free_pages(zones, GFP_NOFS, 0);
+                       try_to_free_pages(zones, GFP_NOFS);
        }
 }
 
index 2af3338f891bb17d069ec48a0323ecc710cf1ebd..3a9b6d179cbdf492da7924012fd85aa8241a64f1 100644 (file)
@@ -122,6 +122,9 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 
        start_addr = mm->free_area_cache;
 
+       if (len <= mm->cached_hole_size)
+               start_addr = TASK_UNMAPPED_BASE;
+
 full_search:
        addr = ALIGN(start_addr, HPAGE_SIZE);
 
index 6030956b894b907a91b95d9af667b728a414a4f7..7901ac9f97ab4728150c0ba68e11e48645f51a26 100644 (file)
@@ -193,12 +193,17 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
 
                /* Handle everything else.  Do name translation if there
                   is no Rock Ridge NM field. */
-               if (sbi->s_unhide == 'n') {
-                       /* Do not report hidden or associated files */
-                       if (de->flags[-sbi->s_high_sierra] & 5) {
-                               filp->f_pos += de_len;
-                               continue;
-                       }
+
+               /*
+                * Do not report hidden files if so instructed, or associated
+                * files unless instructed to do so
+                */
+               if ((sbi->s_hide == 'y' &&
+                               (de->flags[-sbi->s_high_sierra] & 1)) ||
+                     (sbi->s_showassoc =='n' &&
+                               (de->flags[-sbi->s_high_sierra] & 4))) {
+                       filp->f_pos += de_len;
+                       continue;
                }
 
                map = 1;
index abd7b12eeca74e074373598707ad7b2704146a87..1652de1b6cb9e0a57bb9d33f6dff568b3f84196d 100644 (file)
 
 #define BEQUIET
 
-#ifdef LEAK_CHECK
-static int check_malloc;
-static int check_bread;
-#endif
-
 static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
 static int isofs_hash(struct dentry *parent, struct qstr *qstr);
 static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
@@ -55,11 +50,6 @@ static void isofs_put_super(struct super_block *sb)
        }
 #endif
 
-#ifdef LEAK_CHECK
-       printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
-              check_malloc, check_bread);
-#endif
-
        kfree(sbi);
        sb->s_fs_info = NULL;
        return;
@@ -73,7 +63,7 @@ static kmem_cache_t *isofs_inode_cachep;
 static struct inode *isofs_alloc_inode(struct super_block *sb)
 {
        struct iso_inode_info *ei;
-       ei = (struct iso_inode_info *)kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
+       ei = kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -84,9 +74,9 @@ static void isofs_destroy_inode(struct inode *inode)
        kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
 {
-       struct iso_inode_info *ei = (struct iso_inode_info *) foo;
+       struct iso_inode_info *ei = foo;
 
        if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
            SLAB_CTOR_CONSTRUCTOR)
@@ -107,7 +97,8 @@ static int init_inodecache(void)
 static void destroy_inodecache(void)
 {
        if (kmem_cache_destroy(isofs_inode_cachep))
-               printk(KERN_INFO "iso_inode_cache: not all structures were freed\n");
+               printk(KERN_INFO "iso_inode_cache: not all structures were "
+                                       "freed\n");
 }
 
 static int isofs_remount(struct super_block *sb, int *flags, char *data)
@@ -144,7 +135,7 @@ static struct dentry_operations isofs_dentry_ops[] = {
        {
                .d_hash         = isofs_hashi_ms,
                .d_compare      = isofs_dentry_cmpi_ms,
-       }
+       },
 #endif
 };
 
@@ -153,7 +144,8 @@ struct iso9660_options{
        char rock;
        char joliet;
        char cruft;
-       char unhide;
+       char hide;
+       char showassoc;
        char nocompress;
        unsigned char check;
        unsigned int blocksize;
@@ -219,8 +211,8 @@ isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
 /*
  * Case insensitive compare of two isofs names.
  */
-static int
-isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
+static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a,
+                               struct qstr *b, int ms)
 {
        int alen, blen;
 
@@ -243,8 +235,8 @@ isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int
 /*
  * Case sensitive compare of two isofs names.
  */
-static int
-isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
+static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a,
+                                       struct qstr *b, int ms)
 {
        int alen, blen;
 
@@ -318,13 +310,15 @@ enum {
        Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
        Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
        Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
-       Opt_nocompress,
+       Opt_nocompress, Opt_hide, Opt_showassoc,
 };
 
 static match_table_t tokens = {
        {Opt_norock, "norock"},
        {Opt_nojoliet, "nojoliet"},
        {Opt_unhide, "unhide"},
+       {Opt_hide, "hide"},
+       {Opt_showassoc, "showassoc"},
        {Opt_cruft, "cruft"},
        {Opt_utf8, "utf8"},
        {Opt_iocharset, "iocharset=%s"},
@@ -356,7 +350,7 @@ static match_table_t tokens = {
        {Opt_err, NULL}
 };
 
-static int parse_options(char *options, struct iso9660_options * popt)
+static int parse_options(char *options, struct iso9660_options *popt)
 {
        char *p;
        int option;
@@ -365,7 +359,8 @@ static int parse_options(char *options, struct iso9660_options * popt)
        popt->rock = 'y';
        popt->joliet = 'y';
        popt->cruft = 'n';
-       popt->unhide = 'n';
+       popt->hide = 'n';
+       popt->showassoc = 'n';
        popt->check = 'u';              /* unset */
        popt->nocompress = 0;
        popt->blocksize = 1024;
@@ -398,8 +393,12 @@ static int parse_options(char *options, struct iso9660_options * popt)
                case Opt_nojoliet:
                        popt->joliet = 'n';
                        break;
+               case Opt_hide:
+                       popt->hide = 'y';
+                       break;
                case Opt_unhide:
-                       popt->unhide = 'y';
+               case Opt_showassoc:
+                       popt->showassoc = 'y';
                        break;
                case Opt_cruft:
                        popt->cruft = 'y';
@@ -493,7 +492,7 @@ static int parse_options(char *options, struct iso9660_options * popt)
  */
 #define WE_OBEY_THE_WRITTEN_STANDARDS 1
 
-static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
+static unsigned int isofs_get_last_session(struct super_block *sb, s32 session)
 {
        struct cdrom_multisession ms_info;
        unsigned int vol_desc_start;
@@ -518,7 +517,8 @@ static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
                printk(KERN_ERR "Invalid session number or type of track\n");
        }
        i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
-       if(session > 0) printk(KERN_ERR "Invalid session number\n");
+       if (session > 0)
+               printk(KERN_ERR "Invalid session number\n");
 #if 0
        printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
        if (i==0) {
@@ -557,13 +557,13 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
        struct iso9660_options          opt;
        struct isofs_sb_info          * sbi;
 
-       sbi = kmalloc(sizeof(struct isofs_sb_info), GFP_KERNEL);
+       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct isofs_sb_info));
+       memset(sbi, 0, sizeof(*sbi));
 
-       if (!parse_options((char *) data, &opt))
+       if (!parse_options((char *)data, &opt))
                goto out_freesbi;
 
        /*
@@ -792,7 +792,8 @@ root_found:
        sbi->s_rock = (opt.rock == 'y' ? 2 : 0);
        sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
        sbi->s_cruft = opt.cruft;
-       sbi->s_unhide = opt.unhide;
+       sbi->s_hide = opt.hide;
+       sbi->s_showassoc = opt.showassoc;
        sbi->s_uid = opt.uid;
        sbi->s_gid = opt.gid;
        sbi->s_utf8 = opt.utf8;
@@ -1002,7 +1003,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
                rv++;
        }
 
-
 abort:
        unlock_kernel();
        return rv;
@@ -1014,7 +1014,7 @@ abort:
 static int isofs_get_block(struct inode *inode, sector_t iblock,
                    struct buffer_head *bh_result, int create)
 {
-       if ( create ) {
+       if (create) {
                printk("isofs_get_block: Kernel tries to allocate a block\n");
                return -EROFS;
        }
@@ -1061,19 +1061,17 @@ static struct address_space_operations isofs_aops = {
 
 static inline void test_and_set_uid(uid_t *p, uid_t value)
 {
-       if(value) {
+       if (value)
                *p = value;
-       }
 }
 
 static inline void test_and_set_gid(gid_t *p, gid_t value)
 {
-        if(value) {
+        if (value)
                 *p = value;
-        }
 }
 
-static int isofs_read_level3_size(struct inode * inode)
+static int isofs_read_level3_size(struct inode *inode)
 {
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
@@ -1136,7 +1134,7 @@ static int isofs_read_level3_size(struct inode * inode)
                                bh = sb_bread(inode->i_sb, block);
                                if (!bh)
                                        goto out_noread;
-                               memcpy((void *) tmpde + slop, bh->b_data, offset);
+                               memcpy((void *)tmpde+slop, bh->b_data, offset);
                        }
                        de = tmpde;
                }
@@ -1150,12 +1148,11 @@ static int isofs_read_level3_size(struct inode * inode)
                more_entries = de->flags[-high_sierra] & 0x80;
 
                i++;
-               if(i > 100)
+               if (i > 100)
                        goto out_toomany;
-       } while(more_entries);
+       } while (more_entries);
 out:
-       if (tmpde)
-               kfree(tmpde);
+       kfree(tmpde);
        if (bh)
                brelse(bh);
        return 0;
@@ -1179,7 +1176,7 @@ out_toomany:
        goto out;
 }
 
-static void isofs_read_inode(struct inode * inode)
+static void isofs_read_inode(struct inode *inode)
 {
        struct super_block *sb = inode->i_sb;
        struct isofs_sb_info *sbi = ISOFS_SB(sb);
@@ -1249,7 +1246,7 @@ static void isofs_read_inode(struct inode * inode)
        ei->i_format_parm[2] = 0;
 
        ei->i_section_size = isonum_733 (de->size);
-       if(de->flags[-high_sierra] & 0x80) {
+       if (de->flags[-high_sierra] & 0x80) {
                if(isofs_read_level3_size(inode)) goto fail;
        } else {
                ei->i_next_section_block = 0;
@@ -1336,16 +1333,16 @@ static void isofs_read_inode(struct inode * inode)
                /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
                init_special_inode(inode, inode->i_mode, inode->i_rdev);
 
- out:
+out:
        if (tmpde)
                kfree(tmpde);
        if (bh)
                brelse(bh);
        return;
 
- out_badread:
+out_badread:
        printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
- fail:
+fail:
        make_bad_inode(inode);
        goto out;
 }
@@ -1394,11 +1391,8 @@ struct inode *isofs_iget(struct super_block *sb,
 
        hashval = (block << sb->s_blocksize_bits) | offset;
 
-       inode = iget5_locked(sb,
-                            hashval,
-                            &isofs_iget5_test,
-                            &isofs_iget5_set,
-                            &data);
+       inode = iget5_locked(sb, hashval, &isofs_iget5_test,
+                            &isofs_iget5_set, &data);
 
        if (inode && (inode->i_state & I_NEW)) {
                sb->s_op->read_inode(inode);
@@ -1408,36 +1402,6 @@ struct inode *isofs_iget(struct super_block *sb,
        return inode;
 }
 
-#ifdef LEAK_CHECK
-#undef malloc
-#undef free_s
-#undef sb_bread
-#undef brelse
-
-void * leak_check_malloc(unsigned int size){
-  void * tmp;
-  check_malloc++;
-  tmp = kmalloc(size, GFP_KERNEL);
-  return tmp;
-}
-
-void leak_check_free_s(void * obj, int size){
-  check_malloc--;
-  return kfree(obj);
-}
-
-struct buffer_head * leak_check_bread(struct super_block *sb, int block){
-  check_bread++;
-  return sb_bread(sb, block);
-}
-
-void leak_check_brelse(struct buffer_head * bh){
-  check_bread--;
-  return brelse(bh);
-}
-
-#endif
-
 static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
index 9ce7b51fb6141ea6b82d85687d490c74755591fb..38c75151fc66b60ec49f2b89df7a340c09ee344e 100644 (file)
@@ -47,6 +47,8 @@ struct isofs_sb_info {
        unsigned char s_nosuid;
        unsigned char s_nodev;
        unsigned char s_nocompress;
+       unsigned char s_hide;
+       unsigned char s_showassoc;
 
        mode_t s_mode;
        gid_t s_gid;
index 690edf37173c8c5d864a64a73de1e4a87796e6d6..e37e82b7cbf0127281fb12deca7475810906674a 100644 (file)
@@ -131,14 +131,16 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
                }
 
                /*
-                * Skip hidden or associated files unless unhide is set 
+                * Skip hidden or associated files unless hide or showassoc,
+                * respectively, is set
                 */
                match = 0;
                if (dlen > 0 &&
-                   (!(de->flags[-sbi->s_high_sierra] & 5)
-                    || sbi->s_unhide == 'y'))
-               {
-                       match = (isofs_cmp(dentry,dpnt,dlen) == 0);
+                       (sbi->s_hide =='n' ||
+                               (!(de->flags[-sbi->s_high_sierra] & 1))) &&
+                       (sbi->s_showassoc =='y' ||
+                               (!(de->flags[-sbi->s_high_sierra] & 4)))) {
+                       match = (isofs_cmp(dentry, dpnt, dlen) == 0);
                }
                if (match) {
                        isofs_normalize_block_and_offset(de,
@@ -146,11 +148,11 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
                                                         &offset_saved);
                         *block_rv = block_saved;
                         *offset_rv = offset_saved;
-                       if (bh) brelse(bh);
+                       brelse(bh);
                        return 1;
                }
        }
-       if (bh) brelse(bh);
+       brelse(bh);
        return 0;
 }
 
index 089e79c65585ae5fadb58ce1db43d5ee2bad7126..4326cb47f8fa267667311d2b65b361aa66508858 100644 (file)
 #include "isofs.h"
 #include "rock.h"
 
-/* These functions are designed to read the system areas of a directory record
+/*
+ * These functions are designed to read the system areas of a directory record
  * and extract relevant information.  There are different functions provided
  * depending upon what information we need at the time.  One function fills
  * out an inode structure, a second one extracts a filename, a third one
  * returns a symbolic link name, and a fourth one returns the extent number
- * for the file. */
-
-#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
-
-
-/* This is a way of ensuring that we have something in the system
-   use fields that is compatible with Rock Ridge */
-#define CHECK_SP(FAIL)                         \
-      if(rr->u.SP.magic[0] != 0xbe) FAIL;      \
-      if(rr->u.SP.magic[1] != 0xef) FAIL;       \
-      ISOFS_SB(inode->i_sb)->s_rock_offset=rr->u.SP.skip;
-/* We define a series of macros because each function must do exactly the
-   same thing in certain places.  We use the macros to ensure that everything
-   is done correctly */
-
-#define CONTINUE_DECLS \
-  int cont_extent = 0, cont_offset = 0, cont_size = 0;   \
-  void *buffer = NULL
-
-#define CHECK_CE                               \
-      {cont_extent = isonum_733(rr->u.CE.extent); \
-      cont_offset = isonum_733(rr->u.CE.offset); \
-      cont_size = isonum_733(rr->u.CE.size);}
-
-#define SETUP_ROCK_RIDGE(DE,CHR,LEN)                           \
-  {LEN= sizeof(struct iso_directory_record) + DE->name_len[0]; \
-  if(LEN & 1) LEN++;                                           \
-  CHR = ((unsigned char *) DE) + LEN;                          \
-  LEN = *((unsigned char *) DE) - LEN;                          \
-  if (LEN<0) LEN=0;                                             \
-  if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1)                \
-  {                                                             \
-     LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset;                \
-     CHR+=ISOFS_SB(inode->i_sb)->s_rock_offset;                \
-     if (LEN<0) LEN=0;                                          \
-  }                                                             \
-}                                     
-
-#define MAYBE_CONTINUE(LABEL,DEV) \
-  {if (buffer) { kfree(buffer); buffer = NULL; } \
-  if (cont_extent){ \
-    int block, offset, offset1; \
-    struct buffer_head * pbh; \
-    buffer = kmalloc(cont_size,GFP_KERNEL); \
-    if (!buffer) goto out; \
-    block = cont_extent; \
-    offset = cont_offset; \
-    offset1 = 0; \
-    pbh = sb_bread(DEV->i_sb, block); \
-    if(pbh){       \
-      if (offset > pbh->b_size || offset + cont_size > pbh->b_size){   \
-       brelse(pbh); \
-       goto out; \
-      } \
-      memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
-      brelse(pbh); \
-      chr = (unsigned char *) buffer; \
-      len = cont_size; \
-      cont_extent = 0; \
-      cont_size = 0; \
-      cont_offset = 0; \
-      goto LABEL; \
-    }    \
-    printk("Unable to read rock-ridge attributes\n");    \
-  }}
-
-/* return length of name field; 0: not found, -1: to be ignored */
-int get_rock_ridge_filename(struct iso_directory_record * de,
-                           char * retname, struct inode * inode)
+ * for the file.
+ */
+
+#define SIG(A,B) ((A) | ((B) << 8))    /* isonum_721() */
+
+struct rock_state {
+       void *buffer;
+       unsigned char *chr;
+       int len;
+       int cont_size;
+       int cont_extent;
+       int cont_offset;
+       struct inode *inode;
+};
+
+/*
+ * This is a way of ensuring that we have something in the system
+ * use fields that is compatible with Rock Ridge.  Return zero on success.
+ */
+
+static int check_sp(struct rock_ridge *rr, struct inode *inode)
 {
-  int len;
-  unsigned char * chr;
-  CONTINUE_DECLS;
-  int retnamlen = 0, truncate=0;
-  if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
-  *retname = 0;
-
-  SETUP_ROCK_RIDGE(de, chr, len);
- repeat:
-  {
-    struct rock_ridge * rr;
-    int sig;
-    
-    while (len > 2){ /* There may be one byte for padding somewhere */
-      rr = (struct rock_ridge *) chr;
-      if (rr->len < 3) goto out; /* Something got screwed up here */
-      sig = isonum_721(chr);
-      chr += rr->len; 
-      len -= rr->len;
-      if (len < 0) goto out;   /* corrupted isofs */
-
-      switch(sig){
-      case SIG('R','R'):
-       if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
-       break;
-      case SIG('S','P'):
-       CHECK_SP(goto out);
-       break;
-      case SIG('C','E'):
-       CHECK_CE;
-       break;
-      case SIG('N','M'):
-       if (truncate) break;
-       if (rr->len < 5) break;
-        /*
-        * If the flags are 2 or 4, this indicates '.' or '..'.
-        * We don't want to do anything with this, because it
-        * screws up the code that calls us.  We don't really
-        * care anyways, since we can just use the non-RR
-        * name.
-        */
-       if (rr->u.NM.flags & 6) {
-         break;
+       if (rr->u.SP.magic[0] != 0xbe)
+               return -1;
+       if (rr->u.SP.magic[1] != 0xef)
+               return -1;
+       ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
+       return 0;
+}
+
+static void setup_rock_ridge(struct iso_directory_record *de,
+                       struct inode *inode, struct rock_state *rs)
+{
+       rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
+       if (rs->len & 1)
+               (rs->len)++;
+       rs->chr = (unsigned char *)de + rs->len;
+       rs->len = *((unsigned char *)de) - rs->len;
+       if (rs->len < 0)
+               rs->len = 0;
+
+       if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
+               rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
+               rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
+               if (rs->len < 0)
+                       rs->len = 0;
+       }
+}
+
+static void init_rock_state(struct rock_state *rs, struct inode *inode)
+{
+       memset(rs, 0, sizeof(*rs));
+       rs->inode = inode;
+}
+
+/*
+ * Returns 0 if the caller should continue scanning, 1 if the scan must end
+ * and -ve on error.
+ */
+static int rock_continue(struct rock_state *rs)
+{
+       int ret = 1;
+       int blocksize = 1 << rs->inode->i_blkbits;
+       const int min_de_size = offsetof(struct rock_ridge, u);
+
+       kfree(rs->buffer);
+       rs->buffer = NULL;
+
+       if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
+           (unsigned)rs->cont_size > blocksize ||
+           (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
+               printk(KERN_NOTICE "rock: corrupted directory entry. "
+                       "extent=%d, offset=%d, size=%d\n",
+                       rs->cont_extent, rs->cont_offset, rs->cont_size);
+               ret = -EIO;
+               goto out;
        }
 
-       if (rr->u.NM.flags & ~1) {
-         printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
-         break;
+       if (rs->cont_extent) {
+               struct buffer_head *bh;
+
+               rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
+               if (!rs->buffer) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               ret = -EIO;
+               bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
+               if (bh) {
+                       memcpy(rs->buffer, bh->b_data + rs->cont_offset,
+                                       rs->cont_size);
+                       put_bh(bh);
+                       rs->chr = rs->buffer;
+                       rs->len = rs->cont_size;
+                       rs->cont_extent = 0;
+                       rs->cont_size = 0;
+                       rs->cont_offset = 0;
+                       return 0;
+               }
+               printk("Unable to read rock-ridge attributes\n");
+       }
+out:
+       kfree(rs->buffer);
+       rs->buffer = NULL;
+       return ret;
+}
+
+/*
+ * We think there's a record of type `sig' at rs->chr.  Parse the signature
+ * and make sure that there's really room for a record of that type.
+ */
+static int rock_check_overflow(struct rock_state *rs, int sig)
+{
+       int len;
+
+       switch (sig) {
+       case SIG('S', 'P'):
+               len = sizeof(struct SU_SP_s);
+               break;
+       case SIG('C', 'E'):
+               len = sizeof(struct SU_CE_s);
+               break;
+       case SIG('E', 'R'):
+               len = sizeof(struct SU_ER_s);
+               break;
+       case SIG('R', 'R'):
+               len = sizeof(struct RR_RR_s);
+               break;
+       case SIG('P', 'X'):
+               len = sizeof(struct RR_PX_s);
+               break;
+       case SIG('P', 'N'):
+               len = sizeof(struct RR_PN_s);
+               break;
+       case SIG('S', 'L'):
+               len = sizeof(struct RR_SL_s);
+               break;
+       case SIG('N', 'M'):
+               len = sizeof(struct RR_NM_s);
+               break;
+       case SIG('C', 'L'):
+               len = sizeof(struct RR_CL_s);
+               break;
+       case SIG('P', 'L'):
+               len = sizeof(struct RR_PL_s);
+               break;
+       case SIG('T', 'F'):
+               len = sizeof(struct RR_TF_s);
+               break;
+       case SIG('Z', 'F'):
+               len = sizeof(struct RR_ZF_s);
+               break;
+       default:
+               len = 0;
+               break;
        }
-       if((strlen(retname) + rr->len - 5) >= 254) {
-         truncate = 1;
-         break;
+       len += offsetof(struct rock_ridge, u);
+       if (len > rs->len) {
+               printk(KERN_NOTICE "rock: directory entry would overflow "
+                               "storage\n");
+               printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
+                               sig, len, rs->len);
+               return -EIO;
+       }
+       return 0;
+}
+
+/*
+ * return length of name field; 0: not found, -1: to be ignored
+ */
+int get_rock_ridge_filename(struct iso_directory_record *de,
+                           char *retname, struct inode *inode)
+{
+       struct rock_state rs;
+       struct rock_ridge *rr;
+       int sig;
+       int retnamlen = 0;
+       int truncate = 0;
+       int ret = 0;
+
+       if (!ISOFS_SB(inode->i_sb)->s_rock)
+               return 0;
+       *retname = 0;
+
+       init_rock_state(&rs, inode);
+       setup_rock_ridge(de, inode, &rs);
+repeat:
+
+       while (rs.len > 2) { /* There may be one byte for padding somewhere */
+               rr = (struct rock_ridge *)rs.chr;
+               if (rr->len < 3)
+                       goto out;       /* Something got screwed up here */
+               sig = isonum_721(rs.chr);
+               if (rock_check_overflow(&rs, sig))
+                       goto eio;
+               rs.chr += rr->len;
+               rs.len -= rr->len;
+               if (rs.len < 0)
+                       goto eio;       /* corrupted isofs */
+
+               switch (sig) {
+               case SIG('R', 'R'):
+                       if ((rr->u.RR.flags[0] & RR_NM) == 0)
+                               goto out;
+                       break;
+               case SIG('S', 'P'):
+                       if (check_sp(rr, inode))
+                               goto out;
+                       break;
+               case SIG('C', 'E'):
+                       rs.cont_extent = isonum_733(rr->u.CE.extent);
+                       rs.cont_offset = isonum_733(rr->u.CE.offset);
+                       rs.cont_size = isonum_733(rr->u.CE.size);
+                       break;
+               case SIG('N', 'M'):
+                       if (truncate)
+                               break;
+                       if (rr->len < 5)
+                               break;
+                       /*
+                        * If the flags are 2 or 4, this indicates '.' or '..'.
+                        * We don't want to do anything with this, because it
+                        * screws up the code that calls us.  We don't really
+                        * care anyways, since we can just use the non-RR
+                        * name.
+                        */
+                       if (rr->u.NM.flags & 6)
+                               break;
+
+                       if (rr->u.NM.flags & ~1) {
+                               printk("Unsupported NM flag settings (%d)\n",
+                                       rr->u.NM.flags);
+                               break;
+                       }
+                       if ((strlen(retname) + rr->len - 5) >= 254) {
+                               truncate = 1;
+                               break;
+                       }
+                       strncat(retname, rr->u.NM.name, rr->len - 5);
+                       retnamlen += rr->len - 5;
+                       break;
+               case SIG('R', 'E'):
+                       kfree(rs.buffer);
+                       return -1;
+               default:
+                       break;
+               }
        }
-       strncat(retname, rr->u.NM.name, rr->len - 5);
-       retnamlen += rr->len - 5;
-       break;
-      case SIG('R','E'):
-       if (buffer) kfree(buffer);
-       return -1;
-      default:
-       break;
-      }
-    }
-  }
-  MAYBE_CONTINUE(repeat,inode);
-  if (buffer) kfree(buffer);
-  return retnamlen; /* If 0, this file did not have a NM field */
- out:
-  if(buffer) kfree(buffer);
-  return 0;
+       ret = rock_continue(&rs);
+       if (ret == 0)
+               goto repeat;
+       if (ret == 1)
+               return retnamlen; /* If 0, this file did not have a NM field */
+out:
+       kfree(rs.buffer);
+       return ret;
+eio:
+       ret = -EIO;
+       goto out;
 }
 
 static int
 parse_rock_ridge_inode_internal(struct iso_directory_record *de,
                                struct inode *inode, int regard_xa)
 {
-  int len;
-  unsigned char * chr;
-  int symlink_len = 0;
-  CONTINUE_DECLS;
-
-  if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
-
-  SETUP_ROCK_RIDGE(de, chr, len);
-  if (regard_xa)
-   {
-     chr+=14;
-     len-=14;
-     if (len<0) len=0;
-   }
-   
- repeat:
-  {
-    int cnt, sig;
-    struct inode * reloc;
-    struct rock_ridge * rr;
-    int rootflag;
-    
-    while (len > 2){ /* There may be one byte for padding somewhere */
-      rr = (struct rock_ridge *) chr;
-      if (rr->len < 3) goto out; /* Something got screwed up here */
-      sig = isonum_721(chr);
-      chr += rr->len; 
-      len -= rr->len;
-      if (len < 0) goto out;   /* corrupted isofs */
-      
-      switch(sig){
+       int symlink_len = 0;
+       int cnt, sig;
+       struct inode *reloc;
+       struct rock_ridge *rr;
+       int rootflag;
+       struct rock_state rs;
+       int ret = 0;
+
+       if (!ISOFS_SB(inode->i_sb)->s_rock)
+               return 0;
+
+       init_rock_state(&rs, inode);
+       setup_rock_ridge(de, inode, &rs);
+       if (regard_xa) {
+               rs.chr += 14;
+               rs.len -= 14;
+               if (rs.len < 0)
+                       rs.len = 0;
+       }
+
+repeat:
+       while (rs.len > 2) { /* There may be one byte for padding somewhere */
+               rr = (struct rock_ridge *)rs.chr;
+               if (rr->len < 3)
+                       goto out;       /* Something got screwed up here */
+               sig = isonum_721(rs.chr);
+               if (rock_check_overflow(&rs, sig))
+                       goto eio;
+               rs.chr += rr->len;
+               rs.len -= rr->len;
+               if (rs.len < 0)
+                       goto eio;       /* corrupted isofs */
+
+               switch (sig) {
 #ifndef CONFIG_ZISOFS          /* No flag for SF or ZF */
-      case SIG('R','R'):
-       if((rr->u.RR.flags[0] & 
-           (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
-       break;
+               case SIG('R', 'R'):
+                       if ((rr->u.RR.flags[0] &
+                            (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
+                               goto out;
+                       break;
 #endif
-      case SIG('S','P'):
-       CHECK_SP(goto out);
-       break;
-      case SIG('C','E'):
-       CHECK_CE;
-       break;
-      case SIG('E','R'):
-       ISOFS_SB(inode->i_sb)->s_rock = 1;
-       printk(KERN_DEBUG "ISO 9660 Extensions: ");
-       { int p;
-         for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
-       }
-         printk("\n");
-       break;
-      case SIG('P','X'):
-       inode->i_mode  = isonum_733(rr->u.PX.mode);
-       inode->i_nlink = isonum_733(rr->u.PX.n_links);
-       inode->i_uid   = isonum_733(rr->u.PX.uid);
-       inode->i_gid   = isonum_733(rr->u.PX.gid);
-       break;
-      case SIG('P','N'):
-       { int high, low;
-         high = isonum_733(rr->u.PN.dev_high);
-         low = isonum_733(rr->u.PN.dev_low);
-         /*
-          * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
-          * then the high field is unused, and the device number is completely
-          * stored in the low field.  Some writers may ignore this subtlety,
-          * and as a result we test to see if the entire device number is
-          * stored in the low field, and use that.
-          */
-         if((low & ~0xff) && high == 0) {
-           inode->i_rdev = MKDEV(low >> 8, low & 0xff);
-         } else {
-           inode->i_rdev = MKDEV(high, low);
-         }
-       }
-       break;
-      case SIG('T','F'):
-       /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
-          Try to handle this correctly for either case. */
-       cnt = 0; /* Rock ridge never appears on a High Sierra disk */
-       if(rr->u.TF.flags & TF_CREATE) { 
-         inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
-         inode->i_ctime.tv_nsec = 0;
-       }
-       if(rr->u.TF.flags & TF_MODIFY) {
-         inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
-         inode->i_mtime.tv_nsec = 0;
-       }
-       if(rr->u.TF.flags & TF_ACCESS) {
-         inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
-         inode->i_atime.tv_nsec = 0;
-       }
-       if(rr->u.TF.flags & TF_ATTRIBUTES) { 
-         inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
-         inode->i_ctime.tv_nsec = 0;
-       } 
-       break;
-      case SIG('S','L'):
-       {int slen;
-        struct SL_component * slp;
-        struct SL_component * oldslp;
-        slen = rr->len - 5;
-        slp = &rr->u.SL.link;
-        inode->i_size = symlink_len;
-        while (slen > 1){
-          rootflag = 0;
-          switch(slp->flags &~1){
-          case 0:
-            inode->i_size += slp->len;
-            break;
-          case 2:
-            inode->i_size += 1;
-            break;
-          case 4:
-            inode->i_size += 2;
-            break;
-          case 8:
-            rootflag = 1;
-            inode->i_size += 1;
-            break;
-          default:
-            printk("Symlink component flag not implemented\n");
-          }
-          slen -= slp->len + 2;
-          oldslp = slp;
-          slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
-
-          if(slen < 2) {
-            if(    ((rr->u.SL.flags & 1) != 0) 
-                   && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
-            break;
-          }
-
-          /*
-           * If this component record isn't continued, then append a '/'.
-           */
-          if (!rootflag && (oldslp->flags & 1) == 0)
-                  inode->i_size += 1;
-        }
-       }
-       symlink_len = inode->i_size;
-       break;
-      case SIG('R','E'):
-       printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
-       goto out;
-      case SIG('C','L'):
-       ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
-       reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0);
-       if (!reloc)
-               goto out;
-       inode->i_mode = reloc->i_mode;
-       inode->i_nlink = reloc->i_nlink;
-       inode->i_uid = reloc->i_uid;
-       inode->i_gid = reloc->i_gid;
-       inode->i_rdev = reloc->i_rdev;
-       inode->i_size = reloc->i_size;
-       inode->i_blocks = reloc->i_blocks;
-       inode->i_atime = reloc->i_atime;
-       inode->i_ctime = reloc->i_ctime;
-       inode->i_mtime = reloc->i_mtime;
-       iput(reloc);
-       break;
+               case SIG('S', 'P'):
+                       if (check_sp(rr, inode))
+                               goto out;
+                       break;
+               case SIG('C', 'E'):
+                       rs.cont_extent = isonum_733(rr->u.CE.extent);
+                       rs.cont_offset = isonum_733(rr->u.CE.offset);
+                       rs.cont_size = isonum_733(rr->u.CE.size);
+                       break;
+               case SIG('E', 'R'):
+                       ISOFS_SB(inode->i_sb)->s_rock = 1;
+                       printk(KERN_DEBUG "ISO 9660 Extensions: ");
+                       {
+                               int p;
+                               for (p = 0; p < rr->u.ER.len_id; p++)
+                                       printk("%c", rr->u.ER.data[p]);
+                       }
+                       printk("\n");
+                       break;
+               case SIG('P', 'X'):
+                       inode->i_mode = isonum_733(rr->u.PX.mode);
+                       inode->i_nlink = isonum_733(rr->u.PX.n_links);
+                       inode->i_uid = isonum_733(rr->u.PX.uid);
+                       inode->i_gid = isonum_733(rr->u.PX.gid);
+                       break;
+               case SIG('P', 'N'):
+                       {
+                               int high, low;
+                               high = isonum_733(rr->u.PN.dev_high);
+                               low = isonum_733(rr->u.PN.dev_low);
+                               /*
+                                * The Rock Ridge standard specifies that if
+                                * sizeof(dev_t) <= 4, then the high field is
+                                * unused, and the device number is completely
+                                * stored in the low field.  Some writers may
+                                * ignore this subtlety,
+                                * and as a result we test to see if the entire
+                                * device number is
+                                * stored in the low field, and use that.
+                                */
+                               if ((low & ~0xff) && high == 0) {
+                                       inode->i_rdev =
+                                           MKDEV(low >> 8, low & 0xff);
+                               } else {
+                                       inode->i_rdev =
+                                           MKDEV(high, low);
+                               }
+                       }
+                       break;
+               case SIG('T', 'F'):
+                       /*
+                        * Some RRIP writers incorrectly place ctime in the
+                        * TF_CREATE field. Try to handle this correctly for
+                        * either case.
+                        */
+                       /* Rock ridge never appears on a High Sierra disk */
+                       cnt = 0;
+                       if (rr->u.TF.flags & TF_CREATE) {
+                               inode->i_ctime.tv_sec =
+                                   iso_date(rr->u.TF.times[cnt++].time,
+                                            0);
+                               inode->i_ctime.tv_nsec = 0;
+                       }
+                       if (rr->u.TF.flags & TF_MODIFY) {
+                               inode->i_mtime.tv_sec =
+                                   iso_date(rr->u.TF.times[cnt++].time,
+                                            0);
+                               inode->i_mtime.tv_nsec = 0;
+                       }
+                       if (rr->u.TF.flags & TF_ACCESS) {
+                               inode->i_atime.tv_sec =
+                                   iso_date(rr->u.TF.times[cnt++].time,
+                                            0);
+                               inode->i_atime.tv_nsec = 0;
+                       }
+                       if (rr->u.TF.flags & TF_ATTRIBUTES) {
+                               inode->i_ctime.tv_sec =
+                                   iso_date(rr->u.TF.times[cnt++].time,
+                                            0);
+                               inode->i_ctime.tv_nsec = 0;
+                       }
+                       break;
+               case SIG('S', 'L'):
+                       {
+                               int slen;
+                               struct SL_component *slp;
+                               struct SL_component *oldslp;
+                               slen = rr->len - 5;
+                               slp = &rr->u.SL.link;
+                               inode->i_size = symlink_len;
+                               while (slen > 1) {
+                                       rootflag = 0;
+                                       switch (slp->flags & ~1) {
+                                       case 0:
+                                               inode->i_size +=
+                                                   slp->len;
+                                               break;
+                                       case 2:
+                                               inode->i_size += 1;
+                                               break;
+                                       case 4:
+                                               inode->i_size += 2;
+                                               break;
+                                       case 8:
+                                               rootflag = 1;
+                                               inode->i_size += 1;
+                                               break;
+                                       default:
+                                               printk("Symlink component flag "
+                                                       "not implemented\n");
+                                       }
+                                       slen -= slp->len + 2;
+                                       oldslp = slp;
+                                       slp = (struct SL_component *)
+                                               (((char *)slp) + slp->len + 2);
+
+                                       if (slen < 2) {
+                                               if (((rr->u.SL.
+                                                     flags & 1) != 0)
+                                                   &&
+                                                   ((oldslp->
+                                                     flags & 1) == 0))
+                                                       inode->i_size +=
+                                                           1;
+                                               break;
+                                       }
+
+                                       /*
+                                        * If this component record isn't
+                                        * continued, then append a '/'.
+                                        */
+                                       if (!rootflag
+                                           && (oldslp->flags & 1) == 0)
+                                               inode->i_size += 1;
+                               }
+                       }
+                       symlink_len = inode->i_size;
+                       break;
+               case SIG('R', 'E'):
+                       printk(KERN_WARNING "Attempt to read inode for "
+                                       "relocated directory\n");
+                       goto out;
+               case SIG('C', 'L'):
+                       ISOFS_I(inode)->i_first_extent =
+                           isonum_733(rr->u.CL.location);
+                       reloc =
+                           isofs_iget(inode->i_sb,
+                                      ISOFS_I(inode)->i_first_extent,
+                                      0);
+                       if (!reloc)
+                               goto out;
+                       inode->i_mode = reloc->i_mode;
+                       inode->i_nlink = reloc->i_nlink;
+                       inode->i_uid = reloc->i_uid;
+                       inode->i_gid = reloc->i_gid;
+                       inode->i_rdev = reloc->i_rdev;
+                       inode->i_size = reloc->i_size;
+                       inode->i_blocks = reloc->i_blocks;
+                       inode->i_atime = reloc->i_atime;
+                       inode->i_ctime = reloc->i_ctime;
+                       inode->i_mtime = reloc->i_mtime;
+                       iput(reloc);
+                       break;
 #ifdef CONFIG_ZISOFS
-      case SIG('Z','F'):
-             if ( !ISOFS_SB(inode->i_sb)->s_nocompress ) {
-                     int algo;
-                     algo = isonum_721(rr->u.ZF.algorithm);
-                     if ( algo == SIG('p','z') ) {
-                             int block_shift = isonum_711(&rr->u.ZF.parms[1]);
-                             if ( block_shift < PAGE_CACHE_SHIFT || block_shift > 17 ) {
-                                     printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift);
-                             } else {
-                               /* Note: we don't change i_blocks here */
-                                     ISOFS_I(inode)->i_file_format = isofs_file_compressed;
-                               /* Parameters to compression algorithm (header size, block size) */
-                                     ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]);
-                                     ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]);
-                                     inode->i_size = isonum_733(rr->u.ZF.real_size);
-                             }
-                     } else {
-                             printk(KERN_WARNING "isofs: Unknown ZF compression algorithm: %c%c\n",
-                                    rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]);
-                     }
-             }
-             break;
+               case SIG('Z', 'F'): {
+                       int algo;
+
+                       if (ISOFS_SB(inode->i_sb)->s_nocompress)
+                               break;
+                       algo = isonum_721(rr->u.ZF.algorithm);
+                       if (algo == SIG('p', 'z')) {
+                               int block_shift =
+                                       isonum_711(&rr->u.ZF.parms[1]);
+                               if (block_shift < PAGE_CACHE_SHIFT
+                                               || block_shift > 17) {
+                                       printk(KERN_WARNING "isofs: "
+                                               "Can't handle ZF block "
+                                               "size of 2^%d\n",
+                                               block_shift);
+                               } else {
+                                       /*
+                                        * Note: we don't change
+                                        * i_blocks here
+                                        */
+                                       ISOFS_I(inode)->i_file_format =
+                                               isofs_file_compressed;
+                                       /*
+                                        * Parameters to compression
+                                        * algorithm (header size,
+                                        * block size)
+                                        */
+                                       ISOFS_I(inode)->i_format_parm[0] =
+                                               isonum_711(&rr->u.ZF.parms[0]);
+                                       ISOFS_I(inode)->i_format_parm[1] =
+                                               isonum_711(&rr->u.ZF.parms[1]);
+                                       inode->i_size =
+                                           isonum_733(rr->u.ZF.
+                                                      real_size);
+                               }
+                       } else {
+                               printk(KERN_WARNING
+                                      "isofs: Unknown ZF compression "
+                                               "algorithm: %c%c\n",
+                                      rr->u.ZF.algorithm[0],
+                                      rr->u.ZF.algorithm[1]);
+                       }
+                       break;
+               }
 #endif
-      default:
-       break;
-      }
-    }
-  }
-  MAYBE_CONTINUE(repeat,inode);
- out:
-  if(buffer) kfree(buffer);
-  return 0;
+               default:
+                       break;
+               }
+       }
+       ret = rock_continue(&rs);
+       if (ret == 0)
+               goto repeat;
+       if (ret == 1)
+               ret = 0;
+out:
+       kfree(rs.buffer);
+       return ret;
+eio:
+       ret = -EIO;
+       goto out;
 }
 
 static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
@@ -376,32 +566,32 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
                        if (slp->len > plimit - rpnt)
                                return NULL;
                        memcpy(rpnt, slp->text, slp->len);
-                       rpnt+=slp->len;
+                       rpnt += slp->len;
                        break;
                case 2:
                        if (rpnt >= plimit)
                                return NULL;
-                       *rpnt++='.';
+                       *rpnt++ = '.';
                        break;
                case 4:
                        if (2 > plimit - rpnt)
                                return NULL;
-                       *rpnt++='.';
-                       *rpnt++='.';
+                       *rpnt++ = '.';
+                       *rpnt++ = '.';
                        break;
                case 8:
                        if (rpnt >= plimit)
                                return NULL;
                        rootflag = 1;
-                       *rpnt++='/';
+                       *rpnt++ = '/';
                        break;
                default:
                        printk("Symlink component flag not implemented (%d)\n",
-                            slp->flags);
+                              slp->flags);
                }
                slen -= slp->len + 2;
                oldslp = slp;
-               slp = (struct SL_component *) ((char *) slp + slp->len + 2);
+               slp = (struct SL_component *)((char *)slp + slp->len + 2);
 
                if (slen < 2) {
                        /*
@@ -412,7 +602,7 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
                            !(oldslp->flags & 1)) {
                                if (rpnt >= plimit)
                                        return NULL;
-                               *rpnt++='/';
+                               *rpnt++ = '/';
                        }
                        break;
                }
@@ -423,59 +613,61 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
                if (!rootflag && !(oldslp->flags & 1)) {
                        if (rpnt >= plimit)
                                return NULL;
-                       *rpnt++='/';
+                       *rpnt++ = '/';
                }
        }
        return rpnt;
 }
 
-int parse_rock_ridge_inode(struct iso_directory_record * de,
-                          struct inode * inode)
+int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
 {
-   int result=parse_rock_ridge_inode_internal(de,inode,0);
-   /* if rockridge flag was reset and we didn't look for attributes
-    * behind eventual XA attributes, have a look there */
-   if ((ISOFS_SB(inode->i_sb)->s_rock_offset==-1)
-       &&(ISOFS_SB(inode->i_sb)->s_rock==2))
-     {
-       result=parse_rock_ridge_inode_internal(de,inode,14);
-     }
-   return result;
-}
+       int result = parse_rock_ridge_inode_internal(de, inode, 0);
 
-/* readpage() for symlinks: reads symlink contents into the page and either
-   makes it uptodate and returns 0 or returns error (-EIO) */
+       /*
+        * if rockridge flag was reset and we didn't look for attributes
+        * behind eventual XA attributes, have a look there
+        */
+       if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
+           && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
+               result = parse_rock_ridge_inode_internal(de, inode, 14);
+       }
+       return result;
+}
 
+/*
+ * readpage() for symlinks: reads symlink contents into the page and either
+ * makes it uptodate and returns 0 or returns error (-EIO)
+ */
 static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 {
        struct inode *inode = page->mapping->host;
-        struct iso_inode_info *ei = ISOFS_I(inode);
+       struct iso_inode_info *ei = ISOFS_I(inode);
        char *link = kmap(page);
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        struct buffer_head *bh;
        char *rpnt = link;
        unsigned char *pnt;
-       struct iso_directory_record *raw_inode;
-       CONTINUE_DECLS;
+       struct iso_directory_record *raw_de;
        unsigned long block, offset;
        int sig;
-       int len;
-       unsigned char *chr;
        struct rock_ridge *rr;
+       struct rock_state rs;
+       int ret;
 
        if (!ISOFS_SB(inode->i_sb)->s_rock)
                goto error;
 
+       init_rock_state(&rs, inode);
        block = ei->i_iget5_block;
        lock_kernel();
        bh = sb_bread(inode->i_sb, block);
        if (!bh)
                goto out_noread;
 
-        offset = ei->i_iget5_offset;
-       pnt = (unsigned char *) bh->b_data + offset;
+       offset = ei->i_iget5_offset;
+       pnt = (unsigned char *)bh->b_data + offset;
 
-       raw_inode = (struct iso_directory_record *) pnt;
+       raw_de = (struct iso_directory_record *)pnt;
 
        /*
         * If we go past the end of the buffer, there is some sort of error.
@@ -483,20 +675,24 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
        if (offset + *pnt > bufsize)
                goto out_bad_span;
 
-       /* Now test for possible Rock Ridge extensions which will override
-          some of these numbers in the inode structure. */
+       /*
+        * Now test for possible Rock Ridge extensions which will override
+        * some of these numbers in the inode structure.
+        */
 
-       SETUP_ROCK_RIDGE(raw_inode, chr, len);
+       setup_rock_ridge(raw_de, inode, &rs);
 
-      repeat:
-       while (len > 2) { /* There may be one byte for padding somewhere */
-               rr = (struct rock_ridge *) chr;
+repeat:
+       while (rs.len > 2) { /* There may be one byte for padding somewhere */
+               rr = (struct rock_ridge *)rs.chr;
                if (rr->len < 3)
                        goto out;       /* Something got screwed up here */
-               sig = isonum_721(chr);
-               chr += rr->len;
-               len -= rr->len;
-               if (len < 0)
+               sig = isonum_721(rs.chr);
+               if (rock_check_overflow(&rs, sig))
+                       goto out;
+               rs.chr += rr->len;
+               rs.len -= rr->len;
+               if (rs.len < 0)
                        goto out;       /* corrupted isofs */
 
                switch (sig) {
@@ -505,7 +701,8 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
                                goto out;
                        break;
                case SIG('S', 'P'):
-                       CHECK_SP(goto out);
+                       if (check_sp(rr, inode))
+                               goto out;
                        break;
                case SIG('S', 'L'):
                        rpnt = get_symlink_chunk(rpnt, rr,
@@ -515,14 +712,18 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
                        break;
                case SIG('C', 'E'):
                        /* This tells is if there is a continuation record */
-                       CHECK_CE;
+                       rs.cont_extent = isonum_733(rr->u.CE.extent);
+                       rs.cont_offset = isonum_733(rr->u.CE.offset);
+                       rs.cont_size = isonum_733(rr->u.CE.size);
                default:
                        break;
                }
        }
-       MAYBE_CONTINUE(repeat, inode);
-       if (buffer)
-               kfree(buffer);
+       ret = rock_continue(&rs);
+       if (ret == 0)
+               goto repeat;
+       if (ret < 0)
+               goto fail;
 
        if (rpnt == link)
                goto fail;
@@ -535,19 +736,18 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
        return 0;
 
        /* error exit from macro */
-      out:
-       if (buffer)
-               kfree(buffer);
+out:
+       kfree(rs.buffer);
        goto fail;
-      out_noread:
+out_noread:
        printk("unable to read i-node block");
        goto fail;
-      out_bad_span:
+out_bad_span:
        printk("symlink spans iso9660 blocks\n");
-      fail:
+fail:
        brelse(bh);
        unlock_kernel();
-      error:
+error:
        SetPageError(page);
        kunmap(page);
        unlock_page(page);
@@ -555,5 +755,5 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 }
 
 struct address_space_operations isofs_symlink_aops = {
-       .readpage       = rock_ridge_symlink_readpage
+       .readpage = rock_ridge_symlink_readpage
 };
index deaf5c8e8b4a5693665630bd7b17a2af79766417..ed09e2b086372f0954200e487814e8e12e315542 100644 (file)
@@ -1,85 +1,88 @@
-/* These structs are used by the system-use-sharing protocol, in which the
-   Rock Ridge extensions are embedded.  It is quite possible that other
-   extensions are present on the disk, and this is fine as long as they
-   all use SUSP */
-
-struct SU_SP{
-  unsigned char magic[2];
-  unsigned char skip;
-} __attribute__((packed));
-
-struct SU_CE{
-  char extent[8];
-  char offset[8];
-  char size[8];
+/*
+ * These structs are used by the system-use-sharing protocol, in which the
+ * Rock Ridge extensions are embedded.  It is quite possible that other
+ * extensions are present on the disk, and this is fine as long as they
+ * all use SUSP
+ */
+
+struct SU_SP_s {
+       unsigned char magic[2];
+       unsigned char skip;
+} __attribute__ ((packed));
+
+struct SU_CE_s {
+       char extent[8];
+       char offset[8];
+       char size[8];
 };
 
-struct SU_ER{
-  unsigned char len_id;
-  unsigned char len_des;
-  unsigned char len_src;
-  unsigned char ext_ver;
-  char data[0];
-} __attribute__((packed));
-
-struct RR_RR{
-  char flags[1];
-} __attribute__((packed));
-
-struct RR_PX{
-  char mode[8];
-  char n_links[8];
-  char uid[8];
-  char gid[8];
+struct SU_ER_s {
+       unsigned char len_id;
+       unsigned char len_des;
+       unsigned char len_src;
+       unsigned char ext_ver;
+       char data[0];
+} __attribute__ ((packed));
+
+struct RR_RR_s {
+       char flags[1];
+} __attribute__ ((packed));
+
+struct RR_PX_s {
+       char mode[8];
+       char n_links[8];
+       char uid[8];
+       char gid[8];
 };
 
-struct RR_PN{
-  char dev_high[8];
-  char dev_low[8];
+struct RR_PN_s {
+       char dev_high[8];
+       char dev_low[8];
 };
 
+struct SL_component {
+       unsigned char flags;
+       unsigned char len;
+       char text[0];
+} __attribute__ ((packed));
 
-struct SL_component{
-  unsigned char flags;
-  unsigned char len;
-  char text[0];
-} __attribute__((packed));
+struct RR_SL_s {
+       unsigned char flags;
+       struct SL_component link;
+} __attribute__ ((packed));
 
-struct RR_SL{
-  unsigned char flags;
-  struct SL_component link;
-} __attribute__((packed));
+struct RR_NM_s {
+       unsigned char flags;
+       char name[0];
+} __attribute__ ((packed));
 
-struct RR_NM{
-  unsigned char flags;
-  char name[0];
-} __attribute__((packed));
-
-struct RR_CL{
-  char location[8];
+struct RR_CL_s {
+       char location[8];
 };
 
-struct RR_PL{
-  char location[8];
+struct RR_PL_s {
+       char location[8];
 };
 
-struct stamp{
-  char time[7];
-} __attribute__((packed));
+struct stamp {
+       char time[7];
+} __attribute__ ((packed));
 
-struct RR_TF{
-  char flags;
-  struct stamp times[0];  /* Variable number of these beasts */
-} __attribute__((packed));
+struct RR_TF_s {
+       char flags;
+       struct stamp times[0];  /* Variable number of these beasts */
+} __attribute__ ((packed));
 
 /* Linux-specific extension for transparent decompression */
-struct RR_ZF{
-  char algorithm[2];
-  char parms[2];
-  char real_size[8];
+struct RR_ZF_s {
+       char algorithm[2];
+       char parms[2];
+       char real_size[8];
 };
 
-/* These are the bits and their meanings for flags in the TF structure. */
+/*
+ * These are the bits and their meanings for flags in the TF structure.
+ */
 #define TF_CREATE 1
 #define TF_MODIFY 2
 #define TF_ACCESS 4
@@ -89,31 +92,31 @@ struct RR_ZF{
 #define TF_EFFECTIVE 64
 #define TF_LONG_FORM 128
 
-struct rock_ridge{
-  char signature[2];
-  unsigned char len;
-  unsigned char version;
-  union{
-    struct SU_SP SP;
-    struct SU_CE CE;
-    struct SU_ER ER;
-    struct RR_RR RR;
-    struct RR_PX PX;
-    struct RR_PN PN;
-    struct RR_SL SL;
-    struct RR_NM NM;
-    struct RR_CL CL;
-    struct RR_PL PL;
-    struct RR_TF TF;
-    struct RR_ZF ZF;
-  } u;
+struct rock_ridge {
+       char signature[2];
+       unsigned char len;
+       unsigned char version;
+       union {
+               struct SU_SP_s SP;
+               struct SU_CE_s CE;
+               struct SU_ER_s ER;
+               struct RR_RR_s RR;
+               struct RR_PX_s PX;
+               struct RR_PN_s PN;
+               struct RR_SL_s SL;
+               struct RR_NM_s NM;
+               struct RR_CL_s CL;
+               struct RR_PL_s PL;
+               struct RR_TF_s TF;
+               struct RR_ZF_s ZF;
+       } u;
 };
 
-#define RR_PX 1   /* POSIX attributes */
-#define RR_PN 2   /* POSIX devices */
-#define RR_SL 4   /* Symbolic link */
-#define RR_NM 8   /* Alternate Name */
-#define RR_CL 16  /* Child link */
-#define RR_PL 32  /* Parent link */
-#define RR_RE 64  /* Relocation directory */
-#define RR_TF 128 /* Timestamps */
+#define RR_PX 1                        /* POSIX attributes */
+#define RR_PN 2                        /* POSIX devices */
+#define RR_SL 4                        /* Symbolic link */
+#define RR_NM 8                        /* Alternate Name */
+#define RR_CL 16               /* Child link */
+#define RR_PL 32               /* Parent link */
+#define RR_RE 64               /* Relocation directory */
+#define RR_TF 128              /* Timestamps */
index a60a3b3d8a7b1c31870dee3d947fe119a5787a5d..63a9fbf1ac51be4f8bf06d772c70d2c6083cd833 100644 (file)
@@ -219,6 +219,19 @@ static struct file_operations fragmentation_file_operations = {
        .release        = seq_release,
 };
 
+extern struct seq_operations zoneinfo_op;
+static int zoneinfo_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &zoneinfo_op);
+}
+
+static struct file_operations proc_zoneinfo_file_operations = {
+       .open           = zoneinfo_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
 static int version_read_proc(char *page, char **start, off_t off,
                                 int count, int *eof, void *data)
 {
@@ -589,6 +602,7 @@ void __init proc_misc_init(void)
        create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
        create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
        create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
+       create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
        create_seq_entry("diskstats", 0, &proc_diskstats_operations);
 #ifdef CONFIG_MODULES
        create_seq_entry("modules", 0, &proc_modules_operations);
index 3a1b8ca04ba601b37ffa5dadb8f9695272952e39..573bcc81bb82ae25caa4de0d0b779d562c87535b 100644 (file)
@@ -835,6 +835,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
        mnt->mnt_parent = mnt;
        mnt->mnt_namespace = current->namespace;
        up_write(&sb->s_umount);
+       free_secdata(secdata);
        put_filesystem(type);
        return mnt;
 out_sb:
index 997963e5362234809dbd14b6a4a52eb1628a75d5..c60e69431e11d746abc9b41d3c525c0ac65116d7 100644 (file)
  * File wide globals
  */
 
-STATIC kmem_cache_t *pagebuf_cache;
+STATIC kmem_cache_t *pagebuf_zone;
 STATIC kmem_shaker_t pagebuf_shake;
-STATIC int pagebuf_daemon_wakeup(int, unsigned int);
+STATIC int xfsbufd_wakeup(int, unsigned int);
 STATIC void pagebuf_delwri_queue(xfs_buf_t *, int);
-STATIC struct workqueue_struct *pagebuf_logio_workqueue;
-STATIC struct workqueue_struct *pagebuf_dataio_workqueue;
+
+STATIC struct workqueue_struct *xfslogd_workqueue;
+STATIC struct workqueue_struct *xfsdatad_workqueue;
 
 /*
  * Pagebuf debugging
@@ -123,9 +124,9 @@ ktrace_t *pagebuf_trace_buf;
 
 
 #define pagebuf_allocate(flags) \
-       kmem_zone_alloc(pagebuf_cache, pb_to_km(flags))
+       kmem_zone_alloc(pagebuf_zone, pb_to_km(flags))
 #define pagebuf_deallocate(pb) \
-       kmem_zone_free(pagebuf_cache, (pb));
+       kmem_zone_free(pagebuf_zone, (pb));
 
 /*
  * Page Region interfaces.
@@ -425,7 +426,7 @@ _pagebuf_lookup_pages(
                                        __FUNCTION__, gfp_mask);
 
                        XFS_STATS_INC(pb_page_retries);
-                       pagebuf_daemon_wakeup(0, gfp_mask);
+                       xfsbufd_wakeup(0, gfp_mask);
                        blk_congestion_wait(WRITE, HZ/50);
                        goto retry;
                }
@@ -1136,8 +1137,8 @@ pagebuf_iodone(
        if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
                if (schedule) {
                        INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb);
-                       queue_work(dataio ? pagebuf_dataio_workqueue :
-                               pagebuf_logio_workqueue, &pb->pb_iodone_work);
+                       queue_work(dataio ? xfsdatad_workqueue :
+                               xfslogd_workqueue, &pb->pb_iodone_work);
                } else {
                        pagebuf_iodone_work(pb);
                }
@@ -1562,16 +1563,6 @@ xfs_free_buftarg(
        kmem_free(btp, sizeof(*btp));
 }
 
-void
-xfs_incore_relse(
-       xfs_buftarg_t           *btp,
-       int                     delwri_only,
-       int                     wait)
-{
-       invalidate_bdev(btp->pbr_bdev, 1);
-       truncate_inode_pages(btp->pbr_mapping, 0LL);
-}
-
 STATIC int
 xfs_setsize_buftarg_flags(
        xfs_buftarg_t           *btp,
@@ -1742,27 +1733,27 @@ pagebuf_runall_queues(
 }
 
 /* Defines for pagebuf daemon */
-STATIC DECLARE_COMPLETION(pagebuf_daemon_done);
-STATIC struct task_struct *pagebuf_daemon_task;
-STATIC int pagebuf_daemon_active;
-STATIC int force_flush;
-STATIC int force_sleep;
+STATIC DECLARE_COMPLETION(xfsbufd_done);
+STATIC struct task_struct *xfsbufd_task;
+STATIC int xfsbufd_active;
+STATIC int xfsbufd_force_flush;
+STATIC int xfsbufd_force_sleep;
 
 STATIC int
-pagebuf_daemon_wakeup(
+xfsbufd_wakeup(
        int                     priority,
        unsigned int            mask)
 {
-       if (force_sleep)
+       if (xfsbufd_force_sleep)
                return 0;
-       force_flush = 1;
+       xfsbufd_force_flush = 1;
        barrier();
-       wake_up_process(pagebuf_daemon_task);
+       wake_up_process(xfsbufd_task);
        return 0;
 }
 
 STATIC int
-pagebuf_daemon(
+xfsbufd(
        void                    *data)
 {
        struct list_head        tmp;
@@ -1774,17 +1765,17 @@ pagebuf_daemon(
        daemonize("xfsbufd");
        current->flags |= PF_MEMALLOC;
 
-       pagebuf_daemon_task = current;
-       pagebuf_daemon_active = 1;
+       xfsbufd_task = current;
+       xfsbufd_active = 1;
        barrier();
 
        INIT_LIST_HEAD(&tmp);
        do {
                if (unlikely(current->flags & PF_FREEZE)) {
-                       force_sleep = 1;
+                       xfsbufd_force_sleep = 1;
                        refrigerator(PF_FREEZE);
                } else {
-                       force_sleep = 0;
+                       xfsbufd_force_sleep = 0;
                }
 
                set_current_state(TASK_INTERRUPTIBLE);
@@ -1797,7 +1788,7 @@ pagebuf_daemon(
                        ASSERT(pb->pb_flags & PBF_DELWRI);
 
                        if (!pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) {
-                               if (!force_flush &&
+                               if (!xfsbufd_force_flush &&
                                    time_before(jiffies,
                                                pb->pb_queuetime + age)) {
                                        pagebuf_unlock(pb);
@@ -1824,10 +1815,10 @@ pagebuf_daemon(
                if (as_list_len > 0)
                        purge_addresses();
 
-               force_flush = 0;
-       } while (pagebuf_daemon_active);
+               xfsbufd_force_flush = 0;
+       } while (xfsbufd_active);
 
-       complete_and_exit(&pagebuf_daemon_done, 0);
+       complete_and_exit(&xfsbufd_done, 0);
 }
 
 /*
@@ -1844,8 +1835,8 @@ xfs_flush_buftarg(
        xfs_buf_t               *pb, *n;
        int                     pincount = 0;
 
-       pagebuf_runall_queues(pagebuf_dataio_workqueue);
-       pagebuf_runall_queues(pagebuf_logio_workqueue);
+       pagebuf_runall_queues(xfsdatad_workqueue);
+       pagebuf_runall_queues(xfslogd_workqueue);
 
        INIT_LIST_HEAD(&tmp);
        spin_lock(&pbd_delwrite_lock);
@@ -1898,43 +1889,43 @@ xfs_flush_buftarg(
 }
 
 STATIC int
-pagebuf_daemon_start(void)
+xfs_buf_daemons_start(void)
 {
-       int             rval;
+       int             error = -ENOMEM;
 
-       pagebuf_logio_workqueue = create_workqueue("xfslogd");
-       if (!pagebuf_logio_workqueue)
-               return -ENOMEM;
+       xfslogd_workqueue = create_workqueue("xfslogd");
+       if (!xfslogd_workqueue)
+               goto out;
 
-       pagebuf_dataio_workqueue = create_workqueue("xfsdatad");
-       if (!pagebuf_dataio_workqueue) {
-               destroy_workqueue(pagebuf_logio_workqueue);
-               return -ENOMEM;
-       }
+       xfsdatad_workqueue = create_workqueue("xfsdatad");
+       if (!xfsdatad_workqueue)
+               goto out_destroy_xfslogd_workqueue;
 
-       rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES);
-       if (rval < 0) {
-               destroy_workqueue(pagebuf_logio_workqueue);
-               destroy_workqueue(pagebuf_dataio_workqueue);
-       }
+       error = kernel_thread(xfsbufd, NULL, CLONE_FS|CLONE_FILES);
+       if (error < 0)
+               goto out_destroy_xfsdatad_workqueue;
+       return 0;
 
-       return rval;
+ out_destroy_xfsdatad_workqueue:
+       destroy_workqueue(xfsdatad_workqueue);
+ out_destroy_xfslogd_workqueue:
+       destroy_workqueue(xfslogd_workqueue);
+ out:
+       return error;
 }
 
 /*
- * pagebuf_daemon_stop
- *
  * Note: do not mark as __exit, it is called from pagebuf_terminate.
  */
 STATIC void
-pagebuf_daemon_stop(void)
+xfs_buf_daemons_stop(void)
 {
-       pagebuf_daemon_active = 0;
+       xfsbufd_active = 0;
        barrier();
-       wait_for_completion(&pagebuf_daemon_done);
+       wait_for_completion(&xfsbufd_done);
 
-       destroy_workqueue(pagebuf_logio_workqueue);
-       destroy_workqueue(pagebuf_dataio_workqueue);
+       destroy_workqueue(xfslogd_workqueue);
+       destroy_workqueue(xfsdatad_workqueue);
 }
 
 /*
@@ -1944,27 +1935,37 @@ pagebuf_daemon_stop(void)
 int __init
 pagebuf_init(void)
 {
-       pagebuf_cache = kmem_cache_create("xfs_buf_t", sizeof(xfs_buf_t), 0,
-                       SLAB_HWCACHE_ALIGN, NULL, NULL);
-       if (pagebuf_cache == NULL) {
-               printk("XFS: couldn't init xfs_buf_t cache\n");
-               pagebuf_terminate();
-               return -ENOMEM;
-       }
+       int             error = -ENOMEM;
+
+       pagebuf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf");
+       if (!pagebuf_zone)
+               goto out;
 
 #ifdef PAGEBUF_TRACE
        pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP);
 #endif
 
-       pagebuf_daemon_start();
+       error = xfs_buf_daemons_start();
+       if (error)
+               goto out_free_buf_zone;
 
-       pagebuf_shake = kmem_shake_register(pagebuf_daemon_wakeup);
-       if (pagebuf_shake == NULL) {
-               pagebuf_terminate();
-               return -ENOMEM;
+       pagebuf_shake = kmem_shake_register(xfsbufd_wakeup);
+       if (!pagebuf_shake) {
+               error = -ENOMEM;
+               goto out_stop_daemons;
        }
 
        return 0;
+
+ out_stop_daemons:
+       xfs_buf_daemons_stop();
+ out_free_buf_zone:
+#ifdef PAGEBUF_TRACE
+       ktrace_free(pagebuf_trace_buf);
+#endif
+       kmem_zone_destroy(pagebuf_zone);
+ out:
+       return error;
 }
 
 
@@ -1976,12 +1977,12 @@ pagebuf_init(void)
 void
 pagebuf_terminate(void)
 {
-       pagebuf_daemon_stop();
+       xfs_buf_daemons_stop();
 
 #ifdef PAGEBUF_TRACE
        ktrace_free(pagebuf_trace_buf);
 #endif
 
-       kmem_zone_destroy(pagebuf_cache);
+       kmem_zone_destroy(pagebuf_zone);
        kmem_shake_deregister(pagebuf_shake);
 }
index 74deed8e6d9056d3b4faf01bd668c884c0a3f31e..3f8f69a66aeaba714b75a03a50c63b0fc6b59097 100644 (file)
@@ -576,7 +576,6 @@ extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int);
 extern void xfs_free_buftarg(xfs_buftarg_t *, int);
 extern void xfs_wait_buftarg(xfs_buftarg_t *);
 extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
-extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
 
 #define xfs_getsize_buftarg(buftarg) \
index 24fa3b101b93c89ea70cb068f3f256be1fd5e3e5..f1ce4323f56e905c499e3889734d878d82c7b566 100644 (file)
@@ -57,7 +57,9 @@
 #include <linux/smp_lock.h>
 
 static struct vm_operations_struct linvfs_file_vm_ops;
-
+#ifdef CONFIG_XFS_DMAPI
+static struct vm_operations_struct linvfs_dmapi_file_vm_ops;
+#endif
 
 STATIC inline ssize_t
 __linvfs_read(
@@ -388,6 +390,14 @@ done:
        return -error;
 }
 
+#ifdef CONFIG_XFS_DMAPI
+STATIC void
+linvfs_mmap_close(
+       struct vm_area_struct   *vma)
+{
+       xfs_dm_mm_put(vma);
+}
+#endif /* CONFIG_XFS_DMAPI */
 
 STATIC int
 linvfs_file_mmap(
@@ -399,16 +409,19 @@ linvfs_file_mmap(
        vattr_t         va = { .va_mask = XFS_AT_UPDATIME };
        int             error;
 
+       vma->vm_ops = &linvfs_file_vm_ops;
+
        if (vp->v_vfsp->vfs_flag & VFS_DMI) {
                xfs_mount_t     *mp = XFS_VFSTOM(vp->v_vfsp);
 
                error = -XFS_SEND_MMAP(mp, vma, 0);
                if (error)
                        return error;
+#ifdef CONFIG_XFS_DMAPI
+               vma->vm_ops = &linvfs_dmapi_file_vm_ops;
+#endif
        }
 
-       vma->vm_ops = &linvfs_file_vm_ops;
-
        VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
        if (!error)
                vn_revalidate(vp);      /* update Linux inode flags */
@@ -609,7 +622,15 @@ struct file_operations linvfs_dir_operations = {
 static struct vm_operations_struct linvfs_file_vm_ops = {
        .nopage         = filemap_nopage,
        .populate       = filemap_populate,
+};
+
+#ifdef CONFIG_XFS_DMAPI
+static struct vm_operations_struct linvfs_dmapi_file_vm_ops = {
+       .close          = linvfs_mmap_close,
+       .nopage         = filemap_nopage,
+       .populate       = filemap_populate,
 #ifdef HAVE_VMOP_MPROTECT
        .mprotect       = linvfs_mprotect,
 #endif
 };
+#endif /* CONFIG_XFS_DMAPI */
index 69809eef8a54b0999489ff3ef250c996596a32dc..05a447e51cc023c4d19f2aa4dd275d4b59d87db6 100644 (file)
@@ -1174,7 +1174,8 @@ xfs_ioc_xattr(
 
        switch (cmd) {
        case XFS_IOC_FSGETXATTR: {
-               va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS;
+               va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
+                            XFS_AT_NEXTENTS | XFS_AT_PROJID;
                VOP_GETATTR(vp, &va, 0, NULL, error);
                if (error)
                        return -error;
@@ -1182,6 +1183,7 @@ xfs_ioc_xattr(
                fa.fsx_xflags   = va.va_xflags;
                fa.fsx_extsize  = va.va_extsize;
                fa.fsx_nextents = va.va_nextents;
+               fa.fsx_projid   = va.va_projid;
 
                if (copy_to_user(arg, &fa, sizeof(fa)))
                        return -XFS_ERROR(EFAULT);
@@ -1196,9 +1198,10 @@ xfs_ioc_xattr(
                if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
                        attr_flags |= ATTR_NONBLOCK;
 
-               va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE;
+               va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
                va.va_xflags  = fa.fsx_xflags;
                va.va_extsize = fa.fsx_extsize;
+               va.va_projid  = fa.fsx_projid;
 
                VOP_SETATTR(vp, &va, attr_flags, NULL, error);
                if (!error)
@@ -1207,7 +1210,8 @@ xfs_ioc_xattr(
        }
 
        case XFS_IOC_FSGETXATTRA: {
-               va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS;
+               va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
+                            XFS_AT_ANEXTENTS | XFS_AT_PROJID;
                VOP_GETATTR(vp, &va, 0, NULL, error);
                if (error)
                        return -error;
@@ -1215,6 +1219,7 @@ xfs_ioc_xattr(
                fa.fsx_xflags   = va.va_xflags;
                fa.fsx_extsize  = va.va_extsize;
                fa.fsx_nextents = va.va_anextents;
+               fa.fsx_projid   = va.va_projid;
 
                if (copy_to_user(arg, &fa, sizeof(fa)))
                        return -XFS_ERROR(EFAULT);
index 71bb41019a12c16c9bf2ee4e879842e9d21f7320..42dc5e4662ed9f950506ba25fd7d1ead729251dc 100644 (file)
@@ -145,10 +145,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
 #define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val
 #define xfs_rotorstep          xfs_params.rotorstep.val
 
-#ifndef __smp_processor_id
-#define __smp_processor_id()   smp_processor_id()
+#ifndef raw_smp_processor_id
+#define raw_smp_processor_id() smp_processor_id()
 #endif
-#define current_cpu()          __smp_processor_id()
+#define current_cpu()          raw_smp_processor_id()
 #define current_pid()          (current->pid)
 #define current_fsuid(cred)    (current->fsuid)
 #define current_fsgid(cred)    (current->fsgid)
@@ -230,8 +230,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
  * field (see the QCMD macro in quota.h).  These macros help keep the
  * code portable - they are not visible from the syscall interface.
  */
-#define Q_XSETGQLIM    XQM_CMD(0x8)    /* set groups disk limits */
-#define Q_XGETGQUOTA   XQM_CMD(0x9)    /* get groups disk limits */
+#define Q_XSETGQLIM    XQM_CMD(8)      /* set groups disk limits */
+#define Q_XGETGQUOTA   XQM_CMD(9)      /* get groups disk limits */
+#define Q_XSETPQLIM    XQM_CMD(10)     /* set projects disk limits */
+#define Q_XGETPQUOTA   XQM_CMD(11)     /* get projects disk limits */
 
 /* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */
 /* we may well need to fine-tune this if it ever becomes an issue.  */
index aa9daaea6c34b2d98697b899e73ee10e4222e1bb..acab58c48043bd77c471c724090fbfe0156b120b 100644 (file)
@@ -209,30 +209,6 @@ unlock:
        return (-status);
 }
 
-/*
- * xfs_inval_cached_pages
- * 
- * This routine is responsible for keeping direct I/O and buffered I/O
- * somewhat coherent.  From here we make sure that we're at least
- * temporarily holding the inode I/O lock exclusively and then call
- * the page cache to flush and invalidate any cached pages.  If there
- * are no cached pages this routine will be very quick.
- */
-void
-xfs_inval_cached_pages(
-       vnode_t         *vp,
-       xfs_iocore_t    *io,
-       xfs_off_t       offset,
-       int             write,
-       int             relock)
-{
-       if (VN_CACHED(vp)) {
-               xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
-               VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
-       }
-
-}
-
 ssize_t                        /* bytes read, or (-)  error */
 xfs_read(
        bhv_desc_t              *bdp,
@@ -304,10 +280,11 @@ xfs_read(
        if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
            !(ioflags & IO_INVIS)) {
                vrwlock_t locktype = VRWLOCK_READ;
+               int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
 
                ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
                                        BHV_TO_VNODE(bdp), *offset, size,
-                                       FILP_DELAY_FLAG(file), &locktype);
+                                       dmflags, &locktype);
                if (ret) {
                        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
                        goto unlock_isem;
@@ -867,11 +844,15 @@ retry:
            !(ioflags & IO_INVIS)) {
 
                xfs_rwunlock(bdp, locktype);
+               if (need_isem)
+                       up(&inode->i_sem);
                error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
                                DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
                                0, 0, 0); /* Delay flag intentionally  unused */
                if (error)
-                       goto out_unlock_isem;
+                       goto out_nounlocks;
+               if (need_isem)
+                       down(&inode->i_sem);
                xfs_rwlock(bdp, locktype);
                pos = xip->i_d.di_size;
                ret = 0;
@@ -986,6 +967,7 @@ retry:
  out_unlock_isem:
        if (need_isem)
                up(&inode->i_sem);
+ out_nounlocks:
        return -error;
 }
 
index d723e35254a0b977b169e2bf65b6de34e27599b5..f197a720e394db5b1bca538a3f826882cc3b7f46 100644 (file)
@@ -94,8 +94,6 @@ extern int xfs_bdstrat_cb(struct xfs_buf *);
 
 extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
                                xfs_fsize_t, xfs_fsize_t);
-extern void xfs_inval_cached_pages(struct vnode        *, struct xfs_iocore *,
-                               xfs_off_t, int, int);
 extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
                                const struct iovec *, unsigned int,
                                loff_t *, int, struct cred *);
index 455e2b2fb9640dbf598e48ca77d9bb415edeb134..5fe9af38aa2063ac56c23ef7faa39a539b4161d1 100644 (file)
@@ -590,8 +590,10 @@ linvfs_sync_super(
        int             error;
        int             flags = SYNC_FSDATA;
 
-       if (wait)
-               flags |= SYNC_WAIT;
+       if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
+               flags = SYNC_QUIESCE;
+       else
+               flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
 
        VFS_SYNC(vfsp, flags, NULL, error);
        sb->s_dirt = 0;
@@ -701,7 +703,8 @@ linvfs_getxquota(
        struct vfs              *vfsp = LINVFS_GET_VFS(sb);
        int                     error, getmode;
 
-       getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA;
+       getmode = (type == USRQUOTA) ? Q_XGETQUOTA :
+                ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
        VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
        return -error;
 }
@@ -716,7 +719,8 @@ linvfs_setxquota(
        struct vfs              *vfsp = LINVFS_GET_VFS(sb);
        int                     error, setmode;
 
-       setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM;
+       setmode = (type == USRQUOTA) ? Q_XSETQLIM :
+                ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
        VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
        return -error;
 }
index 76493991578ffe30f039094f640f0578a50ac23d..7ee1f714e9babfcefe02864f9a785fcb4ab52973 100644 (file)
@@ -107,6 +107,7 @@ typedef enum {
 #define SYNC_FSDATA            0x0020  /* flush fs data (e.g. superblocks) */
 #define SYNC_REFCACHE          0x0040  /* prune some of the nfs ref cache */
 #define SYNC_REMOUNT           0x0080  /* remount readonly, no dummy LRs */
+#define SYNC_QUIESCE           0x0100  /* quiesce fileystem for a snapshot */
 
 typedef int    (*vfs_mount_t)(bhv_desc_t *,
                                struct xfs_mount_args *, struct cred *);
index a832d165f24ff6d7e84fded59529439f1a16cfb0..250cad54e8920e4226f3fab93c05b4b3afb44a0d 100644 (file)
@@ -411,13 +411,13 @@ vn_remove(
 /*  0 */               (void *)(__psint_t)(vk),                \
 /*  1 */               (void *)(s),                            \
 /*  2 */               (void *)(__psint_t) line,               \
-/*  3 */               (void *)(vn_count(vp)), \
+/*  3 */               (void *)(__psint_t)(vn_count(vp)),      \
 /*  4 */               (void *)(ra),                           \
 /*  5 */               (void *)(__psunsigned_t)(vp)->v_flag,   \
 /*  6 */               (void *)(__psint_t)current_cpu(),       \
 /*  7 */               (void *)(__psint_t)current_pid(),       \
 /*  8 */               (void *)__return_address,               \
-/*  9 */               0, 0, 0, 0, 0, 0, 0)
+/*  9 */               NULL, NULL, NULL, NULL, NULL, NULL, NULL)
 
 /*
  * Vnode tracing code.
index 00466c3194acc29f194adba50c1eb0e7b2ebebc0..a6e57c647be4f3ae7a9ada8f6508e13967f94c17 100644 (file)
@@ -426,7 +426,7 @@ typedef struct vattr {
        u_long          va_extsize;     /* file extent size */
        u_long          va_nextents;    /* number of extents in file */
        u_long          va_anextents;   /* number of attr extents in file */
-       int             va_projid;      /* project id */
+       prid_t          va_projid;      /* project id */
 } vattr_t;
 
 /*
index 740d20d331874cee3bec1c0d2257f08629747acb..46ce1e3ce1d6c04c90b93ec46d86d2e4f64651fc 100644 (file)
@@ -101,7 +101,7 @@ int xfs_dqerror_mod = 33;
  * is the d_id field. The idea is to fill in the entire q_core
  * when we read in the on disk dquot.
  */
-xfs_dquot_t *
+STATIC xfs_dquot_t *
 xfs_qm_dqinit(
        xfs_mount_t  *mp,
        xfs_dqid_t   id,
@@ -286,7 +286,9 @@ xfs_qm_adjust_dqlimits(
  * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
  * enforcement's off.
  * In contrast, warnings are a little different in that they don't
- * 'automatically' get started when limits get exceeded.
+ * 'automatically' get started when limits get exceeded.  They do
+ * get reset to zero, however, when we find the count to be under
+ * the soft limit (they are only ever set non-zero via userspace).
  */
 void
 xfs_qm_adjust_dqtimers(
@@ -315,6 +317,8 @@ xfs_qm_adjust_dqtimers(
                                INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
                        INT_SET(d->d_btimer, ARCH_CONVERT,
                                get_seconds() + XFS_QI_BTIMELIMIT(mp));
+               } else {
+                       d->d_bwarns = 0;
                }
        } else {
                if ((!d->d_blk_softlimit ||
@@ -336,6 +340,8 @@ xfs_qm_adjust_dqtimers(
                                INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
                        INT_SET(d->d_itimer, ARCH_CONVERT,
                                get_seconds() + XFS_QI_ITIMELIMIT(mp));
+               } else {
+                       d->d_iwarns = 0;
                }
        } else {
                if ((!d->d_ino_softlimit ||
@@ -357,6 +363,8 @@ xfs_qm_adjust_dqtimers(
                                INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
                        INT_SET(d->d_rtbtimer, ARCH_CONVERT,
                                get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
+               } else {
+                       d->d_rtbwarns = 0;
                }
        } else {
                if ((!d->d_rtb_softlimit ||
@@ -370,68 +378,6 @@ xfs_qm_adjust_dqtimers(
        }
 }
 
-/*
- * Increment or reset warnings of a given dquot.
- */
-int
-xfs_qm_dqwarn(
-       xfs_disk_dquot_t        *d,
-       uint                    flags)
-{
-       int     warned;
-
-       /*
-        * root's limits are not real limits.
-        */
-       if (!d->d_id)
-               return (0);
-
-       warned = 0;
-       if (INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
-           (INT_GET(d->d_bcount, ARCH_CONVERT) >=
-            INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
-               if (flags & XFS_QMOPT_DOWARN) {
-                       INT_MOD(d->d_bwarns, ARCH_CONVERT, +1);
-                       warned++;
-               }
-       } else {
-               if (!d->d_blk_softlimit ||
-                   (INT_GET(d->d_bcount, ARCH_CONVERT) <
-                    INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
-                       d->d_bwarns = 0;
-               }
-       }
-
-       if (INT_GET(d->d_ino_softlimit, ARCH_CONVERT) > 0 &&
-           (INT_GET(d->d_icount, ARCH_CONVERT) >=
-            INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
-               if (flags & XFS_QMOPT_DOWARN) {
-                       INT_MOD(d->d_iwarns, ARCH_CONVERT, +1);
-                       warned++;
-               }
-       } else {
-               if (!d->d_ino_softlimit ||
-                   (INT_GET(d->d_icount, ARCH_CONVERT) <
-                    INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
-                       d->d_iwarns = 0;
-               }
-       }
-#ifdef QUOTADEBUG
-       if (INT_GET(d->d_iwarns, ARCH_CONVERT))
-               cmn_err(CE_DEBUG,
-                       "--------@@Inode warnings running : %Lu >= %Lu",
-                       INT_GET(d->d_icount, ARCH_CONVERT),
-                       INT_GET(d->d_ino_softlimit, ARCH_CONVERT));
-       if (INT_GET(d->d_bwarns, ARCH_CONVERT))
-               cmn_err(CE_DEBUG,
-                       "--------@@Blks warnings running : %Lu >= %Lu",
-                       INT_GET(d->d_bcount, ARCH_CONVERT),
-                       INT_GET(d->d_blk_softlimit, ARCH_CONVERT));
-#endif
-       return (warned);
-}
-
-
 /*
  * initialize a buffer full of dquots and log the whole thing
  */
@@ -461,9 +407,9 @@ xfs_qm_init_dquot_blk(
        for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++)
                xfs_qm_dqinit_core(curid, type, d);
        xfs_trans_dquot_buf(tp, bp,
-                           type & XFS_DQ_USER ?
-                           XFS_BLI_UDQUOT_BUF :
-                           XFS_BLI_GDQUOT_BUF);
+                           (type & XFS_DQ_USER ? XFS_BLI_UDQUOT_BUF :
+                           ((type & XFS_DQ_PROJ) ? XFS_BLI_PDQUOT_BUF :
+                            XFS_BLI_GDQUOT_BUF)));
        xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1);
 }
 
@@ -544,8 +490,7 @@ xfs_qm_dqalloc(
         * the entire thing.
         */
        xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
-                             dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
-                             bp);
+                             dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
 
        if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
                goto error1;
@@ -675,8 +620,7 @@ xfs_qm_dqtobp(
        /*
         * A simple sanity check in case we got a corrupted dquot...
         */
-       if (xfs_qm_dqcheck(ddq, id,
-                          dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
+       if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
                           flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
                           "dqtobp")) {
                if (!(flags & XFS_QMOPT_DQREPAIR)) {
@@ -953,8 +897,8 @@ int
 xfs_qm_dqget(
        xfs_mount_t     *mp,
        xfs_inode_t     *ip,      /* locked inode (optional) */
-       xfs_dqid_t      id,       /* gid or uid, depending on type */
-       uint            type,     /* UDQUOT or GDQUOT */
+       xfs_dqid_t      id,       /* uid/projid/gid depending on type */
+       uint            type,     /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
        uint            flags,    /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
        xfs_dquot_t     **O_dqpp) /* OUT : locked incore dquot */
 {
@@ -965,6 +909,7 @@ xfs_qm_dqget(
 
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
        if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) ||
+           (! XFS_IS_PQUOTA_ON(mp) && type == XFS_DQ_PROJ) ||
            (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) {
                return (ESRCH);
        }
@@ -983,7 +928,9 @@ xfs_qm_dqget(
  again:
 
 #ifdef DEBUG
-       ASSERT(type == XFS_DQ_USER || type == XFS_DQ_GROUP);
+       ASSERT(type == XFS_DQ_USER ||
+              type == XFS_DQ_PROJ ||
+              type == XFS_DQ_GROUP);
        if (ip) {
                ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
                if (type == XFS_DQ_USER)
@@ -1306,8 +1253,8 @@ xfs_qm_dqflush(
                return (error);
        }
 
-       if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT), 0, XFS_QMOPT_DOWARN,
-                          "dqflush (incore copy)")) {
+       if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT),
+                          0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
                xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
                return XFS_ERROR(EIO);
        }
@@ -1459,7 +1406,8 @@ xfs_dqlock2(
 {
        if (d1 && d2) {
                ASSERT(d1 != d2);
-               if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) > INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
+               if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) >
+                   INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
                        xfs_dqlock(d2);
                        xfs_dqlock(d1);
                } else {
@@ -1582,8 +1530,7 @@ xfs_qm_dqprint(xfs_dquot_t *dqp)
        cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
        cmn_err(CE_DEBUG, "---- dquotID =  %d",
                (int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT));
-       cmn_err(CE_DEBUG, "---- type    =  %s",
-               XFS_QM_ISUDQ(dqp) ? "USR" : "GRP");
+       cmn_err(CE_DEBUG, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp));
        cmn_err(CE_DEBUG, "---- fs      =  0x%p", dqp->q_mount);
        cmn_err(CE_DEBUG, "---- blkno   =  0x%x", (int) dqp->q_blkno);
        cmn_err(CE_DEBUG, "---- boffset =  0x%x", (int) dqp->q_bufoffset);
index 0c3fe3175baa4a125c83dfaa3a3e3b6fc3de9d50..39175103c8e0ca5ec2c81a859d5dc846aa6dab0e 100644 (file)
@@ -114,25 +114,18 @@ typedef struct xfs_dquot {
 #define XFS_DQHOLD(dqp)                ((dqp)->q_nrefs++)
 
 /*
- * Quota Accounting flags
+ * Quota Accounting/Enforcement flags
  */
-#define XFS_ALL_QUOTA_ACCT     (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT)
-#define XFS_ALL_QUOTA_ENFD     (XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD)
-#define XFS_ALL_QUOTA_CHKD     (XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD)
-#define XFS_ALL_QUOTA_ACTV     (XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE)
-#define XFS_ALL_QUOTA_ACCT_ENFD (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
-                                XFS_GQUOTA_ACCT|XFS_GQUOTA_ENFD)
+#define XFS_ALL_QUOTA_ACCT     \
+               (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
+#define XFS_ALL_QUOTA_ENFD     (XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
+#define XFS_ALL_QUOTA_CHKD     (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
 
-#define XFS_IS_QUOTA_RUNNING(mp)  ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
-#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
-#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
-
-/*
- * Quota Limit Enforcement flags
- */
+#define XFS_IS_QUOTA_RUNNING(mp)       ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
 #define XFS_IS_QUOTA_ENFORCED(mp)      ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
-#define XFS_IS_UQUOTA_ENFORCED(mp)     ((mp)->m_qflags & XFS_UQUOTA_ENFD)
-#define XFS_IS_GQUOTA_ENFORCED(mp)     ((mp)->m_qflags & XFS_GQUOTA_ENFD)
+#define XFS_IS_UQUOTA_RUNNING(mp)      ((mp)->m_qflags & XFS_UQUOTA_ACCT)
+#define XFS_IS_PQUOTA_RUNNING(mp)      ((mp)->m_qflags & XFS_PQUOTA_ACCT)
+#define XFS_IS_GQUOTA_RUNNING(mp)      ((mp)->m_qflags & XFS_GQUOTA_ACCT)
 
 #ifdef DEBUG
 static inline int
@@ -167,6 +160,8 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
 #define XFS_DQ_IS_ON_FREELIST(dqp)  ((dqp)->dq_flnext != (dqp))
 #define XFS_DQ_IS_DIRTY(dqp)   ((dqp)->dq_flags & XFS_DQ_DIRTY)
 #define XFS_QM_ISUDQ(dqp)      ((dqp)->dq_flags & XFS_DQ_USER)
+#define XFS_QM_ISPDQ(dqp)      ((dqp)->dq_flags & XFS_DQ_PROJ)
+#define XFS_QM_ISGDQ(dqp)      ((dqp)->dq_flags & XFS_DQ_GROUP)
 #define XFS_DQ_TO_QINF(dqp)    ((dqp)->q_mount->m_quotainfo)
 #define XFS_DQ_TO_QIP(dqp)     (XFS_QM_ISUDQ(dqp) ? \
                                 XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
@@ -174,7 +169,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
 
 #define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \
                                     (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
-                                    (XFS_IS_GQUOTA_ON((d)->q_mount))))
+                                    (XFS_IS_OQUOTA_ON((d)->q_mount))))
 
 #ifdef XFS_DQUOT_TRACE
 /*
@@ -211,7 +206,6 @@ extern void         xfs_qm_adjust_dqtimers(xfs_mount_t *,
                                        xfs_disk_dquot_t *);
 extern void            xfs_qm_adjust_dqlimits(xfs_mount_t *,
                                        xfs_disk_dquot_t *);
-extern int             xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
 extern int             xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
                                        xfs_dqid_t, uint, uint, xfs_dquot_t **);
 extern void            xfs_qm_dqput(xfs_dquot_t *);
index a5425ee6e7bd534b0444456dedbfb79f550065f4..f5271b7b1e84196c2d1202cc4c630747b9f54183 100644 (file)
@@ -428,7 +428,7 @@ xfs_qm_dquot_logitem_committing(
 /*
  * This is the ops vector for dquots
  */
-struct xfs_item_ops xfs_dquot_item_ops = {
+STATIC struct xfs_item_ops xfs_dquot_item_ops = {
        .iop_size       = (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size,
        .iop_format     = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
                                        xfs_qm_dquot_logitem_format,
@@ -646,7 +646,7 @@ xfs_qm_qoffend_logitem_committing(xfs_qoff_logitem_t *qip, xfs_lsn_t commit_lsn)
        return;
 }
 
-struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
+STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
        .iop_size       = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
        .iop_format     = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
                                        xfs_qm_qoff_logitem_format,
@@ -669,7 +669,7 @@ struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
 /*
  * This is the ops vector shared by all quotaoff-start log items.
  */
-struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
+STATIC struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
        .iop_size       = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
        .iop_format     = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
                                        xfs_qm_qoff_logitem_format,
index 89f2cd656ebfd3969bd0a40af131d3d9c24f8c16..f665ca8f9e960c93c65d0cc31c244fded5f3e73a 100644 (file)
@@ -81,12 +81,18 @@ struct xfs_qm       *xfs_Gqm;
 
 kmem_zone_t    *qm_dqzone;
 kmem_zone_t    *qm_dqtrxzone;
-kmem_shaker_t  xfs_qm_shaker;
+STATIC kmem_shaker_t   xfs_qm_shaker;
 
 STATIC void    xfs_qm_list_init(xfs_dqlist_t *, char *, int);
 STATIC void    xfs_qm_list_destroy(xfs_dqlist_t *);
 
+STATIC void    xfs_qm_freelist_init(xfs_frlist_t *);
+STATIC void    xfs_qm_freelist_destroy(xfs_frlist_t *);
+STATIC int     xfs_qm_mplist_nowait(xfs_mount_t *);
+STATIC int     xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
+
 STATIC int     xfs_qm_init_quotainos(xfs_mount_t *);
+STATIC int     xfs_qm_init_quotainfo(xfs_mount_t *);
 STATIC int     xfs_qm_shake(int, unsigned int);
 
 #ifdef DEBUG
@@ -184,7 +190,7 @@ xfs_Gqm_init(void)
 /*
  * Destroy the global quota manager when its reference count goes to zero.
  */
-void
+STATIC void
 xfs_qm_destroy(
        struct xfs_qm   *xqm)
 {
@@ -304,9 +310,9 @@ xfs_qm_mount_quotainit(
        uint            flags)
 {
        /*
-        * User or group quotas has to be on.
+        * User, projects or group quotas has to be on.
         */
-       ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA));
+       ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
 
        /*
         * Initialize the flags in the mount structure. From this point
@@ -324,7 +330,11 @@ xfs_qm_mount_quotainit(
        if (flags & XFSMNT_GQUOTA) {
                mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
                if (flags & XFSMNT_GQUOTAENF)
-                       mp->m_qflags |= XFS_GQUOTA_ENFD;
+                       mp->m_qflags |= XFS_OQUOTA_ENFD;
+       } else if (flags & XFSMNT_PQUOTA) {
+               mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
+               if (flags & XFSMNT_PQUOTAENF)
+                       mp->m_qflags |= XFS_OQUOTA_ENFD;
        }
 }
 
@@ -357,11 +367,11 @@ xfs_qm_mount_quotas(
 
        /*
         * If a file system had quotas running earlier, but decided to
-        * mount without -o quota/uquota/gquota options, revoke the
+        * mount without -o uquota/pquota/gquota options, revoke the
         * quotachecked license, and bail out.
         */
        if (! XFS_IS_QUOTA_ON(mp) &&
-           (mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) {
+           (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT)) {
                mp->m_qflags = 0;
                goto write_changes;
        }
@@ -509,7 +519,7 @@ out:
  * Flush all dquots of the given file system to disk. The dquots are
  * _not_ purged from memory here, just their data written to disk.
  */
-int
+STATIC int
 xfs_qm_dqflush_all(
        xfs_mount_t     *mp,
        int             flags)
@@ -613,7 +623,7 @@ xfs_qm_detach_gdquots(
 STATIC int
 xfs_qm_dqpurge_int(
        xfs_mount_t     *mp,
-       uint            flags) /* QUOTAOFF/UMOUNTING/UQUOTA/GQUOTA */
+       uint            flags) /* QUOTAOFF/UMOUNTING/UQUOTA/PQUOTA/GQUOTA */
 {
        xfs_dquot_t     *dqp;
        uint            dqtype;
@@ -625,6 +635,7 @@ xfs_qm_dqpurge_int(
                return (0);
 
        dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0;
+       dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0;
        dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0;
 
        xfs_qm_mplist_lock(mp);
@@ -734,11 +745,11 @@ xfs_qm_dqattach_one(
 
        /*
         * udqhint is the i_udquot field in inode, and is non-NULL only
-        * when the type arg is XFS_DQ_GROUP. Its purpose is to save a
+        * when the type arg is group/project. Its purpose is to save a
         * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside
         * the user dquot.
         */
-       ASSERT(!udqhint || type == XFS_DQ_GROUP);
+       ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
        if (udqhint && !dolock)
                xfs_dqlock(udqhint);
 
@@ -897,8 +908,8 @@ xfs_qm_dqattach_grouphint(
 
 
 /*
- * Given a locked inode, attach dquot(s) to it, taking UQUOTAON / GQUOTAON
- * in to account.
+ * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
+ * into account.
  * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed.
  * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty
  * much made this code a complete mess, but it has been pretty useful.
@@ -937,8 +948,13 @@ xfs_qm_dqattach(
                nquotas++;
        }
        ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
-       if (XFS_IS_GQUOTA_ON(mp)) {
-               error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+       if (XFS_IS_OQUOTA_ON(mp)) {
+               error = XFS_IS_GQUOTA_ON(mp) ?
+                       xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+                                               flags & XFS_QMOPT_DQALLOC,
+                                               flags & XFS_QMOPT_DQLOCK,
+                                               ip->i_udquot, &ip->i_gdquot) :
+                       xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
                                                flags & XFS_QMOPT_DQALLOC,
                                                flags & XFS_QMOPT_DQLOCK,
                                                ip->i_udquot, &ip->i_gdquot);
@@ -989,7 +1005,7 @@ xfs_qm_dqattach(
                }
                if (XFS_IS_UQUOTA_ON(mp))
                        ASSERT(ip->i_udquot);
-               if (XFS_IS_GQUOTA_ON(mp))
+               if (XFS_IS_OQUOTA_ON(mp))
                        ASSERT(ip->i_gdquot);
        }
 #endif
@@ -1018,13 +1034,13 @@ xfs_qm_dqdetach(
 
        ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
        ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
-       if (ip->i_udquot)
-               xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
        if (ip->i_udquot) {
+               xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
                xfs_qm_dqrele(ip->i_udquot);
                ip->i_udquot = NULL;
        }
        if (ip->i_gdquot) {
+               xfs_dqtrace_entry_ino(ip->i_gdquot, "DQDETTACH", ip);
                xfs_qm_dqrele(ip->i_gdquot);
                ip->i_gdquot = NULL;
        }
@@ -1149,7 +1165,7 @@ xfs_qm_sync(
  * This initializes all the quota information that's kept in the
  * mount structure
  */
-int
+STATIC int
 xfs_qm_init_quotainfo(
        xfs_mount_t     *mp)
 {
@@ -1202,8 +1218,9 @@ xfs_qm_init_quotainfo(
         * and group quotas, at least not at this point.
         */
        error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0,
-                            (XFS_IS_UQUOTA_RUNNING(mp)) ?
-                            XFS_DQ_USER : XFS_DQ_GROUP,
+                            XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER : 
+                            (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
+                               XFS_DQ_PROJ),
                             XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
                             &dqp);
        if (! error) {
@@ -1234,6 +1251,10 @@ xfs_qm_init_quotainfo(
                                INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ?
                                INT_GET(ddqp->d_iwarns, ARCH_CONVERT) :
                                XFS_QM_IWARNLIMIT;
+               qinf->qi_rtbwarnlimit =
+                               INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) ?
+                               INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) :
+                               XFS_QM_RTBWARNLIMIT;
                qinf->qi_bhardlimit =
                                INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT);
                qinf->qi_bsoftlimit =
@@ -1259,6 +1280,7 @@ xfs_qm_init_quotainfo(
                qinf->qi_rtbtimelimit = XFS_QM_RTBTIMELIMIT;
                qinf->qi_bwarnlimit = XFS_QM_BWARNLIMIT;
                qinf->qi_iwarnlimit = XFS_QM_IWARNLIMIT;
+               qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT;
        }
 
        return (0);
@@ -1366,13 +1388,20 @@ xfs_qm_dqget_noattach(
                ASSERT(udqp);
        }
 
-       if (XFS_IS_GQUOTA_ON(mp)) {
+       if (XFS_IS_OQUOTA_ON(mp)) {
                ASSERT(ip->i_gdquot == NULL);
                if (udqp)
                        xfs_dqunlock(udqp);
-               if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_gid, XFS_DQ_GROUP,
-                                        XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
-                                        &gdqp))) {
+               error = XFS_IS_GQUOTA_ON(mp) ?
+                               xfs_qm_dqget(mp, ip,
+                                            ip->i_d.di_gid, XFS_DQ_GROUP,
+                                            XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
+                                            &gdqp) :
+                               xfs_qm_dqget(mp, ip,
+                                            ip->i_d.di_projid, XFS_DQ_PROJ,
+                                            XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
+                                            &gdqp);
+               if (error) {
                        if (udqp)
                                xfs_qm_dqrele(udqp);
                        ASSERT(error != ESRCH);
@@ -1521,8 +1550,10 @@ xfs_qm_reset_dqcounts(
                INT_SET(ddq->d_rtbcount, ARCH_CONVERT, 0ULL);
                INT_SET(ddq->d_btimer, ARCH_CONVERT, (time_t)0);
                INT_SET(ddq->d_itimer, ARCH_CONVERT, (time_t)0);
+               INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, (time_t)0);
                INT_SET(ddq->d_bwarns, ARCH_CONVERT, 0UL);
                INT_SET(ddq->d_iwarns, ARCH_CONVERT, 0UL);
+               INT_SET(ddq->d_rtbwarns, ARCH_CONVERT, 0UL);
                ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
        }
 
@@ -1541,11 +1572,14 @@ xfs_qm_dqiter_bufs(
        int             error;
        int             notcommitted;
        int             incr;
+       int             type;
 
        ASSERT(blkcnt > 0);
        notcommitted = 0;
        incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ?
                XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt;
+       type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER :
+               (flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP);
        error = 0;
 
        /*
@@ -1564,9 +1598,7 @@ xfs_qm_dqiter_bufs(
                if (error)
                        break;
 
-               (void) xfs_qm_reset_dqcounts(mp, bp, firstid,
-                                            flags & XFS_QMOPT_UQUOTA ?
-                                            XFS_DQ_USER : XFS_DQ_GROUP);
+               (void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
                xfs_bdwrite(mp, bp);
                /*
                 * goto the next block.
@@ -1578,7 +1610,7 @@ xfs_qm_dqiter_bufs(
 }
 
 /*
- * Iterate over all allocated USR/GRP dquots in the system, calling a
+ * Iterate over all allocated USR/GRP/PRJ dquots in the system, calling a
  * caller supplied function for every chunk of dquots that we find.
  */
 STATIC int
@@ -1849,7 +1881,7 @@ xfs_qm_dqusage_adjust(
                xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
                xfs_qm_dqput(udqp);
        }
-       if (XFS_IS_GQUOTA_ON(mp)) {
+       if (XFS_IS_OQUOTA_ON(mp)) {
                ASSERT(gdqp);
                xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
                xfs_qm_dqput(gdqp);
@@ -1898,7 +1930,7 @@ xfs_qm_quotacheck(
        cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
 
        /*
-        * First we go thru all the dquots on disk, USR and GRP, and reset
+        * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
         * their counters to zero. We need a clean slate.
         * We don't log our changes till later.
         */
@@ -1909,9 +1941,10 @@ xfs_qm_quotacheck(
        }
 
        if ((gip = XFS_QI_GQIP(mp))) {
-               if ((error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA)))
+               if ((error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ?
+                                       XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA)))
                        goto error_return;
-               flags |= XFS_GQUOTA_CHKD;
+               flags |= XFS_OQUOTA_CHKD;
        }
 
        do {
@@ -1938,7 +1971,7 @@ xfs_qm_quotacheck(
        if (error) {
                xfs_qm_dqpurge_all(mp,
                                   XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA|
-                                  XFS_QMOPT_QUOTAOFF);
+                                  XFS_QMOPT_PQUOTA|XFS_QMOPT_QUOTAOFF);
                goto error_return;
        }
        /*
@@ -1961,7 +1994,7 @@ xfs_qm_quotacheck(
         * quotachecked status, since we won't be doing accounting for
         * that type anymore.
         */
-       mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_UQUOTA_CHKD);
+       mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
        mp->m_qflags |= flags;
 
        XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++");
@@ -2013,7 +2046,7 @@ xfs_qm_init_quotainos(
                                             0, 0, &uip, 0)))
                                return XFS_ERROR(error);
                }
-               if (XFS_IS_GQUOTA_ON(mp) &&
+               if (XFS_IS_OQUOTA_ON(mp) &&
                    mp->m_sb.sb_gquotino != NULLFSINO) {
                        ASSERT(mp->m_sb.sb_gquotino > 0);
                        if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -2043,10 +2076,12 @@ xfs_qm_init_quotainos(
 
                flags &= ~XFS_QMOPT_SBVERSION;
        }
-       if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
-               if ((error = xfs_qm_qino_alloc(mp, &gip,
-                                             sbflags | XFS_SB_GQUOTINO,
-                                             flags | XFS_QMOPT_GQUOTA))) {
+       if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
+               flags |= (XFS_IS_GQUOTA_ON(mp) ?
+                               XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
+               error = xfs_qm_qino_alloc(mp, &gip,
+                                         sbflags | XFS_SB_GQUOTINO, flags);
+               if (error) {
                        if (uip)
                                VN_RELE(XFS_ITOV(uip));
 
@@ -2452,6 +2487,7 @@ xfs_qm_vop_dqalloc(
        xfs_inode_t     *ip,
        uid_t           uid,
        gid_t           gid,
+       prid_t          prid,
        uint            flags,
        xfs_dquot_t     **O_udqpp,
        xfs_dquot_t     **O_gdqpp)
@@ -2483,8 +2519,7 @@ xfs_qm_vop_dqalloc(
        }
 
        uq = gq = NULL;
-       if ((flags & XFS_QMOPT_UQUOTA) &&
-           XFS_IS_UQUOTA_ON(mp)) {
+       if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
                if (ip->i_d.di_uid != uid) {
                        /*
                         * What we need is the dquot that has this uid, and
@@ -2522,8 +2557,7 @@ xfs_qm_vop_dqalloc(
                        xfs_dqunlock(uq);
                }
        }
-       if ((flags & XFS_QMOPT_GQUOTA) &&
-           XFS_IS_GQUOTA_ON(mp)) {
+       if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
                if (ip->i_d.di_gid != gid) {
                        xfs_iunlock(ip, lockflags);
                        if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
@@ -2546,6 +2580,29 @@ xfs_qm_vop_dqalloc(
                        XFS_DQHOLD(gq);
                        xfs_dqunlock(gq);
                }
+       } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
+               if (ip->i_d.di_projid != prid) {
+                       xfs_iunlock(ip, lockflags);
+                       if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
+                                                XFS_DQ_PROJ,
+                                                XFS_QMOPT_DQALLOC |
+                                                XFS_QMOPT_DOWARN,
+                                                &gq))) {
+                               if (uq)
+                                       xfs_qm_dqrele(uq);
+                               ASSERT(error != ENOENT);
+                               return (error);
+                       }
+                       xfs_dqunlock(gq);
+                       lockflags = XFS_ILOCK_SHARED;
+                       xfs_ilock(ip, lockflags);
+               } else {
+                       ASSERT(ip->i_gdquot);
+                       gq = ip->i_gdquot;
+                       xfs_dqlock(gq);
+                       XFS_DQHOLD(gq);
+                       xfs_dqunlock(gq);
+               }
        }
        if (uq)
                xfs_dqtrace_entry_ino(uq, "DQALLOC", ip);
@@ -2574,6 +2631,9 @@ xfs_qm_vop_chown(
        xfs_dquot_t     *newdq)
 {
        xfs_dquot_t     *prevdq;
+       uint            bfield = XFS_IS_REALTIME_INODE(ip) ?
+                                XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
+
        ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
        ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
 
@@ -2582,20 +2642,12 @@ xfs_qm_vop_chown(
        ASSERT(prevdq);
        ASSERT(prevdq != newdq);
 
-       xfs_trans_mod_dquot(tp, prevdq,
-                           XFS_TRANS_DQ_BCOUNT,
-                           -(ip->i_d.di_nblocks));
-       xfs_trans_mod_dquot(tp, prevdq,
-                           XFS_TRANS_DQ_ICOUNT,
-                           -1);
+       xfs_trans_mod_dquot(tp, prevdq, bfield, -(ip->i_d.di_nblocks));
+       xfs_trans_mod_dquot(tp, prevdq, XFS_TRANS_DQ_ICOUNT, -1);
 
        /* the sparkling new dquot */
-       xfs_trans_mod_dquot(tp, newdq,
-                           XFS_TRANS_DQ_BCOUNT,
-                           ip->i_d.di_nblocks);
-       xfs_trans_mod_dquot(tp, newdq,
-                           XFS_TRANS_DQ_ICOUNT,
-                           1);
+       xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_d.di_nblocks);
+       xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1);
 
        /*
         * Take an extra reference, because the inode
@@ -2611,7 +2663,7 @@ xfs_qm_vop_chown(
 }
 
 /*
- * Quota reservations for setattr(AT_UID|AT_GID).
+ * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
  */
 int
 xfs_qm_vop_chown_reserve(
@@ -2623,7 +2675,7 @@ xfs_qm_vop_chown_reserve(
 {
        int             error;
        xfs_mount_t     *mp;
-       uint            delblks;
+       uint            delblks, blkflags;
        xfs_dquot_t     *unresudq, *unresgdq, *delblksudq, *delblksgdq;
 
        ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2632,6 +2684,8 @@ xfs_qm_vop_chown_reserve(
 
        delblks = ip->i_delayed_blks;
        delblksudq = delblksgdq = unresudq = unresgdq = NULL;
+       blkflags = XFS_IS_REALTIME_INODE(ip) ?
+                       XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
 
        if (XFS_IS_UQUOTA_ON(mp) && udqp &&
            ip->i_d.di_uid != (uid_t)INT_GET(udqp->q_core.d_id, ARCH_CONVERT)) {
@@ -2646,18 +2700,22 @@ xfs_qm_vop_chown_reserve(
                        unresudq = ip->i_udquot;
                }
        }
-       if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
-           ip->i_d.di_gid != INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) {
-               delblksgdq = gdqp;
-               if (delblks) {
-                       ASSERT(ip->i_gdquot);
-                       unresgdq = ip->i_gdquot;
+       if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
+               if ((XFS_IS_GQUOTA_ON(ip->i_mount) && ip->i_d.di_gid !=
+                               INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) ||
+                   (XFS_IS_PQUOTA_ON(ip->i_mount) && ip->i_d.di_projid !=
+                               INT_GET(gdqp->q_core.d_id, ARCH_CONVERT))) {
+                       delblksgdq = gdqp;
+                       if (delblks) {
+                               ASSERT(ip->i_gdquot);
+                               unresgdq = ip->i_gdquot;
+                       }
                }
        }
 
        if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
                                delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
-                               flags | XFS_QMOPT_RES_REGBLKS)))
+                               flags | blkflags)))
                return (error);
 
        /*
@@ -2674,11 +2732,11 @@ xfs_qm_vop_chown_reserve(
                ASSERT(unresudq || unresgdq);
                if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
                                delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
-                               flags | XFS_QMOPT_RES_REGBLKS)))
+                               flags | blkflags)))
                        return (error);
                xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
                                unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
-                               XFS_QMOPT_RES_REGBLKS);
+                               blkflags);
        }
 
        return (0);
@@ -2751,7 +2809,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
 }
 
 /* ------------- list stuff -----------------*/
-void
+STATIC void
 xfs_qm_freelist_init(xfs_frlist_t *ql)
 {
        ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql;
@@ -2760,7 +2818,7 @@ xfs_qm_freelist_init(xfs_frlist_t *ql)
        ql->qh_nelems = 0;
 }
 
-void
+STATIC void
 xfs_qm_freelist_destroy(xfs_frlist_t *ql)
 {
        xfs_dquot_t     *dqp, *nextdqp;
@@ -2786,7 +2844,7 @@ xfs_qm_freelist_destroy(xfs_frlist_t *ql)
        ASSERT(ql->qh_nelems == 0);
 }
 
-void
+STATIC void
 xfs_qm_freelist_insert(xfs_frlist_t *ql, xfs_dquot_t *dq)
 {
        dq->dq_flnext = ql->qh_next;
@@ -2816,7 +2874,7 @@ xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq)
        xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq);
 }
 
-int
+STATIC int
 xfs_qm_dqhashlock_nowait(
        xfs_dquot_t *dqp)
 {
@@ -2836,7 +2894,7 @@ xfs_qm_freelist_lock_nowait(
        return (locked);
 }
 
-int
+STATIC int
 xfs_qm_mplist_nowait(
        xfs_mount_t     *mp)
 {
index dcf1a7a831d8ab1a62ffeb2b23689b10f23fbe72..b03eecf3b6cb19c4dba39596ce440178ebd858fd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -133,8 +133,9 @@ typedef struct xfs_quotainfo {
        time_t           qi_btimelimit;  /* limit for blks timer */
        time_t           qi_itimelimit;  /* limit for inodes timer */
        time_t           qi_rtbtimelimit;/* limit for rt blks timer */
-       xfs_qwarncnt_t   qi_bwarnlimit;  /* limit for num warnings */
-       xfs_qwarncnt_t   qi_iwarnlimit;  /* limit for num warnings */
+       xfs_qwarncnt_t   qi_bwarnlimit;  /* limit for blks warnings */
+       xfs_qwarncnt_t   qi_iwarnlimit;  /* limit for inodes warnings */
+       xfs_qwarncnt_t   qi_rtbwarnlimit;/* limit for rt blks warnings */
        mutex_t          qi_quotaofflock;/* to serialize quotaoff */
        xfs_filblks_t    qi_dqchunklen;  /* # BBs in a chunk of dqs */
        uint             qi_dqperchunk;  /* # ondisk dqs in above chunk */
@@ -176,6 +177,7 @@ typedef struct xfs_dquot_acct {
 
 #define XFS_QM_BWARNLIMIT      5
 #define XFS_QM_IWARNLIMIT      5
+#define XFS_QM_RTBWARNLIMIT    5
 
 #define XFS_QM_LOCK(xqm)       (mutex_lock(&xqm##_lock, PINOD))
 #define XFS_QM_UNLOCK(xqm)     (mutex_unlock(&xqm##_lock))
@@ -184,7 +186,6 @@ typedef struct xfs_dquot_acct {
 
 extern void            xfs_mount_reset_sbqflags(xfs_mount_t *);
 
-extern int             xfs_qm_init_quotainfo(xfs_mount_t *);
 extern void            xfs_qm_destroy_quotainfo(xfs_mount_t *);
 extern int             xfs_qm_mount_quotas(xfs_mount_t *, int);
 extern void            xfs_qm_mount_quotainit(xfs_mount_t *, uint);
@@ -203,7 +204,7 @@ extern void         xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
 
 /* vop stuff */
 extern int             xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *,
-                                       uid_t, gid_t, uint,
+                                       uid_t, gid_t, prid_t, uint,
                                        xfs_dquot_t **, xfs_dquot_t **);
 extern void            xfs_qm_vop_dqattach_and_dqmod_newinode(
                                        xfs_trans_t *, xfs_inode_t *,
@@ -215,14 +216,9 @@ extern int         xfs_qm_vop_chown_reserve(xfs_trans_t *, xfs_inode_t *,
                                        xfs_dquot_t *, xfs_dquot_t *, uint);
 
 /* list stuff */
-extern void            xfs_qm_freelist_init(xfs_frlist_t *);
-extern void            xfs_qm_freelist_destroy(xfs_frlist_t *);
-extern void            xfs_qm_freelist_insert(xfs_frlist_t *, xfs_dquot_t *);
 extern void            xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *);
 extern void            xfs_qm_freelist_unlink(xfs_dquot_t *);
 extern int             xfs_qm_freelist_lock_nowait(xfs_qm_t *);
-extern int             xfs_qm_mplist_nowait(xfs_mount_t *);
-extern int             xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
 
 /* system call interface */
 extern int             xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t);
index be67d9c265f8ffc762f83f0081177f3e73bd1a3b..dc3c37a1e1585702eeb814da992b216b57f4c96d 100644 (file)
 #define MNTOPT_NOQUOTA "noquota"       /* no quotas */
 #define MNTOPT_USRQUOTA        "usrquota"      /* user quota enabled */
 #define MNTOPT_GRPQUOTA        "grpquota"      /* group quota enabled */
+#define MNTOPT_PRJQUOTA        "prjquota"      /* project quota enabled */
 #define MNTOPT_UQUOTA  "uquota"        /* user quota (IRIX variant) */
 #define MNTOPT_GQUOTA  "gquota"        /* group quota (IRIX variant) */
+#define MNTOPT_PQUOTA  "pquota"        /* project quota (IRIX variant) */
 #define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
 #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
+#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
 #define MNTOPT_QUOTANOENF  "qnoenforce"        /* same as uqnoenforce */
 
 STATIC int
@@ -109,6 +112,14 @@ xfs_qm_parseargs(
                        args->flags |= XFSMNT_UQUOTA;
                        args->flags &= ~XFSMNT_UQUOTAENF;
                        referenced = 1;
+               } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
+                          !strcmp(this_char, MNTOPT_PRJQUOTA)) {
+                       args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
+                       referenced = 1;
+               } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
+                       args->flags |= XFSMNT_PQUOTA;
+                       args->flags &= ~XFSMNT_PQUOTAENF;
+                       referenced = 1;
                } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
                           !strcmp(this_char, MNTOPT_GRPQUOTA)) {
                        args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
@@ -127,6 +138,12 @@ xfs_qm_parseargs(
                        *this_char++ = ',';
        }
 
+       if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
+               cmn_err(CE_WARN,
+                       "XFS: cannot mount with both project and group quota");
+               return XFS_ERROR(EINVAL);
+       }
+
        PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
        if (!error && !referenced)
                bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
@@ -148,13 +165,19 @@ xfs_qm_showargs(
                        seq_puts(m, "," MNTOPT_UQUOTANOENF);
        }
 
+       if (mp->m_qflags & XFS_PQUOTA_ACCT) {
+               (mp->m_qflags & XFS_OQUOTA_ENFD) ?
+                       seq_puts(m, "," MNTOPT_PRJQUOTA) :
+                       seq_puts(m, "," MNTOPT_PQUOTANOENF);
+       }
+
        if (mp->m_qflags & XFS_GQUOTA_ACCT) {
-               (mp->m_qflags & XFS_GQUOTA_ENFD) ?
+               (mp->m_qflags & XFS_OQUOTA_ENFD) ?
                        seq_puts(m, "," MNTOPT_GRPQUOTA) :
                        seq_puts(m, "," MNTOPT_GQUOTANOENF);
        }
 
-       if (!(mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT)))
+       if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
                seq_puts(m, "," MNTOPT_NOQUOTA);
 
        PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
@@ -171,7 +194,7 @@ xfs_qm_mount(
        struct xfs_mount        *mp = XFS_VFSTOM(vfsp);
        int                     error;
 
-       if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA))
+       if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
                xfs_qm_mount_quotainit(mp, args->flags);
        PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error);
        return error;
@@ -255,16 +278,17 @@ xfs_qm_newmount(
        uint            *quotaflags)
 {
        uint            quotaondisk;
-       uint            uquotaondisk = 0, gquotaondisk = 0;
+       uint            uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
 
        *quotaflags = 0;
        *needquotamount = B_FALSE;
 
        quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
-               mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT);
+                               (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
 
        if (quotaondisk) {
                uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT;
+               pquotaondisk = mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT;
                gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT;
        }
 
@@ -277,13 +301,16 @@ xfs_qm_newmount(
 
        if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
            (!uquotaondisk &&  XFS_IS_UQUOTA_ON(mp)) ||
+            (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
+           (!pquotaondisk &&  XFS_IS_PQUOTA_ON(mp)) ||
             (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
-           (!gquotaondisk &&  XFS_IS_GQUOTA_ON(mp)))  &&
+           (!gquotaondisk &&  XFS_IS_OQUOTA_ON(mp)))  &&
            xfs_dev_is_read_only(mp, "changing quota state")) {
                cmn_err(CE_WARN,
-                       "XFS: please mount with%s%s%s.",
+                       "XFS: please mount with%s%s%s%s.",
                        (!quotaondisk ? "out quota" : ""),
                        (uquotaondisk ? " usrquota" : ""),
+                       (pquotaondisk ? " prjquota" : ""),
                        (gquotaondisk ? " grpquota" : ""));
                return XFS_ERROR(EPERM);
        }
@@ -359,7 +386,7 @@ xfs_qm_dqrele_null(
 }
 
 
-struct xfs_qmops xfs_qmcore_xfs = {
+STATIC struct xfs_qmops xfs_qmcore_xfs = {
        .xfs_qminit             = xfs_qm_newmount,
        .xfs_qmdone             = xfs_qm_unmount_quotadestroy,
        .xfs_qmmount            = xfs_qm_endmount,
index 229f5b5a2d25e9ffec948fa050c3decb478efe64..68e98962dbefe0db3f303204c97c53b82b6da975 100644 (file)
@@ -118,40 +118,41 @@ xfs_qm_quotactl(
         * The following commands are valid even when quotaoff.
         */
        switch (cmd) {
+       case Q_XQUOTARM:
                /*
-                * truncate quota files. quota must be off.
+                * Truncate quota files. quota must be off.
                 */
-             case Q_XQUOTARM:
                if (XFS_IS_QUOTA_ON(mp) || addr == NULL)
                        return XFS_ERROR(EINVAL);
                if (vfsp->vfs_flag & VFS_RDONLY)
                        return XFS_ERROR(EROFS);
                return (xfs_qm_scall_trunc_qfiles(mp,
                               xfs_qm_import_qtype_flags(*(uint *)addr)));
+
+       case Q_XGETQSTAT:
                /*
                 * Get quota status information.
                 */
-             case Q_XGETQSTAT:
                return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
 
+       case Q_XQUOTAON:
                /*
-                * QUOTAON for root f/s and quota enforcement on others..
-                * Quota accounting for non-root f/s's must be turned on
-                * at mount time.
+                * QUOTAON - enabling quota enforcement.
+                * Quota accounting must be turned on at mount time.
                 */
-             case Q_XQUOTAON:
                if (addr == NULL)
                        return XFS_ERROR(EINVAL);
                if (vfsp->vfs_flag & VFS_RDONLY)
                        return XFS_ERROR(EROFS);
                return (xfs_qm_scall_quotaon(mp,
                                          xfs_qm_import_flags(*(uint *)addr)));
-             case Q_XQUOTAOFF:
+
+       case Q_XQUOTAOFF:
                if (vfsp->vfs_flag & VFS_RDONLY)
                        return XFS_ERROR(EROFS);
                break;
 
-             default:
+       default:
                break;
        }
 
@@ -159,7 +160,7 @@ xfs_qm_quotactl(
                return XFS_ERROR(ESRCH);
 
        switch (cmd) {
-             case Q_XQUOTAOFF:
+       case Q_XQUOTAOFF:
                if (vfsp->vfs_flag & VFS_RDONLY)
                        return XFS_ERROR(EROFS);
                error = xfs_qm_scall_quotaoff(mp,
@@ -167,42 +168,39 @@ xfs_qm_quotactl(
                                            B_FALSE);
                break;
 
-               /*
-                * Defaults to XFS_GETUQUOTA.
-                */
-             case Q_XGETQUOTA:
+       case Q_XGETQUOTA:
                error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
                                        (fs_disk_quota_t *)addr);
                break;
-               /*
-                * Set limits, both hard and soft. Defaults to Q_SETUQLIM.
-                */
-             case Q_XSETQLIM:
+       case Q_XGETGQUOTA:
+               error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
+                                       (fs_disk_quota_t *)addr);
+               break;
+       case Q_XGETPQUOTA:
+               error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
+                                       (fs_disk_quota_t *)addr);
+               break;
+
+       case Q_XSETQLIM:
                if (vfsp->vfs_flag & VFS_RDONLY)
                        return XFS_ERROR(EROFS);
                error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
                                             (fs_disk_quota_t *)addr);
                break;
-
-              case Q_XSETGQLIM:
+       case Q_XSETGQLIM:
                if (vfsp->vfs_flag & VFS_RDONLY)
                        return XFS_ERROR(EROFS);
                error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
                                             (fs_disk_quota_t *)addr);
                break;
-
-
-             case Q_XGETGQUOTA:
-               error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
-                                       (fs_disk_quota_t *)addr);
+       case Q_XSETPQLIM:
+               if (vfsp->vfs_flag & VFS_RDONLY)
+                       return XFS_ERROR(EROFS);
+               error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
+                                            (fs_disk_quota_t *)addr);
                break;
 
-               /*
-                * Quotas are entirely undefined after quotaoff in XFS quotas.
-                * For instance, there's no way to set limits when quotaoff.
-                */
-
-             default:
+       default:
                error = XFS_ERROR(EINVAL);
                break;
        }
@@ -286,8 +284,12 @@ xfs_qm_scall_quotaoff(
        }
        if (flags & XFS_GQUOTA_ACCT) {
                dqtype |= XFS_QMOPT_GQUOTA;
-               flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
+               flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
                inactivate_flags |= XFS_GQUOTA_ACTIVE;
+       } else if (flags & XFS_PQUOTA_ACCT) {
+               dqtype |= XFS_QMOPT_PQUOTA;
+               flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
+               inactivate_flags |= XFS_PQUOTA_ACTIVE;
        }
 
        /*
@@ -364,7 +366,8 @@ xfs_qm_scall_quotaoff(
        /*
         * If quotas is completely disabled, close shop.
         */
-       if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
+       if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
+           ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
                mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
                xfs_qm_destroy_quotainfo(mp);
                return (0);
@@ -378,7 +381,7 @@ xfs_qm_scall_quotaoff(
                XFS_PURGE_INODE(XFS_QI_UQIP(mp));
                XFS_QI_UQIP(mp) = NULL;
        }
-       if ((dqtype & XFS_QMOPT_GQUOTA) && XFS_QI_GQIP(mp)) {
+       if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && XFS_QI_GQIP(mp)) {
                XFS_PURGE_INODE(XFS_QI_GQIP(mp));
                XFS_QI_GQIP(mp) = NULL;
        }
@@ -411,7 +414,8 @@ xfs_qm_scall_trunc_qfiles(
                }
        }
 
-       if ((flags & XFS_DQ_GROUP) && mp->m_sb.sb_gquotino != NULLFSINO) {
+       if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
+           mp->m_sb.sb_gquotino != NULLFSINO) {
                error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
                if (! error) {
                        (void) xfs_truncate_file(mp, qip);
@@ -434,7 +438,7 @@ xfs_qm_scall_quotaon(
        uint            flags)
 {
        int             error;
-       unsigned long s;
+       unsigned long   s;
        uint            qf;
        uint            accflags;
        __int64_t       sbflags;
@@ -468,9 +472,13 @@ xfs_qm_scall_quotaon(
            (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
            (flags & XFS_UQUOTA_ENFD))
            ||
+           ((flags & XFS_PQUOTA_ACCT) == 0 &&
+           (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
+           (flags & XFS_OQUOTA_ENFD))
+           ||
            ((flags & XFS_GQUOTA_ACCT) == 0 &&
            (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
-           (flags & XFS_GQUOTA_ENFD))) {
+           (flags & XFS_OQUOTA_ENFD))) {
                qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
                        flags, mp->m_sb.sb_qflags);
                return XFS_ERROR(EINVAL);
@@ -504,6 +512,10 @@ xfs_qm_scall_quotaon(
         */
        if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
             (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
+            ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
+            (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
+            ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
+            (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
            (flags & XFS_ALL_QUOTA_ENFD) == 0)
                return (0);
 
@@ -521,7 +533,6 @@ xfs_qm_scall_quotaon(
 }
 
 
-
 /*
  * Return quota status information, such as uquota-off, enforcements, etc.
  */
@@ -606,7 +617,8 @@ xfs_qm_scall_setqlim(
        if (!capable(CAP_SYS_ADMIN))
                return XFS_ERROR(EPERM);
 
-       if ((newlim->d_fieldmask & (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK)) == 0)
+       if ((newlim->d_fieldmask &
+           (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0)
                return (0);
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
@@ -691,12 +703,23 @@ xfs_qm_scall_setqlim(
                qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
        }
 
+       /*
+        * Update warnings counter(s) if requested
+        */
+       if (newlim->d_fieldmask & FS_DQ_BWARNS)
+               INT_SET(ddq->d_bwarns, ARCH_CONVERT, newlim->d_bwarns);
+       if (newlim->d_fieldmask & FS_DQ_IWARNS)
+               INT_SET(ddq->d_iwarns, ARCH_CONVERT, newlim->d_iwarns);
+       if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
+               INT_SET(ddq->d_rtbwarns, ARCH_CONVERT, newlim->d_rtbwarns);
+
        if (id == 0) {
                /*
                 * Timelimits for the super user set the relative time
                 * the other users can be over quota for this file system.
                 * If it is zero a default is used.  Ditto for the default
-                * soft and hard limit values (already done, above).
+                * soft and hard limit values (already done, above), and
+                * for warnings.
                 */
                if (newlim->d_fieldmask & FS_DQ_BTIMER) {
                        mp->m_quotainfo->qi_btimelimit = newlim->d_btimer;
@@ -710,7 +733,13 @@ xfs_qm_scall_setqlim(
                        mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer;
                        INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
                }
-       } else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ {
+               if (newlim->d_fieldmask & FS_DQ_BWARNS)
+                       mp->m_quotainfo->qi_bwarnlimit = newlim->d_bwarns;
+               if (newlim->d_fieldmask & FS_DQ_IWARNS)
+                       mp->m_quotainfo->qi_iwarnlimit = newlim->d_iwarns;
+               if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
+                       mp->m_quotainfo->qi_rtbwarnlimit = newlim->d_rtbwarns;
+       } else {
                /*
                 * If the user is now over quota, start the timelimit.
                 * The user will not be 'warned'.
@@ -776,9 +805,9 @@ xfs_qm_log_quotaoff_end(
        xfs_qoff_logitem_t      *startqoff,
        uint                    flags)
 {
-       xfs_trans_t            *tp;
+       xfs_trans_t             *tp;
        int                     error;
-       xfs_qoff_logitem_t     *qoffi;
+       xfs_qoff_logitem_t      *qoffi;
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
 
@@ -928,18 +957,26 @@ xfs_qm_export_dquot(
 
 STATIC uint
 xfs_qm_import_qtype_flags(
-       uint uflags)
+       uint            uflags)
 {
+       uint            oflags = 0;
+
        /*
-        * Can't be both at the same time.
+        * Can't be more than one, or none.
         */
        if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ==
-            (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
-           ((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 0))
+                       (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
+           ((uflags & (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ==
+                       (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ||
+           ((uflags & (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ==
+                       (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ||
+           ((uflags & (XFS_GROUP_QUOTA|XFS_USER_QUOTA|XFS_PROJ_QUOTA)) == 0))
                return (0);
 
-       return (uflags & XFS_USER_QUOTA) ?
-               XFS_DQ_USER : XFS_DQ_GROUP;
+       oflags |= (uflags & XFS_USER_QUOTA) ? XFS_DQ_USER : 0;
+       oflags |= (uflags & XFS_PROJ_QUOTA) ? XFS_DQ_PROJ : 0;
+       oflags |= (uflags & XFS_GROUP_QUOTA) ? XFS_DQ_GROUP: 0;
+       return oflags;
 }
 
 STATIC uint
@@ -947,14 +984,19 @@ xfs_qm_export_qtype_flags(
        uint flags)
 {
        /*
-        * Can't be both at the same time.
+        * Can't be more than one, or none.
         */
-       ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) !=
-               (XFS_GROUP_QUOTA | XFS_USER_QUOTA));
-       ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 0);
+       ASSERT((flags & (XFS_PROJ_QUOTA | XFS_USER_QUOTA)) !=
+               (XFS_PROJ_QUOTA | XFS_USER_QUOTA));
+       ASSERT((flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)) !=
+               (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA));
+       ASSERT((flags & (XFS_USER_QUOTA | XFS_GROUP_QUOTA)) !=
+               (XFS_USER_QUOTA | XFS_GROUP_QUOTA));
+       ASSERT((flags & (XFS_PROJ_QUOTA|XFS_USER_QUOTA|XFS_GROUP_QUOTA)) != 0);
 
        return (flags & XFS_DQ_USER) ?
-               XFS_USER_QUOTA : XFS_GROUP_QUOTA;
+               XFS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
+                       XFS_PROJ_QUOTA : XFS_GROUP_QUOTA;
 }
 
 STATIC uint
@@ -965,12 +1007,14 @@ xfs_qm_import_flags(
 
        if (uflags & XFS_QUOTA_UDQ_ACCT)
                flags |= XFS_UQUOTA_ACCT;
+       if (uflags & XFS_QUOTA_PDQ_ACCT)
+               flags |= XFS_PQUOTA_ACCT;
        if (uflags & XFS_QUOTA_GDQ_ACCT)
                flags |= XFS_GQUOTA_ACCT;
        if (uflags & XFS_QUOTA_UDQ_ENFD)
                flags |= XFS_UQUOTA_ENFD;
-       if (uflags & XFS_QUOTA_GDQ_ENFD)
-               flags |= XFS_GQUOTA_ENFD;
+       if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))
+               flags |= XFS_OQUOTA_ENFD;
        return (flags);
 }
 
@@ -984,12 +1028,16 @@ xfs_qm_export_flags(
        uflags = 0;
        if (flags & XFS_UQUOTA_ACCT)
                uflags |= XFS_QUOTA_UDQ_ACCT;
+       if (flags & XFS_PQUOTA_ACCT)
+               uflags |= XFS_QUOTA_PDQ_ACCT;
        if (flags & XFS_GQUOTA_ACCT)
                uflags |= XFS_QUOTA_GDQ_ACCT;
        if (flags & XFS_UQUOTA_ENFD)
                uflags |= XFS_QUOTA_UDQ_ENFD;
-       if (flags & XFS_GQUOTA_ENFD)
-               uflags |= XFS_QUOTA_GDQ_ENFD;
+       if (flags & (XFS_OQUOTA_ENFD)) {
+               uflags |= (flags & XFS_GQUOTA_ACCT) ?
+                       XFS_QUOTA_GDQ_ENFD : XFS_QUOTA_PDQ_ENFD;
+       }
        return (uflags);
 }
 
@@ -1070,7 +1118,7 @@ again:
                        xfs_qm_dqrele(ip->i_udquot);
                        ip->i_udquot = NULL;
                }
-               if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
+               if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
                        xfs_qm_dqrele(ip->i_gdquot);
                        ip->i_gdquot = NULL;
                }
@@ -1160,7 +1208,6 @@ xfs_qm_dqtest_print(
 {
        cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
        cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
-       cmn_err(CE_DEBUG, "---- type     = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP");
        cmn_err(CE_DEBUG, "---- fs       = 0x%p", d->q_mount);
        cmn_err(CE_DEBUG, "---- bcount   = %Lu (0x%x)",
                d->d_bcount, (int)d->d_bcount);
@@ -1231,7 +1278,7 @@ xfs_dqtest_cmp2(
 #ifdef QUOTADEBUG
        if (!err) {
                cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
-                       d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount);
+                       d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
        }
 #endif
        return (err);
@@ -1287,6 +1334,7 @@ STATIC void
 xfs_qm_internalqcheck_get_dquots(
        xfs_mount_t     *mp,
        xfs_dqid_t      uid,
+       xfs_dqid_t      projid,
        xfs_dqid_t      gid,
        xfs_dqtest_t    **ud,
        xfs_dqtest_t    **gd)
@@ -1295,6 +1343,8 @@ xfs_qm_internalqcheck_get_dquots(
                xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
        if (XFS_IS_GQUOTA_ON(mp))
                xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
+       else if (XFS_IS_PQUOTA_ON(mp))
+               xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);
 }
 
 
@@ -1362,13 +1412,14 @@ xfs_qm_internalqcheck_adjust(
        }
        xfs_qm_internalqcheck_get_dquots(mp,
                                        (xfs_dqid_t) ip->i_d.di_uid,
+                                       (xfs_dqid_t) ip->i_d.di_projid,
                                        (xfs_dqid_t) ip->i_d.di_gid,
                                        &ud, &gd);
        if (XFS_IS_UQUOTA_ON(mp)) {
                ASSERT(ud);
                xfs_qm_internalqcheck_dqadjust(ip, ud);
        }
-       if (XFS_IS_GQUOTA_ON(mp)) {
+       if (XFS_IS_OQUOTA_ON(mp)) {
                ASSERT(gd);
                xfs_qm_internalqcheck_dqadjust(ip, gd);
        }
index 414b6004af2160ce5a16c8f86b5f50d7c17a87f2..bf413e70ec073ea3434e3ad25f284a4302549f30 100644 (file)
@@ -56,6 +56,7 @@
 #define XFS_QI_RTBTIMELIMIT(mp) ((mp)->m_quotainfo->qi_rtbtimelimit)
 #define XFS_QI_ITIMELIMIT(mp)  ((mp)->m_quotainfo->qi_itimelimit)
 #define XFS_QI_BWARNLIMIT(mp)  ((mp)->m_quotainfo->qi_bwarnlimit)
+#define XFS_QI_RTBWARNLIMIT(mp)        ((mp)->m_quotainfo->qi_rtbwarnlimit)
 #define XFS_QI_IWARNLIMIT(mp)  ((mp)->m_quotainfo->qi_iwarnlimit)
 #define XFS_QI_QOFFLOCK(mp)    ((mp)->m_quotainfo->qi_quotaofflock)
 
@@ -102,7 +103,8 @@ static inline int XQMISLCKD(struct xfs_dqhash *h)
                                     (xfs_Gqm->qm_grp_dqhtable + \
                                      XFS_DQ_HASHVAL(mp, id)))
 #define XFS_IS_DQTYPE_ON(mp, type)   (type == XFS_DQ_USER ? \
-                                     XFS_IS_UQUOTA_ON(mp):XFS_IS_GQUOTA_ON(mp))
+                                       XFS_IS_UQUOTA_ON(mp) : \
+                                       XFS_IS_OQUOTA_ON(mp))
 #define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
        !dqp->q_core.d_blk_hardlimit && \
        !dqp->q_core.d_blk_softlimit && \
@@ -177,16 +179,11 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
        (!((dqp)->q_core.d_id))
 
 #define XFS_PURGE_INODE(ip)            \
-       {                               \
-         vmap_t dqvmap;                \
-         vnode_t *dqvp;                \
-         dqvp = XFS_ITOV(ip);          \
-         VMAP(dqvp, dqvmap);           \
-         VN_RELE(dqvp);                \
-       }
+       IRELE(ip);
 
 #define DQFLAGTO_TYPESTR(d)    (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
-                                (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : "???"))
+                                (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
+                                (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
 #define DQFLAGTO_DIRTYSTR(d)   (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY")
 
 #endif /* __XFS_QUOTA_PRIV_H__ */
index 149b2a1fd949beed7a82f63786f825db677bba83..3b99daf8a640f3dd3a6691558fbf70ba5fa0a462 100644 (file)
@@ -187,7 +187,7 @@ xfs_trans_dup_dqinfo(
 /*
  * Wrap around mod_dquot to account for both user and group quotas.
  */
-void
+STATIC void
 xfs_trans_mod_dquot_byino(
        xfs_trans_t     *tp,
        xfs_inode_t     *ip,
@@ -207,12 +207,10 @@ xfs_trans_mod_dquot_byino(
        if (tp->t_dqinfo == NULL)
                xfs_trans_alloc_dqinfo(tp);
 
-       if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) {
+       if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
                (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
-       }
-       if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
+       if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot)
                (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
-       }
 }
 
 STATIC xfs_dqtrx_t *
@@ -368,7 +366,7 @@ xfs_trans_dqlockedjoin(
  * Unreserve just the reservations done by this transaction.
  * dquot is still left locked at exit.
  */
-void
+STATIC void
 xfs_trans_apply_dquot_deltas(
        xfs_trans_t             *tp)
 {
@@ -499,7 +497,7 @@ xfs_trans_apply_dquot_deltas(
                         * Adjust the RT reservation.
                         */
                        if (qtrx->qt_rtblk_res != 0) {
-                               if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) {
+                               if (qtrx->qt_rtblk_res != qtrx->qt_rtblk_res_used) {
                                        if (qtrx->qt_rtblk_res >
                                            qtrx->qt_rtblk_res_used)
                                               dqp->q_res_rtbcount -= (xfs_qcnt_t)
@@ -532,12 +530,6 @@ xfs_trans_apply_dquot_deltas(
                                            (xfs_qcnt_t)qtrx->qt_icount_delta;
                        }
 
-
-#ifdef QUOTADEBUG
-                       if (qtrx->qt_rtblk_res != 0)
-                               cmn_err(CE_DEBUG, "RT res %d for 0x%p\n",
-                                       (int) qtrx->qt_rtblk_res, dqp);
-#endif
                        ASSERT(dqp->q_res_bcount >=
                                INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
                        ASSERT(dqp->q_res_icount >=
@@ -638,7 +630,10 @@ xfs_trans_dqresv(
        int             error;
        xfs_qcnt_t      hardlimit;
        xfs_qcnt_t      softlimit;
-       time_t          btimer;
+       time_t          timer;
+       xfs_qwarncnt_t  warns;
+       xfs_qwarncnt_t  warnlimit;
+       xfs_qcnt_t      count;
        xfs_qcnt_t      *resbcountp;
        xfs_quotainfo_t *q = mp->m_quotainfo;
 
@@ -653,7 +648,9 @@ xfs_trans_dqresv(
                softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
                if (!softlimit)
                        softlimit = q->qi_bsoftlimit;
-               btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
+               timer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
+               warns = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT);
+               warnlimit = XFS_QI_BWARNLIMIT(dqp->q_mount);
                resbcountp = &dqp->q_res_bcount;
        } else {
                ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
@@ -663,7 +660,9 @@ xfs_trans_dqresv(
                softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
                if (!softlimit)
                        softlimit = q->qi_rtbsoftlimit;
-               btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
+               timer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
+               warns = INT_GET(dqp->q_core.d_rtbwarns, ARCH_CONVERT);
+               warnlimit = XFS_QI_RTBWARNLIMIT(dqp->q_mount);
                resbcountp = &dqp->q_res_rtbcount;
        }
        error = 0;
@@ -693,37 +692,36 @@ xfs_trans_dqresv(
                                 * If timer or warnings has expired,
                                 * return EDQUOT
                                 */
-                               if ((btimer != 0 && get_seconds() > btimer) ||
-                                   (dqp->q_core.d_bwarns &&
-                                    INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
-                                    XFS_QI_BWARNLIMIT(dqp->q_mount))) {
+                               if ((timer != 0 && get_seconds() > timer) ||
+                                   (warns != 0 && warns >= warnlimit)) {
                                        error = EDQUOT;
                                        goto error_return;
                                }
                        }
                }
                if (ninos > 0) {
-                       hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT);
+                       count = INT_GET(dqp->q_core.d_icount, ARCH_CONVERT);
+                       timer = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT);
+                       warns = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT);
+                       warnlimit = XFS_QI_IWARNLIMIT(dqp->q_mount);
+                       hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit,
+                                               ARCH_CONVERT);
                        if (!hardlimit)
                                hardlimit = q->qi_ihardlimit;
-                       softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT);
+                       softlimit = INT_GET(dqp->q_core.d_ino_softlimit,
+                                               ARCH_CONVERT);
                        if (!softlimit)
                                softlimit = q->qi_isoftlimit;
-                       if (hardlimit > 0ULL &&
-                           INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
+                       if (hardlimit > 0ULL && count >= hardlimit) {
                                error = EDQUOT;
                                goto error_return;
-                       } else if (softlimit > 0ULL &&
-                                  INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
+                       } else if (softlimit > 0ULL && count >= softlimit) {
                                /*
                                 * If timer or warnings has expired,
                                 * return EDQUOT
                                 */
-                               if ((dqp->q_core.d_itimer &&
-                                    get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) ||
-                                   (dqp->q_core.d_iwarns &&
-                                    INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
-                                    XFS_QI_IWARNLIMIT(dqp->q_mount))) {
+                               if ((timer != 0 && get_seconds() > timer) ||
+                                    (warns != 0 && warns >= warnlimit)) {
                                        error = EDQUOT;
                                        goto error_return;
                                }
index 7d6e1f37df10d88c621be9363f6c865d81decd02..4ed7b6928cd78c4e6a02f0e4930116174295f4f2 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 
-int                    doass = 1;
 static char            message[256];   /* keep it off the stack */
 static DEFINE_SPINLOCK(xfs_err_lock);
 
index 40b0f4c54d9e5fe2409c39e1da5ebf66a355042b..c5b9365a7e2ac2dd2eb3a8b6f243f8da2aea5a94 100644 (file)
@@ -50,16 +50,11 @@ extern void cmn_err(int, char *, ...);
 #endif
 
 #ifdef DEBUG
-# ifdef lint
-#  define ASSERT(EX)   ((void)0) /* avoid "constant in conditional" babble */
-# else
-#  define ASSERT(EX) ((!doass||(EX))?((void)0):assfail(#EX, __FILE__, __LINE__))
-# endif        /* lint */
+# define ASSERT(EX)    ((EX) ? ((void)0) : assfail(#EX, __FILE__, __LINE__))
 #else
 # define ASSERT(x)     ((void)0)
 #endif
 
-extern int doass;              /* dynamically turn off asserts */
 extern void assfail(char *, char *, int);
 #ifdef DEBUG
 extern unsigned long random(void);
index 36603db10fe97babbff94b0b367c413c621b9fe8..dcfe1970362016637854091e53715f6f2f30f569 100644 (file)
@@ -59,7 +59,7 @@
 #define        XFSA_FIXUP_BNO_OK       1
 #define        XFSA_FIXUP_CNT_OK       2
 
-int
+STATIC int
 xfs_alloc_search_busy(xfs_trans_t *tp,
                    xfs_agnumber_t agno,
                    xfs_agblock_t bno,
@@ -2562,7 +2562,7 @@ xfs_alloc_clear_busy(xfs_trans_t *tp,
 /*
  * returns non-zero if any of (agno,bno):len is in a busy list
  */
-int
+STATIC int
 xfs_alloc_search_busy(xfs_trans_t *tp,
                    xfs_agnumber_t agno,
                    xfs_agblock_t bno,
index ee8b5904ec7ccd7e7fb0a15ec3470cd1336e2c45..a41ad3a5e5540af909dcc446357da97b5111baef 100644 (file)
  * Provide the external interfaces to manage attribute lists.
  */
 
+#define ATTR_SYSCOUNT  2
+STATIC struct attrnames posix_acl_access;
+STATIC struct attrnames posix_acl_default;
+STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT];
+
 /*========================================================================
  * Function prototypes for the kernel.
  *========================================================================*/
@@ -83,6 +88,7 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
 /*
  * Internal routines when attribute list is one block.
  */
+STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
@@ -90,6 +96,7 @@ STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
 /*
  * Internal routines when attribute list is more than one block.
  */
+STATIC int xfs_attr_node_get(xfs_da_args_t *args);
 STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
 STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
 STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
@@ -1102,7 +1109,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
  * This leaf block cannot have a "remote" value, we only call this routine
  * if bmap_one_block() says there is only one block (ie: no remote blks).
  */
-int
+STATIC int
 xfs_attr_leaf_get(xfs_da_args_t *args)
 {
        xfs_dabuf_t *bp;
@@ -1707,7 +1714,7 @@ xfs_attr_refillstate(xfs_da_state_t *state)
  * block, ie: both true Btree attr lists and for single-leaf-blocks with
  * "remote" values taking up more blocks.
  */
-int
+STATIC int
 xfs_attr_node_get(xfs_da_args_t *args)
 {
        xfs_da_state_t *state;
@@ -2398,7 +2405,7 @@ posix_acl_default_exists(
        return xfs_acl_vhasacl_default(vp);
 }
 
-struct attrnames posix_acl_access = {
+STATIC struct attrnames posix_acl_access = {
        .attr_name      = "posix_acl_access",
        .attr_namelen   = sizeof("posix_acl_access") - 1,
        .attr_get       = posix_acl_access_get,
@@ -2407,7 +2414,7 @@ struct attrnames posix_acl_access = {
        .attr_exists    = posix_acl_access_exists,
 };
 
-struct attrnames posix_acl_default = {
+STATIC struct attrnames posix_acl_default = {
        .attr_name      = "posix_acl_default",
        .attr_namelen   = sizeof("posix_acl_default") - 1,
        .attr_get       = posix_acl_default_get,
@@ -2416,7 +2423,7 @@ struct attrnames posix_acl_default = {
        .attr_exists    = posix_acl_default_exists,
 };
 
-struct attrnames *attr_system_names[] =
+STATIC struct attrnames *attr_system_names[] =
        { &posix_acl_access, &posix_acl_default };
 
 
index 67cd0f5ac1a759e39507acb281f8867143963d59..45ab1c542baf9892de67055867ddf6b1842f8a25 100644 (file)
@@ -76,11 +76,6 @@ extern struct attrnames attr_system;
 extern struct attrnames attr_trusted;
 extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
 
-#define ATTR_SYSCOUNT  2
-extern struct attrnames posix_acl_access;
-extern struct attrnames posix_acl_default;
-extern struct attrnames *attr_system_names[ATTR_SYSCOUNT];
-
 extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
 extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
 
@@ -184,8 +179,6 @@ int xfs_attr_list(bhv_desc_t *, char *, int, int,
                         struct attrlist_cursor_kern *, struct cred *);
 int xfs_attr_inactive(struct xfs_inode *dp);
 
-int xfs_attr_node_get(struct xfs_da_args *);
-int xfs_attr_leaf_get(struct xfs_da_args *);
 int xfs_attr_shortform_getvalue(struct xfs_da_args *);
 int xfs_attr_fetch(struct xfs_inode *, char *, int,
                        char *, int *, int, struct cred *);
index b11256e58bf4f23911c4b6f787a46ade1c93fe93..1cdd574c63a9de334ab9359eeb87652378118c9a 100644 (file)
@@ -79,6 +79,8 @@
 /*
  * Routines used for growing the Btree.
  */
+STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block,
+                                   xfs_dabuf_t **bpp);
 STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
                                              int freemap_index);
 STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer);
@@ -91,6 +93,16 @@ STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
                                           int *number_entries_in_blk1,
                                           int *number_usedbytes_in_blk1);
 
+/*
+ * Routines used for shrinking the Btree.
+ */
+STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
+                                 xfs_dabuf_t *bp, int level);
+STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
+                                 xfs_dabuf_t *bp);
+STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
+                                  xfs_dablk_t blkno, int blkcnt);
+
 /*
  * Utility routines.
  */
@@ -99,6 +111,10 @@ STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
                                         xfs_attr_leafblock_t *dst_leaf,
                                         int dst_start, int move_count,
                                         xfs_mount_t *mp);
+STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
+STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context,
+                            attrnames_t *, char *name, int namelen,
+                            int valuelen);
 
 
 /*========================================================================
@@ -774,7 +790,7 @@ out:
  * Create the initial contents of a leaf attribute list
  * or a leaf in a node attribute list.
  */
-int
+STATIC int
 xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
 {
        xfs_attr_leafblock_t *leaf;
@@ -2209,7 +2225,7 @@ xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
  * Calculate the number of bytes used to store the indicated attribute
  * (whether local or remote only calculate bytes in this block).
  */
-int
+STATIC int
 xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
 {
        xfs_attr_leaf_name_local_t *name_loc;
@@ -2380,7 +2396,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
  * we may be reading them directly out of a user buffer.
  */
 /*ARGSUSED*/
-int
+STATIC int
 xfs_attr_put_listent(xfs_attr_list_context_t *context,
                     attrnames_t *namesp, char *name, int namelen, int valuelen)
 {
@@ -2740,7 +2756,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
  * Recurse (gasp!) through the attribute nodes until we find leaves.
  * We're doing a depth-first traversal in order to invalidate everything.
  */
-int
+STATIC int
 xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
                                   int level)
 {
@@ -2849,7 +2865,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
  * Note that we must release the lock on the buffer so that we are not
  * caught holding something that the logging code wants to flush to disk.
  */
-int
+STATIC int
 xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
 {
        xfs_attr_leafblock_t *leaf;
@@ -2934,7 +2950,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
  * Look at all the extents for this logical region,
  * invalidate any buffers that are incore/in transactions.
  */
-int
+STATIC int
 xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
                                    xfs_dablk_t blkno, int blkcnt)
 {
index b1480e0b3349227d9b032d5ed625576a0d28bf32..0a4cfad6df91baf68b7f1d38308703a59ae500d1 100644 (file)
@@ -261,8 +261,6 @@ int xfs_attr_leaf_flipflags(xfs_da_args_t *args);
 /*
  * Routines used for growing the Btree.
  */
-int    xfs_attr_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block,
-                                   struct xfs_dabuf **bpp);
 int    xfs_attr_leaf_split(struct xfs_da_state *state,
                                   struct xfs_da_state_blk *oldblk,
                                   struct xfs_da_state_blk *newblk);
@@ -284,12 +282,6 @@ void       xfs_attr_leaf_unbalance(struct xfs_da_state *state,
                                       struct xfs_da_state_blk *drop_blk,
                                       struct xfs_da_state_blk *save_blk);
 int    xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp);
-int    xfs_attr_node_inactive(struct xfs_trans **trans, struct xfs_inode *dp,
-                                     struct xfs_dabuf *bp, int level);
-int    xfs_attr_leaf_inactive(struct xfs_trans **trans, struct xfs_inode *dp,
-                                     struct xfs_dabuf *bp);
-int    xfs_attr_leaf_freextent(struct xfs_trans **trans, struct xfs_inode *dp,
-                                      xfs_dablk_t blkno, int blkcnt);
 
 /*
  * Utility routines.
@@ -299,10 +291,6 @@ int        xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp,
                                   struct xfs_dabuf *leaf2_bp);
 int    xfs_attr_leaf_newentsize(struct xfs_da_args *args, int blocksize,
                                        int *local);
-int    xfs_attr_leaf_entsize(struct xfs_attr_leafblock *leaf, int index);
-int    xfs_attr_put_listent(struct xfs_attr_list_context *context,
-                            struct attrnames *, char *name, int namelen,
-                            int valuelen);
 int    xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
 
 #endif /* __XFS_ATTR_LEAF_H__ */
index a20a6c3dc13e751cd7ac7ef9c24c537704d75d9f..76c9ad3875ef8aeb6574475676fca2cf257cf329 100644 (file)
@@ -45,7 +45,7 @@
 /*
  * Index of high bit number in byte, -1 for none set, 0..7 otherwise.
  */
-const char xfs_highbit[256] = {
+STATIC const char xfs_highbit[256] = {
        -1, 0, 1, 1, 2, 2, 2, 2,                        /* 00 .. 07 */
        3, 3, 3, 3, 3, 3, 3, 3,                 /* 08 .. 0f */
        4, 4, 4, 4, 4, 4, 4, 4,                 /* 10 .. 17 */
index de316241866305c988f186730948f0fe2753e5b7..6f5d283888aa2b9ab243d93f8df1fe25c4e8cc34 100644 (file)
@@ -301,6 +301,19 @@ xfs_bmap_search_extents(
        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
        xfs_bmbt_irec_t *prevp);        /* out: previous extent entry found */
 
+/*
+ * Check the last inode extent to determine whether this allocation will result
+ * in blocks being allocated at the end of the file. When we allocate new data
+ * blocks at the end of the file which do not start at the previous data block,
+ * we will try to align the new blocks at stripe unit boundaries.
+ */
+STATIC int                             /* error */
+xfs_bmap_isaeof(
+       xfs_inode_t     *ip,            /* incore inode pointer */
+       xfs_fileoff_t   off,            /* file offset in fsblocks */
+       int             whichfork,      /* data or attribute fork */
+       char            *aeof);         /* return value */
+
 #ifdef XFS_BMAP_TRACE
 /*
  * Add a bmap trace buffer entry.  Base routine for the others.
@@ -4532,18 +4545,17 @@ xfs_bmapi(
        xfs_extlen_t    alen;           /* allocated extent length */
        xfs_fileoff_t   aoff;           /* allocated file offset */
        xfs_bmalloca_t  bma;            /* args for xfs_bmap_alloc */
-       char            contig;         /* allocation must be one extent */
        xfs_btree_cur_t *cur;           /* bmap btree cursor */
-       char            delay;          /* this request is for delayed alloc */
        xfs_fileoff_t   end;            /* end of mapped file region */
        int             eof;            /* we've hit the end of extent list */
+       char            contig;         /* allocation must be one extent */
+       char            delay;          /* this request is for delayed alloc */
+       char            exact;          /* don't do all of wasdelayed extent */
        xfs_bmbt_rec_t  *ep;            /* extent list entry pointer */
        int             error;          /* error return */
-       char            exact;          /* don't do all of wasdelayed extent */
        xfs_bmbt_irec_t got;            /* current extent list record */
        xfs_ifork_t     *ifp;           /* inode fork pointer */
        xfs_extlen_t    indlen;         /* indirect blocks length */
-       char            inhole;         /* current location is hole in file */
        xfs_extnum_t    lastx;          /* last useful extent number */
        int             logflags;       /* flags for transaction logging */
        xfs_extlen_t    minleft;        /* min blocks left after allocation */
@@ -4554,13 +4566,15 @@ xfs_bmapi(
        xfs_extnum_t    nextents;       /* number of extents in file */
        xfs_fileoff_t   obno;           /* old block number (offset) */
        xfs_bmbt_irec_t prev;           /* previous extent list record */
-       char            stateless;      /* ignore state flag set */
        int             tmp_logflags;   /* temp flags holder */
+       int             whichfork;      /* data or attr fork */
+       char            inhole;         /* current location is hole in file */
+       char            stateless;      /* ignore state flag set */
        char            trim;           /* output trimmed to match range */
        char            userdata;       /* allocating non-metadata */
        char            wasdelay;       /* old extent was delayed */
-       int             whichfork;      /* data or attr fork */
        char            wr;             /* this is a write request */
+       char            rt;             /* this is a realtime file */
        char            rsvd;           /* OK to allocate reserved blocks */
 #ifdef DEBUG
        xfs_fileoff_t   orig_bno;       /* original block number value */
@@ -4590,6 +4604,7 @@ xfs_bmapi(
        }
        if (XFS_FORCED_SHUTDOWN(mp))
                return XFS_ERROR(EIO);
+       rt = XFS_IS_REALTIME_INODE(ip);
        ifp = XFS_IFORK_PTR(ip, whichfork);
        ASSERT(ifp->if_ext_max ==
               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
@@ -4694,9 +4709,16 @@ xfs_bmapi(
                        }
                        minlen = contig ? alen : 1;
                        if (delay) {
-                               indlen = (xfs_extlen_t)
-                                       xfs_bmap_worst_indlen(ip, alen);
-                               ASSERT(indlen > 0);
+                               xfs_extlen_t    extsz = 0;
+
+                               /* Figure out the extent size, adjust alen */
+                               if (rt) {
+                                       if (!(extsz = ip->i_d.di_extsize))
+                                               extsz = mp->m_sb.sb_rextsize;
+                                       alen = roundup(alen, extsz);
+                                       extsz = alen / mp->m_sb.sb_rextsize;
+                               }
+
                                /*
                                 * Make a transaction-less quota reservation for
                                 * delayed allocation blocks. This number gets
@@ -4704,8 +4726,10 @@ xfs_bmapi(
                                 * We return EDQUOT if we haven't allocated
                                 * blks already inside this loop;
                                 */
-                               if (XFS_TRANS_RESERVE_BLKQUOTA(
-                                               mp, NULL, ip, (long)alen)) {
+                               if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
+                                               mp, NULL, ip, (long)alen, 0,
+                                               rt ? XFS_QMOPT_RES_RTBLKS :
+                                                    XFS_QMOPT_RES_REGBLKS)) {
                                        if (n == 0) {
                                                *nmap = 0;
                                                ASSERT(cur == NULL);
@@ -4718,40 +4742,34 @@ xfs_bmapi(
                                 * Split changing sb for alen and indlen since
                                 * they could be coming from different places.
                                 */
-                               if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) {
-                                       xfs_extlen_t    extsz;
-                                       xfs_extlen_t    ralen;
-                                       if (!(extsz = ip->i_d.di_extsize))
-                                               extsz = mp->m_sb.sb_rextsize;
-                                       ralen = roundup(alen, extsz);
-                                       ralen = ralen / mp->m_sb.sb_rextsize;
-                                       if (xfs_mod_incore_sb(mp,
-                                               XFS_SBS_FREXTENTS,
-                                               -(ralen), rsvd)) {
-                                               if (XFS_IS_QUOTA_ON(ip->i_mount))
-                                                       XFS_TRANS_UNRESERVE_BLKQUOTA(
-                                                               mp, NULL, ip,
-                                                               (long)alen);
-                                               break;
-                                       }
-                               } else {
-                                       if (xfs_mod_incore_sb(mp,
-                                                             XFS_SBS_FDBLOCKS,
-                                                             -(alen), rsvd)) {
-                                               if (XFS_IS_QUOTA_ON(ip->i_mount))
-                                                       XFS_TRANS_UNRESERVE_BLKQUOTA(
-                                                               mp, NULL, ip,
-                                                               (long)alen);
-                                               break;
-                                       }
-                               }
+                               indlen = (xfs_extlen_t)
+                                       xfs_bmap_worst_indlen(ip, alen);
+                               ASSERT(indlen > 0);
 
-                               if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-                                               -(indlen), rsvd)) {
-                                       XFS_TRANS_UNRESERVE_BLKQUOTA(
-                                               mp, NULL, ip, (long)alen);
+                               if (rt)
+                                       error = xfs_mod_incore_sb(mp,
+                                                       XFS_SBS_FREXTENTS,
+                                                       -(extsz), rsvd);
+                               else
+                                       error = xfs_mod_incore_sb(mp,
+                                                       XFS_SBS_FDBLOCKS,
+                                                       -(alen), rsvd);
+                               if (!error)
+                                       error = xfs_mod_incore_sb(mp,
+                                                       XFS_SBS_FDBLOCKS,
+                                                       -(indlen), rsvd);
+
+                               if (error) {
+                                       if (XFS_IS_QUOTA_ON(ip->i_mount))
+                                               /* unreserve the blocks now */
+                                               XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
+                                                       mp, NULL, ip,
+                                                       (long)alen, 0, rt ?
+                                                       XFS_QMOPT_RES_RTBLKS :
+                                                       XFS_QMOPT_RES_REGBLKS);
                                        break;
                                }
+
                                ip->i_delayed_blks += alen;
                                abno = NULLSTARTBLOCK(indlen);
                        } else {
@@ -5376,13 +5394,24 @@ xfs_bunmapi(
                }
                if (wasdel) {
                        ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
-                       xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-                               (int)del.br_blockcount, rsvd);
-                       /* Unreserve our quota space */
-                       XFS_TRANS_RESERVE_QUOTA_NBLKS(
-                               mp, NULL, ip, -((long)del.br_blockcount), 0,
-                               isrt ?  XFS_QMOPT_RES_RTBLKS :
+                       /* Update realtim/data freespace, unreserve quota */
+                       if (isrt) {
+                               xfs_filblks_t rtexts;
+
+                               rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
+                               do_div(rtexts, mp->m_sb.sb_rextsize);
+                               xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
+                                               (int)rtexts, rsvd);
+                               XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
+                                       -((long)del.br_blockcount), 0,
+                                       XFS_QMOPT_RES_RTBLKS);
+                       } else {
+                               xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
+                                               (int)del.br_blockcount, rsvd);
+                               XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
+                                       -((long)del.br_blockcount), 0,
                                        XFS_QMOPT_RES_REGBLKS);
+                       }
                        ip->i_delayed_blks -= del.br_blockcount;
                        if (cur)
                                cur->bc_private.b.flags |=
@@ -5714,7 +5743,7 @@ unlock_and_return:
  * blocks at the end of the file which do not start at the previous data block,
  * we will try to align the new blocks at stripe unit boundaries.
  */
-int                                    /* error */
+STATIC int                             /* error */
 xfs_bmap_isaeof(
        xfs_inode_t     *ip,            /* incore inode pointer */
        xfs_fileoff_t   off,            /* file offset in fsblocks */
index f1bc22fb26aec4abb63a7df717c22f40f7a3114a..e6d22ec9b2e4c90867035840fff72abd8d2084d2 100644 (file)
@@ -331,19 +331,6 @@ xfs_getbmap(
        void                    __user *ap,     /* pointer to user's array */
        int                     iflags);        /* interface flags */
 
-/*
- * Check the last inode extent to determine whether this allocation will result
- * in blocks being allocated at the end of the file. When we allocate new data
- * blocks at the end of the file which do not start at the previous data block,
- * we will try to align the new blocks at stripe unit boundaries.
- */
-int
-xfs_bmap_isaeof(
-       struct xfs_inode        *ip,
-       xfs_fileoff_t           off,
-       int                     whichfork,
-       char                    *aeof);
-
 /*
  * Check if the endoff is outside the last extent. If so the caller will grow
  * the allocation to a stripe unit boundary
index 163305a79fcc583cac98d43ce8c21ba1bc0a3fd9..09c413576ba81b838254837c3f708ca24797e88c 100644 (file)
@@ -2331,20 +2331,6 @@ xfs_bmbt_lookup_ge(
        return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
 }
 
-int                                    /* error */
-xfs_bmbt_lookup_le(
-       xfs_btree_cur_t *cur,
-       xfs_fileoff_t   off,
-       xfs_fsblock_t   bno,
-       xfs_filblks_t   len,
-       int             *stat)          /* success/failure */
-{
-       cur->bc_rec.b.br_startoff = off;
-       cur->bc_rec.b.br_startblock = bno;
-       cur->bc_rec.b.br_blockcount = len;
-       return xfs_bmbt_lookup(cur, XFS_LOOKUP_LE, stat);
-}
-
 /*
  * Give the bmap btree a new root block.  Copy the old broot contents
  * down into a real block and make the broot point to it.
index 843ff12b4bf22307d6f5db24b64051c3efaef7b1..0a40cf126c285cfb940b5915f898722fc6ca1ea3 100644 (file)
@@ -580,14 +580,6 @@ xfs_bmbt_lookup_ge(
        xfs_filblks_t,
        int *);
 
-int
-xfs_bmbt_lookup_le(
-       struct xfs_btree_cur *,
-       xfs_fileoff_t,
-       xfs_fsblock_t,
-       xfs_filblks_t,
-       int *);
-
 /*
  * Give the bmap btree a new root block.  Copy the old broot contents
  * down into a real block and make the broot point to it.
index 9dd22dd95487d82343d40265f1874adfa2c03fc5..0cc63d657a14ed2937df63826b3445aac41ef600 100644 (file)
@@ -89,6 +89,16 @@ xfs_btree_maxrecs(
  * Internal routines.
  */
 
+/*
+ * Retrieve the block pointer from the cursor at the given level.
+ * This may be a bmap btree root or from a buffer.
+ */
+STATIC xfs_btree_block_t *                     /* generic btree block pointer */
+xfs_btree_get_block(
+       xfs_btree_cur_t         *cur,   /* btree cursor */
+       int                     level,  /* level in btree */
+       struct xfs_buf          **bpp); /* buffer containing the block */
+
 /*
  * Checking routine: return maxrecs for the block.
  */
@@ -497,7 +507,7 @@ xfs_btree_firstrec(
  * Retrieve the block pointer from the cursor at the given level.
  * This may be a bmap btree root or from a buffer.
  */
-xfs_btree_block_t *                    /* generic btree block pointer */
+STATIC xfs_btree_block_t *             /* generic btree block pointer */
 xfs_btree_get_block(
        xfs_btree_cur_t         *cur,   /* btree cursor */
        int                     level,  /* level in btree */
index 93872bba41f50e1f69a2b4f0eb6c9611d5797005..09b4e1532a351da8e00a1c372b01380ff82687a5 100644 (file)
@@ -324,16 +324,6 @@ xfs_btree_firstrec(
        xfs_btree_cur_t         *cur,   /* btree cursor */
        int                     level); /* level to change */
 
-/*
- * Retrieve the block pointer from the cursor at the given level.
- * This may be a bmap btree root or from a buffer.
- */
-xfs_btree_block_t *                    /* generic btree block pointer */
-xfs_btree_get_block(
-       xfs_btree_cur_t         *cur,   /* btree cursor */
-       int                     level,  /* level in btree */
-       struct xfs_buf          **bpp); /* buffer containing the block */
-
 /*
  * Get a buffer for the block, return it with no data read.
  * Long-form addressing.
index 9ab0039f07df214462b07eedfbc6f403cb5f64c7..30b8285ad4769de7f6ee5b5007ae80dee9519b29 100644 (file)
@@ -172,7 +172,7 @@ STATIC void xfs_buf_do_callbacks(xfs_buf_t *bp, xfs_log_item_t *lip);
  *
  * If the XFS_BLI_STALE flag has been set, then log nothing.
  */
-uint
+STATIC uint
 xfs_buf_item_size(
        xfs_buf_log_item_t      *bip)
 {
@@ -240,7 +240,7 @@ xfs_buf_item_size(
  * format structure, and the rest point to contiguous chunks
  * within the buffer.
  */
-void
+STATIC void
 xfs_buf_item_format(
        xfs_buf_log_item_t      *bip,
        xfs_log_iovec_t         *log_vector)
@@ -365,7 +365,7 @@ xfs_buf_item_format(
  * item in memory so it cannot be written out.  Simply call bpin()
  * on the buffer to do this.
  */
-void
+STATIC void
 xfs_buf_item_pin(
        xfs_buf_log_item_t      *bip)
 {
@@ -391,7 +391,7 @@ xfs_buf_item_pin(
  * If the XFS_BLI_STALE flag is set and we are the last reference,
  * then free up the buf log item and unlock the buffer.
  */
-void
+STATIC void
 xfs_buf_item_unpin(
        xfs_buf_log_item_t      *bip,
        int                     stale)
@@ -446,7 +446,7 @@ xfs_buf_item_unpin(
  * so we need to free the item's descriptor (that points to the item)
  * in the transaction.
  */
-void
+STATIC void
 xfs_buf_item_unpin_remove(
        xfs_buf_log_item_t      *bip,
        xfs_trans_t             *tp)
@@ -493,7 +493,7 @@ xfs_buf_item_unpin_remove(
  * the lock right away, return 0.  If we can get the lock, pull the
  * buffer from the free list, mark it busy, and return 1.
  */
-uint
+STATIC uint
 xfs_buf_item_trylock(
        xfs_buf_log_item_t      *bip)
 {
@@ -537,7 +537,7 @@ xfs_buf_item_trylock(
  * This is for support of xfs_trans_bhold(). Make sure the
  * XFS_BLI_HOLD field is cleared if we don't free the item.
  */
-void
+STATIC void
 xfs_buf_item_unlock(
        xfs_buf_log_item_t      *bip)
 {
@@ -635,7 +635,7 @@ xfs_buf_item_unlock(
  * by returning the original lsn of that transaction here rather than
  * the current one.
  */
-xfs_lsn_t
+STATIC xfs_lsn_t
 xfs_buf_item_committed(
        xfs_buf_log_item_t      *bip,
        xfs_lsn_t               lsn)
@@ -654,7 +654,7 @@ xfs_buf_item_committed(
  * and have aborted this transaction, we'll trap this buffer when it tries to
  * get written out.
  */
-void
+STATIC void
 xfs_buf_item_abort(
        xfs_buf_log_item_t      *bip)
 {
@@ -674,7 +674,7 @@ xfs_buf_item_abort(
  * B_DELWRI set, then get it going out to disk with a call to bawrite().
  * If not, then just release the buffer.
  */
-void
+STATIC void
 xfs_buf_item_push(
        xfs_buf_log_item_t      *bip)
 {
@@ -693,7 +693,7 @@ xfs_buf_item_push(
 }
 
 /* ARGSUSED */
-void
+STATIC void
 xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
 {
 }
@@ -701,7 +701,7 @@ xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
 /*
  * This is the ops vector shared by all buf log items.
  */
-struct xfs_item_ops xfs_buf_item_ops = {
+STATIC struct xfs_item_ops xfs_buf_item_ops = {
        .iop_size       = (uint(*)(xfs_log_item_t*))xfs_buf_item_size,
        .iop_format     = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
                                        xfs_buf_item_format,
index 5f1b0c9308f672f37bb101b32011a4c6a1cfd2b0..01aed5f2d579718e52bbba0f3a2f580167e9f4e7 100644 (file)
@@ -80,7 +80,7 @@ typedef struct xfs_buf_log_format_t {
  * user or group dquots and may require special recovery handling.
  */
 #define        XFS_BLI_UDQUOT_BUF      0x4
-/* #define XFS_BLI_PDQUOT_BUF  0x8 */
+#define XFS_BLI_PDQUOT_BUF     0x8
 #define        XFS_BLI_GDQUOT_BUF      0x10
 
 #define        XFS_BLI_CHUNK           128
index d7fe2886676440fb0c7328141e6a8e23791c6080..8b792ddf2164d05111ab6075cc40c596ce4bd46c 100644 (file)
@@ -113,7 +113,10 @@ STATIC void xfs_da_node_unbalance(xfs_da_state_t *state,
 STATIC uint    xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
 STATIC int     xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
 STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra);
-
+STATIC int     xfs_da_blk_unlink(xfs_da_state_t *state,
+                                 xfs_da_state_blk_t *drop_blk,
+                                 xfs_da_state_blk_t *save_blk);
+STATIC void    xfs_da_state_kill_altpath(xfs_da_state_t *state);
 
 /*========================================================================
  * Routines used for growing the Btree.
@@ -1424,7 +1427,7 @@ xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
 /*
  * Unlink a block from a doubly linked list of blocks.
  */
-int                                                    /* error */
+STATIC int                                             /* error */
 xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
                                 xfs_da_state_blk_t *save_blk)
 {
@@ -2381,7 +2384,7 @@ xfs_da_state_alloc(void)
 /*
  * Kill the altpath contents of a da-state structure.
  */
-void
+STATIC void
 xfs_da_state_kill_altpath(xfs_da_state_t *state)
 {
        int     i;
index 9fc699d9699575f8fc2ad69cb095b4ca3d5a6565..3a9b9e809c602481ecd48264a4bcf4fe880e83be 100644 (file)
@@ -296,8 +296,6 @@ int xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
 /*
  * Utility routines.
  */
-int    xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
-                                        xfs_da_state_blk_t *save_blk);
 int    xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
                                       xfs_da_state_blk_t *new_blk);
 
@@ -320,7 +318,6 @@ uint xfs_da_hashname(uchar_t *name_string, int name_length);
 uint xfs_da_log2_roundup(uint i);
 xfs_da_state_t *xfs_da_state_alloc(void);
 void xfs_da_state_free(xfs_da_state_t *state);
-void xfs_da_state_kill_altpath(xfs_da_state_t *state);
 
 void xfs_da_buf_done(xfs_dabuf_t *dabuf);
 void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first,
index 63abdc2ac7f4ba0da434c45e32f08a8e6be5209a..681be5c93af500f63fc2cd4e744682023b6c7497 100644 (file)
@@ -180,9 +180,10 @@ xfs_swapext(
                goto error0;
        }
 
-       if (VN_CACHED(tvp) != 0)
-               xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore),
-                                               (xfs_off_t)0, 0, 0);
+       if (VN_CACHED(tvp) != 0) {
+               xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
+               VOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED);
+       }
 
        /* Verify O_DIRECT for ftmp */
        if (VN_CACHED(tvp) != 0) {
index db9887a107deaab10addcc4e2cc96476ec1e4a03..a0aa0e44ff9d6dfe3afa918c944ff6d27ec53577 100644 (file)
@@ -304,7 +304,7 @@ xfs_dir2_data_freeinsert(
 /*
  * Remove a bestfree entry from the table.
  */
-void
+STATIC void
 xfs_dir2_data_freeremove(
        xfs_dir2_data_t         *d,             /* data block pointer */
        xfs_dir2_data_free_t    *dfp,           /* bestfree entry pointer */
index 3f02294ccff0a574935a06ae10d167a4b5b6ec84..476cac920bf5037d5222f3423bba44367468dd91 100644 (file)
@@ -192,10 +192,6 @@ extern xfs_dir2_data_free_t *
        xfs_dir2_data_freeinsert(xfs_dir2_data_t *d,
                                 xfs_dir2_data_unused_t *dup, int *loghead);
 
-extern void
-       xfs_dir2_data_freeremove(xfs_dir2_data_t *d,
-                                xfs_dir2_data_free_t *dfp, int *loghead);
-
 extern void
        xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d,
                               int *loghead, char *aendp);
index 262d1e86df30f01d8c46995f05ad1eb4fd212639..056f5283904b981184b968e75944112ee109d20c 100644 (file)
@@ -77,6 +77,10 @@ static void xfs_dir2_leaf_check(xfs_inode_t *dp, xfs_dabuf_t *bp);
 #endif
 static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **lbpp,
                                    int *indexp, xfs_dabuf_t **dbpp);
+static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
+                                   int first, int last);
+static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
+
 
 /*
  * Convert a block form directory to a leaf form directory.
@@ -1214,7 +1218,7 @@ xfs_dir2_leaf_init(
 /*
  * Log the bests entries indicated from a leaf1 block.
  */
-void
+static void
 xfs_dir2_leaf_log_bests(
        xfs_trans_t             *tp,            /* transaction pointer */
        xfs_dabuf_t             *bp,            /* leaf buffer */
@@ -1278,7 +1282,7 @@ xfs_dir2_leaf_log_header(
 /*
  * Log the tail of the leaf1 block.
  */
-void
+STATIC void
 xfs_dir2_leaf_log_tail(
        xfs_trans_t             *tp,            /* transaction pointer */
        xfs_dabuf_t             *bp)            /* leaf buffer */
index 7f20eee56a52a158194250074a12754a254d147b..3303cd6f4c0045362b4b1e87fa27918a2baf470d 100644 (file)
@@ -329,16 +329,9 @@ extern void
        xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,
                               int first, int last);
 
-extern void
-       xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
-                               int first, int last);
-
 extern void
        xfs_dir2_leaf_log_header(struct xfs_trans *tp, struct xfs_dabuf *bp);
 
-extern void
-       xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
-
 extern int
        xfs_dir2_leaf_lookup(struct xfs_da_args *args);
 
index 617018d6bbdc0c47f0b64ff1d8ead575785adb88..c2ea6171fb0e3dff5e9afa32c0674a4782df0476 100644 (file)
@@ -91,6 +91,10 @@ STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
                                          int *number_entries_in_blk1,
                                          int *number_namebytes_in_blk1);
 
+STATIC int xfs_dir_leaf_create(struct xfs_da_args *args,
+                               xfs_dablk_t which_block,
+                               struct xfs_dabuf **bpp);
+
 /*
  * Utility routines.
  */
@@ -781,7 +785,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args)
  * Create the initial contents of a leaf directory
  * or a leaf in a node directory.
  */
-int
+STATIC int
 xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
 {
        xfs_dir_leafblock_t *leaf;
index 00d68d33cc7a39e825ec0b313aea05134844ebc1..dd423ce1bc8d082a177effddde9f35b341932996 100644 (file)
@@ -202,8 +202,6 @@ int xfs_dir_leaf_to_shortform(struct xfs_da_args *args);
 /*
  * Routines used for growing the Btree.
  */
-int    xfs_dir_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block,
-                                  struct xfs_dabuf **bpp);
 int    xfs_dir_leaf_split(struct xfs_da_state *state,
                                  struct xfs_da_state_blk *oldblk,
                                  struct xfs_da_state_blk *newblk);
index 55ae3e67d2450b3dd4188f968e56ec24046bd928..55c17adaaa37d64e3c7b22be419bbd6398a9c428 100644 (file)
@@ -166,27 +166,32 @@ typedef enum {
 #define DM_FLAGS_NDELAY                0x001   /* return EAGAIN after dm_pending() */
 #define DM_FLAGS_UNWANTED      0x002   /* event not in fsys dm_eventset_t */
 #define DM_FLAGS_ISEM          0x004   /* thread holds i_sem */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)
-/* i_alloc_sem was added in 2.4.22-pre1 */
 #define DM_FLAGS_IALLOCSEM_RD  0x010   /* thread holds i_alloc_sem rd */
 #define DM_FLAGS_IALLOCSEM_WR  0x020   /* thread holds i_alloc_sem wr */
-#endif
-#endif
 
 /*
  *     Based on IO_ISDIRECT, decide which i_ flag is set.
  */
-#ifdef DM_FLAGS_IALLOCSEM_RD
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+                             DM_FLAGS_ISEM : 0)
+#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \
+    (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22))
 #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
                              DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM)
 #define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
-#else
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21)
 #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
                              0 : DM_FLAGS_ISEM)
 #define DM_SEM_FLAG_WR (DM_FLAGS_ISEM)
 #endif
 
+
 /*
  *     Macros to turn caller specified delay/block flags into
  *     dm_send_xxxx_event flag DM_FLAGS_NDELAY.
index bbe1dea11c0879d463ae0591cf94e6b65c890acb..dcd3fdd5c1f7817697090617136c7622ebc67419 100644 (file)
@@ -280,7 +280,7 @@ xfs_error_report(
        }
 }
 
-void
+STATIC void
 xfs_hex_dump(void *p, int length)
 {
        __uint8_t *uip = (__uint8_t*)p;
index 6bc0535c0a65bf345149f90ea61de527b75ca603..52ee2b90b5edc370f602a2390e21266e18284bc3 100644 (file)
@@ -73,9 +73,6 @@ xfs_corruption_error(
        int             linenum,
        inst_t          *ra);
 
-extern void
-xfs_hex_dump(void *p, int length);
-
 #define        XFS_ERROR_REPORT(e, lvl, mp)    \
        xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
 #define        XFS_CORRUPTION_ERROR(e, lvl, mp, mem)   \
index 5eafd5b6321183cea0bfba7acbce1be7000b5200..db7cbd1bc8573e81d5f05699032b7731573a5bf2 100644 (file)
@@ -59,6 +59,18 @@ STATIC void  xfs_efi_item_abort(xfs_efi_log_item_t *);
 STATIC void    xfs_efd_item_abort(xfs_efd_log_item_t *);
 
 
+void
+xfs_efi_item_free(xfs_efi_log_item_t *efip)
+{
+       int nexts = efip->efi_format.efi_nextents;
+
+       if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
+               kmem_free(efip, sizeof(xfs_efi_log_item_t) +
+                               (nexts - 1) * sizeof(xfs_extent_t));
+       } else {
+               kmem_zone_free(xfs_efi_zone, efip);
+       }
+}
 
 /*
  * This returns the number of iovecs needed to log the given efi item.
@@ -120,8 +132,6 @@ xfs_efi_item_pin(xfs_efi_log_item_t *efip)
 STATIC void
 xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
 {
-       int             nexts;
-       int             size;
        xfs_mount_t     *mp;
        SPLDECL(s);
 
@@ -132,21 +142,11 @@ xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
                 * xfs_trans_delete_ail() drops the AIL lock.
                 */
                xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-
-               nexts = efip->efi_format.efi_nextents;
-               if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-                       size = sizeof(xfs_efi_log_item_t);
-                       size += (nexts - 1) * sizeof(xfs_extent_t);
-                       kmem_free(efip, size);
-               } else {
-                       kmem_zone_free(xfs_efi_zone, efip);
-               }
+               xfs_efi_item_free(efip);
        } else {
                efip->efi_flags |= XFS_EFI_COMMITTED;
                AIL_UNLOCK(mp, s);
        }
-
-       return;
 }
 
 /*
@@ -159,8 +159,6 @@ xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
 STATIC void
 xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
 {
-       int             nexts;
-       int             size;
        xfs_mount_t     *mp;
        xfs_log_item_desc_t     *lidp;
        SPLDECL(s);
@@ -178,23 +176,11 @@ xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
                 * xfs_trans_delete_ail() drops the AIL lock.
                 */
                xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-               /*
-                * now free the item itself
-                */
-               nexts = efip->efi_format.efi_nextents;
-               if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-                       size = sizeof(xfs_efi_log_item_t);
-                       size += (nexts - 1) * sizeof(xfs_extent_t);
-                       kmem_free(efip, size);
-               } else {
-                       kmem_zone_free(xfs_efi_zone, efip);
-               }
+               xfs_efi_item_free(efip);
        } else {
                efip->efi_flags |= XFS_EFI_COMMITTED;
                AIL_UNLOCK(mp, s);
        }
-
-       return;
 }
 
 /*
@@ -245,18 +231,7 @@ xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
 STATIC void
 xfs_efi_item_abort(xfs_efi_log_item_t *efip)
 {
-       int     nexts;
-       int     size;
-
-       nexts = efip->efi_format.efi_nextents;
-       if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-               size = sizeof(xfs_efi_log_item_t);
-               size += (nexts - 1) * sizeof(xfs_extent_t);
-               kmem_free(efip, size);
-       } else {
-               kmem_zone_free(xfs_efi_zone, efip);
-       }
-       return;
+       xfs_efi_item_free(efip);
 }
 
 /*
@@ -288,7 +263,7 @@ xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
 /*
  * This is the ops vector shared by all efi log items.
  */
-struct xfs_item_ops xfs_efi_item_ops = {
+STATIC struct xfs_item_ops xfs_efi_item_ops = {
        .iop_size       = (uint(*)(xfs_log_item_t*))xfs_efi_item_size,
        .iop_format     = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
                                        xfs_efi_item_format,
@@ -355,8 +330,6 @@ xfs_efi_release(xfs_efi_log_item_t  *efip,
 {
        xfs_mount_t     *mp;
        int             extents_left;
-       uint            size;
-       int             nexts;
        SPLDECL(s);
 
        mp = efip->efi_item.li_mountp;
@@ -372,20 +345,10 @@ xfs_efi_release(xfs_efi_log_item_t        *efip,
                 * xfs_trans_delete_ail() drops the AIL lock.
                 */
                xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
+               xfs_efi_item_free(efip);
        } else {
                AIL_UNLOCK(mp, s);
        }
-
-       if (extents_left == 0) {
-               nexts = efip->efi_format.efi_nextents;
-               if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-                       size = sizeof(xfs_efi_log_item_t);
-                       size += (nexts - 1) * sizeof(xfs_extent_t);
-                       kmem_free(efip, size);
-               } else {
-                       kmem_zone_free(xfs_efi_zone, efip);
-               }
-       }
 }
 
 /*
@@ -398,8 +361,6 @@ STATIC void
 xfs_efi_cancel(
        xfs_efi_log_item_t      *efip)
 {
-       int             nexts;
-       int             size;
        xfs_mount_t     *mp;
        SPLDECL(s);
 
@@ -410,26 +371,25 @@ xfs_efi_cancel(
                 * xfs_trans_delete_ail() drops the AIL lock.
                 */
                xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-
-               nexts = efip->efi_format.efi_nextents;
-               if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-                       size = sizeof(xfs_efi_log_item_t);
-                       size += (nexts - 1) * sizeof(xfs_extent_t);
-                       kmem_free(efip, size);
-               } else {
-                       kmem_zone_free(xfs_efi_zone, efip);
-               }
+               xfs_efi_item_free(efip);
        } else {
                efip->efi_flags |= XFS_EFI_CANCELED;
                AIL_UNLOCK(mp, s);
        }
-
-       return;
 }
 
+STATIC void
+xfs_efd_item_free(xfs_efd_log_item_t *efdp)
+{
+       int nexts = efdp->efd_format.efd_nextents;
 
-
-
+       if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
+               kmem_free(efdp, sizeof(xfs_efd_log_item_t) +
+                               (nexts - 1) * sizeof(xfs_extent_t));
+       } else {
+               kmem_zone_free(xfs_efd_zone, efdp);
+       }
+}
 
 /*
  * This returns the number of iovecs needed to log the given efd item.
@@ -533,9 +493,6 @@ xfs_efd_item_unlock(xfs_efd_log_item_t *efdp)
 STATIC xfs_lsn_t
 xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
 {
-       uint    size;
-       int     nexts;
-
        /*
         * If we got a log I/O error, it's always the case that the LR with the
         * EFI got unpinned and freed before the EFD got aborted.
@@ -543,15 +500,7 @@ xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
        if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
                xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents);
 
-       nexts = efdp->efd_format.efd_nextents;
-       if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
-               size = sizeof(xfs_efd_log_item_t);
-               size += (nexts - 1) * sizeof(xfs_extent_t);
-               kmem_free(efdp, size);
-       } else {
-               kmem_zone_free(xfs_efd_zone, efdp);
-       }
-
+       xfs_efd_item_free(efdp);
        return (xfs_lsn_t)-1;
 }
 
@@ -565,9 +514,6 @@ xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
 STATIC void
 xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
 {
-       int     nexts;
-       int     size;
-
        /*
         * If we got a log I/O error, it's always the case that the LR with the
         * EFI got unpinned and freed before the EFD got aborted. So don't
@@ -576,15 +522,7 @@ xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
        if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
                xfs_efi_cancel(efdp->efd_efip);
 
-       nexts = efdp->efd_format.efd_nextents;
-       if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
-               size = sizeof(xfs_efd_log_item_t);
-               size += (nexts - 1) * sizeof(xfs_extent_t);
-               kmem_free(efdp, size);
-       } else {
-               kmem_zone_free(xfs_efd_zone, efdp);
-       }
-       return;
+       xfs_efd_item_free(efdp);
 }
 
 /*
@@ -615,7 +553,7 @@ xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn)
 /*
  * This is the ops vector shared by all efd log items.
  */
-struct xfs_item_ops xfs_efd_item_ops = {
+STATIC struct xfs_item_ops xfs_efd_item_ops = {
        .iop_size       = (uint(*)(xfs_log_item_t*))xfs_efd_item_size,
        .iop_format     = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
                                        xfs_efd_item_format,
index 7122d6101d15803644220269f172ba4817118f2e..d433bac9f59d81f59de6f6593e7ab8a96d2c3149 100644 (file)
@@ -118,6 +118,8 @@ xfs_efi_log_item_t  *xfs_efi_init(struct xfs_mount *, uint);
 xfs_efd_log_item_t     *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
                                      uint);
 
+void                   xfs_efi_item_free(xfs_efi_log_item_t *);
+
 #endif /* __KERNEL__ */
 
 #endif /* __XFS_EXTFREE_ITEM_H__ */
index 6ee8443bf9d33da239e8b389f0dd64108d429324..095af0a5cff3bc50a4420d81e65ef8ed2b7ae710 100644 (file)
@@ -60,7 +60,8 @@ struct fsxattr {
        __u32           fsx_xflags;     /* xflags field value (get/set) */
        __u32           fsx_extsize;    /* extsize field value (get/set)*/
        __u32           fsx_nextents;   /* nextents field value (get)   */
-       unsigned char   fsx_pad[16];
+       __u32           fsx_projid;     /* project identifier (get/set) */
+       unsigned char   fsx_pad[12];
 };
 #endif
 
index 21213057c27f9ff655100f986cd7ad49d930b619..ca535d613190fca9ac1a15df62713223d4a69825 100644 (file)
@@ -559,32 +559,6 @@ xfs_reserve_blocks(
        return(0);
 }
 
-void
-xfs_fs_log_dummy(xfs_mount_t *mp)
-{
-       xfs_trans_t *tp;
-       xfs_inode_t *ip;
-
-
-       tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
-       atomic_inc(&mp->m_active_trans);
-       if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
-               xfs_trans_cancel(tp, 0);
-               return;
-       }
-
-       ip = mp->m_rootip;
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-       xfs_trans_ihold(tp, ip);
-       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       xfs_trans_set_sync(tp);
-       xfs_trans_commit(tp, 0, NULL);
-
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-}
-
 int
 xfs_fs_goingdown(
        xfs_mount_t     *mp,
index 803c4d17a057b3e313707289fdc3a00b81b5d38b..44be188674a6a0e405b40559deec84d2aa4dd75c 100644 (file)
@@ -100,9 +100,13 @@ xfs_inofree_t xfs_inobt_mask(int i);
 #endif
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_IS_FREE)
 int xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i);
-#define        XFS_INOBT_IS_FREE(rp,i) xfs_inobt_is_free(rp,i)
+#define        XFS_INOBT_IS_FREE(rp,i)         xfs_inobt_is_free(rp,i)
+#define        XFS_INOBT_IS_FREE_DISK(rp,i)    xfs_inobt_is_free_disk(rp,i)
 #else
-#define        XFS_INOBT_IS_FREE(rp,i) (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
+#define        XFS_INOBT_IS_FREE(rp,i) \
+       (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
+#define XFS_INOBT_IS_FREE_DISK(rp,i) \
+       ((INT_GET((rp)->ir_free, ARCH_CONVERT) & XFS_INOBT_MASK(i)) != 0)
 #endif
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_SET_FREE)
 void xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i);
index bc8c8c7f9039d507978d727a25c446b661af4d56..34bdf5909687b30d0619e3e9f6d42feee4de4098 100644 (file)
@@ -145,51 +145,6 @@ xfs_inobp_check(
 }
 #endif
 
-/*
- * called from bwrite on xfs inode buffers
- */
-void
-xfs_inobp_bwcheck(xfs_buf_t *bp)
-{
-       xfs_mount_t     *mp;
-       int             i;
-       int             j;
-       xfs_dinode_t    *dip;
-
-       ASSERT(XFS_BUF_FSPRIVATE3(bp, void *) != NULL);
-
-       mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *);
-
-
-       j = mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog;
-
-       for (i = 0; i < j; i++)  {
-               dip = (xfs_dinode_t *) xfs_buf_offset(bp,
-                                               i * mp->m_sb.sb_inodesize);
-               if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
-                       cmn_err(CE_WARN,
-"Bad magic # 0x%x in XFS inode buffer 0x%Lx, starting blockno %Ld, offset 0x%x",
-                               INT_GET(dip->di_core.di_magic, ARCH_CONVERT),
-                               (__uint64_t)(__psunsigned_t) bp,
-                               (__int64_t) XFS_BUF_ADDR(bp),
-                               xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
-                       xfs_fs_cmn_err(CE_WARN, mp,
-                               "corrupt, unmount and run xfs_repair");
-               }
-               if (!dip->di_next_unlinked)  {
-                       cmn_err(CE_WARN,
-"Bad next_unlinked field (0) in XFS inode buffer 0x%p, starting blockno %Ld, offset 0x%x",
-                               (__uint64_t)(__psunsigned_t) bp,
-                               (__int64_t) XFS_BUF_ADDR(bp),
-                               xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
-                       xfs_fs_cmn_err(CE_WARN, mp,
-                               "corrupt, unmount and run xfs_repair");
-               }
-       }
-
-       return;
-}
-
 /*
  * This routine is called to map an inode number within a file
  * system to the buffer containing the on-disk version of the
@@ -203,7 +158,7 @@ xfs_inobp_bwcheck(xfs_buf_t *bp)
  * Use xfs_imap() to determine the size and location of the
  * buffer to read from disk.
  */
-int
+STATIC int
 xfs_inotobp(
        xfs_mount_t     *mp,
        xfs_trans_t     *tp,
@@ -1247,26 +1202,32 @@ xfs_ialloc(
        case S_IFREG:
        case S_IFDIR:
                if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
-                       if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
-                               if ((mode & S_IFMT) == S_IFDIR) {
-                                       ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT;
-                               } else {
-                                       ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
+                       uint    di_flags = 0;
+
+                       if ((mode & S_IFMT) == S_IFDIR) {
+                               if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
+                                       di_flags |= XFS_DIFLAG_RTINHERIT;
+                       } else {
+                               if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
+                                       di_flags |= XFS_DIFLAG_REALTIME;
                                        ip->i_iocore.io_flags |= XFS_IOCORE_RT;
                                }
                        }
                        if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
                            xfs_inherit_noatime)
-                               ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
+                               di_flags |= XFS_DIFLAG_NOATIME;
                        if ((pip->i_d.di_flags & XFS_DIFLAG_NODUMP) &&
                            xfs_inherit_nodump)
-                               ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
+                               di_flags |= XFS_DIFLAG_NODUMP;
                        if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) &&
                            xfs_inherit_sync)
-                               ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+                               di_flags |= XFS_DIFLAG_SYNC;
                        if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) &&
                            xfs_inherit_nosymlinks)
-                               ip->i_d.di_flags |= XFS_DIFLAG_NOSYMLINKS;
+                               di_flags |= XFS_DIFLAG_NOSYMLINKS;
+                       if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+                               di_flags |= XFS_DIFLAG_PROJINHERIT;
+                       ip->i_d.di_flags |= di_flags;
                }
                /* FALLTHROUGH */
        case S_IFLNK:
@@ -2156,7 +2117,7 @@ static __inline__ int xfs_inode_clean(xfs_inode_t *ip)
                (ip->i_update_core == 0));
 }
 
-void
+STATIC void
 xfs_ifree_cluster(
        xfs_inode_t     *free_ip,
        xfs_trans_t     *tp,
@@ -2875,7 +2836,7 @@ xfs_iunpin(
  * be subsequently pinned once someone is waiting for it to be
  * unpinned.
  */
-void
+STATIC void
 xfs_iunpin_wait(
        xfs_inode_t     *ip)
 {
@@ -3601,107 +3562,43 @@ corrupt_out:
 
 
 /*
- * Flush all inactive inodes in mp.  Return true if no user references
- * were found, false otherwise.
+ * Flush all inactive inodes in mp.
  */
-int
+void
 xfs_iflush_all(
-       xfs_mount_t     *mp,
-       int             flag)
+       xfs_mount_t     *mp)
 {
-       int             busy;
-       int             done;
-       int             purged;
        xfs_inode_t     *ip;
-       vmap_t          vmap;
        vnode_t         *vp;
 
-       busy = done = 0;
-       while (!done) {
-               purged = 0;
-               XFS_MOUNT_ILOCK(mp);
-               ip = mp->m_inodes;
-               if (ip == NULL) {
-                       break;
-               }
-               do {
-                       /* Make sure we skip markers inserted by sync */
-                       if (ip->i_mount == NULL) {
-                               ip = ip->i_mnext;
-                               continue;
-                       }
-
-                       /*
-                        * It's up to our caller to purge the root
-                        * and quota vnodes later.
-                        */
-                       vp = XFS_ITOV_NULL(ip);
-
-                       if (!vp) {
-                               XFS_MOUNT_IUNLOCK(mp);
-                               xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
-                               purged = 1;
-                               break;
-                       }
+ again:
+       XFS_MOUNT_ILOCK(mp);
+       ip = mp->m_inodes;
+       if (ip == NULL)
+               goto out;
 
-                       if (vn_count(vp) != 0) {
-                               if (vn_count(vp) == 1 &&
-                                   (ip == mp->m_rootip ||
-                                    (mp->m_quotainfo &&
-                                     (ip->i_ino == mp->m_sb.sb_uquotino ||
-                                      ip->i_ino == mp->m_sb.sb_gquotino)))) {
+       do {
+               /* Make sure we skip markers inserted by sync */
+               if (ip->i_mount == NULL) {
+                       ip = ip->i_mnext;
+                       continue;
+               }
 
-                                       ip = ip->i_mnext;
-                                       continue;
-                               }
-                               if (!(flag & XFS_FLUSH_ALL)) {
-                                       busy = 1;
-                                       done = 1;
-                                       break;
-                               }
-                               /*
-                                * Ignore busy inodes but continue flushing
-                                * others.
-                                */
-                               ip = ip->i_mnext;
-                               continue;
-                       }
-                       /*
-                        * Sample vp mapping while holding mp locked on MP
-                        * systems, so we don't purge a reclaimed or
-                        * nonexistent vnode.  We break from the loop
-                        * since we know that we modify
-                        * it by pulling ourselves from it in xfs_reclaim()
-                        * called via vn_purge() below.  Set ip to the next
-                        * entry in the list anyway so we'll know below
-                        * whether we reached the end or not.
-                        */
-                       VMAP(vp, vmap);
+               vp = XFS_ITOV_NULL(ip);
+               if (!vp) {
                        XFS_MOUNT_IUNLOCK(mp);
+                       xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
+                       goto again;
+               }
 
-                       vn_purge(vp, &vmap);
+               ASSERT(vn_count(vp) == 0);
 
-                       purged = 1;
-                       break;
-               } while (ip != mp->m_inodes);
-               /*
-                * We need to distinguish between when we exit the loop
-                * after a purge and when we simply hit the end of the
-                * list.  We can't use the (ip == mp->m_inodes) test,
-                * because when we purge an inode at the start of the list
-                * the next inode on the list becomes mp->m_inodes.  That
-                * would cause such a test to bail out early.  The purged
-                * variable tells us how we got out of the loop.
-                */
-               if (!purged) {
-                       done = 1;
-               }
-       }
+               ip = ip->i_mnext;
+       } while (ip != mp->m_inodes);
+ out:
        XFS_MOUNT_IUNLOCK(mp);
-       return !busy;
 }
 
-
 /*
  * xfs_iaccess: check accessibility of inode for mode.
  */
index 37e1c316f3b6bd520c37d4bea1a86aeaf0375a6e..54d9e54c7c9572f5bb79ebe4434990a5abc6025b 100644 (file)
@@ -411,11 +411,6 @@ void xfs_ifork_next_set(xfs_inode_t *ip, int w, int n);
 #define        XFS_IFLUSH_ASYNC                4
 #define        XFS_IFLUSH_DELWRI               5
 
-/*
- * Flags for xfs_iflush_all.
- */
-#define        XFS_FLUSH_ALL           0x1
-
 /*
  * Flags for xfs_itruncate_start().
  */
@@ -487,8 +482,6 @@ int         xfs_finish_reclaim_all(struct xfs_mount *, int);
 /*
  * xfs_inode.c prototypes.
  */
-int            xfs_inotobp(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-                           xfs_dinode_t **, struct xfs_buf **, int *);
 int            xfs_itobp(struct xfs_mount *, struct xfs_trans *,
                          xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
                          xfs_daddr_t);
@@ -522,7 +515,7 @@ void                xfs_ipin(xfs_inode_t *);
 void           xfs_iunpin(xfs_inode_t *);
 int            xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
 int            xfs_iflush(xfs_inode_t *, uint);
-int            xfs_iflush_all(struct xfs_mount *, int);
+void           xfs_iflush_all(struct xfs_mount *);
 int            xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
 uint           xfs_iroundup(uint);
 void           xfs_ichgtime(xfs_inode_t *, int);
index 768cb1816b8eace41f94f6ffcf9f4c2d8a7e4113..0eed30f5cb19de82e45518bb1f2b08c963f9d7d3 100644 (file)
@@ -910,7 +910,7 @@ xfs_inode_item_committing(
 /*
  * This is the ops vector shared by all buf log items.
  */
-struct xfs_item_ops xfs_inode_item_ops = {
+STATIC struct xfs_item_ops xfs_inode_item_ops = {
        .iop_size       = (uint(*)(xfs_log_item_t*))xfs_inode_item_size,
        .iop_format     = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
                                        xfs_inode_item_format,
index 469e1a7939d44fbbe4dfbdbe8c9b2e90f0d4f7f2..2edd6769e5d328d18da1d854d69595ff3cb5a996 100644 (file)
@@ -385,15 +385,15 @@ xfs_iomap_write_direct(
        int             nimaps, maps;
        int             error;
        int             bmapi_flag;
+       int             quota_flag;
        int             rt;
        xfs_trans_t     *tp;
        xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
        xfs_bmap_free_t free_list;
        int             aeof;
-       xfs_filblks_t   datablocks;
+       xfs_filblks_t   datablocks, qblocks, resblks;
        int             committed;
        int             numrtextents;
-       uint            resblks;
 
        /*
         * Make sure that the dquots are there. This doesn't hold
@@ -419,7 +419,6 @@ xfs_iomap_write_direct(
                xfs_fileoff_t   map_last_fsb;
 
                map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
-
                if (map_last_fsb < last_fsb) {
                        last_fsb = map_last_fsb;
                        count_fsb = last_fsb - offset_fsb;
@@ -428,56 +427,47 @@ xfs_iomap_write_direct(
        }
 
        /*
-        * determine if reserving space on
-        * the data or realtime partition.
+        * Determine if reserving space on the data or realtime partition.
         */
        if ((rt = XFS_IS_REALTIME_INODE(ip))) {
-               int     sbrtextsize, iprtextsize;
+               xfs_extlen_t    extsz;
 
-               sbrtextsize = mp->m_sb.sb_rextsize;
-               iprtextsize =
-                       ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize;
-               numrtextents = (count_fsb + iprtextsize - 1);
-               do_div(numrtextents, sbrtextsize);
+               if (!(extsz = ip->i_d.di_extsize))
+                       extsz = mp->m_sb.sb_rextsize;
+               numrtextents = qblocks = (count_fsb + extsz - 1);
+               do_div(numrtextents, mp->m_sb.sb_rextsize);
+               quota_flag = XFS_QMOPT_RES_RTBLKS;
                datablocks = 0;
        } else {
-               datablocks = count_fsb;
+               datablocks = qblocks = count_fsb;
+               quota_flag = XFS_QMOPT_RES_REGBLKS;
                numrtextents = 0;
        }
 
        /*
-        * allocate and setup the transaction
+        * Allocate and setup the transaction
         */
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
-
        resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
-
        error = xfs_trans_reserve(tp, resblks,
                        XFS_WRITE_LOG_RES(mp), numrtextents,
                        XFS_TRANS_PERM_LOG_RES,
                        XFS_WRITE_LOG_COUNT);
 
        /*
-        * check for running out of space
+        * Check for running out of space, note: need lock to return
         */
        if (error)
-               /*
-                * Free the transaction structure.
-                */
                xfs_trans_cancel(tp, 0);
-
        xfs_ilock(ip, XFS_ILOCK_EXCL);
-
        if (error)
-               goto error_out; /* Don't return in above if .. trans ..,
-                                       need lock to return */
+               goto error_out;
 
-       if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) {
+       if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) {
                error = (EDQUOT);
                goto error1;
        }
-       nimaps = 1;
 
        bmapi_flag = XFS_BMAPI_WRITE;
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
@@ -487,31 +477,29 @@ xfs_iomap_write_direct(
                bmapi_flag |= XFS_BMAPI_PREALLOC;
 
        /*
-        * issue the bmapi() call to allocate the blocks
+        * Issue the bmapi() call to allocate the blocks
         */
        XFS_BMAP_INIT(&free_list, &firstfsb);
+       nimaps = 1;
        imapp = &imap[0];
        error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
                bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
-       if (error) {
+       if (error)
                goto error0;
-       }
 
        /*
-        * complete the transaction
+        * Complete the transaction
         */
-
        error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
-       if (error) {
+       if (error)
                goto error0;
-       }
-
        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
-       if (error) {
+       if (error)
                goto error_out;
-       }
 
-       /* copy any maps to caller's array and return any error. */
+       /*
+        * Copy any maps to caller's array and return any error.
+        */
        if (nimaps == 0) {
                error = (ENOSPC);
                goto error_out;
@@ -530,10 +518,11 @@ xfs_iomap_write_direct(
         }
        return 0;
 
- error0:       /* Cancel bmap, unlock inode, and cancel trans */
+error0:        /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
        xfs_bmap_cancel(&free_list);
+       XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
 
- error1:       /* Just cancel transaction */
+error1:        /* Just cancel transaction */
        xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
        *nmaps = 0;     /* nothing set-up here */
 
index 092d5fb096b13e8c5fa9c65bfe02693a3870592c..1cd2ac1638778b3e69c67acd6a47280cdc52cd3a 100644 (file)
@@ -134,7 +134,7 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
 #define xlog_verify_tail_lsn(a,b,c)
 #endif
 
-int            xlog_iclogs_empty(xlog_t *log);
+STATIC int     xlog_iclogs_empty(xlog_t *log);
 
 #ifdef DEBUG
 int xlog_do_error = 0;
@@ -1857,7 +1857,7 @@ xlog_write(xfs_mount_t *  mp,
  *
  * State Change: DIRTY -> ACTIVE
  */
-void
+STATIC void
 xlog_state_clean_log(xlog_t *log)
 {
        xlog_in_core_t  *iclog;
@@ -3542,7 +3542,7 @@ xfs_log_force_umount(
        return (retval);
 }
 
-int
+STATIC int
 xlog_iclogs_empty(xlog_t *log)
 {
        xlog_in_core_t  *iclog;
index c31e3ce3be6602cd8f96fcb7419af04d9912b445..1a1d452f15f97b023f8ce0d33c9e74aad32f4ad6 100644 (file)
@@ -535,7 +535,6 @@ typedef struct log {
 
 /* common routines */
 extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
-extern int      xlog_find_head(xlog_t *log, xfs_daddr_t *head_blk);
 extern int      xlog_find_tail(xlog_t  *log,
                                xfs_daddr_t *head_blk,
                                xfs_daddr_t *tail_blk,
@@ -548,7 +547,6 @@ extern void  xlog_recover_process_iunlinks(xlog_t *log);
 extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
 extern void     xlog_put_bp(struct xfs_buf *);
 extern int      xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
-extern xfs_caddr_t xlog_align(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
 
 /* iclog tracing */
 #define XLOG_TRACE_GRAB_FLUSH  1
index 9824b5bf0ec03ea6af15803978106adeedc5a1d9..0aac28ddb81c6bc00d6b37ee341fa4db5258d119 100644 (file)
@@ -148,7 +148,7 @@ xlog_bread(
  * The buffer is kept locked across the write and is returned locked.
  * This can only be used for synchronous log writes.
  */
-int
+STATIC int
 xlog_bwrite(
        xlog_t          *log,
        xfs_daddr_t     blk_no,
@@ -179,7 +179,7 @@ xlog_bwrite(
        return error;
 }
 
-xfs_caddr_t
+STATIC xfs_caddr_t
 xlog_align(
        xlog_t          *log,
        xfs_daddr_t     blk_no,
@@ -528,7 +528,7 @@ out:
  *
  * Return: zero if normal, non-zero if error.
  */
-int
+STATIC int
 xlog_find_head(
        xlog_t          *log,
        xfs_daddr_t     *return_head_blk)
@@ -1964,7 +1964,8 @@ xlog_recover_do_reg_buffer(
                 * probably a good thing to do for other buf types also.
                 */
                error = 0;
-               if (buf_f->blf_flags & (XFS_BLI_UDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
+               if (buf_f->blf_flags &
+                  (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
                        error = xfs_qm_dqcheck((xfs_disk_dquot_t *)
                                               item->ri_buf[i].i_addr,
                                               -1, 0, XFS_QMOPT_DOWARN,
@@ -2030,6 +2031,7 @@ xfs_qm_dqcheck(
        }
 
        if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER &&
+           INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_PROJ &&
            INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) {
                if (flags & XFS_QMOPT_DOWARN)
                        cmn_err(CE_ALERT,
@@ -2135,6 +2137,8 @@ xlog_recover_do_dquot_buffer(
        type = 0;
        if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF)
                type |= XFS_DQ_USER;
+       if (buf_f->blf_flags & XFS_BLI_PDQUOT_BUF)
+               type |= XFS_DQ_PROJ;
        if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF)
                type |= XFS_DQ_GROUP;
        /*
@@ -2247,7 +2251,8 @@ xlog_recover_do_buffer_trans(
        error = 0;
        if (flags & XFS_BLI_INODE_BUF) {
                error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
-       } else if (flags & (XFS_BLI_UDQUOT_BUF | XFS_BLI_GDQUOT_BUF)) {
+       } else if (flags &
+                 (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
                xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
        } else {
                xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
@@ -2619,7 +2624,7 @@ xlog_recover_do_dquot_trans(
         * This type of quotas was turned off, so ignore this record.
         */
        type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
-                       (XFS_DQ_USER | XFS_DQ_GROUP);
+                       (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
        ASSERT(type);
        if (log->l_quotaoffs_flag & type)
                return (0);
@@ -2742,7 +2747,6 @@ xlog_recover_do_efd_trans(
        xfs_efi_log_item_t      *efip = NULL;
        xfs_log_item_t          *lip;
        int                     gen;
-       int                     nexts;
        __uint64_t              efi_id;
        SPLDECL(s);
 
@@ -2777,22 +2781,15 @@ xlog_recover_do_efd_trans(
                }
                lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
        }
-       if (lip == NULL) {
-               AIL_UNLOCK(mp, s);
-       }
 
        /*
         * If we found it, then free it up.  If it wasn't there, it
         * must have been overwritten in the log.  Oh well.
         */
        if (lip != NULL) {
-               nexts = efip->efi_format.efi_nextents;
-               if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-                       kmem_free(lip, sizeof(xfs_efi_log_item_t) +
-                                 ((nexts - 1) * sizeof(xfs_extent_t)));
-               } else {
-                       kmem_zone_free(xfs_efi_zone, efip);
-               }
+               xfs_efi_item_free(efip);
+       } else {
+               AIL_UNLOCK(mp, s);
        }
 }
 
index ce4f46c6b3aba1d36ae898dc42f1a0ba15c64139..698c2cd6285802ac13435856a23261d9fca3ae3d 100644 (file)
@@ -1658,6 +1658,11 @@ xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i)
 {
        return XFS_INOBT_IS_FREE(rp, i);
 }
+int
+xfs_inobt_is_free_disk(xfs_inobt_rec_t *rp, int i)
+{
+       return XFS_INOBT_IS_FREE_DISK(rp, i);
+}
 #endif
 
 #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_INOBT_IS_LAST_REC)
index 2ec967d93e5ae5eb2aaf1ac06441294ee357382a..82e1646e6243765e121231680f5514470e4bd0a1 100644 (file)
@@ -64,6 +64,7 @@
 STATIC void    xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);
 STATIC int     xfs_uuid_mount(xfs_mount_t *);
 STATIC void    xfs_uuid_unmount(xfs_mount_t *mp);
+STATIC void    xfs_unmountfs_wait(xfs_mount_t *);
 
 static struct {
     short offset;
@@ -555,7 +556,7 @@ xfs_readsb(xfs_mount_t *mp)
  * fields from the superblock associated with the given
  * mount structure
  */
-void
+STATIC void
 xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
 {
        int     i;
@@ -1081,7 +1082,7 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
        int64_t         fsid;
 #endif
 
-       xfs_iflush_all(mp, XFS_FLUSH_ALL);
+       xfs_iflush_all(mp);
 
        XFS_QM_DQPURGEALL(mp,
                XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING);
@@ -1111,15 +1112,6 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
         */
        ASSERT(mp->m_inodes == NULL);
 
-       /*
-        * We may have bufs that are in the process of getting written still.
-        * We must wait for the I/O completion of those. The sync flag here
-        * does a two pass iteration thru the bufcache.
-        */
-       if (XFS_FORCED_SHUTDOWN(mp)) {
-               xfs_incore_relse(mp->m_ddev_targp, 0, 1); /* synchronous */
-       }
-
        xfs_unmountfs_close(mp, cr);
        if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
                xfs_uuid_unmount(mp);
@@ -1146,7 +1138,7 @@ xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
        xfs_free_buftarg(mp->m_ddev_targp, 0);
 }
 
-void
+STATIC void
 xfs_unmountfs_wait(xfs_mount_t *mp)
 {
        if (mp->m_logdev_targp != mp->m_ddev_targp)
index 30dd08fb9f577bb1943e54d83ba9d3625a45303f..5affba38a57753510952570e6dd0f71969ea350a 100644 (file)
@@ -141,7 +141,7 @@ typedef int (*xfs_dqattach_t)(struct xfs_inode *, uint);
 typedef void   (*xfs_dqdetach_t)(struct xfs_inode *);
 typedef int    (*xfs_dqpurgeall_t)(struct xfs_mount *, uint);
 typedef int    (*xfs_dqvopalloc_t)(struct xfs_mount *,
-                       struct xfs_inode *, uid_t, gid_t, uint,
+                       struct xfs_inode *, uid_t, gid_t, prid_t, uint,
                        struct xfs_dquot **, struct xfs_dquot **);
 typedef void   (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *,
                        struct xfs_dquot *, struct xfs_dquot *);
@@ -185,8 +185,8 @@ typedef struct xfs_qmops {
        (*(mp)->m_qm_ops.xfs_dqdetach)(ip)
 #define XFS_QM_DQPURGEALL(mp, fl) \
        (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
-#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, fl, dq1, dq2) \
-       (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, fl, dq1, dq2)
+#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
+       (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
 #define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
        (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
 #define XFS_QM_DQVOPRENAME(mp, ip) \
@@ -544,7 +544,6 @@ extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
 extern int     xfs_mountfs(struct vfs *, xfs_mount_t *mp, int);
 
 extern int     xfs_unmountfs(xfs_mount_t *, struct cred *);
-extern void    xfs_unmountfs_wait(xfs_mount_t *);
 extern void    xfs_unmountfs_close(xfs_mount_t *, struct cred *);
 extern int     xfs_unmountfs_writesb(xfs_mount_t *);
 extern int     xfs_unmount_flush(xfs_mount_t *, int);
index 703ec4efcb411574ca3c39a42f52907922922557..7134576ae7faed4f64e1dbb0661bc634a0dbd611 100644 (file)
@@ -96,7 +96,7 @@ typedef struct xfs_dqblk {
  * flags for q_flags field in the dquot.
  */
 #define XFS_DQ_USER            0x0001          /* a user quota */
-/* #define XFS_DQ_PROJ         0x0002          -- project quota (IRIX) */
+#define XFS_DQ_PROJ            0x0002          /* project quota */
 #define XFS_DQ_GROUP           0x0004          /* a group quota */
 #define XFS_DQ_FLOCKED         0x0008          /* flush lock taken */
 #define XFS_DQ_DIRTY           0x0010          /* dquot is dirty */
@@ -104,6 +104,8 @@ typedef struct xfs_dqblk {
 #define XFS_DQ_INACTIVE                0x0040          /* dq off mplist & hashlist */
 #define XFS_DQ_MARKER          0x0080          /* sentinel */
 
+#define XFS_DQ_ALLTYPES                (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
+
 /*
  * In the worst case, when both user and group quotas are on,
  * we can have a max of three dquots changing in a single transaction.
@@ -124,7 +126,7 @@ typedef struct xfs_dqblk {
 typedef struct xfs_dq_logformat {
        __uint16_t              qlf_type;      /* dquot log item type */
        __uint16_t              qlf_size;      /* size of this item */
-       xfs_dqid_t              qlf_id;        /* usr/grp id number : 32 bits */
+       xfs_dqid_t              qlf_id;        /* usr/grp/proj id : 32 bits */
        __int64_t               qlf_blkno;     /* blkno of dquot buffer */
        __int32_t               qlf_len;       /* len of dquot buffer */
        __uint32_t              qlf_boffset;   /* off of dquot in buffer */
@@ -152,9 +154,9 @@ typedef struct xfs_qoff_logformat {
 #define XFS_UQUOTA_ACCT        0x0001  /* user quota accounting ON */
 #define XFS_UQUOTA_ENFD        0x0002  /* user quota limits enforced */
 #define XFS_UQUOTA_CHKD        0x0004  /* quotacheck run on usr quotas */
-#define XFS_PQUOTA_ACCT        0x0008  /* (IRIX) project quota accounting ON */
-#define XFS_GQUOTA_ENFD        0x0010  /* group quota limits enforced */
-#define XFS_GQUOTA_CHKD        0x0020  /* quotacheck run on grp quotas */
+#define XFS_PQUOTA_ACCT        0x0008  /* project quota accounting ON */
+#define XFS_OQUOTA_ENFD        0x0010  /* other (grp/prj) quota limits enforced */
+#define XFS_OQUOTA_CHKD        0x0020  /* quotacheck run on other (grp/prj) quotas */
 #define XFS_GQUOTA_ACCT        0x0040  /* group quota accounting ON */
 
 /*
@@ -162,17 +164,22 @@ typedef struct xfs_qoff_logformat {
  * are in the process of getting turned off. These flags are in m_qflags but
  * never in sb_qflags.
  */
-#define XFS_UQUOTA_ACTIVE      0x0080  /* uquotas are being turned off */
-#define XFS_GQUOTA_ACTIVE      0x0100  /* gquotas are being turned off */
+#define XFS_UQUOTA_ACTIVE      0x0100  /* uquotas are being turned off */
+#define XFS_PQUOTA_ACTIVE      0x0200  /* pquotas are being turned off */
+#define XFS_GQUOTA_ACTIVE      0x0400  /* gquotas are being turned off */
 
 /*
  * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
  * quota will be not be switched off as long as that inode lock is held.
  */
 #define XFS_IS_QUOTA_ON(mp)    ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
-                                                  XFS_GQUOTA_ACTIVE))
+                                                  XFS_GQUOTA_ACTIVE | \
+                                                  XFS_PQUOTA_ACTIVE))
+#define XFS_IS_OQUOTA_ON(mp)   ((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \
+                                                  XFS_PQUOTA_ACTIVE))
 #define XFS_IS_UQUOTA_ON(mp)   ((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
 #define XFS_IS_GQUOTA_ON(mp)   ((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
+#define XFS_IS_PQUOTA_ON(mp)   ((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
 
 /*
  * Flags to tell various functions what to do. Not all of these are meaningful
@@ -182,7 +189,7 @@ typedef struct xfs_qoff_logformat {
 #define XFS_QMOPT_DQLOCK       0x0000001 /* dqlock */
 #define XFS_QMOPT_DQALLOC      0x0000002 /* alloc dquot ondisk if needed */
 #define XFS_QMOPT_UQUOTA       0x0000004 /* user dquot requested */
-#define XFS_QMOPT_GQUOTA       0x0000008 /* group dquot requested */
+#define XFS_QMOPT_PQUOTA       0x0000008 /* project dquot requested */
 #define XFS_QMOPT_FORCE_RES    0x0000010 /* ignore quota limits */
 #define XFS_QMOPT_DQSUSER      0x0000020 /* don't cache super users dquot */
 #define XFS_QMOPT_SBVERSION    0x0000040 /* change superblock version num */
@@ -192,6 +199,7 @@ typedef struct xfs_qoff_logformat {
 #define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if necessary */
 #define XFS_QMOPT_ILOCKED      0x0000800 /* inode is already locked (excl) */
 #define XFS_QMOPT_DQREPAIR     0x0001000 /* repair dquot, if damaged. */
+#define XFS_QMOPT_GQUOTA       0x0002000 /* group dquot requested */
 
 /*
  * flags to xfs_trans_mod_dquot to indicate which field needs to be
@@ -231,7 +239,8 @@ typedef struct xfs_qoff_logformat {
 #define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT
 
 
-#define XFS_QMOPT_QUOTALL      (XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA)
+#define XFS_QMOPT_QUOTALL      \
+               (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
 #define XFS_QMOPT_RESBLK_MASK  (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
 
 #ifdef __KERNEL__
@@ -246,21 +255,33 @@ typedef struct xfs_qoff_logformat {
  */
 #define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
                                     (ip)->i_udquot == NULL) || \
-                                   (XFS_IS_GQUOTA_ON(mp) && \
+                                   (XFS_IS_OQUOTA_ON(mp) && \
                                     (ip)->i_gdquot == NULL))
 
-#define XFS_QM_NEED_QUOTACHECK(mp) ((XFS_IS_UQUOTA_ON(mp) && \
-                                    (mp->m_sb.sb_qflags & \
-                                     XFS_UQUOTA_CHKD) == 0) || \
-                                   (XFS_IS_GQUOTA_ON(mp) && \
-                                    (mp->m_sb.sb_qflags & \
-                                     XFS_GQUOTA_CHKD) == 0))
+#define XFS_QM_NEED_QUOTACHECK(mp) \
+       ((XFS_IS_UQUOTA_ON(mp) && \
+               (mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
+        (XFS_IS_GQUOTA_ON(mp) && \
+               ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
+                (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT))) || \
+        (XFS_IS_PQUOTA_ON(mp) && \
+               ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
+                (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT))))
+
+#define XFS_MOUNT_QUOTA_SET1   (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
+                                XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
+                                XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
+
+#define XFS_MOUNT_QUOTA_SET2   (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
+                                XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
+                                XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
 
 #define XFS_MOUNT_QUOTA_ALL    (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
-                                XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
-                                XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD)
+                                XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
+                                XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
+                                XFS_GQUOTA_ACCT)
 #define XFS_MOUNT_QUOTA_MASK   (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
-                                XFS_GQUOTA_ACTIVE)
+                                XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
 
 
 /*
@@ -331,15 +352,8 @@ typedef struct xfs_dqtrxops {
 #define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
        XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
 
-#define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \
-       XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
-                               XFS_QMOPT_RES_REGBLKS)
-#define XFS_TRANS_RESERVE_BLKQUOTA_FORCE(mp, tp, ip, nblks) \
-       XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
-                               XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES)
-#define XFS_TRANS_UNRESERVE_BLKQUOTA(mp, tp, ip, nblks) \
-       XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), 0, \
-                               XFS_QMOPT_RES_REGBLKS)
+#define XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, flags) \
+       XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), -(ninos), flags)
 #define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \
        XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \
                                f | XFS_QMOPT_RES_REGBLKS)
index cb13f9a1d45ba43aa20bd016a92b564370ed89ad..23b48ac1cb7e5fb9ff73e1f041f8cbf37d9ef38b 100644 (file)
@@ -234,9 +234,6 @@ xfs_lock_for_rename(
        return 0;
 }
 
-
-int rename_which_error_return = 0;
-
 /*
  * xfs_rename
  */
@@ -316,7 +313,6 @@ xfs_rename(
                        &num_inodes);
 
        if (error) {
-               rename_which_error_return = __LINE__;
                /*
                 * We have nothing locked, no inode references, and
                 * no transaction, so just get out.
@@ -332,7 +328,6 @@ xfs_rename(
                 */
                if (target_ip == NULL && (src_dp != target_dp) &&
                    target_dp->i_d.di_nlink >= XFS_MAXLINK) {
-                       rename_which_error_return = __LINE__;
                        error = XFS_ERROR(EMLINK);
                        xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
                        goto rele_return;
@@ -359,7 +354,6 @@ xfs_rename(
                                XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
        }
        if (error) {
-               rename_which_error_return = __LINE__;
                xfs_trans_cancel(tp, 0);
                goto rele_return;
        }
@@ -369,7 +363,6 @@ xfs_rename(
         */
        if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) {
                xfs_trans_cancel(tp, cancel_flags);
-               rename_which_error_return = __LINE__;
                goto rele_return;
        }
 
@@ -413,7 +406,6 @@ xfs_rename(
                if (spaceres == 0 &&
                    (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name,
                                target_namelen))) {
-                       rename_which_error_return = __LINE__;
                        goto error_return;
                }
                /*
@@ -425,11 +417,9 @@ xfs_rename(
                                           target_namelen, src_ip->i_ino,
                                           &first_block, &free_list, spaceres);
                if (error == ENOSPC) {
-                       rename_which_error_return = __LINE__;
                        goto error_return;
                }
                if (error) {
-                       rename_which_error_return = __LINE__;
                        goto abort_return;
                }
                xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -437,7 +427,6 @@ xfs_rename(
                if (new_parent && src_is_directory) {
                        error = xfs_bumplink(tp, target_dp);
                        if (error) {
-                               rename_which_error_return = __LINE__;
                                goto abort_return;
                        }
                }
@@ -455,7 +444,6 @@ xfs_rename(
                        if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) ||
                            (target_ip->i_d.di_nlink > 2)) {
                                error = XFS_ERROR(EEXIST);
-                               rename_which_error_return = __LINE__;
                                goto error_return;
                        }
                }
@@ -473,7 +461,6 @@ xfs_rename(
                        target_namelen, src_ip->i_ino, &first_block,
                        &free_list, spaceres);
                if (error) {
-                       rename_which_error_return = __LINE__;
                        goto abort_return;
                }
                xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -484,7 +471,6 @@ xfs_rename(
                 */
                error = xfs_droplink(tp, target_ip);
                if (error) {
-                       rename_which_error_return = __LINE__;
                        goto abort_return;
                }
                target_ip_dropped = 1;
@@ -495,7 +481,6 @@ xfs_rename(
                         */
                        error = xfs_droplink(tp, target_ip);
                        if (error) {
-                               rename_which_error_return = __LINE__;
                                goto abort_return;
                        }
                }
@@ -519,7 +504,6 @@ xfs_rename(
                                        &free_list, spaceres);
                ASSERT(error != EEXIST);
                if (error) {
-                       rename_which_error_return = __LINE__;
                        goto abort_return;
                }
                xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -550,7 +534,6 @@ xfs_rename(
                 */
                error = xfs_droplink(tp, src_dp);
                if (error) {
-                       rename_which_error_return = __LINE__;
                        goto abort_return;
                }
        }
@@ -558,7 +541,6 @@ xfs_rename(
        error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen,
                        src_ip->i_ino, &first_block, &free_list, spaceres);
        if (error) {
-               rename_which_error_return = __LINE__;
                goto abort_return;
        }
        xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
index 3db0e22007759c076b0ed561270203af3dedd026..06dfca531f79880fc146845b6863d8dc28b6e1d4 100644 (file)
@@ -331,25 +331,6 @@ undo_blocks:
 }
 
 
-/*
- * This is called to set the a callback to be called when the given
- * transaction is committed to disk.  The transaction pointer and the
- * argument pointer will be passed to the callback routine.
- *
- * Only one callback can be associated with any single transaction.
- */
-void
-xfs_trans_callback(
-       xfs_trans_t             *tp,
-       xfs_trans_callback_t    callback,
-       void                    *arg)
-{
-       ASSERT(tp->t_callback == NULL);
-       tp->t_callback = callback;
-       tp->t_callarg = arg;
-}
-
-
 /*
  * Record the indicated change to the given field for application
  * to the file system's superblock when the transaction commits.
@@ -551,7 +532,7 @@ xfs_trans_apply_sb_deltas(
  *
  * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
  */
-void
+STATIC void
 xfs_trans_unreserve_and_mod_sb(
        xfs_trans_t     *tp)
 {
index bd37ccb85e76d30f98d2d61e6c7b79b47a4d9f26..ec541d66fa2a47309a8ec76523435d3756edf71e 100644 (file)
@@ -987,8 +987,6 @@ xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint);
 xfs_trans_t    *xfs_trans_dup(xfs_trans_t *);
 int            xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
                                  uint, uint);
-void           xfs_trans_callback(xfs_trans_t *,
-                                  void (*)(xfs_trans_t *, void *), void *);
 void           xfs_trans_mod_sb(xfs_trans_t *, uint, long);
 struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t,
                                   int, uint);
@@ -1010,7 +1008,6 @@ int               xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
                               xfs_ino_t , uint, uint, struct xfs_inode **);
 void           xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint);
 void           xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *);
-void           xfs_trans_ihold_release(xfs_trans_t *, struct xfs_inode *);
 void           xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
 void           xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
 struct xfs_efi_log_item        *xfs_trans_get_efi(xfs_trans_t *, uint);
index a9682b9510c1dd1f0e2ab1c41746a2f734479eea..144da7a85466c2e85fbffe66ff1f15e08c0873ec 100644 (file)
@@ -976,6 +976,7 @@ xfs_trans_dquot_buf(
        ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
        ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
        ASSERT(type == XFS_BLI_UDQUOT_BUF ||
+              type == XFS_BLI_PDQUOT_BUF ||
               type == XFS_BLI_GDQUOT_BUF);
 
        bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
index e2c3706f453de78c9b9063a87733f7d3f87d8618..7e7631ca49793b6ad8b2cad24d3a0e9ab530f442 100644 (file)
@@ -253,24 +253,6 @@ xfs_trans_ihold(
        ip->i_itemp->ili_flags |= XFS_ILI_HOLD;
 }
 
-/*
- * Cancel the previous inode hold request made on this inode
- * for this transaction.
- */
-/*ARGSUSED*/
-void
-xfs_trans_ihold_release(
-       xfs_trans_t     *tp,
-       xfs_inode_t     *ip)
-{
-       ASSERT(ip->i_transp == tp);
-       ASSERT(ip->i_itemp != NULL);
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
-       ASSERT(ip->i_itemp->ili_flags & XFS_ILI_HOLD);
-
-       ip->i_itemp->ili_flags &= ~XFS_ILI_HOLD;
-}
-
 
 /*
  * This is called to mark the fields indicated in fieldmask as needing
index e4bf711e48ff80f3b1fc9241b12c9bffc94dc348..16f5371ce102ef7da305673e882e751bb7a29273 100644 (file)
@@ -55,7 +55,7 @@ typedef signed long long int  __int64_t;
 typedef unsigned long long int __uint64_t;
 
 typedef enum { B_FALSE,B_TRUE }        boolean_t;
-typedef __int64_t              prid_t;         /* project ID */
+typedef __uint32_t             prid_t;         /* project ID */
 typedef __uint32_t             inst_t;         /* an instruction */
 
 typedef __s64                  xfs_off_t;      /* <file offset> type */
index d1f8146a06ea16d39c09b3997e819800a5189d05..11351f08d438e9b5a3302e32a5c181585c90e8c5 100644 (file)
@@ -428,7 +428,7 @@ xfs_truncate_file(
                if (ip->i_ino != mp->m_sb.sb_uquotino)
                        ASSERT(ip->i_udquot);
        }
-       if (XFS_IS_GQUOTA_ON(mp)) {
+       if (XFS_IS_OQUOTA_ON(mp)) {
                if (ip->i_ino != mp->m_sb.sb_gquotino)
                        ASSERT(ip->i_gdquot);
        }
index b53736650100d3f62644e00ed0de2e1dba685d51..42bcc0215203b16f19e71c844a395a2b3398fb72 100644 (file)
@@ -367,16 +367,6 @@ xfs_finish_flags(
                return XFS_ERROR(EROFS);
        }
 
-       /*
-        * disallow mount attempts with (IRIX) project quota enabled
-        */
-       if (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
-           (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT)) {
-               cmn_err(CE_WARN,
-       "XFS: cannot mount a filesystem with IRIX project quota enabled");
-               return XFS_ERROR(ENOSYS);
-       }
-
        /*
         * check for shared mount.
         */
@@ -622,7 +612,34 @@ out:
        return XFS_ERROR(error);
 }
 
-#define REMOUNT_READONLY_FLAGS (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
+STATIC int
+xfs_quiesce_fs(
+       xfs_mount_t             *mp)
+{
+       int                     count = 0, pincount;
+               
+       xfs_refcache_purge_mp(mp);
+       xfs_flush_buftarg(mp->m_ddev_targp, 0);
+       xfs_finish_reclaim_all(mp, 0);
+
+       /* This loop must run at least twice.
+        * The first instance of the loop will flush
+        * most meta data but that will generate more
+        * meta data (typically directory updates).
+        * Which then must be flushed and logged before
+        * we can write the unmount record.
+        */ 
+       do {
+               xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL);
+               pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
+               if (!pincount) {
+                       delay(50);
+                       count++;
+               }
+       } while (count < 2);
+
+       return 0;
+}
 
 STATIC int
 xfs_mntupdate(
@@ -632,8 +649,7 @@ xfs_mntupdate(
 {
        struct vfs      *vfsp = bhvtovfs(bdp);
        xfs_mount_t     *mp = XFS_BHVTOM(bdp);
-       int             pincount, error;
-       int             count = 0;
+       int             error;
 
        if (args->flags & XFSMNT_NOATIME)
                mp->m_flags |= XFS_MOUNT_NOATIME;
@@ -645,25 +661,7 @@ xfs_mntupdate(
        }
 
        if (*flags & MS_RDONLY) {
-               xfs_refcache_purge_mp(mp);
-               xfs_flush_buftarg(mp->m_ddev_targp, 0);
-               xfs_finish_reclaim_all(mp, 0);
-
-               /* This loop must run at least twice.
-                * The first instance of the loop will flush
-                * most meta data but that will generate more
-                * meta data (typically directory updates).
-                * Which then must be flushed and logged before
-                * we can write the unmount record.
-                */ 
-               do {
-                       VFS_SYNC(vfsp, REMOUNT_READONLY_FLAGS, NULL, error);
-                       pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
-                       if (!pincount) {
-                               delay(50);
-                               count++;
-                       }
-               } while (count < 2);
+               xfs_quiesce_fs(mp);
 
                /* Ok now write out an unmount record */
                xfs_log_unmount_write(mp);
@@ -879,10 +877,12 @@ xfs_sync(
        int             flags,
        cred_t          *credp)
 {
-       xfs_mount_t     *mp;
+       xfs_mount_t     *mp = XFS_BHVTOM(bdp);
 
-       mp = XFS_BHVTOM(bdp);
-       return (xfs_syncsub(mp, flags, 0, NULL));
+       if (unlikely(flags == SYNC_QUIESCE))
+               return xfs_quiesce_fs(mp);
+       else
+               return xfs_syncsub(mp, flags, 0, NULL);
 }
 
 /*
@@ -1681,7 +1681,7 @@ suffix_strtoul(const char *cp, char **endp, unsigned int base)
        return simple_strtoul(cp, endp, base) << shift_left_factor;
 }
 
-int
+STATIC int
 xfs_parseargs(
        struct bhv_desc         *bhv,
        char                    *options,
@@ -1867,7 +1867,7 @@ printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
        return 0;
 }
 
-int
+STATIC int
 xfs_showargs(
        struct bhv_desc         *bhv,
        struct seq_file         *m)
index 25a526629b125163c772815025fec6be0d283657..1377c868f3f4929aec4106f187b01c03f480c433 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -351,21 +351,28 @@ xfs_setattr(
         * If the IDs do change before we take the ilock, we're covered
         * because the i_*dquot fields will get updated anyway.
         */
-       if (XFS_IS_QUOTA_ON(mp) && (mask & (XFS_AT_UID|XFS_AT_GID))) {
+       if (XFS_IS_QUOTA_ON(mp) &&
+           (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
                uint    qflags = 0;
 
-               if (mask & XFS_AT_UID) {
+               if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) {
                        uid = vap->va_uid;
                        qflags |= XFS_QMOPT_UQUOTA;
                } else {
                        uid = ip->i_d.di_uid;
                }
-               if (mask & XFS_AT_GID) {
+               if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) {
                        gid = vap->va_gid;
                        qflags |= XFS_QMOPT_GQUOTA;
                }  else {
                        gid = ip->i_d.di_gid;
                }
+               if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) {
+                       projid = vap->va_projid;
+                       qflags |= XFS_QMOPT_PQUOTA;
+               }  else {
+                       projid = ip->i_d.di_projid;
+               }
                /*
                 * We take a reference when we initialize udqp and gdqp,
                 * so it is important that we never blindly double trip on
@@ -373,7 +380,8 @@ xfs_setattr(
                 */
                ASSERT(udqp == NULL);
                ASSERT(gdqp == NULL);
-               code = XFS_QM_DQVOPALLOC(mp, ip, uid,gid, qflags, &udqp, &gdqp);
+               code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
+                                        &udqp, &gdqp);
                if (code)
                        return (code);
        }
@@ -499,8 +507,6 @@ xfs_setattr(
                 * that the group ID supplied to the chown() function
                 * shall be equal to either the group ID or one of the
                 * supplementary group IDs of the calling process.
-                *
-                * XXX: How does restricted_chown affect projid?
                 */
                if (restricted_chown &&
                    (iuid != uid || (igid != gid &&
@@ -510,10 +516,11 @@ xfs_setattr(
                        goto error_return;
                }
                /*
-                * Do a quota reservation only if uid or gid is actually
+                * Do a quota reservation only if uid/projid/gid is actually
                 * going to change.
                 */
                if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
+                   (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
                    (XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
                        ASSERT(tp);
                        code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
@@ -774,6 +781,7 @@ xfs_setattr(
                }
                if (igid != gid) {
                        if (XFS_IS_GQUOTA_ON(mp)) {
+                               ASSERT(!XFS_IS_PQUOTA_ON(mp));
                                ASSERT(mask & XFS_AT_GID);
                                ASSERT(gdqp);
                                olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
@@ -782,6 +790,13 @@ xfs_setattr(
                        ip->i_d.di_gid = gid;
                }
                if (iprojid != projid) {
+                       if (XFS_IS_PQUOTA_ON(mp)) {
+                               ASSERT(!XFS_IS_GQUOTA_ON(mp));
+                               ASSERT(mask & XFS_AT_PROJID);
+                               ASSERT(gdqp);
+                               olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
+                                                       &ip->i_gdquot, gdqp);
+                       }
                        ip->i_d.di_projid = projid;
                        /*
                         * We may have to rev the inode as well as
@@ -843,6 +858,8 @@ xfs_setattr(
                                di_flags |= XFS_DIFLAG_NOATIME;
                        if (vap->va_xflags & XFS_XFLAG_NODUMP)
                                di_flags |= XFS_DIFLAG_NODUMP;
+                       if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
+                               di_flags |= XFS_DIFLAG_PROJINHERIT;
                        if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
                                if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
                                        di_flags |= XFS_DIFLAG_RTINHERIT;
@@ -1898,7 +1915,9 @@ xfs_create(
        /* Return through std_return after this point. */
 
        udqp = gdqp = NULL;
-       if (vap->va_mask & XFS_AT_PROJID)
+       if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+               prid = dp->i_d.di_projid;
+       else if (vap->va_mask & XFS_AT_PROJID)
                prid = (xfs_prid_t)vap->va_projid;
        else
                prid = (xfs_prid_t)dfltprid;
@@ -1907,7 +1926,7 @@ xfs_create(
         * Make sure that we have allocated dquot(s) on disk.
         */
        error = XFS_QM_DQVOPALLOC(mp, dp,
-                       current_fsuid(credp), current_fsgid(credp),
+                       current_fsuid(credp), current_fsgid(credp), prid,
                        XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
        if (error)
                goto std_return;
@@ -2604,17 +2623,7 @@ xfs_link(
        if (src_vp->v_type == VDIR)
                return XFS_ERROR(EPERM);
 
-       /*
-        * For now, manually find the XFS behavior descriptor for
-        * the source vnode.  If it doesn't exist then something
-        * is wrong and we should just return an error.
-        * Eventually we need to figure out how link is going to
-        * work in the face of stacked vnodes.
-        */
        src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops);
-       if (src_bdp == NULL) {
-               return XFS_ERROR(EXDEV);
-       }
        sip = XFS_BHVTOI(src_bdp);
        tdp = XFS_BHVTOI(target_dir_bdp);
        mp = tdp->i_mount;
@@ -2681,6 +2690,17 @@ xfs_link(
                goto error_return;
        }
 
+       /*
+        * If we are using project inheritance, we only allow hard link
+        * creation in our tree when the project IDs are the same; else
+        * the tree quota mechanism could be circumvented.
+        */
+       if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+                    (tdp->i_d.di_projid != sip->i_d.di_projid))) {
+               error = XFS_ERROR(EPERM);
+               goto error_return;
+       }
+
        if (resblks == 0 &&
            (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name,
                        target_namelen)))
@@ -2803,7 +2823,9 @@ xfs_mkdir(
 
        mp = dp->i_mount;
        udqp = gdqp = NULL;
-       if (vap->va_mask & XFS_AT_PROJID)
+       if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+               prid = dp->i_d.di_projid;
+       else if (vap->va_mask & XFS_AT_PROJID)
                prid = (xfs_prid_t)vap->va_projid;
        else
                prid = (xfs_prid_t)dfltprid;
@@ -2812,7 +2834,7 @@ xfs_mkdir(
         * Make sure that we have allocated dquot(s) on disk.
         */
        error = XFS_QM_DQVOPALLOC(mp, dp,
-                       current_fsuid(credp), current_fsgid(credp),
+                       current_fsuid(credp), current_fsgid(credp), prid,
                        XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
        if (error)
                goto std_return;
@@ -3357,7 +3379,9 @@ xfs_symlink(
        /* Return through std_return after this point. */
 
        udqp = gdqp = NULL;
-       if (vap->va_mask & XFS_AT_PROJID)
+       if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+               prid = dp->i_d.di_projid;
+       else if (vap->va_mask & XFS_AT_PROJID)
                prid = (xfs_prid_t)vap->va_projid;
        else
                prid = (xfs_prid_t)dfltprid;
@@ -3366,7 +3390,7 @@ xfs_symlink(
         * Make sure that we have allocated dquot(s) on disk.
         */
        error = XFS_QM_DQVOPALLOC(mp, dp,
-                       current_fsuid(credp), current_fsgid(credp),
+                       current_fsuid(credp), current_fsgid(credp), prid,
                        XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
        if (error)
                goto std_return;
@@ -4028,7 +4052,7 @@ xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
  *      errno on error
  *
  */
-int
+STATIC int
 xfs_alloc_file_space(
        xfs_inode_t             *ip,
        xfs_off_t               offset,
@@ -4151,9 +4175,8 @@ retry:
                        break;
                }
                xfs_ilock(ip, XFS_ILOCK_EXCL);
-               error = XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp,
-                               ip->i_udquot, ip->i_gdquot, resblks, 0, rt ?
-                               XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+               error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
+                               ip->i_udquot, ip->i_gdquot, resblks, 0, 0);
                if (error)
                        goto error1;
 
@@ -4305,6 +4328,7 @@ xfs_free_file_space(
        xfs_off_t               len,
        int                     attr_flags)
 {
+       vnode_t                 *vp;
        int                     committed;
        int                     done;
        xfs_off_t               end_dmi_offset;
@@ -4325,9 +4349,11 @@ xfs_free_file_space(
        xfs_trans_t             *tp;
        int                     need_iolock = 1;
 
-       vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
+       vp = XFS_ITOV(ip);
        mp = ip->i_mount;
 
+       vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+
        if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
                return error;
 
@@ -4344,7 +4370,7 @@ xfs_free_file_space(
            DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
                if (end_dmi_offset > ip->i_d.di_size)
                        end_dmi_offset = ip->i_d.di_size;
-               error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
+               error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
                                offset, end_dmi_offset - offset,
                                AT_DELAY_FLAG(attr_flags), NULL);
                if (error)
@@ -4363,7 +4389,14 @@ xfs_free_file_space(
        ioffset = offset & ~(rounding - 1);
        if (ilen & (rounding - 1))
                ilen = (ilen + rounding) & ~(rounding - 1);
-       xfs_inval_cached_pages(XFS_ITOV(ip), &(ip->i_iocore), ioffset, 0, 0);
+
+       if (VN_CACHED(vp) != 0) {
+               xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
+                               ctooff(offtoct(ioffset)), -1);
+               VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)),
+                               -1, FI_REMAPF_LOCKED);
+       }
+
        /*
         * Need to zero the stuff we're not freeing, on disk.
         * If its a realtime file & can't use unwritten extents then we
index cbc173ae45aa2a711fee8cf9c913aac5c91c2e84..9950706abdf8289f0d2815dd45102aa787016038 100644 (file)
@@ -43,7 +43,7 @@ extern struct cpuinfo_alpha cpu_data[NR_CPUS];
 #define PROC_CHANGE_PENALTY     20
 
 #define hard_smp_processor_id()        __hard_smp_processor_id()
-#define smp_processor_id()     (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern cpumask_t cpu_present_mask;
 extern cpumask_t cpu_online_map;
index 0f97bb2e8fcef91ffbe3fedbe6c0c1a7f139007b..b9aa2b3a390956cd5eef58563ecfcfb7f7fccffe 100644 (file)
 #ifndef __ASM_ARCH_TPS65010_H
 #define __ASM_ARCH_TPS65010_H
 
+/*
+ * ----------------------------------------------------------------------------
+ * Registers, all 8 bits
+ * ----------------------------------------------------------------------------
+ */
+
+#define        TPS_CHGSTATUS           0x01
+#      define  TPS_CHG_USB             (1 << 7)
+#      define  TPS_CHG_AC              (1 << 6)
+#      define  TPS_CHG_THERM           (1 << 5)
+#      define  TPS_CHG_TERM            (1 << 4)
+#      define  TPS_CHG_TAPER_TMO       (1 << 3)
+#      define  TPS_CHG_CHG_TMO         (1 << 2)
+#      define  TPS_CHG_PRECHG_TMO      (1 << 1)
+#      define  TPS_CHG_TEMP_ERR        (1 << 0)
+#define        TPS_REGSTATUS           0x02
+#      define  TPS_REG_ONOFF           (1 << 7)
+#      define  TPS_REG_COVER           (1 << 6)
+#      define  TPS_REG_UVLO            (1 << 5)
+#      define  TPS_REG_NO_CHG          (1 << 4)        /* tps65013 */
+#      define  TPS_REG_PG_LD02         (1 << 3)
+#      define  TPS_REG_PG_LD01         (1 << 2)
+#      define  TPS_REG_PG_MAIN         (1 << 1)
+#      define  TPS_REG_PG_CORE         (1 << 0)
+#define        TPS_MASK1               0x03
+#define        TPS_MASK2               0x04
+#define        TPS_ACKINT1             0x05
+#define        TPS_ACKINT2             0x06
+#define        TPS_CHGCONFIG           0x07
+#      define  TPS_CHARGE_POR          (1 << 7)        /* 65010/65012 */
+#      define  TPS65013_AUA            (1 << 7)        /* 65011/65013 */
+#      define  TPS_CHARGE_RESET        (1 << 6)
+#      define  TPS_CHARGE_FAST         (1 << 5)
+#      define  TPS_CHARGE_CURRENT      (3 << 3)
+#      define  TPS_VBUS_500MA          (1 << 2)
+#      define  TPS_VBUS_CHARGING       (1 << 1)
+#      define  TPS_CHARGE_ENABLE       (1 << 0)
+#define        TPS_LED1_ON             0x08
+#define        TPS_LED1_PER            0x09
+#define        TPS_LED2_ON             0x0a
+#define        TPS_LED2_PER            0x0b
+#define        TPS_VDCDC1              0x0c
+#      define  TPS_ENABLE_LP           (1 << 3)
+#define        TPS_VDCDC2              0x0d
+#define        TPS_VREGS1              0x0e
+#      define  TPS_LDO2_ENABLE (1 << 7)
+#      define  TPS_LDO2_OFF    (1 << 6)
+#      define  TPS_VLDO2_3_0V  (3 << 4)
+#      define  TPS_VLDO2_2_75V (2 << 4)
+#      define  TPS_VLDO2_2_5V  (1 << 4)
+#      define  TPS_VLDO2_1_8V  (0 << 4)
+#      define  TPS_LDO1_ENABLE (1 << 3)
+#      define  TPS_LDO1_OFF    (1 << 2)
+#      define  TPS_VLDO1_3_0V  (3 << 0)
+#      define  TPS_VLDO1_2_75V (2 << 0)
+#      define  TPS_VLDO1_2_5V  (1 << 0)
+#      define  TPS_VLDO1_ADJ   (0 << 0)
+#define        TPS_MASK3               0x0f
+#define        TPS_DEFGPIO             0x10
+
 /*
  * ----------------------------------------------------------------------------
  * Macros used by exported functions
@@ -71,10 +131,26 @@ extern int tps65010_set_gpio_out_value(unsigned gpio, unsigned value);
  */
 extern int tps65010_set_led(unsigned led, unsigned mode);
 
+/* tps65010_set_vib parameter:
+ * value: ON or OFF
+ */
+extern int tps65010_set_vib(unsigned value);
+
 /* tps65010_set_low_pwr parameter:
  * mode: ON or OFF
  */
 extern int tps65010_set_low_pwr(unsigned mode);
 
+/* tps65010_config_vregs1 parameter:
+ * value to be written to VREGS1 register
+ * Note: The complete register is written, set all bits you need
+ */
+extern int tps65010_config_vregs1(unsigned value);
+
+/* tps65013_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+extern int tps65013_set_low_pwr(unsigned mode);
+
 #endif /*  __ASM_ARCH_TPS65010_H */
 
index bd44f894690f55d74c8679ad2168c4e73dbd030c..6c6c60adbbaa0552aabe8433625a2153b45e5d0e 100644 (file)
@@ -21,7 +21,7 @@
 # error "<asm-arm/smp.h> included in non-SMP build"
 #endif
 
-#define smp_processor_id()     (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern cpumask_t cpu_present_mask;
 #define cpu_possible_map cpu_present_mask
index 8405eb6558edf141999df5ace0c3ba4bf7070ce4..39dd7008013c839a102bc49f53ba4ba5691ab864 100644 (file)
@@ -308,7 +308,7 @@ do {                                                                        \
 ({                                     \
        unsigned long flags;            \
        local_save_flags(flags);        \
-       flags & PSR_I_BIT;              \
+       (int)(flags & PSR_I_BIT);       \
 })
 
 #ifdef CONFIG_SMP
index 1f4ec7b702706ed643c799e034c128595b3527a7..f40593565173939c5755adda6bee419d90a24635 100644 (file)
@@ -125,6 +125,9 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 
 #ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
 #define page_test_and_clear_dirty(page) (0)
+#define pte_maybe_dirty(pte)           pte_dirty(pte)
+#else
+#define pte_maybe_dirty(pte)           (1)
 #endif
 
 #ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
index ed13969fa2d6da7f91c5678da441f645d45c579d..41400d342d442c5d47f2abdf738b91d42bd2d80f 100644 (file)
@@ -68,6 +68,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define HPAGE_MASK     (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
 #endif
 
 #define pgd_val(x)     ((x).pgd)
index 8d60c2b4b0035f888ab943a8e3eb1ae170e30587..e9efe148fdf7f9bfec5bf1ce109a77ca982b89dc 100644 (file)
@@ -236,6 +236,7 @@ static inline pte_t pte_mkexec(pte_t pte)   { (pte).pte_low |= _PAGE_USER; return
 static inline pte_t pte_mkdirty(pte_t pte)     { (pte).pte_low |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)     { (pte).pte_low |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)     { (pte).pte_low |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkhuge(pte_t pte)      { (pte).pte_low |= _PAGE_PRESENT | _PAGE_PSE; return pte; }
 
 #ifdef CONFIG_X86_PAE
 # include <asm/pgtable-3level.h>
@@ -275,7 +276,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
  */
 
 #define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
-#define mk_pte_huge(entry) ((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE)
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
index e03a206dfa36fbde0d15ac5a65f8eea1e7fa7503..55ef31f66bbec2c7771a7571658dad9451dd4823 100644 (file)
@@ -51,7 +51,7 @@ extern u8 x86_cpu_to_apicid[];
  * from the initial startup. We map APIC_BASE very early in page_setup(),
  * so this is correct in the x86 case.
  */
-#define __smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern cpumask_t cpu_callout_map;
 extern cpumask_t cpu_callin_map;
index 61bcc1b1e3f4327fe8f24d6afb6c671ba86f349a..176413fb9ae3b9922031e3ddf57197cbf4430fd1 100644 (file)
 #define __NR_io_submit         248
 #define __NR_io_cancel         249
 #define __NR_fadvise64         250
-
+#define __NR_set_zone_reclaim  251
 #define __NR_exit_group                252
 #define __NR_lookup_dcookie    253
 #define __NR_epoll_create      254
index 9491dacc89cfe0d21fec7adbb471b30d6f4bcde1..83ca4043fc1158076965dfaeae8e782da7f92292 100644 (file)
 #include <asm/page.h>
 #include <asm/meminit.h>
 
+static inline int pfn_to_nid(unsigned long pfn)
+{
+#ifdef CONFIG_NUMA
+       extern int paddr_to_nid(unsigned long);
+       int nid = paddr_to_nid(pfn << PAGE_SHIFT);
+       if (nid < 0)
+               return 0;
+       else
+               return nid;
+#else
+       return 0;
+#endif
+}
+
 #ifdef CONFIG_DISCONTIGMEM
 
 #ifdef CONFIG_IA64_DIG /* DIG systems are small */
index fcc9c3344ab40f3ebd3891eb273fd1898f9e3fdc..48586e08f432b5cc2793d0d4952869497e11d7bf 100644 (file)
@@ -283,6 +283,7 @@ ia64_phys_addr_valid (unsigned long addr)
 #define pte_mkyoung(pte)       (__pte(pte_val(pte) | _PAGE_A))
 #define pte_mkclean(pte)       (__pte(pte_val(pte) & ~_PAGE_D))
 #define pte_mkdirty(pte)       (__pte(pte_val(pte) | _PAGE_D))
+#define pte_mkhuge(pte)                (__pte(pte_val(pte) | _PAGE_P))
 
 /*
  * Macro to a page protection value as "uncacheable".  Note that "protection" is really a
index 3ba1a061e4aed516b6eef4452af84b1c5f444db6..a3914352c995e83222080a9d7151a9567256196c 100644 (file)
@@ -46,7 +46,7 @@ ia64_get_lid (void)
 #define SMP_IRQ_REDIRECTION    (1 << 0)
 #define SMP_IPI_REDIRECTION    (1 << 1)
 
-#define smp_processor_id()     (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern struct smp_boot_data {
        int cpu_count;
diff --git a/include/asm-ia64/sn/mspec.h b/include/asm-ia64/sn/mspec.h
new file mode 100644 (file)
index 0000000..dbe13c6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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) 2001-2004 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+#ifndef _ASM_IA64_SN_MSPEC_H
+#define _ASM_IA64_SN_MSPEC_H
+
+#define FETCHOP_VAR_SIZE 64 /* 64 byte per fetchop variable */
+
+#define FETCHOP_LOAD           0
+#define FETCHOP_INCREMENT      8
+#define FETCHOP_DECREMENT      16
+#define FETCHOP_CLEAR          24
+
+#define FETCHOP_STORE          0
+#define FETCHOP_AND            24
+#define FETCHOP_OR             32
+
+#define FETCHOP_CLEAR_CACHE    56
+
+#define FETCHOP_LOAD_OP(addr, op) ( \
+         *(volatile long *)((char*) (addr) + (op)))
+
+#define FETCHOP_STORE_OP(addr, op, x) ( \
+         *(volatile long *)((char*) (addr) + (op)) = (long) (x))
+
+#ifdef __KERNEL__
+
+/*
+ * Each Atomic Memory Operation (AMO formerly known as fetchop)
+ * variable is 64 bytes long.  The first 8 bytes are used.  The
+ * remaining 56 bytes are unaddressable due to the operation taking
+ * that portion of the address.
+ *
+ * NOTE: The AMO_t _MUST_ be placed in either the first or second half
+ * of the cache line.  The cache line _MUST NOT_ be used for anything
+ * other than additional AMO_t entries.  This is because there are two
+ * addresses which reference the same physical cache line.  One will
+ * be a cached entry with the memory type bits all set.  This address
+ * may be loaded into processor cache.  The AMO_t will be referenced
+ * uncached via the memory special memory type.  If any portion of the
+ * cached cache-line is modified, when that line is flushed, it will
+ * overwrite the uncached value in physical memory and lead to
+ * inconsistency.
+ */
+typedef struct {
+        u64 variable;
+        u64 unused[7];
+} AMO_t;
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IA64_SN_MSPEC_H */
diff --git a/include/asm-ia64/uncached.h b/include/asm-ia64/uncached.h
new file mode 100644 (file)
index 0000000..b82d923
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2001-2005 Silicon Graphics, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * Prototypes for the uncached page allocator
+ */
+
+extern unsigned long uncached_alloc_page(int nid);
+extern void uncached_free_page(unsigned long);
index 33e26c557c5c6b59206ae2237d31d1c37fe37260..f7f43ec2483a604640e965a7feb39df031fe65e5 100644 (file)
 #define __NR_add_key                   1271
 #define __NR_request_key               1272
 #define __NR_keyctl                    1273
+#define __NR_set_zone_reclaim          1276
 
 #ifdef __KERNEL__
 
index 417a51bd552de78b0c4a26c0239626f250daff68..6cd978cefb2850be383e462f77a05c23ff7adc33 100644 (file)
@@ -1,38 +1 @@
-#ifndef _ASM_M32R_DIV64
-#define _ASM_M32R_DIV64
-
-/* $Id$ */
-
-/* unsigned long long division.
- * Input:
- *  unsigned long long  n
- *  unsigned long  base
- * Output:
- *  n = n / base;
- *  return value = n % base;
- */
-#define do_div(n, base)                                                \
-({                                                             \
-       unsigned long _res, _high, _mid, _low;                  \
-                                                               \
-       _low = (n) & 0xffffffffUL;                              \
-       _high = (n) >> 32;                                      \
-       if (_high) {                                            \
-               _mid = (_high % (unsigned long)(base)) << 16;   \
-               _high = _high / (unsigned long)(base);          \
-               _mid += _low >> 16;                             \
-               _low &= 0x0000ffffUL;                           \
-               _low += (_mid % (unsigned long)(base)) << 16;   \
-               _mid = _mid / (unsigned long)(base);            \
-               _res = _low % (unsigned long)(base);            \
-               _low = _low / (unsigned long)(base);            \
-               n = _low + ((long long)_mid << 16) +            \
-                       ((long long)_high << 32);               \
-       } else {                                                \
-               _res = _low % (unsigned long)(base);            \
-               n = (_low / (unsigned long)(base));             \
-       }                                                       \
-       _res;                                                   \
-})
-
-#endif  /* _ASM_M32R_DIV64 */
+#include <asm-generic/div64.h>
index be64f24e37eed06a59dac18c459bf6d2db071e6e..194393bd8beb8f07eee63a375211c34350efc603 100644 (file)
@@ -35,7 +35,7 @@
 static __inline__ int ide_default_irq(unsigned long base)
 {
        switch (base) {
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
                case 0x1f0: return PLD_IRQ_CFIREQ;
                default:
                        return 0;
index b56034026bf80025e31122c6a017f6f15dc94a7d..cb98101f4f6e02177ba546df4850fd5471d33920 100644 (file)
 #define M32R_ICU_CR5_PORTL    (0x210+M32R_ICU_OFFSET)  /* INT4 */
 #define M32R_ICU_CR6_PORTL    (0x214+M32R_ICU_OFFSET)  /* INT5 */
 #define M32R_ICU_CR7_PORTL    (0x218+M32R_ICU_OFFSET)  /* INT6 */
+#define M32R_ICU_CR8_PORTL    (0x219+M32R_ICU_OFFSET)  /* INT7 */
 #define M32R_ICU_CR16_PORTL   (0x23C+M32R_ICU_OFFSET)  /* MFT0 */
 #define M32R_ICU_CR17_PORTL   (0x240+M32R_ICU_OFFSET)  /* MFT1 */
 #define M32R_ICU_CR18_PORTL   (0x244+M32R_ICU_OFFSET)  /* MFT2 */
diff --git a/include/asm-m32r/m32102peri.h b/include/asm-m32r/m32102peri.h
deleted file mode 100644 (file)
index 3c12955..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-/* $Id$
- *
- * 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) 2000,2001 by Hiroyuki Kondo
- */
-
-#ifndef __ASSEMBLY__
-
-typedef        void    V;
-typedef        char    B;
-typedef        short   S;
-typedef        int             W;
-typedef        long    L;
-typedef        float   F;
-typedef        double  D;
-typedef        unsigned char   UB;
-typedef        unsigned short  US;
-typedef        unsigned int    UW;
-typedef        unsigned long   UL;
-typedef        const unsigned int      CUW;
-
-/*********************************
-
-M32102 ICU
-
-*********************************/
-#define                ICUISTS         (UW *)0xa0EFF004
-#define                ICUIREQ0        (UW *)0xa0EFF008
-#define                ICUIREQ1        (UW *)0xa0EFF00C
-
-#define                ICUSBICR        (UW *)0xa0EFF018
-#define                ICUIMASK        (UW *)0xa0EFF01C
-
-#define                ICUCR1          (UW *)0xa0EFF200        /* INT0 */
-#define                ICUCR2          (UW *)0xa0EFF204        /* INT1 */
-#define                ICUCR3          (UW *)0xa0EFF208        /* INT2 */
-#define                ICUCR4          (UW *)0xa0EFF20C        /* INT3 */
-#define                ICUCR5          (UW *)0xa0EFF210        /* INT4 */
-#define                ICUCR6          (UW *)0xa0EFF214        /* INT5 */
-#define                ICUCR7          (UW *)0xa0EFF218        /* INT6 */
-
-#define                ICUCR16         (UW *)0xa0EFF23C        /* MFT0 */
-#define                ICUCR17         (UW *)0xa0EFF240        /* MFT1 */
-#define                ICUCR18         (UW *)0xa0EFF244        /* MFT2 */
-#define                ICUCR19         (UW *)0xa0EFF248        /* MFT3 */
-#define                ICUCR20         (UW *)0xa0EFF24C        /* MFT4 */
-#define                ICUCR21         (UW *)0xa0EFF250        /* MFT5 */
-
-#define                ICUCR32         (UW *)0xa0EFF27C        /* DMA0 */
-#define                ICUCR33         (UW *)0xa0EFF280        /* DMA1 */
-
-#define                ICUCR48         (UW *)0xa0EFF2BC        /* SIO0R */
-#define                ICUCR49         (UW *)0xa0EFF2C0        /* SIO0S */
-#define                ICUCR50         (UW *)0xa0EFF2C4        /* SIO1R */
-#define                ICUCR51         (UW *)0xa0EFF2C8        /* SIO1S */
-#define                ICUCR52         (UW *)0xa0EFF2CC        /* SIO2R */
-#define                ICUCR53         (UW *)0xa0EFF2D0        /* SIO2S */
-#define                ICUCR54         (UW *)0xa0EFF2D4        /* SIO3R */
-#define                ICUCR55         (UW *)0xa0EFF2D8        /* SIO3S */
-#define                ICUCR56         (UW *)0xa0EFF2DC        /* SIO4R */
-#define                ICUCR57         (UW *)0xa0EFF2E0        /* SIO4S */
-
-/*********************************
-
-M32102 MFT
-
-*********************************/
-#define                MFTCR           (US *)0xa0EFC002
-#define                MFTRPR          (UB *)0xa0EFC006
-
-#define                MFT0MOD         (US *)0xa0EFC102
-#define                MFT0BOS         (US *)0xa0EFC106
-#define                MFT0CUT         (US *)0xa0EFC10A
-#define                MFT0RLD         (US *)0xa0EFC10E
-#define                MFT0CRLD        (US *)0xa0EFC112
-
-#define                MFT1MOD         (US *)0xa0EFC202
-#define                MFT1BOS         (US *)0xa0EFC206
-#define                MFT1CUT         (US *)0xa0EFC20A
-#define                MFT1RLD         (US *)0xa0EFC20E
-#define                MFT1CRLD        (US *)0xa0EFC212
-
-#define                MFT2MOD         (US *)0xa0EFC302
-#define                MFT2BOS         (US *)0xa0EFC306
-#define                MFT2CUT         (US *)0xa0EFC30A
-#define                MFT2RLD         (US *)0xa0EFC30E
-#define                MFT2CRLD        (US *)0xa0EFC312
-
-#define                MFT3MOD         (US *)0xa0EFC402
-#define                MFT3CUT         (US *)0xa0EFC40A
-#define                MFT3RLD         (US *)0xa0EFC40E
-#define                MFT3CRLD        (US *)0xa0EFC412
-
-#define                MFT4MOD         (US *)0xa0EFC502
-#define                MFT4CUT         (US *)0xa0EFC50A
-#define                MFT4RLD         (US *)0xa0EFC50E
-#define                MFT4CRLD        (US *)0xa0EFC512
-
-#define                MFT5MOD         (US *)0xa0EFC602
-#define                MFT5CUT         (US *)0xa0EFC60A
-#define                MFT5RLD         (US *)0xa0EFC60E
-#define                MFT5CRLD        (US *)0xa0EFC612
-
-/*********************************
-
-M32102 SIO
-
-*********************************/
-
-#define SIO0CR     (volatile int *)0xa0efd000
-#define SIO0MOD0   (volatile int *)0xa0efd004
-#define SIO0MOD1   (volatile int *)0xa0efd008
-#define SIO0STS    (volatile int *)0xa0efd00c
-#define SIO0IMASK  (volatile int *)0xa0efd010
-#define SIO0BAUR   (volatile int *)0xa0efd014
-#define SIO0RBAUR  (volatile int *)0xa0efd018
-#define SIO0TXB    (volatile int *)0xa0efd01c
-#define SIO0RXB    (volatile int *)0xa0efd020
-
-#define SIO1CR     (volatile int *)0xa0efd100
-#define SIO1MOD0   (volatile int *)0xa0efd104
-#define SIO1MOD1   (volatile int *)0xa0efd108
-#define SIO1STS    (volatile int *)0xa0efd10c
-#define SIO1IMASK  (volatile int *)0xa0efd110
-#define SIO1BAUR   (volatile int *)0xa0efd114
-#define SIO1RBAUR  (volatile int *)0xa0efd118
-#define SIO1TXB    (volatile int *)0xa0efd11c
-#define SIO1RXB    (volatile int *)0xa0efd120
-/*********************************
-
-M32102 PORT
-
-*********************************/
-#define                PIEN            (UB *)0xa0EF1003        /* input enable */
-
-#define                P0DATA          (UB *)0xa0EF1020        /* data */
-#define                P1DATA          (UB *)0xa0EF1021
-#define                P2DATA          (UB *)0xa0EF1022
-#define                P3DATA          (UB *)0xa0EF1023
-#define                P4DATA          (UB *)0xa0EF1024
-#define                P5DATA          (UB *)0xa0EF1025
-#define                P6DATA          (UB *)0xa0EF1026
-#define                P7DATA          (UB *)0xa0EF1027
-
-#define                P0DIR           (UB *)0xa0EF1040        /* direction */
-#define                P1DIR           (UB *)0xa0EF1041
-#define                P2DIR           (UB *)0xa0EF1042
-#define                P3DIR           (UB *)0xa0EF1043
-#define                P4DIR           (UB *)0xa0EF1044
-#define                P5DIR           (UB *)0xa0EF1045
-#define                P6DIR           (UB *)0xa0EF1046
-#define                P7DIR           (UB *)0xa0EF1047
-
-#define                P0MOD           (US *)0xa0EF1060        /* mode control */
-#define                P1MOD           (US *)0xa0EF1062
-#define                P2MOD           (US *)0xa0EF1064
-#define                P3MOD           (US *)0xa0EF1066
-#define                P4MOD           (US *)0xa0EF1068
-#define                P5MOD           (US *)0xa0EF106A
-#define                P6MOD           (US *)0xa0EF106C
-#define                P7MOD           (US *)0xa0EF106E
-
-#define                P0ODCR          (UB *)0xa0EF1080        /* open-drain control */
-#define                P1ODCR          (UB *)0xa0EF1081
-#define                P2ODCR          (UB *)0xa0EF1082
-#define                P3ODCR          (UB *)0xa0EF1083
-#define                P4ODCR          (UB *)0xa0EF1084
-#define                P5ODCR          (UB *)0xa0EF1085
-#define                P6ODCR          (UB *)0xa0EF1086
-#define                P7ODCR          (UB *)0xa0EF1087
-
-/*********************************
-
-M32102 Cache
-
-********************************/
-
-#define                MCCR    (US *)0xFFFFFFFE
-
-
-#else  /* __ASSEMBLY__ */
-
-;;
-;; PIO     0x80ef1000
-;;
-
-#define PIEN          0xa0ef1000
-
-#define P0DATA        0xa0ef1020
-#define P1DATA        0xa0ef1021
-#define P2DATA        0xa0ef1022
-#define P3DATA        0xa0ef1023
-#define P4DATA        0xa0ef1024
-#define P5DATA        0xa0ef1025
-#define P6DATA        0xa0ef1026
-#define P7DATA        0xa0ef1027
-
-#define P0DIR         0xa0ef1040
-#define P1DIR         0xa0ef1041
-#define P2DIR         0xa0ef1042
-#define P3DIR         0xa0ef1043
-#define P4DIR         0xa0ef1044
-#define P5DIR         0xa0ef1045
-#define P6DIR         0xa0ef1046
-#define P7DIR         0xa0ef1047
-
-#define P0MOD         0xa0ef1060
-#define P1MOD         0xa0ef1062
-#define P2MOD         0xa0ef1064
-#define P3MOD         0xa0ef1066
-#define P4MOD         0xa0ef1068
-#define P5MOD         0xa0ef106a
-#define P6MOD         0xa0ef106c
-#define P7MOD         0xa0ef106e
-;
-#define P0ODCR        0xa0ef1080
-#define P1ODCR        0xa0ef1081
-#define P2ODCR        0xa0ef1082
-#define P3ODCR        0xa0ef1083
-#define P4ODCR        0xa0ef1084
-#define P5ODCR        0xa0ef1085
-#define P6ODCR        0xa0ef1086
-#define P7ODCR        0xa0ef1087
-
-;;
-;; WDT     0xa0ef2000
-;;
-
-#define WDTCR         0xa0ef2000
-
-
-;;
-;; CLK     0xa0ef4000
-;;
-
-#define CPUCLKCR      0xa0ef4000
-#define CLKMOD        0xa0ef4004
-#define PLLCR         0xa0ef4008
-
-
-;;
-;; BSEL    0xa0ef5000
-;;
-
-#define BSEL0CR       0xa0ef5000
-#define BSEL1CR       0xa0ef5004
-#define BSEL2CR       0xa0ef5008
-#define BSEL3CR       0xa0ef500c
-#define BSEL4CR       0xa0ef5010
-#define BSEL5CR       0xa0ef5014
-
-
-;;
-;; SDRAMC  0xa0ef6000
-;;
-
-#define SDRF0         0xa0ef6000
-#define SDRF1         0xa0ef6004
-#define SDIR0         0xa0ef6008
-#define SDIR1         0xa0ef600c
-#define SDBR          0xa0ef6010
-
-;; CH0
-#define SD0ADR        0xa0ef6020
-#define SD0SZ         0xa0ef6022
-#define SD0ER         0xa0ef6024
-#define SD0TR         0xa0ef6028
-#define SD0MOD        0xa0ef602c
-
-;; CH1
-#define SD1ADR        0xa0ef6040
-#define SD1SZ         0xa0ef6042
-#define SD1ER         0xa0ef6044
-#define SD1TR         0xa0ef6048
-#define SD1MOD        0xa0ef604c
-
-
-;;
-;; DMAC    0xa0ef8000
-;;
-
-#define DMAEN         0xa0ef8000
-#define DMAISTS       0xa0ef8004
-#define DMAEDET       0xa0ef8008
-#define DMAASTS       0xa0ef800c
-
-;; CH0
-#define DMA0CR0       0xa0ef8100
-#define DMA0CR1       0xa0ef8104
-#define DMA0CSA       0xa0ef8108
-#define DMA0RSA       0xa0ef810c
-#define DMA0CDA       0xa0ef8110
-#define DMA0RDA       0xa0ef8114
-#define DMA0CBCUT     0xa0ef8118
-#define DMA0RBCUT     0xa0ef811c
-
-;; CH1
-#define DMA1CR0       0xa0ef8200
-#define DMA1CR1       0xa0ef8204
-#define DMA1CSA       0xa0ef8208
-#define DMA1RSA       0xa0ef820c
-#define DMA1CDA       0xa0ef8210
-#define DMA1RDA       0xa0ef8214
-#define DMA1CBCUT     0xa0ef8218
-#define DMA1RBCUT     0xa0ef821c
-
-
-;;
-;; MFT     0xa0efc000
-;;
-
-#define MFTCR        0xa0efc000
-#define MFTRPR       0xa0efc004
-
-;; CH0
-#define MFT0MOD      0xa0efc100
-#define MFT0BOS      0xa0efc104
-#define MFT0CUT      0xa0efc108
-#define MFT0RLD      0xa0efc10c
-#define MFT0CMPRLD   0xa0efc110
-
-;; CH1
-#define MFT1MOD      0xa0efc200
-#define MFT1BOS      0xa0efc204
-#define MFT1CUT      0xa0efc208
-#define MFT1RLD      0xa0efc20c
-#define MFT1CMPRLD   0xa0efc210
-
-;; CH2
-#define MFT2MOD      0xa0efc300
-#define MFT2BOS      0xa0efc304
-#define MFT2CUT      0xa0efc308
-#define MFT2RLD      0xa0efc30c
-#define MFT2CMPRLD   0xa0efc310
-
-;; CH3
-#define MFT3MOD      0xa0efc400
-#define MFT3BOS      0xa0efc404
-#define MFT3CUT      0xa0efc408
-#define MFT3RLD      0xa0efc40c
-#define MFT3CMPRLD   0xa0efc410
-
-;; CH4
-#define MFT4MOD      0xa0efc500
-#define MFT4BOS      0xa0efc504
-#define MFT4CUT      0xa0efc508
-#define MFT4RLD      0xa0efc50c
-#define MFT4CMPRLD   0xa0efc510
-
-;; CH5
-#define MFT5MOD      0xa0efc600
-#define MFT5BOS      0xa0efc604
-#define MFT5CUT      0xa0efc608
-#define MFT5RLD      0xa0efc60c
-#define MFT5CMPRLD   0xa0efc610
-
-
-;;
-;; SIO     0xa0efd000
-;;
-
-;; CH0
-#define SIO0CR        0xa0efd000
-#define SIO0MOD0      0xa0efd004
-#define SIO0MOD1      0xa0efd008
-#define SIO0STS       0xa0efd00c
-#define SIO0IMASK     0xa0efd010
-#define SIO0BAUR      0xa0efd014
-#define SIO0RBAUR     0xa0efd018
-#define SIO0TXB       0xa0efd01c
-#define SIO0RXB       0xa0efd020
-
-;; CH1
-#define SIO1CR        0xa0efd100
-#define SIO1MOD0      0xa0efd104
-#define SIO1MOD1      0xa0efd108
-#define SIO1STS       0xa0efd10c
-#define SIO1IMASK     0xa0efd110
-#define SIO1BAUR      0xa0efd114
-#define SIO1RBAUR     0xa0efd118
-#define SIO1TXB       0xa0efd11c
-#define SIO1RXB       0xa0efd120
-
-;; CH2
-#define SIO2CR        0xa0efd200
-#define SIO2MOD0      0xa0efd204
-#define SIO2MOD1      0xa0efd208
-#define SIO2STS       0xa0efd20c
-#define SIO2IMASK     0xa0efd210
-#define SIO2BAUR      0xa0efd214
-#define SIO2RBAUR     0xa0efd218
-#define SIO2TXB       0xa0efd21c
-#define SIO2RXB       0xa0efd220
-
-;; CH3
-#define SIO3CR        0xa0efd300
-#define SIO3MOD0      0xa0efd304
-#define SIO3MOD1      0xa0efd308
-#define SIO3STS       0xa0efd30c
-#define SIO3IMASK     0xa0efd310
-#define SIO3BAUR      0xa0efd314
-#define SIO3RBAUR     0xa0efd318
-#define SIO3TXB       0xa0efd31c
-#define SIO3RXB       0xa0efd320
-
-;; CH4
-#define SIO4CR        0xa0efd400
-#define SIO4MOD0      0xa0efd404
-#define SIO4MOD1      0xa0efd408
-#define SIO4STS       0xa0efd40c
-#define SIO4IMASK     0xa0efd410
-#define SIO4BAUR      0xa0efd414
-#define SIO4RBAUR     0xa0efd418
-#define SIO4TXB       0xa0efd41c
-#define SIO4RXB       0xa0efd420
-
-
-;;
-;; ICU     0xa0eff000
-;;
-
-#define ICUISTS       0xa0eff004
-#define ICUIREQ0      0xa0eff008
-#define ICUIREQ1      0xa0eff00c
-
-#define ICUSBICR      0xa0eff018
-#define ICUIMASK      0xa0eff01c
-
-#define ICUCR1        0xa0eff200
-#define ICUCR2        0xa0eff204
-#define ICUCR3        0xa0eff208
-#define ICUCR4        0xa0eff20c
-#define ICUCR5        0xa0eff210
-#define ICUCR6        0xa0eff214
-#define ICUCR7        0xa0eff218
-
-#define ICUCR16       0xa0eff23c
-#define ICUCR17       0xa0eff240
-#define ICUCR18       0xa0eff244
-#define ICUCR19       0xa0eff248
-#define ICUCR20       0xa0eff24c
-#define ICUCR21       0xa0eff250
-
-#define ICUCR32       0xa0eff27c
-#define ICUCR33       0xa0eff280
-
-#define ICUCR48       0xa0eff2bc
-#define ICUCR49       0xa0eff2c0
-#define ICUCR50       0xa0eff2c4
-#define ICUCR51       0xa0eff2c8
-#define ICUCR52       0xa0eff2cc
-#define ICUCR53       0xa0eff2d0
-#define ICUCR54       0xa0eff2d4
-#define ICUCR55       0xa0eff2d8
-#define ICUCR56       0xa0eff2dc
-#define ICUCR57       0xa0eff2e0
-
-;;
-;; CACHE
-;;
-
-#define MCCR             0xfffffffc
-
-
-#endif  /* __ASSEMBLY__ */
index f116649bbef375d82b8c54e4f5c741220b31e8d1..ec142be008621338bc1ddf4ae0132e927c78e105 100644 (file)
@@ -16,7 +16,6 @@
        || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
         || defined(CONFIG_CHIP_OPSP)
 #include <asm/m32102.h>
-#include <asm/m32102peri.h>
 #endif
 
 /* Platform type */
 #include <asm/mappi2/mappi2_pld.h>
 #endif /* CONFIG_PLAT_MAPPI2 */
 
+#if defined(CONFIG_PLAT_MAPPI3)
+#include <asm/mappi3/mappi3_pld.h>
+#endif /* CONFIG_PLAT_MAPPI3 */
+
 #if defined(CONFIG_PLAT_USRV)
 #include <asm/m32700ut/m32700ut_pld.h>
 #endif
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/include/asm-m32r/mappi3/mappi3_pld.h
new file mode 100644 (file)
index 0000000..3f1551f
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * include/asm/mappi3/mappi3_pld.h
+ *
+ * Definitions for Extended IO Logic on MAPPI3 board.
+ *  based on m32700ut_pld.h
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MAPPI3_PLD_H
+#define _MAPPI3_PLD_H
+
+#ifndef __ASSEMBLY__
+/* FIXME:
+ * Some C functions use non-cache address, so can't define non-cache address.
+ */
+#define PLD_BASE               (0x1c000000 /* + NONCACHE_OFFSET */)
+#define __reg8                 (volatile unsigned char *)
+#define __reg16                        (volatile unsigned short *)
+#define __reg32                        (volatile unsigned int *)
+#else
+#define PLD_BASE               (0x1c000000 + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif /* __ASSEMBLY__ */
+
+/* CFC */
+#define        PLD_CFRSTCR             __reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS              __reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK            __reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR            __reg16(PLD_BASE + 0x0006)
+#define PLD_CFCR0              __reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1              __reg16(PLD_BASE + 0x000c)
+
+/* MMC */
+#define PLD_MMCCR              __reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD             __reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS             __reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR            __reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT         __reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT         __reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET             __reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP              __reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA           __reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA           __reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA         __reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA         __reg16(PLD_BASE + 0x7006)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR               __reg16(PLD_BASE + 0x14000)
+
+
+/*==== ICU ====*/
+#define  M32R_IRQ_PC104        (5)   /* INT4(PC/104) */
+#define  M32R_IRQ_I2C          (28)  /* I2C-BUS     */
+#define  PLD_IRQ_CFIREQ       (6)  /* INT5 CFC Card Interrupt */
+#define  PLD_IRQ_CFC_INSERT   (7)  /* INT6 CFC Card Insert */
+#define  PLD_IRQ_CFC_EJECT    (8)  /* INT7 CFC Card Eject */
+#define  PLD_IRQ_MMCCARD      (43)  /* MMC Card Insert */
+#define  PLD_IRQ_MMCIRQ       (44)  /* MMC Transfer Done */
+
+
+#if 0
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR            __reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON         0x001
+#define PLD_IOLED_1_OFF                0x000
+#define PLD_IOLED_2_ON         0x002
+#define PLD_IOLED_2_OFF                0x000
+
+/* DIP Switch
+ *  0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ *  1: -
+ *  2: -
+ *  3: -
+ */
+#define PLD_IOSWSTS            __reg16(PLD_BASE + 0x14004)
+#define        PLD_IOSWSTS_IOSW2       0x0200
+#define        PLD_IOSWSTS_IOSW1       0x0100
+#define        PLD_IOSWSTS_IOWP0       0x0001
+
+#endif
+
+/* CRC */
+#define PLD_CRC7DATA           __reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA         __reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA          __reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA                __reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA         __reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA       __reg16(PLD_BASE + 0x1800a)
+
+
+#if 0
+/* RTC */
+#define PLD_RTCCR              __reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR            __reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA          __reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA          __reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT          __reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR            __reg16(PLD_BASE + 0x20000)
+#define        PLD_ESIO0CR_TXEN        0x0001
+#define        PLD_ESIO0CR_RXEN        0x0002
+#define PLD_ESIO0MOD0          __reg16(PLD_BASE + 0x20002)
+#define        PLD_ESIO0MOD0_CTSS      0x0040
+#define        PLD_ESIO0MOD0_RTSS      0x0080
+#define PLD_ESIO0MOD1          __reg16(PLD_BASE + 0x20004)
+#define        PLD_ESIO0MOD1_LMFS      0x0010
+#define PLD_ESIO0STS           __reg16(PLD_BASE + 0x20006)
+#define        PLD_ESIO0STS_TEMP       0x0001
+#define        PLD_ESIO0STS_TXCP       0x0002
+#define        PLD_ESIO0STS_RXCP       0x0004
+#define        PLD_ESIO0STS_TXSC       0x0100
+#define        PLD_ESIO0STS_RXSC       0x0200
+#define PLD_ESIO0STS_TXREADY   (PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR         __reg16(PLD_BASE + 0x20008)
+#define        PLD_ESIO0INTCR_TXIEN    0x0002
+#define        PLD_ESIO0INTCR_RXCEN    0x0004
+#define PLD_ESIO0BAUR          __reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB           __reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB           __reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR               __reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD              __reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS              __reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR            __reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR             __reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB              __reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB              __reg16(PLD_BASE + 0x3800e)
+
+#endif
+
+#endif /* _MAPPI3_PLD.H */
index 8cd4d0da4be19ec366dccef697a3dc6bc5f15c16..b9a20cdad65f4a7c4208e6407b1bc2fdd7218f0d 100644 (file)
@@ -66,7 +66,7 @@ extern volatile int cpu_2_physid[NR_CPUS];
 #define physid_to_cpu(physid)  physid_2_cpu[physid]
 #define cpu_to_physid(cpu_id)  cpu_2_physid[cpu_id]
 
-#define smp_processor_id()     (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern cpumask_t cpu_callout_map;
 #define cpu_possible_map cpu_callout_map
index 8ba370ecfd4cc26b9138da3bf2fce8ca759fa4fa..5618f1e12f404d6d6d93671a471c69ef46619530 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/cpumask.h>
 #include <asm/atomic.h>
 
-#define smp_processor_id()     (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 /* Map from cpu id to sequential logical cpu number.  This will only
    not be idempotent when cpus failed to come on-line.  */
diff --git a/include/asm-mips/vr41xx/giu.h b/include/asm-mips/vr41xx/giu.h
new file mode 100644 (file)
index 0000000..8590885
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *  Include file for NEC VR4100 series General-purpose I/O Unit.
+ *
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  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 __NEC_VR41XX_GIU_H
+#define __NEC_VR41XX_GIU_H
+
+typedef enum {
+       IRQ_TRIGGER_LEVEL,
+       IRQ_TRIGGER_EDGE,
+       IRQ_TRIGGER_EDGE_FALLING,
+       IRQ_TRIGGER_EDGE_RISING,
+} irq_trigger_t;
+
+typedef enum {
+       IRQ_SIGNAL_THROUGH,
+       IRQ_SIGNAL_HOLD,
+} irq_signal_t;
+
+extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal);
+
+typedef enum {
+       IRQ_LEVEL_LOW,
+       IRQ_LEVEL_HIGH,
+} irq_level_t;
+
+extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level);
+
+typedef enum {
+       GPIO_DATA_LOW,
+       GPIO_DATA_HIGH,
+       GPIO_DATA_INVAL,
+} gpio_data_t;
+
+extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin);
+extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data);
+
+typedef enum {
+       GPIO_INPUT,
+       GPIO_OUTPUT,
+       GPIO_OUTPUT_DISABLE,
+} gpio_direction_t;
+
+extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir);
+
+typedef enum {
+       GPIO_PULL_DOWN,
+       GPIO_PULL_UP,
+       GPIO_PULL_DISABLE,
+} gpio_pull_t;
+
+extern int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull);
+
+#endif /* __NEC_VR41XX_GIU_H */
index ad0d1ea144f01eb2214296f87c4fc405eebb2bd4..7d41e44463f954ee6edcbf93a88efe8d33684d7d 100644 (file)
@@ -126,7 +126,6 @@ extern void vr41xx_mask_clock(vr41xx_clock_t clock);
 #define GIU_IRQ_BASE           40
 #define GIU_IRQ(x)             (GIU_IRQ_BASE + (x))    /* IRQ 40-71 */
 #define GIU_IRQ_LAST           GIU_IRQ(31)
-#define GIU_IRQ_TO_PIN(x)      ((x) - GIU_IRQ_BASE)    /* Pin 0-31 */
 
 extern int vr41xx_set_intassign(unsigned int irq, unsigned char intassign);
 extern int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq));
@@ -197,38 +196,4 @@ extern void vr41xx_disable_csiint(uint16_t mask);
 extern void vr41xx_enable_bcuint(void);
 extern void vr41xx_disable_bcuint(void);
 
-/*
- * General-Purpose I/O Unit
- */
-enum {
-       TRIGGER_LEVEL,
-       TRIGGER_EDGE,
-       TRIGGER_EDGE_FALLING,
-       TRIGGER_EDGE_RISING
-};
-
-enum {
-       SIGNAL_THROUGH,
-       SIGNAL_HOLD
-};
-
-extern void vr41xx_set_irq_trigger(int pin, int trigger, int hold);
-
-enum {
-       LEVEL_LOW,
-       LEVEL_HIGH
-};
-
-extern void vr41xx_set_irq_level(int pin, int level);
-
-enum {
-       PIO_INPUT,
-       PIO_OUTPUT
-};
-
-enum {
-       DATA_LOW,
-       DATA_HIGH
-};
-
 #endif /* __NEC_VR41XX_H */
index fde77ac35463b1610c7c085d57b3ca9bd55f0fc6..9413f67a540bb24ae2b2d2866a48c3fc8dc1a37a 100644 (file)
@@ -51,7 +51,7 @@ extern void smp_send_reschedule(int cpu);
 
 extern unsigned long cpu_present_mask;
 
-#define smp_processor_id()     (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 #endif /* CONFIG_SMP */
 
index 06b86be61ed13e32851b60a66ebefd39386a5166..a9b33324f56299dfb49704ec5789e2cfd29df686 100644 (file)
@@ -176,7 +176,7 @@ static __inline__ int irq_canonicalize(int irq)
 */
 #include <asm/mpc85xx.h>
 
-/* The MPC8560 openpic has  32 internal interrupts and 12 external
+/* The MPC8548 openpic has 48 internal interrupts and 12 external
  * interrupts.
  *
  * We are "flattening" the interrupt vectors of the cascaded CPM
@@ -184,7 +184,7 @@ static __inline__ int irq_canonicalize(int irq)
  * single integer.
  */
 #define NR_CPM_INTS    64
-#define NR_EPIC_INTS   44
+#define NR_EPIC_INTS   60
 #ifndef NR_8259_INTS
 #define NR_8259_INTS   0
 #endif
@@ -223,9 +223,15 @@ static __inline__ int irq_canonicalize(int irq)
 #define MPC85xx_IRQ_RIO_RX     (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC1_TX   (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC1_RX   (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_TX   (15 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_RX   (16 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_ERROR        (17 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC1_ERROR        (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC2_TX   (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC2_RX   (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_TX   (21 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_RX   (22 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_ERROR        (23 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC2_ERROR        (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_FEC                (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_DUART      (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
@@ -235,18 +241,18 @@ static __inline__ int irq_canonicalize(int irq)
 #define MPC85xx_IRQ_CPM                (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
 
 /* The 12 external interrupt lines */
-#define MPC85xx_IRQ_EXT0        (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT1        (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT2        (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT3        (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT4        (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT5        (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT6        (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT7        (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT8        (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT9        (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT10       (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT11       (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT0        (48 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT1        (49 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT2        (50 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT3        (51 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT4        (52 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT5        (53 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT6        (54 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT7        (55 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT8        (56 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT9        (57 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT10       (58 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT11       (59 + MPC85xx_OPENPIC_IRQ_OFFSET)
 
 /* CPM related interrupts */
 #define        SIU_INT_ERROR           ((uint)0x00+CPM_IRQ_OFFSET)
index d8e7e2d6128e70f5f170f58188da06966485af50..f5196a4efbe0ff43e4e16c54780b126808887efe 100644 (file)
@@ -159,6 +159,12 @@ extern unsigned long                       ioremap_base;
 #define        MPC10X_MAPA_EUMB_BASE           (ioremap_base - MPC10X_EUMB_SIZE)
 #define        MPC10X_MAPB_EUMB_BASE           MPC10X_MAPA_EUMB_BASE
 
+enum ppc_sys_devices {
+       MPC10X_IIC1,
+       MPC10X_DMA0,
+       MPC10X_DMA1,
+       MPC10X_DUART,
+};
 
 int mpc10x_bridge_init(struct pci_controller *hose,
                       uint current_map,
index 22713e331585a7e9c0360ca4691674221a817261..516984ee14b58782f98fb6168e7cea4c3c44e00f 100644 (file)
@@ -25,7 +25,7 @@
 #ifdef CONFIG_MPC8540_ADS
 #include <platforms/85xx/mpc8540_ads.h>
 #endif
-#ifdef CONFIG_MPC8555_CDS
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
 #include <platforms/85xx/mpc8555_cds.h>
 #endif
 #ifdef CONFIG_MPC8560_ADS
@@ -74,7 +74,7 @@ extern unsigned char __res[];
 #define MPC85xx_GUTS_OFFSET    (0xe0000)
 #define MPC85xx_GUTS_SIZE      (0x01000)
 #define MPC85xx_IIC1_OFFSET    (0x03000)
-#define MPC85xx_IIC1_SIZE      (0x01000)
+#define MPC85xx_IIC1_SIZE      (0x00100)
 #define MPC85xx_OPENPIC_OFFSET (0x40000)
 #define MPC85xx_OPENPIC_SIZE   (0x40000)
 #define MPC85xx_PCI1_OFFSET    (0x08000)
@@ -127,8 +127,64 @@ enum ppc_sys_devices {
        MPC85xx_CPM_MCC2,
        MPC85xx_CPM_SMC1,
        MPC85xx_CPM_SMC2,
+       MPC85xx_eTSEC1,
+       MPC85xx_eTSEC2,
+       MPC85xx_eTSEC3,
+       MPC85xx_eTSEC4,
+       MPC85xx_IIC2,
 };
 
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+#define MPC85XX_INTERNAL_IRQ_SENSES \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  0 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  1 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  2 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  3 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  4 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  5 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  6 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  7 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  8 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal  9 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 10 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 11 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 12 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 13 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 14 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 15 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 16 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 17 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 18 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 19 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 20 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 21 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 22 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 23 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 24 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 25 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 26 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 27 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 28 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 29 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 30 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 31 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 32 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 33 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 34 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 35 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 36 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 37 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 38 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 39 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 40 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 41 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 42 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 43 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 44 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 45 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* Internal 46 */       \
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE)       /* Internal 47 */
+
 #endif /* CONFIG_85xx */
 #endif /* __ASM_MPC85xx_H__ */
 #endif /* __KERNEL__ */
index a38606d15549ac326babf08d583972a4be973d07..4d4b20c9de78fbf31097ea3cb5e098b352cf73f7 100644 (file)
@@ -267,8 +267,6 @@ extern unsigned long ioremap_bot, ioremap_base;
 #define _PMD_PRESENT_MASK (PAGE_MASK)
 #define _PMD_BAD       (~PAGE_MASK)
 
-#define NUM_TLBCAMS    (16)
-
 #elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
 #define _PAGE_PRESENT  0x0001  /* Page is valid */
index 24b991c427694d425225c2cacde01b5bc469ed0a..8ea6245662312f644aef30cf26c204e99e4512a2 100644 (file)
@@ -27,6 +27,8 @@
 #include <asm/mpc85xx.h>
 #elif defined(CONFIG_PPC_MPC52xx)
 #include <asm/mpc52xx.h>
+#elif defined(CONFIG_MPC10X_BRIDGE)
+#include <asm/mpc10x.h>
 #else
 #error "need definition of ppc_sys_devices"
 #endif
index ebfb614f55f650707ec092e05a15187d6d0855b4..17530c232c7690c6a47a0b87a0e50ea4e23b8788 100644 (file)
@@ -44,7 +44,7 @@ extern void smp_message_recv(int, struct pt_regs *);
 #define NO_PROC_ID             0xFF            /* No processor magic marker */
 #define PROC_CHANGE_PENALTY    20
 
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern int __cpu_up(unsigned int cpu);
 
index d693b8026bc342052b70dced032ffc2aec944627..dfd1f69059baaeb63cbd90db3798ffd816f199b0 100644 (file)
@@ -27,6 +27,8 @@
 /* Doesn't really apply... */
 #define MAX_DMA_ADDRESS  (~0UL)
 
+#if !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)
+
 #define dma_outb       outb
 #define dma_inb                inb
 
@@ -323,4 +325,5 @@ extern int isa_dma_bridge_buggy;
 #else                                                         
 #define isa_dma_bridge_buggy   (0)
 #endif
+#endif /* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */
 #endif /* _ASM_DMA_H */
index d9a2e74e2399979081790ee5268ced56fa932d74..c3f19475c0d946e8a323826a7759f5f2bf9804da 100644 (file)
@@ -1,84 +1,36 @@
 /*
  * HvCall.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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
  */
-
-//===========================================================================
-//
-//     This file contains the "hypervisor call" interface which is used to
-//     drive the hypervisor from the OS.
-//
-//===========================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
 #ifndef _HVCALL_H
 #define _HVCALL_H
 
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 #include <asm/paca.h>
 
-/*
-enum HvCall_ReturnCode
-{
-       HvCall_Good             = 0,
-       HvCall_Partial          = 1,
-       HvCall_NotOwned         = 2,
-       HvCall_NotFreed         = 3,
-       HvCall_UnspecifiedError = 4
-};
-
-enum HvCall_TypeOfSIT
-{
-       HvCall_ReduceOnly       = 0,
-       HvCall_Unconditional    = 1
-};
-
-enum HvCall_TypeOfYield
-{
-       HvCall_YieldTimed       = 0,    // Yield until specified time
-       HvCall_YieldToActive    = 1,    // Yield until all active procs have run
-       HvCall_YieldToProc      = 2     // Yield until the specified processor has run
-};
-
-enum HvCall_InterruptMasks
-{
-       HvCall_MaskIPI          = 0x00000001,
-       HvCall_MaskLpEvent      = 0x00000002,
-       HvCall_MaskLpProd       = 0x00000004,
-       HvCall_MaskTimeout      = 0x00000008
-};
-
-enum HvCall_VaryOffChunkRc
-{
-       HvCall_VaryOffSucceeded         = 0,
-       HvCall_VaryOffWithdrawn         = 1,
-       HvCall_ChunkInLoadArea          = 2,
-       HvCall_ChunkInHPT               = 3,
-       HvCall_ChunkNotAccessible       = 4,
-       HvCall_ChunkInUse               = 5
-};
-*/
-
 /* Type of yield for HvCallBaseYieldProcessor */
-#define HvCall_YieldTimed      0       // Yield until specified time (tb)
-#define HvCall_YieldToActive   1       // Yield until all active procs have run
-#define HvCall_YieldToProc     2       // Yield until the specified processor has run
+#define HvCall_YieldTimed      0       /* Yield until specified time (tb) */
+#define HvCall_YieldToActive   1       /* Yield until all active procs have run */
+#define HvCall_YieldToProc     2       /* Yield until the specified processor has run */
 
 /* interrupt masks for setEnabledInterrupts */
 #define HvCall_MaskIPI         0x00000001
@@ -86,7 +38,7 @@ enum HvCall_VaryOffChunkRc
 #define HvCall_MaskLpProd      0x00000004
 #define HvCall_MaskTimeout     0x00000008
 
-/* Log buffer formats                       */
+/* Log buffer formats */
 #define HvCall_LogBuffer_ASCII          0
 #define HvCall_LogBuffer_EBCDIC         1
 
@@ -95,7 +47,7 @@ enum HvCall_VaryOffChunkRc
 #define HvCallBaseGetHwPatch                           HvCallBase +  2
 #define HvCallBaseReIplSpAttn                          HvCallBase +  3
 #define HvCallBaseSetASR                               HvCallBase +  4
-#define HvCallBaseSetASRAndRfi                         HvCallBase +  5 
+#define HvCallBaseSetASRAndRfi                         HvCallBase +  5
 #define HvCallBaseSetIMR                               HvCallBase +  6
 #define HvCallBaseSendIPI                              HvCallBase +  7
 #define HvCallBaseTerminateMachine                     HvCallBase +  8
@@ -115,91 +67,47 @@ enum HvCall_VaryOffChunkRc
 #define HvCallBaseGetLogBufferCodePage                 HvCallBase + 22
 #define HvCallBaseGetLogBufferFormat                   HvCallBase + 23
 #define HvCallBaseGetLogBufferLength                   HvCallBase + 24
-#define HvCallBaseReadLogBuffer                        HvCallBase + 25
+#define HvCallBaseReadLogBuffer                                HvCallBase + 25
 #define HvCallBaseSetLogBufferFormatAndCodePage                HvCallBase + 26
-#define HvCallBaseWriteLogBuffer                               HvCallBase + 27
+#define HvCallBaseWriteLogBuffer                       HvCallBase + 27
 #define HvCallBaseRouter28                             HvCallBase + 28
 #define HvCallBaseRouter29                             HvCallBase + 29
 #define HvCallBaseRouter30                             HvCallBase + 30
-#define HvCallBaseSetDebugBus                          HvCallBase + 31
+#define HvCallBaseSetDebugBus                          HvCallBase + 31
 
-#define HvCallCcSetDABR                                HvCallCc + 7
+#define HvCallCcSetDABR                                        HvCallCc + 7
 
-//=====================================================================================
-static inline void             HvCall_setVirtualDecr(void)
+static inline void HvCall_setVirtualDecr(void)
 {
-       /* Ignore any error return codes - most likely means that the target value for the
-        * LP has been increased and this vary off would bring us below the new target. */
+       /*
+        * Ignore any error return codes - most likely means that the
+        * target value for the LP has been increased and this vary off
+        * would bring us below the new target.
+        */
        HvCall0(HvCallBaseSetVirtualDecr);
 }
-//=====================================================================
-static inline void             HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm)
-{
-       HvCall2( HvCallBaseYieldProcessor, typeOfYield, yieldParm );
-}
-//=====================================================================
-static inline void             HvCall_setEnabledInterrupts(u64 enabledInterrupts)
-{
-       HvCall1(HvCallBaseSetEnabledInterrupts,enabledInterrupts);
-}
-
-//=====================================================================
-static inline void             HvCall_clearLogBuffer(HvLpIndex lpindex)
-{
-       HvCall1(HvCallBaseClearLogBuffer,lpindex);
-}
-
-//=====================================================================
-static inline u32              HvCall_getLogBufferCodePage(HvLpIndex lpindex)
-{
-       u32 retVal = HvCall1(HvCallBaseGetLogBufferCodePage,lpindex);
-       return retVal;
-}
-
-//=====================================================================
-static inline int              HvCall_getLogBufferFormat(HvLpIndex lpindex)
-{
-       int retVal = HvCall1(HvCallBaseGetLogBufferFormat,lpindex);
-       return retVal;
-}
-
-//=====================================================================
-static inline u32              HvCall_getLogBufferLength(HvLpIndex lpindex)
-{
-       u32 retVal = HvCall1(HvCallBaseGetLogBufferLength,lpindex);
-       return retVal;
-}
 
-//=====================================================================
-static inline void             HvCall_setLogBufferFormatAndCodepage(int format, u32 codePage)
+static inline void HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm)
 {
-       HvCall2(HvCallBaseSetLogBufferFormatAndCodePage,format, codePage);
+       HvCall2(HvCallBaseYieldProcessor, typeOfYield, yieldParm);
 }
 
-//=====================================================================
-int HvCall_readLogBuffer(HvLpIndex lpindex, void *buffer, u64 bufLen);
-void HvCall_writeLogBuffer(const void *buffer, u64 bufLen);
-
-//=====================================================================
-static inline void             HvCall_sendIPI(struct paca_struct * targetPaca)
+static inline void HvCall_setEnabledInterrupts(u64 enabledInterrupts)
 {
-       HvCall1( HvCallBaseSendIPI, targetPaca->paca_index );
+       HvCall1(HvCallBaseSetEnabledInterrupts, enabledInterrupts);
 }
 
-//=====================================================================
-static inline void             HvCall_terminateMachineSrc(void)
+static inline void HvCall_setLogBufferFormatAndCodepage(int format,
+               u32 codePage)
 {
-       HvCall0( HvCallBaseTerminateMachineSrc );
+       HvCall2(HvCallBaseSetLogBufferFormatAndCodePage, format, codePage);
 }
 
-static inline void HvCall_setDABR(unsigned long val)
-{
-       HvCall1(HvCallCcSetDABR, val);
-}
+extern void HvCall_writeLogBuffer(const void *buffer, u64 bufLen);
 
-static inline void HvCall_setDebugBus(unsigned long val)
+static inline void HvCall_sendIPI(struct paca_struct *targetPaca)
 {
-       HvCall1(HvCallBaseSetDebugBus, val);
+       HvCall1(HvCallBaseSendIPI, targetPaca->paca_index);
 }
 
 #endif /* _HVCALL_H */
diff --git a/include/asm-ppc64/iSeries/HvCallCfg.h b/include/asm-ppc64/iSeries/HvCallCfg.h
deleted file mode 100644 (file)
index 9f40f16..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * HvCallCfg.h
- * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
- * 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
- */
-
-//=====================================================================================
-//
-//     This file contains the "hypervisor call" interface which is used to
-//     drive the hypervisor from the OS.
-//
-//=====================================================================================
-#ifndef _HVCALLCFG_H
-#define _HVCALLCFG_H
-
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
-#include <asm/iSeries/HvCallSc.h>
-#include <asm/iSeries/HvTypes.h>
-
-//-------------------------------------------------------------------------------------
-// Constants
-//-------------------------------------------------------------------------------------
-
-enum HvCallCfg_ReqQual
-{
-       HvCallCfg_Cur   = 0,
-       HvCallCfg_Init  = 1,
-       HvCallCfg_Max   = 2,
-       HvCallCfg_Min   = 3
-};
-
-#define HvCallCfgGetLps                                        HvCallCfg +  0
-#define HvCallCfgGetActiveLpMap                                HvCallCfg +  1
-#define HvCallCfgGetLpVrmIndex                         HvCallCfg +  2
-#define HvCallCfgGetLpMinSupportedPlicVrmIndex         HvCallCfg +  3
-#define HvCallCfgGetLpMinCompatablePlicVrmIndex                HvCallCfg +  4
-#define HvCallCfgGetLpVrmName                          HvCallCfg +  5 
-#define HvCallCfgGetSystemPhysicalProcessors           HvCallCfg +  6
-#define HvCallCfgGetPhysicalProcessors                 HvCallCfg +  7
-#define HvCallCfgGetSystemMsChunks                     HvCallCfg +  8
-#define HvCallCfgGetMsChunks                           HvCallCfg +  9
-#define HvCallCfgGetInteractivePercentage              HvCallCfg + 10
-#define HvCallCfgIsBusDedicated                                HvCallCfg + 11
-#define HvCallCfgGetBusOwner                           HvCallCfg + 12
-#define HvCallCfgGetBusAllocation                      HvCallCfg + 13
-#define HvCallCfgGetBusUnitOwner                       HvCallCfg + 14
-#define HvCallCfgGetBusUnitAllocation                  HvCallCfg + 15
-#define HvCallCfgGetVirtualBusPool                     HvCallCfg + 16
-#define HvCallCfgGetBusUnitInterruptProc               HvCallCfg + 17
-#define HvCallCfgGetConfiguredBusUnitsForIntProc       HvCallCfg + 18
-#define HvCallCfgGetRioSanBusPool                      HvCallCfg + 19
-#define HvCallCfgGetSharedPoolIndex                    HvCallCfg + 20
-#define HvCallCfgGetSharedProcUnits                    HvCallCfg + 21
-#define HvCallCfgGetNumProcsInSharedPool               HvCallCfg + 22
-#define HvCallCfgRouter23                              HvCallCfg + 23
-#define HvCallCfgRouter24                              HvCallCfg + 24
-#define HvCallCfgRouter25                              HvCallCfg + 25
-#define HvCallCfgRouter26                              HvCallCfg + 26
-#define HvCallCfgRouter27                              HvCallCfg + 27
-#define HvCallCfgGetMinRuntimeMsChunks                 HvCallCfg + 28
-#define HvCallCfgSetMinRuntimeMsChunks                 HvCallCfg + 29
-#define HvCallCfgGetVirtualLanIndexMap                 HvCallCfg + 30
-#define HvCallCfgGetLpExecutionMode                    HvCallCfg + 31
-#define HvCallCfgGetHostingLpIndex                     HvCallCfg + 32
-
-//====================================================================
-static inline HvLpIndex        HvCallCfg_getLps(void)
-{
-       HvLpIndex retVal = HvCall0(HvCallCfgGetLps);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//====================================================================
-static inline int              HvCallCfg_isBusDedicated(u64 busIndex)
-{
-       int retVal = HvCall1(HvCallCfgIsBusDedicated,busIndex);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//====================================================================
-static inline HvLpIndex        HvCallCfg_getBusOwner(u64 busIndex)
-{
-       HvLpIndex retVal = HvCall1(HvCallCfgGetBusOwner,busIndex);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//====================================================================
-static inline HvLpIndexMap     HvCallCfg_getBusAllocation(u64 busIndex)
-{
-       HvLpIndexMap retVal = HvCall1(HvCallCfgGetBusAllocation,busIndex);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//====================================================================
-static inline HvLpIndexMap     HvCallCfg_getActiveLpMap(void)
-{
-       HvLpIndexMap retVal = HvCall0(HvCallCfgGetActiveLpMap);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//====================================================================
-static inline HvLpVirtualLanIndexMap   HvCallCfg_getVirtualLanIndexMap(HvLpIndex lp)
-{
-       // This is a new function in V5R1 so calls to this on older 
-       // hypervisors will return -1
-       u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp);
-       if(retVal == -1)
-               retVal = 0;
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//===================================================================
-static inline u64              HvCallCfg_getSystemMsChunks(void)
-{
-       u64 retVal = HvCall0(HvCallCfgGetSystemMsChunks);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//===================================================================
-static inline u64              HvCallCfg_getMsChunks(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
-       u64 retVal = HvCall2(HvCallCfgGetMsChunks,lp,qual);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//===================================================================
-static inline u64              HvCallCfg_getMinRuntimeMsChunks(HvLpIndex lp)
-{
-       // NOTE: This function was added in v5r1 so older hypervisors will return a -1 value
-       u64 retVal = HvCall1(HvCallCfgGetMinRuntimeMsChunks,lp);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//===================================================================
-static inline u64              HvCallCfg_setMinRuntimeMsChunks(u64 chunks)
-{
-       u64 retVal = HvCall1(HvCallCfgSetMinRuntimeMsChunks,chunks);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//===================================================================
-static inline u64              HvCallCfg_getSystemPhysicalProcessors(void)
-{
-       u64 retVal = HvCall0(HvCallCfgGetSystemPhysicalProcessors);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//===================================================================
-static inline u64              HvCallCfg_getPhysicalProcessors(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
-       u64 retVal = HvCall2(HvCallCfgGetPhysicalProcessors,lp,qual);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-}
-//===================================================================
-static inline u64              HvCallCfg_getConfiguredBusUnitsForInterruptProc(HvLpIndex lp,
-                                                                               u16 hvLogicalProcIndex)
-{
-       u64 retVal = HvCall2(HvCallCfgGetConfiguredBusUnitsForIntProc,lp,hvLogicalProcIndex);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-
-}
-//==================================================================
-static inline HvLpSharedPoolIndex      HvCallCfg_getSharedPoolIndex(HvLpIndex lp)
-{
-       HvLpSharedPoolIndex retVal =
-               HvCall1(HvCallCfgGetSharedPoolIndex,lp);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-
-}
-//==================================================================
-static inline u64      HvCallCfg_getSharedProcUnits(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
-       u64 retVal = HvCall2(HvCallCfgGetSharedProcUnits,lp,qual);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-
-}
-//==================================================================
-static inline u64      HvCallCfg_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
-{
-       u16 retVal = HvCall1(HvCallCfgGetNumProcsInSharedPool,sPI);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-
-}
-//==================================================================
-static inline HvLpIndex        HvCallCfg_getHostingLpIndex(HvLpIndex lp)
-{
-       u64 retVal = HvCall1(HvCallCfgGetHostingLpIndex,lp);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
-
-}
-
-#endif /* _HVCALLCFG_H */
index 191ddce0c2c6528316587d2ffbc5929365c6b066..5d9a327d012202647aff029aa5cdccca86ec1fe4 100644 (file)
@@ -1,32 +1,28 @@
 /*
  * HvCallEvent.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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
  */
-
 /*
- *     This file contains the "hypervisor call" interface which is used to
- *     drive the hypervisor from the OS.
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
  */
 #ifndef _HVCALLEVENT_H
 #define _HVCALLEVENT_H
 
-/*
- * Standard Includes
- */
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 #include <asm/abs_addr.h>
@@ -71,7 +67,7 @@ typedef u64 HvLpDma_Rc;
 #define HvCallEventCloseLpEventPath                    HvCallEvent +  2
 #define HvCallEventDmaBufList                          HvCallEvent +  3
 #define HvCallEventDmaSingle                           HvCallEvent +  4
-#define HvCallEventDmaToSp                             HvCallEvent +  5 
+#define HvCallEventDmaToSp                             HvCallEvent +  5
 #define HvCallEventGetOverflowLpEvents                 HvCallEvent +  6
 #define HvCallEventGetSourceLpInstanceId               HvCallEvent +  7
 #define HvCallEventGetTargetLpInstanceId               HvCallEvent +  8
@@ -85,14 +81,12 @@ typedef u64 HvLpDma_Rc;
 
 static inline void HvCallEvent_getOverflowLpEvents(u8 queueIndex)
 {
-       HvCall1(HvCallEventGetOverflowLpEvents,queueIndex);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       HvCall1(HvCallEventGetOverflowLpEvents, queueIndex);
 }
 
 static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex)
 {
-       HvCall1(HvCallEventSetInterLpQueueIndex,queueIndex);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       HvCall1(HvCallEventSetInterLpQueueIndex, queueIndex);
 }
 
 static inline void HvCallEvent_setLpEventStack(u8 queueIndex,
@@ -103,7 +97,6 @@ static inline void HvCallEvent_setLpEventStack(u8 queueIndex,
        abs_addr = virt_to_abs(eventStackAddr);
        HvCall3(HvCallEventSetLpEventStack, queueIndex, abs_addr,
                        eventStackSize);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
 
 static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex,
@@ -111,22 +104,18 @@ static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex,
 {
        HvCall2(HvCallEventSetLpEventQueueInterruptProc, queueIndex,
                        lpLogicalProcIndex);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
 
 static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event)
 {
        u64 abs_addr;
-       HvLpEvent_Rc retVal;
 
 #ifdef DEBUG_SENDEVENT
        printk("HvCallEvent_signalLpEvent: *event = %016lx\n ",
                        (unsigned long)event);
 #endif
        abs_addr = virt_to_abs(event);
-       retVal = (HvLpEvent_Rc)HvCall1(HvCallEventSignalLpEvent, abs_addr);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall1(HvCallEventSignalLpEvent, abs_addr);
 }
 
 static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
@@ -136,9 +125,7 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
                u64 eventData1, u64 eventData2, u64 eventData3,
                u64 eventData4, u64 eventData5)
 {
-       HvLpEvent_Rc retVal;
-
-       // Pack the misc bits into a single Dword to pass to PLIC
+       /* Pack the misc bits into a single Dword to pass to PLIC */
        union {
                struct HvCallEvent_PackedParms  parms;
                u64             dword;
@@ -152,67 +139,49 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
        packed.parms.xSourceInstId      = sourceInstanceId;
        packed.parms.xTargetInstId      = targetInstanceId;
 
-       retVal = (HvLpEvent_Rc)HvCall7(HvCallEventSignalLpEventParms,
-                       packed.dword, correlationToken, eventData1,eventData2,
-                       eventData3,eventData4, eventData5);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall7(HvCallEventSignalLpEventParms, packed.dword,
+                       correlationToken, eventData1, eventData2,
+                       eventData3, eventData4, eventData5);
 }
 
 static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event)
 {
        u64 abs_addr;
-       HvLpEvent_Rc retVal;
 
        abs_addr = virt_to_abs(event);
-       retVal = (HvLpEvent_Rc)HvCall1(HvCallEventAckLpEvent, abs_addr);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall1(HvCallEventAckLpEvent, abs_addr);
 }
 
 static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event)
 {
        u64 abs_addr;
-       HvLpEvent_Rc retVal;
 
        abs_addr = virt_to_abs(event);
-       retVal = (HvLpEvent_Rc)HvCall1(HvCallEventCancelLpEvent, abs_addr);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall1(HvCallEventCancelLpEvent, abs_addr);
 }
 
 static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId(
                HvLpIndex targetLp, HvLpEvent_Type type)
 {
-       HvLpInstanceId retVal;  
-
-       retVal = HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type);
 }
 
 static inline HvLpInstanceId HvCallEvent_getTargetLpInstanceId(
                HvLpIndex targetLp, HvLpEvent_Type type)
 {
-       HvLpInstanceId retVal;  
-
-       retVal = HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type);
 }
 
 static inline void HvCallEvent_openLpEventPath(HvLpIndex targetLp,
                HvLpEvent_Type type)
 {
        HvCall2(HvCallEventOpenLpEventPath, targetLp, type);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
 
 static inline void HvCallEvent_closeLpEventPath(HvLpIndex targetLp,
                HvLpEvent_Type type)
 {
        HvCall2(HvCallEventCloseLpEventPath, targetLp, type);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
 
 static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
@@ -224,8 +193,7 @@ static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
                /* Do these need to be converted to absolute addresses? */
                u64 localBufList, u64 remoteBufList, u32 transferLength)
 {
-       HvLpDma_Rc retVal;
-       // Pack the misc bits into a single Dword to pass to PLIC
+       /* Pack the misc bits into a single Dword to pass to PLIC */
        union {
                struct HvCallEvent_PackedDmaParms       parms;
                u64             dword;
@@ -241,11 +209,8 @@ static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
        packed.parms.xLocalInstId       = localInstanceId;
        packed.parms.xRemoteInstId      = remoteInstanceId;
 
-       retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaBufList,
-                       packed.dword, localBufList, remoteBufList,
-                       transferLength);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall4(HvCallEventDmaBufList, packed.dword, localBufList,
+                       remoteBufList, transferLength);
 }
 
 static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type,
@@ -256,8 +221,7 @@ static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type,
                HvLpDma_AddressType remoteAddressType,
                u64 localAddrOrTce, u64 remoteAddrOrTce, u32 transferLength)
 {
-       HvLpDma_Rc retVal;
-       // Pack the misc bits into a single Dword to pass to PLIC
+       /* Pack the misc bits into a single Dword to pass to PLIC */
        union {
                struct HvCallEvent_PackedDmaParms       parms;
                u64             dword;
@@ -273,25 +237,17 @@ static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type,
        packed.parms.xLocalInstId       = localInstanceId;
        packed.parms.xRemoteInstId      = remoteInstanceId;
 
-       retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle,
-                       packed.dword, localAddrOrTce, remoteAddrOrTce,
-                       transferLength);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle, packed.dword,
+                       localAddrOrTce, remoteAddrOrTce, transferLength);
 }
 
-static inline HvLpDma_Rc HvCallEvent_dmaToSp(voidlocal, u32 remote,
+static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote,
                u32 length, HvLpDma_Direction dir)
 {
        u64 abs_addr;
-       HvLpDma_Rc retVal;
 
        abs_addr = virt_to_abs(local);
-       retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaToSp, abs_addr, remote,
-                       length, dir);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall4(HvCallEventDmaToSp, abs_addr, remote, length, dir);
 }
 
-
 #endif /* _HVCALLEVENT_H */
index da769873d18b030920c785ac531cc48b730b1cdc..66f38222ff755baf9374947a161cefca067c3dbb 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * HvCallHpt.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _HVCALLHPT_H
 #define _HVCALLHPT_H
 
-//============================================================================
-//
-//     This file contains the "hypervisor call" interface which is used to
-//     drive the hypervisor from the OS.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
 
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 #include <asm/mmu.h>
 
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
 #define HvCallHptGetHptAddress         HvCallHpt +  0
 #define HvCallHptGetHptPages           HvCallHpt +  1
 #define HvCallHptSetPp                 HvCallHpt +  5
 #define HvCallHptInvalidateSetSwBitsGet HvCallHpt + 18
 
 
-//============================================================================
-static inline u64              HvCallHpt_getHptAddress(void)
+static inline u64 HvCallHpt_getHptAddress(void)
 {
-       u64 retval = HvCall0(HvCallHptGetHptAddress);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retval;
+       return HvCall0(HvCallHptGetHptAddress);
 }
-//============================================================================
-static inline u64              HvCallHpt_getHptPages(void)
-{      
-       u64 retval = HvCall0(HvCallHptGetHptPages);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retval;
+
+static inline u64 HvCallHpt_getHptPages(void)
+{
+       return HvCall0(HvCallHptGetHptPages);
 }
-//=============================================================================
-static inline void             HvCallHpt_setPp(u32 hpteIndex, u8 value)
+
+static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value)
 {
-       HvCall2( HvCallHptSetPp, hpteIndex, value );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       HvCall2(HvCallHptSetPp, hpteIndex, value);
 }
-//=============================================================================
-static inline void             HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff )
+
+static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff)
 {
-       HvCall3( HvCallHptSetSwBits, hpteIndex, bitson, bitsoff );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       HvCall3(HvCallHptSetSwBits, hpteIndex, bitson, bitsoff);
 }
-//=============================================================================
-static inline void             HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
-                                               
+
+static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
 {
-       HvCall1( HvCallHptInvalidateNoSyncICache, hpteIndex );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
 }
-//=============================================================================
-static inline u64              HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, u8 bitsoff )
-                                               
+
+static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
+               u8 bitsoff)
 {
        u64 compressedStatus;
-       compressedStatus = HvCall4( HvCallHptInvalidateSetSwBitsGet, hpteIndex, bitson, bitsoff, 1 );
-       HvCall1( HvCallHptInvalidateNoSyncICache, hpteIndex );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+
+       compressedStatus = HvCall4(HvCallHptInvalidateSetSwBitsGet,
+                       hpteIndex, bitson, bitsoff, 1);
+       HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
        return compressedStatus;
 }
-//=============================================================================
-static inline u64              HvCallHpt_findValid( HPTE *hpte, u64 vpn )
+
+static inline u64 HvCallHpt_findValid(HPTE *hpte, u64 vpn)
 {
-       u64 retIndex = HvCall3Ret16( HvCallHptFindValid, hpte, vpn, 0, 0 );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retIndex;
+       return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
 }
-//=============================================================================
-static inline u64              HvCallHpt_findNextValid( HPTE *hpte, u32 hpteIndex, u8 bitson, u8 bitsoff )
+
+static inline u64 HvCallHpt_findNextValid(HPTE *hpte, u32 hpteIndex,
+               u8 bitson, u8 bitsoff)
 {
-       u64 retIndex = HvCall3Ret16( HvCallHptFindNextValid, hpte, hpteIndex, bitson, bitsoff );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retIndex;
+       return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
+                       bitson, bitsoff);
 }
-//=============================================================================
-static inline void             HvCallHpt_get( HPTE *hpte, u32 hpteIndex )
+
+static inline void HvCallHpt_get(HPTE *hpte, u32 hpteIndex)
 {
-       HvCall2Ret16( HvCallHptGet, hpte, hpteIndex, 0 );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
 }
-//============================================================================
-static inline void             HvCallHpt_addValidate( u32 hpteIndex,
-                                                      u32 hBit,
-                                                      HPTE *hpte )
-                                               
+
+static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, HPTE *hpte)
 {
-       HvCall4( HvCallHptAddValidate, hpteIndex,
-                hBit, (*((u64 *)hpte)), (*(((u64 *)hpte)+1)) );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       HvCall4(HvCallHptAddValidate, hpteIndex, hBit, (*((u64 *)hpte)),
+                       (*(((u64 *)hpte)+1)));
 }
 
-
-//=============================================================================
-
 #endif /* _HVCALLHPT_H */
index 6887b619288eeb3fa062afc85cc2d365daae13d0..c8d675c40f5efcde0e41a95684ac79a630b328e2 100644 (file)
@@ -1,26 +1,26 @@
-/************************************************************************/
-/* Provides the Hypervisor PCI calls for iSeries Linux Parition.        */
-/* Copyright (C) 2001  <Wayne G Holm> <IBM Corporation>                 */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created, Jan 9, 2001                                               */
-/************************************************************************/
+/*
+ * Provides the Hypervisor PCI calls for iSeries Linux Parition.
+ * Copyright (C) 2001  <Wayne G Holm> <IBM Corporation>
+ *
+ * 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
+ *
+ * Change Activity:
+ *   Created, Jan 9, 2001
+ */
 
 #ifndef _HVCALLPCI_H
 #define _HVCALLPCI_H
@@ -34,8 +34,8 @@
  */
 struct HvCallPci_DsaAddr {
        u16             busNumber;              /* PHB index? */
-       u8              subBusNumber;           /* PCI bus number? */
-       u8              deviceId;               /* device and function? */
+       u8              subBusNumber;           /* PCI bus number? */
+       u8              deviceId;               /* device and function? */
        u8              barNumber;
        u8              reserved[3];
 };
@@ -52,34 +52,37 @@ struct HvCallPci_LoadReturn {
 
 enum HvCallPci_DeviceType {
        HvCallPci_NodeDevice    = 1,
-       HvCallPci_SpDevice      = 2,    
-       HvCallPci_IopDevice     = 3,    
-       HvCallPci_BridgeDevice  = 4,    
-       HvCallPci_MultiFunctionDevice = 5,      
-       HvCallPci_IoaDevice     = 6     
+       HvCallPci_SpDevice      = 2,
+       HvCallPci_IopDevice     = 3,
+       HvCallPci_BridgeDevice  = 4,
+       HvCallPci_MultiFunctionDevice = 5,
+       HvCallPci_IoaDevice     = 6
 };
 
 
 struct HvCallPci_DeviceInfo {
-       u32     deviceType;             // See DeviceType enum for values
+       u32     deviceType;             /* See DeviceType enum for values */
 };
-    
+
 struct HvCallPci_BusUnitInfo {
-       u32     sizeReturned;           // length of data returned
-       u32     deviceType;             // see DeviceType enum for values
+       u32     sizeReturned;           /* length of data returned */
+       u32     deviceType;             /* see DeviceType enum for values */
 };
 
 struct HvCallPci_BridgeInfo {
-       struct HvCallPci_BusUnitInfo busUnitInfo;  // Generic bus unit info
-       u8              subBusNumber;           // Bus number of secondary bus
-       u8              maxAgents;              // Max idsels on secondary bus
-        u8              maxSubBusNumber;        // Max Sub Bus
-       u8              logicalSlotNumber;      // Logical Slot Number for IOA 
+       struct HvCallPci_BusUnitInfo busUnitInfo;  /* Generic bus unit info */
+       u8              subBusNumber;   /* Bus number of secondary bus */
+       u8              maxAgents;      /* Max idsels on secondary bus */
+        u8              maxSubBusNumber; /* Max Sub Bus */
+       u8              logicalSlotNumber; /* Logical Slot Number for IOA */
 };
-    
 
-//  Maximum BusUnitInfo buffer size.  Provided for clients so they can allocate
-//  a buffer big enough for any type of bus unit.  Increase as needed.
+
+/*
+ * Maximum BusUnitInfo buffer size.  Provided for clients so
+ * they can allocate a buffer big enough for any type of bus
+ * unit.  Increase as needed.
+ */
 enum {HvCallPci_MaxBusUnitInfoSize = 128};
 
 struct HvCallPci_BarParms {
@@ -89,12 +92,12 @@ struct HvCallPci_BarParms {
        u64             protectStart;
        u64             protectEnd;
        u64             relocationOffset;
-       u64             pciAddress;             
+       u64             pciAddress;
        u64             reserved[3];
-};                                     
+};
 
 enum HvCallPci_VpdType {
-       HvCallPci_BusVpd                = 1,
+       HvCallPci_BusVpd        = 1,
        HvCallPci_BusAdapterVpd = 2
 };
 
@@ -123,15 +126,13 @@ enum HvCallPci_VpdType {
 #define HvCallPciUnmaskInterrupts      HvCallPci + 49
 #define HvCallPciGetBusUnitInfo                HvCallPci + 50
 
-//============================================================================
 static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber,
-                                       u8 deviceId, u32 offset,
-                                       u8 *value)
+               u8 deviceId, u32 offset, u8 *value)
 {
        struct HvCallPci_DsaAddr dsa;
        struct HvCallPci_LoadReturn retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumber;
        dsa.subBusNumber = subBusNumber;
@@ -139,21 +140,18 @@ static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber,
 
        HvCall3Ret16(HvCallPciConfigLoad8, &retVal, *(u64 *)&dsa, offset, 0);
 
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
        *value = retVal.value;
 
        return retVal.rc;
 }
-//============================================================================
+
 static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
-                                        u8 deviceId, u32 offset,
-                                        u16 *value)
+               u8 deviceId, u32 offset, u16 *value)
 {
        struct HvCallPci_DsaAddr dsa;
        struct HvCallPci_LoadReturn retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumber;
        dsa.subBusNumber = subBusNumber;
@@ -161,21 +159,18 @@ static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
 
        HvCall3Ret16(HvCallPciConfigLoad16, &retVal, *(u64 *)&dsa, offset, 0);
 
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
        *value = retVal.value;
 
        return retVal.rc;
 }
-//============================================================================
-static inline u64      HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
-                                             u8 deviceId, u32 offset,
-                                             u32 *value)
+
+static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
+               u8 deviceId, u32 offset, u32 *value)
 {
        struct HvCallPci_DsaAddr dsa;
        struct HvCallPci_LoadReturn retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumber;
        dsa.subBusNumber = subBusNumber;
@@ -183,84 +178,61 @@ static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
 
        HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
 
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
        *value = retVal.value;
 
        return retVal.rc;
 }
-//============================================================================
-static inline u64      HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
-                                             u8 deviceId, u32 offset,
-                                             u8  value)
+
+static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
+               u8 deviceId, u32 offset, u8 value)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumber;
        dsa.subBusNumber = subBusNumber;
        dsa.deviceId = deviceId;
 
-       retVal = HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
 }
-//============================================================================
-static inline u64      HvCallPci_configStore16(u16 busNumber, u8 subBusNumber,
-                                             u8 deviceId, u32 offset,
-                                             u16  value)
+
+static inline u64 HvCallPci_configStore16(u16 busNumber, u8 subBusNumber,
+               u8 deviceId, u32 offset, u16 value)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumber;
        dsa.subBusNumber = subBusNumber;
        dsa.deviceId = deviceId;
 
-       retVal = HvCall4(HvCallPciConfigStore16, *(u64 *)&dsa, offset, value, 0);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall4(HvCallPciConfigStore16, *(u64 *)&dsa, offset, value, 0);
 }
-//============================================================================
-static inline u64      HvCallPci_configStore32(u16 busNumber, u8 subBusNumber,
-                                             u8 deviceId, u32 offset,
-                                             u32  value)
+
+static inline u64 HvCallPci_configStore32(u16 busNumber, u8 subBusNumber,
+               u8 deviceId, u32 offset, u32 value)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumber;
        dsa.subBusNumber = subBusNumber;
        dsa.deviceId = deviceId;
 
-       retVal = HvCall4(HvCallPciConfigStore32, *(u64 *)&dsa, offset, value, 0);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall4(HvCallPciConfigStore32, *(u64 *)&dsa, offset, value, 0);
 }
-//============================================================================
-static inline u64      HvCallPci_barLoad8(u16  busNumberParm,
-                                          u8           subBusParm,
-                                          u8           deviceIdParm,
-                                          u8           barNumberParm,
-                                          u64          offsetParm,
-                                          u8*          valueParm)
+
+static inline u64 HvCallPci_barLoad8(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+               u8 *valueParm)
 {
        struct HvCallPci_DsaAddr dsa;
        struct HvCallPci_LoadReturn retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
@@ -269,24 +241,19 @@ static inline u64 HvCallPci_barLoad8(u16  busNumberParm,
 
        HvCall3Ret16(HvCallPciBarLoad8, &retVal, *(u64 *)&dsa, offsetParm, 0);
 
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
        *valueParm = retVal.value;
 
        return retVal.rc;
 }
-//============================================================================
-static inline u64      HvCallPci_barLoad16(u16 busNumberParm,
-                                          u8           subBusParm,
-                                          u8           deviceIdParm,
-                                          u8           barNumberParm,
-                                          u64          offsetParm,
-                                          u16*         valueParm)
+
+static inline u64 HvCallPci_barLoad16(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+               u16 *valueParm)
 {
        struct HvCallPci_DsaAddr dsa;
        struct HvCallPci_LoadReturn retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
@@ -295,24 +262,19 @@ static inline u64 HvCallPci_barLoad16(u16 busNumberParm,
 
        HvCall3Ret16(HvCallPciBarLoad16, &retVal, *(u64 *)&dsa, offsetParm, 0);
 
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
        *valueParm = retVal.value;
 
        return retVal.rc;
 }
-//============================================================================
-static inline u64      HvCallPci_barLoad32(u16 busNumberParm,
-                                          u8           subBusParm,
-                                          u8           deviceIdParm,
-                                          u8           barNumberParm,
-                                          u64          offsetParm,
-                                          u32*         valueParm)
+
+static inline u64 HvCallPci_barLoad32(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+               u32 *valueParm)
 {
        struct HvCallPci_DsaAddr dsa;
        struct HvCallPci_LoadReturn retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
@@ -321,24 +283,19 @@ static inline u64 HvCallPci_barLoad32(u16 busNumberParm,
 
        HvCall3Ret16(HvCallPciBarLoad32, &retVal, *(u64 *)&dsa, offsetParm, 0);
 
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
        *valueParm = retVal.value;
 
        return retVal.rc;
 }
-//============================================================================
-static inline u64      HvCallPci_barLoad64(u16 busNumberParm,
-                                          u8           subBusParm,
-                                          u8           deviceIdParm,
-                                          u8           barNumberParm,
-                                          u64          offsetParm,
-                                          u64*         valueParm)
+
+static inline u64 HvCallPci_barLoad64(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+               u64 *valueParm)
 {
        struct HvCallPci_DsaAddr dsa;
        struct HvCallPci_LoadReturn retVal;
 
-       *((u64*)&dsa) = 0;                              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
@@ -347,112 +304,81 @@ static inline u64        HvCallPci_barLoad64(u16 busNumberParm,
 
        HvCall3Ret16(HvCallPciBarLoad64, &retVal, *(u64 *)&dsa, offsetParm, 0);
 
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
        *valueParm = retVal.value;
 
        return retVal.rc;
 }
-//============================================================================
-static inline u64      HvCallPci_barStore8(u16 busNumberParm,
-                                           u8          subBusParm,
-                                           u8          deviceIdParm,
-                                           u8          barNumberParm,
-                                           u64         offsetParm,
-                                           u8          valueParm)
+
+static inline u64 HvCallPci_barStore8(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+               u8 valueParm)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
        *((u64*)&dsa) = 0;
-                               
+
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
        dsa.barNumber = barNumberParm;
 
-       retVal = HvCall4(HvCallPciBarStore8, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall4(HvCallPciBarStore8, *(u64 *)&dsa, offsetParm,
+                       valueParm, 0);
 }
-//============================================================================
-static inline u64      HvCallPci_barStore16(u16        busNumberParm,
-                                            u8         subBusParm,
-                                            u8         deviceIdParm,
-                                            u8         barNumberParm,
-                                            u64        offsetParm,
-                                            u16        valueParm)
+
+static inline u64 HvCallPci_barStore16(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+               u16 valueParm)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
        *((u64*)&dsa) = 0;
-                               
+
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
        dsa.barNumber = barNumberParm;
 
-       retVal = HvCall4(HvCallPciBarStore16, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall4(HvCallPciBarStore16, *(u64 *)&dsa, offsetParm,
+                       valueParm, 0);
 }
-//============================================================================
-static inline u64      HvCallPci_barStore32(u16        busNumberParm,
-                                            u8         subBusParm,
-                                            u8         deviceIdParm,
-                                            u8         barNumberParm,
-                                            u64        offsetParm,
-                                            u32        valueParm)
+
+static inline u64 HvCallPci_barStore32(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+               u32 valueParm)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
        *((u64*)&dsa) = 0;
-                               
+
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
        dsa.barNumber = barNumberParm;
 
-       retVal = HvCall4(HvCallPciBarStore32, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall4(HvCallPciBarStore32, *(u64 *)&dsa, offsetParm,
+                       valueParm, 0);
 }
-//============================================================================
-static inline u64      HvCallPci_barStore64(u16        busNumberParm,
-                                            u8         subBusParm,
-                                            u8         deviceIdParm,
-                                            u8         barNumberParm,
-                                            u64        offsetParm,
-                                            u64        valueParm)
+
+static inline u64 HvCallPci_barStore64(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+               u64 valueParm)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
        *((u64*)&dsa) = 0;
-                               
+
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
        dsa.barNumber = barNumberParm;
 
-       retVal = HvCall4(HvCallPciBarStore64, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall4(HvCallPciBarStore64, *(u64 *)&dsa, offsetParm,
+                       valueParm, 0);
 }
-//============================================================================
-static inline u64      HvCallPci_eoi(u16       busNumberParm,
-                                     u8        subBusParm,  
-                                     u8        deviceIdParm)
+
+static inline u64 HvCallPci_eoi(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm)
 {
        struct HvCallPci_DsaAddr dsa;
        struct HvCallPci_LoadReturn retVal;
@@ -465,20 +391,13 @@ static inline u64 HvCallPci_eoi(u16       busNumberParm,
 
        HvCall1Ret16(HvCallPciEoi, &retVal, *(u64*)&dsa);
 
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
        return retVal.rc;
 }
-//============================================================================
-static inline u64      HvCallPci_getBarParms(u16       busNumberParm,
-                                             u8        subBusParm,  
-                                             u8        deviceIdParm,
-                                             u8        barNumberParm,
-                                             u64       parms,
-                                             u32       sizeofParms)
+
+static inline u64 HvCallPci_getBarParms(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u8 barNumberParm, u64 parms, u32 sizeofParms)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
        *((u64*)&dsa) = 0;
 
@@ -487,62 +406,41 @@ static inline u64 HvCallPci_getBarParms(u16       busNumberParm,
        dsa.deviceId = deviceIdParm;
        dsa.barNumber = barNumberParm;
 
-       retVal = HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
 }
-//============================================================================
-static inline u64      HvCallPci_maskFisr(u16  busNumberParm,
-                                          u8   subBusParm,  
-                                          u8   deviceIdParm,
-                                          u64  fisrMask)
+
+static inline u64 HvCallPci_maskFisr(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u64 fisrMask)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
-       *((u64*)&dsa) = 0;              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
 
-       retVal = HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
 }
-//============================================================================
-static inline u64      HvCallPci_unmaskFisr(u16        busNumberParm,
-                                            u8         subBusParm,  
-                                            u8         deviceIdParm,
-                                            u64        fisrMask)
+
+static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u64 fisrMask)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
-       *((u64*)&dsa) = 0;              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
 
-       retVal = HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
 }
-//============================================================================
-static inline u64      HvCallPci_setSlotReset(u16              busNumberParm,
-                                              u8               subBusParm,
-                                              u8               deviceIdParm,
-                                              u64              onNotOff)
+
+static inline u64 HvCallPci_setSlotReset(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u64 onNotOff)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
        *((u64*)&dsa) = 0;
 
@@ -550,21 +448,13 @@ static inline u64 HvCallPci_setSlotReset(u16              busNumberParm,
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
 
-       retVal = HvCall2(HvCallPciSetSlotReset, *(u64*)&dsa, onNotOff);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall2(HvCallPciSetSlotReset, *(u64*)&dsa, onNotOff);
 }
-//============================================================================
-static inline u64      HvCallPci_getDeviceInfo(u16     busNumberParm,
-                                               u8      subBusParm,  
-                                               u8      deviceNumberParm,
-                                               u64     parms,
-                                               u32     sizeofParms)
+
+static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm, u8 subBusParm,
+               u8 deviceNumberParm, u64 parms, u32 sizeofParms)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
        *((u64*)&dsa) = 0;
 
@@ -572,102 +462,72 @@ static inline u64        HvCallPci_getDeviceInfo(u16     busNumberParm,
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceNumberParm << 4;
 
-       retVal = HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
 }
-//============================================================================
-static inline u64      HvCallPci_maskInterrupts(u16    busNumberParm,
-                                                u8     subBusParm,  
-                                                u8     deviceIdParm,
-                                                u64    interruptMask)
+
+static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u64 interruptMask)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
-       *((u64*)&dsa) = 0;              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
 
-       retVal = HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
 }
-//============================================================================
-static inline u64      HvCallPci_unmaskInterrupts(u16  busNumberParm,
-                                                u8             subBusParm,  
-                                                u8             deviceIdParm,
-                                                u64            interruptMask)
+
+static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u64 interruptMask)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
-       *((u64*)&dsa) = 0;              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
 
-       retVal = HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
 }
-//============================================================================
 
-static inline u64      HvCallPci_getBusUnitInfo(u16            busNumberParm,
-                                                u8             subBusParm,  
-                                                u8             deviceIdParm,
-                                                u64            parms,
-                                                u32            sizeofParms)
+static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm, u8 subBusParm,
+               u8 deviceIdParm, u64 parms, u32 sizeofParms)
 {
        struct HvCallPci_DsaAddr dsa;
-       u64 retVal;
 
-       *((u64*)&dsa) = 0;              
+       *((u64*)&dsa) = 0;
 
        dsa.busNumber = busNumberParm;
        dsa.subBusNumber = subBusParm;
        dsa.deviceId = deviceIdParm;
 
-       retVal = HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms, sizeofParms);
-
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-       return retVal;
+       return HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms,
+                       sizeofParms);
 }
-//============================================================================
 
-static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm, u16 sizeParm)
+static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm,
+               u16 sizeParm)
 {
-       int xRetSize;
-       u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm, sizeParm, HvCallPci_BusVpd);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
+                       sizeParm, HvCallPci_BusVpd);
        if (xRc == -1)
-               xRetSize = -1;
+               return -1;
        else
-               xRetSize = xRc & 0xFFFF;
-       return xRetSize;
+               return xRc & 0xFFFF;
 }
-//============================================================================
 
-static inline int HvCallPci_getBusAdapterVpd(u16 busNumParm, u64 destParm, u16 sizeParm)
+static inline int HvCallPci_getBusAdapterVpd(u16 busNumParm, u64 destParm,
+               u16 sizeParm)
 {
-       int xRetSize;
-       u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm, sizeParm, HvCallPci_BusAdapterVpd);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+       u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
+                       sizeParm, HvCallPci_BusAdapterVpd);
        if (xRc == -1)
-               xRetSize = -1;
+               return -1;
        else
-               xRetSize = xRc & 0xFFFF;
-       return xRetSize;
+               return xRc & 0xFFFF;
 }
-//============================================================================
+
 #endif /* _HVCALLPCI_H */
index eea258447642dce41907f13957749ab6f4b0102a..a62cef3822f9be9f0224ad5f983a4c10ccbd38e8 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * HvCallSc.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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
@@ -19,7 +19,7 @@
 #ifndef _HVCALLSC_H
 #define _HVCALLSC_H
 
-#include <asm/iSeries/HvTypes.h>
+#include <linux/types.h>
 
 #define HvCallBase             0x8000000000000000ul
 #define HvCallCc               0x8001000000000000ul
 #define HvCallSm               0x8007000000000000ul
 #define HvCallXm               0x8009000000000000ul
 
-u64 HvCall0( u64 );
-u64 HvCall1( u64, u64 );
-u64 HvCall2( u64, u64, u64 );
-u64 HvCall3( u64, u64, u64, u64 );
-u64 HvCall4( u64, u64, u64, u64, u64 );
-u64 HvCall5( u64, u64, u64, u64, u64, u64 );
-u64 HvCall6( u64, u64, u64, u64, u64, u64, u64 );
-u64 HvCall7( u64, u64, u64, u64, u64, u64, u64, u64 );
+extern u64 HvCall0(u64);
+extern u64 HvCall1(u64, u64);
+extern u64 HvCall2(u64, u64, u64);
+extern u64 HvCall3(u64, u64, u64, u64);
+extern u64 HvCall4(u64, u64, u64, u64, u64);
+extern u64 HvCall5(u64, u64, u64, u64, u64, u64);
+extern u64 HvCall6(u64, u64, u64, u64, u64, u64, u64);
+extern u64 HvCall7(u64, u64, u64, u64, u64, u64, u64, u64);
 
-u64 HvCall0Ret16( u64, void * );
-u64 HvCall1Ret16( u64, void *, u64 );
-u64 HvCall2Ret16( u64, void *, u64, u64 );
-u64 HvCall3Ret16( u64, void *, u64, u64, u64 );
-u64 HvCall4Ret16( u64, void *, u64, u64, u64, u64 );
-u64 HvCall5Ret16( u64, void *, u64, u64, u64, u64, u64 );
-u64 HvCall6Ret16( u64, void *, u64, u64, u64, u64, u64, u64 );
-u64 HvCall7Ret16( u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64 );
+extern u64 HvCall0Ret16(u64, void *);
+extern u64 HvCall1Ret16(u64, void *, u64);
+extern u64 HvCall2Ret16(u64, void *, u64, u64);
+extern u64 HvCall3Ret16(u64, void *, u64, u64, u64);
+extern u64 HvCall4Ret16(u64, void *, u64, u64, u64, u64);
+extern u64 HvCall5Ret16(u64, void *, u64, u64, u64, u64, u64);
+extern u64 HvCall6Ret16(u64, void *, u64, u64, u64, u64, u64, u64);
+extern u64 HvCall7Ret16(u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64);
 
 #endif /* _HVCALLSC_H */
index 9050c94a529d8196b4719b0f6466629eda5a5779..8a3dbb071a4397962948c8ac0778a370c4d99b6f 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * HvCallSm.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _HVCALLSM_H
 #define _HVCALLSM_H
 
-//============================================================================
-//
-//     This file contains the "hypervisor call" interface which is used to
-//     drive the hypervisor from the OS.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
 
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
 #define HvCallSmGet64BitsOfAccessMap   HvCallSm  + 11
 
-
-//============================================================================
-static inline u64              HvCallSm_get64BitsOfAccessMap(
-                                       HvLpIndex lpIndex, u64 indexIntoBitMap )
+static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex,
+               u64 indexIntoBitMap)
 {
-       u64 retval = HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex,
-                            indexIntoBitMap );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retval;
+       return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap);
 }
-//============================================================================
+
 #endif /* _HVCALLSM_H */
index bfb898f4db8d0e3b91a8da5c7a96950a88ca6609..8b9ba608daafe7cf28578c50f073a9eec1f82540 100644 (file)
@@ -1,30 +1,13 @@
-//============================================================================
-//                                                      Header File Id
-// Name______________: HvCallXm.H
-//
-// Description_______:
-//
-//     This file contains the "hypervisor call" interface which is used to
-//     drive the hypervisor from SLIC.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from SLIC.
+ */
 #ifndef _HVCALLXM_H
 #define _HVCALLXM_H
 
-//-------------------------------------------------------------------
-// Forward declarations 
-//-------------------------------------------------------------------
-
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
 #define HvCallXmGetTceTableParms       HvCallXm +  0
 #define HvCallXmTestBus                        HvCallXm +  1
 #define HvCallXmConnectBusUnit         HvCallXm +  2
 #define HvCallXmSetTce                 HvCallXm + 11
 #define HvCallXmSetTces                        HvCallXm + 13
 
+/*
+ * Structure passed to HvCallXm_getTceTableParms
+ */
+struct iommu_table_cb {
+       unsigned long   itc_busno;      /* Bus number for this tce table */
+       unsigned long   itc_start;      /* Will be NULL for secondary */
+       unsigned long   itc_totalsize;  /* Size (in pages) of whole table */
+       unsigned long   itc_offset;     /* Index into real tce table of the
+                                          start of our section */
+       unsigned long   itc_size;       /* Size (in pages) of our section */
+       unsigned long   itc_index;      /* Index of this tce table */
+       unsigned short  itc_maxtables;  /* Max num of tables for partition */
+       unsigned char   itc_virtbus;    /* Flag to indicate virtual bus */
+       unsigned char   itc_slotno;     /* IOA Tce Slot Index */
+       unsigned char   itc_rsvd[4];
+};
 
-
-//============================================================================
-static inline void             HvCallXm_getTceTableParms(u64 cb)
+static inline void HvCallXm_getTceTableParms(u64 cb)
 {
        HvCall1(HvCallXmGetTceTableParms, cb);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
-//============================================================================
-static inline u64              HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce)
-{      
-       u64 retval = HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retval;
-}
-//============================================================================
-static inline u64              HvCallXm_setTces(u64 tceTableToken, u64 tceOffset, u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4)
-{      
-       u64 retval = HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces,
-                            tce1, tce2, tce3, tce4 );
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retval;
+
+static inline u64 HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce)
+{
+       return HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce);
 }
-//=============================================================================
-static inline u64      HvCallXm_testBus(u16 busNumber)
+
+static inline u64 HvCallXm_setTces(u64 tceTableToken, u64 tceOffset,
+               u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4)
 {
-       u64 retVal = HvCall1(HvCallXmTestBus, busNumber);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces,
+                            tce1, tce2, tce3, tce4);
 }
-//=====================================================================================
-static inline u64      HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber, u8 deviceId)
+
+static inline u64 HvCallXm_testBus(u16 busNumber)
 {
-       u64 busUnitNumber = (subBusNumber << 8) | deviceId;
-       u64 retVal = HvCall2(HvCallXmTestBusUnit, busNumber, busUnitNumber);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall1(HvCallXmTestBus, busNumber);
 }
-//=====================================================================================
-static inline u64      HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber, u8 deviceId,
-                                               u64 interruptToken)
+
+static inline u64 HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber,
+               u8 deviceId)
 {
-       u64 busUnitNumber = (subBusNumber << 8) | deviceId;
-       u64 queueIndex = 0; // HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard));  
+       return HvCall2(HvCallXmTestBusUnit, busNumber,
+                       (subBusNumber << 8) | deviceId);
+}
 
-       u64 retVal = HvCall5(HvCallXmConnectBusUnit, busNumber, busUnitNumber,
-                            interruptToken, 0, queueIndex);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+static inline u64 HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber,
+               u8 deviceId, u64 interruptToken)
+{
+       return HvCall5(HvCallXmConnectBusUnit, busNumber,
+                       (subBusNumber << 8) | deviceId, interruptToken, 0,
+                       0 /* HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard)) */);
 }
-//=====================================================================================
-static inline u64      HvCallXm_loadTod(void)
+
+static inline u64 HvCallXm_loadTod(void)
 {
-       u64 retVal = HvCall0(HvCallXmLoadTod);
-       // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-       return retVal;
+       return HvCall0(HvCallXmLoadTod);
 }
-//=====================================================================================
 
 #endif /* _HVCALLXM_H */
index bdbd70f42c9dfbce3781404def899e743cc15ec1..f1cf1e70ca3c2de386eb9ce870fca368065aad52 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * HvLpConfig.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _HVLPCONFIG_H
 #define _HVLPCONFIG_H
 
-//===========================================================================
-//
-//      This file contains the interface to the LPAR configuration data
-//  to determine which resources should be allocated to each partition.
-//
-//===========================================================================
+/*
+ * This file contains the interface to the LPAR configuration data
+ * to determine which resources should be allocated to each partition.
+ */
 
-#include <asm/iSeries/HvCallCfg.h>
+#include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 #include <asm/iSeries/ItLpNaca.h>
-#include <asm/iSeries/LparData.h>
 
-//-------------------------------------------------------------------
-// Constants
-//-------------------------------------------------------------------
+enum {
+       HvCallCfg_Cur   = 0,
+       HvCallCfg_Init  = 1,
+       HvCallCfg_Max   = 2,
+       HvCallCfg_Min   = 3
+};
+
+#define HvCallCfgGetSystemPhysicalProcessors           HvCallCfg +  6
+#define HvCallCfgGetPhysicalProcessors                 HvCallCfg +  7
+#define HvCallCfgGetMsChunks                           HvCallCfg +  9
+#define HvCallCfgGetSharedPoolIndex                    HvCallCfg + 20
+#define HvCallCfgGetSharedProcUnits                    HvCallCfg + 21
+#define HvCallCfgGetNumProcsInSharedPool               HvCallCfg + 22
+#define HvCallCfgGetVirtualLanIndexMap                 HvCallCfg + 30
+#define HvCallCfgGetHostingLpIndex                     HvCallCfg + 32
 
 extern HvLpIndex HvLpConfig_getLpIndex_outline(void);
 
-//===================================================================
 static inline HvLpIndex        HvLpConfig_getLpIndex(void)
 {
        return itLpNaca.xLpIndex;
 }
-//===================================================================
+
 static inline HvLpIndex        HvLpConfig_getPrimaryLpIndex(void)
 {
        return itLpNaca.xPrimaryLpIndex;
 }
-//=================================================================
-static inline HvLpIndex        HvLpConfig_getLps(void)
-{
-       return HvCallCfg_getLps();
-}
-//=================================================================
-static inline HvLpIndexMap     HvLpConfig_getActiveLpMap(void)
-{
-       return HvCallCfg_getActiveLpMap();
-}
-//=================================================================
-static inline u64              HvLpConfig_getSystemMsMegs(void)
-{
-       return HvCallCfg_getSystemMsChunks() / HVCHUNKSPERMEG;
-}
-//=================================================================
-static inline u64              HvLpConfig_getSystemMsChunks(void)
-{
-       return HvCallCfg_getSystemMsChunks();
-}
-//=================================================================
-static inline u64              HvLpConfig_getSystemMsPages(void)
-{
-       return HvCallCfg_getSystemMsChunks() * HVPAGESPERCHUNK;
-}
-//================================================================
-static inline u64              HvLpConfig_getMsMegs(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur) / HVCHUNKSPERMEG;
-}
-//================================================================
-static inline u64              HvLpConfig_getMsChunks(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
-}
-//================================================================
-static inline u64              HvLpConfig_getMsPages(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur) * HVPAGESPERCHUNK;
-}
-//================================================================
-static inline u64              HvLpConfig_getMinMsMegs(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min) / HVCHUNKSPERMEG;
-}
-//================================================================
-static inline u64              HvLpConfig_getMinMsChunks(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min);
-}
-//================================================================
-static inline u64              HvLpConfig_getMinMsPages(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min) * HVPAGESPERCHUNK;
-}
-//================================================================
-static inline u64              HvLpConfig_getMinRuntimeMsMegs(void)
-{
-       return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64              HvLpConfig_getMinRuntimeMsChunks(void)
-{
-       return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex());
-}
-//===============================================================
-static inline u64              HvLpConfig_getMinRuntimeMsPages(void)
-{
-       return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64              HvLpConfig_getMaxMsMegs(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64              HvLpConfig_getMaxMsChunks(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64              HvLpConfig_getMaxMsPages(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64              HvLpConfig_getInitMsMegs(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64              HvLpConfig_getInitMsChunks(void)
-{
-       return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init);
-}
-//===============================================================
-static inline u64              HvLpConfig_getInitMsPages(void)
-{    return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64              HvLpConfig_getSystemPhysicalProcessors(void)
-{
-       return HvCallCfg_getSystemPhysicalProcessors();
-}
-//===============================================================
-static inline u64              HvLpConfig_getSystemLogicalProcessors(void)
-{
-       return HvCallCfg_getSystemPhysicalProcessors() * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64              HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
-{
-       return HvCallCfg_getNumProcsInSharedPool(sPI);
-}
-//===============================================================
-static inline u64              HvLpConfig_getPhysicalProcessors(void)
-{
-       return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
-}
-//===============================================================
-static inline u64              HvLpConfig_getLogicalProcessors(void)
-{
-       return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Cur) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline HvLpSharedPoolIndex      HvLpConfig_getSharedPoolIndex(void)
-{
-       return HvCallCfg_getSharedPoolIndex(HvLpConfig_getLpIndex());
-}
-//===============================================================
-static inline u64              HvLpConfig_getSharedProcUnits(void)
-{
-       return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
-}
-//===============================================================
-static inline u64              HvLpConfig_getMinSharedProcUnits(void)
-{
-       return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Min);
-}
-//===============================================================
-static inline u64              HvLpConfig_getMaxSharedProcUnits(void)
-{
-       return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64              HvLpConfig_getMinPhysicalProcessors(void)
-{
-       return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Min);
-}
-//===============================================================
-static inline u64              HvLpConfig_getMinLogicalProcessors(void)
-{
-       return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Min) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64              HvLpConfig_getMaxPhysicalProcessors(void)
-{
-       return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64              HvLpConfig_getMaxLogicalProcessors(void)
-{
-       return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Max) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64              HvLpConfig_getInitPhysicalProcessors(void)
+
+static inline u64 HvLpConfig_getMsChunks(void)
 {
-       return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Init);
+       return HvCall2(HvCallCfgGetMsChunks, HvLpConfig_getLpIndex(),
+                       HvCallCfg_Cur);
 }
-//===============================================================
-static inline u64              HvLpConfig_getInitLogicalProcessors(void)
+
+static inline u64 HvLpConfig_getSystemPhysicalProcessors(void)
 {
-       return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Init) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
+       return HvCall0(HvCallCfgGetSystemPhysicalProcessors);
 }
-//================================================================
-static inline HvLpVirtualLanIndexMap   HvLpConfig_getVirtualLanIndexMap(void)
+
+static inline u64 HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
 {
-       return HvCallCfg_getVirtualLanIndexMap(HvLpConfig_getLpIndex_outline());
+       return (u16)HvCall1(HvCallCfgGetNumProcsInSharedPool, sPI);
 }
-//===============================================================
-static inline HvLpVirtualLanIndexMap   HvLpConfig_getVirtualLanIndexMapForLp(HvLpIndex lp)
+
+static inline u64 HvLpConfig_getPhysicalProcessors(void)
 {
-       return HvCallCfg_getVirtualLanIndexMap(lp);
+       return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(),
+                       HvCallCfg_Cur);
 }
-//================================================================
-static inline HvLpIndex        HvLpConfig_getBusOwner(HvBusNumber busNumber)
+
+static inline HvLpSharedPoolIndex HvLpConfig_getSharedPoolIndex(void)
 {
-       return HvCallCfg_getBusOwner(busNumber);
+       return HvCall1(HvCallCfgGetSharedPoolIndex, HvLpConfig_getLpIndex());
 }
-//===============================================================
-static inline int              HvLpConfig_isBusDedicated(HvBusNumber busNumber)
+
+static inline u64 HvLpConfig_getSharedProcUnits(void)
 {
-       return HvCallCfg_isBusDedicated(busNumber);
+       return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(),
+                       HvCallCfg_Cur);
 }
-//================================================================
-static inline HvLpIndexMap     HvLpConfig_getBusAllocation(HvBusNumber busNumber)
+
+static inline u64 HvLpConfig_getMaxSharedProcUnits(void)
 {
-       return HvCallCfg_getBusAllocation(busNumber);
+       return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(),
+                       HvCallCfg_Max);
 }
-//================================================================
-// returns the absolute real address of the load area
-static inline u64              HvLpConfig_getLoadAddress(void)
+
+static inline u64 HvLpConfig_getMaxPhysicalProcessors(void)
 {
-       return itLpNaca.xLoadAreaAddr & 0x7fffffffffffffff;
+       return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(),
+                       HvCallCfg_Max);
 }
-//================================================================
-static inline u64              HvLpConfig_getLoadPages(void)
-{
-       return itLpNaca.xLoadAreaChunks * HVPAGESPERCHUNK;
+
+static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMapForLp(
+               HvLpIndex lp)
+{
+       /*
+        * This is a new function in V5R1 so calls to this on older
+        * hypervisors will return -1
+        */
+       u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp);
+       if (retVal == -1)
+               retVal = 0;
+       return retVal;
 }
-//================================================================
-static inline int              HvLpConfig_isBusOwnedByThisLp(HvBusNumber busNumber)
+
+static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMap(void)
 {
-       HvLpIndex busOwner = HvLpConfig_getBusOwner(busNumber);
-       return (busOwner == HvLpConfig_getLpIndex());
+       return HvLpConfig_getVirtualLanIndexMapForLp(
+                       HvLpConfig_getLpIndex_outline());
 }
-//================================================================
-static inline int         HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1, HvLpIndex lp2)
+
+static inline int HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1,
+               HvLpIndex lp2)
 {
-       HvLpVirtualLanIndexMap virtualLanIndexMap1 = HvCallCfg_getVirtualLanIndexMap( lp1 );
-       HvLpVirtualLanIndexMap virtualLanIndexMap2 = HvCallCfg_getVirtualLanIndexMap( lp2 );
+       HvLpVirtualLanIndexMap virtualLanIndexMap1 =
+               HvLpConfig_getVirtualLanIndexMapForLp(lp1);
+       HvLpVirtualLanIndexMap virtualLanIndexMap2 =
+               HvLpConfig_getVirtualLanIndexMapForLp(lp2);
        return ((virtualLanIndexMap1 & virtualLanIndexMap2) != 0);
 }
-//================================================================
-static inline HvLpIndex                HvLpConfig_getHostingLpIndex(HvLpIndex lp)
+
+static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp)
 {
-       return HvCallCfg_getHostingLpIndex(lp);
+       return HvCall1(HvCallCfgGetHostingLpIndex, lp);
 }
-//================================================================
 
 #endif /* _HVLPCONFIG_H */
index 30936e433064a31c31d59db7f6f7eb3316510daa..865000de79b6fa3b4f56f39236297cc26dae6e44 100644 (file)
@@ -1,27 +1,24 @@
 /*
  * HvLpEvent.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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
  */
 
-//======================================================================
-//
-//     This file contains the class for HV events in the system.
-//
-//=====================================================================
+/* This file contains the class for HV events in the system. */
+
 #ifndef _HVLPEVENT_H
 #define _HVLPEVENT_H
 
 #include <asm/iSeries/HvTypes.h>
 #include <asm/iSeries/HvCallEvent.h>
 
-//=====================================================================
-//
-// HvLpEvent is the structure for Lp Event messages passed between
-// partitions through PLIC. 
-//
-//=====================================================================
-
-struct HvEventFlags
-{
-       u8      xValid:1;               // Indicates a valid request    x00-x00
-       u8      xRsvd1:4;               // Reserved                     ...
-       u8      xAckType:1;             // Immediate or deferred        ...
-       u8      xAckInd:1;              // Indicates if ACK required    ...
-       u8      xFunction:1;            // Interrupt or Acknowledge     ...
+/*
+ * HvLpEvent is the structure for Lp Event messages passed between
+ * partitions through PLIC.
+ */
+
+struct HvEventFlags {
+       u8      xValid:1;       /* Indicates a valid request    x00-x00 */
+       u8      xRsvd1:4;       /* Reserved                     ... */
+       u8      xAckType:1;     /* Immediate or deferred        ... */
+       u8      xAckInd:1;      /* Indicates if ACK required    ... */
+       u8      xFunction:1;    /* Interrupt or Acknowledge     ... */
 };
 
 
-struct HvLpEvent
-{
-       struct HvEventFlags xFlags;     // Event flags                  x00-x00
-       u8      xType;                  // Type of message              x01-x01
-       u16     xSubtype;               // Subtype for event            x02-x03
-       u8      xSourceLp;              // Source LP                    x04-x04
-       u8      xTargetLp;              // Target LP                    x05-x05
-       u8      xSizeMinus1;            // Size of Derived class - 1    x06-x06
-       u8      xRc;                    // RC for Ack flows             x07-x07
-       u16     xSourceInstanceId;      // Source sides instance id     x08-x09
-       u16     xTargetInstanceId;      // Target sides instance id     x0A-x0B
+struct HvLpEvent {
+       struct HvEventFlags xFlags;     /* Event flags                x00-x00 */
+       u8      xType;                  /* Type of message            x01-x01 */
+       u16     xSubtype;               /* Subtype for event          x02-x03 */
+       u8      xSourceLp;              /* Source LP                  x04-x04 */
+       u8      xTargetLp;              /* Target LP                  x05-x05 */
+       u8      xSizeMinus1;            /* Size of Derived class - 1  x06-x06 */
+       u8      xRc;                    /* RC for Ack flows           x07-x07 */
+       u16     xSourceInstanceId;      /* Source sides instance id   x08-x09 */
+       u16     xTargetInstanceId;      /* Target sides instance id   x0A-x0B */
        union {
-               u32     xSubtypeData;   // Data usable by the subtype   x0C-x0F
-               u16     xSubtypeDataShort[2];   // Data as 2 shorts
-               u8      xSubtypeDataChar[4];    // Data as 4 chars
+               u32     xSubtypeData;   /* Data usable by the subtype x0C-x0F */
+               u16     xSubtypeDataShort[2];   /* Data as 2 shorts */
+               u8      xSubtypeDataChar[4];    /* Data as 4 chars */
        } x;
 
-       u64     xCorrelationToken;      // Unique value for source/type x10-x17
+       u64     xCorrelationToken;      /* Unique value for source/type x10-x17 */
 };
 
-// Lp Event handler function
 typedef void (*LpEventHandler)(struct HvLpEvent *, struct pt_regs *);
 
-// Register a handler for an event type
-//  returns 0 on success
-extern int HvLpEvent_registerHandler( HvLpEvent_Type eventType, LpEventHandler hdlr);
-
-// Unregister a handler for an event type
-//  This call will sleep until the handler being removed is guaranteed to
-//  be no longer executing on any CPU. Do not call with locks held.
-//
-//  returns 0 on success
-//  Unregister will fail if there are any paths open for the type
-extern int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType );
+/* Register a handler for an event type - returns 0 on success */
+extern int HvLpEvent_registerHandler(HvLpEvent_Type eventType,
+               LpEventHandler hdlr);
 
-// Open an Lp Event Path for an event type
-//  returns 0 on success
-//  openPath will fail if there is no handler registered for the event type.
-//  The lpIndex specified is the partition index for the target partition
-//  (for VirtualIo, VirtualLan and SessionMgr) other types specify zero) 
-extern int HvLpEvent_openPath( HvLpEvent_Type eventType, HvLpIndex lpIndex );
+/*
+ * Unregister a handler for an event type
+ *
+ * This call will sleep until the handler being removed is guaranteed to
+ * be no longer executing on any CPU. Do not call with locks held.
+ *
+ *  returns 0 on success
+ *  Unregister will fail if there are any paths open for the type
+ */
+extern int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType);
 
+/*
+ * Open an Lp Event Path for an event type
+ * returns 0 on success
+ * openPath will fail if there is no handler registered for the event type.
+ * The lpIndex specified is the partition index for the target partition
+ * (for VirtualIo, VirtualLan and SessionMgr) other types specify zero)
+ */
+extern int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
 
-// Close an Lp Event Path for a type and partition
-//  returns 0 on sucess
-extern int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex );
+/*
+ * Close an Lp Event Path for a type and partition
+ * returns 0 on sucess
+ */
+extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
 
 #define HvLpEvent_Type_Hypervisor 0
 #define HvLpEvent_Type_MachineFac 1
@@ -141,4 +139,4 @@ extern int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex );
 #define HvLpDma_Rc_InvalidAddress 4
 #define HvLpDma_Rc_InvalidLength 5
 
-#endif // _HVLPEVENT_H
+#endif /* _HVLPEVENT_H */
index 183e5e738c26e405abcdf4d596c800bfe2dedc54..01a1f13ea4a0511959f9f4eeb5f97aa7f5b15f4a 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * HvReleaseData.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _HVRELEASEDATA_H
 #define _HVRELEASEDATA_H
 
-//=============================================================================
-//
-//   This control block contains the critical information about the 
-//   release so that it can be changed in the future (ie, the virtual 
-//   address of the OS's NACA).
-//
+/*
+ * This control block contains the critical information about the
+ * release so that it can be changed in the future (ie, the virtual
+ * address of the OS's NACA).
+ */
 #include <asm/types.h>
 #include <asm/naca.h>
 
-//=============================================================================
-//
-//     When we IPL a secondary partition, we will check if if the 
-//     secondary xMinPlicVrmIndex > the primary xVrmIndex.  
-//     If it is then this tells PLIC that this secondary is not 
-//     supported running on this "old" of a level of PLIC.
-//
-//     Likewise, we will compare the primary xMinSlicVrmIndex to 
-//     the secondary xVrmIndex. 
-//     If the primary xMinSlicVrmDelta > secondary xVrmDelta then we 
-//     know that this PLIC does not support running an OS "that old".
-//
-//=============================================================================
+/*
+ * When we IPL a secondary partition, we will check if if the
+ * secondary xMinPlicVrmIndex > the primary xVrmIndex.
+ * If it is then this tells PLIC that this secondary is not
+ * supported running on this "old" of a level of PLIC.
+ *
+ * Likewise, we will compare the primary xMinSlicVrmIndex to
+ * the secondary xVrmIndex.
+ * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we
+ * know that this PLIC does not support running an OS "that old".
+ */
 
-struct HvReleaseData
-{
-       u32     xDesc;                  // Descriptor   "HvRD" ebcdic   x00-x03
-       u16     xSize;                  // Size of this control block   x04-x05
-       u16     xVpdAreasPtrOffset;     // Offset in NACA of ItVpdAreas x06-x07
-       struct  naca_struct * xSlicNacaAddr; // Virt addr of SLIC NACA  x08-x0F
-       u32     xMsNucDataOffset;       // Offset of Linux Mapping Data x10-x13
-       u32     xRsvd1;                 // Reserved                     x14-x17
-       u16     xTagsMode:1;            // 0 == tags active, 1 == tags inactive
-       u16     xAddressSize:1;         // 0 == 64-bit, 1 == 32-bit
-       u16     xNoSharedProcs:1;       // 0 == shared procs, 1 == no shared
-       u16     xNoHMT:1;               // 0 == allow HMT, 1 == no HMT
-       u16     xRsvd2:12;              // Reserved                     x18-x19
-       u16     xVrmIndex;              // VRM Index of OS image        x1A-x1B
-       u16     xMinSupportedPlicVrmIndex;// Min PLIC level  (soft)     x1C-x1D
-       u16     xMinCompatablePlicVrmIndex;// Min PLIC levelP (hard)    x1E-x1F
-       char    xVrmName[12];           // Displayable name             x20-x2B
-       char    xRsvd3[20];             // Reserved                     x2C-x3F
+struct HvReleaseData {
+       u32     xDesc;          /* Descriptor "HvRD" ebcdic     x00-x03 */
+       u16     xSize;          /* Size of this control block   x04-x05 */
+       u16     xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */
+       struct  naca_struct     *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */
+       u32     xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */
+       u32     xRsvd1;         /* Reserved                     x14-x17 */
+       u16     xTagsMode:1;    /* 0 == tags active, 1 == tags inactive */
+       u16     xAddressSize:1; /* 0 == 64-bit, 1 == 32-bit */
+       u16     xNoSharedProcs:1; /* 0 == shared procs, 1 == no shared */
+       u16     xNoHMT:1;       /* 0 == allow HMT, 1 == no HMT */
+       u16     xRsvd2:12;      /* Reserved                     x18-x19 */
+       u16     xVrmIndex;      /* VRM Index of OS image        x1A-x1B */
+       u16     xMinSupportedPlicVrmIndex; /* Min PLIC level  (soft) x1C-x1D */
+       u16     xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */
+       char    xVrmName[12];   /* Displayable name             x20-x2B */
+       char    xRsvd3[20];     /* Reserved                     x2C-x3F */
 };
 
+extern struct HvReleaseData    hvReleaseData;
+
 #endif /* _HVRELEASEDATA_H */
index 3ec49c1aec328c5e846fe9f3f2acaa82096a2152..b1ef2b4cb3e3de084f67e2c6d5a440a82a448b2d 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * HvTypes.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _HVTYPES_H
 #define _HVTYPES_H
 
-//===========================================================================
-//                                                             Header File Id
-// Name______________:  HvTypes.H
-//
-// Description_______:
-//
-//     General typedefs for the hypervisor.
-//
-// Declared Class(es):
-//
-//===========================================================================
+/*
+ * General typedefs for the hypervisor.
+ */
 
 #include <asm/types.h>
 
-//-------------------------------------------------------------------
-// Typedefs
-//-------------------------------------------------------------------
 typedef u8     HvLpIndex;
 typedef u16    HvLpInstanceId;
-typedef u64     HvLpTOD;
-typedef u64     HvLpSystemSerialNum;
-typedef u8      HvLpDeviceSerialNum[12];
-typedef u16     HvLpSanHwSet;
-typedef u16     HvLpBus;
-typedef u16     HvLpBoard;
-typedef u16     HvLpCard;
-typedef u8      HvLpDeviceType[4];
-typedef u8      HvLpDeviceModel[3];
-typedef u64     HvIoToken;
-typedef u8      HvLpName[8];
+typedef u64    HvLpTOD;
+typedef u64    HvLpSystemSerialNum;
+typedef u8     HvLpDeviceSerialNum[12];
+typedef u16    HvLpSanHwSet;
+typedef u16    HvLpBus;
+typedef u16    HvLpBoard;
+typedef u16    HvLpCard;
+typedef u8     HvLpDeviceType[4];
+typedef u8     HvLpDeviceModel[3];
+typedef u64    HvIoToken;
+typedef u8     HvLpName[8];
 typedef u32    HvIoId;
 typedef u64    HvRealMemoryIndex;
-typedef u32     HvLpIndexMap;          // Must hold HvMaxArchitectedLps bits!!!
+typedef u32    HvLpIndexMap;   /* Must hold HVMAXARCHITECTEDLPS bits!!! */
 typedef u16    HvLpVrmIndex;
 typedef u32    HvXmGenerationId;
-typedef u8     HvLpBusPool;                    
-typedef u8     HvLpSharedPoolIndex;            
+typedef u8     HvLpBusPool;
+typedef u8     HvLpSharedPoolIndex;
 typedef u16    HvLpSharedProcUnitsX100;
 typedef u8     HvLpVirtualLanIndex;
-typedef u16    HvLpVirtualLanIndexMap; // Must hold HvMaxArchitectedVirtualLans bits!!!
-typedef u16    HvBusNumber;            // Hypervisor Bus Number
-typedef u8     HvSubBusNumber;         // Hypervisor SubBus Number
-typedef u8     HvAgentId;              // Hypervisor DevFn
+typedef u16    HvLpVirtualLanIndexMap; /* Must hold HVMAXARCHITECTEDVIRTUALLANS bits!!! */
+typedef u16    HvBusNumber;    /* Hypervisor Bus Number */
+typedef u8     HvSubBusNumber; /* Hypervisor SubBus Number */
+typedef u8     HvAgentId;      /* Hypervisor DevFn */
+
 
+#define HVMAXARCHITECTEDLPS            32
+#define HVMAXARCHITECTEDVIRTUALLANS    16
+#define HVMAXARCHITECTEDVIRTUALDISKS   32
+#define HVMAXARCHITECTEDVIRTUALCDROMS  8
+#define HVMAXARCHITECTEDVIRTUALTAPES   8
+#define HVCHUNKSIZE                    (256 * 1024)
+#define HVPAGESIZE                     (4 * 1024)
+#define HVLPMINMEGSPRIMARY             256
+#define HVLPMINMEGSSECONDARY           64
+#define HVCHUNKSPERMEG                 4
+#define HVPAGESPERMEG                  256
+#define HVPAGESPERCHUNK                        64
 
-#define HVMAXARCHITECTEDLPS 32
-#define HVMAXARCHITECTEDVIRTUALLANS 16
-#define HVMAXARCHITECTEDVIRTUALDISKS 32
-#define HVMAXARCHITECTEDVIRTUALCDROMS 8
-#define HVMAXARCHITECTEDVIRTUALTAPES 8
-#define HVCHUNKSIZE 256 * 1024
-#define HVPAGESIZE 4 * 1024
-#define HVLPMINMEGSPRIMARY 256
-#define HVLPMINMEGSSECONDARY 64
-#define HVCHUNKSPERMEG 4
-#define HVPAGESPERMEG 256
-#define HVPAGESPERCHUNK 64
-#define HvMaxArchitectedLps            ((HvLpIndex)HVMAXARCHITECTEDLPS)
-#define HvMaxArchitectedVirtualLans    ((HvLpVirtualLanIndex)16)
 #define HvLpIndexInvalid               ((HvLpIndex)0xff)
 
-//--------------------------------------------------------------------
-// Enums for the sub-components under PLIC
-// Used in HvCall  and HvPrimaryCall
-//--------------------------------------------------------------------
-enum   HvCallCompIds
-{
+/*
+ * Enums for the sub-components under PLIC
+ * Used in HvCall  and HvPrimaryCall
+ */
+enum {
        HvCallCompId = 0,
        HvCallCpuCtlsCompId = 1,
        HvCallCfgCompId = 2,
@@ -97,18 +83,18 @@ enum   HvCallCompIds
        HvCallSmCompId = 7,
        HvCallSpdCompId = 8,
        HvCallXmCompId = 9,
-       HvCallRioCompId = 10, 
+       HvCallRioCompId = 10,
        HvCallRsvd3CompId = 11,
        HvCallRsvd2CompId = 12,
        HvCallRsvd1CompId = 13,
        HvCallMaxCompId = 14,
-       HvPrimaryCallCompId = 0,    
+       HvPrimaryCallCompId = 0,
        HvPrimaryCallCfgCompId = 1,
-       HvPrimaryCallPciCompId = 2,    
+       HvPrimaryCallPciCompId = 2,
        HvPrimaryCallSmCompId = 3,
        HvPrimaryCallSpdCompId = 4,
        HvPrimaryCallXmCompId = 5,
-       HvPrimaryCallRioCompId = 6, 
+       HvPrimaryCallRioCompId = 6,
        HvPrimaryCallRsvd7CompId = 7,
        HvPrimaryCallRsvd6CompId = 8,
        HvPrimaryCallRsvd5CompId = 9,
@@ -116,7 +102,7 @@ enum   HvCallCompIds
        HvPrimaryCallRsvd3CompId = 11,
        HvPrimaryCallRsvd2CompId = 12,
        HvPrimaryCallRsvd1CompId = 13,
-       HvPrimaryCallMaxCompId = HvCallMaxCompId     
+       HvPrimaryCallMaxCompId = HvCallMaxCompId
 };
 
 struct HvLpBufferList {
index ff00e865f620553b81efcc83e618fbca2bb7c31f..45ed3ea67d060facbad6575a9327df80a3cfac1d 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * IoHriMainStore.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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
@@ -21,7 +21,7 @@
 #define _IOHRIMAINSTORE_H
 
 /* Main Store Vpd for Condor,iStar,sStar */
-struct IoHriMainStoreSegment4 {    
+struct IoHriMainStoreSegment4 {
        u8      msArea0Exists:1;
        u8      msArea1Exists:1;
        u8      msArea2Exists:1;
@@ -51,7 +51,7 @@ struct IoHriMainStoreSegment4 {
        u8      msArea1HasRiserVpd:1;
        u8      msArea2HasRiserVpd:1;
        u8      msArea3HasRiserVpd:1;
-       u8      reserved5:4;    
+       u8      reserved5:4;
        u8      reserved6;
        u16     reserved7;
 
@@ -82,8 +82,8 @@ struct IoHriMainStoreVpdFruData {
 };
 
 struct IoHriMainStoreAdrRangeBlock {
-       void *  blockStart      __attribute((packed));
-       void *  blockEnd        __attribute((packed));
+       void    *blockStart      __attribute((packed));
+       void    *blockEnd        __attribute((packed));
        u32     blockProcChipId __attribute((packed));
 };
 
@@ -102,7 +102,7 @@ struct IoHriMainStoreArea4 {
        u32     procNodeId                      __attribute((packed));
 
        u32     numAdrRangeBlocks               __attribute((packed));
-       struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed));
+       struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks]        __attribute((packed));
 
        struct IoHriMainStoreChipInfo1  chipInfo0       __attribute((packed));
        struct IoHriMainStoreChipInfo1  chipInfo1       __attribute((packed));
@@ -113,17 +113,17 @@ struct IoHriMainStoreArea4 {
        struct IoHriMainStoreChipInfo1  chipInfo6       __attribute((packed));
        struct IoHriMainStoreChipInfo1  chipInfo7       __attribute((packed));
 
-       void *   msRamAreaArray                 __attribute((packed));
+       void    *msRamAreaArray                 __attribute((packed));
        u32     msRamAreaArrayNumEntries        __attribute((packed));
        u32     msRamAreaArrayEntrySize         __attribute((packed));
 
        u32     numaDimmExists                  __attribute((packed));
        u32     numaDimmFunctional              __attribute((packed));
-       void *  numaDimmArray                   __attribute((packed));
+       void    *numaDimmArray                  __attribute((packed));
        u32     numaDimmArrayNumEntries         __attribute((packed));
        u32     numaDimmArrayEntrySize          __attribute((packed));
 
-       struct IoHriMainStoreVpdIdData  idData  __attribute((packed));
+       struct IoHriMainStoreVpdIdData idData   __attribute((packed));
 
        u64     powerData                       __attribute((packed));
        u64     cardAssemblyPartNum             __attribute((packed));
@@ -143,7 +143,7 @@ struct IoHriMainStoreArea4 {
 };
 
 
-struct IoHriMainStoreSegment5 {    
+struct IoHriMainStoreSegment5 {
        u16     reserved1;
        u8      reserved2;
        u8      msVpdFormat;
@@ -151,17 +151,16 @@ struct IoHriMainStoreSegment5 {
        u32     totalMainStore;
        u64     maxConfiguredMsAdr;
 
-       struct IoHriMainStoreArea4*     msAreaArray;
+       struct IoHriMainStoreArea4      *msAreaArray;
        u32     msAreaArrayNumEntries;
        u32     msAreaArrayEntrySize;
 
-       u32     msAreaExists;    
+       u32     msAreaExists;
        u32     msAreaFunctional;
 
        u64     reserved3;
 };
 
+extern u64     xMsVpd[];
 
-
-#endif // _IOHRIMAINSTORE_H
-
+#endif /* _IOHRIMAINSTORE_H */
index 96543388865343697c60228a1256e60cdfd56619..73b73d80b8b11fb980108ae757fc5771a645f1fd 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * IoHriProcessorVpd.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _IOHRIPROCESSORVPD_H
 #define _IOHRIPROCESSORVPD_H
 
-//===================================================================
-//
-//     This struct maps Processor Vpd that is DMAd to SLIC by CSP 
-//
-
 #include <asm/types.h>
 
-struct IoHriProcessorVpd
-{
-
+/*
+ * This struct maps Processor Vpd that is DMAd to SLIC by CSP
+ */
+struct IoHriProcessorVpd {
        u8      xFormat;                // VPD format indicator         x00-x00
        u8      xProcStatus:8;          // Processor State              x01-x01
        u8      xSecondaryThreadCount;  // Secondary thread cnt         x02-x02
@@ -40,12 +36,12 @@ struct IoHriProcessorVpd
        u16     xRsvd2;                 // Reserved                     x06-x07
        u32     xHwNodeId;              // Hardware node id             x08-x0B
        u32     xHwProcId;              // Hardware processor id        x0C-x0F
-       
+
        u32     xTypeNum;               // Card Type/CCIN number        x10-x13
        u32     xModelNum;              // Model/Feature number         x14-x17
        u64     xSerialNum;             // Serial number                x18-x1F
-       char xPartNum[12];              // Book Part or FPU number      x20-x2B
-       char xMfgID[4];                 // Manufacturing ID             x2C-x2F
+       char    xPartNum[12];           // Book Part or FPU number      x20-x2B
+       char    xMfgID[4];              // Manufacturing ID             x2C-x2F
 
        u32     xProcFreq;              // Processor Frequency          x30-x33
        u32     xTimeBaseFreq;          // Time Base Frequency          x34-x37
@@ -71,7 +67,7 @@ struct IoHriProcessorVpd
        u32     xDataL3CacheSizeKB;     // L3 data cache size in KB     x80-x83
        u32     xDataL3CacheLineSize;   // L3 data cache block size     x84-x87
        u64     xRsvd6;                 // Reserved                     x88-x8F
-   
+
        u64     xFruLabel;              // Card Location Label          x90-x97
        u8      xSlotsOnCard;           // Slots on card (0=no slots)   x98-x98
        u8      xPartLocFlag;           // Location flag (0-pluggable 1-imbedded) x99-x99
@@ -79,10 +75,12 @@ struct IoHriProcessorVpd
        u8      xSmartCardPortNo;       // Smart card port number       x9C-x9C
        u8      xRsvd7;                 // Reserved                     x9D-x9D
        u16     xFrameIdAndRackUnit;    // Frame ID and rack unit adr   x9E-x9F
-    
+
        u8      xRsvd8[24];             // Reserved                     xA0-xB7
 
-       char xProcSrc[72];              // CSP format SRC               xB8-xFF
+       char    xProcSrc[72];           // CSP format SRC               xB8-xFF
 };
 
+extern struct IoHriProcessorVpd        xIoHriProcessorVpd[];
+
 #endif /* _IOHRIPROCESSORVPD_H */
index dee6b1273031168cace691849adafe3cf9c80df4..4c546a8802b4cfc55237851f54f253617e6acbed 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * ItExtVpdPanel.h
  * Copyright (C) 2002  Dave Boutcher IBM Corporation
- * 
+ *
  * 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
 #define _ITEXTVPDPANEL_H
 
 /*
- *
- *     This struct maps the panel information 
+ *     This struct maps the panel information
  *
  * Warning:
  *     This data must match the architecture for the panel information
- *
  */
 
-
-/*-------------------------------------------------------------------
- * Standard Includes
- *------------------------------------------------------------------- 
-*/
 #include <asm/types.h>
 
-struct ItExtVpdPanel
-{
-  // Definition of the Extended Vpd On Panel Data Area
-  char                      systemSerial[8];
-  char                      mfgID[4];
-  char                      reserved1[24];
-  char                      machineType[4];
-  char                      systemID[6];
-  char                      somUniqueCnt[4];
-  char                      serialNumberCount;
-  char                      reserved2[7];
-  u16                       bbu3;
-  u16                       bbu2;
-  u16                       bbu1;
-  char                      xLocationLabel[8];
-  u8                        xRsvd1[6];
-  u16                       xFrameId;
-  u8                        xRsvd2[48];
+struct ItExtVpdPanel {
+       /* Definition of the Extended Vpd On Panel Data Area */
+       char    systemSerial[8];
+       char    mfgID[4];
+       char    reserved1[24];
+       char    machineType[4];
+       char    systemID[6];
+       char    somUniqueCnt[4];
+       char    serialNumberCount;
+       char    reserved2[7];
+       u16     bbu3;
+       u16     bbu2;
+       u16     bbu1;
+       char    xLocationLabel[8];
+       u8      xRsvd1[6];
+       u16     xFrameId;
+       u8      xRsvd2[48];
 };
 
-#endif /* _ITEXTVPDPANEL_H  */
+extern struct ItExtVpdPanel    xItExtVpdPanel;
+
+#endif /* _ITEXTVPDPANEL_H */
index 4d8b430ab12d9fec6fff8f5b482d1c0ebc9dd216..ae3417dc599e571da52621fceac99e904fc4b616 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * ItIplParmsReal.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _ITIPLPARMSREAL_H
 #define _ITIPLPARMSREAL_H
 
-//==============================================================================
-//
-//     This struct maps the IPL Parameters DMA'd from the SP.                  
-//
-// Warning:
-//     This data must map in exactly 64 bytes and match the architecture for
-//     the IPL parms
-//
-//=============================================================================
-
+/*
+ *     This struct maps the IPL Parameters DMA'd from the SP.
+ *
+ * Warning:
+ *     This data must map in exactly 64 bytes and match the architecture for
+ *     the IPL parms
+ */
 
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
 #include <asm/types.h>
 
-struct ItIplParmsReal
-{
-       u8      xFormat;                // Defines format of IplParms           x00-x00
-       u8      xRsvd01:6;              // Reserved                             x01-x01
-       u8      xAlternateSearch:1;     // Alternate search indicator           ...
-       u8      xUaSupplied:1;          // UA Supplied on programmed IPL        ...
-       u8      xLsUaFormat;            // Format byte for UA                   x02-x02
-       u8      xRsvd02;                // Reserved                             x03-x03
-       u32     xLsUa;                  // LS UA                                x04-x07
-       u32     xUnusedLsLid;           // First OS LID to load                 x08-x0B
-       u16     xLsBusNumber;           // LS Bus Number                        x0C-x0D
-       u8      xLsCardAdr;             // LS Card Address                      x0E-x0E
-       u8      xLsBoardAdr;            // LS Board Address                     x0F-x0F
-       u32     xRsvd03;                // Reserved                             x10-x13
-       u8      xSpcnPresent:1;         // SPCN present                         x14-x14
-       u8      xCpmPresent:1;          // CPM present                          ...
-       u8      xRsvd04:6;              // Reserved                             ...
-       u8      xRsvd05:4;              // Reserved                             x15-x15
-       u8      xKeyLock:4;             // Keylock setting                      ...
-       u8      xRsvd06:6;              // Reserved                             x16-x16
-       u8      xIplMode:2;             // Ipl mode (A|B|C|D)                   ...
-       u8      xHwIplType;             // Fast v slow v slow EC HW IPL         x17-x17
-       u16     xCpmEnabledIpl:1;       // CPM in effect when IPL initiated     x18-x19
-       u16     xPowerOnResetIpl:1;     // Indicate POR condition               ...
-       u16     xMainStorePreserved:1;  // Main Storage is preserved            ...
-       u16     xRsvd07:13;             // Reserved                             ...
-       u16     xIplSource:16;          // Ipl source                           x1A-x1B
-       u8      xIplReason:8;           // Reason for this IPL                  x1C-x1C
-       u8      xRsvd08;                // Reserved                             x1D-x1D
-       u16     xRsvd09;                // Reserved                             x1E-x1F
-       u16     xSysBoxType;            // System Box Type                      x20-x21
-       u16     xSysProcType;           // System Processor Type                x22-x23
-       u32     xRsvd10;                // Reserved                             x24-x27
-       u64     xRsvd11;                // Reserved                             x28-x2F
-       u64     xRsvd12;                // Reserved                             x30-x37
-       u64     xRsvd13;                // Reserved                             x38-x3F
+struct ItIplParmsReal {
+       u8      xFormat;                // Defines format of IplParms   x00-x00
+       u8      xRsvd01:6;              // Reserved                     x01-x01
+       u8      xAlternateSearch:1;     // Alternate search indicator   ...
+       u8      xUaSupplied:1;          // UA Supplied on programmed IPL...
+       u8      xLsUaFormat;            // Format byte for UA           x02-x02
+       u8      xRsvd02;                // Reserved                     x03-x03
+       u32     xLsUa;                  // LS UA                        x04-x07
+       u32     xUnusedLsLid;           // First OS LID to load         x08-x0B
+       u16     xLsBusNumber;           // LS Bus Number                x0C-x0D
+       u8      xLsCardAdr;             // LS Card Address              x0E-x0E
+       u8      xLsBoardAdr;            // LS Board Address             x0F-x0F
+       u32     xRsvd03;                // Reserved                     x10-x13
+       u8      xSpcnPresent:1;         // SPCN present                 x14-x14
+       u8      xCpmPresent:1;          // CPM present                  ...
+       u8      xRsvd04:6;              // Reserved                     ...
+       u8      xRsvd05:4;              // Reserved                     x15-x15
+       u8      xKeyLock:4;             // Keylock setting              ...
+       u8      xRsvd06:6;              // Reserved                     x16-x16
+       u8      xIplMode:2;             // Ipl mode (A|B|C|D)           ...
+       u8      xHwIplType;             // Fast v slow v slow EC HW IPL x17-x17
+       u16     xCpmEnabledIpl:1;       // CPM in effect when IPL initiatedx18-x19
+       u16     xPowerOnResetIpl:1;     // Indicate POR condition       ...
+       u16     xMainStorePreserved:1;  // Main Storage is preserved    ...
+       u16     xRsvd07:13;             // Reserved                     ...
+       u16     xIplSource:16;          // Ipl source                   x1A-x1B
+       u8      xIplReason:8;           // Reason for this IPL          x1C-x1C
+       u8      xRsvd08;                // Reserved                     x1D-x1D
+       u16     xRsvd09;                // Reserved                     x1E-x1F
+       u16     xSysBoxType;            // System Box Type              x20-x21
+       u16     xSysProcType;           // System Processor Type        x22-x23
+       u32     xRsvd10;                // Reserved                     x24-x27
+       u64     xRsvd11;                // Reserved                     x28-x2F
+       u64     xRsvd12;                // Reserved                     x30-x37
+       u64     xRsvd13;                // Reserved                     x38-x3F
 };
 
+extern struct ItIplParmsReal   xItIplParmsReal;
+
 #endif /* _ITIPLPARMSREAL_H */
index 5baffddfae1beaec66954fa41ee4163f3e777f78..225d0176779da8203aa464e55098715fd566b817 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * ItLpNaca.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _ITLPNACA_H
 #define _ITLPNACA_H
 
-//=============================================================================
-//
-//     This control block contains the data that is shared between the
-//     hypervisor (PLIC) and the OS.
-//
-//=============================================================================
+#include <linux/types.h>
 
-struct ItLpNaca
-{
-//=============================================================================
+/*
+ *     This control block contains the data that is shared between the
+ *     hypervisor (PLIC) and the OS.
+ */
+
+struct ItLpNaca {
 // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data
-//=============================================================================
        u32     xDesc;                  // Eye catcher                  x00-x03
        u16     xSize;                  // Size of this class           x04-x05
        u16     xIntHdlrOffset;         // Offset to IntHdlr array      x06-x07
@@ -59,30 +56,25 @@ struct ItLpNaca
        u64     xLoadAreaAddr;          // ER address of load area      x28-x2F
        u32     xLoadAreaChunks;        // Chunks for the load area     x30-x33
        u32     xPaseSysCallCRMask;     // Mask used to test CR before  x34-x37
-       // doing an ASR switch on PASE
-       // system call.
-       u64     xSlicSegmentTablePtr;   // Pointer to Slic seg table.   x38-x3f
-       u8      xRsvd1_4[64];           //                              x40-x7F 
-   
-//=============================================================================
+                                       // doing an ASR switch on PASE
+                                       // system call.
+       u64     xSlicSegmentTablePtr;   // Pointer to Slic seg table.   x38-x3f
+       u8      xRsvd1_4[64];           //                              x40-x7F
+
 // CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data
-//=============================================================================
        u8      xRsvd2_0[128];          // Reserved                     x00-x7F
 
-//=============================================================================
 // CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators
-// NB: Padding required to keep xInterrruptHdlr at x300 which is required 
+// NB: Padding required to keep xInterrruptHdlr at x300 which is required
 // for v4r4 PLIC.
-//=============================================================================
        u8      xOldLpQueue[128];       // LP Queue needed for v4r4     100-17F
        u8      xRsvd3_0[384];          // Reserved                     180-2FF
-//=============================================================================
+
 // CACHE_LINE_7-8 0x0300 - 0x03FF Contains the address of the OS interrupt
 //  handlers
-//=============================================================================
        u64     xInterruptHdlr[32];     // Interrupt handlers           300-x3FF
 };
 
-//=============================================================================
+extern struct ItLpNaca         itLpNaca;
 
 #endif /* _ITLPNACA_H */
index 4f4dde2a638d50364b8c2192e17bbc5d8ab92378..393299e04d7fcf713915815d74fcba66888f09f0 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * ItLpQueue.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _ITLPQUEUE_H
 #define _ITLPQUEUE_H
 
-//=============================================================================
-//
-//     This control block defines the simple LP queue structure that is 
-//     shared between the hypervisor (PLIC) and the OS in order to send 
-//     events to an LP.  
-//    
+/*
+ *     This control block defines the simple LP queue structure that is
+ *     shared between the hypervisor (PLIC) and the OS in order to send
+ *     events to an LP.
+ */
 
 #include <asm/types.h>
 #include <asm/ptrace.h>
 
 struct HvLpEvent;
 
-#define ITMaxLpQueues 8
+#define ITMaxLpQueues  8
 
 #define NotUsed                0       // Queue will not be used by PLIC
 #define DedicatedIo    1       // Queue dedicated to IO processor specified
 #define DedicatedLp    2       // Queue dedicated to LP specified
 #define Shared         3       // Queue shared for both IO and LP
 
-#define LpEventStackSize 4096
-#define LpEventMaxSize   256
-#define LpEventAlign    64
+#define LpEventStackSize       4096
+#define LpEventMaxSize         256
+#define LpEventAlign           64
 
-struct ItLpQueue
-{
-//
-//  The xSlicCurEventPtr is the pointer to the next event stack entry that will
-//  become valid.  The OS must peek at this entry to determine if it is valid.
-//  PLIC will set the valid indicator as the very last store into that entry.
-//
-//  When the OS has completed processing of the event then it will mark the event
-//  as invalid so that PLIC knows it can store into that event location again.
-//
-// If the event stack fills and there are overflow events, then PLIC will set 
-// the xPlicOverflowIntPending flag in which case the OS will have to fetch the 
-// additional LP events once they have drained the event stack.
-//
-// The first 16-bytes are known by both the OS and PLIC.  The remainder of the
-// cache line is for use by the OS.
-//
-//=============================================================================
+struct ItLpQueue {
+/*
+ * The xSlicCurEventPtr is the pointer to the next event stack entry
+ * that will become valid.  The OS must peek at this entry to determine
+ * if it is valid.  PLIC will set the valid indicator as the very last
+ * store into that entry.
+ *
+ * When the OS has completed processing of the event then it will mark
+ * the event as invalid so that PLIC knows it can store into that event
+ * location again.
+ *
+ * If the event stack fills and there are overflow events, then PLIC
+ * will set the xPlicOverflowIntPending flag in which case the OS will
+ * have to fetch the additional LP events once they have drained the
+ * event stack.
+ *
+ * The first 16-bytes are known by both the OS and PLIC.  The remainder
+ * of the cache line is for use by the OS.
+ */
        u8      xPlicOverflowIntPending;// 0x00 Overflow events are pending
        u8      xPlicStatus;            // 0x01 DedicatedIo or DedicatedLp or NotUsed
        u16     xSlicLogicalProcIndex;  // 0x02 Logical Proc Index for correlation
        u8      xPlicRsvd[12];          // 0x04
-       char*   xSlicCurEventPtr;       // 0x10
-       char*   xSlicLastValidEventPtr; // 0x18
-       char*   xSlicEventStackPtr;     // 0x20
+       char    *xSlicCurEventPtr;      // 0x10
+       char    *xSlicLastValidEventPtr; // 0x18
+       char    *xSlicEventStackPtr;    // 0x20
        u8      xIndex;                 // 0x28 unique sequential index.
        u8      xSlicRsvd[3];           // 0x29-2b
        u32     xInUseWord;             // 0x2C
@@ -76,17 +76,9 @@ struct ItLpQueue
 
 extern struct ItLpQueue xItLpQueue;
 
-extern struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * );
-extern int ItLpQueue_isLpIntPending( struct ItLpQueue * ); 
-extern unsigned ItLpQueue_process( struct ItLpQueue *, struct pt_regs * );
-extern void ItLpQueue_clearValid( struct HvLpEvent * );
-
-static __inline__ void process_iSeries_events( void )
-{
-       __asm__ __volatile__ (
-       "       li      0,0x5555        \n\
-               sc"
-       : : : "r0", "r3" );     
-}
+extern struct HvLpEvent *ItLpQueue_getNextLpEvent(struct ItLpQueue *);
+extern int ItLpQueue_isLpIntPending(struct ItLpQueue *);
+extern unsigned ItLpQueue_process(struct ItLpQueue *, struct pt_regs *);
+extern void ItLpQueue_clearValid(struct HvLpEvent *);
 
 #endif /* _ITLPQUEUE_H */
index dafc4c8137883158c51bc8b3478a03dd942fdbc3..1b3087e76205371e4d7e23e7b4bf4c18216b5234 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * ItLpRegSave.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _ITLPREGSAVE_H
 #define _ITLPREGSAVE_H
 
-//=====================================================================================
-//
-//     This control block contains the data that is shared between PLIC
-//     and the OS
-//    
-//
+/*
+ * This control block contains the data that is shared between PLIC
+ * and the OS
+ */
 
-struct ItLpRegSave
-{
+struct ItLpRegSave {
        u32     xDesc;          // Eye catcher  "LpRS" ebcdic   000-003
        u16     xSize;          // Size of this class           004-005
        u8      xInUse;         // Area is live                 006-007
-       u8      xRsvd1[9];      // Reserved                     007-00F
+       u8      xRsvd1[9];      // Reserved                     007-00F
 
-       u8      xFixedRegSave[352]; // Fixed Register Save Area 010-16F 
+       u8      xFixedRegSave[352]; // Fixed Register Save Area 010-16F
        u32     xCTRL;          // Control Register             170-173
-       u32     xDEC;           // Decrementer                  174-177    
+       u32     xDEC;           // Decrementer                  174-177
        u32     xFPSCR;         // FP Status and Control Reg    178-17B
        u32     xPVR;           // Processor Version Number     17C-17F
-    
+
        u64     xMMCR0;         // Monitor Mode Control Reg 0   180-187
        u32     xPMC1;          // Perf Monitor Counter 1       188-18B
        u32     xPMC2;          // Perf Monitor Counter 2       18C-18F
        u32     xPMC3;          // Perf Monitor Counter 3       190-193
        u32     xPMC4;          // Perf Monitor Counter 4       194-197
        u32     xPIR;           // Processor ID Reg             198-19B
-    
+
        u32     xMMCR1;         // Monitor Mode Control Reg 1   19C-19F
        u32     xMMCRA;         // Monitor Mode Control Reg A   1A0-1A3
        u32     xPMC5;          // Perf Monitor Counter 5       1A4-1A7
@@ -57,17 +54,17 @@ struct ItLpRegSave
        u32     xRsvd;          // Reserved                     1BC-1BF
 
        u64     xACCR;          // Address Compare Control Reg  1C0-1C7
-       u64     xIMR;           // Instruction Match Register   1C8-1CF    
-       u64     xSDR1;          // Storage Description Reg 1    1D0-1D7    
+       u64     xIMR;           // Instruction Match Register   1C8-1CF
+       u64     xSDR1;          // Storage Description Reg 1    1D0-1D7
        u64     xSPRG0;         // Special Purpose Reg General0 1D8-1DF
        u64     xSPRG1;         // Special Purpose Reg General1 1E0-1E7
        u64     xSPRG2;         // Special Purpose Reg General2 1E8-1EF
        u64     xSPRG3;         // Special Purpose Reg General3 1F0-1F7
        u64     xTB;            // Time Base Register           1F8-1FF
-   
+
        u64     xFPR[32];       // Floating Point Registers     200-2FF
 
-       u64     xMSR;           // Machine State Register       300-307
+       u64     xMSR;           // Machine State Register       300-307
        u64     xNIA;           // Next Instruction Address     308-30F
 
        u64     xDABR;          // Data Address Breakpoint Reg  310-317
@@ -76,8 +73,8 @@ struct ItLpRegSave
        u64     xHID0;          // HW Implementation Dependent0 320-327
 
        u64     xHID4;          // HW Implementation Dependent4 328-32F
-       u64     xSCOMd;         // SCON Data Reg (SPRG4)        330-337
-       u64     xSCOMc;         // SCON Command Reg (SPRG5)     338-33F
+       u64     xSCOMd;         // SCON Data Reg (SPRG4)        330-337
+       u64     xSCOMc;         // SCON Command Reg (SPRG5)     338-33F
        u64     xSDAR;          // Sample Data Address Register 340-347
        u64     xSIAR;          // Sample Inst Address Register 348-34F
 
index f1b56f9e11e2ea0225df05184bb4c8d45b523126..5535f8271c9f0bc139876014f6577b21ee53a793 100644 (file)
@@ -1,29 +1,27 @@
 /*
  * ItSpCommArea.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _ITSPCOMMAREA_H
 #define _ITSPCOMMAREA_H
 
 
-struct SpCommArea
-{
+struct SpCommArea {
        u32     xDesc;                  // Descriptor (only in new formats)     000-003
        u8      xFormat;                // Format (only in new formats)         004-004
        u8      xRsvd1[11];             // Reserved                             005-00F
index d120439f30a5e8b882b4cbeb39eae1a9b5fcbf6f..71b3ad24f95a6e4b0f0469ffc443140310446e2e 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * ItVpdAreas.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 _ITVPDAREAS_H
 #define _ITVPDAREAS_H
 
-//=====================================================================================
-//
-//      This file defines the address and length of all of the VPD area passed to
-//     the OS from PLIC (most of which start from the SP).
-//
+/*
+ * This file defines the address and length of all of the VPD area passed to
+ * the OS from PLIC (most of which start from the SP).
+ */
 
 #include <asm/types.h>
 
-// VPD Entry index is carved in stone - cannot be changed (easily).
-#define ItVpdCecVpd                               0
-#define ItVpdDynamicSpace                         1
-#define ItVpdExtVpd                               2
-#define ItVpdExtVpdOnPanel                        3
-#define ItVpdFirstPaca                            4
-#define ItVpdIoVpd                                5
-#define ItVpdIplParms                             6
-#define ItVpdMsVpd                                7
-#define ItVpdPanelVpd                             8
-#define ItVpdLpNaca                               9
-#define ItVpdBackplaneAndMaybeClockCardVpd        10 
-#define ItVpdRecoveryLogBuffer                   11
-#define ItVpdSpCommArea                                  12
-#define ItVpdSpLogBuffer                         13
-#define ItVpdSpLogBufferSave                     14
-#define ItVpdSpCardVpd                           15
-#define ItVpdFirstProcVpd                        16    
-#define ItVpdApModelVpd                                  17
-#define ItVpdClockCardVpd                        18
-#define ItVpdBusExtCardVpd                       19
-#define ItVpdProcCapacityVpd                     20
-#define ItVpdInteractiveCapacityVpd              21
-#define ItVpdFirstSlotLabel                      22
-#define ItVpdFirstLpQueue                        23
-#define ItVpdFirstL3CacheVpd                     24    
-#define ItVpdFirstProcFruVpd                     25
-
-#define ItVpdMaxEntries                                  26
+/* VPD Entry index is carved in stone - cannot be changed (easily). */
+#define ItVpdCecVpd                            0
+#define ItVpdDynamicSpace                      1
+#define ItVpdExtVpd                            2
+#define ItVpdExtVpdOnPanel                     3
+#define ItVpdFirstPaca                         4
+#define ItVpdIoVpd                             5
+#define ItVpdIplParms                          6
+#define ItVpdMsVpd                             7
+#define ItVpdPanelVpd                          8
+#define ItVpdLpNaca                            9
+#define ItVpdBackplaneAndMaybeClockCardVpd     10
+#define ItVpdRecoveryLogBuffer                 11
+#define ItVpdSpCommArea                                12
+#define ItVpdSpLogBuffer                       13
+#define ItVpdSpLogBufferSave                   14
+#define ItVpdSpCardVpd                         15
+#define ItVpdFirstProcVpd                      16
+#define ItVpdApModelVpd                                17
+#define ItVpdClockCardVpd                      18
+#define ItVpdBusExtCardVpd                     19
+#define ItVpdProcCapacityVpd                   20
+#define ItVpdInteractiveCapacityVpd            21
+#define ItVpdFirstSlotLabel                    22
+#define ItVpdFirstLpQueue                      23
+#define ItVpdFirstL3CacheVpd                   24
+#define ItVpdFirstProcFruVpd                   25
 
+#define ItVpdMaxEntries                                26
 
-#define ItDmaMaxEntries                                  10
+#define ItDmaMaxEntries                                10
 
-#define ItVpdAreasMaxSlotLabels                 192 
+#define ItVpdAreasMaxSlotLabels                        192
 
 
-struct SlicVpdAdrs {
-       u32     pad1;
-       void *  vpdAddr;
+struct ItVpdAreas {
+       u32     xSlicDesc;              // Descriptor                   000-003
+       u16     xSlicSize;              // Size of this control block   004-005
+       u16     xPlicAdjustVpdLens:1;   // Flag to indicate new interface006-007
+       u16     xRsvd1:15;              // Reserved bits                ...
+       u16     xSlicVpdEntries;        // Number of VPD entries        008-009
+       u16     xSlicDmaEntries;        // Number of DMA entries        00A-00B
+       u16     xSlicMaxLogicalProcs;   // Maximum logical processors   00C-00D
+       u16     xSlicMaxPhysicalProcs;  // Maximum physical processors  00E-00F
+       u16     xSlicDmaToksOffset;     // Offset into this of array    010-011
+       u16     xSlicVpdAdrsOffset;     // Offset into this of array    012-013
+       u16     xSlicDmaLensOffset;     // Offset into this of array    014-015
+       u16     xSlicVpdLensOffset;     // Offset into this of array    016-017
+       u16     xSlicMaxSlotLabels;     // Maximum number of slot labels018-019
+       u16     xSlicMaxLpQueues;       // Maximum number of LP Queues  01A-01B
+       u8      xRsvd2[4];              // Reserved                     01C-01F
+       u64     xRsvd3[12];             // Reserved                     020-07F
+       u32     xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths   080-0A7
+       u32     xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens    0A8-0CF
+       u32     xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths   0D0-12F
+       void    *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers  130-1EF
 };
 
-
-struct ItVpdAreas
-{
-       u32     xSlicDesc;              // Descriptor                           000-003
-       u16     xSlicSize;              // Size of this control block           004-005
-       u16     xPlicAdjustVpdLens:1;   // Flag to indicate new interface       006-007
-       u16     xRsvd1:15;              // Reserved bits                        ...
-       u16     xSlicVpdEntries;        // Number of VPD entries                008-009
-       u16     xSlicDmaEntries;        // Number of DMA entries                00A-00B
-       u16     xSlicMaxLogicalProcs;   // Maximum logical processors           00C-00D
-       u16     xSlicMaxPhysicalProcs;  // Maximum physical processors          00E-00F
-       u16     xSlicDmaToksOffset;     // Offset into this of array            010-011
-       u16     xSlicVpdAdrsOffset;     // Offset into this of array            012-013
-       u16     xSlicDmaLensOffset;     // Offset into this of array            014-015
-       u16     xSlicVpdLensOffset;     // Offset into this of array            016-017
-       u16     xSlicMaxSlotLabels;     // Maximum number of slot labels        018-019
-       u16     xSlicMaxLpQueues;       // Maximum number of LP Queues          01A-01B
-       u8      xRsvd2[4];              // Reserved                             01C-01F
-       u64     xRsvd3[12];             // Reserved                             020-07F
-       u32     xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths           080-0A7
-       u32     xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens            0A8-0CF
-       u32     xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths           0D0-12F
-       void * xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers    130-1EF
-};
+extern struct ItVpdAreas       itVpdAreas;
 
 #endif /* _ITVPDAREAS_H */
diff --git a/include/asm-ppc64/iSeries/LparData.h b/include/asm-ppc64/iSeries/LparData.h
deleted file mode 100644 (file)
index e54f3b6..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * LparData.h
- * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
- * 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 _LPARDATA_H
-#define _LPARDATA_H
-
-#include <asm/types.h>
-#include <asm/page.h>
-#include <asm/abs_addr.h>
-
-#include <asm/iSeries/ItLpNaca.h>
-#include <asm/iSeries/ItLpRegSave.h>
-#include <asm/iSeries/HvReleaseData.h>
-#include <asm/iSeries/LparMap.h>
-#include <asm/iSeries/ItVpdAreas.h>
-#include <asm/iSeries/ItIplParmsReal.h>
-#include <asm/iSeries/ItExtVpdPanel.h>
-#include <asm/iSeries/ItLpQueue.h>
-#include <asm/iSeries/IoHriProcessorVpd.h>
-
-extern struct LparMap  xLparMap;
-extern struct HvReleaseData hvReleaseData;
-extern struct ItLpNaca itLpNaca;
-extern struct ItIplParmsReal xItIplParmsReal;
-extern struct ItExtVpdPanel xItExtVpdPanel;
-extern struct IoHriProcessorVpd xIoHriProcessorVpd[];
-extern struct ItLpQueue xItLpQueue;
-extern struct ItVpdAreas itVpdAreas;
-extern u64    xMsVpd[];
-extern struct msChunks msChunks;
-
-
-#endif /* _LPARDATA_H */
index 075205bb0f4ae7f49266e0327b6ab7db07757a0d..038e5df7e9f85fb3cf03e2fdb04ed63829f634e9 100644 (file)
@@ -1,17 +1,17 @@
 /*
  * LparMap.h
  * Copyright (C) 2001  Mike Corrigan IBM Corporation
- * 
+ *
  * 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 <asm/types.h>
 
-/* The iSeries hypervisor will set up mapping for one or more 
+/*
+ * The iSeries hypervisor will set up mapping for one or more
  * ESID/VSID pairs (in SLB/segment registers) and will set up
  * mappings of one or more ranges of pages to VAs.
  * We will have the hypervisor set up the ESID->VSID mapping
  * for the four kernel segments (C-F).  With shared processors,
  * the hypervisor will clear all segment registers and reload
- * these four whenever the processor is switched from one 
+ * these four whenever the processor is switched from one
  * partition to another.
  */
 
  * need to be located within the load area (if the total partition size
  * is 64 MB), but cannot be mapped.  Typically, this should specify
  * to map half (32 MB) of the load area.
- * 
- * The hypervisor will set up page table entries for the number of 
+ *
+ * The hypervisor will set up page table entries for the number of
  * pages specified.
  *
  * In 32-bit mode, the hypervisor will load all four of the
- * segment registers (identified by the low-order four bits of the 
+ * segment registers (identified by the low-order four bits of the
  * Esid field.  In 64-bit mode, the hypervisor will load one SLB
  * entry to map the Esid to the Vsid.
 */
 
-// Hypervisor initially maps 32MB of the load area 
-#define HvPagesToMap 8192
+/* Hypervisor initially maps 32MB of the load area */
+#define HvPagesToMap   8192
 
-struct LparMap
-{
-       u64       xNumberEsids;         // Number of ESID/VSID pairs (1)
-       u64       xNumberRanges;        // Number of VA ranges to map (1)
-       u64       xSegmentTableOffs;    // Page number within load area of seg table (0)
-       u64       xRsvd[5];             // Reserved (0)
-       u64       xKernelEsid;          // Esid used to map kernel load (0x0C00000000)  
-       u64       xKernelVsid;          // Vsid used to map kernel load (0x0C00000000)
-       u64       xPages;               // Number of pages to be mapped (8192)
-       u64       xOffset;              // Offset from start of load area (0)
-       u64       xVPN;                 // Virtual Page Number (0x000C000000000000)
+struct LparMap {
+       u64     xNumberEsids;   // Number of ESID/VSID pairs (1)
+       u64     xNumberRanges;  // Number of VA ranges to map (1)
+       u64     xSegmentTableOffs; // Page number within load area of seg table (0)
+       u64     xRsvd[5];
+       u64     xKernelEsid;    // Esid used to map kernel load (0x0C00000000)
+       u64     xKernelVsid;    // Vsid used to map kernel load (0x0C00000000)
+       u64     xPages;         // Number of pages to be mapped (8192)
+       u64     xOffset;        // Offset from start of load area (0)
+       u64     xVPN;           // Virtual Page Number (0x000C000000000000)
 };
 
+extern struct LparMap          xLparMap;
+
 #endif /* _LPARMAP_H */
diff --git a/include/asm-ppc64/iSeries/XmPciLpEvent.h b/include/asm-ppc64/iSeries/XmPciLpEvent.h
deleted file mode 100644 (file)
index a3d27f1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#ifndef        __XMPCILPEVENT_H__
-#define        __XMPCILPEVENT_H__
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int XmPciLpEvent_init(void);
-void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __XMPCILPEVENT_H__ */
index f52b7599b372be60c2d1eb83224aea2014d0ff8c..9f79413342b3f7d096b40724d67fc06b2a53e0c0 100644 (file)
@@ -5,32 +5,33 @@
 
 #ifdef CONFIG_PPC_ISERIES
 #include <linux/types.h>
-/************************************************************************/
-/* File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000.      */
-/************************************************************************/
-/* Remaps the io.h for the iSeries Io                                   */
-/* Copyright (C) 20yy  Allan H Trautman, IBM Corporation                */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created December 28, 2000                                          */
-/* End Change Activity                                                  */
-/************************************************************************/
+/*
+ * File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000.
+ *
+ * Remaps the io.h for the iSeries Io
+ * Copyright (C) 2000  Allan H Trautman, IBM Corporation
+ *
+ * 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
+ *
+ * Change Activity:
+ *   Created December 28, 2000
+ * End Change Activity
+ */
+
 extern u8   iSeries_Read_Byte(const volatile void __iomem * IoAddress);
 extern u16  iSeries_Read_Word(const volatile void __iomem * IoAddress);
 extern u32  iSeries_Read_Long(const volatile void __iomem * IoAddress);
@@ -39,8 +40,10 @@ extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress);
 extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress);
 
 extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n);
-extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t n);
-extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n);
+extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source,
+               size_t n);
+extern void iSeries_memcpy_fromio(void *dest,
+               const volatile void __iomem *source, size_t n);
 
 #endif /* CONFIG_PPC_ISERIES */
 #endif /* _ISERIES_IO_H */
index ff8ddede038c6a4574d1a200e0ea84ec474b8a5f..6c9767ac1302a84c38ae8dd84679dbfb0923c233 100644 (file)
@@ -1,19 +1,8 @@
 #ifndef        __ISERIES_IRQ_H__
 #define        __ISERIES_IRQ_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void iSeries_init_IRQ(void);
-int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
-int  iSeries_assign_IRQ(int, HvBusNumber, HvSubBusNumber, HvAgentId);
-void iSeries_activate_IRQs(void);
-
-int XmPciLpEvent_init(void);
-
-#ifdef __cplusplus
-}
-#endif
+extern void iSeries_init_IRQ(void);
+extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
+extern void iSeries_activate_IRQs(void);
 
 #endif /* __ISERIES_IRQ_H__ */
index 5769cff4c00c865af1a98b64426f53748f48fbaa..575f611f8b3391b04ec461adf70c65dbe207e812 100644 (file)
 #ifndef _ISERIES_64_PCI_H
 #define _ISERIES_64_PCI_H
 
-/************************************************************************/
-/* File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001.    */
-/************************************************************************/
-/* Define some useful macros for the iSeries pci routines.              */
-/* Copyright (C) 2001  Allan H Trautman, IBM Corporation                */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created Feb 20, 2001                                               */
-/*   Added device reset, March 22, 2001                                 */
-/*   Ported to ppc64, May 25, 2001                                      */
-/* End Change Activity                                                  */
-/************************************************************************/
+/*
+ * File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001.
+ *
+ * Define some useful macros for the iSeries pci routines.
+ * Copyright (C) 2001  Allan H Trautman, IBM Corporation
+ *
+ * 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
+ *
+ * Change Activity:
+ *   Created Feb 20, 2001
+ *   Added device reset, March 22, 2001
+ *   Ported to ppc64, May 25, 2001
+ * End Change Activity
+ */
 
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/abs_addr.h>
 
-struct pci_dev;                                /* For Forward Reference        */
+struct pci_dev;                                /* For Forward Reference */
 struct iSeries_Device_Node;
 
-/************************************************************************/
-/* Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure */
-/************************************************************************/
+/*
+ * Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure
+ */
 
 #define ISERIES_BUS(DevPtr)    DevPtr->DsaAddr.Dsa.busNumber
 #define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.Dsa.subBusNumber
 #define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.Dsa.deviceId
 #define ISERIES_DSA(DevPtr)    DevPtr->DsaAddr.DsaAddr
-#define ISERIES_DEVFUN(DevPtr) DevPtr->DevFn
-#define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node*)PciDev->sysdata)
+#define ISERIES_DEVNODE(PciDev)        ((struct iSeries_Device_Node *)PciDev->sysdata)
 
 #define EADsMaxAgents 7
 
-/************************************************************************/
-/* Decodes Linux DevFn to iSeries DevFn, bridge device, or function.    */
-/* For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h          */
-/************************************************************************/
-
-#define ISERIES_PCI_AGENTID(idsel,func)        ((idsel & 0x0F) << 4) | (func  & 0x07)
-#define ISERIES_ENCODE_DEVICE(agentid) ((0x10) | ((agentid&0x20)>>2) | (agentid&07))
-
-#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus)   ((subbus >> 5) & 0x7)
-#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
-
 /*
- * N.B. the ISERIES_DECODE_* macros are not used anywhere, and I think
- * the 0x71 (at least) must be wrong - 0x78 maybe?  -- paulus.
+ * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
+ * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
  */
-#define ISERIES_DECODE_DEVFN(linuxdevfn)  (((linuxdevfn & 0x71) << 1) | (linuxdevfn & 0x07))
-#define ISERIES_DECODE_DEVICE(linuxdevfn) (((linuxdevfn & 0x38) >> 3) |(((linuxdevfn & 0x40) >> 2) + 0x10))
-#define ISERIES_DECODE_FUNCTION(linuxdevfn) (linuxdevfn & 0x07)
 
-/************************************************************************/
-/* Converts Virtual Address to Real Address for Hypervisor calls        */
-/************************************************************************/
+#define ISERIES_PCI_AGENTID(idsel, func)       \
+       (((idsel & 0x0F) << 4) | (func & 0x07))
+#define ISERIES_ENCODE_DEVICE(agentid)         \
+       ((0x10) | ((agentid & 0x20) >> 2) | (agentid & 0x07))
 
-#define ISERIES_HV_ADDR(virtaddr)  (0x8000000000000000 | virt_to_abs(virtaddr))
+#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus)         ((subbus >> 5) & 0x7)
+#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus)       ((subbus >> 2) & 0x7)
 
-/************************************************************************/
-/* iSeries Device Information                                           */
-/************************************************************************/
+/*
+ * Converts Virtual Address to Real Address for Hypervisor calls
+ */
+#define ISERIES_HV_ADDR(virtaddr)      \
+       (0x8000000000000000 | virt_to_abs(virtaddr))
 
+/*
+ * iSeries Device Information
+ */
 struct iSeries_Device_Node {
        struct list_head Device_List;
-       struct pci_dev* PciDev;         /* Pointer to pci_dev structure*/
-        union HvDsaMap DsaAddr;        /* Direct Select Address       */
-                                        /* busNumber,subBusNumber,     */ 
-                                       /* deviceId, barNumber         */
-       HvAgentId       AgentId;        /* Hypervisor DevFn            */
-       int             DevFn;          /* Linux devfn                 */
-       int             BarOffset;
-       int             Irq;            /* Assigned IRQ                */
-       int             ReturnCode;     /* Return Code Holder          */
-       int             IoRetry;        /* Current Retry Count         */
-       int             Flags;          /* Possible flags(disable/bist)*/
-       u16             Vendor;         /* Vendor ID                   */
-       u8              LogicalSlot;    /* Hv Slot Index for Tces      */
-       struct iommu_table* iommu_table;/* Device TCE Table            */ 
-       u8              PhbId;          /* Phb Card is on.             */
-       u16             Board;          /* Board Number                */
-       u8              FrameId;        /* iSeries spcn Frame Id       */
-       char            CardLocation[4];/* Char format of planar vpd   */
-       char            Location[20];   /* Frame  1, Card C10          */
+       struct pci_dev  *PciDev;
+       union HvDsaMap  DsaAddr;        /* Direct Select Address */
+                                       /* busNumber, subBusNumber, */
+                                       /* deviceId, barNumber */
+       int             DevFn;          /* Linux devfn */
+       int             Irq;            /* Assigned IRQ */
+       int             Flags;          /* Possible flags(disable/bist)*/
+       u8              LogicalSlot;    /* Hv Slot Index for Tces */
+       struct iommu_table *iommu_table;/* Device TCE Table */
 };
 
-/************************************************************************/
-/* Functions                                                            */
-/************************************************************************/
-
-extern int           iSeries_Device_Information(struct pci_dev*,char*, int);
-extern void          iSeries_Get_Location_Code(struct iSeries_Device_Node*);
-extern int           iSeries_Device_ToggleReset(struct pci_dev* PciDev, int AssertTime, int DelayTime);
+extern void    iSeries_Device_Information(struct pci_dev*, int);
 
 #endif /* _ISERIES_64_PCI_H */
diff --git a/include/asm-ppc64/iSeries/iSeries_proc.h b/include/asm-ppc64/iSeries/iSeries_proc.h
deleted file mode 100644 (file)
index adb6dc1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * iSeries_proc.h
- * Copyright (C) 2001  Kyle A. Lucke IBM Corporation
- * 
- * 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 _ISERIES_PROC_H
-#define _ISERIES_PROC_H
-
-extern void iSeries_proc_early_init(void);
-
-#endif /* _iSeries_PROC_H */
index db333e1ee216aaac2887b9818fcda48068ec65ff..7e6a0d936999c86cb5d9c835a08ba77e1ae6f687 100644 (file)
@@ -9,17 +9,16 @@
  * 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
index 3e5766a849d68ee48b1a3f6a58b01c8d4a2c6ddb..6c05e6257f53a386f99fbe2b744cb50b64468efc 100644 (file)
@@ -8,32 +8,32 @@
  *           Colin Devilbiss <devilbis@us.ibm.com>
  *
  * (C) Copyright 2000 IBM Corporation
- * 
+ *
  * This header file is used by the iSeries virtual I/O device
  * drivers.  It defines the interfaces to the common functions
  * (implemented in drivers/char/viopath.h) as well as defining
- * common functions and structures.  Currently (at the time I 
+ * common functions and structures.  Currently (at the time I
  * wrote this comment) the iSeries virtual I/O device drivers
- * that use this are 
- *   drivers/block/viodasd.c 
+ * that use this are
+ *   drivers/block/viodasd.c
  *   drivers/char/viocons.c
  *   drivers/char/viotape.c
  *   drivers/cdrom/viocd.c
  *
  * The iSeries virtual ethernet support (veth.c) uses a whole
  * different set of functions.
- * 
+ *
  * 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) anyu later version.
  *
  * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * 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.  
+ * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
+ * 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 <asm/iSeries/HvTypes.h>
 #include <asm/iSeries/HvLpEvent.h>
 
-/* iSeries virtual I/O events use the subtype field in
+/*
+ * iSeries virtual I/O events use the subtype field in
  * HvLpEvent to figure out what kind of vio event is coming
  * in.  We use a table to route these, and this defines
  * the maximum number of distinct subtypes
  */
 #define VIO_MAX_SUBTYPES 8
 
-/* Each subtype can register a handler to process their events.
+/*
+ * Each subtype can register a handler to process their events.
  * The handler must have this interface.
  */
 typedef void (vio_event_handler_t) (struct HvLpEvent * event);
 
-int viopath_open(HvLpIndex remoteLp, int subtype, int numReq);
-int viopath_close(HvLpIndex remoteLp, int subtype, int numReq);
-int vio_setHandler(int subtype, vio_event_handler_t * beh);
-int vio_clearHandler(int subtype);
-int viopath_isactive(HvLpIndex lp);
-HvLpInstanceId viopath_sourceinst(HvLpIndex lp);
-HvLpInstanceId viopath_targetinst(HvLpIndex lp);
-void vio_set_hostlp(void);
-void *vio_get_event_buffer(int subtype);
-void vio_free_event_buffer(int subtype, void *buffer);
+extern int viopath_open(HvLpIndex remoteLp, int subtype, int numReq);
+extern int viopath_close(HvLpIndex remoteLp, int subtype, int numReq);
+extern int vio_setHandler(int subtype, vio_event_handler_t * beh);
+extern int vio_clearHandler(int subtype);
+extern int viopath_isactive(HvLpIndex lp);
+extern HvLpInstanceId viopath_sourceinst(HvLpIndex lp);
+extern HvLpInstanceId viopath_targetinst(HvLpIndex lp);
+extern void vio_set_hostlp(void);
+extern void *vio_get_event_buffer(int subtype);
+extern void vio_free_event_buffer(int subtype, void *buffer);
 
 extern HvLpIndex viopath_hostLp;
 extern HvLpIndex viopath_ourLp;
 
-#define VIOCHAR_MAX_DATA 200
+#define VIOCHAR_MAX_DATA       200
 
-#define VIOMAJOR_SUBTYPE_MASK 0xff00
-#define VIOMINOR_SUBTYPE_MASK 0x00ff
-#define VIOMAJOR_SUBTYPE_SHIFT 8
+#define VIOMAJOR_SUBTYPE_MASK  0xff00
+#define VIOMINOR_SUBTYPE_MASK  0x00ff
+#define VIOMAJOR_SUBTYPE_SHIFT 8
 
-#define VIOVERSION            0x0101
+#define VIOVERSION             0x0101
 
 /*
  * This is the general structure for VIO errors; each module should have
@@ -89,8 +91,8 @@ struct vio_error_entry {
        int errno;
        const char *msg;
 };
-const struct vio_error_entry *vio_lookup_rc(const struct vio_error_entry
-                                           *local_table, u16 rc);
+extern const struct vio_error_entry *vio_lookup_rc(
+               const struct vio_error_entry *local_table, u16 rc);
 
 enum viosubtypes {
        viomajorsubtype_monitor = 0x0100,
@@ -102,7 +104,6 @@ enum viosubtypes {
        viomajorsubtype_scsi = 0x0700
 };
 
-
 enum vioconfigsubtype {
        vioconfigget = 0x0001,
 };
index 3a45e918bf16606a34e0cf1791af858610d2b6d4..e46ff68a6e4184923547153af0853d91bef2264e 100644 (file)
@@ -4,9 +4,9 @@
 /*
  * Define the address range of the imalloc VM area.
  */
-#define PHBS_IO_BASE     IOREGIONBASE
-#define IMALLOC_BASE      (IOREGIONBASE + 0x80000000ul)        /* Reserve 2 gigs for PHBs */
-#define IMALLOC_END       (IOREGIONBASE + EADDR_MASK)
+#define PHBS_IO_BASE     VMALLOC_END
+#define IMALLOC_BASE      (PHBS_IO_BASE + 0x80000000ul)        /* Reserve 2 gigs for PHBs */
+#define IMALLOC_END       (VMALLOC_START + EADDR_MASK)
 
 
 /* imalloc region types */
@@ -18,7 +18,9 @@
 
 extern struct vm_struct * im_get_free_area(unsigned long size);
 extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-                       int region_type);
-unsigned long im_free(void *addr);
+                                     int region_type);
+extern void im_free(void *addr);
+
+extern unsigned long ioremap_bot;
 
 #endif /* _PPC64_IMALLOC_H */
index bd53ca4dcfa269d7c7ae997bdd36e06b32a31731..729de5cc21d984206b33bf8e142cc9cb8a27668b 100644 (file)
@@ -82,24 +82,6 @@ struct iommu_table {
        unsigned long *it_map;       /* A simple allocation bitmap for now */
 };
 
-#ifdef CONFIG_PPC_ISERIES
-struct iommu_table_cb {
-       unsigned long   itc_busno;      /* Bus number for this tce table */
-       unsigned long   itc_start;      /* Will be NULL for secondary */
-       unsigned long   itc_totalsize;  /* Size (in pages) of whole table */
-       unsigned long   itc_offset;     /* Index into real tce table of the
-                                          start of our section */
-       unsigned long   itc_size;       /* Size (in pages) of our section */
-       unsigned long   itc_index;      /* Index of this tce table */
-       unsigned short  itc_maxtables;  /* Max num of tables for partition */
-       unsigned char   itc_virtbus;    /* Flag to indicate virtual bus */
-       unsigned char   itc_slotno;     /* IOA Tce Slot Index */
-       unsigned char   itc_rsvd[4];
-};
-
-extern struct iommu_table vio_tce_table;      /* Tce table for virtual bus */
-#endif /* CONFIG_PPC_ISERIES */
-
 struct scatterlist;
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
@@ -122,9 +104,6 @@ extern void iommu_devnode_init_pSeries(struct device_node *dn);
 
 #ifdef CONFIG_PPC_ISERIES
 
-/* Walks all buses and creates iommu tables */
-extern void iommu_setup_iSeries(void);
-
 /* Initializes tables for bio buses */
 extern void __init iommu_vio_init(void);
 
@@ -158,8 +137,12 @@ extern void iommu_init_early_pSeries(void);
 extern void iommu_init_early_iSeries(void);
 extern void iommu_init_early_u3(void);
 
+#ifdef CONFIG_PCI
 extern void pci_iommu_init(void);
 extern void pci_direct_iommu_init(void);
+#else
+static inline void pci_iommu_init(void) { }
+#endif
 
 extern void alloc_u3_dart_table(void);
 
index 1a0223b5f3b8e5c3bc24ffd8c1deeeb3c4c0fffa..ae76cae1483fad886c002fe33aec8166b2c1a5a7 100644 (file)
 #include       <asm/types.h>
 #include       <asm/lppaca.h>
 #include       <asm/iSeries/ItLpRegSave.h>
+#include       <asm/iSeries/ItLpQueue.h>
 #include       <asm/mmu.h>
 
 register struct paca_struct *local_paca asm("r13");
 #define get_paca()     local_paca
 
 struct task_struct;
-struct ItLpQueue;
 
 /*
  * Defines the layout of the paca.
index bcd21789d3b7816e2e53e85dac6515b347c101cd..257d87eb7c34b48066def0c4d172d1df3529b6cb 100644 (file)
@@ -202,9 +202,7 @@ extern u64 ppc64_pft_size;          /* Log 2 of page table size */
 #define PAGE_OFFSET     ASM_CONST(0xC000000000000000)
 #define KERNELBASE      PAGE_OFFSET
 #define VMALLOCBASE     ASM_CONST(0xD000000000000000)
-#define IOREGIONBASE    ASM_CONST(0xE000000000000000)
 
-#define IO_REGION_ID       (IOREGIONBASE >> REGION_SHIFT)
 #define VMALLOC_REGION_ID  (VMALLOCBASE >> REGION_SHIFT)
 #define KERNEL_REGION_ID   (KERNELBASE >> REGION_SHIFT)
 #define USER_REGION_ID     (0UL)
index 264c4f7993be3557a6b5932bf8dcf943b7c8fd8e..46cf61c2ff69a3b920231122402b1405ca0d4fca 100644 (file)
@@ -53,7 +53,8 @@
  * Define the address range of the vmalloc VM area.
  */
 #define VMALLOC_START (0xD000000000000000ul)
-#define VMALLOC_END   (VMALLOC_START + EADDR_MASK)
+#define VMALLOC_SIZE  (0x10000000000UL)
+#define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
 
 /*
  * Bits in a linux-style PTE.  These match the bits in the
@@ -239,9 +240,6 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
 /* This now only contains the vmalloc pages */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-/* to find an entry in the ioremap page-table-directory */
-#define pgd_offset_i(address) (ioremap_pgd + pgd_index(address))
-
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
@@ -459,15 +457,12 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
 #define __HAVE_ARCH_PTE_SAME
 #define pte_same(A,B)  (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
 
-extern unsigned long ioremap_bot, ioremap_base;
-
 #define pmd_ERROR(e) \
        printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e))
 #define pgd_ERROR(e) \
        printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e))
 
 extern pgd_t swapper_pg_dir[];
-extern pgd_t ioremap_dir[];
 
 extern void paging_init(void);
 
index 809c634ba1dfa03e41078b737a3f0be4945f7314..3084099086a820f2d25d13456e86bf258f4ed388 100644 (file)
@@ -429,16 +429,6 @@ struct thread_struct {
        .fpexc_mode = MSR_FE0|MSR_FE1, \
 }
 
-/*
- * Note: the vm_start and vm_end fields here should *not*
- * be in kernel space.  (Could vm_end == vm_start perhaps?)
- */
-#define IOREMAP_MMAP { &ioremap_mm, 0, 0x1000, NULL, \
-                   PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \
-                   1, NULL, NULL }
-
-extern struct mm_struct ioremap_mm;
-
 /*
  * Return saved PC of a blocked thread. For now, this is the "user" PC
  */
index c8646fa999c2ff61217ff01b2cb702784a5ed1df..8115ecb8feee24abd99a25b3659fb58d98315ce0 100644 (file)
@@ -45,7 +45,7 @@ void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
 #endif
 
-#define __smp_processor_id() (get_paca()->paca_index)
+#define raw_smp_processor_id() (get_paca()->paca_index)
 #define hard_smp_processor_id() (get_paca()->hw_cpu_id)
 
 extern cpumask_t cpu_sibling_map[NR_CPUS];
index 9473786387a349123cafb4cd43221bf884ccd089..dd50e57a928f2a6fa37e29b5cca503075221971c 100644 (file)
@@ -47,7 +47,7 @@ extern int smp_call_function_on(void (*func) (void *info), void *info,
  
 #define PROC_CHANGE_PENALTY    20              /* Schedule penalty */
 
-#define smp_processor_id() (S390_lowcore.cpu_data.cpu_nr)
+#define raw_smp_processor_id() (S390_lowcore.cpu_data.cpu_nr)
 
 extern int smp_get_cpu(cpumask_t cpu_map);
 extern void smp_put_cpu(int cpu);
index 4c6d129e7d91e0dbe52657c575b689d5a9fa96a5..180467be8e7bb84c7f4f41397697bfc503b2ef98 100644 (file)
@@ -31,6 +31,7 @@
 #define HPAGE_SIZE             (1UL << HPAGE_SHIFT)
 #define HPAGE_MASK             (~(HPAGE_SIZE-1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT-PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
 #endif
 
 #ifdef __KERNEL__
index cd847a47a9aa1a681d8f44cf250d9e12f8341ea3..ecb909572d3fc955efba94c6bb1035f28e203ab0 100644 (file)
@@ -196,6 +196,7 @@ static inline pte_t pte_mkexec(pte_t pte)   { set_pte(&pte, __pte(pte_val(pte) | _
 static inline pte_t pte_mkdirty(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+static inline pte_t pte_mkhuge(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
 
 /*
  * Macro and implementation to make a page protection as uncachable.
index 38b54469d7d1a1557715f2196f703094a6c93cb1..f19a8b3b69a6a24af8519ab3828469ed510eb5d3 100644 (file)
@@ -25,7 +25,7 @@ extern cpumask_t cpu_possible_map;
 
 #define cpu_online(cpu)                cpu_isset(cpu, cpu_online_map)
 
-#define smp_processor_id()     (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 /* I've no idea what the real meaning of this is */
 #define PROC_CHANGE_PENALTY    20
index e1f7f5a41210f7421f64e2a1a31f92d7aa950f64..d6167f1c0e99ef10f86877259441bfb7c5e4e908 100644 (file)
@@ -41,6 +41,7 @@
 #define HPAGE_SIZE             (1UL << HPAGE_SHIFT)
 #define HPAGE_MASK             (~(HPAGE_SIZE-1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT-PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
 #endif
 
 #ifdef __KERNEL__
index 525e1523ef5f229b49d61e413e0aa2561e4a7383..78ac6be2d9ef0ebe6de29d7e4f8a5a7be3e91e34 100644 (file)
@@ -430,6 +430,8 @@ extern inline pte_t pte_mkwrite(pte_t pte)  { set_pte(&pte, __pte(pte_val(pte) |
 extern inline pte_t pte_mkexec(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
 extern inline pte_t pte_mkdirty(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
+extern inline pte_t pte_mkhuge(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
+
 
 /*
  * Conversion functions: convert a page and protection to a page entry.
index f986c0d0922a1c87215fb48456a41132245616a0..4f96d8333a12ad362a70b3c86d95937564cd43c5 100644 (file)
@@ -148,7 +148,7 @@ extern __inline__ int hard_smp_processor_id(void)
 }
 #endif
 
-#define smp_processor_id()     (current_thread_info()->cpu)
+#define raw_smp_processor_id()         (current_thread_info()->cpu)
 
 #define prof_multiplier(__cpu)         cpu_data(__cpu).multiplier
 #define prof_counter(__cpu)            cpu_data(__cpu).counter
index 219ea043a14a842268ca8656faa4c9d2a11fb2b1..b87dbbd64bc9ca723e3077521cb5cd87af63906e 100644 (file)
@@ -95,6 +95,8 @@ typedef unsigned long pgprot_t;
 #define HPAGE_SIZE             (_AC(1,UL) << HPAGE_SHIFT)
 #define HPAGE_MASK             (~(HPAGE_SIZE - 1UL))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
+#define ARCH_HAS_HUGETLB_PREFAULT_HOOK
 #endif
 
 #define TASK_UNMAPPED_BASE     (test_thread_flag(TIF_32BIT) ? \
index ae2cd5b09a7cc523e96640d805eb97e299da8907..1ae00c5087f10d6eb3a0c2ea8c6ade9ff304774b 100644 (file)
@@ -286,6 +286,7 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
 #define pte_mkyoung(pte)       (__pte(pte_val(pte) | _PAGE_ACCESSED | _PAGE_R))
 #define pte_mkwrite(pte)       (__pte(pte_val(pte) | _PAGE_WRITE))
 #define pte_mkdirty(pte)       (__pte(pte_val(pte) | _PAGE_MODIFIED | _PAGE_W))
+#define pte_mkhuge(pte)                (__pte(pte_val(pte) | _PAGE_SZHUGE))
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address)     (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
index bc1445b904efdb80a1991c895ae52ba4d067bc9b..d0bee2413560147a62b4f7f1af7ea7f781e0b847 100644 (file)
@@ -192,6 +192,40 @@ extern unsigned long get_wchan(struct task_struct *task);
 
 #define cpu_relax()    barrier()
 
+/* Prefetch support.  This is tuned for UltraSPARC-III and later.
+ * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
+ * a shallower prefetch queue than later chips.
+ */
+#define ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCHW
+#define ARCH_HAS_SPINLOCK_PREFETCH
+
+static inline void prefetch(const void *x)
+{
+       /* We do not use the read prefetch mnemonic because that
+        * prefetches into the prefetch-cache which only is accessible
+        * by floating point operations in UltraSPARC-III and later.
+        * By contrast, "#one_write" prefetches into the L2 cache
+        * in shared state.
+        */
+       __asm__ __volatile__("prefetch [%0], #one_write"
+                            : /* no outputs */
+                            : "r" (x));
+}
+
+static inline void prefetchw(const void *x)
+{
+       /* The most optimal prefetch to use for writes is
+        * "#n_writes".  This brings the cacheline into the
+        * L2 cache in "owned" state.
+        */
+       __asm__ __volatile__("prefetch [%0], #n_writes"
+                            : /* no outputs */
+                            : "r" (x));
+}
+
+#define spin_lock_prefetch(x)  prefetchw(x)
+
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__ASM_SPARC64_PROCESSOR_H) */
index 5e3e06d908feb9b19f33b0b18816d1da8e823710..110a2de891239407ff048772b920fa531119a7eb 100644 (file)
@@ -64,7 +64,7 @@ static __inline__ int hard_smp_processor_id(void)
        }
 }
 
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 #endif /* !(__ASSEMBLY__) */
 
index 4412d5d9c26ba7376a738ba419f2b544b88486fe..d879eba2b52c7d74e646a3213911304f877279c5 100644 (file)
@@ -8,7 +8,8 @@
 #include "asm/current.h"
 #include "linux/cpumask.h"
 
-#define smp_processor_id() (current_thread->cpu)
+#define raw_smp_processor_id() (current_thread->cpu)
+
 #define cpu_logical_map(n) (n)
 #define cpu_number_map(n) (n)
 #define PROC_CHANGE_PENALTY    15 /* Pick a number, any number */
index 5952914f4121008f1ff78d86e248d938cd1a4c3d..7255cde065384d9508507c88ac522fedfc9d36b2 100644 (file)
@@ -21,7 +21,7 @@ struct exec
 
 #ifdef __KERNEL__
 #include <linux/thread_info.h>
-#define STACK_TOP (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE)
+#define STACK_TOP TASK_SIZE
 #endif
 
 #endif /* __A_OUT_GNU_H__ */
index f43048035a03394ce6330e58e0c4333c01170604..9ce338c3a71eb8fa5a2db09b5ce9b7c109f0654e 100644 (file)
@@ -28,6 +28,7 @@
 #define HPAGE_SIZE     ((1UL) << HPAGE_SHIFT)
 #define HPAGE_MASK     (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
+#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
index db2a0efbf5738b8294153713e862183512acdfc1..4eec176c3c39476ab64ed2fc433610823ab5c7fd 100644 (file)
@@ -253,6 +253,7 @@ extern inline int pte_young(pte_t pte)              { return pte_val(pte) & _PAGE_ACCESSED;
 extern inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_RW; }
 static inline int pte_file(pte_t pte)          { return pte_val(pte) & _PAGE_FILE; }
 
+#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
 extern inline pte_t pte_rdprotect(pte_t pte)   { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
 extern inline pte_t pte_exprotect(pte_t pte)   { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
 extern inline pte_t pte_mkclean(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
@@ -263,6 +264,7 @@ extern inline pte_t pte_mkexec(pte_t pte)   { set_pte(&pte, __pte(pte_val(pte) | _
 extern inline pte_t pte_mkdirty(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 extern inline pte_t pte_mkwrite(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+extern inline pte_t pte_mkhuge(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) | __LARGE_PTE)); return pte; }
 
 struct vm_area_struct;
 
@@ -290,7 +292,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
  */
 #define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
 
-#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT) 
 static inline int pmd_large(pmd_t pte) { 
        return (pmd_val(pte) & __LARGE_PTE) == __LARGE_PTE; 
 }      
index d641b19f6da5d7aa9324ffcc17b1b24d023806b3..8b55f139968fc3bd730502eb800182ea95ef139d 100644 (file)
@@ -160,16 +160,17 @@ static inline void clear_in_cr4 (unsigned long mask)
 /*
  * User space process size. 47bits minus one guard page.
  */
-#define TASK_SIZE      (0x800000000000UL - 4096)
+#define TASK_SIZE64    (0x800000000000UL - 4096)
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
 #define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? 0xc0000000 : 0xFFFFe000)
-#define TASK_UNMAPPED_32 PAGE_ALIGN(IA32_PAGE_OFFSET/3)
-#define TASK_UNMAPPED_64 PAGE_ALIGN(TASK_SIZE/3) 
-#define TASK_UNMAPPED_BASE     \
-       (test_thread_flag(TIF_IA32) ? TASK_UNMAPPED_32 : TASK_UNMAPPED_64)  
+
+#define TASK_SIZE              (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE64)
+#define TASK_SIZE_OF(child)    ((test_tsk_thread_flag(child, TIF_IA32)) ? IA32_PAGE_OFFSET : TASK_SIZE64)
+
+#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE/3)
 
 /*
  * Size of io_bitmap.
index 96844fecbde8cd1336555a8006aa0bd0e7eb5cbd..a7425aa5a3b72d369ef676c5f1fda8c5dec049b3 100644 (file)
@@ -68,7 +68,7 @@ static inline int num_booting_cpus(void)
        return cpus_weight(cpu_callout_map);
 }
 
-#define __smp_processor_id() read_pda(cpunumber)
+#define raw_smp_processor_id() read_pda(cpunumber)
 
 extern __inline int hard_smp_processor_id(void)
 {
diff --git a/include/linux/arcfb.h b/include/linux/arcfb.h
new file mode 100644 (file)
index 0000000..721e765
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __LINUX_ARCFB_H__
+#define __LINUX_ARCFB_H__
+
+#define FBIO_WAITEVENT         _IO('F', 0x88)
+#define FBIO_GETCONTROL2       _IOR('F', 0x89, size_t)
+
+#endif
+
index a1657fb99516ba445d3f35d9328348db0b2b4deb..9343c89d843c2437edcc749868506a6807915223 100644 (file)
@@ -23,7 +23,7 @@
 #define AUTOFS_MIN_PROTO_VERSION       3
 #define AUTOFS_MAX_PROTO_VERSION       4
 
-#define AUTOFS_PROTO_SUBVERSION                6
+#define AUTOFS_PROTO_SUBVERSION                7
 
 /* Mask for expire behaviour */
 #define AUTOFS_EXP_IMMEDIATE           1
index b468bf49654782d1d7cc6e6f12dc79d04fd34325..bc24beeed971d7a803af06bd74eb3c6ef2e300fe 100644 (file)
@@ -524,11 +524,11 @@ struct fb_pixmap {
        u32 offset;             /* current offset to buffer             */
        u32 buf_align;          /* byte alignment of each bitmap        */
        u32 scan_align;         /* alignment per scanline               */
-       u32 access_align;       /* alignment per read/write             */
+       u32 access_align;       /* alignment per read/write (bits)      */
        u32 flags;              /* see FB_PIXMAP_*                      */
        /* access methods */
-       void (*outbuf)(struct fb_info *info, u8 *addr, u8 *src, unsigned int size);
-       u8   (*inbuf) (struct fb_info *info, u8 *addr);
+       void (*writeio)(struct fb_info *info, void __iomem *dst, void *src, unsigned int size);
+       void (*readio) (struct fb_info *info, void *dst, void __iomem *src, unsigned int size);
 };
 
 
@@ -816,18 +816,9 @@ extern int unregister_framebuffer(struct fb_info *fb_info);
 extern int fb_prepare_logo(struct fb_info *fb_info);
 extern int fb_show_logo(struct fb_info *fb_info);
 extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
-extern void fb_iomove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
-                               u8 *dst, u32 d_pitch, u8 *src, u32 idx,
+extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx,
                                u32 height, u32 shift_high, u32 shift_low, u32 mod);
-extern void fb_iomove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
-                               u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-                               u32 height);
-extern void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
-                               u8 *dst, u32 d_pitch, u8 *src, u32 idx,
-                               u32 height, u32 shift_high, u32 shift_low, u32 mod);
-extern void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
-                               u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-                               u32 height);
+extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height);
 extern void fb_set_suspend(struct fb_info *info, int state);
 extern int fb_get_color_depth(struct fb_var_screeninfo *var);
 extern int fb_get_options(char *name, char **option);
index fc2d690c9d5f42ff15fe356ad138c48e2af5cb2c..8fc80a7d78ac2e131ce8b7dea5095499a4aa94e5 100644 (file)
@@ -25,19 +25,23 @@ struct font_desc {
 #define VGA8x16_IDX    1
 #define PEARL8x8_IDX   2
 #define VGA6x11_IDX    3
-#define SUN8x16_IDX    4
-#define SUN12x22_IDX   5
-#define ACORN8x8_IDX   6
-#define        MINI4x6_IDX     7
+#define FONT7x14_IDX   4
+#define        FONT10x18_IDX   5
+#define SUN8x16_IDX    6
+#define SUN12x22_IDX   7
+#define ACORN8x8_IDX   8
+#define        MINI4x6_IDX     9
 
 extern struct font_desc        font_vga_8x8,
-                               font_vga_8x16,
-                               font_pearl_8x8,
-                               font_vga_6x11,
-                               font_sun_8x16,
-                               font_sun_12x22,
-                               font_acorn_8x8,
-                               font_mini_4x6;
+                       font_vga_8x16,
+                       font_pearl_8x8,
+                       font_vga_6x11,
+                       font_7x14,
+                       font_10x18,
+                       font_sun_8x16,
+                       font_sun_12x22,
+                       font_acorn_8x8,
+                       font_mini_4x6;
 
 /* Find a font with a specific name */
 
index faaff4c645598cef953bbe1f94379cfd22c517ab..70f54af87b9f116f1ffda706c0293f6a7f6a3e24 100644 (file)
@@ -51,6 +51,7 @@ struct gianfar_platform_data {
 
        /* board specific information */
        u32 board_flags;
+       u32 phy_flags;
        u32 phyid;
        u32 interruptPHY;
        u8 mac_addr[6];
@@ -61,9 +62,14 @@ struct gianfar_platform_data {
 #define FSL_GIANFAR_DEV_HAS_COALESCE           0x00000002
 #define FSL_GIANFAR_DEV_HAS_RMON               0x00000004
 #define FSL_GIANFAR_DEV_HAS_MULTI_INTR         0x00000008
+#define FSL_GIANFAR_DEV_HAS_CSUM               0x00000010
+#define FSL_GIANFAR_DEV_HAS_VLAN               0x00000020
+#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH      0x00000040
+#define FSL_GIANFAR_DEV_HAS_PADDING            0x00000080
 
 /* Flags in gianfar_platform_data */
-#define FSL_GIANFAR_BRD_HAS_PHY_INTR   0x00000001      /* if not set use a timer */
+#define FSL_GIANFAR_BRD_HAS_PHY_INTR   0x00000001 /* set or use a timer */
+#define FSL_GIANFAR_BRD_IS_REDUCED     0x00000002 /* Set if RGMII, RMII */
 
 struct fsl_i2c_platform_data {
        /* device specific information */
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
new file mode 100644 (file)
index 0000000..7fd0576
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Basic general purpose allocator for managing special purpose memory
+ * not managed by the regular kmalloc/kfree interface.
+ * Uses for this includes on-device special memory, uncached memory
+ * etc.
+ *
+ * This code is based on the buddy allocator found in the sym53c8xx_2
+ * driver, adapted for general purpose use.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/spinlock.h>
+
+#define ALLOC_MIN_SHIFT                5 /* 32 bytes minimum */
+/*
+ *  Link between free memory chunks of a given size.
+ */
+struct gen_pool_link {
+       struct gen_pool_link *next;
+};
+
+/*
+ *  Memory pool descriptor.
+ */
+struct gen_pool {
+       spinlock_t lock;
+       unsigned long (*get_new_chunk)(struct gen_pool *);
+       struct gen_pool *next;
+       struct gen_pool_link *h;
+       unsigned long private;
+       int max_chunk_shift;
+};
+
+unsigned long gen_pool_alloc(struct gen_pool *poolp, int size);
+void gen_pool_free(struct gen_pool *mp, unsigned long ptr, int size);
+struct gen_pool *gen_pool_create(int nr_chunks, int max_chunk_shift,
+                                unsigned long (*fp)(struct gen_pool *),
+                                unsigned long data);
index af7407e8cfc53a476cd6d58561358cc8ed3a3b67..8d6bf608b19942c91fd6939bbb1685c765174fd5 100644 (file)
@@ -39,6 +39,7 @@ struct vm_area_struct;
 #define __GFP_COMP     0x4000u /* Add compound page metadata */
 #define __GFP_ZERO     0x8000u /* Return zeroed page on success */
 #define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
+#define __GFP_NORECLAIM  0x20000u /* No realy zone reclaim during allocation */
 
 #define __GFP_BITS_SHIFT 20    /* Room for 20 __GFP_FOO bits */
 #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
@@ -47,7 +48,7 @@ struct vm_area_struct;
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
                        __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
                        __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
-                       __GFP_NOMEMALLOC)
+                       __GFP_NOMEMALLOC|__GFP_NORECLAIM)
 
 #define GFP_ATOMIC     (__GFP_HIGH)
 #define GFP_NOIO       (__GFP_WAIT)
@@ -132,5 +133,10 @@ extern void FASTCALL(free_cold_page(struct page *page));
 #define free_page(addr) free_pages((addr),0)
 
 void page_alloc_init(void);
+#ifdef CONFIG_NUMA
+void drain_remote_pages(void);
+#else
+static inline void drain_remote_pages(void) { };
+#endif
 
 #endif /* __LINUX_GFP_H */
index 6af1ae4a821196a54981887cecc2fe32c0e18241..f529d144281521552491058d1b5ed66d47bc8d71 100644 (file)
@@ -4,6 +4,7 @@
 #ifdef CONFIG_HUGETLB_PAGE
 
 #include <linux/mempolicy.h>
+#include <asm/tlbflush.h>
 
 struct ctl_table;
 
@@ -22,12 +23,6 @@ int hugetlb_report_meminfo(char *);
 int hugetlb_report_node_meminfo(int, char *);
 int is_hugepage_mem_enough(size_t);
 unsigned long hugetlb_total_pages(void);
-struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
-                             int write);
-struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
-                               pmd_t *pmd, int write);
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
-int pmd_huge(pmd_t pmd);
 struct page *alloc_huge_page(void);
 void free_huge_page(struct page *);
 
@@ -35,6 +30,17 @@ extern unsigned long max_huge_pages;
 extern const unsigned long hugetlb_zero, hugetlb_infinity;
 extern int sysctl_hugetlb_shm_group;
 
+/* arch callbacks */
+
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr);
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr);
+struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
+                             int write);
+struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+                               pmd_t *pmd, int write);
+int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
+int pmd_huge(pmd_t pmd);
+
 #ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
 #define is_hugepage_only_range(mm, addr, len)  0
 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \
@@ -48,6 +54,28 @@ extern int sysctl_hugetlb_shm_group;
 int prepare_hugepage_range(unsigned long addr, unsigned long len);
 #endif
 
+#ifndef ARCH_HAS_SETCLEAR_HUGE_PTE
+#define set_huge_pte_at(mm, addr, ptep, pte)   set_pte_at(mm, addr, ptep, pte)
+#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
+#else
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, pte_t pte);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep);
+#endif
+
+#ifndef ARCH_HAS_HUGETLB_PREFAULT_HOOK
+#define hugetlb_prefault_arch_hook(mm)         do { } while (0)
+#else
+void hugetlb_prefault_arch_hook(struct mm_struct *mm);
+#endif
+
+#ifndef ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
+#define hugetlb_clean_stale_pgtable(pte)       BUG()
+#else
+void hugetlb_clean_stale_pgtable(pte_t *pte);
+#endif
+
 #else /* !CONFIG_HUGETLB_PAGE */
 
 static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
diff --git a/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h
new file mode 100644 (file)
index 0000000..1b5018a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  hwmon-sysfs.h - hardware monitoring chip driver sysfs defines
+ *
+ *  Copyright (C) 2005 Yani Ioannou <yani.ioannou@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _LINUX_HWMON_SYSFS_H
+#define _LINUX_HWMON_SYSFS_H
+
+struct sensor_device_attribute{
+       struct device_attribute dev_attr;
+       int index;
+};
+#define to_sensor_dev_attr(_dev_attr) \
+       container_of(_dev_attr, struct sensor_device_attribute, dev_attr)
+
+#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index)    \
+struct sensor_device_attribute sensor_dev_attr_##_name = {     \
+       .dev_attr =     __ATTR(_name,_mode,_show,_store),       \
+       .index =        _index,                                 \
+}
+
+#endif /* _LINUX_HWMON_SYSFS_H */
index 89270ce51470329b2627704081dc02cc3e149819..33f08258f22b4077e4c247e5196b59fa01c14c2c 100644 (file)
 #define I2C_DRIVERID_TDA7313   62      /* TDA7313 audio processor      */
 #define I2C_DRIVERID_MAX6900   63      /* MAX6900 real-time clock      */
 #define I2C_DRIVERID_SAA7114H  64      /* video decoder                */
+#define I2C_DRIVERID_DS1374    65      /* DS1374 real time clock       */
 
 
 #define I2C_DRIVERID_EXP0      0xF0    /* experimental use id's        */
diff --git a/include/linux/i2c-sysfs.h b/include/linux/i2c-sysfs.h
deleted file mode 100644 (file)
index d7bf6ce..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  i2c-sysfs.h - i2c chip driver sysfs defines
- *
- *  Copyright (C) 2005 Yani Ioannou <yani.ioannou@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef _LINUX_I2C_SYSFS_H
-#define _LINUX_I2C_SYSFS_H
-
-struct sensor_device_attribute{
-       struct device_attribute dev_attr;
-       int index;
-};
-#define to_sensor_dev_attr(_dev_attr) \
-       container_of(_dev_attr, struct sensor_device_attribute, dev_attr)
-
-#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index)    \
-struct sensor_device_attribute sensor_dev_attr_##_name = {     \
-       .dev_attr =     __ATTR(_name,_mode,_show,_store),       \
-       .index =        _index,                                 \
-}
-
-#endif /* _LINUX_I2C_SYSFS_H */
index 974835e3530f44a845a7811ff0294ad2273143bd..41d0635e0ba94380a3311de7640833cfee57020a 100644 (file)
@@ -97,3 +97,15 @@ static inline int vid_from_reg(int val, int vrm)
                                     2050 - (val) * 50);
        }
 }
+
+static inline int vid_to_reg(int val, int vrm)
+{
+       switch (vrm) {
+       case 91:                /* VRM 9.1 */
+       case 90:                /* VRM 9.0 */
+               return ((val >= 1100) && (val <= 1850) ?
+                       ((18499 - val * 10) / 25 + 5) / 10 : -1);
+       default:
+               return -1;
+       }
+}
index ebcd745f4cd6f730702b5f00821d5d6448ce12e6..be837b13f2978d027156ee7459c8453da6cdee15 100644 (file)
@@ -290,11 +290,8 @@ static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
  */
 struct i2c_client_address_data {
        unsigned short *normal_i2c;
-       unsigned short *normal_i2c_range;
        unsigned short *probe;
-       unsigned short *probe_range;
        unsigned short *ignore;
-       unsigned short *ignore_range;
        unsigned short *force;
 };
 
@@ -563,24 +560,15 @@ union i2c_smbus_data {
 #define I2C_CLIENT_INSMOD \
   I2C_CLIENT_MODULE_PARM(probe, \
                       "List of adapter,address pairs to scan additionally"); \
-  I2C_CLIENT_MODULE_PARM(probe_range, \
-                      "List of adapter,start-addr,end-addr triples to scan " \
-                      "additionally"); \
   I2C_CLIENT_MODULE_PARM(ignore, \
                       "List of adapter,address pairs not to scan"); \
-  I2C_CLIENT_MODULE_PARM(ignore_range, \
-                      "List of adapter,start-addr,end-addr triples not to " \
-                      "scan"); \
   I2C_CLIENT_MODULE_PARM(force, \
                       "List of adapter,address pairs to boldly assume " \
                       "to be present"); \
        static struct i2c_client_address_data addr_data = {             \
                        .normal_i2c =           normal_i2c,             \
-                       .normal_i2c_range =     normal_i2c_range,       \
                        .probe =                probe,                  \
-                       .probe_range =          probe_range,            \
                        .ignore =               ignore,                 \
-                       .ignore_range =         ignore_range,           \
                        .force =                force,                  \
                }
 
diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h
new file mode 100644 (file)
index 0000000..3dd18b7
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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) 2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#ifndef _LINUX_IOC4_H
+#define _LINUX_IOC4_H
+
+#include <linux/interrupt.h>
+
+/***************
+ * Definitions *
+ ***************/
+
+/* Miscellaneous values inherent to hardware */
+
+#define IOC4_EXTINT_COUNT_DIVISOR 520  /* PCI clocks per COUNT tick */
+
+/***********************************
+ * Structures needed by subdrivers *
+ ***********************************/
+
+/* This structure fully describes the IOC4 miscellaneous registers which
+ * appear at bar[0]+0x00000 through bar[0]+0x0005c.  The corresponding
+ * PCI resource is managed by the main IOC4 driver because it contains
+ * registers of interest to many different IOC4 subdrivers.
+ */
+struct ioc4_misc_regs {
+       /* Miscellaneous IOC4 registers */
+       union ioc4_pci_err_addr_l {
+               uint32_t raw;
+               struct {
+                       uint32_t valid:1;       /* Address captured */
+                       uint32_t master_id:4;   /* Unit causing error
+                                                * 0/1: Serial port 0 TX/RX
+                                                * 2/3: Serial port 1 TX/RX
+                                                * 4/5: Serial port 2 TX/RX
+                                                * 6/7: Serial port 3 TX/RX
+                                                * 8: ATA/ATAPI
+                                                * 9-15: Undefined
+                                                */
+                       uint32_t mul_err:1;     /* Multiple errors occurred */
+                       uint32_t addr:26;       /* Bits 31-6 of error addr */
+               } fields;
+       } pci_err_addr_l;
+       uint32_t pci_err_addr_h;        /* Bits 63-32 of error addr */
+       union ioc4_sio_int {
+               uint32_t raw;
+               struct {
+                       uint8_t tx_mt:1;        /* TX ring buffer empty */
+                       uint8_t rx_full:1;      /* RX ring buffer full */
+                       uint8_t rx_high:1;      /* RX high-water exceeded */
+                       uint8_t rx_timer:1;     /* RX timer has triggered */
+                       uint8_t delta_dcd:1;    /* DELTA_DCD seen */
+                       uint8_t delta_cts:1;    /* DELTA_CTS seen */
+                       uint8_t intr_pass:1;    /* Interrupt pass-through */
+                       uint8_t tx_explicit:1;  /* TX, MCW, or delay complete */
+               } fields[4];
+       } sio_ir;               /* Serial interrupt state */
+       union ioc4_other_int {
+               uint32_t raw;
+               struct {
+                       uint32_t ata_int:1;     /* ATA port passthru */
+                       uint32_t ata_memerr:1;  /* ATA halted by mem error */
+                       uint32_t memerr:4;      /* Serial halted by mem err */
+                       uint32_t kbd_int:1;     /* kbd/mouse intr asserted */
+                       uint32_t reserved:16;   /* zero */
+                       uint32_t rt_int:1;      /* INT_OUT section latch */
+                       uint32_t gen_int:8;     /* Intr. from generic pins */
+               } fields;
+       } other_ir;             /* Other interrupt state */
+       union ioc4_sio_int sio_ies;     /* Serial interrupt enable set */
+       union ioc4_other_int other_ies; /* Other interrupt enable set */
+       union ioc4_sio_int sio_iec;     /* Serial interrupt enable clear */
+       union ioc4_other_int other_iec; /* Other interrupt enable clear */
+       union ioc4_sio_cr {
+               uint32_t raw;
+               struct {
+                       uint32_t cmd_pulse:4;   /* Bytebus strobe width */
+                       uint32_t arb_diag:3;    /* PCI bus requester */
+                       uint32_t sio_diag_idle:1;       /* Active ser req? */
+                       uint32_t ata_diag_idle:1;       /* Active ATA req? */
+                       uint32_t ata_diag_active:1;     /* ATA req is winner */
+                       uint32_t reserved:22;   /* zero */
+               } fields;
+       } sio_cr;
+       uint32_t unused1;
+       union ioc4_int_out {
+               uint32_t raw;
+               struct {
+                       uint32_t count:16;      /* Period control */
+                       uint32_t mode:3;        /* Output signal shape */
+                       uint32_t reserved:11;   /* zero */
+                       uint32_t diag:1;        /* Timebase control */
+                       uint32_t int_out:1;     /* Current value */
+               } fields;
+       } int_out;              /* External interrupt output control */
+       uint32_t unused2;
+       union ioc4_gpcr {
+               uint32_t raw;
+               struct {
+                       uint32_t dir:8; /* Pin direction */
+                       uint32_t edge:8;        /* Edge/level mode */
+                       uint32_t reserved1:4;   /* zero */
+                       uint32_t int_out_en:1;  /* INT_OUT enable */
+                       uint32_t reserved2:11;  /* zero */
+               } fields;
+       } gpcr_s;               /* Generic PIO control set */
+       union ioc4_gpcr gpcr_c; /* Generic PIO control clear */
+       union ioc4_gpdr {
+               uint32_t raw;
+               struct {
+                       uint32_t gen_pin:8;     /* State of pins */
+                       uint32_t reserved:24;
+               } fields;
+       } gpdr;                 /* Generic PIO data */
+       uint32_t unused3;
+       union ioc4_gppr {
+               uint32_t raw;
+               struct {
+                       uint32_t gen_pin:1;     /* Single pin state */
+                       uint32_t reserved:31;
+               } fields;
+       } gppr[8];              /* Generic PIO pins */
+};
+
+/* Masks for GPCR DIR pins */
+#define IOC4_GPCR_DIR_0 0x01   /* External interrupt output */
+#define IOC4_GPCR_DIR_1 0x02   /* External interrupt input */
+#define IOC4_GPCR_DIR_2 0x04
+#define IOC4_GPCR_DIR_3 0x08   /* Keyboard/mouse presence */
+#define IOC4_GPCR_DIR_4 0x10   /* Ser. port 0 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_5 0x20   /* Ser. port 1 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_6 0x40   /* Ser. port 2 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_7 0x80   /* Ser. port 3 xcvr select (0=232, 1=422) */
+
+/* Masks for GPCR EDGE pins */
+#define IOC4_GPCR_EDGE_0 0x01
+#define IOC4_GPCR_EDGE_1 0x02  /* External interrupt input */
+#define IOC4_GPCR_EDGE_2 0x04
+#define IOC4_GPCR_EDGE_3 0x08
+#define IOC4_GPCR_EDGE_4 0x10
+#define IOC4_GPCR_EDGE_5 0x20
+#define IOC4_GPCR_EDGE_6 0x40
+#define IOC4_GPCR_EDGE_7 0x80
+
+/* One of these per IOC4 */
+struct ioc4_driver_data {
+       struct list_head idd_list;
+       unsigned long idd_bar0;
+       struct pci_dev *idd_pdev;
+       const struct pci_device_id *idd_pci_id;
+       struct __iomem ioc4_misc_regs *idd_misc_regs;
+       unsigned long count_period;
+       void *idd_serial_data;
+};
+
+/* One per submodule */
+struct ioc4_submodule {
+       struct list_head is_list;
+       char *is_name;
+       struct module *is_owner;
+       int (*is_probe) (struct ioc4_driver_data *);
+       int (*is_remove) (struct ioc4_driver_data *);
+};
+
+#define IOC4_NUM_CARDS         8       /* max cards per partition */
+
+/**********************************
+ * Functions needed by submodules *
+ **********************************/
+
+extern int ioc4_register_submodule(struct ioc4_submodule *);
+extern void ioc4_unregister_submodule(struct ioc4_submodule *);
+
+#endif                         /* _LINUX_IOC4_H */
diff --git a/include/linux/ioc4_common.h b/include/linux/ioc4_common.h
deleted file mode 100644 (file)
index b03bcc4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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) 2005 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-#ifndef _LINUX_IOC4_COMMON_H
-#define _LINUX_IOC4_COMMON_H
-
-/* prototypes */
-
-int ioc4_serial_init(void);
-
-int ioc4_serial_attach_one(struct pci_dev *pdev, const struct
-                               pci_device_id *pci_id);
-int ioc4_ide_attach_one(struct pci_dev *pdev, const struct
-                               pci_device_id *pci_id);
-
-#endif /* _LINUX_IOC4_COMMON_H */
index c3ff4d1016675fb8d8309b03e090f603bd1ee69e..7fc1022be9ee13254dbfd7a2f6bf67e9c20cb1f6 100644 (file)
@@ -47,6 +47,10 @@ struct hw_interrupt_type {
        void (*ack)(unsigned int irq);
        void (*end)(unsigned int irq);
        void (*set_affinity)(unsigned int irq, cpumask_t dest);
+       /* Currently used only by UML, might disappear one day.*/
+#ifdef CONFIG_IRQ_RELEASE_METHOD
+       void (*release)(unsigned int irq, void *dev_id);
+#endif
 };
 
 typedef struct hw_interrupt_type  hw_irq_controller;
index 17518fe0b311aa0ed08122bc459970d6a21ea139..1813b162b0a8a009531be6aed515be1c4cfa7480 100644 (file)
@@ -691,6 +691,12 @@ extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
 extern void si_meminfo_node(struct sysinfo *val, int nid);
 
+#ifdef CONFIG_NUMA
+extern void setup_per_cpu_pageset(void);
+#else
+static inline void setup_per_cpu_pageset(void) {}
+#endif
+
 /* prio_tree.c */
 void vma_prio_tree_add(struct vm_area_struct *, struct vm_area_struct *old);
 void vma_prio_tree_insert(struct vm_area_struct *, struct prio_tree_root *);
index e530c6c092f1610535f50f24f689bc45e1bbf7ac..4733d35d8223bf847bc6b31ff7e705da8adb45ce 100644 (file)
@@ -63,6 +63,12 @@ struct per_cpu_pageset {
 #endif
 } ____cacheline_aligned_in_smp;
 
+#ifdef CONFIG_NUMA
+#define zone_pcp(__z, __cpu) ((__z)->pageset[(__cpu)])
+#else
+#define zone_pcp(__z, __cpu) (&(__z)->pageset[(__cpu)])
+#endif
+
 #define ZONE_DMA               0
 #define ZONE_NORMAL            1
 #define ZONE_HIGHMEM           2
@@ -122,8 +128,11 @@ struct zone {
         */
        unsigned long           lowmem_reserve[MAX_NR_ZONES];
 
+#ifdef CONFIG_NUMA
+       struct per_cpu_pageset  *pageset[NR_CPUS];
+#else
        struct per_cpu_pageset  pageset[NR_CPUS];
-
+#endif
        /*
         * free areas of different sizes
         */
@@ -144,6 +153,14 @@ struct zone {
        unsigned long           pages_scanned;     /* since last reclaim */
        int                     all_unreclaimable; /* All pages pinned */
 
+       /*
+        * Does the allocator try to reclaim pages from the zone as soon
+        * as it fails a watermark_ok() in __alloc_pages?
+        */
+       int                     reclaim_pages;
+       /* A count of how many reclaimers are scanning this zone */
+       atomic_t                reclaim_in_progress;
+
        /*
         * prev_priority holds the scanning priority for this zone.  It is
         * defined as the scanning priority at which we achieved our reclaim
@@ -381,7 +398,7 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, struct file *,
 
 #include <linux/topology.h>
 /* Returns the number of the current Node. */
-#define numa_node_id()         (cpu_to_node(_smp_processor_id()))
+#define numa_node_id()         (cpu_to_node(raw_smp_processor_id()))
 
 #ifndef CONFIG_DISCONTIGMEM
 
index 39ab8c6b5652edefe8a85559692dac1395c7b8fe..f5a6695d4d21335dddf2aa0da868c31fad454270 100644 (file)
 #define PG_active               6
 #define PG_slab                         7      /* slab debug (Suparna wants this) */
 
-#define PG_highmem              8
-#define PG_checked              9      /* kill me in 2.5.<early>. */
-#define PG_arch_1              10
-#define PG_reserved            11
-
-#define PG_private             12      /* Has something at ->private */
-#define PG_writeback           13      /* Page is under writeback */
-#define PG_nosave              14      /* Used for system suspend/resume */
-#define PG_compound            15      /* Part of a compound page */
-
-#define PG_swapcache           16      /* Swap page: swp_entry_t in private */
-#define PG_mappedtodisk                17      /* Has blocks allocated on-disk */
-#define PG_reclaim             18      /* To be reclaimed asap */
-#define PG_nosave_free         19      /* Free, should not be written */
-#define PG_uncached            20      /* Page has been mapped as uncached */
+#define PG_checked              8      /* kill me in 2.5.<early>. */
+#define PG_arch_1               9
+#define PG_reserved            10
+#define PG_private             11      /* Has something at ->private */
+
+#define PG_writeback           12      /* Page is under writeback */
+#define PG_nosave              13      /* Used for system suspend/resume */
+#define PG_compound            14      /* Part of a compound page */
+#define PG_swapcache           15      /* Swap page: swp_entry_t in private */
+
+#define PG_mappedtodisk                16      /* Has blocks allocated on-disk */
+#define PG_reclaim             17      /* To be reclaimed asap */
+#define PG_nosave_free         18      /* Free, should not be written */
+#define PG_uncached            19      /* Page has been mapped as uncached */
 
 /*
  * Global page accounting.  One instance per CPU.  Only unsigned longs are
@@ -136,8 +135,8 @@ struct page_state {
 
 extern void get_page_state(struct page_state *ret);
 extern void get_full_page_state(struct page_state *ret);
-extern unsigned long __read_page_state(unsigned offset);
-extern void __mod_page_state(unsigned offset, unsigned long delta);
+extern unsigned long __read_page_state(unsigned long offset);
+extern void __mod_page_state(unsigned long offset, unsigned long delta);
 
 #define read_page_state(member) \
        __read_page_state(offsetof(struct page_state, member))
@@ -215,7 +214,7 @@ extern void __mod_page_state(unsigned offset, unsigned long delta);
 #define TestSetPageSlab(page)  test_and_set_bit(PG_slab, &(page)->flags)
 
 #ifdef CONFIG_HIGHMEM
-#define PageHighMem(page)      test_bit(PG_highmem, &(page)->flags)
+#define PageHighMem(page)      is_highmem(page_zone(page))
 #else
 #define PageHighMem(page)      0 /* needed to optimize away at compile time */
 #endif
index 0422031161baa8531f8d189f50fa0e52491bd955..d9a25647a29523b789ebd6346e62f1f7981cb232 100644 (file)
@@ -52,12 +52,12 @@ void release_pages(struct page **pages, int nr, int cold);
 
 static inline struct page *page_cache_alloc(struct address_space *x)
 {
-       return alloc_pages(mapping_gfp_mask(x), 0);
+       return alloc_pages(mapping_gfp_mask(x)|__GFP_NORECLAIM, 0);
 }
 
 static inline struct page *page_cache_alloc_cold(struct address_space *x)
 {
-       return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0);
+       return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD|__GFP_NORECLAIM, 0);
 }
 
 typedef int filler_t(void *, struct page *);
index b8b4ebf9abf1f3b28089030edcb067f4f08a080f..63e89e47b8e98b118bd7f8f088ea2f54c2ec37a9 100644 (file)
 #define PCI_DEVICE_ID_CT_65550         0x00e0
 #define PCI_DEVICE_ID_CT_65554         0x00e4
 #define PCI_DEVICE_ID_CT_65555         0x00e5
+#define PCI_DEVICE_ID_CT_69000         0x00c0
 
 #define PCI_VENDOR_ID_MIRO             0x1031
 #define PCI_DEVICE_ID_MIRO_36050       0x5601
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
new file mode 100644 (file)
index 0000000..e24b74b
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
+ *
+ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
+ */
+#ifndef BITMAP_H
+#define BITMAP_H 1
+
+#define BITMAP_MAJOR 3
+#define BITMAP_MINOR 38
+
+/*
+ * in-memory bitmap:
+ *
+ * Use 16 bit block counters to track pending writes to each "chunk".
+ * The 2 high order bits are special-purpose, the first is a flag indicating
+ * whether a resync is needed.  The second is a flag indicating whether a
+ * resync is active.
+ * This means that the counter is actually 14 bits:
+ *
+ * +--------+--------+------------------------------------------------+
+ * | resync | resync |               counter                          |
+ * | needed | active |                                                |
+ * |  (0-1) |  (0-1) |              (0-16383)                         |
+ * +--------+--------+------------------------------------------------+
+ *
+ * The "resync needed" bit is set when:
+ *    a '1' bit is read from storage at startup.
+ *    a write request fails on some drives
+ *    a resync is aborted on a chunk with 'resync active' set
+ * It is cleared (and resync-active set) when a resync starts across all drives
+ * of the chunk.
+ *
+ *
+ * The "resync active" bit is set when:
+ *    a resync is started on all drives, and resync_needed is set.
+ *       resync_needed will be cleared (as long as resync_active wasn't already set).
+ * It is cleared when a resync completes.
+ *
+ * The counter counts pending write requests, plus the on-disk bit.
+ * When the counter is '1' and the resync bits are clear, the on-disk
+ * bit can be cleared aswell, thus setting the counter to 0.
+ * When we set a bit, or in the counter (to start a write), if the fields is
+ * 0, we first set the disk bit and set the counter to 1.
+ *
+ * If the counter is 0, the on-disk bit is clear and the stipe is clean
+ * Anything that dirties the stipe pushes the counter to 2 (at least)
+ * and sets the on-disk bit (lazily).
+ * If a periodic sweep find the counter at 2, it is decremented to 1.
+ * If the sweep find the counter at 1, the on-disk bit is cleared and the
+ * counter goes to zero.
+ *
+ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block
+ * counters as a fallback when "page" memory cannot be allocated:
+ *
+ * Normal case (page memory allocated):
+ *
+ *     page pointer (32-bit)
+ *
+ *     [ ] ------+
+ *               |
+ *               +-------> [   ][   ]..[   ] (4096 byte page == 2048 counters)
+ *                          c1   c2    c2048
+ *
+ * Hijacked case (page memory allocation failed):
+ *
+ *     hijacked page pointer (32-bit)
+ *
+ *     [                 ][              ] (no page memory allocated)
+ *      counter #1 (16-bit) counter #2 (16-bit)
+ *
+ */
+
+#ifdef __KERNEL__
+
+#define PAGE_BITS (PAGE_SIZE << 3)
+#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3)
+
+typedef __u16 bitmap_counter_t;
+#define COUNTER_BITS 16
+#define COUNTER_BIT_SHIFT 4
+#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
+#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
+
+#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
+#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2)))
+#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1)
+#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK)
+#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK)
+#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX)
+
+/* how many counters per page? */
+#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS)
+/* same, except a shift value for more efficient bitops */
+#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT)
+/* same, except a mask value for more efficient bitops */
+#define PAGE_COUNTER_MASK  (PAGE_COUNTER_RATIO - 1)
+
+#define BITMAP_BLOCK_SIZE 512
+#define BITMAP_BLOCK_SHIFT 9
+
+/* how many blocks per chunk? (this is variable) */
+#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT)
+#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
+#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)
+
+/* when hijacked, the counters and bits represent even larger "chunks" */
+/* there will be 1024 chunks represented by each counter in the page pointers */
+#define PAGEPTR_BLOCK_RATIO(bitmap) \
+                       (CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
+#define PAGEPTR_BLOCK_SHIFT(bitmap) \
+                       (CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
+#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)
+
+/*
+ * on-disk bitmap:
+ *
+ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap
+ * file a page at a time. There's a superblock at the start of the file.
+ */
+
+/* map chunks (bits) to file pages - offset by the size of the superblock */
+#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3))
+
+#endif
+
+/*
+ * bitmap structures:
+ */
+
+#define BITMAP_MAGIC 0x6d746962
+
+/* use these for bitmap->flags and bitmap->sb->state bit-fields */
+enum bitmap_state {
+       BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
+       BITMAP_STALE  = 0x002  /* the bitmap file is out of date or had -EIO */
+};
+
+/* the superblock at the front of the bitmap file -- little endian */
+typedef struct bitmap_super_s {
+       __u32 magic;        /*  0  BITMAP_MAGIC */
+       __u32 version;      /*  4  the bitmap major for now, could change... */
+       __u8  uuid[16];     /*  8  128 bit uuid - must match md device uuid */
+       __u64 events;       /* 24  event counter for the bitmap (1)*/
+       __u64 events_cleared;/*32  event counter when last bit cleared (2) */
+       __u64 sync_size;    /* 40  the size of the md device's sync range(3) */
+       __u32 state;        /* 48  bitmap state information */
+       __u32 chunksize;    /* 52  the bitmap chunk size in bytes */
+       __u32 daemon_sleep; /* 56  seconds between disk flushes */
+
+       __u8  pad[256 - 60]; /* set to zero */
+} bitmap_super_t;
+
+/* notes:
+ * (1) This event counter is updated before the eventcounter in the md superblock
+ *    When a bitmap is loaded, it is only accepted if this event counter is equal
+ *    to, or one greater than, the event counter in the superblock.
+ * (2) This event counter is updated when the other one is *if*and*only*if* the
+ *    array is not degraded.  As bits are not cleared when the array is degraded,
+ *    this represents the last time that any bits were cleared.
+ *    If a device is being added that has an event count with this value or
+ *    higher, it is accepted as conforming to the bitmap.
+ * (3)This is the number of sectors represented by the bitmap, and is the range that
+ *    resync happens across.  For raid1 and raid5/6 it is the size of individual
+ *    devices.  For raid10 it is the size of the array.
+ */
+
+#ifdef __KERNEL__
+
+/* the in-memory bitmap is represented by bitmap_pages */
+struct bitmap_page {
+       /*
+        * map points to the actual memory page
+        */
+       char *map;
+       /*
+        * in emergencies (when map cannot be alloced), hijack the map
+        * pointer and use it as two counters itself
+        */
+       unsigned int hijacked:1;
+       /*
+        * count of dirty bits on the page
+        */
+       unsigned int  count:31;
+};
+
+/* keep track of bitmap file pages that have pending writes on them */
+struct page_list {
+       struct list_head list;
+       struct page *page;
+};
+
+/* the main bitmap structure - one per mddev */
+struct bitmap {
+       struct bitmap_page *bp;
+       unsigned long pages; /* total number of pages in the bitmap */
+       unsigned long missing_pages; /* number of pages not yet allocated */
+
+       mddev_t *mddev; /* the md device that the bitmap is for */
+
+       int counter_bits; /* how many bits per block counter */
+
+       /* bitmap chunksize -- how much data does each bit represent? */
+       unsigned long chunksize;
+       unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
+       unsigned long chunks; /* total number of data chunks for the array */
+
+       /* We hold a count on the chunk currently being synced, and drop
+        * it when the last block is started.  If the resync is aborted
+        * midway, we need to be able to drop that count, so we remember
+        * the counted chunk..
+        */
+       unsigned long syncchunk;
+
+       __u64   events_cleared;
+
+       /* bitmap spinlock */
+       spinlock_t lock;
+
+       long offset; /* offset from superblock if file is NULL */
+       struct file *file; /* backing disk file */
+       struct page *sb_page; /* cached copy of the bitmap file superblock */
+       struct page **filemap; /* list of cache pages for the file */
+       unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
+       unsigned long file_pages; /* number of pages in the file */
+
+       unsigned long flags;
+
+       /*
+        * the bitmap daemon - periodically wakes up and sweeps the bitmap
+        * file, cleaning up bits and flushing out pages to disk as necessary
+        */
+       unsigned long daemon_lastrun; /* jiffies of last run */
+       unsigned long daemon_sleep; /* how many seconds between updates? */
+
+       /*
+        * bitmap_writeback_daemon waits for file-pages that have been written,
+        * as there is no way to get a call-back when a page write completes.
+        */
+       mdk_thread_t *writeback_daemon;
+       spinlock_t write_lock;
+       wait_queue_head_t write_wait;
+       struct list_head complete_pages;
+       mempool_t *write_pool;
+};
+
+/* the bitmap API */
+
+/* these are used only by md/bitmap */
+int  bitmap_create(mddev_t *mddev);
+void bitmap_destroy(mddev_t *mddev);
+int  bitmap_active(struct bitmap *bitmap);
+
+char *file_path(struct file *file, char *buf, int count);
+void bitmap_print_sb(struct bitmap *bitmap);
+int bitmap_update_sb(struct bitmap *bitmap);
+
+int  bitmap_setallbits(struct bitmap *bitmap);
+void bitmap_write_all(struct bitmap *bitmap);
+
+/* these are exported */
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+                    int success);
+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
+void bitmap_close_sync(struct bitmap *bitmap);
+
+int bitmap_unplug(struct bitmap *bitmap);
+int bitmap_daemon_work(struct bitmap *bitmap);
+#endif
+
+#endif
index a6a67d102bfa67e1a49c4d875889f40bf2a167bf..ffa316ce4dc834aa3ab4a4e8967e95a47c0b5c49 100644 (file)
  */
 #define MD_MAJOR_VERSION                0
 #define MD_MINOR_VERSION                90
-#define MD_PATCHLEVEL_VERSION           1
+/*
+ * MD_PATCHLEVEL_VERSION indicates kernel functionality.
+ * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
+ *     and major_version/minor_version accordingly
+ * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
+ *     in the super status byte
+ */
+#define MD_PATCHLEVEL_VERSION           2
 
 extern int register_md_personality (int p_num, mdk_personality_t *p);
 extern int unregister_md_personality (int p_num);
@@ -69,7 +76,7 @@ extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
 extern void md_unregister_thread (mdk_thread_t *thread);
 extern void md_wakeup_thread(mdk_thread_t *thread);
 extern void md_check_recovery(mddev_t *mddev);
-extern void md_write_start(mddev_t *mddev);
+extern void md_write_start(mddev_t *mddev, struct bio *bi);
 extern void md_write_end(mddev_t *mddev);
 extern void md_handle_safemode(mddev_t *mddev);
 extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
@@ -78,6 +85,12 @@ extern void md_unplug_mddev(mddev_t *mddev);
 
 extern void md_print_devices (void);
 
+extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+                          sector_t sector, int size, struct page *page);
+extern int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+                       struct page *page, int rw);
+
+
 #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
 
 #endif 
index c9a0d4013be7c0273a17424b0820cdd16e945fc8..8c14ba565a45b95093b0a65e113bda2898f1d358 100644 (file)
@@ -15,6 +15,9 @@
 #ifndef _MD_K_H
 #define _MD_K_H
 
+/* and dm-bio-list.h is not under include/linux because.... ??? */
+#include "../../../drivers/md/dm-bio-list.h"
+
 #define MD_RESERVED       0UL
 #define LINEAR            1UL
 #define RAID0             2UL
@@ -180,6 +183,10 @@ struct mdk_rdev_s
 
        int desc_nr;                    /* descriptor index in the superblock */
        int raid_disk;                  /* role of device in array */
+       int saved_raid_disk;            /* role that device used to have in the
+                                        * array and could again if we did a partial
+                                        * resync from the bitmap
+                                        */
 
        atomic_t        nr_pending;     /* number of pending requests.
                                         * only maintained for arrays that
@@ -252,6 +259,11 @@ struct mddev_s
        atomic_t                        recovery_active; /* blocks scheduled, but not written */
        wait_queue_head_t               recovery_wait;
        sector_t                        recovery_cp;
+
+       spinlock_t                      write_lock;
+       wait_queue_head_t               sb_wait;        /* for waiting on superblock updates */
+       atomic_t                        pending_writes; /* number of active superblock writes */
+
        unsigned int                    safemode;       /* if set, update "clean" superblock
                                                         * when no writes pending.
                                                         */ 
@@ -260,6 +272,13 @@ struct mddev_s
        atomic_t                        writes_pending; 
        request_queue_t                 *queue; /* for plugging ... */
 
+       struct bitmap                   *bitmap; /* the bitmap for the device */
+       struct file                     *bitmap_file; /* the bitmap file */
+       long                            bitmap_offset; /* offset from superblock of
+                                                       * start of bitmap. May be
+                                                       * negative, but not '0'
+                                                       */
+
        struct list_head                all_mddevs;
 };
 
@@ -291,7 +310,7 @@ struct mdk_personality_s
        int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
        int (*hot_remove_disk) (mddev_t *mddev, int number);
        int (*spare_active) (mddev_t *mddev);
-       int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
+       sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
        int (*resize) (mddev_t *mddev, sector_t sectors);
        int (*reshape) (mddev_t *mddev, int raid_disks);
        int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
@@ -334,6 +353,7 @@ typedef struct mdk_thread_s {
        unsigned long           flags;
        struct completion       *event;
        struct task_struct      *tsk;
+       unsigned long           timeout;
        const char              *name;
 } mdk_thread_t;
 
index 8ba95d67329f0b6189d80795ee807f62e8ae17b7..dc65cd4354942d4efd7b31bd9eba4bba7c8bf405 100644 (file)
@@ -96,6 +96,7 @@ typedef struct mdp_device_descriptor_s {
 #define MD_SB_CLEAN            0
 #define MD_SB_ERRORS           1
 
+#define        MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
 typedef struct mdp_superblock_s {
        /*
         * Constant generic information
@@ -184,7 +185,7 @@ struct mdp_superblock_1 {
        /* constant array information - 128 bytes */
        __u32   magic;          /* MD_SB_MAGIC: 0xa92b4efc - little endian */
        __u32   major_version;  /* 1 */
-       __u32   feature_map;    /* 0 for now */
+       __u32   feature_map;    /* bit 0 set if 'bitmap_offset' is meaningful */
        __u32   pad0;           /* always set to 0 when writing */
 
        __u8    set_uuid[16];   /* user-space generated. */
@@ -197,7 +198,11 @@ struct mdp_superblock_1 {
 
        __u32   chunksize;      /* in 512byte sectors */
        __u32   raid_disks;
-       __u8    pad1[128-96];   /* set to 0 when written */
+       __u32   bitmap_offset;  /* sectors after start of superblock that bitmap starts
+                                * NOTE: signed, so bitmap can be before superblock
+                                * only meaningful of feature_map[0] is set.
+                                */
+       __u8    pad1[128-100];  /* set to 0 when written */
 
        /* constant this-device information - 64 bytes */
        __u64   data_offset;    /* sector start of data, often 0 */
index a2df5c2a42af93e373e3238d97aed33c0319c724..81da20ccec4dadeab0dd13da2ac94b7e7f48243e 100644 (file)
@@ -23,6 +23,7 @@
 #define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
 #define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
 #define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
+#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
 
 /* configuration */
 #define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
@@ -36,6 +37,7 @@
 #define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
 #define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
 #define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
+#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
 
 /* usage */
 #define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
@@ -106,6 +108,11 @@ typedef struct mdu_start_info_s {
 
 } mdu_start_info_t;
 
+typedef struct mdu_bitmap_file_s
+{
+       char pathname[4096];
+} mdu_bitmap_file_t;
+
 typedef struct mdu_param_s
 {
        int                     personality;    /* 1,2,3,4 */
index abbfdd9afe1ec615e288fccced1f5a41b0dafbed..9d93cf12e8901d7cb34f8013d290eb4e8e4d1f1f 100644 (file)
@@ -36,12 +36,21 @@ struct r1_private_data_s {
        spinlock_t              device_lock;
 
        struct list_head        retry_list;
+       /* queue pending writes and submit them on unplug */
+       struct bio_list         pending_bio_list;
+       /* queue of writes that have been unplugged */
+       struct bio_list         flushing_bio_list;
+
        /* for use when syncing mirrors: */
 
        spinlock_t              resync_lock;
-       int nr_pending;
-       int barrier;
+       int                     nr_pending;
+       int                     barrier;
        sector_t                next_resync;
+       int                     fullsync;  /* set to 1 if a full sync is needed,
+                                           * (fresh device added).
+                                           * Cleared when a sync completes.
+                                           */
 
        wait_queue_head_t       wait_idle;
        wait_queue_head_t       wait_resume;
@@ -85,14 +94,17 @@ struct r1bio_s {
        int                     read_disk;
 
        struct list_head        retry_list;
+       struct bitmap_update    *bitmap_update;
        /*
         * if the IO is in WRITE direction, then multiple bios are used.
         * We choose the number when they are allocated.
         */
        struct bio              *bios[0];
+       /* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/
 };
 
 /* bits for r1bio.state */
 #define        R1BIO_Uptodate  0
 #define        R1BIO_IsSync    1
+#define        R1BIO_Degraded  2
 #endif
index 4dbb109022f3646ff39b7f64464bebb0200071fc..b58afd97a180274bad8b8904b018aac1c08621ef 100644 (file)
@@ -201,8 +201,8 @@ extern unsigned long
 arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
                          unsigned long len, unsigned long pgoff,
                          unsigned long flags);
-extern void arch_unmap_area(struct vm_area_struct *area);
-extern void arch_unmap_area_topdown(struct vm_area_struct *area);
+extern void arch_unmap_area(struct mm_struct *, unsigned long);
+extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long);
 
 #define set_mm_counter(mm, member, value) (mm)->_##member = (value)
 #define get_mm_counter(mm, member) ((mm)->_##member)
@@ -218,9 +218,10 @@ struct mm_struct {
        unsigned long (*get_unmapped_area) (struct file *filp,
                                unsigned long addr, unsigned long len,
                                unsigned long pgoff, unsigned long flags);
-       void (*unmap_area) (struct vm_area_struct *area);
-       unsigned long mmap_base;                /* base of mmap area */
-       unsigned long free_area_cache;          /* first hole */
+       void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
+        unsigned long mmap_base;               /* base of mmap area */
+        unsigned long cached_hole_size;         /* if non-zero, the largest hole below free_area_cache */
+       unsigned long free_area_cache;          /* first hole of size cached_hole_size or larger */
        pgd_t * pgd;
        atomic_t mm_users;                      /* How many users with user space? */
        atomic_t mm_count;                      /* How many references to "struct mm_struct" (users count as 1) */
index dcf1db3b35d338ba459d5b53015671a767892edd..9dfa3ee769ae2c02846a19a8f4a7b727a78baf33 100644 (file)
@@ -92,10 +92,7 @@ void smp_prepare_boot_cpu(void);
 /*
  *     These macros fold the SMP functionality into a single CPU system
  */
-
-#if !defined(__smp_processor_id) || !defined(CONFIG_PREEMPT)
-# define smp_processor_id()                    0
-#endif
+#define raw_smp_processor_id()                 0
 #define hard_smp_processor_id()                        0
 #define smp_call_function(func,info,retry,wait)        ({ 0; })
 #define on_each_cpu(func,info,retry,wait)      ({ func(info); 0; })
@@ -106,30 +103,25 @@ static inline void smp_send_reschedule(int cpu) { }
 #endif /* !SMP */
 
 /*
- * DEBUG_PREEMPT support: check whether smp_processor_id() is being
- * used in a preemption-safe way.
+ * smp_processor_id(): get the current CPU ID.
  *
- * An architecture has to enable this debugging code explicitly.
- * It can do so by renaming the smp_processor_id() macro to
- * __smp_processor_id().  This should only be done after some minimal
- * testing, because usually there are a number of false positives
- * that an architecture will trigger.
+ * if DEBUG_PREEMPT is enabled the we check whether it is
+ * used in a preemption-safe way. (smp_processor_id() is safe
+ * if it's used in a preemption-off critical section, or in
+ * a thread that is bound to the current CPU.)
  *
- * To fix a false positive (i.e. smp_processor_id() use that the
- * debugging code reports but which use for some reason is legal),
- * change the smp_processor_id() reference to _smp_processor_id(),
- * which is the nondebug variant.  NOTE: don't use this to hack around
- * real bugs.
+ * NOTE: raw_smp_processor_id() is for internal use only
+ * (smp_processor_id() is the preferred variant), but in rare
+ * instances it might also be used to turn off false positives
+ * (i.e. smp_processor_id() use that the debugging code reports but
+ * which use for some reason is legal). Don't use this to hack around
+ * the warning message, as your code might not work under PREEMPT.
  */
-#ifdef __smp_processor_id
-# if defined(CONFIG_PREEMPT) && defined(CONFIG_DEBUG_PREEMPT)
-   extern unsigned int smp_processor_id(void);
-# else
-#  define smp_processor_id() __smp_processor_id()
-# endif
-# define _smp_processor_id() __smp_processor_id()
+#ifdef CONFIG_DEBUG_PREEMPT
+  extern unsigned int debug_smp_processor_id(void);
+# define smp_processor_id() debug_smp_processor_id()
 #else
-# define _smp_processor_id() smp_processor_id()
+# define smp_processor_id() raw_smp_processor_id()
 #endif
 
 #define get_cpu()              ({ preempt_disable(); smp_processor_id(); })
index 3bbc41be9bd0cb097c6c4c75b581e5cae5e02bb2..2343f999e6e11e287fa20532608d81796c3b58db 100644 (file)
@@ -172,7 +172,8 @@ extern int rotate_reclaimable_page(struct page *page);
 extern void swap_setup(void);
 
 /* linux/mm/vmscan.c */
-extern int try_to_free_pages(struct zone **, unsigned int, unsigned int);
+extern int try_to_free_pages(struct zone **, unsigned int);
+extern int zone_reclaim(struct zone *, unsigned int, unsigned int);
 extern int shrink_all_memory(int);
 extern int vm_swappiness;
 
index d34ca8fc67569ccf2d4af632bb1a08862b359ba1..c3cd069a9aca5f17c0c09b6b6a0f2f7a53be6fa9 100644 (file)
@@ -107,7 +107,7 @@ struct rt_cache_stat
 
 extern struct rt_cache_stat *rt_cache_stat;
 #define RT_CACHE_STAT_INC(field)                                         \
-               (per_cpu_ptr(rt_cache_stat, _smp_processor_id())->field++)
+               (per_cpu_ptr(rt_cache_stat, raw_smp_processor_id())->field++)
 
 extern struct ip_rt_acct *ip_rt_acct;
 
index a15ab256276ed971b4d66c55b093dd3e4818c1bb..a36bed8ea21003b70d6edfcf561fb7ff2b1afc71 100644 (file)
@@ -128,18 +128,18 @@ struct linux_mib {
 #define SNMP_STAT_USRPTR(name) (name[1])
 
 #define SNMP_INC_STATS_BH(mib, field)  \
-       (per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field]++)
+       (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field]++)
 #define SNMP_INC_STATS_OFFSET_BH(mib, field, offset)   \
-       (per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field + (offset)]++)
+       (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field + (offset)]++)
 #define SNMP_INC_STATS_USER(mib, field) \
-       (per_cpu_ptr(mib[1], _smp_processor_id())->mibs[field]++)
+       (per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field]++)
 #define SNMP_INC_STATS(mib, field)     \
-       (per_cpu_ptr(mib[!in_softirq()], _smp_processor_id())->mibs[field]++)
+       (per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]++)
 #define SNMP_DEC_STATS(mib, field)     \
-       (per_cpu_ptr(mib[!in_softirq()], _smp_processor_id())->mibs[field]--)
+       (per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]--)
 #define SNMP_ADD_STATS_BH(mib, field, addend)  \
-       (per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field] += addend)
+       (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend)        \
-       (per_cpu_ptr(mib[1], _smp_processor_id())->mibs[field] += addend)
+       (per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field] += addend)
 
 #endif
index 2433e279e0712040dcd6c6a1b372c000cd4bbd7b..1309c12b8f71274faf024a944a8244abf17ed5e3 100644 (file)
@@ -437,6 +437,7 @@ struct snd_ac97_build_ops {
        void (*suspend) (ac97_t *ac97);
        void (*resume) (ac97_t *ac97);
 #endif
+       void (*update_jacks) (ac97_t *ac97);    /* for jack-sharing */
 };
 
 struct _snd_ac97_bus_ops {
@@ -516,6 +517,9 @@ struct _snd_ac97 {
                } ad18xx;
                unsigned int dev_flags;         /* device specific */
        } spec;
+       /* jack-sharing info */
+       unsigned char indep_surround;
+       unsigned char channel_mode;
 };
 
 /* conditions */
@@ -569,8 +573,8 @@ enum {
 };
 
 struct ac97_quirk {
-       unsigned short vendor;  /* PCI vendor id */
-       unsigned short device;  /* PCI device id */
+       unsigned short subvendor; /* PCI subsystem vendor id */
+       unsigned short subdevice; /* PCI sybsystem device id */
        unsigned short mask;    /* device id bit mask, 0 = accept all */
        unsigned int codec_id;  /* codec id (if any), 0 = accept all */
        const char *name;       /* name shown as info */
index a4d149f34541e2b455a528c35096cbfe5b337ace..9974f83cca440a88e6e9af4f30e0b7cc2bad767b 100644 (file)
@@ -113,9 +113,10 @@ enum sndrv_hwdep_iface {
        SNDRV_HWDEP_IFACE_BLUETOOTH,    /* Bluetooth audio */
        SNDRV_HWDEP_IFACE_USX2Y_PCM,    /* Tascam US122, US224 & US428 rawusb pcm */
        SNDRV_HWDEP_IFACE_PCXHR,        /* Digigram PCXHR */
+       SNDRV_HWDEP_IFACE_SB_RC,        /* SB Extigy/Audigy2NX remote control */
 
        /* Don't forget to change the following: */
-       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_PCXHR
+       SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC
 };
 
 struct sndrv_hwdep_info {
@@ -344,7 +345,7 @@ enum sndrv_pcm_hw_param {
        SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME
 };
 
-#define SNDRV_PCM_HW_PARAMS_RUNTIME            (1<<0)
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE         (1<<0)  /* avoid rate resampling */
 
 struct sndrv_interval {
        unsigned int min, max;
@@ -559,7 +560,7 @@ enum {
  *  Timer section - /dev/snd/timer
  */
 
-#define SNDRV_TIMER_VERSION            SNDRV_PROTOCOL_VERSION(2, 0, 2)
+#define SNDRV_TIMER_VERSION            SNDRV_PROTOCOL_VERSION(2, 0, 4)
 
 enum sndrv_timer_class {
        SNDRV_TIMER_CLASS_NONE = -1,
@@ -672,10 +673,11 @@ enum {
        SNDRV_TIMER_IOCTL_INFO = _IOR('T', 0x11, struct sndrv_timer_info),
        SNDRV_TIMER_IOCTL_PARAMS = _IOW('T', 0x12, struct sndrv_timer_params),
        SNDRV_TIMER_IOCTL_STATUS = _IOR('T', 0x14, struct sndrv_timer_status),
-       SNDRV_TIMER_IOCTL_START = _IO('T', 0x20),
-       SNDRV_TIMER_IOCTL_STOP = _IO('T', 0x21),
-       SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0x22),
-       SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0x23),
+       /* The following four ioctls are changed since 1.0.9 due to confliction */
+       SNDRV_TIMER_IOCTL_START = _IO('T', 0xa0),
+       SNDRV_TIMER_IOCTL_STOP = _IO('T', 0xa1),
+       SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0xa2),
+       SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0xa3),
 };
 
 struct sndrv_timer_read {
index 7b9444cd02f400af4242f21c38db416ea4da02da..ef7903c7a3277b63d7860d8c6c9d18bbb9e9230d 100644 (file)
@@ -106,7 +106,7 @@ typedef int (*snd_kctl_ioctl_func_t) (snd_card_t * card,
 void snd_ctl_notify(snd_card_t * card, unsigned int mask, snd_ctl_elem_id_t * id);
 
 snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * kcontrol, unsigned int access);
-snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * kcontrolnew, void * private_data);
+snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * kcontrolnew, void * private_data);
 void snd_ctl_free_one(snd_kcontrol_t * kcontrol);
 int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol);
 int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol);
index 43b6786abae527e4a7ecbaae77def5a778fa7503..c50b91958ff985c4d2028d3edbef9bc1cec5e28e 100644 (file)
@@ -83,7 +83,8 @@
 #define IPR                    0x08            /* Global interrupt pending register            */
                                                /* Clear pending interrupts by writing a 1 to   */
                                                /* the relevant bits and zero to the other bits */
-
+#define IPR_P16V               0x80000000      /* Bit set when the CA0151 P16V chip wishes
+                                                  to interrupt */
 #define IPR_GPIOMSG            0x20000000      /* GPIO message interrupt (RE'd, still not sure 
                                                   which INTE bits enable it)                   */
 
                                                /* Assumes sample lock                          */
 
 /* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS.                        */
+#define SRCS_SPDIFVALID                0x04000000      /* SPDIF stream valid                           */
 #define SRCS_SPDIFLOCKED       0x02000000      /* SPDIF stream locked                          */
 #define SRCS_RATELOCKED                0x01000000      /* Sample rate locked                           */
 #define SRCS_ESTSAMPLERATE     0x0007ffff      /* Do not modify this field.                    */
 #define A_FXWC2                        0x75            /* Selects 0x9f-0x80 for FX recording           */
 
 #define A_SPDIF_SAMPLERATE     0x76            /* Set the sample rate of SPDIF output          */
-#define A_SPDIF_RATE_MASK      0x000000c0
+#define A_SAMPLE_RATE          0x76            /* Various sample rate settings. */
+#define A_SAMPLE_RATE_NOT_USED  0x0ffc111e     /* Bits that are not used and cannot be set.    */
+#define A_SAMPLE_RATE_UNKNOWN  0xf0030001      /* Bits that can be set, but have unknown use.  */
+#define A_SPDIF_RATE_MASK      0x000000e0      /* Any other values for rates, just use 48000   */
 #define A_SPDIF_48000          0x00000000
-#define A_SPDIF_44100          0x00000080
+#define A_SPDIF_192000         0x00000020
 #define A_SPDIF_96000          0x00000040
+#define A_SPDIF_44100          0x00000080
+
+#define A_I2S_CAPTURE_RATE_MASK        0x00000e00      /* This sets the capture PCM rate, but it is    */
+#define A_I2S_CAPTURE_48000    0x00000000      /* unclear if this sets the ADC rate as well.   */
+#define A_I2S_CAPTURE_192000   0x00000200
+#define A_I2S_CAPTURE_96000    0x00000400
+#define A_I2S_CAPTURE_44100    0x00000800
+
+#define A_PCM_RATE_MASK                0x0000e000      /* This sets the playback PCM rate on the P16V  */
+#define A_PCM_48000            0x00000000
+#define A_PCM_192000           0x00002000
+#define A_PCM_96000            0x00004000
+#define A_PCM_44100            0x00008000
 
 /* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell */
 /* 0x7a, 0x7b - lookup tables */
@@ -1039,28 +1057,28 @@ typedef struct {
        u32 vendor;
        u32 device;
        u32 subsystem;
+       unsigned char revision;
        unsigned char emu10k1_chip; /* Original SB Live. Not SB Live 24bit. */
        unsigned char emu10k2_chip; /* Audigy 1 or Audigy 2. */
        unsigned char ca0102_chip;  /* Audigy 1 or Audigy 2. Not SB Audigy 2 Value. */
        unsigned char ca0108_chip;  /* Audigy 2 Value */
        unsigned char ca0151_chip;  /* P16V */
        unsigned char spk71;        /* Has 7.1 speakers */
+       unsigned char sblive51;     /* SBLive! 5.1 - extout 0x11 -> center, 0x12 -> lfe */
        unsigned char spdif_bug;    /* Has Spdif phasing bug */
        unsigned char ac97_chip;    /* Has an AC97 chip */
        unsigned char ecard;        /* APS EEPROM */
-       char * driver;
-       char * name;
+       const char *driver;
+       const char *name;
+       const char *id;         /* for backward compatibility - can be NULL if not needed */
 } emu_chip_details_t;
 
 struct _snd_emu10k1 {
        int irq;
 
        unsigned long port;                     /* I/O port number */
-       unsigned int APS: 1,                    /* APS flag */
-           no_ac97: 1,                         /* no AC'97 */
-           tos_link: 1,                        /* tos link detected */
-           rear_ac97: 1,                       /* rear channels are on AC'97 */
-           spk71:1;                            /* 7.1 configuration (Audigy 2 ZS) */
+       unsigned int tos_link: 1,               /* tos link detected */
+           rear_ac97: 1;                       /* rear channels are on AC'97 */
        const emu_chip_details_t *card_capabilities;    /* Contains profile of card capabilities */
        unsigned int audigy;                    /* is Audigy? */
        unsigned int revision;                  /* chip revision */
@@ -1109,7 +1127,10 @@ struct _snd_emu10k1 {
 
        emu10k1_voice_t voices[NUM_G];
        emu10k1_voice_t p16v_voices[4];
+       emu10k1_voice_t p16v_capture_voice;
        int p16v_device_offset;
+       u32 p16v_capture_source;
+       u32 p16v_capture_channel;
        emu10k1_pcm_mixer_t pcm_mixer[32];
        emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK];
        snd_kcontrol_t *ctl_send_routing;
@@ -1453,7 +1474,6 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
 #endif
 
 typedef struct {
-       unsigned int card;                      /* card type */
        unsigned int internal_tram_size;        /* in samples */
        unsigned int external_tram_size;        /* in samples */
        char fxbus_names[16][32];               /* names of FXBUSes */
index 8b6287a6fff574b8ea21ee3237c27d7936883fba..b4b461ca173d6eb72a58ce7a1079b1c1e9417aaf 100644 (file)
@@ -526,9 +526,6 @@ extern void snd_gf1_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigne
 extern void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr);
 extern void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data);
 extern unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr);
-extern void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data);
-extern unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr);
-extern void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr, unsigned short value, unsigned int count);
 extern void snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
 extern unsigned int snd_gf1_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
 extern void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg);
@@ -544,9 +541,6 @@ extern inline unsigned short snd_gf1_i_read16(snd_gus_card_t * gus, unsigned cha
 {
        return snd_gf1_i_look16(gus, reg | 0x80);
 }
-extern void snd_gf1_i_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigned char data);
-extern void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
-extern unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
 
 extern void snd_gf1_select_active_voices(snd_gus_card_t * gus);
 
@@ -580,10 +574,6 @@ extern void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *
 
 void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup);
 int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block);
-snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
-                                     unsigned int address);
-snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
-                                      unsigned int *share_id);
 snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
                                       char *name, int size, int w_16,
                                       int align, unsigned int *share_id);
@@ -608,23 +598,13 @@ int snd_gf1_dma_transfer_block(snd_gus_card_t * gus,
 /* gus_volume.c */
 
 unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol);
-unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol);
-unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
-                                   unsigned short start,
-                                   unsigned short end,
-                                   unsigned int us);
 unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq2);
-unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens);
-unsigned short snd_gf1_compute_freq(unsigned int freq,
-                                   unsigned int rate,
-                                   unsigned short mix_rate);
 
 /* gus_reset.c */
 
 void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what);
 void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice);
 void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice);
-void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
 void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
 snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client, int port);
 void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice);
@@ -641,9 +621,6 @@ int snd_gf1_pcm_new(snd_gus_card_t * gus, int pcm_dev, int control_index, snd_pc
 
 #ifdef CONFIG_SND_DEBUG
 extern void snd_gf1_print_voice_registers(snd_gus_card_t * gus);
-extern void snd_gf1_print_global_registers(snd_gus_card_t * gus);
-extern void snd_gf1_print_setup_registers(snd_gus_card_t * gus);
-extern void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count, int w_16bit);
 #endif
 
 /* gus.c */
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
new file mode 100644 (file)
index 0000000..c34427c
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef __SOUND_HDSPM_H                /* -*- linux-c -*- */
+#define __SOUND_HDSPM_H
+/*
+ *   Copyright (C) 2003 Winfried Ritsch (IEM)
+ *   based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
+ *                      
+ *    
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This 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.
+ */
+
+/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
+#define HDSPM_MAX_CHANNELS      64
+
+/* -------------------- IOCTL Peak/RMS Meters -------------------- */
+
+typedef struct _snd_hdspm_peak_rms hdspm_peak_rms_t;
+
+/* peam rms level structure like we get from hardware 
+  
+   maybe in future we can memory map it so I just copy it
+   to user on ioctl call now an dont change anything
+   rms are made out of low and high values
+   where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24)
+   (i asume so from the code)
+*/
+
+struct _snd_hdspm_peak_rms {
+
+       unsigned int level_offset[1024];
+
+       unsigned int input_peak[64];
+       unsigned int playback_peak[64];
+       unsigned int output_peak[64];
+       unsigned int xxx_peak[64];      /* not used */
+
+       unsigned int reserved[256];     /* not used */
+
+       unsigned int input_rms_l[64];
+       unsigned int playback_rms_l[64];
+       unsigned int output_rms_l[64];
+       unsigned int xxx_rms_l[64];     /* not used */
+
+       unsigned int input_rms_h[64];
+       unsigned int playback_rms_h[64];
+       unsigned int output_rms_h[64];
+       unsigned int xxx_rms_h[64];     /* not used */
+};
+
+struct sndrv_hdspm_peak_rms_ioctl {
+       hdspm_peak_rms_t *peak;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct sndrv_hdspm_peak_rms_ioctl)
+
+/* ------------ CONFIG block IOCTL ---------------------- */
+
+typedef struct _snd_hdspm_config_info hdspm_config_info_t;
+
+struct _snd_hdspm_config_info {
+       unsigned char pref_sync_ref;
+       unsigned char wordclock_sync_check;
+       unsigned char madi_sync_check;
+       unsigned int system_sample_rate;
+       unsigned int autosync_sample_rate;
+       unsigned char system_clock_mode;
+       unsigned char clock_source;
+       unsigned char autosync_ref;
+       unsigned char line_out;
+       unsigned int passthru;
+       unsigned int analog_out;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdspm_config_info_t)
+
+
+/* get Soundcard Version */
+
+typedef struct _snd_hdspm_version hdspm_version_t;
+
+struct _snd_hdspm_version {
+       unsigned short firmware_rev;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, hdspm_version_t)
+
+
+/* ------------- get Matrix Mixer IOCTL --------------- */
+
+/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte = 32768 Bytes */
+
+/* organisation is 64 channelfader in a continous memory block */
+/* equivalent to hardware definition, maybe for future feature of mmap of them */
+/* each of 64 outputs has 64 infader and 64 outfader: 
+   Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
+
+#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
+
+typedef struct _snd_hdspm_channelfader snd_hdspm_channelfader_t;
+
+struct _snd_hdspm_channelfader {
+       unsigned int in[HDSPM_MIXER_CHANNELS];
+       unsigned int pb[HDSPM_MIXER_CHANNELS];
+};
+
+typedef struct _snd_hdspm_mixer hdspm_mixer_t;
+
+struct _snd_hdspm_mixer {
+       snd_hdspm_channelfader_t ch[HDSPM_MIXER_CHANNELS];
+};
+
+struct sndrv_hdspm_mixer_ioctl {
+       hdspm_mixer_t *mixer;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct sndrv_hdspm_mixer_ioctl)
+
+#endif                         /* __SOUND_HDSPM_H */
index 53fc04d75badf3be8c27075d2d84afe1965bf1f3..d935417575b542bd94cc9ba1cff1dcc9c6fd4445 100644 (file)
@@ -848,23 +848,6 @@ int snd_interval_ratnum(snd_interval_t *i,
 
 void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params);
 void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var);
-int snd_pcm_hw_param_min(snd_pcm_substream_t *substream, 
-                        snd_pcm_hw_params_t *params,
-                        snd_pcm_hw_param_t var,
-                        unsigned int val, int *dir);
-int snd_pcm_hw_param_max(snd_pcm_substream_t *substream, 
-                        snd_pcm_hw_params_t *params,
-                        snd_pcm_hw_param_t var,
-                        unsigned int val, int *dir);
-int snd_pcm_hw_param_setinteger(snd_pcm_substream_t *substream, 
-                               snd_pcm_hw_params_t *params,
-                               snd_pcm_hw_param_t var);
-int snd_pcm_hw_param_first(snd_pcm_substream_t *substream, 
-                          snd_pcm_hw_params_t *params,
-                          snd_pcm_hw_param_t var, int *dir);
-int snd_pcm_hw_param_last(snd_pcm_substream_t *substream, 
-                         snd_pcm_hw_params_t *params,
-                         snd_pcm_hw_param_t var, int *dir);
 int snd_pcm_hw_param_near(snd_pcm_substream_t *substream, 
                          snd_pcm_hw_params_t *params,
                          snd_pcm_hw_param_t var, 
@@ -876,7 +859,6 @@ int snd_pcm_hw_param_set(snd_pcm_substream_t *pcm,
 int snd_pcm_hw_params_choose(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
 
 int snd_pcm_hw_refine(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
-int snd_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
 
 int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream);
 int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream);
@@ -922,8 +904,22 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format);
 int snd_pcm_format_linear(snd_pcm_format_t format);
 int snd_pcm_format_little_endian(snd_pcm_format_t format);
 int snd_pcm_format_big_endian(snd_pcm_format_t format);
+/**
+ * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
+ * @format: the format to check
+ *
+ * Returns 1 if the given PCM format is CPU-endian, 0 if
+ * opposite, or a negative error code if endian not specified.
+ */
+/* int snd_pcm_format_cpu_endian(snd_pcm_format_t format); */
+#ifdef SNDRV_LITTLE_ENDIAN
+#define snd_pcm_format_cpu_endian      snd_pcm_format_little_endian
+#else
+#define snd_pcm_format_cpu_endian      snd_pcm_format_big_endian
+#endif
 int snd_pcm_format_width(snd_pcm_format_t format);                     /* in bits */
 int snd_pcm_format_physical_width(snd_pcm_format_t format);            /* in bits */
+ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
index 4357cac075000d5a42e9f20ddb087a6d95c5d73b..8857e2bd31a5f690998a276dcee475fae78cdffa 100644 (file)
@@ -41,9 +41,7 @@ struct snd_midi_event_t {
 };
 
 int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev);
-int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize);
 void snd_midi_event_free(snd_midi_event_t *dev);
-void snd_midi_event_init(snd_midi_event_t *dev);
 void snd_midi_event_reset_encode(snd_midi_event_t *dev);
 void snd_midi_event_reset_decode(snd_midi_event_t *dev);
 void snd_midi_event_no_status(snd_midi_event_t *dev, int on);
index cf4e2388103f078aac5f7c95418253a04f6f13cf..1ad27e859af373136d6ae80a5b0f50d93242e25e 100644 (file)
@@ -79,6 +79,5 @@ struct _snd_virmidi_dev {
 #define SNDRV_VIRMIDI_SEQ_DISPATCH     2
 
 int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi);
-int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev);
 
 #endif /* __SOUND_SEQ_VIRMIDI */
index 57fde990606e9b3006789f0510a15c233aa46337..1898511a0f389d53a61023d68d7ad2c2f0b8df9c 100644 (file)
@@ -152,6 +152,4 @@ extern int snd_timer_pause(snd_timer_instance_t * timeri);
 
 extern void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left);
 
-extern unsigned int snd_timer_system_resolution(void);
-
 #endif /* __SOUND_TIMER_H */
index 98b4230778ed456fa34893ec3aed122db9b2e7d0..46acfa8c998843fff235a10586041d710a1ec01e 100644 (file)
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by configure.  */
-#define CONFIG_SND_VERSION "1.0.9rc2"
-#define CONFIG_SND_DATE "  (Thu Mar 24 10:33:39 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.9"
+#define CONFIG_SND_DATE " (Sun May 29 07:31:02 2005 UTC)"
index 40bf367ffdf19f32e6c4a14a05ea366c3a0213a6..d324801729ba713938481fd4f3a8199fdc2eb6e9 100644 (file)
@@ -490,6 +490,7 @@ asmlinkage void __init start_kernel(void)
        vfs_caches_init_early();
        mem_init();
        kmem_cache_init();
+       setup_per_cpu_pageset();
        numa_policy_init();
        if (late_time_init)
                late_time_init();
index f42a17f88699bb4c1a07b4f93961c92e3c5d75a5..a28d11e10877d07ebdd1ccde6006493122873b28 100644 (file)
@@ -194,6 +194,7 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
        mm->mmap = NULL;
        mm->mmap_cache = NULL;
        mm->free_area_cache = oldmm->mmap_base;
+       mm->cached_hole_size = ~0UL;
        mm->map_count = 0;
        set_mm_counter(mm, rss, 0);
        set_mm_counter(mm, anon_rss, 0);
@@ -249,8 +250,9 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
 
                /*
                 * Link in the new vma and copy the page table entries:
-                * link in first so that swapoff can see swap entries,
-                * and try_to_unmap_one's find_vma find the new vma.
+                * link in first so that swapoff can see swap entries.
+                * Note that, exceptionally, here the vma is inserted
+                * without holding mm->mmap_sem.
                 */
                spin_lock(&mm->page_table_lock);
                *pprev = tmp;
@@ -322,6 +324,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
        mm->ioctx_list = NULL;
        mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
        mm->free_area_cache = TASK_UNMAPPED_BASE;
+       mm->cached_hole_size = ~0UL;
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
index 5202e4c4a5b606e2408dafd1e48904548bc44e83..ac670098570579e980e6b7bba35a235f7be885a9 100644 (file)
@@ -6,6 +6,7 @@
  * This file contains driver APIs to the irq subsystem.
  */
 
+#include <linux/config.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/random.h>
@@ -255,6 +256,13 @@ void free_irq(unsigned int irq, void *dev_id)
 
                        /* Found it - now remove it from the list of entries */
                        *pp = action->next;
+
+                       /* Currently used only by UML, might disappear one day.*/
+#ifdef CONFIG_IRQ_RELEASE_METHOD
+                       if (desc->handler->release)
+                               desc->handler->release(irq, dev_id);
+#endif
+
                        if (!desc->action) {
                                desc->status |= IRQ_DISABLED;
                                if (desc->handler->shutdown)
index 83b3d376708c04f00fdf674622b1c1071045eada..a566745dde621a075e225c52a432316bec58afc0 100644 (file)
@@ -379,7 +379,7 @@ static void module_unload_init(struct module *mod)
        for (i = 0; i < NR_CPUS; i++)
                local_set(&mod->ref[i].count, 0);
        /* Hold reference count during initialization. */
-       local_set(&mod->ref[_smp_processor_id()].count, 1);
+       local_set(&mod->ref[raw_smp_processor_id()].count, 1);
        /* Backwards compatibility macros put refcount during init. */
        mod->waiter = current;
 }
index cba3584b80fefa88b3fdcb8d938800b08d44abeb..457c2302ed424bf05e516136d21c1884033ca1e9 100644 (file)
@@ -48,11 +48,11 @@ void disable_nonboot_cpus(void)
 {
        oldmask = current->cpus_allowed;
        set_cpus_allowed(current, cpumask_of_cpu(0));
-       printk("Freezing CPUs (at %d)", _smp_processor_id());
+       printk("Freezing CPUs (at %d)", raw_smp_processor_id());
        current->state = TASK_INTERRUPTIBLE;
        schedule_timeout(HZ);
        printk("...");
-       BUG_ON(_smp_processor_id() != 0);
+       BUG_ON(raw_smp_processor_id() != 0);
 
        /* FIXME: for this to work, all the CPUs must be running
         * "idle" thread (or we deadlock). Is that guaranteed? */
index f12a0c8a7d98d0cbda8507dd9fa8233acb51f087..deca041fc3645670055502888171811404d249f9 100644 (file)
@@ -3814,7 +3814,7 @@ EXPORT_SYMBOL(yield);
  */
 void __sched io_schedule(void)
 {
-       struct runqueue *rq = &per_cpu(runqueues, _smp_processor_id());
+       struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
 
        atomic_inc(&rq->nr_iowait);
        schedule();
@@ -3825,7 +3825,7 @@ EXPORT_SYMBOL(io_schedule);
 
 long __sched io_schedule_timeout(long timeout)
 {
-       struct runqueue *rq = &per_cpu(runqueues, _smp_processor_id());
+       struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
        long ret;
 
        atomic_inc(&rq->nr_iowait);
index 6116b25aa7cf32ad98761de21f3219b30cea31cc..84a9d18aa8da0ecb9309c6b58a2b8b694a1493e2 100644 (file)
@@ -100,7 +100,7 @@ static int stop_machine(void)
        stopmachine_state = STOPMACHINE_WAIT;
 
        for_each_online_cpu(i) {
-               if (i == _smp_processor_id())
+               if (i == raw_smp_processor_id())
                        continue;
                ret = kernel_thread(stopmachine, (void *)(long)i,CLONE_KERNEL);
                if (ret < 0)
@@ -182,7 +182,7 @@ struct task_struct *__stop_machine_run(int (*fn)(void *), void *data,
 
        /* If they don't care which CPU fn runs on, bind to any online one. */
        if (cpu == NR_CPUS)
-               cpu = _smp_processor_id();
+               cpu = raw_smp_processor_id();
 
        p = kthread_create(do_stop, &smdata, "kstopmachine");
        if (!IS_ERR(p)) {
index 0dda70ed1f983a7caaaf3434244f1ef1852918ae..6f15bea7d1a83dc363826c5bcdb2c0013feaebc0 100644 (file)
@@ -77,6 +77,7 @@ cond_syscall(sys_request_key);
 cond_syscall(sys_keyctl);
 cond_syscall(compat_sys_keyctl);
 cond_syscall(compat_sys_socketcall);
+cond_syscall(sys_set_zone_reclaim);
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read);
index eeb45225248fd7cfb6c347047e93f2fcb3be00fc..2d4d4e3bc4aa47680d0e5581e4cfc4c09397b75b 100644 (file)
@@ -39,6 +39,12 @@ config ZLIB_INFLATE
 config ZLIB_DEFLATE
        tristate
 
+#
+# Generic allocator support is selected if needed
+#
+config GENERIC_ALLOCATOR
+       boolean
+
 #
 # reed solomon support is select'ed if needed
 #
index 9eccea9429a74774ca7c3c0d5a7efc122f2149ff..dcb4231916e2ecb353c80cb1dc51ff5ca75b2b26 100644 (file)
@@ -20,6 +20,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
   lib-y += dec_and_lock.o
@@ -29,6 +30,7 @@ obj-$(CONFIG_CRC_CCITT)       += crc-ccitt.o
 obj-$(CONFIG_CRC32)    += crc32.o
 obj-$(CONFIG_LIBCRC32C)        += libcrc32c.o
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
+obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
diff --git a/lib/genalloc.c b/lib/genalloc.c
new file mode 100644 (file)
index 0000000..d6d30d2
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Basic general purpose allocator for managing special purpose memory
+ * not managed by the regular kmalloc/kfree interface.
+ * Uses for this includes on-device special memory, uncached memory
+ * etc.
+ *
+ * This code is based on the buddy allocator found in the sym53c8xx_2
+ * driver Copyright (C) 1999-2001  Gerard Roudier <groudier@free.fr>,
+ * and adapted for general purpose use.
+ *
+ * Copyright 2005 (C) Jes Sorensen <jes@trained-monkey.org>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+
+#include <asm/page.h>
+
+
+struct gen_pool *gen_pool_create(int nr_chunks, int max_chunk_shift,
+                                unsigned long (*fp)(struct gen_pool *),
+                                unsigned long data)
+{
+       struct gen_pool *poolp;
+       unsigned long tmp;
+       int i;
+
+       /*
+        * This is really an arbitrary limit, +10 is enough for
+        * IA64_GRANULE_SHIFT, aka 16MB. If anyone needs a large limit
+        * this can be increased without problems.
+        */
+       if ((max_chunk_shift > (PAGE_SHIFT + 10)) ||
+           ((max_chunk_shift < ALLOC_MIN_SHIFT) && max_chunk_shift))
+               return NULL;
+
+       if (!max_chunk_shift)
+               max_chunk_shift = PAGE_SHIFT;
+
+       poolp = kmalloc(sizeof(struct gen_pool), GFP_KERNEL);
+       if (!poolp)
+               return NULL;
+       memset(poolp, 0, sizeof(struct gen_pool));
+       poolp->h = kmalloc(sizeof(struct gen_pool_link) *
+                          (max_chunk_shift - ALLOC_MIN_SHIFT + 1),
+                          GFP_KERNEL);
+       if (!poolp->h) {
+               printk(KERN_WARNING "gen_pool_alloc() failed to allocate\n");
+               kfree(poolp);
+               return NULL;
+       }
+       memset(poolp->h, 0, sizeof(struct gen_pool_link) *
+              (max_chunk_shift - ALLOC_MIN_SHIFT + 1));
+
+       spin_lock_init(&poolp->lock);
+       poolp->get_new_chunk = fp;
+       poolp->max_chunk_shift = max_chunk_shift;
+       poolp->private = data;
+
+       for (i = 0; i < nr_chunks; i++) {
+               tmp = poolp->get_new_chunk(poolp);
+               printk(KERN_INFO "allocated %lx\n", tmp);
+               if (!tmp)
+                       break;
+               gen_pool_free(poolp, tmp, (1 << poolp->max_chunk_shift));
+       }
+
+       return poolp;
+}
+EXPORT_SYMBOL(gen_pool_create);
+
+
+/*
+ *  Simple power of two buddy-like generic allocator.
+ *  Provides naturally aligned memory chunks.
+ */
+unsigned long gen_pool_alloc(struct gen_pool *poolp, int size)
+{
+       int j, i, s, max_chunk_size;
+       unsigned long a, flags;
+       struct gen_pool_link *h = poolp->h;
+
+       max_chunk_size = 1 << poolp->max_chunk_shift;
+
+       if (size > max_chunk_size)
+               return 0;
+
+       i = 0;
+
+       size = max(size, 1 << ALLOC_MIN_SHIFT);
+       s = roundup_pow_of_two(size);
+
+       j = i;
+
+       spin_lock_irqsave(&poolp->lock, flags);
+       while (!h[j].next) {
+               if (s == max_chunk_size) {
+                       struct gen_pool_link *ptr;
+                       spin_unlock_irqrestore(&poolp->lock, flags);
+                       ptr = (struct gen_pool_link *)poolp->get_new_chunk(poolp);
+                       spin_lock_irqsave(&poolp->lock, flags);
+                       h[j].next = ptr;
+                       if (h[j].next)
+                               h[j].next->next = NULL;
+                       break;
+               }
+               j++;
+               s <<= 1;
+       }
+       a = (unsigned long) h[j].next;
+       if (a) {
+               h[j].next = h[j].next->next;
+               /*
+                * This should be split into a seperate function doing
+                * the chunk split in order to support custom
+                * handling memory not physically accessible by host
+                */
+               while (j > i) {
+                       j -= 1;
+                       s >>= 1;
+                       h[j].next = (struct gen_pool_link *) (a + s);
+                       h[j].next->next = NULL;
+               }
+       }
+       spin_unlock_irqrestore(&poolp->lock, flags);
+       return a;
+}
+EXPORT_SYMBOL(gen_pool_alloc);
+
+
+/*
+ *  Counter-part of the generic allocator.
+ */
+void gen_pool_free(struct gen_pool *poolp, unsigned long ptr, int size)
+{
+       struct gen_pool_link *q;
+       struct gen_pool_link *h = poolp->h;
+       unsigned long a, b, flags;
+       int i, s, max_chunk_size;
+
+       max_chunk_size = 1 << poolp->max_chunk_shift;
+
+       if (size > max_chunk_size)
+               return;
+
+       i = 0;
+
+       size = max(size, 1 << ALLOC_MIN_SHIFT);
+       s = roundup_pow_of_two(size);
+
+       a = ptr;
+
+       spin_lock_irqsave(&poolp->lock, flags);
+       while (1) {
+               if (s == max_chunk_size) {
+                       ((struct gen_pool_link *)a)->next = h[i].next;
+                       h[i].next = (struct gen_pool_link *)a;
+                       break;
+               }
+               b = a ^ s;
+               q = &h[i];
+
+               while (q->next && q->next != (struct gen_pool_link *)b)
+                       q = q->next;
+
+               if (!q->next) {
+                       ((struct gen_pool_link *)a)->next = h[i].next;
+                       h[i].next = (struct gen_pool_link *)a;
+                       break;
+               }
+               q->next = q->next->next;
+               a = a & b;
+               s <<= 1;
+               i++;
+       }
+       spin_unlock_irqrestore(&poolp->lock, flags);
+}
+EXPORT_SYMBOL(gen_pool_free);
index 81fc430602ee8f4c2b4e336a606813ad54b0e5b2..c5be889de449555dc31b5c5d50a061f34187fdb6 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -175,7 +175,7 @@ build_up:
         * Add a new layer to the top of the tree if the requested
         * id is larger than the currently allocated space.
         */
-       while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
+       while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
                layers++;
                if (!p->count)
                        continue;
index 99b0ae3d51dded390d221525b2cd2389d845ca8c..bd2bc5d887b815e261ff82c4167e410966b659d3 100644 (file)
@@ -9,61 +9,6 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 
-#if defined(CONFIG_PREEMPT) && defined(__smp_processor_id) && \
-               defined(CONFIG_DEBUG_PREEMPT)
-
-/*
- * Debugging check.
- */
-unsigned int smp_processor_id(void)
-{
-       unsigned long preempt_count = preempt_count();
-       int this_cpu = __smp_processor_id();
-       cpumask_t this_mask;
-
-       if (likely(preempt_count))
-               goto out;
-
-       if (irqs_disabled())
-               goto out;
-
-       /*
-        * Kernel threads bound to a single CPU can safely use
-        * smp_processor_id():
-        */
-       this_mask = cpumask_of_cpu(this_cpu);
-
-       if (cpus_equal(current->cpus_allowed, this_mask))
-               goto out;
-
-       /*
-        * It is valid to assume CPU-locality during early bootup:
-        */
-       if (system_state != SYSTEM_RUNNING)
-               goto out;
-
-       /*
-        * Avoid recursion:
-        */
-       preempt_disable();
-
-       if (!printk_ratelimit())
-               goto out_enable;
-
-       printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
-       print_symbol("caller is %s\n", (long)__builtin_return_address(0));
-       dump_stack();
-
-out_enable:
-       preempt_enable_no_resched();
-out:
-       return this_cpu;
-}
-
-EXPORT_SYMBOL(smp_processor_id);
-
-#endif /* PREEMPT && __smp_processor_id && DEBUG_PREEMPT */
-
 #ifdef CONFIG_PREEMPT_BKL
 /*
  * The 'big kernel semaphore'
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
new file mode 100644 (file)
index 0000000..42c08ef
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * lib/smp_processor_id.c
+ *
+ * DEBUG_PREEMPT variant of smp_processor_id().
+ */
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+unsigned int debug_smp_processor_id(void)
+{
+       unsigned long preempt_count = preempt_count();
+       int this_cpu = raw_smp_processor_id();
+       cpumask_t this_mask;
+
+       if (likely(preempt_count))
+               goto out;
+
+       if (irqs_disabled())
+               goto out;
+
+       /*
+        * Kernel threads bound to a single CPU can safely use
+        * smp_processor_id():
+        */
+       this_mask = cpumask_of_cpu(this_cpu);
+
+       if (cpus_equal(current->cpus_allowed, this_mask))
+               goto out;
+
+       /*
+        * It is valid to assume CPU-locality during early bootup:
+        */
+       if (system_state != SYSTEM_RUNNING)
+               goto out;
+
+       /*
+        * Avoid recursion:
+        */
+       preempt_disable();
+
+       if (!printk_ratelimit())
+               goto out_enable;
+
+       printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
+       print_symbol("caller is %s\n", (long)__builtin_return_address(0));
+       dump_stack();
+
+out_enable:
+       preempt_enable_no_resched();
+out:
+       return this_cpu;
+}
+
+EXPORT_SYMBOL(debug_smp_processor_id);
+
index 4eb5ae3fbe10d3f34aca918c3325c62f76bdd8ee..fbd1111ea1194fc106042d57d2115a743dce7ced 100644 (file)
@@ -7,10 +7,14 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/hugetlb.h>
 #include <linux/sysctl.h>
 #include <linux/highmem.h>
 #include <linux/nodemask.h>
+#include <linux/pagemap.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <linux/hugetlb.h>
 
 const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL;
 static unsigned long nr_huge_pages, free_huge_pages;
@@ -249,6 +253,72 @@ struct vm_operations_struct hugetlb_vm_ops = {
        .nopage = hugetlb_nopage,
 };
 
+static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page)
+{
+       pte_t entry;
+
+       if (vma->vm_flags & VM_WRITE) {
+               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);
+
+       return entry;
+}
+
+int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
+                           struct vm_area_struct *vma)
+{
+       pte_t *src_pte, *dst_pte, entry;
+       struct page *ptepage;
+       unsigned long addr = vma->vm_start;
+       unsigned long end = vma->vm_end;
+
+       while (addr < end) {
+               dst_pte = huge_pte_alloc(dst, addr);
+               if (!dst_pte)
+                       goto nomem;
+               src_pte = huge_pte_offset(src, addr);
+               BUG_ON(!src_pte || pte_none(*src_pte)); /* prefaulted */
+               entry = *src_pte;
+               ptepage = pte_page(entry);
+               get_page(ptepage);
+               add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
+               set_huge_pte_at(dst, addr, dst_pte, entry);
+               addr += HPAGE_SIZE;
+       }
+       return 0;
+
+nomem:
+       return -ENOMEM;
+}
+
+void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
+                         unsigned long end)
+{
+       struct mm_struct *mm = vma->vm_mm;
+       unsigned long address;
+       pte_t pte;
+       struct page *page;
+
+       WARN_ON(!is_vm_hugetlb_page(vma));
+       BUG_ON(start & ~HPAGE_MASK);
+       BUG_ON(end & ~HPAGE_MASK);
+
+       for (address = start; address < end; address += HPAGE_SIZE) {
+               pte = huge_ptep_get_and_clear(mm, address, huge_pte_offset(mm, address));
+               if (pte_none(pte))
+                       continue;
+               page = pte_page(pte);
+               put_page(page);
+       }
+       add_mm_counter(mm, rss,  -((end - start) >> PAGE_SHIFT));
+       flush_tlb_range(vma, start, end);
+}
+
 void zap_hugepage_range(struct vm_area_struct *vma,
                        unsigned long start, unsigned long length)
 {
@@ -258,3 +328,108 @@ void zap_hugepage_range(struct vm_area_struct *vma,
        unmap_hugepage_range(vma, start, start + length);
        spin_unlock(&mm->page_table_lock);
 }
+
+int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long addr;
+       int ret = 0;
+
+       WARN_ON(!is_vm_hugetlb_page(vma));
+       BUG_ON(vma->vm_start & ~HPAGE_MASK);
+       BUG_ON(vma->vm_end & ~HPAGE_MASK);
+
+       hugetlb_prefault_arch_hook(mm);
+
+       spin_lock(&mm->page_table_lock);
+       for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
+               unsigned long idx;
+               pte_t *pte = huge_pte_alloc(mm, addr);
+               struct page *page;
+
+               if (!pte) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               if (! pte_none(*pte))
+                       hugetlb_clean_stale_pgtable(pte);
+
+               idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
+                       + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
+               page = find_get_page(mapping, idx);
+               if (!page) {
+                       /* charge the fs quota first */
+                       if (hugetlb_get_quota(mapping)) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       page = alloc_huge_page();
+                       if (!page) {
+                               hugetlb_put_quota(mapping);
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
+                       if (! ret) {
+                               unlock_page(page);
+                       } else {
+                               hugetlb_put_quota(mapping);
+                               free_huge_page(page);
+                               goto out;
+                       }
+               }
+               add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
+               set_huge_pte_at(mm, addr, pte, make_huge_pte(vma, page));
+       }
+out:
+       spin_unlock(&mm->page_table_lock);
+       return ret;
+}
+
+int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
+                       struct page **pages, struct vm_area_struct **vmas,
+                       unsigned long *position, int *length, int i)
+{
+       unsigned long vpfn, vaddr = *position;
+       int remainder = *length;
+
+       BUG_ON(!is_vm_hugetlb_page(vma));
+
+       vpfn = vaddr/PAGE_SIZE;
+       while (vaddr < vma->vm_end && remainder) {
+
+               if (pages) {
+                       pte_t *pte;
+                       struct page *page;
+
+                       /* Some archs (sparc64, sh*) have multiple
+                        * pte_ts to each hugepage.  We have to make
+                        * sure we get the first, for the page
+                        * indexing below to work. */
+                       pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
+
+                       /* hugetlb should be locked, and hence, prefaulted */
+                       WARN_ON(!pte || pte_none(*pte));
+
+                       page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
+
+                       WARN_ON(!PageCompound(page));
+
+                       get_page(page);
+                       pages[i] = page;
+               }
+
+               if (vmas)
+                       vmas[i] = vma;
+
+               vaddr += PAGE_SIZE;
+               ++vpfn;
+               --remainder;
+               ++i;
+       }
+
+       *length = remainder;
+       *position = vaddr;
+
+       return i;
+}
index 944b5e52d812f051fb2bffaed33a4288ba4c920e..e3108054733c2530fd28114b4814e27eda106ac0 100644 (file)
@@ -8,17 +8,47 @@
 #include <linux/mman.h>
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
+#include <linux/mempolicy.h>
 #include <linux/hugetlb.h>
 
 /*
  * We can potentially split a vm area into separate
  * areas, each area with its own behavior.
  */
-static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
-                            unsigned long end, int behavior)
+static long madvise_behavior(struct vm_area_struct * vma,
+                    struct vm_area_struct **prev,
+                    unsigned long start, unsigned long end, int behavior)
 {
        struct mm_struct * mm = vma->vm_mm;
        int error = 0;
+       pgoff_t pgoff;
+       int new_flags = vma->vm_flags & ~VM_READHINTMASK;
+
+       switch (behavior) {
+       case MADV_SEQUENTIAL:
+               new_flags |= VM_SEQ_READ;
+               break;
+       case MADV_RANDOM:
+               new_flags |= VM_RAND_READ;
+               break;
+       default:
+               break;
+       }
+
+       if (new_flags == vma->vm_flags) {
+               *prev = vma;
+               goto success;
+       }
+
+       pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+       *prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma,
+                               vma->vm_file, pgoff, vma_policy(vma));
+       if (*prev) {
+               vma = *prev;
+               goto success;
+       }
+
+       *prev = vma;
 
        if (start != vma->vm_start) {
                error = split_vma(mm, vma, start, 1);
@@ -36,21 +66,12 @@ static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
         * vm_flags is protected by the mmap_sem held in write mode.
         */
        VM_ClearReadHint(vma);
-
-       switch (behavior) {
-       case MADV_SEQUENTIAL:
-               vma->vm_flags |= VM_SEQ_READ;
-               break;
-       case MADV_RANDOM:
-               vma->vm_flags |= VM_RAND_READ;
-               break;
-       default:
-               break;
-       }
+       vma->vm_flags = new_flags;
 
 out:
        if (error == -ENOMEM)
                error = -EAGAIN;
+success:
        return error;
 }
 
@@ -58,6 +79,7 @@ out:
  * Schedule all required I/O operations.  Do not wait for completion.
  */
 static long madvise_willneed(struct vm_area_struct * vma,
+                            struct vm_area_struct ** prev,
                             unsigned long start, unsigned long end)
 {
        struct file *file = vma->vm_file;
@@ -65,6 +87,7 @@ static long madvise_willneed(struct vm_area_struct * vma,
        if (!file)
                return -EBADF;
 
+       *prev = vma;
        start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
        if (end > vma->vm_end)
                end = vma->vm_end;
@@ -95,8 +118,10 @@ static long madvise_willneed(struct vm_area_struct * vma,
  * dirty pages is already available as msync(MS_INVALIDATE).
  */
 static long madvise_dontneed(struct vm_area_struct * vma,
+                            struct vm_area_struct ** prev,
                             unsigned long start, unsigned long end)
 {
+       *prev = vma;
        if ((vma->vm_flags & VM_LOCKED) || is_vm_hugetlb_page(vma))
                return -EINVAL;
 
@@ -111,8 +136,8 @@ static long madvise_dontneed(struct vm_area_struct * vma,
        return 0;
 }
 
-static long madvise_vma(struct vm_area_struct * vma, unsigned long start,
-                       unsigned long end, int behavior)
+static long madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
+                       unsigned long start, unsigned long end, int behavior)
 {
        long error = -EBADF;
 
@@ -120,15 +145,15 @@ static long madvise_vma(struct vm_area_struct * vma, unsigned long start,
        case MADV_NORMAL:
        case MADV_SEQUENTIAL:
        case MADV_RANDOM:
-               error = madvise_behavior(vma, start, end, behavior);
+               error = madvise_behavior(vma, prev, start, end, behavior);
                break;
 
        case MADV_WILLNEED:
-               error = madvise_willneed(vma, start, end);
+               error = madvise_willneed(vma, prev, start, end);
                break;
 
        case MADV_DONTNEED:
-               error = madvise_dontneed(vma, start, end);
+               error = madvise_dontneed(vma, prev, start, end);
                break;
 
        default:
@@ -175,8 +200,8 @@ static long madvise_vma(struct vm_area_struct * vma, unsigned long start,
  */
 asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
 {
-       unsigned long end;
-       struct vm_area_struct * vma;
+       unsigned long end, tmp;
+       struct vm_area_struct * vma, *prev;
        int unmapped_error = 0;
        int error = -EINVAL;
        size_t len;
@@ -202,40 +227,42 @@ asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
        /*
         * If the interval [start,end) covers some unmapped address
         * ranges, just ignore them, but return -ENOMEM at the end.
+        * - different from the way of handling in mlock etc.
         */
-       vma = find_vma(current->mm, start);
+       vma = find_vma_prev(current->mm, start, &prev);
+       if (!vma && prev)
+               vma = prev->vm_next;
        for (;;) {
                /* Still start < end. */
                error = -ENOMEM;
                if (!vma)
                        goto out;
 
-               /* Here start < vma->vm_end. */
+               /* Here start < (end|vma->vm_end). */
                if (start < vma->vm_start) {
                        unmapped_error = -ENOMEM;
                        start = vma->vm_start;
+                       if (start >= end)
+                               goto out;
                }
 
-               /* Here vma->vm_start <= start < vma->vm_end. */
-               if (end <= vma->vm_end) {
-                       if (start < end) {
-                               error = madvise_vma(vma, start, end,
-                                                       behavior);
-                               if (error)
-                                       goto out;
-                       }
-                       error = unmapped_error;
-                       goto out;
-               }
+               /* Here vma->vm_start <= start < (end|vma->vm_end) */
+               tmp = vma->vm_end;
+               if (end < tmp)
+                       tmp = end;
 
-               /* Here vma->vm_start <= start < vma->vm_end < end. */
-               error = madvise_vma(vma, start, vma->vm_end, behavior);
+               /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */
+               error = madvise_vma(vma, &prev, start, tmp, behavior);
                if (error)
                        goto out;
-               start = vma->vm_end;
-               vma = vma->vm_next;
+               start = tmp;
+               if (start < prev->vm_end)
+                       start = prev->vm_end;
+               error = unmapped_error;
+               if (start >= end)
+                       goto out;
+               vma = prev->vm_next;
        }
-
 out:
        up_write(&current->mm->mmap_sem);
        return error;
index d209f745db7fbc3154e83cf04666770068986724..da91b7bf998605677a87d4d0500dde2acf11aa28 100644 (file)
@@ -840,23 +840,8 @@ check_user_page_readable(struct mm_struct *mm, unsigned long address)
 {
        return __follow_page(mm, address, /*read*/1, /*write*/0) != NULL;
 }
-
 EXPORT_SYMBOL(check_user_page_readable);
 
-/* 
- * Given a physical address, is there a useful struct page pointing to
- * it?  This may become more complex in the future if we start dealing
- * with IO-aperture pages for direct-IO.
- */
-
-static inline struct page *get_page_map(struct page *page)
-{
-       if (!pfn_valid(page_to_pfn(page)))
-               return NULL;
-       return page;
-}
-
-
 static inline int
 untouched_anonymous_page(struct mm_struct* mm, struct vm_area_struct *vma,
                         unsigned long address)
@@ -887,7 +872,6 @@ untouched_anonymous_page(struct mm_struct* mm, struct vm_area_struct *vma,
        return 0;
 }
 
-
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                unsigned long start, int len, int write, int force,
                struct page **pages, struct vm_area_struct **vmas)
@@ -951,21 +935,21 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                }
                spin_lock(&mm->page_table_lock);
                do {
-                       struct page *map;
+                       struct page *page;
                        int lookup_write = write;
 
                        cond_resched_lock(&mm->page_table_lock);
-                       while (!(map = follow_page(mm, start, lookup_write))) {
+                       while (!(page = follow_page(mm, start, lookup_write))) {
                                /*
                                 * Shortcut for anonymous pages. We don't want
                                 * to force the creation of pages tables for
-                                * insanly big anonymously mapped areas that
+                                * insanely big anonymously mapped areas that
                                 * nobody touched so far. This is important
                                 * for doing a core dump for these mappings.
                                 */
                                if (!lookup_write &&
                                    untouched_anonymous_page(mm,vma,start)) {
-                                       map = ZERO_PAGE(start);
+                                       page = ZERO_PAGE(start);
                                        break;
                                }
                                spin_unlock(&mm->page_table_lock);
@@ -994,30 +978,21 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                spin_lock(&mm->page_table_lock);
                        }
                        if (pages) {
-                               pages[i] = get_page_map(map);
-                               if (!pages[i]) {
-                                       spin_unlock(&mm->page_table_lock);
-                                       while (i--)
-                                               page_cache_release(pages[i]);
-                                       i = -EFAULT;
-                                       goto out;
-                               }
-                               flush_dcache_page(pages[i]);
-                               if (!PageReserved(pages[i]))
-                                       page_cache_get(pages[i]);
+                               pages[i] = page;
+                               flush_dcache_page(page);
+                               if (!PageReserved(page))
+                                       page_cache_get(page);
                        }
                        if (vmas)
                                vmas[i] = vma;
                        i++;
                        start += PAGE_SIZE;
                        len--;
-               } while(len && start < vma->vm_end);
+               } while (len && start < vma->vm_end);
                spin_unlock(&mm->page_table_lock);
-       } while(len);
-out:
+       } while (len);
        return i;
 }
-
 EXPORT_SYMBOL(get_user_pages);
 
 static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
@@ -1264,7 +1239,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
        }
        old_page = pfn_to_page(pfn);
 
-       if (!TestSetPageLocked(old_page)) {
+       if (PageAnon(old_page) && !TestSetPageLocked(old_page)) {
                int reuse = can_share_swap_page(old_page);
                unlock_page(old_page);
                if (reuse) {
@@ -1711,10 +1686,6 @@ static int do_swap_page(struct mm_struct * mm,
        }
 
        /* The page isn't present yet, go ahead with the fault. */
-               
-       swap_free(entry);
-       if (vm_swap_full())
-               remove_exclusive_swap_page(page);
 
        inc_mm_counter(mm, rss);
        pte = mk_pte(page, vma->vm_page_prot);
@@ -1722,12 +1693,16 @@ static int do_swap_page(struct mm_struct * mm,
                pte = maybe_mkwrite(pte_mkdirty(pte), vma);
                write_access = 0;
        }
-       unlock_page(page);
 
        flush_icache_page(vma, page);
        set_pte_at(mm, address, page_table, pte);
        page_add_anon_rmap(page, vma, address);
 
+       swap_free(entry);
+       if (vm_swap_full())
+               remove_exclusive_swap_page(page);
+       unlock_page(page);
+
        if (write_access) {
                if (do_wp_page(mm, vma, address,
                                page_table, pmd, pte) == VM_FAULT_OOM)
index 08c41da429cf015e9c22443ae5d811d4f5fa3569..cb41c31e7c875873f96a5c6d24ab91ab17d3311c 100644 (file)
@@ -238,46 +238,80 @@ static struct mempolicy *mpol_new(int mode, unsigned long *nodes)
 }
 
 /* Ensure all existing pages follow the policy. */
-static int
-verify_pages(struct mm_struct *mm,
-            unsigned long addr, unsigned long end, unsigned long *nodes)
+static int check_pte_range(struct mm_struct *mm, pmd_t *pmd,
+               unsigned long addr, unsigned long end, unsigned long *nodes)
 {
-       while (addr < end) {
-               struct page *p;
-               pte_t *pte;
-               pmd_t *pmd;
-               pud_t *pud;
-               pgd_t *pgd;
-               pgd = pgd_offset(mm, addr);
-               if (pgd_none(*pgd)) {
-                       unsigned long next = (addr + PGDIR_SIZE) & PGDIR_MASK;
-                       if (next > addr)
-                               break;
-                       addr = next;
+       pte_t *orig_pte;
+       pte_t *pte;
+
+       spin_lock(&mm->page_table_lock);
+       orig_pte = pte = pte_offset_map(pmd, addr);
+       do {
+               unsigned long pfn;
+               unsigned int nid;
+
+               if (!pte_present(*pte))
                        continue;
-               }
-               pud = pud_offset(pgd, addr);
-               if (pud_none(*pud)) {
-                       addr = (addr + PUD_SIZE) & PUD_MASK;
+               pfn = pte_pfn(*pte);
+               if (!pfn_valid(pfn))
                        continue;
-               }
-               pmd = pmd_offset(pud, addr);
-               if (pmd_none(*pmd)) {
-                       addr = (addr + PMD_SIZE) & PMD_MASK;
+               nid = pfn_to_nid(pfn);
+               if (!test_bit(nid, nodes))
+                       break;
+       } while (pte++, addr += PAGE_SIZE, addr != end);
+       pte_unmap(orig_pte);
+       spin_unlock(&mm->page_table_lock);
+       return addr != end;
+}
+
+static inline int check_pmd_range(struct mm_struct *mm, pud_t *pud,
+               unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+       pmd_t *pmd;
+       unsigned long next;
+
+       pmd = pmd_offset(pud, addr);
+       do {
+               next = pmd_addr_end(addr, end);
+               if (pmd_none_or_clear_bad(pmd))
                        continue;
-               }
-               p = NULL;
-               pte = pte_offset_map(pmd, addr);
-               if (pte_present(*pte))
-                       p = pte_page(*pte);
-               pte_unmap(pte);
-               if (p) {
-                       unsigned nid = page_to_nid(p);
-                       if (!test_bit(nid, nodes))
-                               return -EIO;
-               }
-               addr += PAGE_SIZE;
-       }
+               if (check_pte_range(mm, pmd, addr, next, nodes))
+                       return -EIO;
+       } while (pmd++, addr = next, addr != end);
+       return 0;
+}
+
+static inline int check_pud_range(struct mm_struct *mm, pgd_t *pgd,
+               unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+       pud_t *pud;
+       unsigned long next;
+
+       pud = pud_offset(pgd, addr);
+       do {
+               next = pud_addr_end(addr, end);
+               if (pud_none_or_clear_bad(pud))
+                       continue;
+               if (check_pmd_range(mm, pud, addr, next, nodes))
+                       return -EIO;
+       } while (pud++, addr = next, addr != end);
+       return 0;
+}
+
+static inline int check_pgd_range(struct mm_struct *mm,
+               unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+       pgd_t *pgd;
+       unsigned long next;
+
+       pgd = pgd_offset(mm, addr);
+       do {
+               next = pgd_addr_end(addr, end);
+               if (pgd_none_or_clear_bad(pgd))
+                       continue;
+               if (check_pud_range(mm, pgd, addr, next, nodes))
+                       return -EIO;
+       } while (pgd++, addr = next, addr != end);
        return 0;
 }
 
@@ -299,7 +333,7 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
                if (prev && prev->vm_end < vma->vm_start)
                        return ERR_PTR(-EFAULT);
                if ((flags & MPOL_MF_STRICT) && !is_vm_hugetlb_page(vma)) {
-                       err = verify_pages(vma->vm_mm,
+                       err = check_pgd_range(vma->vm_mm,
                                           vma->vm_start, vma->vm_end, nodes);
                        if (err) {
                                first = ERR_PTR(err);
@@ -721,7 +755,7 @@ static struct page *alloc_page_interleave(unsigned int __nocast gfp, unsigned or
        zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK);
        page = __alloc_pages(gfp, order, zl);
        if (page && page_zone(page) == zl->zones[0]) {
-               zl->zones[0]->pageset[get_cpu()].interleave_hit++;
+               zone_pcp(zl->zones[0],get_cpu())->interleave_hit++;
                put_cpu();
        }
        return page;
index de54acd9942f9929004921042721df5cdfe2b6c7..da3fa90a0aae2b9af04ec553209deb6a51b80b48 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1175,7 +1175,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
-       start_addr = addr = mm->free_area_cache;
+       if (len > mm->cached_hole_size) {
+               start_addr = addr = mm->free_area_cache;
+       } else {
+               start_addr = addr = TASK_UNMAPPED_BASE;
+               mm->cached_hole_size = 0;
+       }
 
 full_search:
        for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
@@ -1186,7 +1191,9 @@ full_search:
                         * some holes.
                         */
                        if (start_addr != TASK_UNMAPPED_BASE) {
-                               start_addr = addr = TASK_UNMAPPED_BASE;
+                               addr = TASK_UNMAPPED_BASE;
+                               start_addr = addr;
+                               mm->cached_hole_size = 0;
                                goto full_search;
                        }
                        return -ENOMEM;
@@ -1198,19 +1205,22 @@ full_search:
                        mm->free_area_cache = addr + len;
                        return addr;
                }
+               if (addr + mm->cached_hole_size < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
                addr = vma->vm_end;
        }
 }
 #endif 
 
-void arch_unmap_area(struct vm_area_struct *area)
+void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
 {
        /*
         * Is this a new hole at the lowest possible address?
         */
-       if (area->vm_start >= TASK_UNMAPPED_BASE &&
-                       area->vm_start < area->vm_mm->free_area_cache)
-               area->vm_mm->free_area_cache = area->vm_start;
+       if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) {
+               mm->free_area_cache = addr;
+               mm->cached_hole_size = ~0UL;
+       }
 }
 
 /*
@@ -1240,6 +1250,12 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                        return addr;
        }
 
+       /* check if free_area_cache is useful for us */
+       if (len <= mm->cached_hole_size) {
+               mm->cached_hole_size = 0;
+               mm->free_area_cache = mm->mmap_base;
+       }
+
        /* either no address requested or can't fit in requested address hole */
        addr = mm->free_area_cache;
 
@@ -1251,6 +1267,9 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                        return (mm->free_area_cache = addr-len);
        }
 
+       if (mm->mmap_base < len)
+               goto bottomup;
+
        addr = mm->mmap_base-len;
 
        do {
@@ -1264,38 +1283,45 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                        /* remember the address as a hint for next time */
                        return (mm->free_area_cache = addr);
 
+               /* remember the largest hole we saw so far */
+               if (addr + mm->cached_hole_size < vma->vm_start)
+                       mm->cached_hole_size = vma->vm_start - addr;
+
                /* try just below the current vma->vm_start */
                addr = vma->vm_start-len;
        } while (len < vma->vm_start);
 
+bottomup:
        /*
         * 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;
+       mm->cached_hole_size = ~0UL;
+       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 = mm->mmap_base;
+       mm->cached_hole_size = ~0UL;
 
        return addr;
 }
 #endif
 
-void arch_unmap_area_topdown(struct vm_area_struct *area)
+void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr)
 {
        /*
         * Is this a new hole at the highest possible address?
         */
-       if (area->vm_end > area->vm_mm->free_area_cache)
-               area->vm_mm->free_area_cache = area->vm_end;
+       if (addr > mm->free_area_cache)
+               mm->free_area_cache = addr;
 
        /* dont allow allocations above current base */
-       if (area->vm_mm->free_area_cache > area->vm_mm->mmap_base)
-               area->vm_mm->free_area_cache = area->vm_mm->mmap_base;
+       if (mm->free_area_cache > mm->mmap_base)
+               mm->free_area_cache = mm->mmap_base;
 }
 
 unsigned long
@@ -1595,7 +1621,6 @@ static void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area)
        if (area->vm_flags & VM_LOCKED)
                area->vm_mm->locked_vm -= len >> PAGE_SHIFT;
        vm_stat_unaccount(area);
-       area->vm_mm->unmap_area(area);
        remove_vm_struct(area);
 }
 
@@ -1649,6 +1674,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
 {
        struct vm_area_struct **insertion_point;
        struct vm_area_struct *tail_vma = NULL;
+       unsigned long addr;
 
        insertion_point = (prev ? &prev->vm_next : &mm->mmap);
        do {
@@ -1659,6 +1685,11 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
        } while (vma && vma->vm_start < end);
        *insertion_point = vma;
        tail_vma->vm_next = NULL;
+       if (mm->unmap_area == arch_unmap_area)
+               addr = prev ? prev->vm_end : mm->mmap_base;
+       else
+               addr = vma ?  vma->vm_start : mm->mmap_base;
+       mm->unmap_area(mm, addr);
        mm->mmap_cache = NULL;          /* Kill the cache. */
 }
 
index 090f426bca7d538d5f84c9a8c53a677f50a31434..d0f5a1bce7cb14ecd7b74b960e87c8b079024020 100644 (file)
@@ -34,6 +34,8 @@ static void sync_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 
                if (!pte_present(*pte))
                        continue;
+               if (!pte_maybe_dirty(*pte))
+                       continue;
                pfn = pte_pfn(*pte);
                if (!pfn_valid(pfn))
                        continue;
index c53e9c8f6b4adc98ac9fe69b1bc3526bba1baaa5..ce74452c02d945e40e6cdb503499609f24e1cd64 100644 (file)
@@ -1067,7 +1067,7 @@ unsigned long arch_get_unmapped_area(struct file *file, unsigned long addr,
        return -ENOMEM;
 }
 
-void arch_unmap_area(struct vm_area_struct *area)
+void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
 {
 }
 
index 4bbb1cb10495ea486db83868055762888835c8b3..59666d905f1997521c89f4a7b1a492df4414be0e 100644 (file)
@@ -258,6 +258,10 @@ void out_of_memory(unsigned int __nocast gfp_mask)
        struct mm_struct *mm = NULL;
        task_t * p;
 
+       printk("oom-killer: gfp_mask=0x%x\n", gfp_mask);
+       /* print memory stats */
+       show_mem();
+
        read_lock(&tasklist_lock);
 retry:
        p = select_bad_process();
@@ -268,12 +272,9 @@ retry:
        /* Found nothing?!?! Either we hang forever, or we panic. */
        if (!p) {
                read_unlock(&tasklist_lock);
-               show_free_areas();
                panic("Out of memory and no killable processes...\n");
        }
 
-       printk("oom-killer: gfp_mask=0x%x\n", gfp_mask);
-       show_free_areas();
        mm = oom_kill_process(p);
        if (!mm)
                goto retry;
index b1061b1962f86497a0deb83c2409b0e571fbf9d3..206920796f5f68cb176afa138238bd3584106a5a 100644 (file)
@@ -105,11 +105,13 @@ static void bad_page(const char *function, struct page *page)
        printk(KERN_EMERG "Backtrace:\n");
        dump_stack();
        printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
-       page->flags &= ~(1 << PG_private        |
+       page->flags &= ~(1 << PG_lru    |
+                       1 << PG_private |
                        1 << PG_locked  |
-                       1 << PG_lru     |
                        1 << PG_active  |
                        1 << PG_dirty   |
+                       1 << PG_reclaim |
+                       1 << PG_slab    |
                        1 << PG_swapcache |
                        1 << PG_writeback);
        set_page_count(page, 0);
@@ -440,14 +442,17 @@ void set_page_refs(struct page *page, int order)
  */
 static void prep_new_page(struct page *page, int order)
 {
-       if (page->mapping || page_mapcount(page) ||
-           (page->flags & (
+       if (    page_mapcount(page) ||
+               page->mapping != NULL ||
+               page_count(page) != 0 ||
+               (page->flags & (
+                       1 << PG_lru     |
                        1 << PG_private |
                        1 << PG_locked  |
-                       1 << PG_lru     |
                        1 << PG_active  |
                        1 << PG_dirty   |
                        1 << PG_reclaim |
+                       1 << PG_slab    |
                        1 << PG_swapcache |
                        1 << PG_writeback )))
                bad_page(__FUNCTION__, page);
@@ -511,6 +516,36 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
        return allocated;
 }
 
+#ifdef CONFIG_NUMA
+/* Called from the slab reaper to drain remote pagesets */
+void drain_remote_pages(void)
+{
+       struct zone *zone;
+       int i;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       for_each_zone(zone) {
+               struct per_cpu_pageset *pset;
+
+               /* Do not drain local pagesets */
+               if (zone->zone_pgdat->node_id == numa_node_id())
+                       continue;
+
+               pset = zone->pageset[smp_processor_id()];
+               for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
+                       struct per_cpu_pages *pcp;
+
+                       pcp = &pset->pcp[i];
+                       if (pcp->count)
+                               pcp->count -= free_pages_bulk(zone, pcp->count,
+                                               &pcp->list, 0);
+               }
+       }
+       local_irq_restore(flags);
+}
+#endif
+
 #if defined(CONFIG_PM) || defined(CONFIG_HOTPLUG_CPU)
 static void __drain_pages(unsigned int cpu)
 {
@@ -520,7 +555,7 @@ static void __drain_pages(unsigned int cpu)
        for_each_zone(zone) {
                struct per_cpu_pageset *pset;
 
-               pset = &zone->pageset[cpu];
+               pset = zone_pcp(zone, cpu);
                for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
                        struct per_cpu_pages *pcp;
 
@@ -583,12 +618,12 @@ static void zone_statistics(struct zonelist *zonelist, struct zone *z)
 
        local_irq_save(flags);
        cpu = smp_processor_id();
-       p = &z->pageset[cpu];
+       p = zone_pcp(z,cpu);
        if (pg == orig) {
-               z->pageset[cpu].numa_hit++;
+               p->numa_hit++;
        } else {
                p->numa_miss++;
-               zonelist->zones[0]->pageset[cpu].numa_foreign++;
+               zone_pcp(zonelist->zones[0], cpu)->numa_foreign++;
        }
        if (pg == NODE_DATA(numa_node_id()))
                p->local_node++;
@@ -615,12 +650,12 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
        if (PageAnon(page))
                page->mapping = NULL;
        free_pages_check(__FUNCTION__, page);
-       pcp = &zone->pageset[get_cpu()].pcp[cold];
+       pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
        local_irq_save(flags);
-       if (pcp->count >= pcp->high)
-               pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
        list_add(&page->lru, &pcp->list);
        pcp->count++;
+       if (pcp->count >= pcp->high)
+               pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
        local_irq_restore(flags);
        put_cpu();
 }
@@ -659,7 +694,7 @@ buffered_rmqueue(struct zone *zone, int order, unsigned int __nocast gfp_flags)
        if (order == 0) {
                struct per_cpu_pages *pcp;
 
-               pcp = &zone->pageset[get_cpu()].pcp[cold];
+               pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
                local_irq_save(flags);
                if (pcp->count <= pcp->low)
                        pcp->count += rmqueue_bulk(zone, 0,
@@ -724,6 +759,16 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
        return 1;
 }
 
+static inline int
+should_reclaim_zone(struct zone *z, unsigned int gfp_mask)
+{
+       if (!z->reclaim_pages)
+               return 0;
+       if (gfp_mask & __GFP_NORECLAIM)
+               return 0;
+       return 1;
+}
+
 /*
  * This is the 'heart' of the zoned buddy allocator.
  */
@@ -760,17 +805,32 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
 
        classzone_idx = zone_idx(zones[0]);
 
- restart:
+restart:
        /* Go through the zonelist once, looking for a zone with enough free */
        for (i = 0; (z = zones[i]) != NULL; i++) {
-
-               if (!zone_watermark_ok(z, order, z->pages_low,
-                                      classzone_idx, 0, 0))
-                       continue;
+               int do_reclaim = should_reclaim_zone(z, gfp_mask);
 
                if (!cpuset_zone_allowed(z))
                        continue;
 
+               /*
+                * If the zone is to attempt early page reclaim then this loop
+                * will try to reclaim pages and check the watermark a second
+                * time before giving up and falling back to the next zone.
+                */
+zone_reclaim_retry:
+               if (!zone_watermark_ok(z, order, z->pages_low,
+                                      classzone_idx, 0, 0)) {
+                       if (!do_reclaim)
+                               continue;
+                       else {
+                               zone_reclaim(z, gfp_mask, order);
+                               /* Only try reclaim once */
+                               do_reclaim = 0;
+                               goto zone_reclaim_retry;
+                       }
+               }
+
                page = buffered_rmqueue(z, order, gfp_mask);
                if (page)
                        goto got_pg;
@@ -829,7 +889,7 @@ rebalance:
        reclaim_state.reclaimed_slab = 0;
        p->reclaim_state = &reclaim_state;
 
-       did_some_progress = try_to_free_pages(zones, gfp_mask, order);
+       did_some_progress = try_to_free_pages(zones, gfp_mask);
 
        p->reclaim_state = NULL;
        p->flags &= ~PF_MEMALLOC;
@@ -905,6 +965,7 @@ nopage:
                        " order:%d, mode:0x%x\n",
                        p->comm, order, gfp_mask);
                dump_stack();
+               show_mem();
        }
        return NULL;
 got_pg:
@@ -1114,7 +1175,7 @@ void get_full_page_state(struct page_state *ret)
        __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long));
 }
 
-unsigned long __read_page_state(unsigned offset)
+unsigned long __read_page_state(unsigned long offset)
 {
        unsigned long ret = 0;
        int cpu;
@@ -1128,7 +1189,7 @@ unsigned long __read_page_state(unsigned offset)
        return ret;
 }
 
-void __mod_page_state(unsigned offset, unsigned long delta)
+void __mod_page_state(unsigned long offset, unsigned long delta)
 {
        unsigned long flags;
        void* ptr;
@@ -1237,22 +1298,23 @@ void show_free_areas(void)
                        if (!cpu_possible(cpu))
                                continue;
 
-                       pageset = zone->pageset + cpu;
+                       pageset = zone_pcp(zone, cpu);
 
                        for (temperature = 0; temperature < 2; temperature++)
-                               printk("cpu %d %s: low %d, high %d, batch %d\n",
+                               printk("cpu %d %s: low %d, high %d, batch %d used:%d\n",
                                        cpu,
                                        temperature ? "cold" : "hot",
                                        pageset->pcp[temperature].low,
                                        pageset->pcp[temperature].high,
-                                       pageset->pcp[temperature].batch);
+                                       pageset->pcp[temperature].batch,
+                                       pageset->pcp[temperature].count);
                }
        }
 
        get_page_state(&ps);
        get_zone_counts(&active, &inactive, &free);
 
-       printk("\nFree pages: %11ukB (%ukB HighMem)\n",
+       printk("Free pages: %11ukB (%ukB HighMem)\n",
                K(nr_free_pages()),
                K(nr_free_highpages()));
 
@@ -1620,6 +1682,155 @@ void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
        memmap_init_zone((size), (nid), (zone), (start_pfn))
 #endif
 
+static int __devinit zone_batchsize(struct zone *zone)
+{
+       int batch;
+
+       /*
+        * The per-cpu-pages pools are set to around 1000th of the
+        * size of the zone.  But no more than 1/4 of a meg - there's
+        * no point in going beyond the size of L2 cache.
+        *
+        * OK, so we don't know how big the cache is.  So guess.
+        */
+       batch = zone->present_pages / 1024;
+       if (batch * PAGE_SIZE > 256 * 1024)
+               batch = (256 * 1024) / PAGE_SIZE;
+       batch /= 4;             /* We effectively *= 4 below */
+       if (batch < 1)
+               batch = 1;
+
+       /*
+        * Clamp the batch to a 2^n - 1 value. Having a power
+        * of 2 value was found to be more likely to have
+        * suboptimal cache aliasing properties in some cases.
+        *
+        * For example if 2 tasks are alternately allocating
+        * batches of pages, one task can end up with a lot
+        * of pages of one half of the possible page colors
+        * and the other with pages of the other colors.
+        */
+       batch = (1 << fls(batch + batch/2)) - 1;
+       return batch;
+}
+
+inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
+{
+       struct per_cpu_pages *pcp;
+
+       pcp = &p->pcp[0];               /* hot */
+       pcp->count = 0;
+       pcp->low = 2 * batch;
+       pcp->high = 6 * batch;
+       pcp->batch = max(1UL, 1 * batch);
+       INIT_LIST_HEAD(&pcp->list);
+
+       pcp = &p->pcp[1];               /* cold*/
+       pcp->count = 0;
+       pcp->low = 0;
+       pcp->high = 2 * batch;
+       pcp->batch = max(1UL, 1 * batch);
+       INIT_LIST_HEAD(&pcp->list);
+}
+
+#ifdef CONFIG_NUMA
+/*
+ * Boot pageset table. One per cpu which is going to be used for all
+ * zones and all nodes. The parameters will be set in such a way
+ * that an item put on a list will immediately be handed over to
+ * the buddy list. This is safe since pageset manipulation is done
+ * with interrupts disabled.
+ *
+ * Some NUMA counter updates may also be caught by the boot pagesets.
+ * These will be discarded when bootup is complete.
+ */
+static struct per_cpu_pageset
+       boot_pageset[NR_CPUS] __initdata;
+
+/*
+ * Dynamically allocate memory for the
+ * per cpu pageset array in struct zone.
+ */
+static int __devinit process_zones(int cpu)
+{
+       struct zone *zone, *dzone;
+
+       for_each_zone(zone) {
+
+               zone->pageset[cpu] = kmalloc_node(sizeof(struct per_cpu_pageset),
+                                        GFP_KERNEL, cpu_to_node(cpu));
+               if (!zone->pageset[cpu])
+                       goto bad;
+
+               setup_pageset(zone->pageset[cpu], zone_batchsize(zone));
+       }
+
+       return 0;
+bad:
+       for_each_zone(dzone) {
+               if (dzone == zone)
+                       break;
+               kfree(dzone->pageset[cpu]);
+               dzone->pageset[cpu] = NULL;
+       }
+       return -ENOMEM;
+}
+
+static inline void free_zone_pagesets(int cpu)
+{
+#ifdef CONFIG_NUMA
+       struct zone *zone;
+
+       for_each_zone(zone) {
+               struct per_cpu_pageset *pset = zone_pcp(zone, cpu);
+
+               zone_pcp(zone, cpu) = NULL;
+               kfree(pset);
+       }
+#endif
+}
+
+static int __devinit pageset_cpuup_callback(struct notifier_block *nfb,
+               unsigned long action,
+               void *hcpu)
+{
+       int cpu = (long)hcpu;
+       int ret = NOTIFY_OK;
+
+       switch (action) {
+               case CPU_UP_PREPARE:
+                       if (process_zones(cpu))
+                               ret = NOTIFY_BAD;
+                       break;
+#ifdef CONFIG_HOTPLUG_CPU
+               case CPU_DEAD:
+                       free_zone_pagesets(cpu);
+                       break;
+#endif
+               default:
+                       break;
+       }
+       return ret;
+}
+
+static struct notifier_block pageset_notifier =
+       { &pageset_cpuup_callback, NULL, 0 };
+
+void __init setup_per_cpu_pageset()
+{
+       int err;
+
+       /* Initialize per_cpu_pageset for cpu 0.
+        * A cpuup callback will do this for every cpu
+        * as it comes online
+        */
+       err = process_zones(smp_processor_id());
+       BUG_ON(err);
+       register_cpu_notifier(&pageset_notifier);
+}
+
+#endif
+
 /*
  * Set up the zone data structures:
  *   - mark all pages reserved
@@ -1662,48 +1873,16 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
 
                zone->temp_priority = zone->prev_priority = DEF_PRIORITY;
 
-               /*
-                * The per-cpu-pages pools are set to around 1000th of the
-                * size of the zone.  But no more than 1/4 of a meg - there's
-                * no point in going beyond the size of L2 cache.
-                *
-                * OK, so we don't know how big the cache is.  So guess.
-                */
-               batch = zone->present_pages / 1024;
-               if (batch * PAGE_SIZE > 256 * 1024)
-                       batch = (256 * 1024) / PAGE_SIZE;
-               batch /= 4;             /* We effectively *= 4 below */
-               if (batch < 1)
-                       batch = 1;
-
-               /*
-                * Clamp the batch to a 2^n - 1 value. Having a power
-                * of 2 value was found to be more likely to have
-                * suboptimal cache aliasing properties in some cases.
-                *
-                * For example if 2 tasks are alternately allocating
-                * batches of pages, one task can end up with a lot
-                * of pages of one half of the possible page colors
-                * and the other with pages of the other colors.
-                */
-               batch = (1 << fls(batch + batch/2)) - 1;
+               batch = zone_batchsize(zone);
 
                for (cpu = 0; cpu < NR_CPUS; cpu++) {
-                       struct per_cpu_pages *pcp;
-
-                       pcp = &zone->pageset[cpu].pcp[0];       /* hot */
-                       pcp->count = 0;
-                       pcp->low = 2 * batch;
-                       pcp->high = 6 * batch;
-                       pcp->batch = 1 * batch;
-                       INIT_LIST_HEAD(&pcp->list);
-
-                       pcp = &zone->pageset[cpu].pcp[1];       /* cold */
-                       pcp->count = 0;
-                       pcp->low = 0;
-                       pcp->high = 2 * batch;
-                       pcp->batch = 1 * batch;
-                       INIT_LIST_HEAD(&pcp->list);
+#ifdef CONFIG_NUMA
+                       /* Early boot. Slab allocator not functional yet */
+                       zone->pageset[cpu] = &boot_pageset[cpu];
+                       setup_pageset(&boot_pageset[cpu],0);
+#else
+                       setup_pageset(zone_pcp(zone,cpu), batch);
+#endif
                }
                printk(KERN_DEBUG "  %s zone: %lu pages, LIFO batch:%lu\n",
                                zone_names[j], realsize, batch);
@@ -1713,6 +1892,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
                zone->nr_scan_inactive = 0;
                zone->nr_active = 0;
                zone->nr_inactive = 0;
+               atomic_set(&zone->reclaim_in_progress, -1);
                if (!size)
                        continue;
 
@@ -1853,6 +2033,115 @@ struct seq_operations fragmentation_op = {
        .show   = frag_show,
 };
 
+/*
+ * Output information about zones in @pgdat.
+ */
+static int zoneinfo_show(struct seq_file *m, void *arg)
+{
+       pg_data_t *pgdat = arg;
+       struct zone *zone;
+       struct zone *node_zones = pgdat->node_zones;
+       unsigned long flags;
+
+       for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) {
+               int i;
+
+               if (!zone->present_pages)
+                       continue;
+
+               spin_lock_irqsave(&zone->lock, flags);
+               seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name);
+               seq_printf(m,
+                          "\n  pages free     %lu"
+                          "\n        min      %lu"
+                          "\n        low      %lu"
+                          "\n        high     %lu"
+                          "\n        active   %lu"
+                          "\n        inactive %lu"
+                          "\n        scanned  %lu (a: %lu i: %lu)"
+                          "\n        spanned  %lu"
+                          "\n        present  %lu",
+                          zone->free_pages,
+                          zone->pages_min,
+                          zone->pages_low,
+                          zone->pages_high,
+                          zone->nr_active,
+                          zone->nr_inactive,
+                          zone->pages_scanned,
+                          zone->nr_scan_active, zone->nr_scan_inactive,
+                          zone->spanned_pages,
+                          zone->present_pages);
+               seq_printf(m,
+                          "\n        protection: (%lu",
+                          zone->lowmem_reserve[0]);
+               for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
+                       seq_printf(m, ", %lu", zone->lowmem_reserve[i]);
+               seq_printf(m,
+                          ")"
+                          "\n  pagesets");
+               for (i = 0; i < ARRAY_SIZE(zone->pageset); i++) {
+                       struct per_cpu_pageset *pageset;
+                       int j;
+
+                       pageset = zone_pcp(zone, i);
+                       for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+                               if (pageset->pcp[j].count)
+                                       break;
+                       }
+                       if (j == ARRAY_SIZE(pageset->pcp))
+                               continue;
+                       for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+                               seq_printf(m,
+                                          "\n    cpu: %i pcp: %i"
+                                          "\n              count: %i"
+                                          "\n              low:   %i"
+                                          "\n              high:  %i"
+                                          "\n              batch: %i",
+                                          i, j,
+                                          pageset->pcp[j].count,
+                                          pageset->pcp[j].low,
+                                          pageset->pcp[j].high,
+                                          pageset->pcp[j].batch);
+                       }
+#ifdef CONFIG_NUMA
+                       seq_printf(m,
+                                  "\n            numa_hit:       %lu"
+                                  "\n            numa_miss:      %lu"
+                                  "\n            numa_foreign:   %lu"
+                                  "\n            interleave_hit: %lu"
+                                  "\n            local_node:     %lu"
+                                  "\n            other_node:     %lu",
+                                  pageset->numa_hit,
+                                  pageset->numa_miss,
+                                  pageset->numa_foreign,
+                                  pageset->interleave_hit,
+                                  pageset->local_node,
+                                  pageset->other_node);
+#endif
+               }
+               seq_printf(m,
+                          "\n  all_unreclaimable: %u"
+                          "\n  prev_priority:     %i"
+                          "\n  temp_priority:     %i"
+                          "\n  start_pfn:         %lu",
+                          zone->all_unreclaimable,
+                          zone->prev_priority,
+                          zone->temp_priority,
+                          zone->zone_start_pfn);
+               spin_unlock_irqrestore(&zone->lock, flags);
+               seq_putc(m, '\n');
+       }
+       return 0;
+}
+
+struct seq_operations zoneinfo_op = {
+       .start  = frag_start, /* iterate over all zones. The same as in
+                              * fragmentation. */
+       .next   = frag_next,
+       .stop   = frag_stop,
+       .show   = zoneinfo_show,
+};
+
 static char *vmstat_text[] = {
        "nr_dirty",
        "nr_writeback",
@@ -2058,10 +2347,10 @@ static void setup_per_zone_pages_min(void)
                                min_pages = 128;
                        zone->pages_min = min_pages;
                } else {
-                       /* if it's a lowmem zone, reserve a number of pages 
+                       /* if it's a lowmem zone, reserve a number of pages
                         * proportionate to the zone's size.
                         */
-                       zone->pages_min = (pages_min * zone->present_pages) / 
+                       zone->pages_min = (pages_min * zone->present_pages) /
                                           lowmem_pages;
                }
 
index 9827409eb7c7ea4026e27b34fdaceacd909cabc3..89770bd25f31be71877813a292793fcc62e01116 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -539,27 +539,6 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
                goto out_unmap;
        }
 
-       /*
-        * Don't pull an anonymous page out from under get_user_pages.
-        * GUP carefully breaks COW and raises page count (while holding
-        * page_table_lock, as we have here) to make sure that the page
-        * cannot be freed.  If we unmap that page here, a user write
-        * access to the virtual address will bring back the page, but
-        * its raised count will (ironically) be taken to mean it's not
-        * an exclusive swap page, do_wp_page will replace it by a copy
-        * page, and the user never get to see the data GUP was holding
-        * the original page for.
-        *
-        * This test is also useful for when swapoff (unuse_process) has
-        * to drop page lock: its reference to the page stops existing
-        * ptes from being unmapped, so swapoff can make progress.
-        */
-       if (PageSwapCache(page) &&
-           page_count(page) != page_mapcount(page) + 2) {
-               ret = SWAP_FAIL;
-               goto out_unmap;
-       }
-
        /* Nuke the page table entry. */
        flush_cache_page(vma, address, page_to_pfn(page));
        pteval = ptep_clear_flush(vma, address, pte);
index 61574b81d979f3169bd77f0af20e4d7cde626743..e64fa726a790e0c4162fec88db0e1032dd8a5be0 100644 (file)
@@ -6,8 +6,8 @@
  *              2000-2001 Christoph Rohland
  *              2000-2001 SAP AG
  *              2002 Red Hat Inc.
- * Copyright (C) 2002-2004 Hugh Dickins.
- * Copyright (C) 2002-2004 VERITAS Software Corporation.
+ * Copyright (C) 2002-2005 Hugh Dickins.
+ * Copyright (C) 2002-2005 VERITAS Software Corporation.
  * Copyright (C) 2004 Andi Kleen, SuSE Labs
  *
  * Extended attribute support for tmpfs:
@@ -194,7 +194,7 @@ static DEFINE_SPINLOCK(shmem_swaplist_lock);
 static void shmem_free_blocks(struct inode *inode, long pages)
 {
        struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-       if (sbinfo) {
+       if (sbinfo->max_blocks) {
                spin_lock(&sbinfo->stat_lock);
                sbinfo->free_blocks += pages;
                inode->i_blocks -= pages*BLOCKS_PER_PAGE;
@@ -357,7 +357,7 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long
                 * page (and perhaps indirect index pages) yet to allocate:
                 * a waste to allocate index if we cannot allocate data.
                 */
-               if (sbinfo) {
+               if (sbinfo->max_blocks) {
                        spin_lock(&sbinfo->stat_lock);
                        if (sbinfo->free_blocks <= 1) {
                                spin_unlock(&sbinfo->stat_lock);
@@ -677,8 +677,8 @@ static void shmem_delete_inode(struct inode *inode)
                        spin_unlock(&shmem_swaplist_lock);
                }
        }
-       if (sbinfo) {
-               BUG_ON(inode->i_blocks);
+       BUG_ON(inode->i_blocks);
+       if (sbinfo->max_inodes) {
                spin_lock(&sbinfo->stat_lock);
                sbinfo->free_inodes++;
                spin_unlock(&sbinfo->stat_lock);
@@ -1080,7 +1080,7 @@ repeat:
        } else {
                shmem_swp_unmap(entry);
                sbinfo = SHMEM_SB(inode->i_sb);
-               if (sbinfo) {
+               if (sbinfo->max_blocks) {
                        spin_lock(&sbinfo->stat_lock);
                        if (sbinfo->free_blocks == 0 ||
                            shmem_acct_block(info->flags)) {
@@ -1269,7 +1269,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
        struct shmem_inode_info *info;
        struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
 
-       if (sbinfo) {
+       if (sbinfo->max_inodes) {
                spin_lock(&sbinfo->stat_lock);
                if (!sbinfo->free_inodes) {
                        spin_unlock(&sbinfo->stat_lock);
@@ -1319,7 +1319,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
                        mpol_shared_policy_init(&info->policy);
                        break;
                }
-       } else if (sbinfo) {
+       } else if (sbinfo->max_inodes) {
                spin_lock(&sbinfo->stat_lock);
                sbinfo->free_inodes++;
                spin_unlock(&sbinfo->stat_lock);
@@ -1328,31 +1328,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 }
 
 #ifdef CONFIG_TMPFS
-
-static int shmem_set_size(struct shmem_sb_info *sbinfo,
-                         unsigned long max_blocks, unsigned long max_inodes)
-{
-       int error;
-       unsigned long blocks, inodes;
-
-       spin_lock(&sbinfo->stat_lock);
-       blocks = sbinfo->max_blocks - sbinfo->free_blocks;
-       inodes = sbinfo->max_inodes - sbinfo->free_inodes;
-       error = -EINVAL;
-       if (max_blocks < blocks)
-               goto out;
-       if (max_inodes < inodes)
-               goto out;
-       error = 0;
-       sbinfo->max_blocks  = max_blocks;
-       sbinfo->free_blocks = max_blocks - blocks;
-       sbinfo->max_inodes  = max_inodes;
-       sbinfo->free_inodes = max_inodes - inodes;
-out:
-       spin_unlock(&sbinfo->stat_lock);
-       return error;
-}
-
 static struct inode_operations shmem_symlink_inode_operations;
 static struct inode_operations shmem_symlink_inline_operations;
 
@@ -1607,15 +1582,17 @@ static int shmem_statfs(struct super_block *sb, struct kstatfs *buf)
        buf->f_type = TMPFS_MAGIC;
        buf->f_bsize = PAGE_CACHE_SIZE;
        buf->f_namelen = NAME_MAX;
-       if (sbinfo) {
-               spin_lock(&sbinfo->stat_lock);
+       spin_lock(&sbinfo->stat_lock);
+       if (sbinfo->max_blocks) {
                buf->f_blocks = sbinfo->max_blocks;
                buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
+       }
+       if (sbinfo->max_inodes) {
                buf->f_files = sbinfo->max_inodes;
                buf->f_ffree = sbinfo->free_inodes;
-               spin_unlock(&sbinfo->stat_lock);
        }
        /* else leave those fields 0 like simple_statfs */
+       spin_unlock(&sbinfo->stat_lock);
        return 0;
 }
 
@@ -1672,7 +1649,7 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
         * but each new link needs a new dentry, pinning lowmem, and
         * tmpfs dentries cannot be pruned until they are unlinked.
         */
-       if (sbinfo) {
+       if (sbinfo->max_inodes) {
                spin_lock(&sbinfo->stat_lock);
                if (!sbinfo->free_inodes) {
                        spin_unlock(&sbinfo->stat_lock);
@@ -1697,7 +1674,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
 
        if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
                struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-               if (sbinfo) {
+               if (sbinfo->max_inodes) {
                        spin_lock(&sbinfo->stat_lock);
                        sbinfo->free_inodes++;
                        spin_unlock(&sbinfo->stat_lock);
@@ -1921,22 +1898,42 @@ bad_val:
 static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
 {
        struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
-       unsigned long max_blocks = 0;
-       unsigned long max_inodes = 0;
+       unsigned long max_blocks = sbinfo->max_blocks;
+       unsigned long max_inodes = sbinfo->max_inodes;
+       unsigned long blocks;
+       unsigned long inodes;
+       int error = -EINVAL;
+
+       if (shmem_parse_options(data, NULL, NULL, NULL,
+                               &max_blocks, &max_inodes))
+               return error;
 
-       if (sbinfo) {
-               max_blocks = sbinfo->max_blocks;
-               max_inodes = sbinfo->max_inodes;
-       }
-       if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks, &max_inodes))
-               return -EINVAL;
-       /* Keep it simple: disallow limited <-> unlimited remount */
-       if ((max_blocks || max_inodes) == !sbinfo)
-               return -EINVAL;
-       /* But allow the pointless unlimited -> unlimited remount */
-       if (!sbinfo)
-               return 0;
-       return shmem_set_size(sbinfo, max_blocks, max_inodes);
+       spin_lock(&sbinfo->stat_lock);
+       blocks = sbinfo->max_blocks - sbinfo->free_blocks;
+       inodes = sbinfo->max_inodes - sbinfo->free_inodes;
+       if (max_blocks < blocks)
+               goto out;
+       if (max_inodes < inodes)
+               goto out;
+       /*
+        * Those tests also disallow limited->unlimited while any are in
+        * use, so i_blocks will always be zero when max_blocks is zero;
+        * but we must separately disallow unlimited->limited, because
+        * in that case we have no record of how much is already in use.
+        */
+       if (max_blocks && !sbinfo->max_blocks)
+               goto out;
+       if (max_inodes && !sbinfo->max_inodes)
+               goto out;
+
+       error = 0;
+       sbinfo->max_blocks  = max_blocks;
+       sbinfo->free_blocks = max_blocks - blocks;
+       sbinfo->max_inodes  = max_inodes;
+       sbinfo->free_inodes = max_inodes - inodes;
+out:
+       spin_unlock(&sbinfo->stat_lock);
+       return error;
 }
 #endif
 
@@ -1961,11 +1958,11 @@ static int shmem_fill_super(struct super_block *sb,
        uid_t uid = current->fsuid;
        gid_t gid = current->fsgid;
        int err = -ENOMEM;
-
-#ifdef CONFIG_TMPFS
+       struct shmem_sb_info *sbinfo;
        unsigned long blocks = 0;
        unsigned long inodes = 0;
 
+#ifdef CONFIG_TMPFS
        /*
         * Per default we only allow half of the physical ram per
         * tmpfs instance, limiting inodes to one per page of lowmem;
@@ -1976,34 +1973,34 @@ static int shmem_fill_super(struct super_block *sb,
                inodes = totalram_pages - totalhigh_pages;
                if (inodes > blocks)
                        inodes = blocks;
-
-               if (shmem_parse_options(data, &mode,
-                                       &uid, &gid, &blocks, &inodes))
+               if (shmem_parse_options(data, &mode, &uid, &gid,
+                                       &blocks, &inodes))
                        return -EINVAL;
        }
-
-       if (blocks || inodes) {
-               struct shmem_sb_info *sbinfo;
-               sbinfo = kmalloc(sizeof(struct shmem_sb_info), GFP_KERNEL);
-               if (!sbinfo)
-                       return -ENOMEM;
-               sb->s_fs_info = sbinfo;
-               spin_lock_init(&sbinfo->stat_lock);
-               sbinfo->max_blocks = blocks;
-               sbinfo->free_blocks = blocks;
-               sbinfo->max_inodes = inodes;
-               sbinfo->free_inodes = inodes;
-       }
-       sb->s_xattr = shmem_xattr_handlers;
 #else
        sb->s_flags |= MS_NOUSER;
 #endif
 
+       /* Round up to L1_CACHE_BYTES to resist false sharing */
+       sbinfo = kmalloc(max((int)sizeof(struct shmem_sb_info),
+                               L1_CACHE_BYTES), GFP_KERNEL);
+       if (!sbinfo)
+               return -ENOMEM;
+
+       spin_lock_init(&sbinfo->stat_lock);
+       sbinfo->max_blocks = blocks;
+       sbinfo->free_blocks = blocks;
+       sbinfo->max_inodes = inodes;
+       sbinfo->free_inodes = inodes;
+
+       sb->s_fs_info = sbinfo;
        sb->s_maxbytes = SHMEM_MAX_BYTES;
        sb->s_blocksize = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
        sb->s_magic = TMPFS_MAGIC;
        sb->s_op = &shmem_ops;
+       sb->s_xattr = shmem_xattr_handlers;
+
        inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
        if (!inode)
                goto failed;
index c78d343b3c5f909d29090e0608c5fc7ebb3ca146..93cbbbb39f42a783244e6bfaebfbd68f1f017e4c 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2851,6 +2851,7 @@ next:
        }
        check_irq_on();
        up(&cache_chain_sem);
+       drain_remote_pages();
        /* Setup the next iteration */
        schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
 }
index da48405cd9a3199d9088d1221864fa77a76a108d..60cd24a55204efc5c84956443d02f9806bd66a9d 100644 (file)
@@ -276,61 +276,37 @@ void swap_free(swp_entry_t entry)
 }
 
 /*
- * Check if we're the only user of a swap page,
- * when the page is locked.
+ * How many references to page are currently swapped out?
  */
-static int exclusive_swap_page(struct page *page)
+static inline int page_swapcount(struct page *page)
 {
-       int retval = 0;
-       struct swap_info_struct * p;
+       int count = 0;
+       struct swap_info_struct *p;
        swp_entry_t entry;
 
        entry.val = page->private;
        p = swap_info_get(entry);
        if (p) {
-               /* Is the only swap cache user the cache itself? */
-               if (p->swap_map[swp_offset(entry)] == 1) {
-                       /* Recheck the page count with the swapcache lock held.. */
-                       write_lock_irq(&swapper_space.tree_lock);
-                       if (page_count(page) == 2)
-                               retval = 1;
-                       write_unlock_irq(&swapper_space.tree_lock);
-               }
+               /* Subtract the 1 for the swap cache itself */
+               count = p->swap_map[swp_offset(entry)] - 1;
                swap_info_put(p);
        }
-       return retval;
+       return count;
 }
 
 /*
  * We can use this swap cache entry directly
  * if there are no other references to it.
- *
- * Here "exclusive_swap_page()" does the real
- * work, but we opportunistically check whether
- * we need to get all the locks first..
  */
 int can_share_swap_page(struct page *page)
 {
-       int retval = 0;
+       int count;
 
-       if (!PageLocked(page))
-               BUG();
-       switch (page_count(page)) {
-       case 3:
-               if (!PagePrivate(page))
-                       break;
-               /* Fallthrough */
-       case 2:
-               if (!PageSwapCache(page))
-                       break;
-               retval = exclusive_swap_page(page);
-               break;
-       case 1:
-               if (PageReserved(page))
-                       break;
-               retval = 1;
-       }
-       return retval;
+       BUG_ON(!PageLocked(page));
+       count = page_mapcount(page);
+       if (count <= 1 && PageSwapCache(page))
+               count += page_swapcount(page);
+       return count == 1;
 }
 
 /*
@@ -529,9 +505,10 @@ static int unuse_mm(struct mm_struct *mm,
 
        if (!down_read_trylock(&mm->mmap_sem)) {
                /*
-                * Our reference to the page stops try_to_unmap_one from
-                * unmapping its ptes, so swapoff can make progress.
+                * Activate page so shrink_cache is unlikely to unmap its
+                * ptes while lock is dropped, so swapoff can make progress.
                 */
+               activate_page(page);
                unlock_page(page);
                down_read(&mm->mmap_sem);
                lock_page(page);
index 269eded9b459804a8f090ea8dad0b908a4afef0d..4b8e62a193708b7c12808cdb0eccfad61a38bce5 100644 (file)
@@ -74,6 +74,9 @@ struct scan_control {
 
        int may_writepage;
 
+       /* Can pages be swapped as part of reclaim? */
+       int may_swap;
+
        /* This context's SWAP_CLUSTER_MAX. If freeing memory for
         * suspend, we effectively ignore SWAP_CLUSTER_MAX.
         * In this context, it doesn't matter that we scan the
@@ -180,17 +183,20 @@ EXPORT_SYMBOL(remove_shrinker);
  * `lru_pages' represents the number of on-LRU pages in all the zones which
  * are eligible for the caller's allocation attempt.  It is used for balancing
  * slab reclaim versus page reclaim.
+ *
+ * Returns the number of slab objects which we shrunk.
  */
 static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
                        unsigned long lru_pages)
 {
        struct shrinker *shrinker;
+       int ret = 0;
 
        if (scanned == 0)
                scanned = SWAP_CLUSTER_MAX;
 
        if (!down_read_trylock(&shrinker_rwsem))
-               return 0;
+               return 1;       /* Assume we'll be able to shrink next time */
 
        list_for_each_entry(shrinker, &shrinker_list, list) {
                unsigned long long delta;
@@ -209,10 +215,14 @@ static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
                while (total_scan >= SHRINK_BATCH) {
                        long this_scan = SHRINK_BATCH;
                        int shrink_ret;
+                       int nr_before;
 
+                       nr_before = (*shrinker->shrinker)(0, gfp_mask);
                        shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask);
                        if (shrink_ret == -1)
                                break;
+                       if (shrink_ret < nr_before)
+                               ret += nr_before - shrink_ret;
                        mod_page_state(slabs_scanned, this_scan);
                        total_scan -= this_scan;
 
@@ -222,7 +232,7 @@ static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
                shrinker->nr += total_scan;
        }
        up_read(&shrinker_rwsem);
-       return 0;
+       return ret;
 }
 
 /* Called without lock on whether page is mapped, so answer is unstable */
@@ -407,7 +417,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
                 * Anonymous process memory has backing store?
                 * Try to allocate it some swap space here.
                 */
-               if (PageAnon(page) && !PageSwapCache(page)) {
+               if (PageAnon(page) && !PageSwapCache(page) && sc->may_swap) {
                        if (!add_to_swap(page))
                                goto activate_locked;
                }
@@ -890,7 +900,9 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
                if (zone->all_unreclaimable && sc->priority != DEF_PRIORITY)
                        continue;       /* Let kswapd poll it */
 
+               atomic_inc(&zone->reclaim_in_progress);
                shrink_zone(zone, sc);
+               atomic_dec(&zone->reclaim_in_progress);
        }
 }
  
@@ -907,8 +919,7 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
  * holds filesystem locks which prevent writeout this might not work, and the
  * allocation attempt will fail.
  */
-int try_to_free_pages(struct zone **zones,
-               unsigned int gfp_mask, unsigned int order)
+int try_to_free_pages(struct zone **zones, unsigned int gfp_mask)
 {
        int priority;
        int ret = 0;
@@ -920,6 +931,7 @@ int try_to_free_pages(struct zone **zones,
 
        sc.gfp_mask = gfp_mask;
        sc.may_writepage = 0;
+       sc.may_swap = 1;
 
        inc_page_state(allocstall);
 
@@ -1020,6 +1032,7 @@ loop_again:
        total_reclaimed = 0;
        sc.gfp_mask = GFP_KERNEL;
        sc.may_writepage = 0;
+       sc.may_swap = 1;
        sc.nr_mapped = read_page_state(nr_mapped);
 
        inc_page_state(pageoutrun);
@@ -1079,6 +1092,7 @@ scan:
                 */
                for (i = 0; i <= end_zone; i++) {
                        struct zone *zone = pgdat->node_zones + i;
+                       int nr_slab;
 
                        if (zone->present_pages == 0)
                                continue;
@@ -1098,16 +1112,19 @@ scan:
                        sc.nr_reclaimed = 0;
                        sc.priority = priority;
                        sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX;
+                       atomic_inc(&zone->reclaim_in_progress);
                        shrink_zone(zone, &sc);
+                       atomic_dec(&zone->reclaim_in_progress);
                        reclaim_state->reclaimed_slab = 0;
-                       shrink_slab(sc.nr_scanned, GFP_KERNEL, lru_pages);
+                       nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
+                                               lru_pages);
                        sc.nr_reclaimed += reclaim_state->reclaimed_slab;
                        total_reclaimed += sc.nr_reclaimed;
                        total_scanned += sc.nr_scanned;
                        if (zone->all_unreclaimable)
                                continue;
-                       if (zone->pages_scanned >= (zone->nr_active +
-                                                       zone->nr_inactive) * 4)
+                       if (nr_slab == 0 && zone->pages_scanned >=
+                                   (zone->nr_active + zone->nr_inactive) * 4)
                                zone->all_unreclaimable = 1;
                        /*
                         * If we've done a decent amount of scanning and
@@ -1309,3 +1326,73 @@ static int __init kswapd_init(void)
 }
 
 module_init(kswapd_init)
+
+
+/*
+ * Try to free up some pages from this zone through reclaim.
+ */
+int zone_reclaim(struct zone *zone, unsigned int gfp_mask, unsigned int order)
+{
+       struct scan_control sc;
+       int nr_pages = 1 << order;
+       int total_reclaimed = 0;
+
+       /* The reclaim may sleep, so don't do it if sleep isn't allowed */
+       if (!(gfp_mask & __GFP_WAIT))
+               return 0;
+       if (zone->all_unreclaimable)
+               return 0;
+
+       sc.gfp_mask = gfp_mask;
+       sc.may_writepage = 0;
+       sc.may_swap = 0;
+       sc.nr_mapped = read_page_state(nr_mapped);
+       sc.nr_scanned = 0;
+       sc.nr_reclaimed = 0;
+       /* scan at the highest priority */
+       sc.priority = 0;
+
+       if (nr_pages > SWAP_CLUSTER_MAX)
+               sc.swap_cluster_max = nr_pages;
+       else
+               sc.swap_cluster_max = SWAP_CLUSTER_MAX;
+
+       /* Don't reclaim the zone if there are other reclaimers active */
+       if (!atomic_inc_and_test(&zone->reclaim_in_progress))
+               goto out;
+
+       shrink_zone(zone, &sc);
+       total_reclaimed = sc.nr_reclaimed;
+
+ out:
+       atomic_dec(&zone->reclaim_in_progress);
+       return total_reclaimed;
+}
+
+asmlinkage long sys_set_zone_reclaim(unsigned int node, unsigned int zone,
+                                    unsigned int state)
+{
+       struct zone *z;
+       int i;
+
+       if (node >= MAX_NUMNODES || !node_online(node))
+               return -EINVAL;
+
+       /* This will break if we ever add more zones */
+       if (!(zone & (1<<ZONE_DMA|1<<ZONE_NORMAL|1<<ZONE_HIGHMEM)))
+               return -EINVAL;
+
+       for (i = 0; i < MAX_NR_ZONES; i++) {
+               if (!(zone & 1<<i))
+                       continue;
+
+               z = &NODE_DATA(node)->node_zones[i];
+
+               if (state)
+                       z->reclaim_pages = 1;
+               else
+                       z->reclaim_pages = 0;
+       }
+
+       return 0;
+}
index 05107e0dc1450ec8f45d28f1320620c06cde17ca..567b03b1c349c3bfd4a7ba3ec5110bd3c0e474bb 100644 (file)
@@ -2,7 +2,7 @@
 # IP configuration
 #
 choice 
-       prompt "Choose IP: FIB lookup""
+       prompt "Choose IP: FIB lookup"
        depends on INET
        default IP_FIB_HASH
 
index db845cbd584138a25e569f78c7c11c4d587dafdc..87302a49067bd091d3bfa970524088b929f5e298 100644 (file)
@@ -1945,6 +1945,7 @@ static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void
        } while (*in_end++);
 
        copy_page(in_save, nosec_save);
+       free_page((unsigned long)nosec_save);
 out:
        return rc;
 }
index 047d59ea0573557392878be64ecbad3bb4acc395..ee794ae06040a2cf768092f79300ab4f8f1cf4fe 100644 (file)
@@ -42,6 +42,11 @@ menu "Advanced Linux Sound Architecture"
 config SND
        tristate "Advanced Linux Sound Architecture"
        depends on SOUND
+       help
+         Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture),
+         the new base sound system.
+
+         For more information, see <http://www.alsa-project.org/>
 
 source "sound/core/Kconfig"
 
index cdacf4d3a38719daf1813f318c0614c96df715f0..34c1740aa6e9a7e1a1e0f32cbecca1cd9d2783ca 100644 (file)
@@ -14,5 +14,11 @@ config SND_SA11XX_UDA1341
          To compile this driver as a module, choose M here: the module
          will be called snd-sa11xx-uda1341.
 
+config SND_ARMAACI
+       tristate "ARM PrimeCell PL041 AC Link support"
+       depends on SND && ARM_AMBA
+       select SND_PCM
+       select SND_AC97_CODEC
+
 endmenu
 
index d7e7dc0c3cdfafd8a346c36be1782ea4ce12c30e..f74ec28e1068179719fb8e39c87de50e67b10101 100644 (file)
@@ -6,3 +6,6 @@ snd-sa11xx-uda1341-objs := sa11xx-uda1341.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o 
+
+obj-$(CONFIG_SND_ARMAACI)      += snd-aaci.o
+snd-aaci-objs                  := aaci.o devdma.o
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
new file mode 100644 (file)
index 0000000..08cc3dd
--- /dev/null
@@ -0,0 +1,968 @@
+/*
+ *  linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Documentation: ARM DDI 0173B
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware/amba.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "aaci.h"
+#include "devdma.h"
+
+#define DRIVER_NAME    "aaci-pl041"
+
+/*
+ * PM support is not complete.  Turn it off.
+ */
+#undef CONFIG_PM
+
+static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97)
+{
+       u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);
+
+       /*
+        * Ensure that the slot 1/2 RX registers are empty.
+        */
+       v = readl(aaci->base + AACI_SLFR);
+       if (v & SLFR_2RXV)
+               readl(aaci->base + AACI_SL2RX);
+       if (v & SLFR_1RXV)
+               readl(aaci->base + AACI_SL1RX);
+
+       writel(maincr, aaci->base + AACI_MAINCR);
+}
+
+/*
+ * P29:
+ *  The recommended use of programming the external codec through slot 1
+ *  and slot 2 data is to use the channels during setup routines and the
+ *  slot register at any other time.  The data written into slot 1, slot 2
+ *  and slot 12 registers is transmitted only when their corresponding
+ *  SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
+ *  register.
+ */
+static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+{
+       struct aaci *aaci = ac97->private_data;
+       u32 v;
+
+       if (ac97->num >= 4)
+               return;
+
+       down(&aaci->ac97_sem);
+
+       aaci_ac97_select_codec(aaci, ac97);
+
+       /*
+        * P54: You must ensure that AACI_SL2TX is always written
+        * to, if required, before data is written to AACI_SL1TX.
+        */
+       writel(val << 4, aaci->base + AACI_SL2TX);
+       writel(reg << 12, aaci->base + AACI_SL1TX);
+
+       /*
+        * Wait for the transmission of both slots to complete.
+        */
+       do {
+               v = readl(aaci->base + AACI_SLFR);
+       } while (v & (SLFR_1TXB|SLFR_2TXB));
+
+       up(&aaci->ac97_sem);
+}
+
+/*
+ * Read an AC'97 register.
+ */
+static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg)
+{
+       struct aaci *aaci = ac97->private_data;
+       u32 v;
+
+       if (ac97->num >= 4)
+               return ~0;
+
+       down(&aaci->ac97_sem);
+
+       aaci_ac97_select_codec(aaci, ac97);
+
+       /*
+        * Write the register address to slot 1.
+        */
+       writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);
+
+       /*
+        * Wait for the transmission to complete.
+        */
+       do {
+               v = readl(aaci->base + AACI_SLFR);
+       } while (v & SLFR_1TXB);
+
+       /*
+        * Give the AC'97 codec more than enough time
+        * to respond. (42us = ~2 frames at 48kHz.)
+        */
+       udelay(42);
+
+       /*
+        * Wait for slot 2 to indicate data.
+        */
+       do {
+               cond_resched();
+               v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
+       } while (v != (SLFR_1RXV|SLFR_2RXV));
+
+       v = readl(aaci->base + AACI_SL1RX) >> 12;
+       if (v == reg) {
+               v = readl(aaci->base + AACI_SL2RX) >> 4;
+       } else {
+               dev_err(&aaci->dev->dev,
+                       "wrong ac97 register read back (%x != %x)\n",
+                       v, reg);
+               v = ~0;
+       }
+
+       up(&aaci->ac97_sem);
+       return v;
+}
+
+static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
+{
+       u32 val;
+       int timeout = 5000;
+
+       do {
+               val = readl(aacirun->base + AACI_SR);
+       } while (val & (SR_TXB|SR_RXB) && timeout--);
+}
+
+
+
+/*
+ * Interrupt support.
+ */
+static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
+{
+       if (mask & ISR_URINTR) {
+               writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR);
+       }
+
+       if (mask & ISR_TXINTR) {
+               struct aaci_runtime *aacirun = &aaci->playback;
+               void *ptr;
+
+               if (!aacirun->substream || !aacirun->start) {
+                       dev_warn(&aaci->dev->dev, "TX interrupt???");
+                       writel(0, aacirun->base + AACI_IE);
+                       return;
+               }
+
+               ptr = aacirun->ptr;
+               do {
+                       unsigned int len = aacirun->fifosz;
+                       u32 val;
+
+                       if (aacirun->bytes <= 0) {
+                               aacirun->bytes += aacirun->period;
+                               aacirun->ptr = ptr;
+                               spin_unlock(&aaci->lock);
+                               snd_pcm_period_elapsed(aacirun->substream);
+                               spin_lock(&aaci->lock);
+                       }
+                       if (!(aacirun->cr & TXCR_TXEN))
+                               break;
+
+                       val = readl(aacirun->base + AACI_SR);
+                       if (!(val & SR_TXHE))
+                               break;
+                       if (!(val & SR_TXFE))
+                               len >>= 1;
+
+                       aacirun->bytes -= len;
+
+                       /* writing 16 bytes at a time */
+                       for ( ; len > 0; len -= 16) {
+                               asm(
+                                       "ldmia  %0!, {r0, r1, r2, r3}\n\t"
+                                       "stmia  %1, {r0, r1, r2, r3}"
+                                       : "+r" (ptr)
+                                       : "r" (aacirun->fifo)
+                                       : "r0", "r1", "r2", "r3", "cc");
+
+                               if (ptr >= aacirun->end)
+                                       ptr = aacirun->start;
+                       }
+               } while (1);
+
+               aacirun->ptr = ptr;
+       }
+}
+
+static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+       struct aaci *aaci = devid;
+       u32 mask;
+       int i;
+
+       spin_lock(&aaci->lock);
+       mask = readl(aaci->base + AACI_ALLINTS);
+       if (mask) {
+               u32 m = mask;
+               for (i = 0; i < 4; i++, m >>= 7) {
+                       if (m & 0x7f) {
+                               aaci_fifo_irq(aaci, m);
+                       }
+               }
+       }
+       spin_unlock(&aaci->lock);
+
+       return mask ? IRQ_HANDLED : IRQ_NONE;
+}
+
+
+
+/*
+ * ALSA support.
+ */
+
+struct aaci_stream {
+       unsigned char codec_idx;
+       unsigned char rate_idx;
+};
+
+static struct aaci_stream aaci_streams[] = {
+       [ACSTREAM_FRONT] = {
+               .codec_idx      = 0,
+               .rate_idx       = AC97_RATES_FRONT_DAC,
+       },
+       [ACSTREAM_SURROUND] = {
+               .codec_idx      = 0,
+               .rate_idx       = AC97_RATES_SURR_DAC,
+       },
+       [ACSTREAM_LFE] = {
+               .codec_idx      = 0,
+               .rate_idx       = AC97_RATES_LFE_DAC,
+       },
+};
+
+static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid)
+{
+       struct aaci_stream *s = aaci_streams + streamid;
+       return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx];
+}
+
+static unsigned int rate_list[] = {
+       5512, 8000, 11025, 16000, 22050, 32000, 44100,
+       48000, 64000, 88200, 96000, 176400, 192000
+};
+
+/*
+ * Double-rate rule: we can support double rate iff channels == 2
+ *  (unimplemented)
+ */
+static int
+aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
+{
+       struct aaci *aaci = rule->private;
+       unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512;
+       snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS);
+
+       switch (c->max) {
+       case 6:
+               rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE);
+       case 4:
+               rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND);
+       case 2:
+               rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT);
+       }
+
+       return snd_interval_list(hw_param_interval(p, rule->var),
+                                ARRAY_SIZE(rate_list), rate_list,
+                                rate_mask);
+}
+
+static snd_pcm_hardware_t aaci_hw_info = {
+       .info                   = SNDRV_PCM_INFO_MMAP |
+                                 SNDRV_PCM_INFO_MMAP_VALID |
+                                 SNDRV_PCM_INFO_INTERLEAVED |
+                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                 SNDRV_PCM_INFO_RESUME,
+
+       /*
+        * ALSA doesn't support 18-bit or 20-bit packed into 32-bit
+        * words.  It also doesn't support 12-bit at all.
+        */
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
+
+       /* should this be continuous or knot? */
+       .rates                  = SNDRV_PCM_RATE_CONTINUOUS,
+       .rate_max               = 48000,
+       .rate_min               = 4000,
+       .channels_min           = 2,
+       .channels_max           = 6,
+       .buffer_bytes_max       = 64 * 1024,
+       .period_bytes_min       = 256,
+       .period_bytes_max       = PAGE_SIZE,
+       .periods_min            = 4,
+       .periods_max            = PAGE_SIZE / 16,
+};
+
+static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream,
+                        struct aaci_runtime *aacirun)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       int ret;
+
+       aacirun->substream = substream;
+       runtime->private_data = aacirun;
+       runtime->hw = aaci_hw_info;
+
+       /*
+        * FIXME: ALSA specifies fifo_size in bytes.  If we're in normal
+        * mode, each 32-bit word contains one sample.  If we're in
+        * compact mode, each 32-bit word contains two samples, effectively
+        * halving the FIFO size.  However, we don't know for sure which
+        * we'll be using at this point.  We set this to the lower limit.
+        */
+       runtime->hw.fifo_size = aaci->fifosize * 2;
+
+       /*
+        * Add rule describing hardware rate dependency
+        * on the number of channels.
+        */
+       ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+                                 aaci_rule_rate_by_channels, aaci,
+                                 SNDRV_PCM_HW_PARAM_CHANNELS,
+                                 SNDRV_PCM_HW_PARAM_RATE, -1);
+       if (ret)
+               goto out;
+
+       ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT,
+                         DRIVER_NAME, aaci);
+       if (ret)
+               goto out;
+
+       return 0;
+
+ out:
+       return ret;
+}
+
+
+/*
+ * Common ALSA stuff
+ */
+static int aaci_pcm_close(snd_pcm_substream_t *substream)
+{
+       struct aaci *aaci = substream->private_data;
+       struct aaci_runtime *aacirun = substream->runtime->private_data;
+
+       WARN_ON(aacirun->cr & TXCR_TXEN);
+
+       aacirun->substream = NULL;
+       free_irq(aaci->dev->irq[0], aaci);
+
+       return 0;
+}
+
+static int aaci_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+       struct aaci_runtime *aacirun = substream->runtime->private_data;
+
+       /*
+        * This must not be called with the device enabled.
+        */
+       WARN_ON(aacirun->cr & TXCR_TXEN);
+
+       if (aacirun->pcm_open)
+               snd_ac97_pcm_close(aacirun->pcm);
+       aacirun->pcm_open = 0;
+
+       /*
+        * Clear out the DMA and any allocated buffers.
+        */
+       devdma_hw_free(NULL, substream);
+
+       return 0;
+}
+
+static int aaci_pcm_hw_params(snd_pcm_substream_t *substream,
+                             struct aaci_runtime *aacirun,
+                             snd_pcm_hw_params_t *params)
+{
+       int err;
+
+       aaci_pcm_hw_free(substream);
+
+       err = devdma_hw_alloc(NULL, substream,
+                             params_buffer_bytes(params));
+       if (err < 0)
+               goto out;
+
+       err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+                               params_channels(params),
+                               aacirun->pcm->r[0].slots);
+       if (err)
+               goto out;
+
+       aacirun->pcm_open = 1;
+
+ out:
+       return err;
+}
+
+static int aaci_pcm_prepare(snd_pcm_substream_t *substream)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct aaci_runtime *aacirun = runtime->private_data;
+
+       aacirun->start  = (void *)runtime->dma_area;
+       aacirun->end    = aacirun->start + runtime->dma_bytes;
+       aacirun->ptr    = aacirun->start;
+       aacirun->period =
+       aacirun->bytes  = frames_to_bytes(runtime, runtime->period_size);
+
+       return 0;
+}
+
+static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct aaci_runtime *aacirun = runtime->private_data;
+       ssize_t bytes = aacirun->ptr - aacirun->start;
+
+       return bytes_to_frames(runtime, bytes);
+}
+
+static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+{
+       return devdma_mmap(NULL, substream, vma);
+}
+
+
+/*
+ * Playback specific ALSA stuff
+ */
+static const u32 channels_to_txmask[] = {
+       [2] = TXCR_TX3 | TXCR_TX4,
+       [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
+       [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
+};
+
+/*
+ * We can support two and four channel audio.  Unfortunately
+ * six channel audio requires a non-standard channel ordering:
+ *   2 -> FL(3), FR(4)
+ *   4 -> FL(3), FR(4), SL(7), SR(8)
+ *   6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
+ *        FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
+ * This requires an ALSA configuration file to correct.
+ */
+static unsigned int channel_list[] = { 2, 4, 6 };
+
+static int
+aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
+{
+       struct aaci *aaci = rule->private;
+       unsigned int chan_mask = 1 << 0, slots;
+
+       /*
+        * pcms[0] is the our 5.1 PCM instance.
+        */
+       slots = aaci->ac97_bus->pcms[0].r[0].slots;
+       if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
+               chan_mask |= 1 << 1;
+               if (slots & (1 << AC97_SLOT_LFE))
+                       chan_mask |= 1 << 2;
+       }
+
+       return snd_interval_list(hw_param_interval(p, rule->var),
+                                ARRAY_SIZE(channel_list), channel_list,
+                                chan_mask);
+}
+
+static int aaci_pcm_playback_open(snd_pcm_substream_t *substream)
+{
+       struct aaci *aaci = substream->private_data;
+       int ret;
+
+       /*
+        * Add rule describing channel dependency.
+        */
+       ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                 SNDRV_PCM_HW_PARAM_CHANNELS,
+                                 aaci_rule_channels, aaci,
+                                 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+       if (ret)
+               return ret;
+
+       return aaci_pcm_open(aaci, substream, &aaci->playback);
+}
+
+static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream,
+                                      snd_pcm_hw_params_t *params)
+{
+       struct aaci *aaci = substream->private_data;
+       struct aaci_runtime *aacirun = substream->runtime->private_data;
+       unsigned int channels = params_channels(params);
+       int ret;
+
+       WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) ||
+               !channels_to_txmask[channels]);
+
+       ret = aaci_pcm_hw_params(substream, aacirun, params);
+
+       /*
+        * Enable FIFO, compact mode, 16 bits per sample.
+        * FIXME: double rate slots?
+        */
+       if (ret >= 0) {
+               aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
+               aacirun->cr |= channels_to_txmask[channels];
+
+               aacirun->fifosz = aaci->fifosize * 4;
+               if (aacirun->cr & TXCR_COMPACT)
+                       aacirun->fifosz >>= 1;
+       }
+       return ret;
+}
+
+static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
+{
+       u32 ie;
+
+       ie = readl(aacirun->base + AACI_IE);
+       ie &= ~(IE_URIE|IE_TXIE);
+       writel(ie, aacirun->base + AACI_IE);
+       aacirun->cr &= ~TXCR_TXEN;
+       aaci_chan_wait_ready(aacirun);
+       writel(aacirun->cr, aacirun->base + AACI_TXCR);
+}
+
+static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
+{
+       u32 ie;
+
+       aaci_chan_wait_ready(aacirun);
+       aacirun->cr |= TXCR_TXEN;
+
+       ie = readl(aacirun->base + AACI_IE);
+       ie |= IE_URIE | IE_TXIE;
+       writel(ie, aacirun->base + AACI_IE);
+       writel(aacirun->cr, aacirun->base + AACI_TXCR);
+}
+
+static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+       struct aaci *aaci = substream->private_data;
+       struct aaci_runtime *aacirun = substream->runtime->private_data;
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&aaci->lock, flags);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               aaci_pcm_playback_start(aacirun);
+               break;
+
+       case SNDRV_PCM_TRIGGER_RESUME:
+               aaci_pcm_playback_start(aacirun);
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+               aaci_pcm_playback_stop(aacirun);
+               break;
+
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               aaci_pcm_playback_stop(aacirun);
+               break;
+
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               break;
+
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+       spin_unlock_irqrestore(&aaci->lock, flags);
+
+       return ret;
+}
+
+static snd_pcm_ops_t aaci_playback_ops = {
+       .open           = aaci_pcm_playback_open,
+       .close          = aaci_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = aaci_pcm_playback_hw_params,
+       .hw_free        = aaci_pcm_hw_free,
+       .prepare        = aaci_pcm_prepare,
+       .trigger        = aaci_pcm_playback_trigger,
+       .pointer        = aaci_pcm_pointer,
+       .mmap           = aaci_pcm_mmap,
+};
+
+
+
+/*
+ * Power Management.
+ */
+#ifdef CONFIG_PM
+static int aaci_do_suspend(snd_card_t *card, unsigned int state)
+{
+       struct aaci *aaci = card->private_data;
+       if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) {
+               snd_pcm_suspend_all(aaci->pcm);
+               snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold);
+       }
+       return 0;
+}
+
+static int aaci_do_resume(snd_card_t *card, unsigned int state)
+{
+       struct aaci *aaci = card->private_data;
+       if (aaci->card->power_state != SNDRV_CTL_POWER_D0) {
+               snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0);
+       }
+       return 0;
+}
+
+static int aaci_suspend(struct amba_device *dev, u32 state)
+{
+       snd_card_t *card = amba_get_drvdata(dev);
+       return card ? aaci_do_suspend(card) : 0;
+}
+
+static int aaci_resume(struct amba_device *dev)
+{
+       snd_card_t *card = amba_get_drvdata(dev);
+       return card ? aaci_do_resume(card) : 0;
+}
+#else
+#define aaci_do_suspend                NULL
+#define aaci_do_resume         NULL
+#define aaci_suspend           NULL
+#define aaci_resume            NULL
+#endif
+
+
+static struct ac97_pcm ac97_defs[] __devinitdata = {
+       [0] = {         /* Front PCM */
+               .exclusive = 1,
+               .r = {
+                       [0] = {
+                               .slots  = (1 << AC97_SLOT_PCM_LEFT) |
+                                         (1 << AC97_SLOT_PCM_RIGHT) |
+                                         (1 << AC97_SLOT_PCM_CENTER) |
+                                         (1 << AC97_SLOT_PCM_SLEFT) |
+                                         (1 << AC97_SLOT_PCM_SRIGHT) |
+                                         (1 << AC97_SLOT_LFE),
+                       },
+               },
+       },
+       [1] = { /* PCM in */
+               .stream = 1,
+               .exclusive = 1,
+               .r = {
+                       [0] = {
+                               .slots  = (1 << AC97_SLOT_PCM_LEFT) |
+                                         (1 << AC97_SLOT_PCM_RIGHT),
+                       },
+               },
+       },
+       [2] = { /* Mic in */
+               .stream = 1,
+               .exclusive = 1,
+               .r = {
+                       [0] = {
+                               .slots  = (1 << AC97_SLOT_MIC),
+                       },
+               },
+       }
+};
+
+static ac97_bus_ops_t aaci_bus_ops = {
+       .write  = aaci_ac97_write,
+       .read   = aaci_ac97_read,
+};
+
+static int __devinit aaci_probe_ac97(struct aaci *aaci)
+{
+       ac97_template_t ac97_template;
+       ac97_bus_t *ac97_bus;
+       ac97_t *ac97;
+       int ret;
+
+       /*
+        * Assert AACIRESET for 2us
+        */
+       writel(0, aaci->base + AACI_RESET);
+       udelay(2);
+       writel(RESET_NRST, aaci->base + AACI_RESET);
+
+       /*
+        * Give the AC'97 codec more than enough time
+        * to wake up. (42us = ~2 frames at 48kHz.)
+        */
+       udelay(42);
+
+       ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);
+       if (ret)
+               goto out;
+
+       ac97_bus->clock = 48000;
+       aaci->ac97_bus = ac97_bus;
+
+       memset(&ac97_template, 0, sizeof(ac97_template_t));
+       ac97_template.private_data = aaci;
+       ac97_template.num = 0;
+       ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
+
+       ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
+       if (ret)
+               goto out;
+
+       /*
+        * Disable AC97 PC Beep input on audio codecs.
+        */
+       if (ac97_is_audio(ac97))
+               snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
+
+       ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs);
+       if (ret)
+               goto out;
+
+       aaci->playback.pcm = &ac97_bus->pcms[0];
+
+ out:
+       return ret;
+}
+
+static void aaci_free_card(snd_card_t *card)
+{
+       struct aaci *aaci = card->private_data;
+       if (aaci->base)
+               iounmap(aaci->base);
+}
+
+static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
+{
+       struct aaci *aaci;
+       snd_card_t *card;
+
+       card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+                           THIS_MODULE, sizeof(struct aaci));
+       if (card == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       card->private_free = aaci_free_card;
+       snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL);
+
+       strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+       strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
+       snprintf(card->longname, sizeof(card->longname),
+                "%s at 0x%08lx, irq %d",
+                card->shortname, dev->res.start, dev->irq[0]);
+
+       aaci = card->private_data;
+       init_MUTEX(&aaci->ac97_sem);
+       spin_lock_init(&aaci->lock);
+       aaci->card = card;
+       aaci->dev = dev;
+
+       /* Set MAINCR to allow slot 1 and 2 data IO */
+       aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN |
+                      MAINCR_SL2RXEN | MAINCR_SL2TXEN;
+
+       return aaci;
+}
+
+static int __devinit aaci_init_pcm(struct aaci *aaci)
+{
+       snd_pcm_t *pcm;
+       int ret;
+
+       ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
+       if (ret == 0) {
+               aaci->pcm = pcm;
+               pcm->private_data = aaci;
+               pcm->info_flags = 0;
+
+               strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
+
+               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
+       }
+
+       return ret;
+}
+
+static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
+{
+       void *base = aaci->base + AACI_CSCH1;
+       int i;
+
+       writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
+
+       for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
+               writel(0, aaci->base + AACI_DR1);
+
+       writel(0, base + AACI_TXCR);
+
+       /*
+        * Re-initialise the AACI after the FIFO depth test, to
+        * ensure that the FIFOs are empty.  Unfortunately, merely
+        * disabling the channel doesn't clear the FIFO.
+        */
+       writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR);
+       writel(aaci->maincr, aaci->base + AACI_MAINCR);
+
+       /*
+        * If we hit 4096, we failed.  Go back to the specified
+        * fifo depth.
+        */
+       if (i == 4096)
+               i = 8;
+
+       return i;
+}
+
+static int __devinit aaci_probe(struct amba_device *dev, void *id)
+{
+       struct aaci *aaci;
+       int ret, i;
+
+       ret = amba_request_regions(dev, NULL);
+       if (ret)
+               return ret;
+
+       aaci = aaci_init_card(dev);
+       if (IS_ERR(aaci)) {
+               ret = PTR_ERR(aaci);
+               goto out;
+       }
+
+       aaci->base = ioremap(dev->res.start, SZ_4K);
+       if (!aaci->base) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /*
+        * Playback uses AACI channel 0
+        */
+       aaci->playback.base = aaci->base + AACI_CSCH1;
+       aaci->playback.fifo = aaci->base + AACI_DR1;
+
+       for (i = 0; i < 4; i++) {
+               void *base = aaci->base + i * 0x14;
+
+               writel(0, base + AACI_IE);
+               writel(0, base + AACI_TXCR);
+               writel(0, base + AACI_RXCR);
+       }
+
+       writel(0x1fff, aaci->base + AACI_INTCLR);
+       writel(aaci->maincr, aaci->base + AACI_MAINCR);
+
+       /*
+        * Size the FIFOs.
+        */
+       aaci->fifosize = aaci_size_fifo(aaci);
+
+       ret = aaci_probe_ac97(aaci);
+       if (ret)
+               goto out;
+
+       ret = aaci_init_pcm(aaci);
+       if (ret)
+               goto out;
+
+       ret = snd_card_register(aaci->card);
+       if (ret == 0) {
+               dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
+                       aaci->fifosize);
+               amba_set_drvdata(dev, aaci->card);
+               return ret;
+       }
+
+ out:
+       if (aaci)
+               snd_card_free(aaci->card);
+       amba_release_regions(dev);
+       return ret;
+}
+
+static int __devexit aaci_remove(struct amba_device *dev)
+{
+       snd_card_t *card = amba_get_drvdata(dev);
+
+       amba_set_drvdata(dev, NULL);
+
+       if (card) {
+               struct aaci *aaci = card->private_data;
+               writel(0, aaci->base + AACI_MAINCR);
+
+               snd_card_free(card);
+               amba_release_regions(dev);
+       }
+
+       return 0;
+}
+
+static struct amba_id aaci_ids[] = {
+       {
+               .id     = 0x00041041,
+               .mask   = 0x000fffff,
+       },
+       { 0, 0 },
+};
+
+static struct amba_driver aaci_driver = {
+       .drv            = {
+               .name   = DRIVER_NAME,
+       },
+       .probe          = aaci_probe,
+       .remove         = __devexit_p(aaci_remove),
+       .suspend        = aaci_suspend,
+       .resume         = aaci_resume,
+       .id_table       = aaci_ids,
+};
+
+static int __init aaci_init(void)
+{
+       return amba_driver_register(&aaci_driver);
+}
+
+static void __exit aaci_exit(void)
+{
+       amba_driver_unregister(&aaci_driver);
+}
+
+module_init(aaci_init);
+module_exit(aaci_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver");
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
new file mode 100644 (file)
index 0000000..d752e64
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ *  linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef AACI_H
+#define AACI_H
+
+/*
+ * Control and status register offsets
+ *  P39.
+ */
+#define AACI_CSCH1     0x000
+#define AACI_CSCH2     0x014
+#define AACI_CSCH3     0x028
+#define AACI_CSCH4     0x03c
+
+#define AACI_RXCR      0x000   /* 29 bits Control Rx FIFO */
+#define AACI_TXCR      0x004   /* 17 bits Control Tx FIFO */
+#define AACI_SR                0x008   /* 12 bits Status */
+#define AACI_ISR       0x00c   /* 7 bits  Int Status */
+#define AACI_IE        0x010   /* 7 bits  Int Enable */
+
+/*
+ * Other registers
+ */
+#define AACI_SL1RX     0x050
+#define AACI_SL1TX     0x054
+#define AACI_SL2RX     0x058
+#define AACI_SL2TX     0x05c
+#define AACI_SL12RX    0x060
+#define AACI_SL12TX    0x064
+#define AACI_SLFR      0x068   /* slot flags */
+#define AACI_SLISTAT   0x06c   /* slot interrupt status */
+#define AACI_SLIEN     0x070   /* slot interrupt enable */
+#define AACI_INTCLR    0x074   /* interrupt clear */
+#define AACI_MAINCR    0x078   /* main control */
+#define AACI_RESET     0x07c   /* reset control */
+#define AACI_SYNC      0x080   /* sync control */
+#define AACI_ALLINTS   0x084   /* all fifo interrupt status */
+#define AACI_MAINFR    0x088   /* main flag register */
+#define AACI_DR1       0x090   /* data read/written fifo 1 */
+#define AACI_DR2       0x0b0   /* data read/written fifo 2 */
+#define AACI_DR3       0x0d0   /* data read/written fifo 3 */
+#define AACI_DR4       0x0f0   /* data read/written fifo 4 */
+
+/*
+ * transmit fifo control register. P48
+ */
+#define TXCR_FEN       (1 << 16)       /* fifo enable */
+#define TXCR_COMPACT   (1 << 15)       /* compact mode */
+#define TXCR_TSZ16     (0 << 13)       /* 16 bits */
+#define TXCR_TSZ18     (1 << 13)       /* 18 bits */
+#define TXCR_TSZ20     (2 << 13)       /* 20 bits */
+#define TXCR_TSZ12     (3 << 13)       /* 12 bits */
+#define TXCR_TX12      (1 << 12)       /* transmits slot 12 */
+#define TXCR_TX11      (1 << 11)       /* transmits slot 12 */
+#define TXCR_TX10      (1 << 10)       /* transmits slot 12 */
+#define TXCR_TX9       (1 << 9)        /* transmits slot 12 */
+#define TXCR_TX8       (1 << 8)        /* transmits slot 12 */
+#define TXCR_TX7       (1 << 7)        /* transmits slot 12 */
+#define TXCR_TX6       (1 << 6)        /* transmits slot 12 */
+#define TXCR_TX5       (1 << 5)        /* transmits slot 12 */
+#define TXCR_TX4       (1 << 4)        /* transmits slot 12 */
+#define TXCR_TX3       (1 << 3)        /* transmits slot 12 */
+#define TXCR_TX2       (1 << 2)        /* transmits slot 12 */
+#define TXCR_TX1       (1 << 1)        /* transmits slot 12 */
+#define TXCR_TXEN      (1 << 0)        /* transmit enable */
+
+/*
+ * status register bits. P49
+ */
+#define SR_RXTOFE      (1 << 11)       /* rx timeout fifo empty */
+#define SR_TXTO                (1 << 10)       /* rx timeout fifo nonempty */
+#define SR_TXU         (1 << 9)        /* tx underrun */
+#define SR_RXO         (1 << 8)        /* rx overrun */
+#define SR_TXB         (1 << 7)        /* tx busy */
+#define SR_RXB         (1 << 6)        /* rx busy */
+#define SR_TXFF                (1 << 5)        /* tx fifo full */
+#define SR_RXFF                (1 << 4)        /* rx fifo full */
+#define SR_TXHE                (1 << 3)        /* tx fifo half empty */
+#define SR_RXHF                (1 << 2)        /* rx fifo half full */
+#define SR_TXFE                (1 << 1)        /* tx fifo empty */
+#define SR_RXFE                (1 << 0)        /* rx fifo empty */
+
+/*
+ * interrupt status register bits.
+ */
+#define ISR_RXTOFEINTR (1 << 6)        /* rx fifo empty */
+#define ISR_URINTR     (1 << 5)        /* tx underflow */
+#define ISR_ORINTR     (1 << 4)        /* rx overflow */
+#define ISR_RXINTR     (1 << 3)        /* rx fifo */
+#define ISR_TXINTR     (1 << 2)        /* tx fifo intr */
+#define ISR_RXTOINTR   (1 << 1)        /* tx timeout */
+#define ISR_TXCINTR    (1 << 0)        /* tx complete */
+
+/*
+ * interrupt enable register bits.
+ */
+#define IE_RXTOIE      (1 << 6)
+#define IE_URIE                (1 << 5)
+#define IE_ORIE                (1 << 4)
+#define IE_RXIE                (1 << 3)
+#define IE_TXIE                (1 << 2)
+#define IE_RXTIE       (1 << 1)
+#define IE_TXCIE       (1 << 0)
+
+/*
+ * interrupt status. P51
+ */
+#define ISR_RXTOFE     (1 << 6)        /* rx timeout fifo empty */
+#define ISR_UR         (1 << 5)        /* tx fifo underrun */
+#define ISR_OR         (1 << 4)        /* rx fifo overrun */
+#define ISR_RX         (1 << 3)        /* rx interrupt status */
+#define ISR_TX         (1 << 2)        /* tx interrupt status */
+#define ISR_RXTO       (1 << 1)        /* rx timeout */
+#define ISR_TXC                (1 << 0)        /* tx complete */
+
+/*
+ * interrupt enable. P52
+ */
+#define IE_RXTOFE      (1 << 6)        /* rx timeout fifo empty */
+#define IE_UR          (1 << 5)        /* tx fifo underrun */
+#define IE_OR          (1 << 4)        /* rx fifo overrun */
+#define IE_RX          (1 << 3)        /* rx interrupt status */
+#define IE_TX          (1 << 2)        /* tx interrupt status */
+#define IE_RXTO                (1 << 1)        /* rx timeout */
+#define IE_TXC         (1 << 0)        /* tx complete */
+
+/*
+ * slot flag register bits. P56
+ */
+#define SLFR_RWIS      (1 << 13)       /* raw wake-up interrupt status */
+#define SLFR_RGPIOINTR (1 << 12)       /* raw gpio interrupt */
+#define SLFR_12TXE     (1 << 11)       /* slot 12 tx empty */
+#define SLFR_12RXV     (1 << 10)       /* slot 12 rx valid */
+#define SLFR_2TXE      (1 << 9)        /* slot 2 tx empty */
+#define SLFR_2RXV      (1 << 8)        /* slot 2 rx valid */
+#define SLFR_1TXE      (1 << 7)        /* slot 1 tx empty */
+#define SLFR_1RXV      (1 << 6)        /* slot 1 rx valid */
+#define SLFR_12TXB     (1 << 5)        /* slot 12 tx busy */
+#define SLFR_12RXB     (1 << 4)        /* slot 12 rx busy */
+#define SLFR_2TXB      (1 << 3)        /* slot 2 tx busy */
+#define SLFR_2RXB      (1 << 2)        /* slot 2 rx busy */
+#define SLFR_1TXB      (1 << 1)        /* slot 1 tx busy */
+#define SLFR_1RXB      (1 << 0)        /* slot 1 rx busy */
+
+/*
+ * Interrupt clear register.
+ */
+#define ICLR_RXTOFEC4  (1 << 12)
+#define ICLR_RXTOFEC3  (1 << 11)
+#define ICLR_RXTOFEC2  (1 << 10)
+#define ICLR_RXTOFEC1  (1 << 9)
+#define ICLR_TXUEC4    (1 << 8)
+#define ICLR_TXUEC3    (1 << 7)
+#define ICLR_TXUEC2    (1 << 6)
+#define ICLR_TXUEC1    (1 << 5)
+#define ICLR_RXOEC4    (1 << 4)
+#define ICLR_RXOEC3    (1 << 3)
+#define ICLR_RXOEC2    (1 << 2)
+#define ICLR_RXOEC1    (1 << 1)
+#define ICLR_WISC      (1 << 0)
+
+/*
+ * Main control register bits. P62
+ */
+#define MAINCR_SCRA(x) ((x) << 10)     /* secondary codec reg access */
+#define MAINCR_DMAEN   (1 << 9)        /* dma enable */
+#define MAINCR_SL12TXEN        (1 << 8)        /* slot 12 transmit enable */
+#define MAINCR_SL12RXEN        (1 << 7)        /* slot 12 receive enable */
+#define MAINCR_SL2TXEN (1 << 6)        /* slot 2 transmit enable */
+#define MAINCR_SL2RXEN (1 << 5)        /* slot 2 receive enable */
+#define MAINCR_SL1TXEN (1 << 4)        /* slot 1 transmit enable */
+#define MAINCR_SL1RXEN (1 << 3)        /* slot 1 receive enable */
+#define MAINCR_LPM     (1 << 2)        /* low power mode */
+#define MAINCR_LOOPBK  (1 << 1)        /* loopback */
+#define MAINCR_IE      (1 << 0)        /* aaci interface enable */
+
+/*
+ * Reset register bits. P65
+ */
+#define RESET_NRST     (1 << 0)
+
+/*
+ * Sync register bits. P65
+ */
+#define SYNC_FORCE     (1 << 0)
+
+/*
+ * Main flag register bits. P66
+ */
+#define MAINFR_TXB     (1 << 1)        /* transmit busy */
+#define MAINFR_RXB     (1 << 0)        /* receive busy */
+
+
+
+struct aaci_runtime {
+       void                    *base;
+       void                    *fifo;
+
+       struct ac97_pcm         *pcm;
+       int                     pcm_open;
+
+       u32                     cr;
+       snd_pcm_substream_t     *substream;
+
+       /*
+        * PIO support
+        */
+       void                    *start;
+       void                    *end;
+       void                    *ptr;
+       int                     bytes;
+       unsigned int            period;
+       unsigned int            fifosz;
+};
+
+struct aaci {
+       struct amba_device      *dev;
+       snd_card_t              *card;
+       void                    *base;
+       unsigned int            fifosize;
+
+       /* AC'97 */
+       struct semaphore        ac97_sem;
+       ac97_bus_t              *ac97_bus;
+
+       u32                     maincr;
+       spinlock_t              lock;
+
+       struct aaci_runtime     playback;
+       struct aaci_runtime     capture;
+
+       snd_pcm_t               *pcm;
+};
+
+#define ACSTREAM_FRONT         0
+#define ACSTREAM_SURROUND      1
+#define ACSTREAM_LFE           2
+
+#endif
diff --git a/sound/arm/devdma.c b/sound/arm/devdma.c
new file mode 100644 (file)
index 0000000..60826a5
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  linux/sound/arm/devdma.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  ARM DMA shim for ALSA.
+ */
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "devdma.h"
+
+void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+
+       if (runtime->dma_area == NULL)
+               return;
+
+       if (buf != &substream->dma_buffer) {
+               dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr);
+               kfree(runtime->dma_buffer_p);
+       }
+
+       snd_pcm_set_runtime_buffer(substream, NULL);
+}
+
+int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+       int ret = 0;
+
+       if (buf) {
+               if (buf->bytes >= size)
+                       goto out;
+               devdma_hw_free(dev, substream);
+       }
+
+       if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
+               buf = &substream->dma_buffer;
+       } else {
+               buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
+               if (!buf)
+                       goto nomem;
+
+               buf->dev.type = SNDRV_DMA_TYPE_DEV;
+               buf->dev.dev = dev;
+               buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL);
+               buf->bytes = size;
+               buf->private_data = NULL;
+
+               if (!buf->area)
+                       goto free;
+       }
+       snd_pcm_set_runtime_buffer(substream, buf);
+       ret = 1;
+ out:
+       runtime->dma_bytes = size;
+       return ret;
+
+ free:
+       kfree(buf);
+ nomem:
+       return -ENOMEM;
+}
+
+int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+}
diff --git a/sound/arm/devdma.h b/sound/arm/devdma.h
new file mode 100644 (file)
index 0000000..5a33b6b
--- /dev/null
@@ -0,0 +1,3 @@
+void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream);
+int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size);
+int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma);
index f4ea6bff1dd3b133ddf528f1cc272c1f647c3070..227f3cf02771605d11e8ddd32c565bc902d75d7d 100644 (file)
@@ -215,7 +215,7 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
  *
  * Returns the pointer of the newly generated instance, or NULL on failure.
  */
-snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * ncontrol, void *private_data)
+snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_data)
 {
        snd_kcontrol_t kctl;
        unsigned int access;
@@ -1102,7 +1102,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                }
        }
        up_read(&snd_ioctl_rwsem);
-       snd_printd("unknown ioctl = 0x%x\n", cmd);
+       snd_printdd("unknown ioctl = 0x%x\n", cmd);
        return -ENOTTY;
 }
 
index 344a83fd7c2e6b884cc318cad9518dfa733def8e..dbc23e35fa065decbbeb4910f39d0153073f0c36 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <asm/uaccess.h>
 #include <linux/dma-mapping.h>
 #include <linux/moduleparam.h>
 #include <asm/semaphore.h>
@@ -46,13 +47,6 @@ MODULE_LICENSE("GPL");
 #define SNDRV_CARDS    8
 #endif
 
-/* FIXME: so far only some PCI devices have the preallocation table */
-#ifdef CONFIG_PCI
-static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
-#endif
-
 /*
  */
 
@@ -451,9 +445,13 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
        list_for_each(p, &mem_list_head) {
                mem = list_entry(p, struct snd_mem_list, list);
                if (mem->id == id &&
-                   ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) {
+                   (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
+                    ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
+                       struct device *dev = dmab->dev.dev;
                        list_del(p);
                        *dmab = mem->buffer;
+                       if (dmab->dev.dev == NULL)
+                               dmab->dev.dev = dev;
                        kfree(mem);
                        up(&list_mutex);
                        return dmab->bytes;
@@ -508,91 +506,13 @@ static void free_all_reserved_pages(void)
 }
 
 
-
-/*
- * allocation of buffers for pre-defined devices
- */
-
-#ifdef CONFIG_PCI
-/* FIXME: for pci only - other bus? */
-struct prealloc_dev {
-       unsigned short vendor;
-       unsigned short device;
-       unsigned long dma_mask;
-       unsigned int size;
-       unsigned int buffers;
-};
-
-#define HAMMERFALL_BUFFER_SIZE    (16*1024*4*(26+1)+0x10000)
-
-static struct prealloc_dev prealloc_devices[] __initdata = {
-       {
-               /* hammerfall */
-               .vendor = 0x10ee,
-               .device = 0x3fc4,
-               .dma_mask = 0xffffffff,
-               .size = HAMMERFALL_BUFFER_SIZE,
-               .buffers = 2
-       },
-       {
-               /* HDSP */
-               .vendor = 0x10ee,
-               .device = 0x3fc5,
-               .dma_mask = 0xffffffff,
-               .size = HAMMERFALL_BUFFER_SIZE,
-               .buffers = 2
-       },
-       { }, /* terminator */
-};
-
-static void __init preallocate_cards(void)
-{
-       struct pci_dev *pci = NULL;
-       int card;
-
-       card = 0;
-
-       while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) {
-               struct prealloc_dev *dev;
-               unsigned int i;
-               if (card >= SNDRV_CARDS)
-                       break;
-               for (dev = prealloc_devices; dev->vendor; dev++) {
-                       if (dev->vendor == pci->vendor && dev->device == pci->device)
-                               break;
-               }
-               if (! dev->vendor)
-                       continue;
-               if (! enable[card++]) {
-                       printk(KERN_DEBUG "snd-page-alloc: skipping card %d, device %04x:%04x\n", card, pci->vendor, pci->device);
-                       continue;
-               }
-                       
-               if (pci_set_dma_mask(pci, dev->dma_mask) < 0 ||
-                   pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) {
-                       printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device);
-                       continue;
-               }
-               for (i = 0; i < dev->buffers; i++) {
-                       struct snd_dma_buffer dmab;
-                       memset(&dmab, 0, sizeof(dmab));
-                       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-                                               dev->size, &dmab) < 0)
-                               printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
-                       else
-                               snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
-               }
-       }
-}
-#else
-#define preallocate_cards()    /* NOP */
-#endif
-
-
 #ifdef CONFIG_PROC_FS
 /*
  * proc file interface
  */
+#define SND_MEM_PROC_FILE      "driver/snd-page-alloc"
+struct proc_dir_entry *snd_mem_proc;
+
 static int snd_mem_proc_read(char *page, char **start, off_t off,
                             int count, int *eof, void *data)
 {
@@ -621,6 +541,97 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
        up(&list_mutex);
        return len;
 }
+
+/* FIXME: for pci only - other bus? */
+#ifdef CONFIG_PCI
+#define gettoken(bufp) strsep(bufp, " \t\n")
+
+static int snd_mem_proc_write(struct file *file, const char __user *buffer,
+                             unsigned long count, void *data)
+{
+       char buf[128];
+       char *token, *p;
+
+       if (count > ARRAY_SIZE(buf) - 1)
+               count = ARRAY_SIZE(buf) - 1;
+       if (copy_from_user(buf, buffer, count))
+               return -EFAULT;
+       buf[ARRAY_SIZE(buf) - 1] = '\0';
+
+       p = buf;
+       token = gettoken(&p);
+       if (! token || *token == '#')
+               return (int)count;
+       if (strcmp(token, "add") == 0) {
+               char *endp;
+               int vendor, device, size, buffers;
+               long mask;
+               int i, alloced;
+               struct pci_dev *pci;
+
+               if ((token = gettoken(&p)) == NULL ||
+                   (vendor = simple_strtol(token, NULL, 0)) <= 0 ||
+                   (token = gettoken(&p)) == NULL ||
+                   (device = simple_strtol(token, NULL, 0)) <= 0 ||
+                   (token = gettoken(&p)) == NULL ||
+                   (mask = simple_strtol(token, NULL, 0)) < 0 ||
+                   (token = gettoken(&p)) == NULL ||
+                   (size = memparse(token, &endp)) < 64*1024 ||
+                   size > 16*1024*1024 /* too big */ ||
+                   (token = gettoken(&p)) == NULL ||
+                   (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
+                   buffers > 4) {
+                       printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
+                       return (int)count;
+               }
+               vendor &= 0xffff;
+               device &= 0xffff;
+
+               alloced = 0;
+               pci = NULL;
+               while ((pci = pci_find_device(vendor, device, pci)) != NULL) {
+                       if (mask > 0 && mask < 0xffffffff) {
+                               if (pci_set_dma_mask(pci, mask) < 0 ||
+                                   pci_set_consistent_dma_mask(pci, mask) < 0) {
+                                       printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
+                                       return (int)count;
+                               }
+                       }
+                       for (i = 0; i < buffers; i++) {
+                               struct snd_dma_buffer dmab;
+                               memset(&dmab, 0, sizeof(dmab));
+                               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+                                                       size, &dmab) < 0) {
+                                       printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+                                       return (int)count;
+                               }
+                               snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
+                       }
+                       alloced++;
+               }
+               if (! alloced) {
+                       for (i = 0; i < buffers; i++) {
+                               struct snd_dma_buffer dmab;
+                               memset(&dmab, 0, sizeof(dmab));
+                               /* FIXME: We can allocate only in ZONE_DMA
+                                * without a device pointer!
+                                */
+                               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
+                                                       size, &dmab) < 0) {
+                                       printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+                                       break;
+                               }
+                               snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
+                       }
+               }
+       } else if (strcmp(token, "erase") == 0)
+               /* FIXME: need for releasing each buffer chunk? */
+               free_all_reserved_pages();
+       else
+               printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
+       return (int)count;
+}
+#endif /* CONFIG_PCI */
 #endif /* CONFIG_PROC_FS */
 
 /*
@@ -630,15 +641,21 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
 static int __init snd_mem_init(void)
 {
 #ifdef CONFIG_PROC_FS
-       create_proc_read_entry("driver/snd-page-alloc", 0, NULL, snd_mem_proc_read, NULL);
+       snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
+       if (snd_mem_proc) {
+               snd_mem_proc->read_proc = snd_mem_proc_read;
+#ifdef CONFIG_PCI
+               snd_mem_proc->write_proc = snd_mem_proc_write;
+#endif
+       }
 #endif
-       preallocate_cards();
        return 0;
 }
 
 static void __exit snd_mem_exit(void)
 {
-       remove_proc_entry("driver/snd-page-alloc", NULL);
+       if (snd_mem_proc)
+               remove_proc_entry(SND_MEM_PROC_FILE, NULL);
        free_all_reserved_pages();
        if (snd_allocated_pages > 0)
                printk(KERN_ERR "snd-malloc: Memory leak?  pages not freed = %li\n", snd_allocated_pages);
index 1a805020f57a5f3f93293a925ae613a13510f8a9..cab30977e7c0887603abacd05218894857176463 100644 (file)
@@ -125,17 +125,26 @@ int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin)
 static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
-       frames = frames_to_bytes(runtime, frames);
+       long buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       long bytes = frames_to_bytes(runtime, frames);
        if (buffer_size == runtime->oss.buffer_bytes)
-               return frames;
-       return (runtime->oss.buffer_bytes * frames) / buffer_size;
+               return bytes;
+#if BITS_PER_LONG >= 64
+       return runtime->oss.buffer_bytes * bytes / buffer_size;
+#else
+       {
+               u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes;
+               u32 rem;
+               div64_32(&bsize, buffer_size, &rem);
+               return (long)bsize;
+       }
+#endif
 }
 
 static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       long buffer_size = snd_pcm_lib_buffer_bytes(substream);
        if (buffer_size == runtime->oss.buffer_bytes)
                return bytes_to_frames(runtime, bytes);
        return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
@@ -464,7 +473,8 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
        sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
        sw_params->period_step = 1;
        sw_params->sleep_min = 0;
-       sw_params->avail_min = 1;
+       sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+               1 : runtime->period_size;
        sw_params->xfer_align = 1;
        if (atomic_read(&runtime->mmap_count) ||
            (substream->oss.setup && substream->oss.setup->nosilence)) {
@@ -1527,12 +1537,15 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str
                        snd_pcm_oss_simulate_fill(substream, delay);
                info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
        } else {
-               delay = snd_pcm_oss_bytes(substream, delay) + fixup;
-               info.blocks = delay / runtime->oss.period_bytes;
-               if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+               delay = snd_pcm_oss_bytes(substream, delay);
+               if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
                        info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
-               else
+               } else {
+                       delay += fixup;
+                       info.blocks = delay / runtime->oss.period_bytes;
                        info.bytes = (runtime->oss.bytes + delay) & INT_MAX;
+               }
        }
        if (copy_to_user(_info, &info, sizeof(info)))
                return -EFAULT;
index 6bb31009f0b4996949981c129b0cc94b29b1b7ce..6430410c6c04703af940b04f377b15fdb304572a 100644 (file)
@@ -663,10 +663,7 @@ static int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug,
                bitset_t *dstmask = bs;
                int err;
                bitset_one(dstmask, schannels);
-               if (plugin == NULL) {
-                       bitset_and(client_vmask, dstmask, schannels);
-                       return 0;
-               }
+
                while (1) {
                        err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
                        if (err < 0)
index 8d94325529a87258bcdade5152f55fdb8f37b53f..9f4c9209b2717a0ff23b938402e9fb5132efeaeb 100644 (file)
@@ -451,6 +451,7 @@ static int snd_pcm_stream_proc_init(snd_pcm_str_t *pstr)
                entry->c.text.read = snd_pcm_xrun_debug_read;
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_pcm_xrun_debug_write;
+               entry->mode |= S_IWUSR;
                entry->private_data = pstr;
                if (snd_info_register(entry) < 0) {
                        snd_info_free_entry(entry);
@@ -1048,7 +1049,6 @@ EXPORT_SYMBOL(snd_pcm_release_substream);
 EXPORT_SYMBOL(snd_pcm_format_name);
   /* pcm_native.c */
 EXPORT_SYMBOL(snd_pcm_link_rwlock);
-EXPORT_SYMBOL(snd_pcm_start);
 #ifdef CONFIG_PM
 EXPORT_SYMBOL(snd_pcm_suspend);
 EXPORT_SYMBOL(snd_pcm_suspend_all);
@@ -1068,6 +1068,7 @@ EXPORT_SYMBOL(snd_pcm_format_little_endian);
 EXPORT_SYMBOL(snd_pcm_format_big_endian);
 EXPORT_SYMBOL(snd_pcm_format_width);
 EXPORT_SYMBOL(snd_pcm_format_physical_width);
+EXPORT_SYMBOL(snd_pcm_format_size);
 EXPORT_SYMBOL(snd_pcm_format_silence_64);
 EXPORT_SYMBOL(snd_pcm_format_set_silence);
 EXPORT_SYMBOL(snd_pcm_build_linear_format);
index 151fd99ca2c9b27b7a5a75e6892c5391bb042cd2..c5bfd0918cff9eba195d733355435580f27f8882 100644 (file)
@@ -1143,7 +1143,8 @@ int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
 #define INT_MIN ((int)((unsigned int)INT_MAX+1))
 #endif
 
-void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
+static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
+                                 snd_pcm_hw_param_t var)
 {
        if (hw_is_mask(var)) {
                snd_mask_any(hw_param_mask(params, var));
@@ -1160,6 +1161,7 @@ void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
        snd_BUG();
 }
 
+#if 0
 /**
  * snd_pcm_hw_param_any
  */
@@ -1169,6 +1171,7 @@ int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
        _snd_pcm_hw_param_any(params, var);
        return snd_pcm_hw_refine(pcm, params);
 }
+#endif  /*  0  */
 
 void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
 {
@@ -1181,6 +1184,7 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
        params->info = ~0U;
 }
 
+#if 0
 /**
  * snd_pcm_hw_params_any
  *
@@ -1191,6 +1195,7 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
        _snd_pcm_hw_params_any(params);
        return snd_pcm_hw_refine(pcm, params);
 }
+#endif  /*  0  */
 
 /**
  * snd_pcm_hw_param_value
@@ -1198,8 +1203,8 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
  * Return the value for field PAR if it's fixed in configuration space 
  *  defined by PARAMS. Return -EINVAL otherwise
  */
-int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
-                          snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
+                                 snd_pcm_hw_param_t var, int *dir)
 {
        if (hw_is_mask(var)) {
                const snd_mask_t *mask = hw_param_mask_c(params, var);
@@ -1296,6 +1301,7 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
        return changed;
 }
        
+#if 0
 /**
  * snd_pcm_hw_param_setinteger
  *
@@ -1317,9 +1323,10 @@ int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm,
        }
        return 0;
 }
+#endif  /*  0  */
 
-int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
-                           snd_pcm_hw_param_t var)
+static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
+                                  snd_pcm_hw_param_t var)
 {
        int changed;
        if (hw_is_mask(var))
@@ -1345,9 +1352,9 @@ int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
  * values > minimum. Reduce configuration space accordingly.
  * Return the minimum.
  */
-int snd_pcm_hw_param_first(snd_pcm_t *pcm, 
-                          snd_pcm_hw_params_t *params, 
-                          snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_first(snd_pcm_t *pcm, 
+                                 snd_pcm_hw_params_t *params, 
+                                 snd_pcm_hw_param_t var, int *dir)
 {
        int changed = _snd_pcm_hw_param_first(params, var);
        if (changed < 0)
@@ -1359,8 +1366,8 @@ int snd_pcm_hw_param_first(snd_pcm_t *pcm,
        return snd_pcm_hw_param_value(params, var, dir);
 }
 
-int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
-                          snd_pcm_hw_param_t var)
+static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
+                                 snd_pcm_hw_param_t var)
 {
        int changed;
        if (hw_is_mask(var))
@@ -1386,9 +1393,9 @@ int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
  * values < maximum. Reduce configuration space accordingly.
  * Return the maximum.
  */
-int snd_pcm_hw_param_last(snd_pcm_t *pcm, 
-                         snd_pcm_hw_params_t *params,
-                         snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_last(snd_pcm_t *pcm, 
+                                snd_pcm_hw_params_t *params,
+                                snd_pcm_hw_param_t var, int *dir)
 {
        int changed = _snd_pcm_hw_param_last(params, var);
        if (changed < 0)
@@ -1437,8 +1444,9 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
  * values < VAL. Reduce configuration space accordingly.
  * Return new minimum or -EINVAL if the configuration space is empty
  */
-int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
-                        snd_pcm_hw_param_t var, unsigned int val, int *dir)
+static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                               snd_pcm_hw_param_t var, unsigned int val,
+                               int *dir)
 {
        int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
        if (changed < 0)
@@ -1451,8 +1459,9 @@ int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
        return snd_pcm_hw_param_value_min(params, var, dir);
 }
 
-int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
-                          snd_pcm_hw_param_t var, unsigned int val, int dir)
+static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
+                                snd_pcm_hw_param_t var, unsigned int val,
+                                int dir)
 {
        int changed;
        int open = 0;
@@ -1490,8 +1499,9 @@ int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
  *  values >= VAL + 1. Reduce configuration space accordingly.
  *  Return new maximum or -EINVAL if the configuration space is empty
  */
-int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
-                         snd_pcm_hw_param_t var, unsigned int val, int *dir)
+static int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                               snd_pcm_hw_param_t var, unsigned int val,
+                               int *dir)
 {
        int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
        if (changed < 0)
@@ -2564,9 +2574,6 @@ snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream,
 EXPORT_SYMBOL(snd_interval_refine);
 EXPORT_SYMBOL(snd_interval_list);
 EXPORT_SYMBOL(snd_interval_ratnum);
-EXPORT_SYMBOL(snd_interval_muldivk);
-EXPORT_SYMBOL(snd_interval_mulkdiv);
-EXPORT_SYMBOL(snd_interval_div);
 EXPORT_SYMBOL(_snd_pcm_hw_params_any);
 EXPORT_SYMBOL(_snd_pcm_hw_param_min);
 EXPORT_SYMBOL(_snd_pcm_hw_param_set);
@@ -2580,7 +2587,6 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last);
 EXPORT_SYMBOL(snd_pcm_hw_param_near);
 EXPORT_SYMBOL(snd_pcm_hw_param_set);
 EXPORT_SYMBOL(snd_pcm_hw_refine);
-EXPORT_SYMBOL(snd_pcm_hw_params);
 EXPORT_SYMBOL(snd_pcm_hw_constraints_init);
 EXPORT_SYMBOL(snd_pcm_hw_constraints_complete);
 EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
index f1d5f7a6ee0c69b4e6131af5c10060a7d68e8590..9a174fb96565368abe767344de9bffca32887e09 100644 (file)
@@ -204,6 +204,7 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
                entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
+               entry->mode |= S_IWUSR;
                entry->private_data = substream;
                if (snd_info_register(entry) < 0) {
                        snd_info_free_entry(entry);
index 422b8db141547fe07b1c69b817ad7de79a651a3b..1453743e4da0ed1f1eb9169bbb7651af63aaf7e0 100644 (file)
@@ -269,22 +269,6 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format)
        return !val;
 }
 
-/**
- * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is CPU-endian, 0 if
- * opposite, or a negative error code if endian not specified.
- */
-int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
-{
-#ifdef SNDRV_LITTLE_ENDIAN
-       return snd_pcm_format_little_endian(format);
-#else
-       return snd_pcm_format_big_endian(format);
-#endif
-}
-
 /**
  * snd_pcm_format_width - return the bit-width of the format
  * @format: the format to check
index cad9bbde99868049c14a1e8c7365d331308bb32c..10c2c98326497e6f0cb5fc0c453c1701daf5f8c4 100644 (file)
@@ -337,8 +337,8 @@ out:
        return err;
 }
 
-int snd_pcm_hw_params(snd_pcm_substream_t *substream,
-                     snd_pcm_hw_params_t *params)
+static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
+                            snd_pcm_hw_params_t *params)
 {
        snd_pcm_runtime_t *runtime;
        int err;
@@ -1368,43 +1368,32 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
                return -EBADFD;
 
-       down_read(&snd_pcm_link_rwsem);
        snd_power_lock(card);
        if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
                result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
-               if (result < 0)
-                       goto _unlock;
+               if (result < 0) {
+                       snd_power_unlock(card);
+                       return result;
+               }
        }
 
        /* allocate temporary record for drain sync */
+       down_read(&snd_pcm_link_rwsem);
        if (snd_pcm_stream_linked(substream)) {
                drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL);
                if (! drec) {
-                       result = -ENOMEM;
-                       goto _unlock;
+                       up_read(&snd_pcm_link_rwsem);
+                       snd_power_unlock(card);
+                       return -ENOMEM;
                }
        } else
                drec = &drec_tmp;
 
-       snd_pcm_stream_lock_irq(substream);
-       /* resume pause */
-       if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
-               snd_pcm_pause(substream, 0);
-
-       /* pre-start/stop - all running streams are changed to DRAINING state */
-       result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
-       if (result < 0)
-               goto _end;
-
-       /* check streams with PLAYBACK & DRAINING */
+       /* count only playback streams */
        num_drecs = 0;
        snd_pcm_group_for_each(pos, substream) {
                snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos);
                runtime = s->runtime;
-               if (runtime->status->state != SNDRV_PCM_STATE_DRAINING) {
-                       runtime->status->state = SNDRV_PCM_STATE_SETUP;
-                       continue;
-               }
                if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        d = &drec[num_drecs++];
                        d->substream = s;
@@ -1418,9 +1407,21 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
                                runtime->stop_threshold = runtime->buffer_size;
                }
        }
-
+       up_read(&snd_pcm_link_rwsem);
        if (! num_drecs)
-               goto _end;
+               goto _error;
+
+       snd_pcm_stream_lock_irq(substream);
+       /* resume pause */
+       if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
+               snd_pcm_pause(substream, 0);
+
+       /* pre-start/stop - all running streams are changed to DRAINING state */
+       result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
+       if (result < 0) {
+               snd_pcm_stream_unlock_irq(substream);
+               goto _error;
+       }
 
        for (;;) {
                long tout;
@@ -1428,6 +1429,15 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
                        result = -ERESTARTSYS;
                        break;
                }
+               /* all finished? */
+               for (i = 0; i < num_drecs; i++) {
+                       runtime = drec[i].substream->runtime;
+                       if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+                               break;
+               }
+               if (i == num_drecs)
+                       break; /* yes, all drained */
+
                set_current_state(TASK_INTERRUPTIBLE);
                snd_pcm_stream_unlock_irq(substream);
                snd_power_unlock(card);
@@ -1444,15 +1454,11 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
                        }
                        break;
                }
-               /* all finished? */
-               for (i = 0; i < num_drecs; i++) {
-                       runtime = drec[i].substream->runtime;
-                       if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
-                               break;
-               }
-               if (i == num_drecs)
-                       break;
        }
+
+       snd_pcm_stream_unlock_irq(substream);
+
+ _error:
        for (i = 0; i < num_drecs; i++) {
                d = &drec[i];
                runtime = d->substream->runtime;
@@ -1460,13 +1466,9 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
                runtime->stop_threshold = d->stop_threshold;
        }
 
- _end:
-       snd_pcm_stream_unlock_irq(substream);
        if (drec != &drec_tmp)
                kfree(drec);
- _unlock:
        snd_power_unlock(card);
-       up_read(&snd_pcm_link_rwsem);
 
        return result;
 }
index 638cc148706dcf4099fd1e3c4125c21b2f79c54c..1a7736cbf3a4717202159087fb4355071c5c7c4e 100644 (file)
@@ -325,14 +325,10 @@ snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp)
                        }
                        snd_use_lock_free(&rec->use_lock);
                }
-               if (info->sysex) {
-                       kfree(info->sysex);
-                       info->sysex = NULL;
-               }
-               if (info->ch) {
-                       kfree(info->ch);
-                       info->ch = NULL;
-               }
+               kfree(info->sysex);
+               info->sysex = NULL;
+               kfree(info->ch);
+               info->ch = NULL;
        }
        dp->synth_opened = 0;
        dp->max_synthdev = 0;
@@ -418,14 +414,10 @@ snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev)
                                          dp->file_mode) < 0) {
                        midi_synth_dev.opened--;
                        info->opened = 0;
-                       if (info->sysex) {
-                               kfree(info->sysex);
-                               info->sysex = NULL;
-                       }
-                       if (info->ch) {
-                               kfree(info->ch);
-                               info->ch = NULL;
-                       }
+                       kfree(info->sysex);
+                       info->sysex = NULL;
+                       kfree(info->ch);
+                       info->ch = NULL;
                }
                return;
        }
index e88967c5b93d1fe6c53428551535840f7043823b..ea945a5d2a0b194f4884cdbac0aeae4c00f3ced2 100644 (file)
@@ -140,10 +140,7 @@ dummy_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int
 static void
 dummy_free(void *private_data)
 {
-       snd_seq_dummy_port_t *p;
-
-       p = private_data;
-       kfree(p);
+       kfree(private_data);
 }
 
 /*
index 18247db45db65d501040eacb4dcf74c2a6b76e6e..57be9155eb622854f97c4f85cacc1c3a259fb566 100644 (file)
@@ -414,6 +414,8 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
        if (newclient)
                synths[card->number] = client;
        up(&register_mutex);
+       kfree(info);
+       kfree(port);
        return 0;       /* success */
 
       __nomem:
index 21e569062bc384e55f98b2403c9b20e61348b4cc..df1e2bb397458f1cea7d5388f250f95ff760b0b2 100644 (file)
@@ -171,11 +171,13 @@ void snd_midi_event_reset_decode(snd_midi_event_t *dev)
        spin_unlock_irqrestore(&dev->lock, flags);
 }
 
+#if 0
 void snd_midi_event_init(snd_midi_event_t *dev)
 {
        snd_midi_event_reset_encode(dev);
        snd_midi_event_reset_decode(dev);
 }
+#endif  /*  0  */
 
 void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
 {
@@ -185,6 +187,7 @@ void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
 /*
  * resize buffer
  */
+#if 0
 int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
 {
        unsigned char *new_buf, *old_buf;
@@ -204,6 +207,7 @@ int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
        kfree(old_buf);
        return 0;
 }
+#endif  /*  0  */
 
 /*
  *  read bytes and encode to sequencer event if finished
@@ -517,8 +521,6 @@ static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int coun
  
 EXPORT_SYMBOL(snd_midi_event_new);
 EXPORT_SYMBOL(snd_midi_event_free);
-EXPORT_SYMBOL(snd_midi_event_resize_buffer);
-EXPORT_SYMBOL(snd_midi_event_init);
 EXPORT_SYMBOL(snd_midi_event_reset_encode);
 EXPORT_SYMBOL(snd_midi_event_reset_decode);
 EXPORT_SYMBOL(snd_midi_event_no_status);
index 3afc7cc0c9a79d65c20de27788c2a701be5b1623..98de2e711fde90b174d6cc87ffde3b00861073d1 100644 (file)
@@ -672,7 +672,8 @@ static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, i
  * process a received queue-control event.
  * this function is exported for seq_sync.c.
  */
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
+static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev,
+                                       int atomic, int hop)
 {
        switch (ev->type) {
        case SNDRV_SEQ_EVENT_START:
index b1bf5519fb3b0ac119a06e953644e47445b2d103..ea3c54216ea83214bc64361df62b296e276cd669 100644 (file)
@@ -111,7 +111,6 @@ int snd_seq_queue_use(int queueid, int client, int use);
 int snd_seq_queue_is_used(int queueid, int client);
 
 int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop);
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop);
 
 /*
  * 64bit division - for sync stuff..
index 753f1c0863ccf29cc24e67e679997f9437674885..a7f76fc9528092bc38985337409f97dd81451270 100644 (file)
@@ -36,7 +36,8 @@ extern int seq_default_timer_resolution;
 
 #define SKEW_BASE      0x10000 /* 16bit shift */
 
-void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks)
+static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick,
+                                             int tempo, int ppq, int nticks)
 {
        if (tempo < 1000000)
                tick->resolution = (tempo * 1000) / ppq;
index 4c0872df8931d996173c8603d3706da6abbd68ac..287ed68591dee872f11eeb7cf421a45793f02564 100644 (file)
@@ -64,8 +64,6 @@ extern seq_timer_t *snd_seq_timer_new(void);
 /* delete timer (destructor) */
 extern void snd_seq_timer_delete(seq_timer_t **tmr);
 
-void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks);
-
 /* */
 static inline void snd_seq_timer_update_tick(seq_timer_tick_t *tick, unsigned long resolution)
 {
index 6b4e630ace54108c6ce2d2bb4f012b4896845fb7..a66484b5cf0e921991895296021ae56aad2c34dc 100644 (file)
@@ -110,7 +110,7 @@ static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_
  * handler of a remote port which is attached to the virmidi via
  * SNDRV_VIRMIDI_SEQ_ATTACH.
  */
-/* exported */
+#if 0
 int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
 {
        snd_virmidi_dev_t *rdev;
@@ -118,6 +118,7 @@ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
        rdev = rmidi->private_data;
        return snd_virmidi_dev_receive_event(rdev, ev);
 }
+#endif  /*  0  */
 
 /*
  * event handler of virmidi port
@@ -384,7 +385,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
        info->client = client;
        info->type = KERNEL_CLIENT;
        sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device);
-       snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info);
+       snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info);
 
        /* create a port */
        memset(pinfo, 0, sizeof(*pinfo));
@@ -405,7 +406,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
        pcallbacks.unuse = snd_virmidi_unuse;
        pcallbacks.event_input = snd_virmidi_event_input;
        pinfo->kernel = &pcallbacks;
-       err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo);
+       err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo);
        if (err < 0) {
                snd_seq_delete_kernel_client(client);
                rdev->client = -1;
@@ -548,4 +549,3 @@ module_init(alsa_virmidi_init)
 module_exit(alsa_virmidi_exit)
 
 EXPORT_SYMBOL(snd_virmidi_new);
-EXPORT_SYMBOL(snd_virmidi_receive);
index 33eaa5e5d284d6b366a2d8f0a42b95b59b0c697d..0815fadeb3ec7915e6b0c31add6cece70073c9dd 100644 (file)
@@ -431,7 +431,6 @@ EXPORT_SYMBOL(snd_card_pci_resume);
 EXPORT_SYMBOL(snd_device_new);
 EXPORT_SYMBOL(snd_device_register);
 EXPORT_SYMBOL(snd_device_free);
-EXPORT_SYMBOL(snd_device_free_all);
   /* isadma.c */
 #ifdef CONFIG_ISA
 EXPORT_SYMBOL(snd_dma_program);
index fa762ca439be43573f9bd2bfaac8d361be4fea82..b498e5482d77d8d40ce20eb1ed08c3e856e49708 100644 (file)
@@ -69,6 +69,7 @@ typedef struct {
        struct timespec tstamp;         /* trigger tstamp */
        wait_queue_head_t qchange_sleep;
        struct fasync_struct *fasync;
+       struct semaphore tread_sem;
 } snd_timer_user_t;
 
 /* list of timers */
@@ -844,7 +845,7 @@ int snd_timer_dev_register(snd_device_t *dev)
        return 0;
 }
 
-int snd_timer_unregister(snd_timer_t *timer)
+static int snd_timer_unregister(snd_timer_t *timer)
 {
        struct list_head *p, *n;
        snd_timer_instance_t *ti;
@@ -945,11 +946,6 @@ struct snd_timer_system_private {
        unsigned long correction;
 };
 
-unsigned int snd_timer_system_resolution(void)
-{
-       return 1000000000L / HZ;
-}
-
 static void snd_timer_s_function(unsigned long data)
 {
        snd_timer_t *timer = (snd_timer_t *)data;
@@ -1208,6 +1204,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
                return -ENOMEM;
        spin_lock_init(&tu->qlock);
        init_waitqueue_head(&tu->qchange_sleep);
+       init_MUTEX(&tu->tread_sem);
        tu->ticks = 1;
        tu->queue_size = 128;
        tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
@@ -1454,46 +1451,51 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *
        snd_timer_user_t *tu;
        snd_timer_select_t tselect;
        char str[32];
-       int err;
+       int err = 0;
        
        tu = file->private_data;
-       if (tu->timeri)
+       down(&tu->tread_sem);
+       if (tu->timeri) {
                snd_timer_close(tu->timeri);
-       if (copy_from_user(&tselect, _tselect, sizeof(tselect)))
-               return -EFAULT;
+               tu->timeri = NULL;
+       }
+       if (copy_from_user(&tselect, _tselect, sizeof(tselect))) {
+               err = -EFAULT;
+               goto __err;
+       }
        sprintf(str, "application %i", current->pid);
        if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
                tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
        if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0)
-               return err;
+               goto __err;
 
-       if (tu->queue) {
-               kfree(tu->queue);
-               tu->queue = NULL;
-       }
-       if (tu->tqueue) {
-               kfree(tu->tqueue);
-               tu->tqueue = NULL;
-       }
+       kfree(tu->queue);
+       tu->queue = NULL;
+       kfree(tu->tqueue);
+       tu->tqueue = NULL;
        if (tu->tread) {
                tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL);
-               if (tu->tqueue == NULL) {
-                       snd_timer_close(tu->timeri);
-                       return -ENOMEM;
-               }
+               if (tu->tqueue == NULL)
+                       err = -ENOMEM;
        } else {
                tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
-               if (tu->queue == NULL) {
-                       snd_timer_close(tu->timeri);
-                       return -ENOMEM;
-               }
+               if (tu->queue == NULL)
+                       err = -ENOMEM;
        }
        
-       tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
-       tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
-       tu->timeri->ccallback = snd_timer_user_ccallback;
-       tu->timeri->callback_data = (void *)tu;
-       return 0;
+       if (err < 0) {
+               snd_timer_close(tu->timeri);
+               tu->timeri = NULL;
+       } else {
+               tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
+               tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
+               tu->timeri->ccallback = snd_timer_user_ccallback;
+               tu->timeri->callback_data = (void *)tu;
+       }
+
+      __err:
+       up(&tu->tread_sem);
+       return err;
 }
 
 static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info)
@@ -1669,6 +1671,23 @@ static int snd_timer_user_continue(struct file *file)
        return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
 }
 
+static int snd_timer_user_pause(struct file *file)
+{
+       int err;
+       snd_timer_user_t *tu;
+               
+       tu = file->private_data;
+       snd_assert(tu->timeri != NULL, return -ENXIO);
+       return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
+}
+
+enum {
+       SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
+       SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
+       SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22),
+       SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
+};
+
 static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        snd_timer_user_t *tu;
@@ -1685,11 +1704,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l
        {
                int xarg;
                
-               if (tu->timeri)         /* too late */
+               down(&tu->tread_sem);
+               if (tu->timeri) {       /* too late */
+                       up(&tu->tread_sem);
                        return -EBUSY;
-               if (get_user(xarg, p))
+               }
+               if (get_user(xarg, p)) {
+                       up(&tu->tread_sem);
                        return -EFAULT;
+               }
                tu->tread = xarg ? 1 : 0;
+               up(&tu->tread_sem);
                return 0;
        }
        case SNDRV_TIMER_IOCTL_GINFO:
@@ -1707,11 +1732,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l
        case SNDRV_TIMER_IOCTL_STATUS:
                return snd_timer_user_status(file, argp);
        case SNDRV_TIMER_IOCTL_START:
+       case SNDRV_TIMER_IOCTL_START_OLD:
                return snd_timer_user_start(file);
        case SNDRV_TIMER_IOCTL_STOP:
+       case SNDRV_TIMER_IOCTL_STOP_OLD:
                return snd_timer_user_stop(file);
        case SNDRV_TIMER_IOCTL_CONTINUE:
+       case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
                return snd_timer_user_continue(file);
+       case SNDRV_TIMER_IOCTL_PAUSE:
+       case SNDRV_TIMER_IOCTL_PAUSE_OLD:
+               return snd_timer_user_pause(file);
        }
        return -ENOTTY;
 }
@@ -1898,4 +1929,3 @@ EXPORT_SYMBOL(snd_timer_global_free);
 EXPORT_SYMBOL(snd_timer_global_register);
 EXPORT_SYMBOL(snd_timer_global_unregister);
 EXPORT_SYMBOL(snd_timer_interrupt);
-EXPORT_SYMBOL(snd_timer_system_resolution);
index 9fbc3957a22dfbc14a7cacf7458c3fefddbb62a0..3de552dfe80f2dcb8a9644acb9824fbd9f1cba5d 100644 (file)
@@ -106,8 +106,13 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
        case SNDRV_TIMER_IOCTL_SELECT:
        case SNDRV_TIMER_IOCTL_PARAMS:
        case SNDRV_TIMER_IOCTL_START:
+       case SNDRV_TIMER_IOCTL_START_OLD:
        case SNDRV_TIMER_IOCTL_STOP:
+       case SNDRV_TIMER_IOCTL_STOP_OLD:
        case SNDRV_TIMER_IOCTL_CONTINUE:
+       case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
+       case SNDRV_TIMER_IOCTL_PAUSE:
+       case SNDRV_TIMER_IOCTL_PAUSE_OLD:
        case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
                return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
        case SNDRV_TIMER_IOCTL_INFO32:
index 98587176b32744469818e9074e9a9508e4821f45..af381b15fe5c4a813eb413ae04b0994b8ae67f38 100644 (file)
@@ -1264,14 +1264,10 @@ static void snd_vx_pcm_free(snd_pcm_t *pcm)
 {
        vx_core_t *chip = pcm->private_data;
        chip->pcm[pcm->device] = NULL;
-       if (chip->playback_pipes) {
-               kfree(chip->playback_pipes);
-               chip->playback_pipes = NULL;
-       }
-       if (chip->capture_pipes) {
-               kfree(chip->capture_pipes);
-               chip->capture_pipes = NULL;
-       }
+       kfree(chip->playback_pipes);
+       chip->playback_pipes = NULL;
+       kfree(chip->capture_pipes);
+       chip->capture_pipes = NULL;
 }
 
 /*
index bb503e70b6645b42b4e4258e46f80dc3b7a66928..2da8d7f157f4609eebc0b8b584af20bea91b1403 100644 (file)
@@ -266,8 +266,7 @@ TEA6330T_TREBLE("Tone Control - Treble", 0)
 
 static void snd_tea6330_free(snd_i2c_device_t *device)
 {
-       tea6330t_t *tea = device->private_data;
-       kfree(tea);
+       kfree(device->private_data);
 }
                                         
 int snd_tea6330t_update_mixer(snd_card_t * card,
index 3a3228b18726c9aaae432f7d3ecec06df3c4afa3..148a856a43ad7631207804137347ba6cd26184ca 100644 (file)
@@ -179,6 +179,7 @@ config SND_INTERWAVE_STB
        select SND_RAWMIDI
        select SND_CS4231_LIB
        select SND_GUS_SYNTH
+       select ISAPNP
        help
          Say Y here to include support for AMD InterWave based
          soundcards with a TEA6330T bass and treble regulator
index 9fa7a78da6c3301254919c9adbcef9a382e1dd10..563296d028941b53e211956fff89b54459640dce 100644 (file)
@@ -83,6 +83,8 @@ struct snd_card_ad1816a {
 static struct pnp_card_device_id snd_ad1816a_pnpids[] = {
        /* Analog Devices AD1815 */
        { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } },
+       /* Analog Device AD1816? */
+       { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
        /* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */
        { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
        /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */
index e745a54e00a1be7269486ce86cb5396cb492ef95..39f4eff44f5c8c5ac8fb2dc7595ef2082325fe5e 100644 (file)
@@ -349,8 +349,7 @@ static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard,
                pnp_init_resource_table(cfg);
                if (mpu_port[dev] != SNDRV_AUTO_PORT)
                        pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
-               if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0 &&
-                   pnp_irq_valid(pdev, 0))
+               if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0)
                        pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
                err = pnp_manual_config_dev(pdev, cfg, 0);
                if (err < 0)
index f0570f2bf75f89d1c0a62fc094622d88999b220c..337b0e2a8a36905a6b996587043699caf0c6c9ac 100644 (file)
@@ -244,6 +244,8 @@ unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg)
        return res;
 }
 
+#if 0
+
 void snd_gf1_i_adlib_write(snd_gus_card_t * gus,
                           unsigned char reg,
                           unsigned char data)
@@ -265,6 +267,8 @@ void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg,
        spin_unlock_irqrestore(&gus->reg_lock, flags);
 }
 
+#endif  /*  0  */
+
 unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
                                 unsigned char reg, short w_16bit)
 {
@@ -329,6 +333,8 @@ unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr)
        return res;
 }
 
+#if 0
+
 void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data)
 {
        unsigned long flags;
@@ -405,9 +411,7 @@ void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr,
        spin_unlock_irqrestore(&gus->reg_lock, flags);
 }
 
-/*
-
- */
+#endif  /*  0  */
 
 void snd_gf1_select_active_voices(snd_gus_card_t * gus)
 {
@@ -469,6 +473,8 @@ void snd_gf1_print_voice_registers(snd_gus_card_t * gus)
                printk(" -%i- GF1  pan                    = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c));
 }
 
+#if 0
+
 void snd_gf1_print_global_registers(snd_gus_card_t * gus)
 {
        unsigned char global_mode = 0x00;
@@ -528,4 +534,6 @@ void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count
        }
 }
 
+#endif  /*  0  */
+
 #endif
index 73f81c14f768ccfc4e7a5e0ba43a201489b648ca..94bbd344be5e31f97b5af4aa72f4e1e38f4eaa05 100644 (file)
@@ -459,7 +459,6 @@ EXPORT_SYMBOL(snd_gf1_write16);
 EXPORT_SYMBOL(snd_gf1_look16);
 EXPORT_SYMBOL(snd_gf1_i_write8);
 EXPORT_SYMBOL(snd_gf1_i_look8);
-EXPORT_SYMBOL(snd_gf1_i_write16);
 EXPORT_SYMBOL(snd_gf1_i_look16);
 EXPORT_SYMBOL(snd_gf1_dram_addr);
 EXPORT_SYMBOL(snd_gf1_write_addr);
@@ -470,8 +469,6 @@ EXPORT_SYMBOL(snd_gf1_alloc_voice);
 EXPORT_SYMBOL(snd_gf1_free_voice);
 EXPORT_SYMBOL(snd_gf1_ctrl_stop);
 EXPORT_SYMBOL(snd_gf1_stop_voice);
-EXPORT_SYMBOL(snd_gf1_start);
-EXPORT_SYMBOL(snd_gf1_stop);
   /* gus_mixer.c */
 EXPORT_SYMBOL(snd_gf1_new_mixer);
   /* gus_pcm.c */
index bfc2b91001d5d8db9f18d3317bf65a9560adaeb2..609838e8ef6727162c8b8b941c0c346e38667cd4 100644 (file)
@@ -39,8 +39,8 @@ void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup)
        }
 }
 
-snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
-                                       snd_gf1_mem_block_t * block)
+static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
+                                              snd_gf1_mem_block_t * block)
 {
        snd_gf1_mem_block_t *pblock, *nblock;
 
@@ -105,8 +105,8 @@ int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block)
        return 0;
 }
 
-snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
-                                     unsigned int address)
+static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
+                                            unsigned int address)
 {
        snd_gf1_mem_block_t *block;
 
@@ -118,8 +118,8 @@ snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
        return NULL;
 }
 
-snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
-                                      unsigned int *share_id)
+static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
+                                             unsigned int *share_id)
 {
        snd_gf1_mem_block_t *block;
 
index 8995ad9c516d0c33dfe063da63780af087838b38..b75066ab46fc33edfa1dd8262f0d1beb822a7bb9 100644 (file)
@@ -656,8 +656,7 @@ static snd_pcm_hardware_t snd_gf1_pcm_capture =
 
 static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
 {
-       gus_pcm_private_t * pcmp = runtime->private_data;
-       kfree(pcmp);
+       kfree(runtime->private_data);
 }
 
 static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
index b4e66f6a10aeee86e40b9779425a924e07321587..ef687abc707093154618df5d4710a6a058c7b328 100644 (file)
@@ -161,7 +161,8 @@ void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice)
 #endif
 }
 
-void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max)
+static void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min,
+                                unsigned short v_max)
 {
        unsigned long flags;
        unsigned int daddr;
index 66552e6013a4bc0dd5b016185b5f76ba95fc45d6..f51c386ee192dcf788e35f1f487c289a829b8f73 100644 (file)
@@ -99,7 +99,8 @@ static void snd_gus_synth_free_private_instruments(snd_gus_port_t *p, int client
        snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0);
 }
  
-int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop)
+static int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct,
+                                    void *private_data, int atomic, int hop)
 {
        snd_gus_port_t * p = (snd_gus_port_t *) private_data;
        
index ed8e9d85ad31888f273050f8f8efcb3a96f78dba..4adf098d3269d6a7d20711a258e4419db11ca197 100644 (file)
@@ -23,6 +23,8 @@
 
 #ifdef __GUS_TABLES_ALLOC__
 
+#if 0
+
 unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] =
 {
       8372,      8870,      9397,      9956,     10548,     11175,
@@ -49,6 +51,8 @@ unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] =
   12123977,  12844906
 };
 
+#endif  /*  0  */
+
 unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = {
   4095 /* 0   */,1789 /* 1   */,1533 /* 2   */,1383 /* 3   */,1277 /* 4   */,
   1195 /* 5   */,1127 /* 6   */,1070 /* 7   */,1021 /* 8   */,978  /* 9   */,
index b72bcfb286174cd9d78a7ec32b25e33304550732..3d36f6c8ee6a5fad70579ad8fbb34db15717e01b 100644 (file)
@@ -55,6 +55,8 @@ unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol)
        return (e << 8) | m;
 }
 
+#if 0
+
 unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol)
 {
        unsigned int rvol;
@@ -108,6 +110,8 @@ unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
        return (range << 6) | (increment & 0x3f);
 }
 
+#endif  /*  0  */
+
 unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
 {
        freq16 >>= 3;
@@ -120,6 +124,8 @@ unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
        return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq;
 }
 
+#if 0
+
 short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
 {
        static short vibrato_table[] =
@@ -208,3 +214,5 @@ unsigned short snd_gf1_compute_freq(unsigned int freq,
        }
        return (unsigned short) fc;
 }
+
+#endif  /*  0  */
index 76774bbc143685138429c6fb6b895bee2bd886c7..b4278eecc9171dc0123809589249d236b4111b30 100644 (file)
@@ -807,7 +807,7 @@ static void* busmaster_malloc(int size) {
                 struct page* page, *last_page;
 
                 page = virt_to_page(buf);
-                last_page = virt_to_page(buf + (1 << pg));
+                last_page = page + (1 << pg);
                 DBG(printk("setting reserved bit\n"));
                 while (page < last_page) {
                        SetPageReserved(page);
index 428efdbd70a12cd65491c60267ed8b25f6cc3732..6d7a00f34d822cc3171e4518f02a8271a1303104 100644 (file)
@@ -274,6 +274,19 @@ config SND_HDSP
          To compile this driver as a module, choose M here: the module
          will be called snd-hdsp.
 
+config SND_HDSPM
+       tristate "RME Hammerfall DSP MADI"
+       depends on SND
+       select SND_HWDEP
+       select SND_RAWMIDI
+       select SND_PCM
+       help
+         Say Y here to include support for RME Hammerfall DSP MADI
+         soundcards.
+
+         To compile this driver as a module, choose M here: the module
+         will be called snd-hdspm.
+
 config SND_TRIDENT
        tristate "Trident 4D-Wave DX/NX; SiS 7018"
        depends on SND
index 0b024ec1f7096d2419c6243b57d9d1d1eff6c3c8..a4b72cd2eea065e0501c8307387897f18af64dee 100644 (file)
@@ -120,6 +120,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
 { 0x414c4770, 0xfffffff0, "ALC203",            NULL,           NULL },
 { 0x434d4941, 0xffffffff, "CMI9738",           patch_cm9738,   NULL },
 { 0x434d4961, 0xffffffff, "CMI9739",           patch_cm9739,   NULL },
+{ 0x434d4969, 0xffffffff, "CMI9780",           patch_cm9780,   NULL },
 { 0x434d4978, 0xffffffff, "CMI9761",           patch_cm9761,   NULL },
 { 0x434d4982, 0xffffffff, "CMI9761",           patch_cm9761,   NULL },
 { 0x434d4983, 0xffffffff, "CMI9761",           patch_cm9761,   NULL },
@@ -149,7 +150,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
 { 0x4e534331, 0xffffffff, "LM4549",            NULL,           NULL },
 { 0x4e534350, 0xffffffff, "LM4550",            NULL,           NULL },
 { 0x50534304, 0xffffffff, "UCB1400",           NULL,           NULL },
-{ 0x53494c20, 0xffffffe0, "Si3036,8",          NULL,           mpatch_si3036 },
+{ 0x53494c20, 0xffffffe0, "Si3036,8",          mpatch_si3036,  mpatch_si3036, AC97_MODEM_PATCH },
 { 0x54524102, 0xffffffff, "TR28022",           NULL,           NULL },
 { 0x54524106, 0xffffffff, "TR28026",           NULL,           NULL },
 { 0x54524108, 0xffffffff, "TR28028",           patch_tritech_tr28028,  NULL }, // added by xin jin [07/09/99]
@@ -462,12 +463,14 @@ int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
 {
        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
        struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
-       unsigned short val;
+       unsigned short val, bitmask;
        
+       for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+               ;
        val = snd_ac97_read_cache(ac97, e->reg);
-       ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1);
+       ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
        if (e->shift_l != e->shift_r)
-               ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1);
+               ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1);
 
        return 0;
 }
@@ -477,17 +480,19 @@ int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
        struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
        unsigned short val;
-       unsigned short mask;
+       unsigned short mask, bitmask;
        
+       for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+               ;
        if (ucontrol->value.enumerated.item[0] > e->mask - 1)
                return -EINVAL;
        val = ucontrol->value.enumerated.item[0] << e->shift_l;
-       mask = (e->mask - 1) << e->shift_l;
+       mask = (bitmask - 1) << e->shift_l;
        if (e->shift_l != e->shift_r) {
                if (ucontrol->value.enumerated.item[1] > e->mask - 1)
                        return -EINVAL;
                val |= ucontrol->value.enumerated.item[1] << e->shift_r;
-               mask |= (e->mask - 1) << e->shift_r;
+               mask |= (bitmask - 1) << e->shift_r;
        }
        return snd_ac97_update_bits(ac97, e->reg, mask, val);
 }
@@ -658,14 +663,14 @@ AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1),
 AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1)
 };
 
-static const snd_kcontrol_new_t snd_ac97_controls_surround[2] = {
-AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
-AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
-};
-
 static const snd_kcontrol_new_t snd_ac97_control_eapd =
 AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1);
 
+static const snd_kcontrol_new_t snd_ac97_controls_modem_switches[2] = {
+AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0),
+AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0)
+};
+
 /* change the existing EAPD control as inverted */
 static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl)
 {
@@ -1072,9 +1077,9 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max
                unsigned short val;
                snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8));
                val = snd_ac97_read(ac97, reg);
-               if (! *lo_max && (val & cbit[i]))
+               if (! *lo_max && (val & 0x7f) == cbit[i])
                        *lo_max = max[i];
-               if (! *hi_max && (val & (cbit[i] << 8)))
+               if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i])
                        *hi_max = max[i];
                if (*lo_max && *hi_max)
                        break;
@@ -1526,13 +1531,25 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
 
 static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97)
 {
-       /* TODO */
+       int err, idx;
+
        //printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG));
        snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH));
        snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH));
        snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff);
        snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0);
        snd_ac97_write(ac97, AC97_MISC_AFE, 0x0);
+
+       /* build modem switches */
+       for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++)
+               if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_modem_switches[idx], ac97))) < 0)
+                       return err;
+
+       /* build chip specific controls */
+       if (ac97->build_ops->build_specific)
+               if ((err = ac97->build_ops->build_specific(ac97)) < 0)
+                       return err;
+
        return 0;
 }
 
@@ -1872,7 +1889,11 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
                        goto __access_ok;
        }
 
-       snd_ac97_write(ac97, AC97_RESET, 0);    /* reset to defaults */
+       /* reset to defaults */
+       if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO))
+               snd_ac97_write(ac97, AC97_RESET, 0);
+       if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM))
+               snd_ac97_write(ac97, AC97_EXTENDED_MID, 0);
        if (bus->ops->wait)
                bus->ops->wait(ac97);
        else {
@@ -1964,21 +1985,21 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
                /* note: it's important to set the rate at first */
                tmp = AC97_MEA_GPIO;
                if (ac97->ext_mid & AC97_MEI_LINE1) {
-                       snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000);
+                       snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000);
                        tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
                }
                if (ac97->ext_mid & AC97_MEI_LINE2) {
-                       snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000);
+                       snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000);
                        tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
                }
                if (ac97->ext_mid & AC97_MEI_HANDSET) {
-                       snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000);
+                       snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000);
                        tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;
                }
-               snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
+               snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
                udelay(100);
                /* nothing should be in powerdown mode */
-               snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
+               snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
                end_time = jiffies + (HZ / 10);
                do {
                        if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
@@ -2521,11 +2542,11 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o
                return result;
        }
 
-       for (; quirk->vendor; quirk++) {
-               if (quirk->vendor != ac97->subsystem_vendor)
+       for (; quirk->subvendor; quirk++) {
+               if (quirk->subvendor != ac97->subsystem_vendor)
                        continue;
-               if ((! quirk->mask && quirk->device == ac97->subsystem_device) ||
-                   quirk->device == (quirk->mask & ac97->subsystem_device)) {
+               if ((! quirk->mask && quirk->subdevice == ac97->subsystem_device) ||
+                   quirk->subdevice == (quirk->mask & ac97->subsystem_device)) {
                        if (quirk->codec_id && quirk->codec_id != ac97->id)
                                continue;
                        snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device);
index 13c34a5d8206dd5a92319a49459019683a49d6f5..a15eb8522b7cc90f098362bcb49e4242b6b4fe41 100644 (file)
@@ -64,6 +64,116 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor
        return ret;
 }
 
+/*
+ * shared line-in/mic controls
+ */
+static int ac97_enum_text_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo,
+                              const char **texts, unsigned int nums)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = nums;
+       if (uinfo->value.enumerated.item > nums - 1)
+               uinfo->value.enumerated.item = nums - 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int ac97_surround_jack_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       static const char *texts[] = { "Shared", "Independent" };
+       return ac97_enum_text_info(kcontrol, uinfo, texts, 2);
+}
+
+static int ac97_surround_jack_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = ac97->indep_surround;
+       return 0;
+}
+
+static int ac97_surround_jack_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+       unsigned char indep = !!ucontrol->value.enumerated.item[0];
+
+       if (indep != ac97->indep_surround) {
+               ac97->indep_surround = indep;
+               if (ac97->build_ops->update_jacks)
+                       ac97->build_ops->update_jacks(ac97);
+               return 1;
+       }
+       return 0;
+}
+
+static int ac97_channel_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       static const char *texts[] = { "2ch", "4ch", "6ch" };
+       if (kcontrol->private_value)
+               return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */
+       return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
+}
+
+static int ac97_channel_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = ac97->channel_mode;
+       return 0;
+}
+
+static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+       unsigned char mode = ucontrol->value.enumerated.item[0];
+
+       if (mode != ac97->channel_mode) {
+               ac97->channel_mode = mode;
+               if (ac97->build_ops->update_jacks)
+                       ac97->build_ops->update_jacks(ac97);
+               return 1;
+       }
+       return 0;
+}
+
+#define AC97_SURROUND_JACK_MODE_CTL \
+       { \
+               .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
+               .name   = "Surround Jack Mode", \
+               .info = ac97_surround_jack_mode_info, \
+               .get = ac97_surround_jack_mode_get, \
+               .put = ac97_surround_jack_mode_put, \
+       }
+#define AC97_CHANNEL_MODE_CTL \
+       { \
+               .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
+               .name   = "Channel Mode", \
+               .info = ac97_channel_mode_info, \
+               .get = ac97_channel_mode_get, \
+               .put = ac97_channel_mode_put, \
+       }
+#define AC97_CHANNEL_MODE_4CH_CTL \
+       { \
+               .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
+               .name   = "Channel Mode", \
+               .info = ac97_channel_mode_info, \
+               .get = ac97_channel_mode_get, \
+               .put = ac97_channel_mode_put, \
+               .private_value = 1, \
+       }
+
+static inline int is_shared_linein(ac97_t *ac97)
+{
+       return ! ac97->indep_surround && ac97->channel_mode >= 1;
+}
+
+static inline int is_shared_micin(ac97_t *ac97)
+{
+       return ! ac97->indep_surround && ac97->channel_mode >= 2;
+}
+
+
 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
 
 /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
@@ -1390,6 +1500,16 @@ static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
                                    AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
 }
 
+static void ad1888_update_jacks(ac97_t *ac97)
+{
+       /* shared Line-In */
+       snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
+                            is_shared_linein(ac97) ? 0 : 1 << 12);
+       /* shared Mic */
+       snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
+                            is_shared_micin(ac97) ? 0 : 1 << 11);
+}
+
 static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1406,8 +1526,8 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
                .get = snd_ac97_ad1888_downmix_get,
                .put = snd_ac97_ad1888_downmix_put
        },
-       AC97_SINGLE("Surround Jack as Input", AC97_AD_MISC, 12, 1, 0),
-       AC97_SINGLE("Center/LFE Jack as Input", AC97_AD_MISC, 11, 1, 0),
+       AC97_SURROUND_JACK_MODE_CTL,
+       AC97_CHANNEL_MODE_CTL,
 };
 
 static int patch_ad1888_specific(ac97_t *ac97)
@@ -1422,8 +1542,9 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = {
        .build_post_spdif = patch_ad198x_post_spdif,
        .build_specific = patch_ad1888_specific,
 #ifdef CONFIG_PM
-       .resume = ad18xx_resume
+       .resume = ad18xx_resume,
 #endif
+       .update_jacks = ad1888_update_jacks,
 };
 
 int patch_ad1888(ac97_t * ac97)
@@ -1459,8 +1580,9 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = {
        .build_post_spdif = patch_ad198x_post_spdif,
        .build_specific = patch_ad1980_specific,
 #ifdef CONFIG_PM
-       .resume = ad18xx_resume
+       .resume = ad18xx_resume,
 #endif
+       .update_jacks = ad1888_update_jacks,
 };
 
 int patch_ad1980(ac97_t * ac97)
@@ -1471,10 +1593,21 @@ int patch_ad1980(ac97_t * ac97)
 }
 
 static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = {
-       AC97_SINGLE("Center/LFE Jack as Mic", AC97_AD_SERIAL_CFG, 9, 1, 0),
        AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0)
 };
 
+static void ad1985_update_jacks(ac97_t *ac97)
+{
+       /* shared Line-In */
+       snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
+                            is_shared_linein(ac97) ? 0 : 1 << 12);
+       /* shared Mic */
+       snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
+                            is_shared_micin(ac97) ? 0 : 1 << 11);
+       snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
+                            is_shared_micin(ac97) ? 0 : 1 << 9);
+}
+
 static int patch_ad1985_specific(ac97_t *ac97)
 {
        int err;
@@ -1488,8 +1621,9 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = {
        .build_post_spdif = patch_ad198x_post_spdif,
        .build_specific = patch_ad1985_specific,
 #ifdef CONFIG_PM
-       .resume = ad18xx_resume
+       .resume = ad18xx_resume,
 #endif
+       .update_jacks = ad1985_update_jacks,
 };
 
 int patch_ad1985(ac97_t * ac97)
@@ -1521,31 +1655,25 @@ int patch_ad1985(ac97_t * ac97)
 /*
  * realtek ALC65x/850 codecs
  */
-static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
-        return 0;
-}
-
-static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc650_update_jacks(ac97_t *ac97)
 {
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-       int change, val;
-       val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10));
-       change = (ucontrol->value.integer.value[0] != val);
-       if (change) {
-               /* disable/enable vref */
-               snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
-                                    ucontrol->value.integer.value[0] ? (1 << 12) : 0);
-               /* turn on/off center-on-mic */
-               snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
-                                    ucontrol->value.integer.value[0] ? (1 << 10) : 0);
-               /* GPIO0 high for mic */
-               snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
-                                    ucontrol->value.integer.value[0] ? 0 : 0x100);
-        }
-        return change;
+       int shared;
+       
+       /* shared Line-In */
+       shared = is_shared_linein(ac97);
+       snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
+                            shared ? (1 << 9) : 0);
+       /* update shared Mic */
+       shared = is_shared_micin(ac97);
+       /* disable/enable vref */
+       snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
+                            shared ? (1 << 12) : 0);
+       /* turn on/off center-on-mic */
+       snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+                            shared ? (1 << 10) : 0);
+       /* GPIO0 high for mic */
+       snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
+                            shared ? 0 : 0x100);
 }
 
 static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
@@ -1558,8 +1686,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
        /* 6: Independent Master Volume Right */
        /* 7: Independent Master Volume Left */
        /* 8: reserved */
-       AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
-       /* 10: mic, see below */
+       /* 9: Line-In/Surround share */
+       /* 10: Mic/CLFE share */
        /* 11-13: in IEC958 controls */
        AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
 #if 0 /* always set in patch_alc650 */
@@ -1570,14 +1698,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
        AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
        AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
 #endif
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Mic As Center/LFE",
-               .info = snd_ac97_info_volsw,
-               .get = snd_ac97_alc650_mic_get,
-               .put = snd_ac97_alc650_mic_put,
-               .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-       },
+       AC97_SURROUND_JACK_MODE_CTL,
+       AC97_CHANNEL_MODE_CTL,
 };
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
@@ -1601,7 +1723,8 @@ static int patch_alc650_specific(ac97_t * ac97)
 }
 
 static struct snd_ac97_build_ops patch_alc650_ops = {
-       .build_specific = patch_alc650_specific
+       .build_specific = patch_alc650_specific,
+       .update_jacks = alc650_update_jacks
 };
 
 int patch_alc650(ac97_t * ac97)
@@ -1659,37 +1782,27 @@ int patch_alc650(ac97_t * ac97)
        return 0;
 }
 
-static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
-        return 0;
-}
-
-static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc655_update_jacks(ac97_t *ac97)
 {
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+       int shared;
+       
+       /* shared Line-In */
+       shared = is_shared_linein(ac97);
+       ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
+                             shared ? (1 << 9) : 0, 0);
+       /* update shared mic */
+       shared = is_shared_micin(ac97);
        /* misc control; vrefout disable */
        snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
-                            ucontrol->value.integer.value[0] ? (1 << 12) : 0);
-       return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
-                                    ucontrol->value.integer.value[0] ? (1 << 10) : 0,
-                                    0);
+                            shared ? (1 << 12) : 0);
+       ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
+                             shared ? (1 << 10) : 0, 0);
 }
 
-
 static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
        AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
-       AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0),
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Mic As Center/LFE",
-               .info = snd_ac97_info_volsw,
-               .get = snd_ac97_alc655_mic_get,
-               .put = snd_ac97_alc655_mic_put,
-               .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-       },
+       AC97_SURROUND_JACK_MODE_CTL,
+       AC97_CHANNEL_MODE_CTL,
 };
 
 static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -1759,7 +1872,8 @@ static int patch_alc655_specific(ac97_t * ac97)
 }
 
 static struct snd_ac97_build_ops patch_alc655_ops = {
-       .build_specific = patch_alc655_specific
+       .build_specific = patch_alc655_specific,
+       .update_jacks = alc655_update_jacks
 };
 
 int patch_alc655(ac97_t * ac97)
@@ -1798,63 +1912,33 @@ int patch_alc655(ac97_t * ac97)
 #define AC97_ALC850_JACK_SELECT        0x76
 #define AC97_ALC850_MISC1      0x7a
 
-static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;
-        return 0;
-}
-
-static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc850_update_jacks(ac97_t *ac97)
 {
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+       int shared;
+       
+       /* shared Line-In */
+       shared = is_shared_linein(ac97);
        /* SURR 1kOhm (bit4), Amp (bit5) */
        snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
-                            ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));
+                            shared ? (1<<5) : (1<<4));
        /* LINE-IN = 0, SURROUND = 2 */
-       return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
-                                   ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));
-}
-
-static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;
-        return 0;
-}
-
-static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+       snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
+                            shared ? (2<<12) : (0<<12));
+       /* update shared mic */
+       shared = is_shared_micin(ac97);
        /* Vref disable (bit12), 1kOhm (bit13) */
        snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
-                            ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));
+                            shared ? (1<<12) : (1<<13));
        /* MIC-IN = 1, CENTER-LFE = 2 */
-       return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
-                                   ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));
+       snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+                            shared ? (2<<4) : (1<<4));
 }
 
 static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
        AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Line-In As Surround",
-               .info = snd_ac97_info_volsw,
-               .get = ac97_alc850_surround_get,
-               .put = ac97_alc850_surround_put,
-               .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-       },
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Mic As Center/LFE",
-               .info = snd_ac97_info_volsw,
-               .get = ac97_alc850_mic_get,
-               .put = ac97_alc850_mic_put,
-               .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-       },
-
+       AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
+       AC97_SURROUND_JACK_MODE_CTL,
+       AC97_CHANNEL_MODE_CTL,
 };
 
 static int patch_alc850_specific(ac97_t *ac97)
@@ -1871,7 +1955,8 @@ static int patch_alc850_specific(ac97_t *ac97)
 }
 
 static struct snd_ac97_build_ops patch_alc850_ops = {
-       .build_specific = patch_alc850_specific
+       .build_specific = patch_alc850_specific,
+       .update_jacks = alc850_update_jacks
 };
 
 int patch_alc850(ac97_t *ac97)
@@ -1911,9 +1996,17 @@ int patch_alc850(ac97_t *ac97)
 /*
  * C-Media CM97xx codecs
  */
+static void cm9738_update_jacks(ac97_t *ac97)
+{
+       /* shared Line-In */
+       snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
+                            is_shared_linein(ac97) ? (1 << 10) : 0);
+}
+
 static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
-       AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
        AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
+       AC97_SURROUND_JACK_MODE_CTL,
+       AC97_CHANNEL_MODE_4CH_CTL,
 };
 
 static int patch_cm9738_specific(ac97_t * ac97)
@@ -1922,7 +2015,8 @@ static int patch_cm9738_specific(ac97_t * ac97)
 }
 
 static struct snd_ac97_build_ops patch_cm9738_ops = {
-       .build_specific = patch_cm9738_specific
+       .build_specific = patch_cm9738_specific,
+       .update_jacks = cm9738_update_jacks
 };
 
 int patch_cm9738(ac97_t * ac97)
@@ -1986,34 +2080,19 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
        /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
 };
 
-static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-       ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-       if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
-               ucontrol->value.integer.value[0] = 1;
-       else
-               ucontrol->value.integer.value[0] = 0;
-       return 0;
-}
-
-static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void cm9739_update_jacks(ac97_t *ac97)
 {
-       ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-       return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
-                                   ucontrol->value.integer.value[0] ? 
-                                   0x1000 : 0x2000);
+       /* shared Line-In */
+       snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
+                            is_shared_linein(ac97) ? (1 << 10) : 0);
+       /* shared Mic */
+       snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
+                            is_shared_micin(ac97) ? 0x1000 : 0x2000);
 }
 
 static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
-       AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Mic As Center/LFE",
-               .info = snd_ac97_info_volsw,
-               .get = snd_ac97_cm9739_center_mic_get,
-               .put = snd_ac97_cm9739_center_mic_put,
-               .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-       },
+       AC97_SURROUND_JACK_MODE_CTL,
+       AC97_CHANNEL_MODE_CTL,
 };
 
 static int patch_cm9739_specific(ac97_t * ac97)
@@ -2028,7 +2107,8 @@ static int patch_cm9739_post_spdif(ac97_t * ac97)
 
 static struct snd_ac97_build_ops patch_cm9739_ops = {
        .build_specific = patch_cm9739_specific,
-       .build_post_spdif = patch_cm9739_post_spdif
+       .build_post_spdif = patch_cm9739_post_spdif,
+       .update_jacks = cm9739_update_jacks
 };
 
 int patch_cm9739(ac97_t * ac97)
@@ -2087,71 +2167,97 @@ int patch_cm9739(ac97_t * ac97)
 }
 
 #define AC97_CM9761_MULTI_CHAN 0x64
+#define AC97_CM9761_FUNC       0x66
 #define AC97_CM9761_SPDIF_CTRL 0x6c
 
-static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-       ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-       if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400)
-               ucontrol->value.integer.value[0] = 1;
-       else
-               ucontrol->value.integer.value[0] = 0;
-       return 0;
-}
-
-static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void cm9761_update_jacks(ac97_t *ac97)
 {
-       ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-       unsigned short vals[2][2] = {
+       unsigned short surr_vals[2][2] = {
                { 0x0008, 0x0400 }, /* off, on */
                { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */
        };
-       return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408,
-                                   vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
+       unsigned short clfe_vals[2][2] = {
+               { 0x2000, 0x1880 }, /* off, on */
+               { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
+       };
+
+       /* shared Line-In */
+       snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408,
+                            surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]);
+       /* shared Mic */
+       snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880,
+                            clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]);
+}
+
+static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
+       AC97_SURROUND_JACK_MODE_CTL,
+       AC97_CHANNEL_MODE_CTL,
+};
+
+static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 3;
+       if (uinfo->value.enumerated.item > 2)
+               uinfo->value.enumerated.item = 2;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
 }
 
-static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-       if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
-               ucontrol->value.integer.value[0] = 1;
+
+       if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
+               ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
+       else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
+               ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */
        else
-               ucontrol->value.integer.value[0] = 0;
-       if (ac97->spec.dev_flags) /* 9761-82 rev.B */
-               ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0];
+               ucontrol->value.enumerated.item[0] = 0; /* AC-link */
        return 0;
 }
 
-static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int cm9761_spdif_out_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-       unsigned short vals[2][2] = {
-               { 0x2000, 0x1880 }, /* off, on */
-               { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
-       };
-       return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880,
-                                   vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
+
+       if (ucontrol->value.enumerated.item[0] == 2)
+               return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
+       snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
+       return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
+                                   ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
 }
 
-static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Line-In As Surround",
-               .info = snd_ac97_info_volsw,
-               .get = snd_ac97_cm9761_linein_rear_get,
-               .put = snd_ac97_cm9761_linein_rear_put,
-               .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-       },
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Mic As Center/LFE",
-               .info = snd_ac97_info_volsw,
-               .get = snd_ac97_cm9761_center_mic_get,
-               .put = snd_ac97_cm9761_center_mic_put,
-               .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" };
+static const struct ac97_enum cm9761_dac_clock_enum =
+       AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
+
+static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = {
+       { /* BIT 1: SPDIFS */
+               .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+               .info = cm9761_spdif_out_source_info,
+               .get = cm9761_spdif_out_source_get,
+               .put = cm9761_spdif_out_source_put,
        },
+       /* BIT 2: IG_SPIV */
+       AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
+       /* BIT 3: SPI2F */
+       AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0), 
+       /* BIT 4: SPI2SDI */
+       AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
+       /* BIT 9-10: DAC_CTL */
+       AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
 };
 
+static int patch_cm9761_post_spdif(ac97_t * ac97)
+{
+       return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
+}
+
 static int patch_cm9761_specific(ac97_t * ac97)
 {
        return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
@@ -2159,7 +2265,8 @@ static int patch_cm9761_specific(ac97_t * ac97)
 
 static struct snd_ac97_build_ops patch_cm9761_ops = {
        .build_specific = patch_cm9761_specific,
-       .build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */
+       .build_post_spdif = patch_cm9761_post_spdif,
+       .update_jacks = cm9761_update_jacks
 };
 
 int patch_cm9761(ac97_t *ac97)
@@ -2193,24 +2300,25 @@ int patch_cm9761(ac97_t *ac97)
        /* to be sure: we overwrite the ext status bits */
        snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
        /* Don't set 0x0200 here.  This results in the silent analog output */
-       snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009);
+       snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */
        ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 
        /* set-up multi channel */
        /* bit 15: pc master beep off
-        * bit 14: ??
+        * bit 14: pin47 = EAPD/SPDIF
         * bit 13: vref ctl [= cm9739]
-        * bit 12: center/mic [= cm9739] (reverted on rev B)
-        * bit 11: ?? (mic/center/lfe) (reverted on rev B)
-        * bit 10: suddound/line [= cm9739]
-        * bit  9: mix 2 surround
-        * bit  8: ?
-        * bit  7: ?? (mic/center/lfe)
-        * bit  4: ?? (front)
-        * bit  3: ?? (line-in/rear share) (revereted with rev B)
-        * bit  2: ?? (surround)
-        * bit  1: front mic
-        * bit  0: mic boost
+        * bit 12: CLFE control (reverted on rev B)
+        * bit 11: Mic/center share (reverted on rev B)
+        * bit 10: suddound/line share
+        * bit  9: Analog-in mix -> surround
+        * bit  8: Analog-in mix -> CLFE
+        * bit  7: Mic/LFE share (mic/center/lfe)
+        * bit  5: vref select (9761A)
+        * bit  4: front control
+        * bit  3: surround control (revereted with rev B)
+        * bit  2: front mic
+        * bit  1: stereo mic
+        * bit  0: mic boost level (0=20dB, 1=30dB)
         */
 
 #if 0
@@ -2230,6 +2338,47 @@ int patch_cm9761(ac97_t *ac97)
        return 0;
 }
        
+#define AC97_CM9780_SIDE       0x60
+#define AC97_CM9780_JACK       0x62
+#define AC97_CM9780_MIXER      0x64
+#define AC97_CM9780_MULTI_CHAN 0x66
+#define AC97_CM9780_SPDIF      0x6c
+
+static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" };
+static const struct ac97_enum cm9780_ch_select_enum =
+       AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
+static const snd_kcontrol_new_t cm9780_controls[] = {
+       AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
+       AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
+       AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
+};
+
+static int patch_cm9780_specific(ac97_t *ac97)
+{
+       return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
+}
+
+static struct snd_ac97_build_ops patch_cm9780_ops = {
+       .build_specific = patch_cm9780_specific,
+       .build_post_spdif = patch_cm9761_post_spdif     /* identical with CM9761 */
+};
+
+int patch_cm9780(ac97_t *ac97)
+{
+       unsigned short val;
+
+       ac97->build_ops = &patch_cm9780_ops;
+
+       /* enable spdif */
+       if (ac97->ext_id & AC97_EI_SPDIF) {
+               ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
+               val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
+               val |= 0x1; /* SPDI_EN */
+               snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
+       }
+
+       return 0;
+}
 
 /*
  * VIA VT1616 codec
@@ -2263,9 +2412,21 @@ int patch_vt1616(ac97_t * ac97)
        return 0;
 }
 
+/*
+ */
+static void it2646_update_jacks(ac97_t *ac97)
+{
+       /* shared Line-In */
+       snd_ac97_update_bits(ac97, 0x76, 1 << 9,
+                            is_shared_linein(ac97) ? (1<<9) : 0);
+       /* shared Mic */
+       snd_ac97_update_bits(ac97, 0x76, 1 << 10,
+                            is_shared_micin(ac97) ? (1<<10) : 0);
+}
+
 static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = {
-       AC97_SINGLE("Line-In As Surround", 0x76, 9, 1, 0),
-       AC97_SINGLE("Mic As Center/LFE", 0x76, 10, 1, 0),
+       AC97_SURROUND_JACK_MODE_CTL,
+       AC97_CHANNEL_MODE_CTL,
 };
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = {
@@ -2285,7 +2446,8 @@ static int patch_it2646_specific(ac97_t * ac97)
 }
 
 static struct snd_ac97_build_ops patch_it2646_ops = {
-       .build_specific = patch_it2646_specific
+       .build_specific = patch_it2646_specific,
+       .update_jacks = it2646_update_jacks
 };
 
 int patch_it2646(ac97_t * ac97)
@@ -2297,12 +2459,29 @@ int patch_it2646(ac97_t * ac97)
        return 0;
 }
 
-/* Si3036/8 specific registers */
+/*
+ * Si3036 codec
+ */
+
 #define AC97_SI3036_CHIP_ID     0x5a
+#define AC97_SI3036_LINE_CFG    0x5c
+
+static const snd_kcontrol_new_t snd_ac97_controls_si3036[] = {
+AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
+};
+
+static int patch_si3036_specific(ac97_t * ac97)
+{
+       return patch_build_controls(ac97, snd_ac97_controls_si3036, ARRAY_SIZE(snd_ac97_controls_si3036));
+}
+
+static struct snd_ac97_build_ops patch_si3036_ops = {
+       .build_specific = patch_si3036_specific,
+};
 
 int mpatch_si3036(ac97_t * ac97)
 {
-       //printk("mpatch_si3036: chip id = %x\n", snd_ac97_read(ac97, 0x5a));
+       ac97->build_ops = &patch_si3036_ops;
        snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
        snd_ac97_write_cache(ac97, 0x68, 0);
        return 0;
index 6db51c96f5d01053529642cdb2cdcc2e0cccede3..7b7377d0f2ae4d3926e3cd7e379be16d488d3027 100644 (file)
@@ -54,6 +54,7 @@ int patch_alc850(ac97_t * ac97);
 int patch_cm9738(ac97_t * ac97);
 int patch_cm9739(ac97_t * ac97);
 int patch_cm9761(ac97_t * ac97);
+int patch_cm9780(ac97_t * ac97);
 int patch_vt1616(ac97_t * ac97);
 int patch_it2646(ac97_t * ac97);
 int mpatch_si3036(ac97_t * ac97);
index 984d5d4ba4e15eb905bd3df47c5e5f3a6cdd1eea..eb5c36d31a52ae75a7e802407b71d7f760529796 100644 (file)
@@ -98,6 +98,8 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
 #define ALI_LEF_CHANNEL                23
 #define ALI_SURR_LEFT_CHANNEL  26
 #define ALI_SURR_RIGHT_CHANNEL 25
+#define ALI_MODEM_IN_CHANNEL    21
+#define ALI_MODEM_OUT_CHANNEL   20
 
 #define        SNDRV_ALI_VOICE_TYPE_PCM        01
 #define SNDRV_ALI_VOICE_TYPE_OTH       02
@@ -122,7 +124,15 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
 
 #define ALI_SCTRL              0x48
 #define   ALI_SPDIF_OUT_ENABLE         0x20
+#define   ALI_SCTRL_LINE_IN2           (1 << 9)
+#define   ALI_SCTRL_GPIO_IN2           (1 << 13)
+#define   ALI_SCTRL_LINE_OUT_EN        (1 << 20)
+#define   ALI_SCTRL_GPIO_OUT_EN        (1 << 23)
+#define   ALI_SCTRL_CODEC1_READY       (1 << 24)
+#define   ALI_SCTRL_CODEC2_READY       (1 << 25)
 #define ALI_AC97_GPIO          0x4c
+#define   ALI_AC97_GPIO_ENABLE         0x8000
+#define   ALI_AC97_GPIO_DATA_SHIFT     16
 #define ALI_SPDIF_CS           0x70
 #define ALI_SPDIF_CTRL         0x74
 #define   ALI_SPDIF_IN_FUNC_ENABLE     0x02
@@ -143,6 +153,7 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
        #define TARGET_REACHED          0x00008000
        #define MIXER_OVERFLOW          0x00000800
        #define MIXER_UNDERFLOW         0x00000400
+       #define GPIO_IRQ                0x01000000
 #define ALI_SBBL_SBCL           0xc0
 #define ALI_SBCTRL_SBE2R_SBDD   0xc4
 #define ALI_STIMER             0xc8
@@ -162,6 +173,9 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
 
 #define ALI_REG(codec, x) ((codec)->port + x)
 
+#define MAX_CODECS 2
+
+
 typedef struct snd_stru_ali ali_t;
 typedef struct snd_ali_stru_voice snd_ali_voice_t;
 
@@ -245,7 +259,7 @@ struct snd_stru_ali {
        struct pci_dev  *pci_m7101;
 
        snd_card_t      *card;
-       snd_pcm_t       *pcm;
+       snd_pcm_t       *pcm[MAX_CODECS];
        alidev_t        synth;
        snd_ali_channel_control_t chregs;
 
@@ -255,8 +269,10 @@ struct snd_stru_ali {
        unsigned int spurious_irq_count;
        unsigned int spurious_irq_max_delta;
 
+       unsigned int num_of_codecs;
+
        ac97_bus_t *ac97_bus;
-       ac97_t *ac97;
+       ac97_t *ac97[MAX_CODECS];
        unsigned short  ac97_ext_id;
        unsigned short  ac97_ext_status;
 
@@ -489,7 +505,12 @@ static void snd_ali_codec_write(ac97_t *ac97,
        ali_t *codec = ac97->private_data;
 
        snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val);
-       snd_ali_codec_poke(codec, 0, reg, val);
+       if(reg == AC97_GPIO_STATUS) {
+               outl((val << ALI_AC97_GPIO_DATA_SHIFT)|ALI_AC97_GPIO_ENABLE,
+                       ALI_REG(codec, ALI_AC97_GPIO));
+               return;
+       }
+       snd_ali_codec_poke(codec, ac97->num, reg, val);
        return ;
 }
 
@@ -499,7 +520,7 @@ static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg)
        ali_t *codec = ac97->private_data;
 
        snd_ali_printk("codec_read reg=%xh.\n", reg);
-       return (snd_ali_codec_peek(codec, 0, reg));
+       return (snd_ali_codec_peek(codec, ac97->num, reg));
 }
 
 /*
@@ -1051,7 +1072,7 @@ static irqreturn_t snd_ali_card_interrupt(int irq,
 }
 
 
-static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec)
+static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel)
 {
        snd_ali_voice_t *pvoice = NULL;
        unsigned long flags;
@@ -1061,7 +1082,8 @@ static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec)
 
        spin_lock_irqsave(&codec->voice_alloc, flags);
        if (type == SNDRV_ALI_VOICE_TYPE_PCM) {
-               idx = snd_ali_find_free_channel(codec,rec);
+               idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :
+                       snd_ali_find_free_channel(codec,rec);
                if(idx < 0) {
                        snd_printk("ali_alloc_voice: err.\n");
                        spin_unlock_irqrestore(&codec->voice_alloc, flags);
@@ -1297,7 +1319,7 @@ static int snd_ali_playback_hw_params(snd_pcm_substream_t * substream,
 
        if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) {
                if (evoice == NULL) {
-                       evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);
+                       evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1);
                        if (evoice == NULL)
                                return -ENOMEM;
                        pvoice->extra = evoice;
@@ -1328,13 +1350,13 @@ static int snd_ali_playback_hw_free(snd_pcm_substream_t * substream)
        return 0;
 }
 
-static int snd_ali_capture_hw_params(snd_pcm_substream_t * substream,
+static int snd_ali_hw_params(snd_pcm_substream_t * substream,
                                 snd_pcm_hw_params_t * hw_params)
 {
        return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 }
 
-static int snd_ali_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_ali_hw_free(snd_pcm_substream_t * substream)
 {
        return snd_pcm_lib_free_pages(substream);
 }
@@ -1428,7 +1450,7 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
 }
 
 
-static int snd_ali_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_ali_prepare(snd_pcm_substream_t * substream)
 {
        ali_t *codec = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1446,11 +1468,13 @@ static int snd_ali_capture_prepare(snd_pcm_substream_t * substream)
 
        spin_lock_irqsave(&codec->reg_lock, flags);
 
-       snd_ali_printk("capture_prepare...\n");
+       snd_ali_printk("ali_prepare...\n");
 
        snd_ali_enable_special_channel(codec,pvoice->number);
 
-       Delta = snd_ali_convert_rate(runtime->rate, 1);
+       Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL ||
+                pvoice->number == ALI_MODEM_OUT_CHANNEL) ? 
+               0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode);
 
        // Prepare capture intr channel
        if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {
@@ -1534,7 +1558,7 @@ static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream
 }
 
 
-static snd_pcm_uframes_t snd_ali_capture_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_ali_pointer(snd_pcm_substream_t *substream)
 {
        ali_t *codec = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1616,7 +1640,8 @@ static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime)
        }
 }
 
-static int snd_ali_playback_open(snd_pcm_substream_t * substream)
+static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
+               snd_pcm_hardware_t *phw)
 {
        ali_t *codec = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1624,7 +1649,7 @@ static int snd_ali_playback_open(snd_pcm_substream_t * substream)
        unsigned long flags = 0;
 
        spin_lock_irqsave(&codec->reg_lock, flags);
-       pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);
+       pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel);
        if (pvoice == NULL) {
                spin_unlock_irqrestore(&codec->reg_lock, flags);
                return -EAGAIN;
@@ -1636,49 +1661,31 @@ static int snd_ali_playback_open(snd_pcm_substream_t * substream)
        runtime->private_data = pvoice;
        runtime->private_free = snd_ali_pcm_free_substream;
 
-       runtime->hw = snd_ali_playback;
+       runtime->hw = *phw;
        snd_pcm_set_sync(substream);
        snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
        return 0;
 }
 
+static int snd_ali_playback_open(snd_pcm_substream_t * substream)
+{
+       return snd_ali_open(substream, 0, -1, &snd_ali_playback);
+}
 
 static int snd_ali_capture_open(snd_pcm_substream_t * substream)
 {
-       ali_t *codec = snd_pcm_substream_chip(substream);
-       snd_pcm_runtime_t *runtime = substream->runtime;
-       snd_ali_voice_t *pvoice;
-       unsigned long flags;
-
-       spin_lock_irqsave(&codec->reg_lock, flags);
-       pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 1);
-       if (pvoice == NULL) {
-               spin_unlock_irqrestore(&codec->reg_lock, flags);
-               return -EAGAIN;
-       }
-       pvoice->codec = codec;
-       spin_unlock_irqrestore(&codec->reg_lock, flags);
-
-       pvoice->substream = substream;
-       runtime->private_data = pvoice;
-       runtime->private_free = snd_ali_pcm_free_substream;
-       runtime->hw = snd_ali_capture;
-       snd_pcm_set_sync(substream);
-       snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
-       return 0;
+       return snd_ali_open(substream, 1, -1, &snd_ali_capture);
 }
 
-
 static int snd_ali_playback_close(snd_pcm_substream_t * substream)
 {
        return 0;
 }
 
-static int snd_ali_capture_close(snd_pcm_substream_t * substream)
+static int snd_ali_close(snd_pcm_substream_t * substream)
 {
        ali_t *codec = snd_pcm_substream_chip(substream);
-       snd_pcm_runtime_t *runtime = substream->runtime;
-       snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
+       snd_ali_voice_t *pvoice = (snd_ali_voice_t *) substream->runtime->private_data;
 
        snd_ali_disable_special_channel(codec,pvoice->number);
 
@@ -1698,29 +1705,121 @@ static snd_pcm_ops_t snd_ali_playback_ops = {
 
 static snd_pcm_ops_t snd_ali_capture_ops = {
        .open =         snd_ali_capture_open,
-       .close =        snd_ali_capture_close,
+       .close =        snd_ali_close,
        .ioctl =        snd_ali_ioctl,
-       .hw_params =    snd_ali_capture_hw_params,
-       .hw_free =      snd_ali_capture_hw_free,
-       .prepare =      snd_ali_capture_prepare,
+       .hw_params =    snd_ali_hw_params,
+       .hw_free =      snd_ali_hw_free,
+       .prepare =      snd_ali_prepare,
+       .trigger =      snd_ali_trigger,
+       .pointer =      snd_ali_pointer,
+};
+
+/*
+ * Modem PCM
+ */
+
+static int snd_ali_modem_hw_params(snd_pcm_substream_t * substream,
+                                snd_pcm_hw_params_t * hw_params)
+{
+       ali_t *chip = snd_pcm_substream_chip(substream);
+       unsigned int modem_num = chip->num_of_codecs - 1;
+       snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params));
+       snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);
+       return snd_ali_hw_params(substream, hw_params);
+}
+
+static snd_pcm_hardware_t snd_ali_modem =
+{
+       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+                                SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                SNDRV_PCM_INFO_MMAP_VALID |
+                                SNDRV_PCM_INFO_RESUME |
+                                SNDRV_PCM_INFO_SYNC_START),
+       .formats =              SNDRV_PCM_FMTBIT_S16_LE,
+       .rates =                SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000,
+       .rate_min =             8000,
+       .rate_max =             16000,
+       .channels_min =         1,
+       .channels_max =         1,
+       .buffer_bytes_max =     (256*1024),
+       .period_bytes_min =     64,
+       .period_bytes_max =     (256*1024),
+       .periods_min =          1,
+       .periods_max =          1024,
+       .fifo_size =            0,
+};
+
+static int snd_ali_modem_open(snd_pcm_substream_t * substream, int rec, int channel)
+{
+       static unsigned int rates [] = {8000,9600,12000,16000};
+       static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
+               .count = ARRAY_SIZE(rates),
+               .list = rates,
+               .mask = 0,
+       };
+       int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);
+       if (err)
+               return err;
+       return snd_pcm_hw_constraint_list(substream->runtime, 0,
+                       SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
+}
+
+static int snd_ali_modem_playback_open(snd_pcm_substream_t * substream)
+{
+       return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);
+}
+
+static int snd_ali_modem_capture_open(snd_pcm_substream_t * substream)
+{
+       return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);
+}
+
+static snd_pcm_ops_t snd_ali_modem_playback_ops = {
+       .open =         snd_ali_modem_playback_open,
+       .close =        snd_ali_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    snd_ali_modem_hw_params,
+       .hw_free =      snd_ali_hw_free,
+       .prepare =      snd_ali_prepare,
+       .trigger =      snd_ali_trigger,
+       .pointer =      snd_ali_pointer,
+};
+
+static snd_pcm_ops_t snd_ali_modem_capture_ops = {
+       .open =         snd_ali_modem_capture_open,
+       .close =        snd_ali_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    snd_ali_modem_hw_params,
+       .hw_free =      snd_ali_hw_free,
+       .prepare =      snd_ali_prepare,
        .trigger =      snd_ali_trigger,
-       .pointer =      snd_ali_capture_pointer,
+       .pointer =      snd_ali_pointer,
+};
+
+
+struct ali_pcm_description {
+       char *name;
+       unsigned int playback_num;
+       unsigned int capture_num;
+       snd_pcm_ops_t *playback_ops;
+       snd_pcm_ops_t *capture_ops;
 };
 
 
 static void snd_ali_pcm_free(snd_pcm_t *pcm)
 {
        ali_t *codec = pcm->private_data;
-       codec->pcm = NULL;
+       codec->pcm[pcm->device] = NULL;
 }
 
-static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm)
+
+static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_description *desc)
 {
        snd_pcm_t *pcm;
        int err;
 
-       if (rpcm) *rpcm = NULL;
-       err = snd_pcm_new(codec->card, "ALI 5451", device, ALI_CHANNELS, 1, &pcm);
+       err = snd_pcm_new(codec->card, desc->name, device,
+                         desc->playback_num, desc->capture_num, &pcm);
        if (err < 0) {
                snd_printk("snd_ali_pcm: err called snd_pcm_new.\n");
                return err;
@@ -1728,20 +1827,36 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm)
        pcm->private_data = codec;
        pcm->private_free = snd_ali_pcm_free;
        pcm->info_flags = 0;
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ali_playback_ops);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ali_capture_ops);
+       if (desc->playback_ops)
+               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops);
+       if (desc->capture_ops)
+               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, desc->capture_ops);
 
        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                                              snd_dma_pci_data(codec->pci), 64*1024, 128*1024);
 
        pcm->info_flags = 0;
        pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
-       strcpy(pcm->name, "ALI 5451");
-       codec->pcm = pcm;
-       if (rpcm) *rpcm = pcm;
+       strcpy(pcm->name, desc->name);
+       codec->pcm[0] = pcm;
        return 0;
 }
 
+struct ali_pcm_description ali_pcms[] = {
+       { "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops },
+       { "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops }
+};
+
+static int __devinit snd_ali_build_pcms(ali_t *codec)
+{
+       int i, err;
+       for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++)
+               if((err = snd_ali_pcm(codec, i, &ali_pcms[i])) < 0)
+                       return err;
+       return 0;
+}
+
+
 #define ALI5451_SPDIF(xname, xindex, value) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
 .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \
@@ -1860,14 +1975,14 @@ static void snd_ali_mixer_free_ac97_bus(ac97_bus_t *bus)
 static void snd_ali_mixer_free_ac97(ac97_t *ac97)
 {
        ali_t *codec = ac97->private_data;
-       codec->ac97 = NULL;
+       codec->ac97[ac97->num] = NULL;
 }
 
 static int __devinit snd_ali_mixer(ali_t * codec)
 {
        ac97_template_t ac97;
        unsigned int idx;
-       int err;
+       int i, err;
        static ac97_bus_ops_t ops = {
                .write = snd_ali_codec_write,
                .read = snd_ali_codec_read,
@@ -1880,10 +1995,16 @@ static int __devinit snd_ali_mixer(ali_t * codec)
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = codec;
        ac97.private_free = snd_ali_mixer_free_ac97;
-       if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97)) < 0) {
-               snd_printk("ali mixer creating error.\n");
+
+       for ( i = 0 ; i < codec->num_of_codecs ; i++) {
+               ac97.num = i;
+               if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) {
+                       snd_printk("ali mixer %d creating error.\n", i);
+                       if(i == 0)
                return err;
        }
+       }
+
        if (codec->spdif_support) {
                for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) {
                        err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec));
@@ -1904,8 +2025,12 @@ static int ali_suspend(snd_card_t *card, pm_message_t state)
        if (! im)
                return 0;
 
-       snd_pcm_suspend_all(chip->pcm);
-       snd_ac97_suspend(chip->ac97);
+       for(i = 0 ; i < chip->num_of_codecs ; i++) {
+               if (chip->pcm[i])
+                       snd_pcm_suspend_all(chip->pcm[i]);
+               if(chip->ac97[i])
+                       snd_ac97_suspend(chip->ac97[i]);
+       }
 
        spin_lock_irq(&chip->reg_lock);
        
@@ -1969,7 +2094,9 @@ static int ali_resume(snd_card_t *card)
        
        spin_unlock_irq(&chip->reg_lock);
 
-       snd_ac97_resume(chip->ac97);
+       for(i = 0 ; i < chip->num_of_codecs ; i++)
+               if(chip->ac97[i])
+                       snd_ac97_resume(chip->ac97[i]);
        
        return 0;
 }
@@ -2036,11 +2163,37 @@ static int snd_ali_chip_init(ali_t *codec)
                codec->spdif_mask = 0x00000002;
        }
 
+       codec->num_of_codecs = 1;
+
+       /* secondary codec - modem */
+       if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) {
+               codec->num_of_codecs++;
+               outl(inl(ALI_REG(codec, ALI_SCTRL)) |
+                       (ALI_SCTRL_LINE_IN2|ALI_SCTRL_GPIO_IN2|ALI_SCTRL_LINE_OUT_EN),
+                       ALI_REG(codec, ALI_SCTRL));
+       }
+
        snd_ali_printk("chip initialize succeed.\n");
        return 0;
 
 }
 
+/* proc for register dump */
+static void snd_ali_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buf)
+{
+       ali_t *codec = entry->private_data;
+       int i;
+       for(i = 0 ; i < 256 ; i+= 4)
+               snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
+}
+
+static void __devinit snd_ali_proc_init(ali_t *codec)
+{
+       snd_info_entry_t *entry;
+       if(!snd_card_proc_new(codec->card, "ali5451", &entry))
+               snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read);
+}
+
 static int __devinit snd_ali_resources(ali_t *codec)
 {
        int err;
@@ -2233,11 +2386,13 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
        }
        
        snd_ali_printk("pcm building ...\n");
-       if ((err = snd_ali_pcm(codec, 0, NULL)) < 0) {
+       if ((err = snd_ali_build_pcms(codec)) < 0) {
                snd_card_free(card);
                return err;
        }
 
+       snd_ali_proc_init(codec);
+
        strcpy(card->driver, "ALI5451");
        strcpy(card->shortname, "ALI 5451");
        
@@ -2270,7 +2425,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_ali_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ali_exit(void)
index f1a5f5723ee6b5f89ad3be89130146bd22a398f8..ca28b229c704051154ef1a05aae2a485f7234e64 100644 (file)
@@ -367,7 +367,7 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *
        if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */
                snd_pcm_period_elapsed(chip->capture_substream);
        if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */
-               snd_mpu401_uart_interrupt(irq, chip->rmidi, regs);
+               snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
        /* release the gcr */
        outb(gcr_status, chip->alt_port + 0xe);
        
@@ -777,7 +777,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_als4000_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_als4000_exit(void)
index 6b04c0acc6f722e47eddc6357d0f205ce2c90a5d..cafab4af5c571752765ad1a4b552c9013f4e4aad 100644 (file)
@@ -1334,8 +1334,8 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r
 
 static struct ac97_quirk ac97_quirks[] __devinitdata = {
        {
-               .vendor = 0x103c,
-               .device = 0x006b,
+               .subvendor = 0x103c,
+               .subdevice = 0x006b,
                .name = "HP Pavilion ZV5030US",
                .type = AC97_TUNE_MUTE_LED
        },
@@ -1645,7 +1645,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_atiixp_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_atiixp_exit(void)
index fb7cecea846d069334d0b83e84401790ec6e78fc..a6b4b8d589fd672918da5efda911e280f59cfc10 100644 (file)
@@ -463,6 +463,11 @@ static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
 static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
        atiixp_t *chip = ac97->private_data;
+       if (reg == AC97_GPIO_STATUS) {
+               atiixp_write(chip, MODEM_OUT_GPIO,
+                       (val << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN);
+               return;
+       }
        snd_atiixp_codec_write(chip, ac97->num, reg, val);
 }
 
@@ -663,44 +668,33 @@ static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
        atiixp_t *chip = snd_pcm_substream_chip(substream);
        atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
-       unsigned int reg = 0;
-       int i;
+       int err = 0;
 
        snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL);
 
-       if (cmd != SNDRV_PCM_TRIGGER_START && cmd != SNDRV_PCM_TRIGGER_STOP)
-               return -EINVAL;
-
        spin_lock(&chip->reg_lock);
-
-       /* hook off/on: via GPIO_OUT */
-       for (i = 0; i < NUM_ATI_CODECS; i++) {
-               if (chip->ac97[i]) {
-                       reg = snd_ac97_read(chip->ac97[i], AC97_GPIO_STATUS);
-                       break;
-       }
-       }
-       if(cmd == SNDRV_PCM_TRIGGER_START)
-               reg |= AC97_GPIO_LINE1_OH;
-       else
-               reg &= ~AC97_GPIO_LINE1_OH;
-       reg = (reg << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN ;
-       atiixp_write(chip, MODEM_OUT_GPIO, reg);
-
-       if (cmd == SNDRV_PCM_TRIGGER_START) {
+       switch(cmd) {
+       case SNDRV_PCM_TRIGGER_START:
                dma->ops->enable_transfer(chip, 1);
                dma->running = 1;
-       } else {
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
                dma->ops->enable_transfer(chip, 0);
                dma->running = 0;
+               break;
+       default:
+               err = -EINVAL;
+               break;
        }
+       if (! err) {
        snd_atiixp_check_bus_busy(chip);
        if (cmd == SNDRV_PCM_TRIGGER_STOP) {
                dma->ops->flush_dma(chip);
                snd_atiixp_check_bus_busy(chip);
        }
+       }
        spin_unlock(&chip->reg_lock);
-       return 0;
+       return err;
 }
 
 
@@ -1332,7 +1326,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_atiixp_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_atiixp_exit(void)
index 889b4a1a51a1adcb8d8e4160e0d512dcfd689be9..f6236c63aaaae2c3d5cdaafe9facf7bd85e56281 100644 (file)
@@ -375,7 +375,7 @@ static struct pci_driver driver = {
 // initialization of the module
 static int __init alsa_card_vortex_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 // clean up the module
index b8ae534125c1ecf9812a4570b11dc9530d88ef91..72bba7b2d983811bbba99a098cbfccbd5740ef20 100644 (file)
@@ -1520,7 +1520,7 @@ static int __init alsa_card_azf3328_init(void)
 {
        int err;
        snd_azf3328_dbgcallenter();
-       err = pci_module_init(&driver);
+       err = pci_register_driver(&driver);
        snd_azf3328_dbgcallleave();
        return err;
 }
index 89a7ffe5e7d7723a0a2317d95144c588c31dfc20..defdc5a459f0ffea3ff7732160bdfabfa0db9b58 100644 (file)
@@ -918,7 +918,7 @@ static int __init alsa_card_bt87x_init(void)
 {
        if (load_all)
                driver.id_table = snd_bt87x_default_ids;
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_bt87x_exit(void)
index deb028851056bd85fad5f8171cf405987e88776f..da09cab405a92748904bd925aba7662b488fc7a7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.20
+ *  Version: 0.0.21
  *
  *  FEATURES currently supported:
  *    See ca0106_main.c for features.
@@ -45,6 +45,8 @@
  *    Added I2C and SPI registers. Filled in interrupt enable.
  *  0.0.20
  *    Added GPIO info for SB Live 24bit.
+ *  0.0.21
+ *   Implement support for Line-in capture on SB Live 24bit.
  *
  *
  *  This code was initally based on code from ALSA's emu10k1x.c which is:
                                                 * bit 9 0 = Mute / 1 = Analog out.
                                                 * bit 10 0 = Line-in / 1 = Mic-in.
                                                 * bit 11 0 = ? / 1 = ?
-                                                * bit 12 0 = ? / 1 = ?
+                                                * bit 12 0 = 48 Khz / 1 = 96 Khz Analog out on SB Live 24bit.
                                                 * bit 13 0 = ? / 1 = ?
                                                 * bit 14 0 = Mute / 1 = Analog out
                                                 * bit 15 0 = ? / 1 = ?
                                                /* Causes interrupts based on timer intervals. */
 #define SPI                    0x7a            /* SPI: Serial Interface Register */
 #define I2C_A                  0x7b            /* I2C Address. 32 bit */
-#define I2C_0                  0x7c            /* I2C Data Port 0. 32 bit */
-#define I2C_1                  0x7d            /* I2C Data Port 1. 32 bit */
+#define I2C_D0                 0x7c            /* I2C Data Port 0. 32 bit */
+#define I2C_D1                 0x7d            /* I2C Data Port 1. 32 bit */
+//I2C values
+#define I2C_A_ADC_ADD_MASK     0x000000fe      //The address is a 7 bit address
+#define I2C_A_ADC_RW_MASK      0x00000001      //bit mask for R/W
+#define I2C_A_ADC_TRANS_MASK   0x00000010      //Bit mask for I2c address DAC value
+#define I2C_A_ADC_ABORT_MASK   0x00000020      //Bit mask for I2C transaction abort flag
+#define I2C_A_ADC_LAST_MASK    0x00000040      //Bit mask for Last word transaction
+#define I2C_A_ADC_BYTE_MASK    0x00000080      //Bit mask for Byte Mode
 
+#define I2C_A_ADC_ADD          0x00000034      //This is the Device address for ADC 
+#define I2C_A_ADC_READ         0x00000001      //To perform a read operation
+#define I2C_A_ADC_START                0x00000100      //Start I2C transaction
+#define I2C_A_ADC_ABORT                0x00000200      //I2C transaction abort
+#define I2C_A_ADC_LAST         0x00000400      //I2C last transaction
+#define I2C_A_ADC_BYTE         0x00000800      //I2C one byte mode
+
+#define I2C_D_ADC_REG_MASK     0xfe000000      //ADC address register 
+#define I2C_D_ADC_DAT_MASK     0x01ff0000      //ADC data register
+
+#define ADC_TIMEOUT            0x00000007      //ADC Timeout Clock Disable
+#define ADC_IFC_CTRL           0x0000000b      //ADC Interface Control
+#define ADC_MASTER             0x0000000c      //ADC Master Mode Control
+#define ADC_POWER              0x0000000d      //ADC PowerDown Control
+#define ADC_ATTEN_ADCL         0x0000000e      //ADC Attenuation ADCL
+#define ADC_ATTEN_ADCR         0x0000000f      //ADC Attenuation ADCR
+#define ADC_ALC_CTRL1          0x00000010      //ADC ALC Control 1
+#define ADC_ALC_CTRL2          0x00000011      //ADC ALC Control 2
+#define ADC_ALC_CTRL3          0x00000012      //ADC ALC Control 3
+#define ADC_NOISE_CTRL         0x00000013      //ADC Noise Gate Control
+#define ADC_LIMIT_CTRL         0x00000014      //ADC Limiter Control
+#define ADC_MUX                        0x00000015      //ADC Mux offset
+
+#if 0
+/* FIXME: Not tested yet. */
+#define ADC_GAIN_MASK          0x000000ff      //Mask for ADC Gain
+#define ADC_ZERODB             0x000000cf      //Value to set ADC to 0dB
+#define ADC_MUTE_MASK          0x000000c0      //Mask for ADC mute
+#define ADC_MUTE               0x000000c0      //Value to mute ADC
+#define ADC_OSR                        0x00000008      //Mask for ADC oversample rate select
+#define ADC_TIMEOUT_DISABLE    0x00000008      //Value and mask to disable Timeout clock
+#define ADC_HPF_DISABLE                0x00000100      //Value and mask to disable High pass filter
+#define ADC_TRANWIN_MASK       0x00000070      //Mask for Length of Transient Window
+#endif
+
+#define ADC_MUX_MASK           0x0000000f      //Mask for ADC Mux
+#define ADC_MUX_MIC            0x00000002      //Value to select Mic at ADC Mux
+#define ADC_MUX_LINEIN         0x00000004      //Value to select LineIn at ADC Mux
+#define ADC_MUX_PHONE          0x00000001      //Value to select TAD at ADC Mux (Not used)
+#define ADC_MUX_AUX            0x00000008      //Value to select Aux at ADC Mux
 
 #define SET_CHANNEL 0  /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
 #define PCM_FRONT_CHANNEL 0
@@ -508,9 +557,18 @@ struct snd_ca0106_pcm {
        unsigned short running;
 };
 
+typedef struct {
+        u32 serial;
+        char * name;
+        int ac97;
+       int gpio_type;
+       int i2c_adc;
+} ca0106_details_t;
+
 // definition of the chip-specific record
 struct snd_ca0106 {
        snd_card_t *card;
+       ca0106_details_t *details;
        struct pci_dev *pci;
 
        unsigned long port;
@@ -531,6 +589,7 @@ struct snd_ca0106 {
        u32 spdif_bits[4];             /* s/pdif out setup */
        int spdif_enable;
        int capture_source;
+       int capture_mic_line_in;
 
        struct snd_dma_buffer buffer;
 };
@@ -547,3 +606,6 @@ void snd_ca0106_ptr_write(ca0106_t *emu,
                                   unsigned int chn, 
                                   unsigned int data);
 
+int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value);
+
+
index 82533b45bc8cd5afed5f515ac124c7a2f10452b4..95c289284267fdf0a33edfd507e5b7277826eac9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.22
+ *  Version: 0.0.23
  *
  *  FEATURES currently supported:
  *    Front, Rear and Center/LFE.
@@ -77,6 +77,8 @@
  *    Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.)
  *  0.0.22
  *    Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
+ *  0.0.23
+ *    Implement support for Line-in capture on SB Live 24bit.
  *
  *  BUGS:
  *    Some stability problems when unloading the snd-ca0106 kernel module.
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
@@ -161,18 +164,32 @@ MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
 
 #include "ca0106.h"
 
-typedef struct {
-       u32 serial;
-       char * name;
-} ca0106_names_t;
-
-static ca0106_names_t ca0106_chip_names[] = {
-        { 0x10021102, "AudigyLS [SB0310]"} , 
-        { 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */
-        { 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
-        { 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97.  */
-        { 0x10091462, "MSI K8N Diamond MB [SB0438]"}, /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
-        { 0, "AudigyLS [Unknown]" }
+static ca0106_details_t ca0106_chip_details[] = {
+        /* AudigyLS[SB0310] */
+        { .serial = 0x10021102,
+          .name   = "AudigyLS [SB0310]",
+          .ac97   = 1 } , 
+        /* Unknown AudigyLS that also says SB0310 on it */
+        { .serial = 0x10051102,
+          .name   = "AudigyLS [SB0310b]",
+          .ac97   = 1 } ,
+        /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
+        { .serial = 0x10061102,
+          .name   = "Live! 7.1 24bit [SB0410]",
+          .gpio_type = 1,
+          .i2c_adc = 1 } ,
+        /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97.  */
+        { .serial = 0x10071102,
+          .name   = "Live! 7.1 24bit [SB0413]",
+          .gpio_type = 1,
+          .i2c_adc = 1 } ,
+        /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
+        { .serial = 0x10091462,
+          .name   = "MSI K8N Diamond MB [SB0438]",
+          .gpio_type = 1,
+          .i2c_adc = 1 } ,
+        { .serial = 0,
+          .name   = "AudigyLS [Unknown]" }
 };
 
 /* hardware definition */
@@ -200,10 +217,10 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = {
                                 SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID),
-       .formats =              SNDRV_PCM_FMTBIT_S16_LE,
-       .rates =                SNDRV_PCM_RATE_48000,
-       .rate_min =             48000,
-       .rate_max =             48000,
+       .formats =              SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+       .rates =                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+       .rate_min =             44100,
+       .rate_max =             192000,
        .channels_min =         2,
        .channels_max =         2,
        .buffer_bytes_max =     ((65536 - 64) * 8),
@@ -246,6 +263,62 @@ void snd_ca0106_ptr_write(ca0106_t *emu,
        spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
+int snd_ca0106_i2c_write(ca0106_t *emu,
+                               u32 reg,
+                               u32 value)
+{
+       u32 tmp;
+       int timeout=0;
+       int status;
+       int retry;
+       if ((reg > 0x7f) || (value > 0x1ff))
+       {
+                snd_printk("i2c_write: invalid values.\n");
+               return -EINVAL;
+       }
+
+       tmp = reg << 25 | value << 16;
+       /* Not sure what this I2C channel controls. */
+       /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
+
+       /* This controls the I2C connected to the WM8775 ADC Codec */
+       snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
+
+       for(retry=0;retry<10;retry++)
+       {
+               /* Send the data to i2c */
+               tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
+               tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
+               tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
+               snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
+
+               /* Wait till the transaction ends */
+               while(1)
+               {
+                       status = snd_ca0106_ptr_read(emu, I2C_A, 0);
+                       //snd_printk("I2C:status=0x%x\n", status);
+                       timeout++;
+                       if((status & I2C_A_ADC_START)==0)
+                               break;
+
+                       if(timeout>1000)
+                               break;
+               }
+               //Read back and see if the transaction is successful
+               if((status & I2C_A_ADC_ABORT)==0)
+                       break;
+       }
+
+       if(retry==10)
+       {
+                snd_printk("Writing to ADC failed!\n");
+               return -EINVAL;
+       }
+    
+       return 0;
+}
+
+
 static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
 {
        unsigned long flags;
@@ -259,11 +332,7 @@ static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
 
 static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-       ca0106_pcm_t *epcm = runtime->private_data;
-  
-       if (epcm) {
-               kfree(epcm);
-       }
+       kfree(runtime->private_data);
 }
 
 /* open_playback callback */
@@ -538,6 +607,61 @@ static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        ca0106_pcm_t *epcm = runtime->private_data;
        int channel = epcm->channel_id;
+       u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
+       u32 hcfg_set = 0x00000000;
+       u32 hcfg;
+       u32 over_sampling=0x2;
+       u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
+       u32 reg71_set = 0;
+       u32 reg71;
+       
+        //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
+        //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
+       //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+       /* reg71 controls ADC rate. */
+       switch (runtime->rate) {
+       case 44100:
+               reg71_set = 0x00004000;
+               break;
+        case 48000:
+               reg71_set = 0; 
+               break;
+       case 96000:
+               reg71_set = 0x00008000;
+               over_sampling=0xa;
+               break;
+       case 192000:
+               reg71_set = 0x0000c000; 
+               over_sampling=0xa;
+               break;
+       default:
+               reg71_set = 0; 
+               break;
+       }
+       /* Format is a global setting */
+       /* FIXME: Only let the first channel accessed set this. */
+       switch (runtime->format) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               hcfg_set = 0;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               hcfg_set = HCFG_CAPTURE_S32_LE;
+               break;
+       default:
+               hcfg_set = 0;
+               break;
+       }
+       hcfg = inl(emu->port + HCFG) ;
+       hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
+       outl(hcfg, emu->port + HCFG);
+       reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
+       reg71 = (reg71 & ~reg71_mask) | reg71_set;
+       snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
+        if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
+               snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
+       }
+
+
         //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size,  frames_to_bytes(runtime, 1));
        snd_ca0106_ptr_write(emu, 0x13, channel, 0);
        snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
@@ -810,6 +934,7 @@ static int snd_ca0106_ac97(ca0106_t *chip)
 
        memset(&ac97, 0, sizeof(ac97));
        ac97.private_data = chip;
+       ac97.scaps = AC97_SCAP_NO_SPDIF;
        return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
 }
 
@@ -993,6 +1118,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
                                         ca0106_t **rchip)
 {
        ca0106_t *chip;
+       ca0106_details_t *c;
        int err;
        int ch;
        static snd_device_ops_t ops = {
@@ -1003,8 +1129,8 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
   
        if ((err = pci_enable_device(pci)) < 0)
                return err;
-       if (pci_set_dma_mask(pci, 0xffffffffUL) < 0 ||
-           pci_set_consistent_dma_mask(pci, 0xffffffffUL) < 0) {
+       if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
+           pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
                printk(KERN_ERR "error to set 32bit mask DMA\n");
                pci_disable_device(pci);
                return -ENXIO;
@@ -1054,6 +1180,15 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
        printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
               chip->revision, chip->serial);
 #endif
+       strcpy(card->driver, "CA0106");
+       strcpy(card->shortname, "CA0106");
+
+       for (c=ca0106_chip_details; c->serial; c++) {
+               if (c->serial == chip->serial) break;
+       }
+       chip->details = c;
+       sprintf(card->longname, "%s at 0x%lx irq %i",
+               c->name, chip->port, chip->irq);
 
        outl(0, chip->port + INTE);
 
@@ -1113,7 +1248,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
        //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
        /* Analog or Digital output */
        snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
-       snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000b0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers */
+       snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
        chip->spdif_enable = 0; /* Set digital SPDIF output off */
        chip->capture_source = 3; /* Set CAPTURE_SOURCE */
        //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
@@ -1138,13 +1273,11 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
         snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
        chip->capture_source = 3; /* Set CAPTURE_SOURCE */
 
-        if ((chip->serial == 0x10061102) || 
-           (chip->serial == 0x10071102) ||
-           (chip->serial == 0x10091462)) { /* The SB0410 and SB0413 use GPIO differently. */
+        if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
                /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
                outl(0x0, chip->port+GPIO);
                //outl(0x00f0e000, chip->port+GPIO); /* Analog */
-               outl(0x005f4300, chip->port+GPIO); /* Analog */
+               outl(0x005f5301, chip->port+GPIO); /* Analog */
        } else {
                outl(0x0, chip->port+GPIO);
                outl(0x005f03a3, chip->port+GPIO); /* Analog */
@@ -1157,6 +1290,10 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
        //outl(0x00000009, chip->port+HCFG);
        outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
 
+        if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
+               snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
+       }
+
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
                                  chip, &ops)) < 0) {
                snd_ca0106_free(chip);
@@ -1172,7 +1309,6 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
        static int dev;
        snd_card_t *card;
        ca0106_t *chip;
-       ca0106_names_t *c;
        int err;
 
        if (dev >= SNDRV_CARDS)
@@ -1207,9 +1343,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
                snd_card_free(card);
                return err;
        }
-        if ((chip->serial != 0x10061102) && 
-           (chip->serial != 0x10071102) && 
-           (chip->serial != 0x10091462) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */
+        if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
                if ((err = snd_ca0106_ac97(chip)) < 0) {
                        snd_card_free(card);
                        return err;
@@ -1222,15 +1356,6 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
 
        snd_ca0106_proc_init(chip);
 
-       strcpy(card->driver, "CA0106");
-       strcpy(card->shortname, "CA0106");
-
-       for (c=ca0106_chip_names; c->serial; c++) {
-               if (c->serial == chip->serial) break;
-       }
-       sprintf(card->longname, "%s at 0x%lx irq %i",
-               c->name, chip->port, chip->irq);
-
        if ((err = snd_card_register(card)) < 0) {
                snd_card_free(card);
                return err;
@@ -1267,7 +1392,7 @@ static int __init alsa_card_ca0106_init(void)
 {
        int err;
 
-       if ((err = pci_module_init(&driver)) > 0)
+       if ((err = pci_register_driver(&driver)) > 0)
                return err;
 
        return 0;
index 97bed1b0899d43dee4bb0771bf3492edcf605739..0e5e9ce0ff28be76943cf8d9809a0028cbaa9bfe 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.16
+ *  Version: 0.0.17
  *
  *  FEATURES currently supported:
  *    See ca0106_main.c for features.
@@ -37,6 +37,8 @@
  *    Separated ca0106.c into separate functional .c files.
  *  0.0.16
  *    Modified Copyright message.
+ *  0.0.17
+ *    Implement Mic and Line in Capture.
  *
  *  This code was initally based on code from ALSA's emu10k1x.c which is:
  *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
@@ -113,7 +115,7 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol,
                } else {
                        /* Analog */
                        snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
-                       snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000b0000);
+                       snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
                        snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
                                snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
                        mask = inl(emu->port + GPIO) | 0x101;
@@ -183,6 +185,65 @@ static snd_kcontrol_new_t snd_ca0106_capture_source __devinitdata =
        .put =          snd_ca0106_capture_source_put
 };
 
+static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[2] = { "Line in", "Mic in" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       if (uinfo->value.enumerated.item > 1)
+                uinfo->value.enumerated.item = 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_ca0106_capture_mic_line_in_get(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+       ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
+       return 0;
+}
+
+static int snd_ca0106_capture_mic_line_in_put(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+       ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       int change = 0;
+       u32 tmp;
+
+       val = ucontrol->value.enumerated.item[0] ;
+       change = (emu->capture_mic_line_in != val);
+       if (change) {
+               emu->capture_mic_line_in = val;
+               if (val) {
+                       snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
+                       tmp = inl(emu->port+GPIO) & ~0x400;
+                       tmp = tmp | 0x400;
+                       outl(tmp, emu->port+GPIO);
+                       snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
+               } else {
+                       snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
+                       tmp = inl(emu->port+GPIO) & ~0x400;
+                       outl(tmp, emu->port+GPIO);
+                       snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
+               }
+       }
+        return change;
+}
+
+static snd_kcontrol_new_t snd_ca0106_capture_mic_line_in __devinitdata =
+{
+       .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name =         "Mic/Line in Capture",
+       .info =         snd_ca0106_capture_mic_line_in_info,
+       .get =          snd_ca0106_capture_mic_line_in_get,
+       .put =          snd_ca0106_capture_mic_line_in_put
+};
+
 static int snd_ca0106_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -437,7 +498,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
 static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "Analog Unknown Volume",
+        .name =         "Analog Side Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_analog_unknown,
         .put =          snd_ca0106_volume_put_analog_unknown
@@ -620,10 +681,11 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu)
                return -ENOMEM;
        if ((err = snd_ctl_add(card, kctl)))
                return err;
-       if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) {
-               /* already defined by ac97, remove it */
-               /* FIXME: or do we need both controls? */
-               remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT));
+       if (emu->details->i2c_adc == 1) {
+               if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL)
+                       return -ENOMEM;
+               if ((err = snd_ctl_add(card, kctl)))
+                       return err;
        }
        if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL)
                return -ENOMEM;
index afb711421e479e7e70c4fa95e90607cab1a32f46..1c9cc821d1b96c3cb60ff359fcad82aa1773a790 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.17
+ *  Version: 0.0.18
  *
  *  FEATURES currently supported:
  *    See ca0106_main.c for features.
@@ -39,7 +39,9 @@
  *    Modified Copyright message.
  *  0.0.17
  *    Add iec958 file in proc file system to show status of SPDIF in.
- *    
+ *  0.0.18
+ *    Implement support for Line-in capture on SB Live 24bit.
+ *
  *  This code was initally based on code from ALSA's emu10k1x.c which is:
  *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
  *
@@ -95,7 +97,7 @@ static struct snd_ca0106_category_str snd_ca0106_con_category[] = {
 };
 
 
-void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
+static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
 {
        int i;
        u32 status[4];
@@ -407,6 +409,20 @@ static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry,
         }
 }
 
+static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry, 
+                                      snd_info_buffer_t * buffer)
+{
+       ca0106_t *emu = entry->private_data;
+        char line[64];
+        unsigned int reg, val;
+        while (!snd_info_get_line(buffer, line, sizeof(line))) {
+                if (sscanf(line, "%x %x", &reg, &val) != 2)
+                        continue;
+                if ((reg <= 0x7f) || (val <= 0x1ff)) {
+                        snd_ca0106_i2c_write(emu, reg, val);
+               }
+        }
+}
 
 int __devinit snd_ca0106_proc_init(ca0106_t * emu)
 {
@@ -418,6 +434,7 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu)
                snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32);
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_ca0106_proc_reg_write32;
+               entry->mode |= S_IWUSR;
        }
        if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry))
                snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16);
@@ -427,6 +444,14 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu)
                snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1);
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_ca0106_proc_reg_write;
+               entry->mode |= S_IWUSR;
+//             entry->private_data = emu;
+       }
+       if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) {
+               snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write);
+               entry->c.text.write_size = 64;
+               entry->c.text.write = snd_ca0106_proc_i2c_write;
+               entry->mode |= S_IWUSR;
 //             entry->private_data = emu;
        }
        if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) 
index 113208fbde1bc3487063f2106cc55db578f40b47..b4503385ea69b62b9717a244bc6d9d0c571bb4e8 100644 (file)
@@ -519,40 +519,50 @@ inline static unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd)
 }
 
 /* bit operations for dword register */
-static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
 {
-       unsigned int val;
-       val = inl(cm->iobase + cmd);
+       unsigned int val, oval;
+       val = oval = inl(cm->iobase + cmd);
        val |= flag;
+       if (val == oval)
+               return 0;
        outl(val, cm->iobase + cmd);
+       return 1;
 }
 
-static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
 {
-       unsigned int val;
-       val = inl(cm->iobase + cmd);
+       unsigned int val, oval;
+       val = oval = inl(cm->iobase + cmd);
        val &= ~flag;
+       if (val == oval)
+               return 0;
        outl(val, cm->iobase + cmd);
+       return 1;
 }
 
-#if 0 // not used
 /* bit operations for byte register */
-static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
 {
-       unsigned char val;
-       val = inb(cm->iobase + cmd);
+       unsigned char val, oval;
+       val = oval = inb(cm->iobase + cmd);
        val |= flag;
+       if (val == oval)
+               return 0;
        outb(val, cm->iobase + cmd);
+       return 1;
 }
 
-static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
 {
-       unsigned char val;
-       val = inb(cm->iobase + cmd);
+       unsigned char val, oval;
+       val = oval = inb(cm->iobase + cmd);
        val &= ~flag;
+       if (val == oval)
+               return 0;
        outb(val, cm->iobase + cmd);
+       return 1;
 }
-#endif
 
 
 /*
@@ -2250,8 +2260,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever
 DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0);
 #endif
 DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0);
-DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
-DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
+// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
+// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
 // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */
 DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0);
 
@@ -2300,10 +2310,114 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
 }
 
 
+static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol,
+                                       snd_ctl_elem_info_t *uinfo)
+{
+       cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+       static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static inline unsigned int get_line_in_mode(cmipci_t *cm)
+{
+       unsigned int val;
+       if (cm->chip_version >= 39) {
+               val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL);
+               if (val & CM_LINE_AS_BASS)
+                       return 2;
+       }
+       val = snd_cmipci_read_b(cm, CM_REG_MIXER1);
+       if (val & CM_SPK4)
+               return 1;
+       return 0;
+}
+
+static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol,
+                                      snd_ctl_elem_value_t *ucontrol)
+{
+       cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+
+       spin_lock_irq(&cm->reg_lock);
+       ucontrol->value.enumerated.item[0] = get_line_in_mode(cm);
+       spin_unlock_irq(&cm->reg_lock);
+       return 0;
+}
+
+static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol,
+                                      snd_ctl_elem_value_t *ucontrol)
+{
+       cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+       int change;
+
+       spin_lock_irq(&cm->reg_lock);
+       if (ucontrol->value.enumerated.item[0] == 2)
+               change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
+       else
+               change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
+       if (ucontrol->value.enumerated.item[0] == 1)
+               change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
+       else
+               change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
+       spin_unlock_irq(&cm->reg_lock);
+       return change;
+}
+
+static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol,
+                                      snd_ctl_elem_info_t *uinfo)
+{
+       static char *texts[2] = { "Mic-In", "Center/LFE Output" };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol,
+                                     snd_ctl_elem_value_t *ucontrol)
+{
+       cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+       /* same bit as spdi_phase */
+       spin_lock_irq(&cm->reg_lock);
+       ucontrol->value.enumerated.item[0] = 
+               (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0;
+       spin_unlock_irq(&cm->reg_lock);
+       return 0;
+}
+
+static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol,
+                                     snd_ctl_elem_value_t *ucontrol)
+{
+       cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+       int change;
+
+       spin_lock_irq(&cm->reg_lock);
+       if (ucontrol->value.enumerated.item[0])
+               change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE);
+       else
+               change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE);
+       spin_unlock_irq(&cm->reg_lock);
+       return change;
+}
+
 /* both for CM8338/8738 */
 static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = {
        DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
-       DEFINE_MIXER_SWITCH("Line-In As Rear", line_rear),
+       {
+               .name = "Line-In Mode",
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .info = snd_cmipci_line_in_mode_info,
+               .get = snd_cmipci_line_in_mode_get,
+               .put = snd_cmipci_line_in_mode_put,
+       },
 };
 
 /* for non-multichannel chips */
@@ -2341,10 +2455,15 @@ static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = {
 
 /* only for model 039 or later */
 static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = {
-       DEFINE_MIXER_SWITCH("Line-In As Bass", line_bass),
        DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
        DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
-       DEFINE_MIXER_SWITCH("Mic As Center/LFE", spdi_phase), /* same bit as spdi_phase */
+       {
+               .name = "Mic-In Mode",
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .info = snd_cmipci_mic_in_mode_info,
+               .get = snd_cmipci_mic_in_mode_get,
+               .put = snd_cmipci_mic_in_mode_put,
+       }
 };
 
 /* card control switches */
@@ -2944,7 +3063,7 @@ static struct pci_driver driver = {
        
 static int __init alsa_card_cmipci_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_cmipci_exit(void)
index d7e06b3caf973bae1af659f170dacbca38ccf438..b6e1854e938980e4678cdb89da4da1d3cd2f9b48 100644 (file)
@@ -206,7 +206,10 @@ MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
 
 #define BA0_PMCS               0x0344  /* Power Management Control/Status */
 #define BA0_CWPR               0x03e0  /* Configuration Write Protect */
+
 #define BA0_EPPMC              0x03e4  /* Extended PCI Power Management Control */
+#define BA0_EPPMC_FPDN         (1<<14) /* Full Power DowN */
+
 #define BA0_GPIOR              0x03e8  /* GPIO Pin Interface Register */
 
 #define BA0_SPMC               0x03ec  /* Serial Port Power Management Control (& ASDIN2 enable) */
@@ -1461,6 +1464,11 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
        int timeout;
        int retry_count = 2;
 
+       /* Having EPPMC.FPDN=1 prevent proper chip initialisation */
+       tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC);
+       if (tmp & BA0_EPPMC_FPDN)
+               snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN);
+
       __retry:
        tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
        if (tmp != BA0_CFLR_DEFAULT) {
@@ -2124,7 +2132,7 @@ static struct pci_driver driver = {
        
 static int __init alsa_card_cs4281_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_cs4281_exit(void)
index 25d6466a867c638ea2d5edd93a1cf45d663ece98..db212ecd792aac6080700f44b365c16290d6286b 100644 (file)
@@ -171,7 +171,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_cs46xx_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_cs46xx_exit(void)
index 5f2ffb7efa061dee5c256d479b178d2f8d326c0c..fd4c50c88bc996d441f1aa9eb38e4b52f8ddcc83 100644 (file)
@@ -1295,8 +1295,7 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
 
 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-       cs46xx_pcm_t * cpcm = runtime->private_data;
-       kfree(cpcm);
+       kfree(runtime->private_data);
 }
 
 static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
index 6446afe19d80cf2147424ab62bc7a4580bedd7a0..2085a998eaeb8c79a5e3d1aa9acb1f2a6101ac40 100644 (file)
@@ -228,7 +228,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_emu10k1_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_emu10k1_exit(void)
index c3c96f9f2c7fe4cd580073567b27aedca8e872aa..a341e758acde20340901f0868ab8c959e229bb6c 100644 (file)
@@ -170,7 +170,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
                        SPCS_GENERATIONSTATUS | 0x00001200 |
                        0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
 
-       if (emu->audigy && emu->revision == 4) { /* audigy2 */
+       if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
                /* Hacks for Alice3 to work independent of haP16V driver */
                u32 tmp;
 
@@ -189,7 +189,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
                /* Enabled Phased (8-channel) P16V playback */
                outl(0x0201, emu->port + HCFG2);
                /* Set playback routing. */
-               snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4);
+               snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4);
        }
        if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */
                /* Hacks for Alice3 to work independent of haP16V driver */
@@ -600,7 +600,7 @@ static int snd_emu10k1_free(emu10k1_t *emu)
        if (emu->port)
                pci_release_regions(emu->pci);
        pci_disable_device(emu->pci);
-       if (emu->audigy && emu->revision == 4) /* P16V */       
+       if (emu->card_capabilities->ca0151_chip) /* P16V */     
                snd_p16v_free(emu);
        kfree(emu);
        return 0;
@@ -612,21 +612,24 @@ static int snd_emu10k1_dev_free(snd_device_t *device)
        return snd_emu10k1_free(emu);
 }
 
-/* vendor, device, subsystem, emu10k1_chip, emu10k2_chip, ca0102_chip, ca0108_chip, ca0151_chip, spk71, spdif_bug, ac97_chip, ecard, driver, name */
-
 static emu_chip_details_t emu_chip_details[] = {
        /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
        {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
         .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", 
+        .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0108_chip = 1,
-        .spk71 = 1} ,
+        .spk71 = 1,
+        .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0008, 
         .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", 
+        .id = "Audigy2",
         .emu10k2_chip = 1,
-        .ca0108_chip = 1} ,
+        .ca0108_chip = 1,
+        .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
         .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", 
+        .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
         .ca0151_chip = 1,
@@ -635,6 +638,7 @@ static emu_chip_details_t emu_chip_details[] = {
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
         .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", 
+        .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
         .ca0151_chip = 1,
@@ -643,6 +647,7 @@ static emu_chip_details_t emu_chip_details[] = {
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
         .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", 
+        .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
         .ca0151_chip = 1,
@@ -651,6 +656,7 @@ static emu_chip_details_t emu_chip_details[] = {
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
         .driver = "Audigy2", .name = "Audigy 2 [SB0240]", 
+        .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
         .ca0151_chip = 1,
@@ -659,35 +665,165 @@ static emu_chip_details_t emu_chip_details[] = {
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
         .driver = "Audigy2", .name = "Audigy 2 EX [1005]", 
+        .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
         .ca0151_chip = 1,
         .spdif_bug = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
         .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", 
+        .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
         .ca0151_chip = 1,
         .spk71 = 1,
         .spdif_bug = 1,
         .ac97_chip = 1} ,
+       {.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
+        .driver = "Audigy2", .name = "Audigy 2 [Unknown]",
+        .id = "Audigy2",
+        .emu10k2_chip = 1,
+        .ca0102_chip = 1,
+        .ca0151_chip = 1,
+        .spdif_bug = 1,
+        .ac97_chip = 1} ,
+       {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10020052,
+        .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", 
+        .id = "Audigy",
+        .emu10k2_chip = 1,
+        .ca0102_chip = 1,
+        .spdif_bug = 1,
+        .ac97_chip = 1} ,
+       {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102,
+        .driver = "Audigy", .name = "Audigy 1 [SB0090]", 
+        .id = "Audigy",
+        .emu10k2_chip = 1,
+        .ca0102_chip = 1,
+        .ac97_chip = 1} ,
+       {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102,
+        .driver = "Audigy", .name = "Audigy 1 [SB0090]", 
+        .id = "Audigy",
+        .emu10k2_chip = 1,
+        .ca0102_chip = 1,
+        .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004,
-        .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]", 
+        .driver = "Audigy", .name = "Audigy 1 [Unknown]", 
+        .id = "Audigy",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
-        .spdif_bug = 1} ,
+        .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
         .driver = "EMU10K1", .name = "E-mu APS [4001]", 
+        .id = "APS",
         .emu10k1_chip = 1,
         .ecard = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
+        .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
        {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
         .driver = "EMU10K1", .name = "SB Live 5.1", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
+        .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", 
+        .id = "Live",
         .emu10k1_chip = 1,
         .ac97_chip = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
+        .driver = "EMU10K1", .name = "SBLive! [CT4620]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
+        .driver = "EMU10K1", .name = "SBLive! Value [CT4670]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
+        .driver = "EMU10K1", .name = "SBLive! Value [CT4780]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
+        .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
+        .driver = "EMU10K1", .name = "SBLive! Value [CT4830]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
+        .driver = "EMU10K1", .name = "SBLive! Value [CT4831]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
+        .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
+        .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
+        .driver = "EMU10K1", .name = "SBLive! Value [CT4870]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
+        .driver = "EMU10K1", .name = "SBLive! Value [CT4871]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
+        .driver = "EMU10K1", .name = "SBLive! Value [SB0060]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
+        .driver = "EMU10K1", .name = "SBLive! Value [SB0101]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102,
+        .driver = "EMU10K1", .name = "SBLive! Value [SB0103]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
+       {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
+        .driver = "EMU10K1", .name = "SBLive! [SB0105]", 
+        .id = "Live",
+        .emu10k1_chip = 1,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
        {.vendor = 0x1102, .device = 0x0002,
         .driver = "EMU10K1", .name = "SB Live [Unknown]", 
+        .id = "Live",
         .emu10k1_chip = 1,
-        .ac97_chip = 1} ,
+        .ac97_chip = 1,
+        .sblive51 = 1} ,
        { } /* terminator */
 };
 
@@ -738,13 +874,15 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
        emu->revision = revision;
        pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
        pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
-       emu->card_type = EMU10K1_CARD_CREATIVE;
        snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
 
        for (c = emu_chip_details; c->vendor; c++) {
                if (c->vendor == pci->vendor && c->device == pci->device) {
-                       if (c->subsystem == emu->serial) break;
-                       if (c->subsystem == 0) break;
+                       if (c->subsystem && c->subsystem != emu->serial)
+                               continue;
+                       if (c->revision && c->revision != emu->revision)
+                               continue;
+                       break;
                }
        }
        if (c->vendor == 0) {
@@ -759,6 +897,23 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
        else
                snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial);
        
+       if (!*card->id && c->id) {
+               int i, n = 0;
+               strlcpy(card->id, c->id, sizeof(card->id));
+               for (;;) {
+                       for (i = 0; i < snd_ecards_limit; i++) {
+                               if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id))
+                                       break;
+                       }
+                       if (i >= snd_ecards_limit)
+                               break;
+                       n++;
+                       if (n >= SNDRV_CARDS)
+                               break;
+                       snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n);
+               }
+       }
+
        is_audigy = emu->audigy = c->emu10k2_chip;
 
        /* set the DMA transfer mask */
@@ -816,15 +971,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
 
        pci_set_master(pci);
 
-       if (c->ecard) {
-               emu->card_type = EMU10K1_CARD_EMUAPS;
-               emu->APS = 1;
-       }
-       if (! c->ac97_chip)
-               emu->no_ac97 = 1;
-       
-       emu->spk71 = c->spk71;
-       
        emu->fx8010.fxbus_mask = 0x303f;
        if (extin_mask == 0)
                extin_mask = 0x3fcf;
@@ -833,7 +979,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
        emu->fx8010.extin_mask = extin_mask;
        emu->fx8010.extout_mask = extout_mask;
 
-       if (emu->APS) {
+       if (emu->card_capabilities->ecard) {
                if ((err = snd_emu10k1_ecard_init(emu)) < 0) {
                        snd_emu10k1_free(emu);
                        return err;
index 27dfd8ddddf486d0c0832d72c6140d9274399814..e90c5ddd1d17ef0451e87010040c72bb71966ac7 100644 (file)
@@ -361,10 +361,7 @@ static void snd_emu10k1x_gpio_write(emu10k1x_t *emu, unsigned int value)
 
 static void snd_emu10k1x_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-       emu10k1x_pcm_t *epcm = runtime->private_data;
-  
-       if (epcm)
-               kfree(epcm);
+       kfree(runtime->private_data);
 }
 
 static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice)
@@ -1075,6 +1072,7 @@ static int __devinit snd_emu10k1x_proc_init(emu10k1x_t * emu)
                snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read);
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_emu10k1x_proc_reg_write;
+               entry->mode |= S_IWUSR;
                entry->private_data = emu;
        }
        
@@ -1627,7 +1625,7 @@ static int __init alsa_card_emu10k1x_init(void)
 {
        int err;
 
-       if ((err = pci_module_init(&driver)) > 0)
+       if ((err = pci_register_driver(&driver)) > 0)
                return err;
 
        return 0;
index b9fa2e887fee3003782d65140ad3650465bbc639..0529fb281125cf949d2de4ebd2163fbe71fb9d67 100644 (file)
@@ -1077,7 +1077,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
        gpr += 2;
        
        /* PCM Side Playback (independent from stereo mix) */
-       if (emu->spk71) {
+       if (emu->card_capabilities->spk71) {
                A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
                A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
                snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
@@ -1145,14 +1145,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L);
        A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R);
        snd_emu10k1_init_stereo_control(&controls[nctl++],
-                                       emu->no_ac97 ? "CD Playback Volume" : "Audigy CD Playback Volume",
+                                       emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume",
                                        gpr, 0);
        gpr += 2;
        /* Audigy CD Capture Volume */
        A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
        A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
        snd_emu10k1_init_stereo_control(&controls[nctl++],
-                                       emu->no_ac97 ? "CD Capture Volume" : "Audigy CD Capture Volume",
+                                       emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume",
                                        gpr, 0);
        gpr += 2;
 
@@ -1171,14 +1171,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L);
        A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R);
        snd_emu10k1_init_stereo_control(&controls[nctl++],
-                                       emu->no_ac97 ? "Line Playback Volume" : "Line2 Playback Volume",
+                                       emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume",
                                        gpr, 0);
        gpr += 2;
        /* Line2 Capture Volume */
        A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
        A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
        snd_emu10k1_init_stereo_control(&controls[nctl++],
-                                       emu->no_ac97 ? "Line Capture Volume" : "Line2 Capture Volume",
+                                       emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume",
                                        gpr, 0);
        gpr += 2;
         
@@ -1197,14 +1197,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L);
        A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R);
        snd_emu10k1_init_stereo_control(&controls[nctl++],
-                                       emu->no_ac97 ? "Aux Playback Volume" : "Aux2 Playback Volume",
+                                       emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume",
                                        gpr, 0);
        gpr += 2;
        /* Aux2 Capture Volume */
        A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
        A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
        snd_emu10k1_init_stereo_control(&controls[nctl++],
-                                       emu->no_ac97 ? "Aux Capture Volume" : "Aux2 Capture Volume",
+                                       emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume",
                                        gpr, 0);
        gpr += 2;
        
@@ -1232,7 +1232,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
        gpr++;
        
-       if (emu->spk71) {
+       if (emu->card_capabilities->spk71) {
                /* Stereo Mix Side Playback */
                A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
                A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
@@ -1266,7 +1266,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */
        A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
        A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */
-       if (emu->spk71) {
+       if (emu->card_capabilities->spk71) {
                A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */
                A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */
        }
@@ -1359,7 +1359,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
        A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
        A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
-       if (emu->spk71)
+       if (emu->card_capabilities->spk71)
                A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
 
        /* headphone */
@@ -1982,22 +1982,27 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
                OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
 
        /* EFX capture - capture the 16 EXTINS */
-       OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
-       OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
-       OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
-       OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
-       /* Dont connect anything to FXBUS2 1 and 2.  These are shared with 
-        * Center/LFE on the SBLive 5.1.  The kX driver only changes the 
-        * routing when it detects an SBLive 5.1.
-        *
-        * Since only 14 of the 16 EXTINs are used, this is not a big problem.  
-        * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture 
-        * 0 and 3, then the rest of the EXTINs to the corresponding FX capture 
-        * channel.
-        */
-       for (z = 4; z < 14; z++) {
-               OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+       if (emu->card_capabilities->sblive51) {
+               /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER
+                * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording.
+                *
+                * Since only 14 of the 16 EXTINs are used, this is not a big problem.  
+                * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture 
+                * 0 and 3, then the rest of the EXTINs to the corresponding FX capture 
+                * channel.  Multitrack recorders will still see the center/lfe output signal 
+                * on the second and third channels.
+                */
+               OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
+               OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
+               OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
+               OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
+               for (z = 4; z < 14; z++)
+                       OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+       } else {
+               for (z = 0; z < 16; z++)
+                       OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
        }
+           
 
        if (gpr > tmp) {
                snd_BUG();
@@ -2128,7 +2133,6 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
        int res;
 
        memset(info, 0, sizeof(info));
-       info->card = emu->card_type;
        info->internal_tram_size = emu->fx8010.itram_size;
        info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
        fxbus = fxbuses;
index 044663d31aa7724d090fe791b88ff4bd6998c231..6be82c5fe138089363749889afbda70fa118b8fe 100644 (file)
@@ -68,6 +68,7 @@ static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol,
        return 0;
 }
 
+#if 0
 static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
        static char *texts[] = {"44100", "48000", "96000"};
@@ -152,6 +153,7 @@ static snd_kcontrol_new_t snd_audigy_spdif_output_rate =
        .get =          snd_audigy_spdif_output_rate_get,
        .put =          snd_audigy_spdif_output_rate_put
 };
+#endif
 
 static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
                                  snd_ctl_elem_value_t * ucontrol)
@@ -791,7 +793,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
                NULL
        };
 
-       if (!emu->no_ac97) {
+       if (emu->card_capabilities->ac97_chip) {
                ac97_bus_t *pbus;
                ac97_template_t ac97;
                static ac97_bus_ops_t ops = {
@@ -833,7 +835,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
                for (; *c; c++)
                        remove_ctl(card, *c);
        } else {
-               if (emu->APS)
+               if (emu->card_capabilities->ecard)
                        strcpy(emu->card->mixername, "EMU APS");
                else if (emu->audigy)
                        strcpy(emu->card->mixername, "SB Audigy");
@@ -918,7 +920,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
                mix->attn[0] = 0xffff;
        }
        
-       if (! emu->APS) { /* FIXME: APS has these controls? */
+       if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
                /* sb live! and audigy */
                if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
                        return -ENOMEM;
@@ -935,18 +937,20 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
                        return -ENOMEM;
                if ((err = snd_ctl_add(card, kctl)))
                        return err;
+#if 0
                if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
                        return -ENOMEM;
                if ((err = snd_ctl_add(card, kctl)))
                        return err;
-       } else if (! emu->APS) {
+#endif
+       } else if (! emu->card_capabilities->ecard) {
                /* sb live! */
                if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
                        return -ENOMEM;
                if ((err = snd_ctl_add(card, kctl)))
                        return err;
        }
-       if (emu->audigy && emu->revision == 4) { /* P16V */
+       if (emu->card_capabilities->ca0151_chip) { /* P16V */
                if ((err = snd_p16v_mixer(emu)))
                        return err;
        }
index d1c2a02c486bcbcb466062d4453c13a364b66231..520b99af5f550d0429ef030c8c90c0d8027c0171 100644 (file)
@@ -262,7 +262,7 @@ static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
  *
  * returns: cache invalidate size in samples
  */
-static int inline emu10k1_ccis(int stereo, int w_16)
+static inline int emu10k1_ccis(int stereo, int w_16)
 {
        if (w_16) {
                return stereo ? 24 : 26;
@@ -991,9 +991,7 @@ static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activa
 
 static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-       emu10k1_pcm_t *epcm = runtime->private_data;
-
-       kfree(epcm);
+       kfree(runtime->private_data);
 }
 
 static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
index d990d5eb45a811df59db01e98ba42e3b35355c53..cc22707c91fae86b4cda85809c250311b7c97269 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <sound/core.h>
 #include <sound/emu10k1.h>
+#include "p16v.h"
 
 static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
                                          snd_info_buffer_t * buffer,
@@ -44,28 +45,34 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
        unsigned int status, rate = 0;
        
        status = snd_emu10k1_ptr_read(emu, status_reg, 0);
-       if (rate_reg > 0)
-               rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
 
        snd_iprintf(buffer, "\n%s\n", title);
 
-       snd_iprintf(buffer, "Professional Mode     : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
-       snd_iprintf(buffer, "Not Audio Data        : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
-       snd_iprintf(buffer, "Copyright             : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
-       snd_iprintf(buffer, "Emphasis              : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
-       snd_iprintf(buffer, "Mode                  : %i\n", (status & SPCS_MODEMASK) >> 6);
-       snd_iprintf(buffer, "Category Code         : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
-       snd_iprintf(buffer, "Generation Status     : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
-       snd_iprintf(buffer, "Source Mask           : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
-       snd_iprintf(buffer, "Channel Number        : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
-       snd_iprintf(buffer, "Sample Rate           : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
-       snd_iprintf(buffer, "Clock Accuracy        : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);
-
-       if (rate_reg > 0) {
-               snd_iprintf(buffer, "S/PDIF Locked         : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
-               snd_iprintf(buffer, "Rate Locked           : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
-               snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", rate & SRCS_ESTSAMPLERATE);
+       if (status != 0xffffffff) {
+               snd_iprintf(buffer, "Professional Mode     : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
+               snd_iprintf(buffer, "Not Audio Data        : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
+               snd_iprintf(buffer, "Copyright             : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
+               snd_iprintf(buffer, "Emphasis              : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
+               snd_iprintf(buffer, "Mode                  : %i\n", (status & SPCS_MODEMASK) >> 6);
+               snd_iprintf(buffer, "Category Code         : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
+               snd_iprintf(buffer, "Generation Status     : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
+               snd_iprintf(buffer, "Source Mask           : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
+               snd_iprintf(buffer, "Channel Number        : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
+               snd_iprintf(buffer, "Sample Rate           : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
+               snd_iprintf(buffer, "Clock Accuracy        : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);
+
+               if (rate_reg > 0) {
+                       rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
+                       snd_iprintf(buffer, "S/PDIF Valid          : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off");
+                       snd_iprintf(buffer, "S/PDIF Locked         : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
+                       snd_iprintf(buffer, "Rate Locked           : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
+                       /* From ((Rate * 48000 ) / 262144); */
+                       snd_iprintf(buffer, "Estimated Sample Rate : %d\n", ((rate & 0xFFFFF ) * 375) >> 11); 
+               }
+       } else {
+               snd_iprintf(buffer, "No signal detected.\n");
        }
+
 }
 
 static void snd_emu10k1_proc_read(snd_info_entry_t *entry, 
@@ -182,7 +189,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
        
        snd_iprintf(buffer, "EMU10K1\n\n");
        snd_iprintf(buffer, "Card                  : %s\n",
-                   emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
+                   emu->audigy ? "Audigy" : (emu->card_capabilities->ecard ? "EMU APS" : "Creative"));
        snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
        snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2);
        snd_iprintf(buffer, "\n");
@@ -223,15 +230,35 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
        snd_iprintf(buffer, "\nAll FX Outputs        :\n");
        for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++)
                snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
-       snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1);
-       snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1);
-       snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 2/3", SPCS2, -1);
-       snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF", CDCS, CDSRCS);
-       snd_emu10k1_proc_spdif_status(emu, buffer, "General purpose S/PDIF", GPSCS, GPSRCS);
+}
+
+static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry, 
+                                 snd_info_buffer_t * buffer)
+{
+       emu10k1_t *emu = entry->private_data;
+       snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
+       snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
+#if 0
        val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0);
        snd_iprintf(buffer, "\nZoomed Video\n");
        snd_iprintf(buffer, "Rate Locked           : %s\n", val & SRCS_RATELOCKED ? "on" : "off");
        snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE);
+#endif
+}
+
+static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry, 
+                                 snd_info_buffer_t * buffer)
+{
+       static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 };
+       emu10k1_t *emu = entry->private_data;
+       unsigned int val, tmp, n;
+       val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
+       tmp = (val >> 16) & 0x8;
+       for (n=0;n<4;n++) {
+               tmp = val >> (16 + (n*4));
+               if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
+               else snd_iprintf(buffer, "Channel %d: No input\n", n);
+       }
 }
 
 static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, 
@@ -500,32 +527,46 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
                snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read);
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_emu_proc_io_reg_write;
+               entry->mode |= S_IWUSR;
        }
        if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
                snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a);
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_emu_proc_ptr_reg_write00;
+               entry->mode |= S_IWUSR;
        }
        if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
                snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b);
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_emu_proc_ptr_reg_write00;
+               entry->mode |= S_IWUSR;
        }
        if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
                snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a);
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_emu_proc_ptr_reg_write20;
+               entry->mode |= S_IWUSR;
        }
        if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
                snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b);
                entry->c.text.write_size = 64;
                entry->c.text.write = snd_emu_proc_ptr_reg_write20;
+               entry->mode |= S_IWUSR;
        }
 #endif
        
        if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
                snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read);
 
+       if (emu->card_capabilities->emu10k2_chip) {
+               if (! snd_card_proc_new(emu->card, "spdif-in", &entry))
+                       snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read);
+       }
+       if (emu->card_capabilities->ca0151_chip) {
+               if (! snd_card_proc_new(emu->card, "capture-rates", &entry))
+                       snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read);
+       }
+
        if (! snd_card_proc_new(emu->card, "voices", &entry))
                snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
 
index b81a7cafff39e5d1d6bf2dd3185b86e8bbc512e5..cd8460d56752d4edfb53a5415111835b7787b5e9 100644 (file)
@@ -37,7 +37,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        int handled = 0;
 
        while ((status = inl(emu->port + IPR)) != 0) {
-               // printk("irq - status = 0x%x\n", status);
+               //printk("emu10k1 irq - status = 0x%x\n", status);
                orig_status = status;
                handled = 1;
                if (status & IPR_PCIERROR) {
@@ -147,9 +147,36 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
                        status &= ~IPR_FXDSP;
                }
+               if (status & IPR_P16V) {
+                       while ((status2 = inl(emu->port + IPR2)) != 0) {
+                               u32 mask = INTE2_PLAYBACK_CH_0_LOOP;  /* Full Loop */
+                               emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
+                               emu10k1_voice_t *cvoice = &(emu->p16v_capture_voice);
+
+                               //printk(KERN_INFO "status2=0x%x\n", status2);
+                               orig_status2 = status2;
+                               if(status2 & mask) {
+                                       if(pvoice->use) {
+                                               snd_pcm_period_elapsed(pvoice->epcm->substream);
+                                       } else { 
+                                               snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
+                                       }
+                               }
+                               if(status2 & 0x110000) {
+                                       //printk(KERN_INFO "capture int found\n");
+                                       if(cvoice->use) {
+                                               //printk(KERN_INFO "capture period_elapsed\n");
+                                               snd_pcm_period_elapsed(cvoice->epcm->substream);
+                                       }
+                               }
+                               outl(orig_status2, emu->port + IPR2); /* ack all */
+                       }
+                       status &= ~IPR_P16V;
+               }
+
                if (status) {
                        unsigned int bits;
-                       //snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
+                       snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
                        //make sure any interrupts we don't handle are disabled:
                        bits = INTE_FXDSPENABLE |
                                INTE_PCIERRORENABLE |
@@ -170,20 +197,5 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                }
                outl(orig_status, emu->port + IPR); /* ack all */
        }
-       if (emu->audigy && emu->revision == 4) { /* P16V */     
-               while ((status2 = inl(emu->port + IPR2)) != 0) {
-                       u32 mask = INTE2_PLAYBACK_CH_0_LOOP;  /* Full Loop */
-                       emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
-                       orig_status2 = status2;
-                       if(status2 & mask) {
-                               if(pvoice->use) {
-                                       snd_pcm_period_elapsed(pvoice->epcm->substream);
-                               } else { 
-                                       snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
-                               }
-                       }
-                       outl(orig_status2, emu->port + IPR2); /* ack all */
-               }
-       }
        return IRQ_RETVAL(handled);
 }
index d03cb2fefc9e2adb5bf69fc26907795ddb4a796a..98f980189892b1cc5dae7e0446150b390ea32495 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver p16v chips
- *  Version: 0.22
+ *  Version: 0.25
  *
  *  FEATURES currently supported:
  *    Output fixed at S32_LE, 2 channel to hw:0,0
  *    Integrated with snd-emu10k1 driver.
  *  0.22
  *    Removed #if 0 ... #endif
- *
+ *  0.23
+ *    Implement different capture rates.
+ *  0.24
+ *    Implement different capture source channels.
+ *    e.g. When HD Capture source is set to SPDIF,
+ *    setting HD Capture channel to 0 captures from CDROM digital input.
+ *    setting HD Capture channel to 1 captures from SPDIF in.
+ *  0.25
+ *    Include capture buffer sizes.
  *
  *  BUGS:
  *    Some stability problems when unloading the snd-p16v kernel module.
@@ -119,22 +127,41 @@ static snd_pcm_hardware_t snd_p16v_playback_hw = {
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID),
        .formats =              SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
-       .rates =                SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 ,
-       .rate_min =             48000,
+       .rates =                SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, 
+       .rate_min =             44100,
        .rate_max =             192000,
        .channels_min =         8, 
        .channels_max =         8,
-       .buffer_bytes_max =     (32*1024),
+       .buffer_bytes_max =     ((65536 - 64) * 8),
        .period_bytes_min =     64,
-       .period_bytes_max =     (16*1024),
+       .period_bytes_max =     (65536 - 64),
        .periods_min =          2,
        .periods_max =          8,
        .fifo_size =            0,
 };
 
+static snd_pcm_hardware_t snd_p16v_capture_hw = {
+       .info =                 (SNDRV_PCM_INFO_MMAP |
+                                SNDRV_PCM_INFO_INTERLEAVED |
+                                SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                SNDRV_PCM_INFO_MMAP_VALID),
+       .formats =              SNDRV_PCM_FMTBIT_S32_LE,
+       .rates =                SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, 
+       .rate_min =             44100,
+       .rate_max =             192000,
+       .channels_min =         2,
+       .channels_max =         2,
+       .buffer_bytes_max =     (65536 - 64),
+       .period_bytes_min =     64,
+       .period_bytes_max =     (65536 - 128) >> 1,  /* size has to be N*64 bytes */
+       .periods_min =          2,
+       .periods_max =          2,
+       .fifo_size =            0,
+};
+
 static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-       snd_pcm_t *epcm = runtime->private_data;
+       emu10k1_pcm_t *epcm = runtime->private_data;
   
        if (epcm) {
                //snd_printk("epcm free: %p\n", epcm);
@@ -178,15 +205,63 @@ static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, in
 
        return 0;
 }
+/* open_capture callback */
+static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       emu10k1_voice_t *channel = &(emu->p16v_capture_voice);
+       emu10k1_pcm_t *epcm;
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       int err;
+
+       epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+       //snd_printk("epcm kcalloc: %p\n", epcm);
+
+       if (epcm == NULL)
+               return -ENOMEM;
+       epcm->emu = emu;
+       epcm->substream = substream;
+       //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
+
+       runtime->private_data = epcm;
+       runtime->private_free = snd_p16v_pcm_free_substream;
+  
+       runtime->hw = snd_p16v_capture_hw;
+
+       channel->emu = emu;
+       channel->number = channel_id;
+
+       channel->use=1;
+       //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
+       //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
+       //channel->interrupt = snd_p16v_pcm_channel_interrupt;
+       channel->epcm=epcm;
+       if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+               return err;
+
+       return 0;
+}
+
 
 /* close callback */
 static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream)
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        //snd_pcm_runtime_t *runtime = substream->runtime;
-        //emu10k1_pcm_t *epcm = runtime->private_data;
-        emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
-/* FIXME: maybe zero others */
+       //emu10k1_pcm_t *epcm = runtime->private_data;
+       emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
+       /* FIXME: maybe zero others */
+       return 0;
+}
+
+/* close callback */
+static int snd_p16v_pcm_close_capture(snd_pcm_substream_t *substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       //snd_pcm_runtime_t *runtime = substream->runtime;
+       //emu10k1_pcm_t *epcm = runtime->private_data;
+       emu->p16v_capture_voice.use=0;
+       /* FIXME: maybe zero others */
        return 0;
 }
 
@@ -195,36 +270,55 @@ static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream)
        return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
 }
 
+static int snd_p16v_pcm_open_capture(snd_pcm_substream_t *substream)
+{
+       // Only using channel 0 for now, but the card has 2 channels.
+       return snd_p16v_pcm_open_capture_channel(substream, 0);
+}
+
 /* hw_params callback */
 static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
                                      snd_pcm_hw_params_t * hw_params)
 {
        int result;
-        //snd_printk("hw_params alloc: substream=%p\n", substream);
        result = snd_pcm_lib_malloc_pages(substream,
                                        params_buffer_bytes(hw_params));
-        //snd_printk("hw_params alloc: result=%d\n", result);
-       //dump_stack();
        return result;
 }
 
+/* hw_params callback */
+static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream,
+                                     snd_pcm_hw_params_t * hw_params)
+{
+       int result;
+       result = snd_pcm_lib_malloc_pages(substream,
+                                       params_buffer_bytes(hw_params));
+       return result;
+}
+
+
 /* hw_free callback */
 static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
 {
        int result;
-        //snd_printk("hw_params free: substream=%p\n", substream);
        result = snd_pcm_lib_free_pages(substream);
-        //snd_printk("hw_params free: result=%d\n", result);
-       //dump_stack();
        return result;
 }
 
+/* hw_free callback */
+static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream)
+{
+       int result;
+       result = snd_pcm_lib_free_pages(substream);
+       return result;
+}
+
+
 /* prepare playback callback */
 static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
 {
        emu10k1_t *emu = snd_pcm_substream_chip(substream);
        snd_pcm_runtime_t *runtime = substream->runtime;
-       //emu10k1_pcm_t *epcm = runtime->private_data;
        int channel = substream->pcm->device - emu->p16v_device_offset;
        u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
        u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
@@ -237,23 +331,21 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
        tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
         switch (runtime->rate) {
        case 44100:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */
-         break;
-       case 48000:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
          break;
        case 96000:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
          break;
        case 192000:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
          break;
+       case 48000:
        default:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
          break;
        }
        /* FIXME: Check emu->buffer.size before actually writing to it. */
-        for(i=0; i < runtime->periods; i++) {
+       for(i=0; i < runtime->periods; i++) {
                table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
                table_base[(i*2)+1]=period_size_bytes<<16;
        }
@@ -262,7 +354,8 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
        snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
        snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
        snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
-       snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+       //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+       snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
        snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
        snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
        snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
@@ -270,6 +363,41 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
        return 0;
 }
 
+/* prepare capture callback */
+static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       int channel = substream->pcm->device - emu->p16v_device_offset;
+       u32 tmp;
+       //printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size,  frames_to_bytes(runtime, 1));
+       tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
+        switch (runtime->rate) {
+       case 44100:
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800);
+         break;
+       case 96000:
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400);
+         break;
+       case 192000:
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200);
+         break;
+       case 48000:
+       default:
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000);
+         break;
+       }
+       /* FIXME: Check emu->buffer.size before actually writing to it. */
+       snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
+       snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
+       snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
+       snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
+       //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
+       //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
+
+       return 0;
+}
+
 static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb)
 {
        unsigned long flags;
@@ -345,6 +473,36 @@ static int snd_p16v_pcm_trigger_playback(snd_pcm_substream_t *substream,
        return result;
 }
 
+/* trigger_capture callback */
+static int snd_p16v_pcm_trigger_capture(snd_pcm_substream_t *substream,
+                                   int cmd)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       emu10k1_pcm_t *epcm = runtime->private_data;
+       int channel = 0;
+       int result = 0;
+       u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               snd_p16v_intr_enable(emu, inte);
+               snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
+               epcm->running = 1;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
+               snd_p16v_intr_disable(emu, inte);
+               //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
+               epcm->running = 0;
+               break;
+       default:
+               result = -EINVAL;
+               break;
+       }
+       return result;
+}
+
 /* pointer_playback callback */
 static snd_pcm_uframes_t
 snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
@@ -370,6 +528,31 @@ snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
        return ptr;
 }
 
+/* pointer_capture callback */
+static snd_pcm_uframes_t
+snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream)
+{
+       emu10k1_t *emu = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       emu10k1_pcm_t *epcm = runtime->private_data;
+       snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
+       int channel = 0;
+
+       if (!epcm->running)
+               return 0;
+
+       ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
+       ptr2 = bytes_to_frames(runtime, ptr1);
+       ptr=ptr2;
+       if (ptr >= runtime->buffer_size) {
+               ptr -= runtime->buffer_size;
+               printk("buffer capture limited!\n");
+       }
+       //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
+
+       return ptr;
+}
+
 /* operators */
 static snd_pcm_ops_t snd_p16v_playback_front_ops = {
        .open =        snd_p16v_pcm_open_playback_front,
@@ -382,6 +565,18 @@ static snd_pcm_ops_t snd_p16v_playback_front_ops = {
        .pointer =     snd_p16v_pcm_pointer_playback,
 };
 
+static snd_pcm_ops_t snd_p16v_capture_ops = {
+       .open =        snd_p16v_pcm_open_capture,
+       .close =       snd_p16v_pcm_close_capture,
+       .ioctl =       snd_pcm_lib_ioctl,
+       .hw_params =   snd_p16v_pcm_hw_params_capture,
+       .hw_free =     snd_p16v_pcm_hw_free_capture,
+       .prepare =     snd_p16v_pcm_prepare_capture,
+       .trigger =     snd_p16v_pcm_trigger_capture,
+       .pointer =     snd_p16v_pcm_pointer_capture,
+};
+
+
 int snd_p16v_free(emu10k1_t *chip)
 {
        // release the data
@@ -405,20 +600,22 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
        snd_pcm_t *pcm;
        snd_pcm_substream_t *substream;
        int err;
-        int capture=0;
+        int capture=1;
   
        //snd_printk("snd_p16v_pcm called. device=%d\n", device);
        emu->p16v_device_offset = device;
        if (rpcm)
                *rpcm = NULL;
-        //if (device == 0) capture=1; 
+
        if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
                return err;
   
        pcm->private_data = emu;
        pcm->private_free = snd_p16v_pcm_free;
-
+       // Single playback 8 channel device.
+       // Single capture 2 channel device.
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops);
 
        pcm->info_flags = 0;
        pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
@@ -431,7 +628,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
                if ((err = snd_pcm_lib_preallocate_pages(substream, 
                                                         SNDRV_DMA_TYPE_DEV, 
                                                         snd_dma_pci_data(emu->pci), 
-                                                        64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
+                                                        ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) 
                        return err;
                //snd_printk("preallocate playback substream: err=%d\n", err);
        }
@@ -442,7 +639,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
                if ((err = snd_pcm_lib_preallocate_pages(substream, 
                                                   SNDRV_DMA_TYPE_DEV, 
                                                   snd_dma_pci_data(emu->pci), 
-                                                  64*1024, 64*1024)) < 0)
+                                                  65536 - 64, 65536 - 64)) < 0)
                        return err;
                //snd_printk("preallocate capture substream: err=%d\n", err);
        }
@@ -694,6 +891,106 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear =
         .put =          snd_p16v_volume_put_spdif_rear
 };
 
+static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[8] = { "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", "CDIF", "FX", "AC97" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 8;
+       if (uinfo->value.enumerated.item > 7)
+                uinfo->value.enumerated.item = 7;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_p16v_capture_source_get(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+       emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
+       return 0;
+}
+
+static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+       emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       int change = 0;
+       u32 mask;
+       u32 source;
+
+       val = ucontrol->value.enumerated.item[0] ;
+       change = (emu->p16v_capture_source != val);
+       if (change) {
+               emu->p16v_capture_source = val;
+               source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
+               mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff;
+               snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask);
+       }
+        return change;
+}
+
+static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata =
+{
+       .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name =         "HD Capture source",
+       .info =         snd_p16v_capture_source_info,
+       .get =          snd_p16v_capture_source_get,
+       .put =          snd_p16v_capture_source_put
+};
+
+static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[4] = { "0", "1", "2", "3",  };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 4;
+       if (uinfo->value.enumerated.item > 3)
+                uinfo->value.enumerated.item = 3;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_p16v_capture_channel_get(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+       emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
+       return 0;
+}
+
+static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+       emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       int change = 0;
+       u32 tmp;
+
+       val = ucontrol->value.enumerated.item[0] ;
+       change = (emu->p16v_capture_channel != val);
+       if (change) {
+               emu->p16v_capture_channel = val;
+               tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc;
+               snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val);
+       }
+        return change;
+}
+
+static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata =
+{
+       .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name =         "HD Capture channel",
+       .info =         snd_p16v_capture_channel_info,
+       .get =          snd_p16v_capture_channel_get,
+       .put =          snd_p16v_capture_channel_put
+};
+
 int snd_p16v_mixer(emu10k1_t *emu)
 {
         int err;
@@ -731,6 +1028,14 @@ int snd_p16v_mixer(emu10k1_t *emu)
                 return -ENOMEM;
         if ((err = snd_ctl_add(card, kctl)))
                 return err;
+        if ((kctl = snd_ctl_new1(&snd_p16v_capture_source, emu)) == NULL)
+                return -ENOMEM;
+        if ((err = snd_ctl_add(card, kctl)))
+                return err;
+        if ((kctl = snd_ctl_new1(&snd_p16v_capture_channel, emu)) == NULL)
+                return -ENOMEM;
+        if ((err = snd_ctl_add(card, kctl)))
+                return err;
         return 0;
 }
 
index f910399db5c39a6eedb9e4901df6fa183fd7b68d..4e63498a58b229e9a338a7eeae40deb31d6be0f0 100644 (file)
@@ -2401,7 +2401,7 @@ static struct pci_driver driver = {
        
 static int __init alsa_card_ens137x_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ens137x_exit(void)
index b4ca8adf393c6a89d72be570607960b5fc66c879..b492777bc30ffda252e86e1677b9d77c75dd9148 100644 (file)
@@ -1761,7 +1761,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_es1938_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_es1938_exit(void)
index faf63ff19c42abf17d15f22c7223f631e2ef58f6..ea889b3113902251af682e1a7d49842276fc1eb9 100644 (file)
@@ -2559,6 +2559,7 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
        { TYPE_MAESTRO2E, 0x103c },
        { TYPE_MAESTRO2E, 0x1179 },
        { TYPE_MAESTRO2E, 0x14c0 },     /* HP omnibook 4150 */
+       { TYPE_MAESTRO2E, 0x1558 },
 };
 
 static struct ess_device_list mpu_blacklist[] __devinitdata = {
@@ -2795,7 +2796,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_es1968_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_es1968_exit(void)
index 08e7c5a296d544159e5907182f75bbeece2ad983..ff10e637a95e0ffb1b5d2882e59765ea1b557efb 100644 (file)
@@ -195,6 +195,7 @@ struct _snd_fm801 {
 
 static struct pci_device_id snd_fm801_ids[] = {
        { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, },   /* FM801 */
+       { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, },   /* Gallant Odyssey Sound 4 */
        { 0, }
 };
 
@@ -1468,7 +1469,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_fm801_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_fm801_exit(void)
index 570a59d33b4194ab1ef1327caf0d9e204096b62d..bd8cb33c4fb492fa4d2a198b3cfbe60b6983d96f 100644 (file)
@@ -1,5 +1,5 @@
 snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o
 ifdef CONFIG_PROC_FS
 snd-hda-codec-objs += hda_proc.o
 endif
index 9ed117ac0c090bd5e9948322cfe6a3204f20f0e3..e2cf0238728925bef2183adeb72bf9cb8abadb1b 100644 (file)
@@ -49,8 +49,10 @@ struct hda_vendor_id {
 /* codec vendor labels */
 static struct hda_vendor_id hda_vendor_ids[] = {
        { 0x10ec, "Realtek" },
+       { 0x11d4, "Analog Devices" },
        { 0x13f6, "C-Media" },
        { 0x434d, "C-Media" },
+       { 0x8384, "SigmaTel" },
        {} /* terminator */
 };
 
@@ -508,7 +510,7 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
        /* FIXME: support for multiple AFGs? */
        codec->afg = look_for_afg_node(codec);
        if (! codec->afg) {
-               snd_printk(KERN_ERR "hda_codec: no AFG node found\n");
+               snd_printdd("hda_codec: no AFG node found\n");
                snd_hda_codec_free(codec);
                return -ENODEV;
        }
@@ -548,6 +550,9 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
 void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
                                int channel_id, int format)
 {
+       if (! nid)
+               return;
+
        snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
                    nid, stream_tag, channel_id, format);
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
@@ -561,9 +566,10 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre
  * amp access functions
  */
 
-#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64)
+/* FIXME: more better hash key? */
+#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
 #define INFO_AMP_CAPS  (1<<0)
-#define INFO_AMP_VOL   (1<<1)
+#define INFO_AMP_VOL(ch)       (1 << (1 + (ch)))
 
 /* initialize the hash table */
 static void init_amp_hash(struct hda_codec *codec)
@@ -622,28 +628,29 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
 
 /*
  * read the current volume to info
- * if the cache exists, read from the cache.
+ * if the cache exists, read the cache value.
  */
-static void get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
+static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
                         hda_nid_t nid, int ch, int direction, int index)
 {
        u32 val, parm;
 
-       if (info->status & (INFO_AMP_VOL << ch))
-               return;
+       if (info->status & INFO_AMP_VOL(ch))
+               return info->vol[ch];
 
        parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
        parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
        parm |= index;
        val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm);
        info->vol[ch] = val & 0xff;
-       info->status |= INFO_AMP_VOL << ch;
+       info->status |= INFO_AMP_VOL(ch);
+       return info->vol[ch];
 }
 
 /*
- * write the current volume in info to the h/w
+ * write the current volume in info to the h/w and update the cache
  */
-static void put_vol_mute(struct hda_codec *codec,
+static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
                         hda_nid_t nid, int ch, int direction, int index, int val)
 {
        u32 parm;
@@ -653,30 +660,34 @@ static void put_vol_mute(struct hda_codec *codec,
        parm |= index << AC_AMP_SET_INDEX_SHIFT;
        parm |= val;
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
+       info->vol[ch] = val;
 }
 
 /*
- * read/write AMP value.  The volume is between 0 to 0x7f, 0x80 = mute bit.
+ * read AMP value.  The volume is between 0 to 0x7f, 0x80 = mute bit.
  */
-int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
+static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
 {
        struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
        if (! info)
                return 0;
-       get_vol_mute(codec, info, nid, ch, direction, index);
-       return info->vol[ch];
+       return get_vol_mute(codec, info, nid, ch, direction, index);
 }
 
-int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val)
+/*
+ * update the AMP value, mask = bit mask to set, val = the value
+ */
+static int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int mask, int val)
 {
        struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
+
        if (! info)
                return 0;
-       get_vol_mute(codec, info, nid, ch, direction, idx);
+       val &= mask;
+       val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
        if (info->vol[ch] == val && ! codec->in_resume)
                return 0;
-       put_vol_mute(codec, nid, ch, direction, idx, val);
-       info->vol[ch] = val;
+       put_vol_mute(codec, info, nid, ch, direction, idx, val);
        return 1;
 }
 
@@ -735,21 +746,15 @@ int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
        int chs = get_amp_channels(kcontrol);
        int dir = get_amp_direction(kcontrol);
        int idx = get_amp_index(kcontrol);
-       int val;
        long *valp = ucontrol->value.integer.value;
        int change = 0;
 
-       if (chs & 1) {
-               val = *valp & 0x7f;
-               val |= snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80;
-               change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
-               valp++;
-       }
-       if (chs & 2) {
-               val = *valp & 0x7f;
-               val |= snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80;
-               change |= snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
-       }
+       if (chs & 1)
+               change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
+                                                 0x7f, *valp);
+       if (chs & 2)
+               change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
+                                                  0x7f, valp[1]);
        return change;
 }
 
@@ -788,21 +793,15 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
        int chs = get_amp_channels(kcontrol);
        int dir = get_amp_direction(kcontrol);
        int idx = get_amp_index(kcontrol);
-       int val;
        long *valp = ucontrol->value.integer.value;
        int change = 0;
 
-       if (chs & 1) {
-               val = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
-               val |= *valp ? 0 : 0x80;
-               change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
-               valp++;
-       }
-       if (chs & 2) {
-               val = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
-               val |= *valp ? 0 : 0x80;
-               change = snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
-       }
+       if (chs & 1)
+               change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
+                                                 0x80, *valp ? 0 : 0x80);
+       if (chs & 2)
+               change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
+                                                  0x80, valp[1] ? 0 : 0x80);
        return change;
 }
 
@@ -1448,10 +1447,6 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream
                snd_assert(info->nid, return -EINVAL);
                info->ops.prepare = hda_pcm_default_prepare;
        }
-       if (info->ops.prepare == NULL) {
-               snd_assert(info->nid, return -EINVAL);
-               info->ops.prepare = hda_pcm_default_prepare;
-       }
        if (info->ops.cleanup == NULL) {
                snd_assert(info->nid, return -EINVAL);
                info->ops.cleanup = hda_pcm_default_cleanup;
@@ -1525,12 +1520,12 @@ int snd_hda_build_pcms(struct hda_bus *bus)
  *
  * If no entries are matching, the function returns a negative value.
  */
-int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl)
+int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl)
 {
-       struct hda_board_config *c;
+       const struct hda_board_config *c;
 
        if (codec->bus->modelname) {
-               for (c = tbl; c->modelname || c->pci_vendor; c++) {
+               for (c = tbl; c->modelname || c->pci_subvendor; c++) {
                        if (c->modelname &&
                            ! strcmp(codec->bus->modelname, c->modelname)) {
                                snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname);
@@ -1543,9 +1538,10 @@ int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config
                u16 subsystem_vendor, subsystem_device;
                pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
                pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-               for (c = tbl; c->modelname || c->pci_vendor; c++) {
-                       if (c->pci_vendor == subsystem_vendor &&
-                           c->pci_device == subsystem_device)
+               for (c = tbl; c->modelname || c->pci_subvendor; c++) {
+                       if (c->pci_subvendor == subsystem_vendor &&
+                           (! c->pci_subdevice /* all match */||
+                            (c->pci_subdevice == subsystem_device)))
                                return c->config;
                }
        }
@@ -1687,11 +1683,12 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o
                snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
        /* surrounds */
        for (i = 1; i < mout->num_dacs; i++) {
-               if (i == HDA_REAR && chs == 2) /* copy front to rear */
-                       snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format);
-               else if (chs >= (i + 1) * 2) /* independent out */
+               if (chs >= (i + 1) * 2) /* independent out */
                        snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2,
                                                   format);
+               else /* copy front */
+                       snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0,
+                                                  format);
        }
        return 0;
 }
@@ -1717,6 +1714,105 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o
        return 0;
 }
 
+/*
+ * Helper for automatic ping configuration
+ */
+/* parse all pin widgets and store the useful pin nids to cfg */
+int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg)
+{
+       hda_nid_t nid, nid_start;
+       int i, j, nodes;
+       short seq, sequences[4], assoc_line_out;
+
+       memset(cfg, 0, sizeof(*cfg));
+
+       memset(sequences, 0, sizeof(sequences));
+       assoc_line_out = 0;
+
+       nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
+       for (nid = nid_start; nid < nodes + nid_start; nid++) {
+               unsigned int wid_caps = snd_hda_param_read(codec, nid,
+                                                          AC_PAR_AUDIO_WIDGET_CAP);
+               unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+               unsigned int def_conf;
+               short assoc, loc;
+
+               /* read all default configuration for pin complex */
+               if (wid_type != AC_WID_PIN)
+                       continue;
+               def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+               if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
+                       continue;
+               loc = get_defcfg_location(def_conf);
+               switch (get_defcfg_device(def_conf)) {
+               case AC_JACK_LINE_OUT:
+               case AC_JACK_SPEAKER:
+                       seq = get_defcfg_sequence(def_conf);
+                       assoc = get_defcfg_association(def_conf);
+                       if (! assoc)
+                               continue;
+                       if (! assoc_line_out)
+                               assoc_line_out = assoc;
+                       else if (assoc_line_out != assoc)
+                               continue;
+                       if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
+                               continue;
+                       cfg->line_out_pins[cfg->line_outs] = nid;
+                       sequences[cfg->line_outs] = seq;
+                       cfg->line_outs++;
+                       break;
+               case AC_JACK_HP_OUT:
+                       cfg->hp_pin = nid;
+                       break;
+               case AC_JACK_MIC_IN:
+                       if (loc == AC_JACK_LOC_FRONT)
+                               cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid;
+                       else
+                               cfg->input_pins[AUTO_PIN_MIC] = nid;
+                       break;
+               case AC_JACK_LINE_IN:
+                       if (loc == AC_JACK_LOC_FRONT)
+                               cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
+                       else
+                               cfg->input_pins[AUTO_PIN_LINE] = nid;
+                       break;
+               case AC_JACK_CD:
+                       cfg->input_pins[AUTO_PIN_CD] = nid;
+                       break;
+               case AC_JACK_AUX:
+                       cfg->input_pins[AUTO_PIN_AUX] = nid;
+                       break;
+               case AC_JACK_SPDIF_OUT:
+                       cfg->dig_out_pin = nid;
+                       break;
+               case AC_JACK_SPDIF_IN:
+                       cfg->dig_in_pin = nid;
+                       break;
+               }
+       }
+
+       /* sort by sequence */
+       for (i = 0; i < cfg->line_outs; i++)
+               for (j = i + 1; j < cfg->line_outs; j++)
+                       if (sequences[i] > sequences[j]) {
+                               seq = sequences[i];
+                               sequences[i] = sequences[j];
+                               sequences[j] = seq;
+                               nid = cfg->line_out_pins[i];
+                               cfg->line_out_pins[i] = cfg->line_out_pins[j];
+                               cfg->line_out_pins[j] = nid;
+                       }
+
+       /* Swap surround and CLFE: the association order is front/CLFE/surr/back */
+       if (cfg->line_outs >= 3) {
+               nid = cfg->line_out_pins[1];
+               cfg->line_out_pins[1] = cfg->line_out_pins[2];
+               cfg->line_out_pins[2] = nid;
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_PM
 /*
  * power management
index c9e9dc9c7c98eae856eea9ef1bccf8fbb3d0b4b8..59991560d492260b9d407fd00ddb11a5f907de36 100644 (file)
@@ -75,6 +75,9 @@ enum {
 #define AC_VERB_GET_DIGI_CONVERT               0x0f0d
 #define AC_VERB_GET_VOLUME_KNOB_CONTROL                0x0f0f
 /* f10-f1a: GPIO */
+#define AC_VERB_GET_GPIO_DATA                  0x0f15
+#define AC_VERB_GET_GPIO_MASK                  0x0f16
+#define AC_VERB_GET_GPIO_DIRECTION             0x0f17
 #define AC_VERB_GET_CONFIG_DEFAULT             0x0f1c
 
 /*
@@ -97,6 +100,9 @@ enum {
 #define AC_VERB_SET_DIGI_CONVERT_1             0x70d
 #define AC_VERB_SET_DIGI_CONVERT_2             0x70e
 #define AC_VERB_SET_VOLUME_KNOB_CONTROL                0x70f
+#define AC_VERB_SET_GPIO_DATA                  0x715
+#define AC_VERB_SET_GPIO_MASK                  0x716
+#define AC_VERB_SET_GPIO_DIRECTION             0x717
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0     0x71c
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1     0x71d
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2     0x71e
@@ -176,16 +182,15 @@ enum {
 #define AC_PINCAP_OUT                  (1<<4)  /* output capable */
 #define AC_PINCAP_IN                   (1<<5)  /* input capable */
 #define AC_PINCAP_BALANCE              (1<<6)  /* balanced I/O capable */
-#define AC_PINCAP_VREF                 (7<<8)
+#define AC_PINCAP_VREF                 (0x37<<8)
 #define AC_PINCAP_VREF_SHIFT           8
 #define AC_PINCAP_EAPD                 (1<<16) /* EAPD capable */
-/* Vref status (used in pin cap and pin ctl) */
-#define AC_PIN_VREF_HIZ                        (1<<0)  /* Hi-Z */
-#define AC_PIN_VREF_50                 (1<<1)  /* 50% */
-#define AC_PIN_VREF_GRD                        (1<<2)  /* ground */
-#define AC_PIN_VREF_80                 (1<<4)  /* 80% */
-#define AC_PIN_VREF_100                        (1<<5)  /* 100% */
-
+/* Vref status (used in pin cap) */
+#define AC_PINCAP_VREF_HIZ             (1<<0)  /* Hi-Z */
+#define AC_PINCAP_VREF_50              (1<<1)  /* 50% */
+#define AC_PINCAP_VREF_GRD             (1<<2)  /* ground */
+#define AC_PINCAP_VREF_80              (1<<4)  /* 80% */
+#define AC_PINCAP_VREF_100             (1<<5)  /* 100% */
 
 /* Amplifier capabilities */
 #define AC_AMPCAP_OFFSET               (0x7f<<0)  /* 0dB offset */
@@ -248,6 +253,11 @@ enum {
 
 /* Pin widget control - 8bit */
 #define AC_PINCTL_VREFEN               (0x7<<0)
+#define AC_PINCTL_VREF_HIZ             0       /* Hi-Z */
+#define AC_PINCTL_VREF_50              1       /* 50% */
+#define AC_PINCTL_VREF_GRD             2       /* ground */
+#define AC_PINCTL_VREF_80              4       /* 80% */
+#define AC_PINCTL_VREF_100             5       /* 100% */
 #define AC_PINCTL_IN_EN                        (1<<5)
 #define AC_PINCTL_OUT_EN               (1<<6)
 #define AC_PINCTL_HP_EN                        (1<<7)
@@ -255,7 +265,9 @@ enum {
 /* configuration default - 32bit */
 #define AC_DEFCFG_SEQUENCE             (0xf<<0)
 #define AC_DEFCFG_DEF_ASSOC            (0xf<<4)
+#define AC_DEFCFG_ASSOC_SHIFT          4
 #define AC_DEFCFG_MISC                 (0xf<<8)
+#define AC_DEFCFG_MISC_SHIFT           8
 #define AC_DEFCFG_COLOR                        (0xf<<12)
 #define AC_DEFCFG_COLOR_SHIFT          12
 #define AC_DEFCFG_CONN_TYPE            (0xf<<16)
@@ -413,7 +425,7 @@ struct hda_bus {
 
        /* codec linked list */
        struct list_head codec_list;
-       struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */
+       struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */
 
        struct semaphore cmd_mutex;
 
index 69f7b6c4cf83a32b9a90d5e312ea8fda8ea21f79..2d046abb591108bc9033be2f5ce16b6a4ab95c6b 100644 (file)
@@ -44,7 +44,7 @@ struct hda_gnode {
        struct list_head list;
 };
 
-/* pathc-specific record */
+/* patch-specific record */
 struct hda_gspec {
        struct hda_gnode *dac_node;     /* DAC node */
        struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */
@@ -68,8 +68,8 @@ struct hda_gspec {
 /*
  * retrieve the default device type from the default config value
  */
-#define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-#define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+#define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
 
 /*
  * destructor
@@ -323,7 +323,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
                if (! (node->pin_caps & AC_PINCAP_OUT))
                        continue;
                if (jack_type >= 0) {
-                       if (jack_type != get_defcfg_type(node))
+                       if (jack_type != defcfg_type(node))
                                continue;
                        if (node->wid_caps & AC_WCAP_DIGITAL)
                                continue; /* skip SPDIF */
@@ -418,15 +418,15 @@ static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
  */
 static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
 {
-       unsigned int location = get_defcfg_location(node);
-       switch (get_defcfg_type(node)) {
+       unsigned int location = defcfg_location(node);
+       switch (defcfg_type(node)) {
        case AC_JACK_LINE_IN:
                if ((location & 0x0f) == AC_JACK_LOC_FRONT)
                        return "Front Line";
                return "Line";
        case AC_JACK_CD:
                if (pinctl)
-                       *pinctl |= AC_PIN_VREF_GRD;
+                       *pinctl |= AC_PINCTL_VREF_GRD;
                return "CD";
        case AC_JACK_AUX:
                if ((location & 0x0f) == AC_JACK_LOC_FRONT)
index 959953ca320a16a7904ecd016e9a66d798564001..5e0cca36ed57d0215e5d407d3ef51f5c4fd610aa 100644 (file)
@@ -51,6 +51,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
 static char *model[SNDRV_CARDS];
+static int position_fix[SNDRV_CARDS];
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -60,12 +61,17 @@ module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
 module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
+module_param_array(position_fix, int, NULL, 0444);
+MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");
 
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
                         "{Intel, ICH6M},"
                         "{Intel, ICH7},"
-                        "{Intel, ESB2}}");
+                        "{Intel, ESB2},"
+                        "{ATI, SB450},"
+                        "{VIA, VT8251},"
+                        "{VIA, VT8237A}}");
 MODULE_DESCRIPTION("Intel HDA driver");
 
 #define SFX    "hda-intel: "
@@ -150,7 +156,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 
 /* STATESTS int mask: SD2,SD1,SD0 */
 #define STATESTS_INT_MASK      0x07
-#define AZX_MAX_CODECS         3
+#define AZX_MAX_CODECS         4
 
 /* SD_CTL bits */
 #define SD_CTL_STREAM_RESET    0x01    /* stream reset bit */
@@ -183,6 +189,18 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define ICH6_MAX_CORB_ENTRIES  256
 #define ICH6_MAX_RIRB_ENTRIES  256
 
+/* position fix mode */
+enum {
+       POS_FIX_FIFO,
+       POS_FIX_NONE,
+       POS_FIX_POSBUF
+};
+
+/* Defines for ATI HD Audio support in SB450 south bridge */
+#define ATI_SB450_HDAUDIO_PCI_DEVICE_ID     0x437b
+#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR   0x42
+#define ATI_SB450_HDAUDIO_ENABLE_SNOOP      0x02
+
 
 /*
  * Use CORB/RIRB for communication from/to codecs.
@@ -190,12 +208,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
  */
 #define USE_CORB_RIRB
 
-/*
- * Define this if use the position buffer instead of reading SD_LPIB
- * It's not used as default since SD_LPIB seems to give more accurate position
- */
-/* #define USE_POSBUF */
-
 /*
  */
 
@@ -271,6 +283,10 @@ struct snd_azx {
        struct snd_dma_buffer bdl;
        struct snd_dma_buffer rb;
        struct snd_dma_buffer posbuf;
+
+       /* flags */
+       int position_fix;
+       unsigned int initialized: 1;
 };
 
 /*
@@ -638,7 +654,7 @@ static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev)
  */
 static void azx_init_chip(azx_t *chip)
 {
-       unsigned char tcsel_reg;
+       unsigned char tcsel_reg, ati_misc_cntl2;
 
        /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
         * TCSEL == Traffic Class Select Register, which sets PCI express QOS
@@ -657,11 +673,20 @@ static void azx_init_chip(azx_t *chip)
        /* initialize the codec command I/O */
        azx_init_cmd_io(chip);
 
-#ifdef USE_POSBUF
-       /* program the position buffer */
-       azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
-       azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
-#endif
+       if (chip->position_fix == POS_FIX_POSBUF) {
+               /* program the position buffer */
+               azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+               azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
+       }
+
+       /* For ATI SB450 azalia HD audio, we need to enable snoop */
+       if (chip->pci->vendor == PCI_VENDOR_ID_ATI && 
+           chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) {
+               pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 
+                                    &ati_misc_cntl2);
+               pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 
+                                     (ati_misc_cntl2 & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP);
+       }
 }
 
 
@@ -791,11 +816,12 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
        /* upper BDL address */
        azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
 
-#ifdef USE_POSBUF
-       /* enable the position buffer */
-       if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
-               azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
-#endif
+       if (chip->position_fix == POS_FIX_POSBUF) {
+               /* enable the position buffer */
+               if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+                       azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+       }
+
        /* set the interrupt enable bits in the descriptor control register */
        azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
 
@@ -1036,16 +1062,20 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 
 static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
 {
+       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+       azx_t *chip = apcm->chip;
        azx_dev_t *azx_dev = get_azx_dev(substream);
        unsigned int pos;
 
-#ifdef USE_POSBUF
-       /* use the position buffer */
-       pos = *azx_dev->posbuf;
-#else
-       /* read LPIB */
-       pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size;
-#endif
+       if (chip->position_fix == POS_FIX_POSBUF) {
+               /* use the position buffer */
+               pos = *azx_dev->posbuf;
+       } else {
+               /* read LPIB */
+               pos = azx_sd_readl(azx_dev, SD_LPIB);
+               if (chip->position_fix == POS_FIX_FIFO)
+                       pos += azx_dev->fifo_size;
+       }
        if (pos >= azx_dev->bufsize)
                pos = 0;
        return bytes_to_frames(substream->runtime, pos);
@@ -1155,9 +1185,8 @@ static int __devinit azx_init_stream(azx_t *chip)
                azx_dev_t *azx_dev = &chip->azx_dev[i];
                azx_dev->bdl = (u32 *)(chip->bdl.area + off);
                azx_dev->bdl_addr = chip->bdl.addr + off;
-#ifdef USE_POSBUF
-               azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
-#endif
+               if (chip->position_fix == POS_FIX_POSBUF)
+                       azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
                /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
                azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
                /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1207,7 +1236,7 @@ static int azx_resume(snd_card_t *card)
  */
 static int azx_free(azx_t *chip)
 {
-       if (chip->remap_addr) {
+       if (chip->initialized) {
                int i;
 
                for (i = 0; i < MAX_ICH6_DEV; i++)
@@ -1237,10 +1266,8 @@ static int azx_free(azx_t *chip)
                snd_dma_free_pages(&chip->bdl);
        if (chip->rb.area)
                snd_dma_free_pages(&chip->rb);
-#ifdef USE_POSBUF
        if (chip->posbuf.area)
                snd_dma_free_pages(&chip->posbuf);
-#endif
        pci_release_regions(chip->pci);
        pci_disable_device(chip->pci);
        kfree(chip);
@@ -1256,7 +1283,8 @@ static int azx_dev_free(snd_device_t *device)
 /*
  * constructor
  */
-static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip)
+static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
+                               int posfix, azx_t **rchip)
 {
        azx_t *chip;
        int err = 0;
@@ -1283,6 +1311,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r
        chip->pci = pci;
        chip->irq = -1;
 
+       chip->position_fix = posfix;
+
        if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
                kfree(chip);
                pci_disable_device(pci);
@@ -1314,14 +1344,14 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r
                snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
                goto errout;
        }
-#ifdef USE_POSBUF
-       /* allocate memory for the position buffer */
-       if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
-                                      MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
-               snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
-               goto errout;
+       if (chip->position_fix == POS_FIX_POSBUF) {
+               /* allocate memory for the position buffer */
+               if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+                                              MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
+                       snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+                       goto errout;
+               }
        }
-#endif
        /* allocate CORB/RIRB */
        if ((err = azx_alloc_cmd_io(chip)) < 0)
                goto errout;
@@ -1332,6 +1362,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r
        /* initialize chip */
        azx_init_chip(chip);
 
+       chip->initialized = 1;
+
        /* codec detection */
        if (! chip->codec_mask) {
                snd_printk(KERN_ERR SFX "no codecs found!\n");
@@ -1372,7 +1404,7 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
                return -ENOMEM;
        }
 
-       if ((err = azx_create(card, pci, &chip)) < 0) {
+       if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) {
                snd_card_free(card);
                return err;
        }
@@ -1424,6 +1456,9 @@ static struct pci_device_id azx_ids[] = {
        { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
        { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
        { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */
+       { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */
+       { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */
+       { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
@@ -1439,7 +1474,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_azx_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_azx_exit(void)
index 7c7b849875a0015a2c4e7878d3744d1d8b2920a8..810cfd2d9bba29b99d6726edb2fb301a69f534ed 100644 (file)
@@ -126,11 +126,11 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
 struct hda_board_config {
        const char *modelname;
        int config;
-       unsigned short pci_vendor;
-       unsigned short pci_device;
+       unsigned short pci_subvendor;
+       unsigned short pci_subdevice;
 };
 
-int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl);
+int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl);
 int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
 
 /*
@@ -158,4 +158,35 @@ struct hda_bus_unsolicited {
        struct work_struct work;
 };
 
+/*
+ * Helper for automatic ping configuration
+ */
+
+enum {
+       AUTO_PIN_MIC,
+       AUTO_PIN_FRONT_MIC,
+       AUTO_PIN_LINE,
+       AUTO_PIN_FRONT_LINE,
+       AUTO_PIN_CD,
+       AUTO_PIN_AUX,
+       AUTO_PIN_LAST
+};
+
+struct auto_pin_cfg {
+       int line_outs;
+       hda_nid_t line_out_pins[4]; /* sorted in the order of Front/Surr/CLFE/Side */
+       hda_nid_t hp_pin;
+       hda_nid_t input_pins[AUTO_PIN_LAST];
+       hda_nid_t dig_out_pin;
+       hda_nid_t dig_in_pin;
+};
+
+#define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
+#define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
+#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE)
+#define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+
+int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg);
+
 #endif /* __SOUND_HDA_LOCAL_H */
index cf6abce42bc9ea15666e50f8b7b2d64b079b782a..a5de684b69446a6c958324ba566d91794f5313a9 100644 (file)
@@ -8,10 +8,13 @@ extern struct hda_codec_preset snd_hda_preset_realtek[];
 extern struct hda_codec_preset snd_hda_preset_cmedia[];
 /* Analog Devices codecs */
 extern struct hda_codec_preset snd_hda_preset_analog[];
+/* SigmaTel codecs */
+extern struct hda_codec_preset snd_hda_preset_sigmatel[];
 
 static const struct hda_codec_preset *hda_preset_tables[] = {
        snd_hda_preset_realtek,
        snd_hda_preset_cmedia,
        snd_hda_preset_analog,
+       snd_hda_preset_sigmatel,
        NULL
 };
index 4d5db7faad8d9db4ed437d16e655a2e1d869661e..de1217bd8e68288733f59fcdab0f4ea6441c33e2 100644 (file)
@@ -68,21 +68,27 @@ static void print_amp_caps(snd_info_buffer_t *buffer,
 
 static void print_amp_vals(snd_info_buffer_t *buffer,
                           struct hda_codec *codec, hda_nid_t nid,
-                          int dir, int stereo)
+                          int dir, int stereo, int indices)
 {
        unsigned int val;
-       if (stereo) {
+       int i;
+
+       if (dir == HDA_OUTPUT)
+               dir = AC_AMP_GET_OUTPUT;
+       else
+               dir = AC_AMP_GET_INPUT;
+       for (i = 0; i < indices; i++) {
+               snd_iprintf(buffer, " [");
+               if (stereo) {
+                       val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+                                                AC_AMP_GET_LEFT | dir | i);
+                       snd_iprintf(buffer, "0x%02x ", val);
+               }
                val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
-                                         AC_AMP_GET_LEFT |
-                                        (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
-                                         AC_AMP_GET_INPUT));
-               snd_iprintf(buffer, "0x%02x ", val);
+                                        AC_AMP_GET_RIGHT | dir | i);
+               snd_iprintf(buffer, "0x%02x]", val);
        }
-       val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
-                                AC_AMP_GET_RIGHT |
-                                (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
-                                 AC_AMP_GET_INPUT));
-       snd_iprintf(buffer, "0x%02x\n", val);
+       snd_iprintf(buffer, "\n");
 }
 
 static void print_pcm_caps(snd_info_buffer_t *buffer,
@@ -157,6 +163,7 @@ static const char *get_jack_color(u32 cfg)
 static void print_pin_caps(snd_info_buffer_t *buffer,
                           struct hda_codec *codec, hda_nid_t nid)
 {
+       static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
        static char *jack_types[16] = {
                "Line Out", "Speaker", "HP Out", "CD",
                "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
@@ -176,7 +183,8 @@ static void print_pin_caps(snd_info_buffer_t *buffer,
                snd_iprintf(buffer, " HP");
        snd_iprintf(buffer, "\n");
        caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
-       snd_iprintf(buffer, "  Pin Default 0x%08x: %s at %s %s\n", caps,
+       snd_iprintf(buffer, "  Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
+                   jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
                    jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
                    jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
                    get_jack_location(caps));
@@ -215,6 +223,9 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
                unsigned int wid_caps = snd_hda_param_read(codec, nid,
                                                           AC_PAR_AUDIO_WIDGET_CAP);
                unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+               int conn_len = 0; 
+               hda_nid_t conn[HDA_MAX_CONNECTIONS];
+
                snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
                            get_wid_type_name(wid_type), wid_caps);
                if (wid_caps & AC_WCAP_STEREO)
@@ -229,19 +240,23 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
                        snd_iprintf(buffer, " Amp-Out");
                snd_iprintf(buffer, "\n");
 
+               if (wid_caps & AC_WCAP_CONN_LIST)
+                       conn_len = snd_hda_get_connections(codec, nid, conn,
+                                                          HDA_MAX_CONNECTIONS);
+
                if (wid_caps & AC_WCAP_IN_AMP) {
                        snd_iprintf(buffer, "  Amp-In caps: ");
                        print_amp_caps(buffer, codec, nid, HDA_INPUT);
                        snd_iprintf(buffer, "  Amp-In vals: ");
                        print_amp_vals(buffer, codec, nid, HDA_INPUT,
-                                      wid_caps & AC_WCAP_STEREO);
+                                      wid_caps & AC_WCAP_STEREO, conn_len);
                }
                if (wid_caps & AC_WCAP_OUT_AMP) {
                        snd_iprintf(buffer, "  Amp-Out caps: ");
                        print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
                        snd_iprintf(buffer, "  Amp-Out vals: ");
                        print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
-                                      wid_caps & AC_WCAP_STEREO);
+                                      wid_caps & AC_WCAP_STEREO, 1);
                }
 
                if (wid_type == AC_WID_PIN) {
@@ -265,14 +280,17 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
                }
 
                if (wid_caps & AC_WCAP_CONN_LIST) {
-                       hda_nid_t conn[HDA_MAX_CONNECTIONS];
-                       int c, conn_len;
-                       conn_len = snd_hda_get_connections(codec, nid, conn,
-                                                          HDA_MAX_CONNECTIONS);
+                       int c, curr = -1;
+                       if (conn_len > 1 && wid_type != AC_WID_AUD_MIX)
+                               curr = snd_hda_codec_read(codec, nid, 0,
+                                       AC_VERB_GET_CONNECT_SEL, 0);
                        snd_iprintf(buffer, "  Connection: %d\n", conn_len);
                        snd_iprintf(buffer, "    ");
-                       for (c = 0; c < conn_len; c++)
+                       for (c = 0; c < conn_len; c++) {
                                snd_iprintf(buffer, " 0x%02x", conn[c]);
+                               if (c == curr)
+                                       snd_iprintf(buffer, "*");
+                       }
                        snd_iprintf(buffer, "\n");
                }
        }
index 75d23849f71ac53e737d4c4a4da26be9eb47f829..2fd05bb841365ee67ebc5f8639307e133c4e0d0a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * HD audio interface patch for AD1986A
+ * HD audio interface patch for AD1981HD, AD1983, AD1986A
  *
  * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
  *
 #include "hda_codec.h"
 #include "hda_local.h"
 
-struct ad1986a_spec {
+struct ad198x_spec {
        struct semaphore amp_mutex;     /* PCM volume/mute control mutex */
        struct hda_multi_out multiout;  /* playback */
+       hda_nid_t adc_nid;
+       const struct hda_input_mux *input_mux;
        unsigned int cur_mux;           /* capture source */
+       unsigned int spdif_route;
+       snd_kcontrol_new_t *mixers;
+       const struct hda_verb *init_verbs;
        struct hda_pcm pcm_rec[2];      /* PCM information */
 };
 
+/*
+ * input MUX handling (common part)
+ */
+static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct ad198x_spec *spec = codec->spec;
+
+       return snd_hda_input_mux_info(spec->input_mux, uinfo);
+}
+
+static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct ad198x_spec *spec = codec->spec;
+
+       ucontrol->value.enumerated.item[0] = spec->cur_mux;
+       return 0;
+}
+
+static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct ad198x_spec *spec = codec->spec;
+
+       return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+                                    spec->adc_nid, &spec->cur_mux);
+}
+
+/*
+ * initialization (common callbacks)
+ */
+static int ad198x_init(struct hda_codec *codec)
+{
+       struct ad198x_spec *spec = codec->spec;
+       snd_hda_sequence_write(codec, spec->init_verbs);
+       return 0;
+}
+
+static int ad198x_build_controls(struct hda_codec *codec)
+{
+       struct ad198x_spec *spec = codec->spec;
+       int err;
+
+       err = snd_hda_add_new_ctls(codec, spec->mixers);
+       if (err < 0)
+               return err;
+       if (spec->multiout.dig_out_nid)
+               err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+       if (err < 0)
+               return err;
+       return 0;
+}
+
+/*
+ * Analog playback callbacks
+ */
+static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
+                                   struct hda_codec *codec,
+                                   snd_pcm_substream_t *substream)
+{
+       struct ad198x_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                      struct hda_codec *codec,
+                                      unsigned int stream_tag,
+                                      unsigned int format,
+                                      snd_pcm_substream_t *substream)
+{
+       struct ad198x_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+                                               format, substream);
+}
+
+static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+                                      struct hda_codec *codec,
+                                      snd_pcm_substream_t *substream)
+{
+       struct ad198x_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+                                       struct hda_codec *codec,
+                                       snd_pcm_substream_t *substream)
+{
+       struct ad198x_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+                                        struct hda_codec *codec,
+                                        snd_pcm_substream_t *substream)
+{
+       struct ad198x_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                     struct hda_codec *codec,
+                                     unsigned int stream_tag,
+                                     unsigned int format,
+                                     snd_pcm_substream_t *substream)
+{
+       struct ad198x_spec *spec = codec->spec;
+       snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format);
+       return 0;
+}
+
+static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+                                     struct hda_codec *codec,
+                                     snd_pcm_substream_t *substream)
+{
+       struct ad198x_spec *spec = codec->spec;
+       snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0);
+       return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream ad198x_pcm_analog_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 6,
+       .nid = 0, /* fill later */
+       .ops = {
+               .open = ad198x_playback_pcm_open,
+               .prepare = ad198x_playback_pcm_prepare,
+               .cleanup = ad198x_playback_pcm_cleanup
+       },
+};
+
+static struct hda_pcm_stream ad198x_pcm_analog_capture = {
+       .substreams = 2,
+       .channels_min = 2,
+       .channels_max = 2,
+       .nid = 0, /* fill later */
+       .ops = {
+               .prepare = ad198x_capture_pcm_prepare,
+               .cleanup = ad198x_capture_pcm_cleanup
+       },
+};
+
+static struct hda_pcm_stream ad198x_pcm_digital_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       .nid = 0, /* fill later */
+       .ops = {
+               .open = ad198x_dig_playback_pcm_open,
+               .close = ad198x_dig_playback_pcm_close
+       },
+};
+
+static int ad198x_build_pcms(struct hda_codec *codec)
+{
+       struct ad198x_spec *spec = codec->spec;
+       struct hda_pcm *info = spec->pcm_rec;
+
+       codec->num_pcms = 1;
+       codec->pcm_info = info;
+
+       info->name = "AD198x Analog";
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
+       info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
+       info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid;
+
+       if (spec->multiout.dig_out_nid) {
+               info++;
+               codec->num_pcms++;
+               info->name = "AD198x Digital";
+               info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
+               info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+       }
+
+       return 0;
+}
+
+static void ad198x_free(struct hda_codec *codec)
+{
+       kfree(codec->spec);
+}
+
+#ifdef CONFIG_PM
+static int ad198x_resume(struct hda_codec *codec)
+{
+       struct ad198x_spec *spec = codec->spec;
+
+       ad198x_init(codec);
+       snd_hda_resume_ctls(codec, spec->mixers);
+       snd_hda_resume_spdif_out(codec);
+       return 0;
+}
+#endif
+
+static struct hda_codec_ops ad198x_patch_ops = {
+       .build_controls = ad198x_build_controls,
+       .build_pcms = ad198x_build_pcms,
+       .init = ad198x_init,
+       .free = ad198x_free,
+#ifdef CONFIG_PM
+       .resume = ad198x_resume,
+#endif
+};
+
+
+/*
+ * AD1986A specific
+ */
+
 #define AD1986A_SPDIF_OUT      0x02
 #define AD1986A_FRONT_DAC      0x03
 #define AD1986A_SURR_DAC       0x04
@@ -68,7 +294,7 @@ static struct hda_input_mux ad1986a_capture_source = {
 static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct ad1986a_spec *ad = codec->spec;
+       struct ad198x_spec *ad = codec->spec;
 
        down(&ad->amp_mutex);
        snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
@@ -79,7 +305,7 @@ static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
 static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct ad1986a_spec *ad = codec->spec;
+       struct ad198x_spec *ad = codec->spec;
        int i, change = 0;
 
        down(&ad->amp_mutex);
@@ -92,12 +318,12 @@ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
        return change;
 }
 
-#define ad1986a_pcm_amp_sw_info                snd_hda_mixer_amp_volume_info
+#define ad1986a_pcm_amp_sw_info                snd_hda_mixer_amp_switch_info
 
 static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct ad1986a_spec *ad = codec->spec;
+       struct ad198x_spec *ad = codec->spec;
 
        down(&ad->amp_mutex);
        snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
@@ -108,7 +334,7 @@ static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct ad1986a_spec *ad = codec->spec;
+       struct ad198x_spec *ad = codec->spec;
        int i, change = 0;
 
        down(&ad->amp_mutex);
@@ -121,32 +347,6 @@ static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
        return change;
 }
 
-/*
- * input MUX handling
- */
-static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
-       return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo);
-}
-
-static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct ad1986a_spec *spec = codec->spec;
-
-       ucontrol->value.enumerated.item[0] = spec->cur_mux;
-       return 0;
-}
-
-static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct ad1986a_spec *spec = codec->spec;
-
-       return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol,
-                                    AD1986A_ADC, &spec->cur_mux);
-}
-
 /*
  * mixers
  */
@@ -194,9 +394,9 @@ static snd_kcontrol_new_t ad1986a_mixers[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Capture Source",
-               .info = ad1986a_mux_enum_info,
-               .get = ad1986a_mux_enum_get,
-               .put = ad1986a_mux_enum_put,
+               .info = ad198x_mux_enum_info,
+               .get = ad198x_mux_enum_get,
+               .put = ad198x_mux_enum_put,
        },
        HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
        { } /* end */
@@ -241,183 +441,328 @@ static struct hda_verb ad1986a_init_verbs[] = {
        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
        {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
        {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* HP Pin */
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* Front, Surround, CLFE Pins */
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* Mono Pin */
+       {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* Mic Pin */
+       {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       /* Line, Aux, CD, Beep-In Pin */
+       {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
        { } /* end */
 };
 
 
-static int ad1986a_init(struct hda_codec *codec)
+static int patch_ad1986a(struct hda_codec *codec)
 {
-       snd_hda_sequence_write(codec, ad1986a_init_verbs);
-       return 0;
-}
+       struct ad198x_spec *spec;
 
-static int ad1986a_build_controls(struct hda_codec *codec)
-{
-       int err;
+       spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       init_MUTEX(&spec->amp_mutex);
+       codec->spec = spec;
+
+       spec->multiout.max_channels = 6;
+       spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
+       spec->multiout.dac_nids = ad1986a_dac_nids;
+       spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
+       spec->adc_nid = AD1986A_ADC;
+       spec->input_mux = &ad1986a_capture_source;
+       spec->mixers = ad1986a_mixers;
+       spec->init_verbs = ad1986a_init_verbs;
+
+       codec->patch_ops = ad198x_patch_ops;
 
-       err = snd_hda_add_new_ctls(codec, ad1986a_mixers);
-       if (err < 0)
-               return err;
-       err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT);
-       if (err < 0)
-               return err;
        return 0;
 }
 
 /*
- * Analog playback callbacks
+ * AD1983 specific
  */
-static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo,
-                                    struct hda_codec *codec,
-                                    snd_pcm_substream_t *substream)
-{
-       struct ad1986a_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
-}
 
-static int ad1986a_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-                                       struct hda_codec *codec,
-                                       unsigned int stream_tag,
-                                       unsigned int format,
-                                       snd_pcm_substream_t *substream)
-{
-       struct ad1986a_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
-                                               format, substream);
-}
+#define AD1983_SPDIF_OUT       0x02
+#define AD1983_DAC             0x03
+#define AD1983_ADC             0x04
 
-static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-                                       struct hda_codec *codec,
-                                       snd_pcm_substream_t *substream)
-{
-       struct ad1986a_spec *spec = codec->spec;
-       return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
+static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
+
+static struct hda_input_mux ad1983_capture_source = {
+       .num_items = 4,
+       .items = {
+               { "Mic", 0x0 },
+               { "Line", 0x1 },
+               { "Mix", 0x2 },
+               { "Mix Mono", 0x3 },
+       },
+};
 
 /*
- * Digital out
+ * SPDIF playback route
  */
-static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-                                        struct hda_codec *codec,
-                                        snd_pcm_substream_t *substream)
+static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
-       struct ad1986a_spec *spec = codec->spec;
-       return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+       static char *texts[] = { "PCM", "ADC" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       if (uinfo->value.enumerated.item > 1)
+               uinfo->value.enumerated.item = 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
 }
 
-static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-                                         struct hda_codec *codec,
-                                         snd_pcm_substream_t *substream)
+static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-       struct ad1986a_spec *spec = codec->spec;
-       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct ad198x_spec *spec = codec->spec;
 
-/*
- * Analog capture
- */
-static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-                                      struct hda_codec *codec,
-                                      unsigned int stream_tag,
-                                      unsigned int format,
-                                      snd_pcm_substream_t *substream)
-{
-       snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format);
+       ucontrol->value.enumerated.item[0] = spec->spdif_route;
        return 0;
 }
 
-static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-                                      struct hda_codec *codec,
-                                      snd_pcm_substream_t *substream)
+static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-       snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0);
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct ad198x_spec *spec = codec->spec;
+
+       if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
+               spec->spdif_route = ucontrol->value.enumerated.item[0];
+               snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
+                                   AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
+               return 1;
+       }
        return 0;
 }
 
-
-/*
- */
-static struct hda_pcm_stream ad1986a_pcm_analog_playback = {
-       .substreams = 1,
-       .channels_min = 2,
-       .channels_max = 6,
-       .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */
-       .ops = {
-               .open = ad1986a_playback_pcm_open,
-               .prepare = ad1986a_playback_pcm_prepare,
-               .cleanup = ad1986a_playback_pcm_cleanup
+static snd_kcontrol_new_t ad1983_mixers[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Capture Source",
+               .info = ad198x_mux_enum_info,
+               .get = ad198x_mux_enum_get,
+               .put = ad198x_mux_enum_put,
        },
-};
-
-static struct hda_pcm_stream ad1986a_pcm_analog_capture = {
-       .substreams = 2,
-       .channels_min = 2,
-       .channels_max = 2,
-       .nid = AD1986A_ADC, /* NID to query formats and rates */
-       .ops = {
-               .prepare = ad1986a_capture_pcm_prepare,
-               .cleanup = ad1986a_capture_pcm_cleanup
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "IEC958 Playback Route",
+               .info = ad1983_spdif_route_info,
+               .get = ad1983_spdif_route_get,
+               .put = ad1983_spdif_route_put,
        },
+       { } /* end */
 };
 
-static struct hda_pcm_stream ad1986a_pcm_digital_playback = {
-       .substreams = 1,
-       .channels_min = 2,
-       .channels_max = 2,
-       .nid = AD1986A_SPDIF_OUT, 
-       .ops = {
-               .open = ad1986a_dig_playback_pcm_open,
-               .close = ad1986a_dig_playback_pcm_close
-       },
+static struct hda_verb ad1983_init_verbs[] = {
+       /* Front, HP, Mono; mute as default */
+       {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* Beep, PCM, Mic, Line-In: mute */
+       {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* Front, HP selectors; from Mix */
+       {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
+       /* Mono selector; from Mix */
+       {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
+       /* Mic selector; Mic */
+       {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
+       /* Line-in selector: Line-in */
+       {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
+       /* Mic boost: 0dB */
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+       /* Record selector: mic */
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* SPDIF route: PCM */
+       {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
+       /* Front Pin */
+       {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* HP Pin */
+       {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* Mono Pin */
+       {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* Mic Pin */
+       {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       /* Line Pin */
+       {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       { } /* end */
 };
 
-static int ad1986a_build_pcms(struct hda_codec *codec)
+static int patch_ad1983(struct hda_codec *codec)
 {
-       struct ad1986a_spec *spec = codec->spec;
-       struct hda_pcm *info = spec->pcm_rec;
+       struct ad198x_spec *spec;
 
-       codec->num_pcms = 2;
-       codec->pcm_info = info;
+       spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
 
-       info->name = "AD1986A Analog";
-       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback;
-       info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture;
-       info++;
+       init_MUTEX(&spec->amp_mutex);
+       codec->spec = spec;
+
+       spec->multiout.max_channels = 2;
+       spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
+       spec->multiout.dac_nids = ad1983_dac_nids;
+       spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
+       spec->adc_nid = AD1983_ADC;
+       spec->input_mux = &ad1983_capture_source;
+       spec->mixers = ad1983_mixers;
+       spec->init_verbs = ad1983_init_verbs;
+       spec->spdif_route = 0;
 
-       info->name = "AD1986A Digital";
-       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback;
+       codec->patch_ops = ad198x_patch_ops;
 
        return 0;
 }
 
-static void ad1986a_free(struct hda_codec *codec)
-{
-       kfree(codec->spec);
-}
 
-#ifdef CONFIG_PM
-static int ad1986a_resume(struct hda_codec *codec)
-{
-       ad1986a_init(codec);
-       snd_hda_resume_ctls(codec, ad1986a_mixers);
-       snd_hda_resume_spdif_out(codec);
-       return 0;
-}
-#endif
+/*
+ * AD1981 HD specific
+ */
 
-static struct hda_codec_ops ad1986a_patch_ops = {
-       .build_controls = ad1986a_build_controls,
-       .build_pcms = ad1986a_build_pcms,
-       .init = ad1986a_init,
-       .free = ad1986a_free,
-#ifdef CONFIG_PM
-       .resume = ad1986a_resume,
-#endif
+#define AD1981_SPDIF_OUT       0x02
+#define AD1981_DAC             0x03
+#define AD1981_ADC             0x04
+
+static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
+
+/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
+static struct hda_input_mux ad1981_capture_source = {
+       .num_items = 7,
+       .items = {
+               { "Front Mic", 0x0 },
+               { "Line", 0x1 },
+               { "Mix", 0x2 },
+               { "Mix Mono", 0x3 },
+               { "CD", 0x4 },
+               { "Mic", 0x6 },
+               { "Aux", 0x7 },
+       },
 };
 
-static int patch_ad1986a(struct hda_codec *codec)
+static snd_kcontrol_new_t ad1981_mixers[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Capture Source",
+               .info = ad198x_mux_enum_info,
+               .get = ad198x_mux_enum_get,
+               .put = ad198x_mux_enum_put,
+       },
+       /* identical with AD1983 */
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "IEC958 Playback Route",
+               .info = ad1983_spdif_route_info,
+               .get = ad1983_spdif_route_get,
+               .put = ad1983_spdif_route_put,
+       },
+       { } /* end */
+};
+
+static struct hda_verb ad1981_init_verbs[] = {
+       /* Front, HP, Mono; mute as default */
+       {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* Front, HP selectors; from Mix */
+       {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
+       /* Mono selector; from Mix */
+       {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
+       /* Mic Mixer; select Front Mic */
+       {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+       {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* Mic boost: 0dB */
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+       /* Record selector: Front mic */
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* SPDIF route: PCM */
+       {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
+       /* Front Pin */
+       {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* HP Pin */
+       {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* Mono Pin */
+       {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* Front & Rear Mic Pins */
+       {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       /* Line Pin */
+       {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       /* Digital Beep */
+       {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
+       /* Line-Out as Input: disabled */
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       { } /* end */
+};
+
+static int patch_ad1981(struct hda_codec *codec)
 {
-       struct ad1986a_spec *spec;
+       struct ad198x_spec *spec;
 
        spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
@@ -426,20 +771,28 @@ static int patch_ad1986a(struct hda_codec *codec)
        init_MUTEX(&spec->amp_mutex);
        codec->spec = spec;
 
-       spec->multiout.max_channels = 6;
-       spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
-       spec->multiout.dac_nids = ad1986a_dac_nids;
-       spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
+       spec->multiout.max_channels = 2;
+       spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
+       spec->multiout.dac_nids = ad1981_dac_nids;
+       spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
+       spec->adc_nid = AD1981_ADC;
+       spec->input_mux = &ad1981_capture_source;
+       spec->mixers = ad1981_mixers;
+       spec->init_verbs = ad1981_init_verbs;
+       spec->spdif_route = 0;
 
-       codec->patch_ops = ad1986a_patch_ops;
+       codec->patch_ops = ad198x_patch_ops;
 
        return 0;
 }
 
+
 /*
  * patch entries
  */
 struct hda_codec_preset snd_hda_preset_analog[] = {
+       { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
+       { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
        { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
        {} /* terminator */
 };
index b7cc8e4bffb7f2e099a8601463935500f972e03e..2d6e3e3d0a38c9354aa5200ef5edf10776564d8d 100644 (file)
@@ -29,6 +29,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#define NUM_PINS       11
 
 
 /* board config type */
@@ -38,6 +39,7 @@ enum {
        CMI_FULL,       /* back 6-jack + front-panel 2-jack */
        CMI_FULL_DIG,   /* back 6-jack + front-panel 2-jack + digital I/O */
        CMI_ALLOUT,     /* back 5-jack + front-panel 2-jack + digital out */
+       CMI_AUTO,       /* let driver guess it */
 };
 
 struct cmi_spec {
@@ -48,6 +50,8 @@ struct cmi_spec {
 
        /* playback */
        struct hda_multi_out multiout;
+       hda_nid_t dac_nids[4];          /* NID for each DAC */
+       int num_dacs;
 
        /* capture */
        hda_nid_t *adc_nids;
@@ -63,8 +67,30 @@ struct cmi_spec {
        const struct cmi_channel_mode *channel_modes;
 
        struct hda_pcm pcm_rec[2];      /* PCM information */
+
+       /* pin deafault configuration */
+       hda_nid_t pin_nid[NUM_PINS];
+       unsigned int def_conf[NUM_PINS];
+       unsigned int pin_def_confs;
+
+       /* multichannel pins */
+       hda_nid_t multich_pin[4];       /* max 8-channel */
+       struct hda_verb multi_init[9];  /* 2 verbs for each pin + terminator */
 };
 
+/* amp values */
+#define AMP_IN_MUTE(idx)       (0x7080 | ((idx)<<8))
+#define AMP_IN_UNMUTE(idx)     (0x7000 | ((idx)<<8))
+#define AMP_OUT_MUTE   0xb080
+#define AMP_OUT_UNMUTE 0xb000
+#define AMP_OUT_ZERO   0xb000
+/* pinctl values */
+#define PIN_IN         0x20
+#define PIN_VREF80     0x24
+#define PIN_VREF50     0x21
+#define PIN_OUT                0x40
+#define PIN_HP         0xc0
+
 /*
  * input MUX
  */
@@ -102,9 +128,9 @@ static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
 /* 3-stack / 2 channel */
 static struct hda_verb cmi9880_ch2_init[] = {
        /* set line-in PIN for input */
-       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
        /* set mic PIN for input, also enable vref */
-       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
        /* route front PCM (DAC1) to HP */
        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
        {}
@@ -113,9 +139,9 @@ static struct hda_verb cmi9880_ch2_init[] = {
 /* 3-stack / 6 channel */
 static struct hda_verb cmi9880_ch6_init[] = {
        /* set line-in PIN for output */
-       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
        /* set mic PIN for output */
-       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
        /* route front PCM (DAC1) to HP */
        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
        {}
@@ -124,9 +150,9 @@ static struct hda_verb cmi9880_ch6_init[] = {
 /* 3-stack+front / 8 channel */
 static struct hda_verb cmi9880_ch8_init[] = {
        /* set line-in PIN for output */
-       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
        /* set mic PIN for output */
-       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
        /* route rear-surround PCM (DAC4) to HP */
        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
        {}
@@ -269,25 +295,27 @@ static hda_nid_t cmi9880_adc_nids[2] = {
  */
 static struct hda_verb cmi9880_basic_init[] = {
        /* port-D for line out (rear panel) */
-       { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
        /* port-E for HP out (front panel) */
-       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
        /* route front PCM to HP */
        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
        /* port-A for surround (rear panel) */
-       { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
        /* port-G for CLFE (rear panel) */
-       { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+       { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
        /* port-H for side (rear panel) */
-       { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+       { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
        /* port-C for line-in (rear panel) */
-       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
        /* port-B for mic-in (rear panel) with vref */
-       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
        /* port-F for mic-in (front panel) with vref */
-       { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
        /* CD-in */
-       { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
        /* route front mic to ADC1/2 */
        { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
        { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -296,23 +324,27 @@ static struct hda_verb cmi9880_basic_init[] = {
 
 static struct hda_verb cmi9880_allout_init[] = {
        /* port-D for line out (rear panel) */
-       { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
        /* port-E for HP out (front panel) */
-       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
        /* route front PCM to HP */
        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
        /* port-A for side (rear panel) */
-       { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
        /* port-G for CLFE (rear panel) */
-       { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+       { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
+       /* port-H for side (rear panel) */
+       { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+       { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
        /* port-C for surround (rear panel) */
-       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
        /* port-B for mic-in (rear panel) with vref */
-       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
        /* port-F for mic-in (front panel) with vref */
-       { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
        /* CD-in */
-       { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
        /* route front mic to ADC1/2 */
        { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
        { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -347,6 +379,81 @@ static int cmi9880_build_controls(struct hda_codec *codec)
        return 0;
 }
 
+/* fill in the multi_dac_nids table, which will decide
+   which audio widget to use for each channel */
+static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
+{
+       struct cmi_spec *spec = codec->spec;
+       hda_nid_t nid;
+       int assigned[4];
+       int i, j;
+
+       /* clear the table, only one c-media dac assumed here */
+       memset(spec->dac_nids, 0, sizeof(spec->dac_nids));
+       memset(assigned, 0, sizeof(assigned));
+       /* check the pins we found */
+       for (i = 0; i < cfg->line_outs; i++) {
+               nid = cfg->line_out_pins[i];
+               /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */
+               if (nid >= 0x0b && nid <= 0x0e) {
+                       spec->dac_nids[i] = (nid - 0x0b) + 0x03;
+                       assigned[nid - 0x0b] = 1;
+               }
+       }
+       /* left pin can be connect to any audio widget */
+       for (i = 0; i < cfg->line_outs; i++) {
+               nid = cfg->line_out_pins[i];
+               if (nid <= 0x0e)
+                       continue;
+               /* search for an empty channel */
+               for (j = 0; j < cfg->line_outs; j++) {
+                       if (! assigned[j]) {
+                               spec->dac_nids[i] = i + 0x03;
+                               assigned[j] = 1;
+                               break;
+                       }
+               }
+       }
+       spec->num_dacs = cfg->line_outs;
+       return 0;
+}
+
+/* create multi_init table, which is used for multichannel initialization */
+static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
+{
+       struct cmi_spec *spec = codec->spec;
+       hda_nid_t nid;
+       int i, j, k, len;
+
+       /* clear the table, only one c-media dac assumed here */
+       memset(spec->multi_init, 0, sizeof(spec->multi_init));
+       for (j = 0, i = 0; i < cfg->line_outs; i++) {
+               hda_nid_t conn[4];
+               nid = cfg->line_out_pins[i];
+               /* set as output */
+               spec->multi_init[j].nid = nid;
+               spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL;
+               spec->multi_init[j].param = PIN_OUT;
+               j++;
+               if (nid > 0x0e) {
+                       /* set connection */
+                       spec->multi_init[j].nid = nid;
+                       spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL;
+                       spec->multi_init[j].param = 0;
+                       /* find the index in connect list */
+                       len = snd_hda_get_connections(codec, nid, conn, 4);
+                       for (k = 0; k < len; k++)
+                               if (conn[k] == spec->dac_nids[i]) {
+                                       spec->multi_init[j].param = j;
+                                       break;
+                               }
+                       j++;
+                       break;
+               }
+       }
+       return 0;
+}
+
 static int cmi9880_init(struct hda_codec *codec)
 {
        struct cmi_spec *spec = codec->spec;
@@ -354,6 +461,8 @@ static int cmi9880_init(struct hda_codec *codec)
                snd_hda_sequence_write(codec, cmi9880_allout_init);
        else
                snd_hda_sequence_write(codec, cmi9880_basic_init);
+       if (spec->board_config == CMI_AUTO)
+               snd_hda_sequence_write(codec, spec->multi_init);
        return 0;
 }
 
@@ -540,6 +649,7 @@ static struct hda_board_config cmi9880_cfg_tbl[] = {
        { .modelname = "full", .config = CMI_FULL },
        { .modelname = "full_dig", .config = CMI_FULL_DIG },
        { .modelname = "allout", .config = CMI_ALLOUT },
+       { .modelname = "auto", .config = CMI_AUTO },
        {} /* terminator */
 };
 
@@ -564,10 +674,14 @@ static int patch_cmi9880(struct hda_codec *codec)
        codec->spec = spec;
        spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
        if (spec->board_config < 0) {
-               snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
-               spec->board_config = CMI_FULL_DIG; /* try everything */
+               snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
+               spec->board_config = CMI_AUTO; /* try everything */
        }
 
+       /* copy default DAC NIDs */
+       memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids));
+       spec->num_dacs = 4;
+
        switch (spec->board_config) {
        case CMI_MINIMAL:
        case CMI_MIN_FP:
@@ -599,10 +713,58 @@ static int patch_cmi9880(struct hda_codec *codec)
                spec->input_mux = &cmi9880_no_line_mux;
                spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
                break;
+       case CMI_AUTO:
+               {
+               unsigned int port_e, port_f, port_g, port_h;
+               unsigned int port_spdifi, port_spdifo;
+               struct auto_pin_cfg cfg;
+
+               /* collect pin default configuration */
+               port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+               port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+               spec->front_panel = 1;
+               if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE ||
+                   get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
+                       port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+                       port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+                       spec->surr_switch = 1;
+                       /* no front panel */
+                       if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
+                           get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) {
+                               /* no optional rear panel */
+                               spec->board_config = CMI_MINIMAL;
+                               spec->front_panel = 0;
+                               spec->num_ch_modes = 2;
+                       } else {
+                               spec->board_config = CMI_MIN_FP;
+                               spec->num_ch_modes = 3;
+                       }
+                       spec->channel_modes = cmi9880_channel_modes;
+                       spec->input_mux = &cmi9880_basic_mux;
+                       spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
+               } else {
+                       spec->input_mux = &cmi9880_basic_mux;
+                       port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+                       port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+                       if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE)
+                               spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+                       if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE)
+                               spec->dig_in_nid = CMI_DIG_IN_NID;
+                       spec->multiout.max_channels = 8;
+               }
+               snd_hda_parse_pin_def_config(codec, &cfg);
+               if (cfg.line_outs) {
+                       spec->multiout.max_channels = cfg.line_outs * 2;
+                       cmi9880_fill_multi_dac_nids(codec, &cfg);
+                       cmi9880_fill_multi_init(codec, &cfg);
+               } else
+                       snd_printd("patch_cmedia: cannot detect association in defcfg\n");
+               break;
+               }
        }
 
-       spec->multiout.num_dacs = 4;
-       spec->multiout.dac_nids = cmi9880_dac_nids;
+       spec->multiout.num_dacs = spec->num_dacs;
+       spec->multiout.dac_nids = spec->dac_nids;
 
        spec->adc_nids = cmi9880_adc_nids;
 
index 17c5062423aee236922d940bb697ffd5822b1ea5..9edd558d6bd34359ce03714598d0de14c384f117 100644 (file)
 
 /* ALC880 board config type */
 enum {
-       ALC880_MINIMAL,
        ALC880_3ST,
        ALC880_3ST_DIG,
        ALC880_5ST,
        ALC880_5ST_DIG,
        ALC880_W810,
+       ALC880_Z71V,
+       ALC880_AUTO,
+       ALC880_6ST_DIG,
+       ALC880_F1734,
+       ALC880_ASUS,
+       ALC880_ASUS_DIG,
+       ALC880_ASUS_W1V,
+       ALC880_UNIWILL_DIG,
+#ifdef CONFIG_SND_DEBUG
+       ALC880_TEST,
+#endif
+       ALC880_MODEL_LAST /* last tag */
+};
+
+/* ALC260 models */
+enum {
+       ALC260_BASIC,
+       ALC260_HP,
+       ALC260_MODEL_LAST /* last tag */
 };
 
+/* amp values */
+#define AMP_IN_MUTE(idx)       (0x7080 | ((idx)<<8))
+#define AMP_IN_UNMUTE(idx)     (0x7000 | ((idx)<<8))
+#define AMP_OUT_MUTE   0xb080
+#define AMP_OUT_UNMUTE 0xb000
+#define AMP_OUT_ZERO   0xb000
+/* pinctl values */
+#define PIN_IN         0x20
+#define PIN_VREF80     0x24
+#define PIN_VREF50     0x21
+#define PIN_OUT                0x40
+#define PIN_HP         0xc0
+
 struct alc_spec {
        /* codec parameterization */
-       unsigned int front_panel: 1;
-
-       snd_kcontrol_new_t* mixers[2];
+       snd_kcontrol_new_t *mixers[3];  /* mixer arrays */
        unsigned int num_mixers;
 
-       struct hda_verb *init_verbs;
+       const struct hda_verb *init_verbs[3];   /* initialization verbs
+                                                * don't forget NULL termination!
+                                                */
+       unsigned int num_init_verbs;
 
-       char* stream_name_analog;
+       char *stream_name_analog;       /* analog PCM stream */
        struct hda_pcm_stream *stream_analog_playback;
        struct hda_pcm_stream *stream_analog_capture;
 
-       char* stream_name_digital;
+       char *stream_name_digital;      /* digital PCM stream */ 
        struct hda_pcm_stream *stream_digital_playback;
        struct hda_pcm_stream *stream_digital_capture;
 
        /* playback */
-       struct hda_multi_out multiout;
+       struct hda_multi_out multiout;  /* playback set-up
+                                        * max_channels, dacs must be set
+                                        * dig_out_nid and hp_nid are optional
+                                        */
 
        /* capture */
        unsigned int num_adc_nids;
        hda_nid_t *adc_nids;
-       hda_nid_t dig_in_nid;
+       hda_nid_t dig_in_nid;           /* digital-in NID; optional */
 
        /* capture source */
        const struct hda_input_mux *input_mux;
@@ -75,61 +110,17 @@ struct alc_spec {
        int num_channel_mode;
 
        /* PCM information */
-       struct hda_pcm pcm_rec[2];
-};
-
-/* DAC/ADC assignment */
-
-static hda_nid_t alc880_dac_nids[4] = {
-       /* front, rear, clfe, rear_surr */
-       0x02, 0x05, 0x04, 0x03
-};
-
-static hda_nid_t alc880_w810_dac_nids[3] = {
-       /* front, rear/surround, clfe */
-       0x02, 0x03, 0x04
-};
-
-static hda_nid_t alc880_adc_nids[3] = {
-       /* ADC0-2 */
-       0x07, 0x08, 0x09,
-};
-
-#define ALC880_DIGOUT_NID      0x06
-#define ALC880_DIGIN_NID       0x0a
-
-static hda_nid_t alc260_dac_nids[1] = {
-       /* front */
-       0x02,
-};
-
-static hda_nid_t alc260_adc_nids[2] = {
-       /* ADC0-1 */
-       0x04, 0x05,
-};
+       struct hda_pcm pcm_rec[2];      /* used in alc_build_pcms() */
 
-#define ALC260_DIGOUT_NID      0x03
-#define ALC260_DIGIN_NID       0x06
+       struct semaphore bind_mutex;    /* for bound controls */
 
-static struct hda_input_mux alc880_capture_source = {
-       .num_items = 4,
-       .items = {
-               { "Mic", 0x0 },
-               { "Front Mic", 0x3 },
-               { "Line", 0x2 },
-               { "CD", 0x4 },
-       },
+       /* dynamic controls, init_verbs and input_mux */
+       struct auto_pin_cfg autocfg;
+       unsigned int num_kctl_alloc, num_kctl_used;
+       snd_kcontrol_new_t *kctl_alloc;
+       struct hda_input_mux private_imux;
 };
 
-static struct hda_input_mux alc260_capture_source = {
-       .num_items = 4,
-       .items = {
-               { "Mic", 0x0 },
-               { "Front Mic", 0x1 },
-               { "Line", 0x2 },
-               { "CD", 0x4 },
-       },
-};
 
 /*
  * input MUX handling
@@ -160,6 +151,7 @@ static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
                                     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
 }
 
+
 /*
  * channel mode setting
  */
@@ -168,135 +160,18 @@ struct alc_channel_mode {
        const struct hda_verb *sequence;
 };
 
-
-/*
- * channel source setting (2/6 channel selection for 3-stack)
- */
-
-/*
- * set the path ways for 2 channel output
- * need to set the codec line out and mic 1 pin widgets to inputs
- */
-static struct hda_verb alc880_threestack_ch2_init[] = {
-       /* set pin widget 1Ah (line in) for input */
-       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-       /* set pin widget 18h (mic1) for input, for mic also enable the vref */
-       { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-       /* mute the output for Line In PW */
-       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-       /* mute for Mic1 PW */
-       { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-       { } /* end */
-};
-
-/*
- * 6ch mode
- * need to set the codec line out and mic 1 pin widgets to outputs
- */
-static struct hda_verb alc880_threestack_ch6_init[] = {
-       /* set pin widget 1Ah (line in) for output */
-       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-       /* set pin widget 18h (mic1) for output */
-       { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-       /* unmute the output for Line In PW */
-       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
-       /* unmute for Mic1 PW */
-       { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
-       /* for rear channel output using Line In 1
-        * set select widget connection (nid = 0x12) - to summer node
-        * for rear NID = 0x0f...offset 3 in connection list
-        */
-       { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
-       /* for Mic1 - retask for center/lfe */
-       /* set select widget connection (nid = 0x10) - to summer node for
-        * front CLFE NID = 0x0e...offset 2 in connection list
-        */
-       { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
-       { } /* end */
-};
-
-static struct alc_channel_mode alc880_threestack_modes[2] = {
-       { 2, alc880_threestack_ch2_init },
-       { 6, alc880_threestack_ch6_init },
-};
-
-
-/*
- * channel source setting (6/8 channel selection for 5-stack)
- */
-
-/* set the path ways for 6 channel output
- * need to set the codec line out and mic 1 pin widgets to inputs
- */
-static struct hda_verb alc880_fivestack_ch6_init[] = {
-       /* set pin widget 1Ah (line in) for input */
-       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-       /* mute the output for Line In PW */
-       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-       { } /* end */
-};
-
-/* need to set the codec line out and mic 1 pin widgets to outputs */
-static struct hda_verb alc880_fivestack_ch8_init[] = {
-       /* set pin widget 1Ah (line in) for output */
-       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-       /* unmute the output for Line In PW */
-       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
-       /* output for surround channel output using Line In 1 */
-       /* set select widget connection (nid = 0x12) - to summer node
-        * for surr_rear NID = 0x0d...offset 1 in connection list
-        */
-       { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
-       { } /* end */
-};
-
-static struct alc_channel_mode alc880_fivestack_modes[2] = {
-       { 6, alc880_fivestack_ch6_init },
-       { 8, alc880_fivestack_ch8_init },
-};
-
-/*
- * channel source setting for W810 system
- *
- * W810 has rear IO for:
- * Front (DAC 02)
- * Surround (DAC 03)
- * Center/LFE (DAC 04)
- * Digital out (06)
- *
- * The system also has a pair of internal speakers, and a headphone jack.
- * These are both connected to Line2 on the codec, hence to DAC 02.
- * 
- * There is a variable resistor to control the speaker or headphone
- * volume. This is a hardware-only device without a software API.
- *
- * Plugging headphones in will disable the internal speakers. This is
- * implemented in hardware, not via the driver using jack sense. In
- * a similar fashion, plugging into the rear socket marked "front" will
- * disable both the speakers and headphones.
- *
- * For input, there's a microphone jack, and an "audio in" jack.
- * These may not do anything useful with this driver yet, because I
- * haven't setup any initialization verbs for these yet...
- */
-
-static struct alc_channel_mode alc880_w810_modes[1] = {
-       { 6, NULL }
-};
-
-/*
- */
 static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct alc_spec *spec = codec->spec;
+       int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
 
        snd_assert(spec->channel_mode, return -ENXIO);
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
-       uinfo->value.enumerated.items = 2;
-       if (uinfo->value.enumerated.item >= 2)
-               uinfo->value.enumerated.item = 1;
+       uinfo->value.enumerated.items = items;
+       if (uinfo->value.enumerated.item >= items)
+               uinfo->value.enumerated.item = items - 1;
        sprintf(uinfo->value.enumerated.name, "%dch",
                spec->channel_mode[uinfo->value.enumerated.item].channels);
        return 0;
@@ -306,10 +181,16 @@ static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct alc_spec *spec = codec->spec;
+       int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
+       int i;
 
        snd_assert(spec->channel_mode, return -ENXIO);
-       ucontrol->value.enumerated.item[0] =
-               (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
+       for (i = 0; i < items; i++) {
+               if (spec->multiout.max_channels == spec->channel_mode[i].channels) {
+                       ucontrol->value.enumerated.item[0] = i;
+                       break;
+               }
+       }
        return 0;
 }
 
@@ -335,21 +216,149 @@ static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
 
 
 /*
+ * bound volume controls
+ *
+ * bind multiple volumes (# indices, from 0)
+ */
+
+#define AMP_VAL_IDX_SHIFT      19
+#define AMP_VAL_IDX_MASK       (0x0f<<19)
+
+static int alc_bind_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct alc_spec *spec = codec->spec;
+       unsigned long pval;
+
+       down(&spec->bind_mutex);
+       pval = kcontrol->private_value;
+       kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
+       snd_hda_mixer_amp_switch_info(kcontrol, uinfo);
+       kcontrol->private_value = pval;
+       up(&spec->bind_mutex);
+       return 0;
+}
+
+static int alc_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct alc_spec *spec = codec->spec;
+       unsigned long pval;
+
+       down(&spec->bind_mutex);
+       pval = kcontrol->private_value;
+       kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
+       snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
+       kcontrol->private_value = pval;
+       up(&spec->bind_mutex);
+       return 0;
+}
+
+static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct alc_spec *spec = codec->spec;
+       unsigned long pval;
+       int i, indices, change = 0;
+
+       down(&spec->bind_mutex);
+       pval = kcontrol->private_value;
+       indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
+       for (i = 0; i < indices; i++) {
+               kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT);
+               change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+       }
+       kcontrol->private_value = pval;
+       up(&spec->bind_mutex);
+       return change;
+}
+
+#define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
+       { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+         .info = alc_bind_switch_info, \
+         .get = alc_bind_switch_get, \
+         .put = alc_bind_switch_put, \
+         .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) }
+
+#define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir)
+
+
+/*
+ * ALC880 3-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
+ * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
+ *                 HP = 0x19
  */
 
-/* 3-stack mode
- * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
- *                 HP=0x19
+static hda_nid_t alc880_dac_nids[4] = {
+       /* front, rear, clfe, rear_surr */
+       0x02, 0x05, 0x04, 0x03
+};
+
+static hda_nid_t alc880_adc_nids[3] = {
+       /* ADC0-2 */
+       0x07, 0x08, 0x09,
+};
+
+/* The datasheet says the node 0x07 is connected from inputs,
+ * but it shows zero connection in the real implementation on some devices.
  */
-static snd_kcontrol_new_t alc880_base_mixer[] = {
+static hda_nid_t alc880_adc_nids_alt[2] = {
+       /* ADC1-2 */
+       0x08, 0x09,
+};
+
+#define ALC880_DIGOUT_NID      0x06
+#define ALC880_DIGIN_NID       0x0a
+
+static struct hda_input_mux alc880_capture_source = {
+       .num_items = 4,
+       .items = {
+               { "Mic", 0x0 },
+               { "Front Mic", 0x3 },
+               { "Line", 0x2 },
+               { "CD", 0x4 },
+       },
+};
+
+/* channel source setting (2/6 channel selection for 3-stack) */
+/* 2ch mode */
+static struct hda_verb alc880_threestack_ch2_init[] = {
+       /* set line-in to input, mute it */
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+       /* set mic-in to input vref 80%, mute it */
+       { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+       { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+       { } /* end */
+};
+
+/* 6ch mode */
+static struct hda_verb alc880_threestack_ch6_init[] = {
+       /* set line-in to output, unmute it */
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+       /* set mic-in to output, unmute it */
+       { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+       { } /* end */
+};
+
+static struct alc_channel_mode alc880_threestack_modes[2] = {
+       { 2, alc880_threestack_ch2_init },
+       { 6, alc880_threestack_ch6_init },
+};
+
+static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
@@ -360,25 +369,7 @@ static snd_kcontrol_new_t alc880_base_mixer[] = {
        HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
        HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
        HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               /* The multiple "Capture Source" controls confuse alsamixer
-                * So call somewhat different..
-                * FIXME: the controls appear in the "playback" view!
-                */
-               /* .name = "Capture Source", */
-               .name = "Input Source",
-               .count = 2,
-               .info = alc_mux_enum_info,
-               .get = alc_mux_enum_get,
-               .put = alc_mux_enum_put,
-       },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Channel Mode",
@@ -389,37 +380,14 @@ static snd_kcontrol_new_t alc880_base_mixer[] = {
        { } /* end */
 };
 
-/* 5-stack mode
- * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
- *                 Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
- */
-static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
-       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
-       HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
-       HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
-       HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+/* capture mixer elements */
+static snd_kcontrol_new_t alc880_capture_mixer[] = {
        HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                /* The multiple "Capture Source" controls confuse alsamixer
@@ -428,37 +396,20 @@ static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
                 */
                /* .name = "Capture Source", */
                .name = "Input Source",
-               .count = 2,
+               .count = 3,
                .info = alc_mux_enum_info,
                .get = alc_mux_enum_get,
                .put = alc_mux_enum_put,
        },
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Channel Mode",
-               .info = alc880_ch_mode_info,
-               .get = alc880_ch_mode_get,
-               .put = alc880_ch_mode_put,
-       },
        { } /* end */
 };
 
-static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
-       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
+/* capture mixer elements (in case NID 0x07 not available) */
+static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
+       HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                /* The multiple "Capture Source" controls confuse alsamixer
@@ -467,7 +418,7 @@ static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
                 */
                /* .name = "Capture Source", */
                .name = "Input Source",
-               .count = 3,
+               .count = 2,
                .info = alc_mux_enum_info,
                .get = alc_mux_enum_get,
                .put = alc_mux_enum_put,
@@ -475,7 +426,268 @@ static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
        { } /* end */
 };
 
-/*
+
+
+/*
+ * ALC880 5-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
+ * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
+ *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
+ */
+
+/* additional mixers to alc880_three_stack_mixer */
+static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
+       HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
+       { } /* end */
+};
+
+/* channel source setting (6/8 channel selection for 5-stack) */
+/* 6ch mode */
+static struct hda_verb alc880_fivestack_ch6_init[] = {
+       /* set line-in to input, mute it */
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+       { } /* end */
+};
+
+/* 8ch mode */
+static struct hda_verb alc880_fivestack_ch8_init[] = {
+       /* set line-in to output, unmute it */
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+       { } /* end */
+};
+
+static struct alc_channel_mode alc880_fivestack_modes[2] = {
+       { 6, alc880_fivestack_ch6_init },
+       { 8, alc880_fivestack_ch8_init },
+};
+
+
+/*
+ * ALC880 6-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
+ * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
+ *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
+ */
+
+static hda_nid_t alc880_6st_dac_nids[4] = {
+       /* front, rear, clfe, rear_surr */
+       0x02, 0x03, 0x04, 0x05
+};     
+
+static struct hda_input_mux alc880_6stack_capture_source = {
+       .num_items = 4,
+       .items = {
+               { "Mic", 0x0 },
+               { "Front Mic", 0x1 },
+               { "Line", 0x2 },
+               { "CD", 0x4 },
+       },
+};
+
+/* fixed 8-channels */
+static struct alc_channel_mode alc880_sixstack_modes[1] = {
+       { 8, NULL },
+};
+
+static snd_kcontrol_new_t alc880_six_stack_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+       HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Channel Mode",
+               .info = alc880_ch_mode_info,
+               .get = alc880_ch_mode_get,
+               .put = alc880_ch_mode_put,
+       },
+       { } /* end */
+};
+
+
+/*
+ * ALC880 W810 model
+ *
+ * W810 has rear IO for:
+ * Front (DAC 02)
+ * Surround (DAC 03)
+ * Center/LFE (DAC 04)
+ * Digital out (06)
+ *
+ * The system also has a pair of internal speakers, and a headphone jack.
+ * These are both connected to Line2 on the codec, hence to DAC 02.
+ * 
+ * There is a variable resistor to control the speaker or headphone
+ * volume. This is a hardware-only device without a software API.
+ *
+ * Plugging headphones in will disable the internal speakers. This is
+ * implemented in hardware, not via the driver using jack sense. In
+ * a similar fashion, plugging into the rear socket marked "front" will
+ * disable both the speakers and headphones.
+ *
+ * For input, there's a microphone jack, and an "audio in" jack.
+ * These may not do anything useful with this driver yet, because I
+ * haven't setup any initialization verbs for these yet...
+ */
+
+static hda_nid_t alc880_w810_dac_nids[3] = {
+       /* front, rear/surround, clfe */
+       0x02, 0x03, 0x04
+};
+
+/* fixed 6 channels */
+static struct alc_channel_mode alc880_w810_modes[1] = {
+       { 6, NULL }
+};
+
+/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
+static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+       { } /* end */
+};
+
+
+/*
+ * Z710V model
+ *
+ * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
+ * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
+ */
+
+static hda_nid_t alc880_z71v_dac_nids[1] = {
+       0x02
+};
+#define ALC880_Z71V_HP_DAC     0x03
+
+/* fixed 2 channels */
+static struct alc_channel_mode alc880_2_jack_modes[1] = {
+       { 2, NULL }
+};
+
+static snd_kcontrol_new_t alc880_z71v_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
+
+/* FIXME! */
+/*
+ * ALC880 F1734 model
+ *
+ * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
+ * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
+ */
+
+static hda_nid_t alc880_f1734_dac_nids[1] = {
+       0x03
+};
+#define ALC880_F1734_HP_DAC    0x02
+
+static snd_kcontrol_new_t alc880_f1734_mixer[] = {
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
+
+/* FIXME! */
+/*
+ * ALC880 ASUS model
+ *
+ * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
+ * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
+ *  Mic = 0x18, Line = 0x1a
+ */
+
+#define alc880_asus_dac_nids   alc880_w810_dac_nids    /* identical with w810 */
+#define alc880_asus_modes      alc880_threestack_modes /* 2/6 channel mode */
+
+static snd_kcontrol_new_t alc880_asus_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Channel Mode",
+               .info = alc880_ch_mode_info,
+               .get = alc880_ch_mode_get,
+               .put = alc880_ch_mode_put,
+       },
+       { } /* end */
+};
+
+/* FIXME! */
+/*
+ * ALC880 ASUS W1V model
+ *
+ * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
+ * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
+ *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
+ */
+
+/* additional mixers to alc880_asus_mixer */
+static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = {
+       HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
+       HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
+       { } /* end */
+};
+
+
+/*
+ * build control elements
  */
 static int alc_build_controls(struct hda_codec *codec)
 {
@@ -502,227 +714,297 @@ static int alc_build_controls(struct hda_codec *codec)
        return 0;
 }
 
+
 /*
  * initialize the codec volumes, etc
  */
 
-static struct hda_verb alc880_init_verbs_three_stack[] = {
-       /* Line In pin widget for input */
-       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-       /* CD pin widget for input */
-       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-       /* Mic1 (rear panel) pin widget for input and vref at 80% */
-       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-       /* Mic2 (front panel) pin widget for input and vref at 80% */
-       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-       /* unmute amp left and right */
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-       /* set connection select to line in (default select for this ADC) */
-       {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
-       /* unmute front mixer amp left (volume = 0) */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* unmute rear mixer amp left and right (volume = 0) */
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* unmute rear mixer amp left and right (volume = 0) */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
-       /* using rear surround as the path for headphone output */
-       /* unmute rear surround mixer amp left and right (volume = 0) */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* PASD 3 stack boards use the Mic 2 as the headphone output */
-       /* need to program the selector associated with the Mic 2 pin widget to
-        * surround path (index 0x01) for headphone output */
-       {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* need to retask the Mic 2 pin widget to output */
-       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
-       /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
-        * to support the input path of analog loopback
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc880_volume_init_verbs[] = {
+       /*
+        * Unmute ADC0-2 and set the default input to mic-in
+        */
+       {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+       /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+        * mixer widget
         * Note: PASD motherboards uses the Line In 2 as the input for front panel
         * mic (mic 2)
         */
-       /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
-       /* unmute CD */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
-       /* unmute Line In */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-       /* unmute Mic 1 */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       /* unmute Line In 2 (for PASD boards Mic 2) */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-
-       /* Unmute input amps for the line out paths to support the output path of
-        * analog loopback
-        * the mixers on the output path has 2 inputs, one from the DAC and one
-        * from the mixer
+       /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+       /*
+        * Set up output mixers (0x0c - 0x0f)
         */
-       /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-       /* Unmute Front out path */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       /* Unmute Surround (used as HP) out path */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       /* Unmute C/LFE out path */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
-       /* Unmute rear Surround out path */
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+       /* set vol=0 to output mixers */
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       /* set up input amps for analog loopback */
+       /* Amp Indices: DAC = 0, mixer = 1 */
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 
        { }
 };
 
-static struct hda_verb alc880_init_verbs_five_stack[] = {
-       /* Line In pin widget for input */
-       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-       /* CD pin widget for input */
-       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-       /* Mic1 (rear panel) pin widget for input and vref at 80% */
-       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-       /* Mic2 (front panel) pin widget for input and vref at 80% */
-       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-       /* unmute amp left and right */
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-       /* set connection select to line in (default select for this ADC) */
-       {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
-       /* unmute front mixer amp left and right (volume = 0) */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* five rear and clfe */
-       /* unmute rear mixer amp left and right (volume = 0)  */
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* unmute clfe mixer amp left and right (volume = 0) */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
-       /* using rear surround as the path for headphone output */
-       /* unmute rear surround mixer amp left and right (volume = 0) */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* PASD 3 stack boards use the Mic 2 as the headphone output */
-       /* need to program the selector associated with the Mic 2 pin widget to
-        * surround path (index 0x01) for headphone output
-        */
-       {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* need to retask the Mic 2 pin widget to output */
-       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
-       /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
-        * widget(nid=0x0B) to support the input path of analog loopback
+/*
+ * 3-stack pin configuration:
+ * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
+ */
+static struct hda_verb alc880_pin_3stack_init_verbs[] = {
+       /*
+        * preset connection lists of input pins
+        * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
         */
-       /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
-       /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
-       /* unmute CD */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
-       /* unmute Line In */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-       /* unmute Mic 1 */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       /* unmute Line In 2 (for PASD boards Mic 2) */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-
-       /* Unmute input amps for the line out paths to support the output path of
-        * analog loopback
-        * the mixers on the output path has 2 inputs, one from the DAC and
-        * one from the mixer
+       {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+       {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+       {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
+
+       /*
+        * Set pin mode and muting
         */
-       /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-       /* Unmute Front out path */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       /* Unmute Surround (used as HP) out path */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       /* Unmute C/LFE out path */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
-       /* Unmute rear Surround out path */
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+       /* set front pin widgets 0x14 for output */
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* Mic1 (rear panel) pin widget for input and vref at 80% */
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Mic2 (as headphone out) for HP output */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* Line In pin widget for input */
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Line2 (as front mic) pin widget for input and vref at 80% */
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* CD pin widget for input */
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
        { }
 };
 
-static struct hda_verb alc880_w810_init_verbs[] = {
-       /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-
-       /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
-
-       /* front channel selector/amp: output 0: unmuted, max volume */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-
-       /* front out pin: muted, (no volume selection)  */
-       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-
-       /* front out pin: NOT headphone enable, out enable, vref disabled */
-       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+/*
+ * 5-stack pin configuration:
+ * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
+ * line-in/side = 0x1a, f-mic = 0x1b
+ */
+static struct hda_verb alc880_pin_5stack_init_verbs[] = {
+       /*
+        * preset connection lists of input pins
+        * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
+        */
+       {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+       {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
 
+       /*
+        * Set pin mode and muting
+        */
+       /* set pin widgets 0x14-0x17 for output */
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       /* unmute pins for output (no gain on this amp) */
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 
-       /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+       /* Mic1 (rear panel) pin widget for input and vref at 80% */
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Mic2 (as headphone out) for HP output */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* Line In pin widget for input */
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Line2 (as front mic) pin widget for input and vref at 80% */
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* CD pin widget for input */
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
-       /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+       { }
+};
 
-       /* surround channel selector/amp: output 0: unmuted, max volume */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+/*
+ * W810 pin configuration:
+ * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
+ */
+static struct hda_verb alc880_pin_w810_init_verbs[] = {
+       /* hphone/speaker input selector: front DAC */
+       {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
 
-       /* surround out pin: muted, (no volume selection)  */
-       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 
-       /* surround out pin: NOT headphone enable, out enable, vref disabled */
-       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
+       { }
+};
 
-       /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+/*
+ * Z71V pin configuration:
+ * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
+ */
+static struct hda_verb alc880_pin_z71v_init_verbs[] = {
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 
-       /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
-       /* c/lfe channel selector/amp: output 0: unmuted, max volume */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+       { }
+};
 
-       /* c/lfe out pin: muted, (no volume selection)  */
-       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+/*
+ * 6-stack pin configuration:
+ * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
+ * line = 0x1a, HP = 0x1b
+ */
+static struct hda_verb alc880_pin_6stack_init_verbs[] = {
+       {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       
+       { }
+};
 
-       /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
-       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+/* FIXME! */
+/*
+ * F1734 pin configuration:
+ * HP = 0x14, speaker-out = 0x15, mic = 0x18
+ */
+static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+       {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+       {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
+       { }
+};
 
-       /* hphone/speaker input selector: front DAC */
-       {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
+/* FIXME! */
+/*
+ * ASUS pin configuration:
+ * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
+ */
+static struct hda_verb alc880_pin_asus_init_verbs[] = {
+       {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+       {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+       {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       
+       { }
+};
 
-       /* hphone/speaker out pin: muted, (no volume selection)  */
-       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+/* Enable GPIO mask and set output */
+static struct hda_verb alc880_gpio1_init_verbs[] = {
+       {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+       {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+};
 
-       /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
-       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+/* Enable GPIO mask and set output */
+static struct hda_verb alc880_gpio2_init_verbs[] = {
+       {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
+       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
+       {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
+};
 
 
-       { }
-};
+/*
+ */
 
 static int alc_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       snd_hda_sequence_write(codec, spec->init_verbs);
+       unsigned int i;
+
+       for (i = 0; i < spec->num_init_verbs; i++)
+               snd_hda_sequence_write(codec, spec->init_verbs[i]);
        return 0;
 }
 
@@ -736,9 +1018,8 @@ static int alc_resume(struct hda_codec *codec)
        int i;
 
        alc_init(codec);
-       for (i = 0; i < spec->num_mixers; i++) {
+       for (i = 0; i < spec->num_mixers; i++)
                snd_hda_resume_ctls(codec, spec->mixers[i]);
-       }
        if (spec->multiout.dig_out_nid)
                snd_hda_resume_spdif_out(codec);
        if (spec->dig_in_nid)
@@ -813,261 +1094,1036 @@ static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
        return 0;
 }
 
-static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-                                     struct hda_codec *codec,
-                                     snd_pcm_substream_t *substream)
+static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+                                     struct hda_codec *codec,
+                                     snd_pcm_substream_t *substream)
+{
+       struct alc_spec *spec = codec->spec;
+
+       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+       return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream alc880_pcm_analog_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 8,
+       /* NID is set in alc_build_pcms */
+       .ops = {
+               .open = alc880_playback_pcm_open,
+               .prepare = alc880_playback_pcm_prepare,
+               .cleanup = alc880_playback_pcm_cleanup
+       },
+};
+
+static struct hda_pcm_stream alc880_pcm_analog_capture = {
+       .substreams = 2,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in alc_build_pcms */
+       .ops = {
+               .prepare = alc880_capture_pcm_prepare,
+               .cleanup = alc880_capture_pcm_cleanup
+       },
+};
+
+static struct hda_pcm_stream alc880_pcm_digital_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in alc_build_pcms */
+       .ops = {
+               .open = alc880_dig_playback_pcm_open,
+               .close = alc880_dig_playback_pcm_close
+       },
+};
+
+static struct hda_pcm_stream alc880_pcm_digital_capture = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in alc_build_pcms */
+};
+
+static int alc_build_pcms(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       struct hda_pcm *info = spec->pcm_rec;
+       int i;
+
+       codec->num_pcms = 1;
+       codec->pcm_info = info;
+
+       info->name = spec->stream_name_analog;
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
+       info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+       info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
+       for (i = 0; i < spec->num_channel_mode; i++) {
+               if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
+                   info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
+               }
+       }
+
+       if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+               codec->num_pcms++;
+               info++;
+               info->name = spec->stream_name_digital;
+               if (spec->multiout.dig_out_nid) {
+                       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
+                       info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+               }
+               if (spec->dig_in_nid) {
+                       info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
+                       info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+               }
+       }
+
+       return 0;
+}
+
+static void alc_free(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       unsigned int i;
+
+       if (! spec)
+               return;
+
+       if (spec->kctl_alloc) {
+               for (i = 0; i < spec->num_kctl_used; i++)
+                       kfree(spec->kctl_alloc[i].name);
+               kfree(spec->kctl_alloc);
+       }
+       kfree(spec);
+}
+
+/*
+ */
+static struct hda_codec_ops alc_patch_ops = {
+       .build_controls = alc_build_controls,
+       .build_pcms = alc_build_pcms,
+       .init = alc_init,
+       .free = alc_free,
+#ifdef CONFIG_PM
+       .resume = alc_resume,
+#endif
+};
+
+
+/*
+ * Test configuration for debugging
+ *
+ * Almost all inputs/outputs are enabled.  I/O pins can be configured via
+ * enum controls.
+ */
+#ifdef CONFIG_SND_DEBUG
+static hda_nid_t alc880_test_dac_nids[4] = {
+       0x02, 0x03, 0x04, 0x05
+};
+
+static struct hda_input_mux alc880_test_capture_source = {
+       .num_items = 5,
+       .items = {
+               { "In-1", 0x0 },
+               { "In-2", 0x1 },
+               { "In-3", 0x2 },
+               { "In-4", 0x3 },
+               { "CD", 0x4 },
+       },
+};
+
+static struct alc_channel_mode alc880_test_modes[4] = {
+       { 2, NULL },
+       { 4, NULL },
+       { 6, NULL },
+       { 8, NULL },
+};
+
+static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       static char *texts[] = {
+               "N/A", "Line Out", "HP Out",
+               "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
+       };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 8;
+       if (uinfo->value.enumerated.item >= 8)
+               uinfo->value.enumerated.item = 7;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+       unsigned int pin_ctl, item = 0;
+
+       pin_ctl = snd_hda_codec_read(codec, nid, 0,
+                                    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+       if (pin_ctl & AC_PINCTL_OUT_EN) {
+               if (pin_ctl & AC_PINCTL_HP_EN)
+                       item = 2;
+               else
+                       item = 1;
+       } else if (pin_ctl & AC_PINCTL_IN_EN) {
+               switch (pin_ctl & AC_PINCTL_VREFEN) {
+               case AC_PINCTL_VREF_HIZ: item = 3; break;
+               case AC_PINCTL_VREF_50:  item = 4; break;
+               case AC_PINCTL_VREF_GRD: item = 5; break;
+               case AC_PINCTL_VREF_80:  item = 6; break;
+               case AC_PINCTL_VREF_100: item = 7; break;
+               }
+       }
+       ucontrol->value.enumerated.item[0] = item;
+       return 0;
+}
+
+static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+       static unsigned int ctls[] = {
+               0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
+               AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
+               AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
+               AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
+               AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
+               AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
+       };
+       unsigned int old_ctl, new_ctl;
+
+       old_ctl = snd_hda_codec_read(codec, nid, 0,
+                                    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+       new_ctl = ctls[ucontrol->value.enumerated.item[0]];
+       if (old_ctl != new_ctl) {
+               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
+               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                                   ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
+               return 1;
+       }
+       return 0;
+}
+
+static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       static char *texts[] = {
+               "Front", "Surround", "CLFE", "Side"
+       };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 4;
+       if (uinfo->value.enumerated.item >= 4)
+               uinfo->value.enumerated.item = 3;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+       unsigned int sel;
+
+       sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
+       ucontrol->value.enumerated.item[0] = sel & 3;
+       return 0;
+}
+
+static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+       unsigned int sel;
+
+       sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
+       if (ucontrol->value.enumerated.item[0] != sel) {
+               sel = ucontrol->value.enumerated.item[0] & 3;
+               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
+               return 1;
+       }
+       return 0;
+}
+
+#define PIN_CTL_TEST(xname,nid) {                      \
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    \
+                       .name = xname,                 \
+                       .info = alc_test_pin_ctl_info, \
+                       .get = alc_test_pin_ctl_get,   \
+                       .put = alc_test_pin_ctl_put,   \
+                       .private_value = nid           \
+                       }
+
+#define PIN_SRC_TEST(xname,nid) {                      \
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    \
+                       .name = xname,                 \
+                       .info = alc_test_pin_src_info, \
+                       .get = alc_test_pin_src_get,   \
+                       .put = alc_test_pin_src_put,   \
+                       .private_value = nid           \
+                       }
+
+static snd_kcontrol_new_t alc880_test_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT),
+       ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT),
+       PIN_CTL_TEST("Front Pin Mode", 0x14),
+       PIN_CTL_TEST("Surround Pin Mode", 0x15),
+       PIN_CTL_TEST("CLFE Pin Mode", 0x16),
+       PIN_CTL_TEST("Side Pin Mode", 0x17),
+       PIN_CTL_TEST("In-1 Pin Mode", 0x18),
+       PIN_CTL_TEST("In-2 Pin Mode", 0x19),
+       PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
+       PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
+       PIN_SRC_TEST("In-1 Pin Source", 0x18),
+       PIN_SRC_TEST("In-2 Pin Source", 0x19),
+       PIN_SRC_TEST("In-3 Pin Source", 0x1a),
+       PIN_SRC_TEST("In-4 Pin Source", 0x1b),
+       HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
+       HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
+       HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
+       HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Input Source",
+               .count = 2,
+               .info = alc_mux_enum_info,
+               .get = alc_mux_enum_get,
+               .put = alc_mux_enum_put,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Channel Mode",
+               .info = alc880_ch_mode_info,
+               .get = alc880_ch_mode_get,
+               .put = alc880_ch_mode_put,
+       },
+       { } /* end */
+};
+
+static struct hda_verb alc880_test_init_verbs[] = {
+       /* Unmute inputs of 0x0c - 0x0f */
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       /* Vol output for 0x0c-0x0f */
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       /* Set output pins 0x14-0x17 */
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       /* Unmute output pins 0x14-0x17 */
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* Set input pins 0x18-0x1c */
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       /* Mute input pins 0x18-0x1b */
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* ADC set up */
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+       /* Analog input/passthru */
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+       { }
+};
+#endif
+
+/*
+ */
+
+static struct hda_board_config alc880_cfg_tbl[] = {
+       /* Back 3 jack, front 2 jack */
+       { .modelname = "3stack", .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
+
+       /* Back 3 jack, front 2 jack (Internal add Aux-In) */
+       { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
+       { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, 
+
+       /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
+       { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
+
+       /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
+       { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
+
+       /* Back 5 jack, front 2 jack */
+       { .modelname = "5stack", .config = ALC880_5ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
+       { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
+       { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
+
+       /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
+       { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
+       { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG },
+
+       { .modelname = "w810", .config = ALC880_W810 },
+       { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
+
+       { .modelname = "z71v", .config = ALC880_Z71V },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
+
+       { .modelname = "6statack-digout", .config = ALC880_6ST_DIG },
+       { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
+       { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
+       { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
+       { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
+
+       { .modelname = "asus", .config = ALC880_ASUS },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
+       { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
+
+       { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
+       { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },     
+
+       { .modelname = "F1734", .config = ALC880_F1734 },
+       { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
+
+#ifdef CONFIG_SND_DEBUG
+       { .modelname = "test", .config = ALC880_TEST },
+#endif
+
+       {}
+};
+
+/*
+ * configuration template - to be copied to the spec instance
+ */
+struct alc_config_preset {
+       snd_kcontrol_new_t *mixers[4];
+       const struct hda_verb *init_verbs[4];
+       unsigned int num_dacs;
+       hda_nid_t *dac_nids;
+       hda_nid_t dig_out_nid;          /* optional */
+       hda_nid_t hp_nid;               /* optional */
+       unsigned int num_adc_nids;
+       hda_nid_t *adc_nids;
+       unsigned int num_channel_mode;
+       const struct alc_channel_mode *channel_mode;
+       const struct hda_input_mux *input_mux;
+};
+
+static struct alc_config_preset alc880_presets[] = {
+       [ALC880_3ST] = {
+               .mixers = { alc880_three_stack_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+               .dac_nids = alc880_dac_nids,
+               .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+               .channel_mode = alc880_threestack_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_3ST_DIG] = {
+               .mixers = { alc880_three_stack_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+               .dac_nids = alc880_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+               .channel_mode = alc880_threestack_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_5ST] = {
+               .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+               .dac_nids = alc880_dac_nids,
+               .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
+               .channel_mode = alc880_fivestack_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_5ST_DIG] = {
+               .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+               .dac_nids = alc880_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
+               .channel_mode = alc880_fivestack_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_6ST_DIG] = {
+               .mixers = { alc880_six_stack_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
+               .dac_nids = alc880_6st_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
+               .channel_mode = alc880_sixstack_modes,
+               .input_mux = &alc880_6stack_capture_source,
+       },
+       [ALC880_W810] = {
+               .mixers = { alc880_w810_base_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
+               .dac_nids = alc880_w810_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
+               .channel_mode = alc880_w810_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_Z71V] = {
+               .mixers = { alc880_z71v_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs,
+                               alc880_gpio2_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
+               .dac_nids = alc880_z71v_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .hp_nid = 0x03,
+               .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+               .channel_mode = alc880_2_jack_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_F1734] = {
+               .mixers = { alc880_f1734_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
+               .dac_nids = alc880_f1734_dac_nids,
+               .hp_nid = 0x02,
+               .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+               .channel_mode = alc880_2_jack_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_ASUS] = {
+               .mixers = { alc880_asus_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+                               alc880_gpio1_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+               .dac_nids = alc880_asus_dac_nids,
+               .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+               .channel_mode = alc880_asus_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_ASUS_DIG] = {
+               .mixers = { alc880_asus_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+                               alc880_gpio1_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+               .dac_nids = alc880_asus_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+               .channel_mode = alc880_asus_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_ASUS_W1V] = {
+               .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+                               alc880_gpio1_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+               .dac_nids = alc880_asus_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+               .channel_mode = alc880_asus_modes,
+               .input_mux = &alc880_capture_source,
+       },
+       [ALC880_UNIWILL_DIG] = {
+               .mixers = { alc880_asus_mixer },
+               .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+               .dac_nids = alc880_asus_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+               .channel_mode = alc880_asus_modes,
+               .input_mux = &alc880_capture_source,
+       },
+#ifdef CONFIG_SND_DEBUG
+       [ALC880_TEST] = {
+               .mixers = { alc880_test_mixer },
+               .init_verbs = { alc880_test_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
+               .dac_nids = alc880_test_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
+               .channel_mode = alc880_test_modes,
+               .input_mux = &alc880_test_capture_source,
+       },
+#endif
+};
+
+/*
+ * Automatic parse of I/O pins from the BIOS configuration
+ */
+
+#define NUM_CONTROL_ALLOC      32
+#define NUM_VERB_ALLOC         32
+
+enum {
+       ALC_CTL_WIDGET_VOL,
+       ALC_CTL_WIDGET_MUTE,
+       ALC_CTL_BIND_MUTE,
+};
+static snd_kcontrol_new_t alc880_control_templates[] = {
+       HDA_CODEC_VOLUME(NULL, 0, 0, 0),
+       HDA_CODEC_MUTE(NULL, 0, 0, 0),
+       ALC_BIND_MUTE(NULL, 0, 0, 0),
+};
+
+/* add dynamic controls */
+static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
+{
+       snd_kcontrol_new_t *knew;
+
+       if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+               int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+               knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
+               if (! knew)
+                       return -ENOMEM;
+               if (spec->kctl_alloc) {
+                       memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
+                       kfree(spec->kctl_alloc);
+               }
+               spec->kctl_alloc = knew;
+               spec->num_kctl_alloc = num;
+       }
+
+       knew = &spec->kctl_alloc[spec->num_kctl_used];
+       *knew = alc880_control_templates[type];
+       knew->name = snd_kmalloc_strdup(name, GFP_KERNEL);
+       if (! knew->name)
+               return -ENOMEM;
+       knew->private_value = val;
+       spec->num_kctl_used++;
+       return 0;
+}
+
+#define alc880_is_fixed_pin(nid)       ((nid) >= 0x14 && (nid) <= 0x17)
+#define alc880_fixed_pin_idx(nid)      ((nid) - 0x14)
+#define alc880_is_multi_pin(nid)       ((nid) >= 0x18)
+#define alc880_multi_pin_idx(nid)      ((nid) - 0x18)
+#define alc880_is_input_pin(nid)       ((nid) >= 0x18)
+#define alc880_input_pin_idx(nid)      ((nid) - 0x18)
+#define alc880_idx_to_dac(nid)         ((nid) + 0x02)
+#define alc880_dac_to_idx(nid)         ((nid) - 0x02)
+#define alc880_idx_to_mixer(nid)       ((nid) + 0x0c)
+#define alc880_idx_to_selector(nid)    ((nid) + 0x10)
+#define ALC880_PIN_CD_NID              0x1c
+
+/* fill in the dac_nids table from the parsed pin configuration */
+static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+       hda_nid_t nid;
+       int assigned[4];
+       int i, j;
+
+       memset(assigned, 0, sizeof(assigned));
+
+       /* check the pins hardwired to audio widget */
+       for (i = 0; i < cfg->line_outs; i++) {
+               nid = cfg->line_out_pins[i];
+               if (alc880_is_fixed_pin(nid)) {
+                       int idx = alc880_fixed_pin_idx(nid);
+                       spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx);
+                       assigned[idx] = 1;
+               }
+       }
+       /* left pins can be connect to any audio widget */
+       for (i = 0; i < cfg->line_outs; i++) {
+               nid = cfg->line_out_pins[i];
+               if (alc880_is_fixed_pin(nid))
+                       continue;
+               /* search for an empty channel */
+               for (j = 0; j < cfg->line_outs; j++) {
+                       if (! assigned[j]) {
+                               spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
+                               assigned[j] = 1;
+                               break;
+                       }
+               }
+       }
+       spec->multiout.num_dacs = cfg->line_outs;
+       return 0;
+}
+
+/* add playback controls from the parsed DAC table */
+static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
 {
-       struct alc_spec *spec = codec->spec;
+       char name[32];
+       static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
+       hda_nid_t nid;
+       int i, err;
+
+       for (i = 0; i < cfg->line_outs; i++) {
+               if (! spec->multiout.dac_nids[i])
+                       continue;
+               nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
+               if (i == 2) {
+                       /* Center/LFE */
+                       if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
+                                              HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
+                               return err;
+                       if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
+                                              HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+                               return err;
+                       if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
+                                              HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
+                               return err;
+                       if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
+                                              HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
+                               return err;
+               } else {
+                       sprintf(name, "%s Playback Volume", chname[i]);
+                       if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+                                              HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+                               return err;
+                       sprintf(name, "%s Playback Switch", chname[i]);
+                       if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+                                              HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+                               return err;
+               }
+       }
 
-       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
        return 0;
 }
 
+/* add playback controls for HP output */
+static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
+{
+       hda_nid_t nid;
+       int err;
 
-/*
- */
-static struct hda_pcm_stream alc880_pcm_analog_playback = {
-       .substreams = 1,
-       .channels_min = 2,
-       .channels_max = 8,
-       .nid = 0x02, /* NID to query formats and rates */
-       .ops = {
-               .open = alc880_playback_pcm_open,
-               .prepare = alc880_playback_pcm_prepare,
-               .cleanup = alc880_playback_pcm_cleanup
-       },
-};
+       if (! pin)
+               return 0;
 
-static struct hda_pcm_stream alc880_pcm_analog_capture = {
-       .substreams = 2,
-       .channels_min = 2,
-       .channels_max = 2,
-       .nid = 0x07, /* NID to query formats and rates */
-       .ops = {
-               .prepare = alc880_capture_pcm_prepare,
-               .cleanup = alc880_capture_pcm_cleanup
-       },
-};
+       if (alc880_is_fixed_pin(pin)) {
+               nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
+               if (! spec->multiout.dac_nids[0]) {
+                       /* use this as the primary output */
+                       spec->multiout.dac_nids[0] = nid;
+                       if (! spec->multiout.num_dacs)
+                               spec->multiout.num_dacs = 1;
+               } else 
+                       /* specify the DAC as the extra HP output */
+                       spec->multiout.hp_nid = nid;
+               /* control HP volume/switch on the output mixer amp */
+               nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
+               if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
+                                      HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+                       return err;
+               if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch",
+                                      HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+                       return err;
+       } else if (alc880_is_multi_pin(pin)) {
+               /* set manual connection */
+               if (! spec->multiout.dac_nids[0]) {
+                       /* use this as the primary output */
+                       spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
+                       if (! spec->multiout.num_dacs)
+                               spec->multiout.num_dacs = 1;
+               }
+               /* we have only a switch on HP-out PIN */
+               if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
+                                      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
+                       return err;
+       }
+       return 0;
+}
 
-static struct hda_pcm_stream alc880_pcm_digital_playback = {
-       .substreams = 1,
-       .channels_min = 2,
-       .channels_max = 2,
-       /* NID is set in alc_build_pcms */
-       .ops = {
-               .open = alc880_dig_playback_pcm_open,
-               .close = alc880_dig_playback_pcm_close
-       },
-};
+/* create input playback/capture controls for the given pin */
+static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname)
+{
+       char name[32];
+       int err, idx;
+
+       sprintf(name, "%s Playback Volume", ctlname);
+       idx = alc880_input_pin_idx(pin);
+       if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+                              HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
+               return err;
+       sprintf(name, "%s Playback Switch", ctlname);
+       if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+                              HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
+               return err;
+       return 0;
+}
 
-static struct hda_pcm_stream alc880_pcm_digital_capture = {
-       .substreams = 1,
-       .channels_min = 2,
-       .channels_max = 2,
-       /* NID is set in alc_build_pcms */
-};
+/* create playback/capture controls for input pins */
+static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+       static char *labels[AUTO_PIN_LAST] = {
+               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
+       };
+       struct hda_input_mux *imux = &spec->private_imux;
+       int i, err;
+
+       for (i = 0; i < AUTO_PIN_LAST; i++) {
+               if (alc880_is_input_pin(cfg->input_pins[i])) {
+                       err = new_analog_input(spec, cfg->input_pins[i], labels[i]);
+                       if (err < 0)
+                               return err;
+                       imux->items[imux->num_items].label = labels[i];
+                       imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
+                       imux->num_items++;
+               }
+       }
+       return 0;
+}
 
-static int alc_build_pcms(struct hda_codec *codec)
+static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type,
+                                             int dac_idx)
+{
+       /* set as output */
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+       /* need the manual connection? */
+       if (alc880_is_multi_pin(nid)) {
+               struct alc_spec *spec = codec->spec;
+               int idx = alc880_multi_pin_idx(nid);
+               snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
+                                   AC_VERB_SET_CONNECT_SEL,
+                                   alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
+       }
+}
+
+static void alc880_auto_init_multi_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       struct hda_pcm *info = spec->pcm_rec;
        int i;
 
-       codec->num_pcms = 1;
-       codec->pcm_info = info;
-
-       info->name = spec->stream_name_analog;
-       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
-       info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
-
-       info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
-       for (i = 0; i < spec->num_channel_mode; i++) {
-               if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
-                   info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
-               }
+       for (i = 0; i < spec->autocfg.line_outs; i++) {
+               hda_nid_t nid = spec->autocfg.line_out_pins[i];
+               alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
        }
+}
 
-       if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
-               codec->num_pcms++;
-               info++;
-               info->name = spec->stream_name_digital;
-               if (spec->multiout.dig_out_nid) {
-                       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
-                       info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
-               }
-               if (spec->dig_in_nid) {
-                       info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
-                       info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
-               }
-       }
+static void alc880_auto_init_hp_out(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       hda_nid_t pin;
 
-       return 0;
+       pin = spec->autocfg.hp_pin;
+       if (pin) /* connect to front */
+               alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
 }
 
-static void alc_free(struct hda_codec *codec)
+static void alc880_auto_init_analog_input(struct hda_codec *codec)
 {
-       kfree(codec->spec);
+       struct alc_spec *spec = codec->spec;
+       int i;
+
+       for (i = 0; i < AUTO_PIN_LAST; i++) {
+               hda_nid_t nid = spec->autocfg.input_pins[i];
+               if (alc880_is_input_pin(nid)) {
+                       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                           i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+                       if (nid != ALC880_PIN_CD_NID)
+                               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                                                   AMP_OUT_MUTE);
+               }
+       }
 }
 
-/*
- */
-static struct hda_codec_ops alc_patch_ops = {
-       .build_controls = alc_build_controls,
-       .build_pcms = alc_build_pcms,
-       .init = alc_init,
-       .free = alc_free,
-#ifdef CONFIG_PM
-       .resume = alc_resume,
-#endif
-};
+/* parse the BIOS configuration and set up the alc_spec */
+/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
+static int alc880_parse_auto_config(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       int err;
 
-/*
- */
+       if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
+               return err;
+       if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0)
+               return err;
+       if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin)
+               return 0; /* can't find valid BIOS pin config */
+       if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
+           (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
+           (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+               return err;
 
-static struct hda_board_config alc880_cfg_tbl[] = {
-       /* Back 3 jack, front 2 jack */
-       { .modelname = "3stack", .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
-       { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
+       spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
-       /* Back 3 jack, front 2 jack (Internal add Aux-In) */
-       { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
+       if (spec->autocfg.dig_out_pin)
+               spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+       if (spec->autocfg.dig_in_pin)
+               spec->dig_in_nid = ALC880_DIGIN_NID;
 
-       /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
-       { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
+       if (spec->kctl_alloc)
+               spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
-       /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
-       { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
-       { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
+       spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
 
-       /* Back 5 jack, front 2 jack */
-       { .modelname = "5stack", .config = ALC880_5ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
-       { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
-       { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
+       spec->input_mux = &spec->private_imux;
 
-       /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
-       { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
-       { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
-       { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
+       return 1;
+}
 
-       { .modelname = "w810", .config = ALC880_W810 },
-       { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
+/* init callback for auto-configuration model -- overriding the default init */
+static int alc880_auto_init(struct hda_codec *codec)
+{
+       alc_init(codec);
+       alc880_auto_init_multi_out(codec);
+       alc880_auto_init_hp_out(codec);
+       alc880_auto_init_analog_input(codec);
+       return 0;
+}
 
-       {}
-};
+/*
+ * OK, here we have finally the patch for ALC880
+ */
 
 static int patch_alc880(struct hda_codec *codec)
 {
        struct alc_spec *spec;
        int board_config;
+       int i, err;
 
        spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
                return -ENOMEM;
 
+       init_MUTEX(&spec->bind_mutex);
        codec->spec = spec;
 
        board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
-       if (board_config < 0) {
-               snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
-               board_config = ALC880_MINIMAL;
+       if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
+               printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
+               board_config = ALC880_AUTO;
        }
 
-       switch (board_config) {
-       case ALC880_W810:
-               spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
-               spec->num_mixers++;
-               break;
-       case ALC880_5ST:
-       case ALC880_5ST_DIG:
-               spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
-               spec->num_mixers++;
-               break;
-       default:
-               spec->mixers[spec->num_mixers] = alc880_base_mixer;
-               spec->num_mixers++;
-               break;
+       if (board_config == ALC880_AUTO) {
+               /* automatic parse from the BIOS config */
+               err = alc880_parse_auto_config(codec);
+               if (err < 0) {
+                       alc_free(codec);
+                       return err;
+               } else if (! err) {
+                       printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using 3-stack mode...\n");
+                       board_config = ALC880_3ST;
+               }
        }
 
-       switch (board_config) {
-       case ALC880_3ST_DIG:
-       case ALC880_5ST_DIG:
-       case ALC880_W810:
-               spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
-               break;
-       default:
-               break;
-       }
+       if (board_config != ALC880_AUTO) {
+               /* set up from the preset table */
+               const struct alc_config_preset *preset;
 
-       switch (board_config) {
-       case ALC880_3ST:
-       case ALC880_3ST_DIG:
-       case ALC880_5ST:
-       case ALC880_5ST_DIG:
-       case ALC880_W810:
-               spec->front_panel = 1;
-               break;
-       default:
-               break;
-       }
+               preset = &alc880_presets[board_config];
 
-       switch (board_config) {
-       case ALC880_5ST:
-       case ALC880_5ST_DIG:
-               spec->init_verbs = alc880_init_verbs_five_stack;
-               spec->channel_mode = alc880_fivestack_modes;
-               spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
-               break;
-       case ALC880_W810:
-               spec->init_verbs = alc880_w810_init_verbs;
-               spec->channel_mode = alc880_w810_modes;
-               spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
-               break;
-       default:
-               spec->init_verbs = alc880_init_verbs_three_stack;
-               spec->channel_mode = alc880_threestack_modes;
-               spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
-               break;
+               for (i = 0; preset->mixers[i]; i++) {
+                       snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break);
+                       spec->mixers[spec->num_mixers++] = preset->mixers[i];
+               }
+               for (i = 0; preset->init_verbs[i]; i++) {
+                       snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break);
+                       spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
+               }
+
+               spec->channel_mode = preset->channel_mode;
+               spec->num_channel_mode = preset->num_channel_mode;
+
+               spec->multiout.max_channels = spec->channel_mode[0].channels;
+
+               spec->multiout.num_dacs = preset->num_dacs;
+               spec->multiout.dac_nids = preset->dac_nids;
+               spec->multiout.dig_out_nid = preset->dig_out_nid;
+               spec->multiout.hp_nid = preset->hp_nid;
+
+               spec->input_mux = preset->input_mux;
+
+               spec->num_adc_nids = preset->num_adc_nids;
+               spec->adc_nids = preset->adc_nids;
        }
 
        spec->stream_name_analog = "ALC880 Analog";
@@ -1078,34 +2134,64 @@ static int patch_alc880(struct hda_codec *codec)
        spec->stream_digital_playback = &alc880_pcm_digital_playback;
        spec->stream_digital_capture = &alc880_pcm_digital_capture;
 
-       spec->multiout.max_channels = spec->channel_mode[0].channels;
-
-       switch (board_config) {
-       case ALC880_W810:
-               spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
-               spec->multiout.dac_nids = alc880_w810_dac_nids;
-               // No dedicated headphone socket - it's shared with built-in speakers.
-               break;
-       default:
-               spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
-               spec->multiout.dac_nids = alc880_dac_nids;
-               spec->multiout.hp_nid = 0x03; /* rear-surround NID */
-               break;
+       if (! spec->adc_nids && spec->input_mux) {
+               /* check whether NID 0x07 is valid */
+               unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0],
+                                                      AC_PAR_AUDIO_WIDGET_CAP);
+               wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+               if (wcap != AC_WID_AUD_IN) {
+                       spec->adc_nids = alc880_adc_nids_alt;
+                       spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
+                       spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
+                       spec->num_mixers++;
+               } else {
+                       spec->adc_nids = alc880_adc_nids;
+                       spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
+                       spec->mixers[spec->num_mixers] = alc880_capture_mixer;
+                       spec->num_mixers++;
+               }
        }
 
-       spec->input_mux = &alc880_capture_source;
-       spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
-       spec->adc_nids = alc880_adc_nids;
-
        codec->patch_ops = alc_patch_ops;
+       if (board_config == ALC880_AUTO)
+               codec->patch_ops.init = alc880_auto_init;
 
        return 0;
 }
 
+
 /*
  * ALC260 support
  */
 
+static hda_nid_t alc260_dac_nids[1] = {
+       /* front */
+       0x02,
+};
+
+static hda_nid_t alc260_adc_nids[1] = {
+       /* ADC0 */
+       0x04,
+};
+
+static hda_nid_t alc260_hp_adc_nids[1] = {
+       /* ADC1 */
+       0x05,
+};
+
+#define ALC260_DIGOUT_NID      0x03
+#define ALC260_DIGIN_NID       0x06
+
+static struct hda_input_mux alc260_capture_source = {
+       .num_items = 4,
+       .items = {
+               { "Mic", 0x0 },
+               { "Front Mic", 0x1 },
+               { "Line", 0x2 },
+               { "CD", 0x4 },
+       },
+};
+
 /*
  * This is just place-holder, so there's something for alc_build_pcms to look
  * at when it calculates the maximum number of channels. ALC260 has no mixer
@@ -1116,11 +2202,9 @@ static struct alc_channel_mode alc260_modes[1] = {
        { 2, NULL },
 };
 
-snd_kcontrol_new_t alc260_base_mixer[] = {
+static snd_kcontrol_new_t alc260_base_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-       /* use LINE2 for the output */
-       /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
-       HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
@@ -1132,9 +2216,9 @@ snd_kcontrol_new_t alc260_base_mixer[] = {
        HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
        HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
        HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
        {
@@ -1147,60 +2231,91 @@ snd_kcontrol_new_t alc260_base_mixer[] = {
        { } /* end */
 };
 
+static snd_kcontrol_new_t alc260_hp_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
+       HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Capture Source",
+               .info = alc_mux_enum_info,
+               .get = alc_mux_enum_get,
+               .put = alc_mux_enum_put,
+       },
+       { } /* end */
+};
+
 static struct hda_verb alc260_init_verbs[] = {
        /* Line In pin widget for input */
-       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
        /* CD pin widget for input */
-       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
        /* Mic1 (rear panel) pin widget for input and vref at 80% */
-       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
        /* Mic2 (front panel) pin widget for input and vref at 80% */
-       {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+       {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
        /* LINE-2 is used for line-out in rear */
-       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
        /* select line-out */
        {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
        /* LINE-OUT pin */
-       {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+       {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
        /* enable HP */
-       {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+       {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
        /* enable Mono */
-       {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-       /* unmute amp left and right */
-       {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+       {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       /* mute capture amp left and right */
+       {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        /* set connection select to line in (default select for this ADC) */
        {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
-       /* unmute Line-Out mixer amp left and right (volume = 0) */
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* unmute HP mixer amp left and right (volume = 0) */
-       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-       /* unmute Mono mixer amp left and right (volume = 0) */
-       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       /* mute pin widget amp left and right (no gain on this amp) */
-       {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-       /* mute LINE-2 out */
-       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+       /* mute capture amp left and right */
+       {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       /* set connection select to line in (default select for this ADC) */
+       {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
+       /* set vol=0 Line-Out mixer amp left and right */
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       /* unmute pin widget amp left and right (no gain on this amp) */
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* set vol=0 HP mixer amp left and right */
+       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       /* unmute pin widget amp left and right (no gain on this amp) */
+       {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* set vol=0 Mono mixer amp left and right */
+       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       /* unmute pin widget amp left and right (no gain on this amp) */
+       {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       /* unmute LINE-2 out pin */
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
-       /* unmute CD */
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
-       /* unmute Line In */
-       {0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-       /* unmute Mic */
-       {0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+       /* mute CD */
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+       /* mute Line In */
+       {0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+       /* mute Mic */
+       {0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-       /* Unmute Front out path */
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       /* Unmute Headphone out path */
-       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       /* Unmute Mono out path */
-       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+       /* mute Front out path */
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       /* mute Headphone out path */
+       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       /* mute Mono out path */
+       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
        { }
 };
 
@@ -1208,30 +2323,52 @@ static struct hda_pcm_stream alc260_pcm_analog_playback = {
        .substreams = 1,
        .channels_min = 2,
        .channels_max = 2,
-       .nid = 0x2,
 };
 
 static struct hda_pcm_stream alc260_pcm_analog_capture = {
        .substreams = 1,
        .channels_min = 2,
        .channels_max = 2,
-       .nid = 0x4,
+};
+
+static struct hda_board_config alc260_cfg_tbl[] = {
+       { .modelname = "hp", .config = ALC260_HP },
+       { .pci_subvendor = 0x103c, .config = ALC260_HP },
+       {}
 };
 
 static int patch_alc260(struct hda_codec *codec)
 {
        struct alc_spec *spec;
+       int board_config;
 
        spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
                return -ENOMEM;
 
+       init_MUTEX(&spec->bind_mutex);
        codec->spec = spec;
 
-       spec->mixers[spec->num_mixers] = alc260_base_mixer;
-       spec->num_mixers++;
+       board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
+       if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
+               snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
+               board_config = ALC260_BASIC;
+       }
+
+       switch (board_config) {
+       case ALC260_HP:
+               spec->mixers[spec->num_mixers] = alc260_hp_mixer;
+               spec->num_mixers++;
+               break;
+       default:
+               spec->mixers[spec->num_mixers] = alc260_base_mixer;
+               spec->num_mixers++;
+               break;
+       }
+
+       spec->init_verbs[0] = alc260_init_verbs;
+       spec->num_init_verbs = 1;
 
-       spec->init_verbs = alc260_init_verbs;
        spec->channel_mode = alc260_modes;
        spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
 
@@ -1244,14 +2381,23 @@ static int patch_alc260(struct hda_codec *codec)
        spec->multiout.dac_nids = alc260_dac_nids;
 
        spec->input_mux = &alc260_capture_source;
-       spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
-       spec->adc_nids = alc260_adc_nids;
+       switch (board_config) {
+       case ALC260_HP:
+               spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);
+               spec->adc_nids = alc260_hp_adc_nids;
+               break;
+       default:
+               spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+               spec->adc_nids = alc260_adc_nids;
+               break;
+       }
 
        codec->patch_ops = alc_patch_ops;
 
        return 0;
 }
 
+
 /*
  * ALC882 support
  *
@@ -1324,15 +2470,15 @@ static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
  */
 static snd_kcontrol_new_t alc882_base_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+       ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
        HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -1364,89 +2510,80 @@ static snd_kcontrol_new_t alc882_base_mixer[] = {
 
 static struct hda_verb alc882_init_verbs[] = {
        /* Front mixer: unmute input/output amp left and right (volume = 0) */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
        /* Rear mixer */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
        /* CLFE mixer */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
        /* Side mixer */
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-
-       /* Front Pin: to output mode */
-       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-       /* Front Pin: mute amp left and right (no volume) */
-       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* select Front mixer (0x0c, index 0) */
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+       /* Front Pin: output 0 (0x0c) */
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-       /* Rear Pin */
-       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-       /* Rear Pin: mute amp left and right (no volume) */
-       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* select Rear mixer (0x0d, index 1) */
+       /* Rear Pin: output 1 (0x0d) */
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-       /* CLFE Pin */
-       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-       /* CLFE Pin: mute amp left and right (no volume) */
-       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* select CLFE mixer (0x0e, index 2) */
+       /* CLFE Pin: output 2 (0x0e) */
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
-       /* Side Pin */
-       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-       /* Side Pin: mute amp left and right (no volume) */
-       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* select Side mixer (0x0f, index 3) */
+       /* Side Pin: output 3 (0x0f) */
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-       /* Headphone Pin */
-       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-       /* Headphone Pin: mute amp left and right (no volume) */
-       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-       /* select Front mixer (0x0c, index 0) */
+       /* Mic (rear) pin: input vref at 80% */
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Front Mic pin: input vref at 80% */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Line In pin: input */
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Line-2 In: Headphone output (output 0 - 0x0c) */
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-       /* Mic (rear) pin widget for input and vref at 80% */
-       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-       /* Front Mic pin widget for input and vref at 80% */
-       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-       /* Line In pin widget for input */
-       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
        /* CD pin widget for input */
-       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+       {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
        /* FIXME: use matrix-type input source selection */
        /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
        /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
        /* Input mixer2 */
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
        /* Input mixer3 */
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-       /* ADC1: unmute amp left and right */
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-       /* ADC2: unmute amp left and right */
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-       /* ADC3: unmute amp left and right */
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-
-       /* Unmute front loopback */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       /* Unmute rear loopback */
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-       /* Mute CLFE loopback */
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
-       /* Unmute side loopback */
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+       /* ADC1: mute amp left and right */
+       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+       /* ADC2: mute amp left and right */
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+       /* ADC3: mute amp left and right */
+       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
 
        { }
 };
@@ -1459,6 +2596,7 @@ static int patch_alc882(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       init_MUTEX(&spec->bind_mutex);
        codec->spec = spec;
 
        spec->mixers[spec->num_mixers] = alc882_base_mixer;
@@ -1466,8 +2604,9 @@ static int patch_alc882(struct hda_codec *codec)
 
        spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
        spec->dig_in_nid = ALC880_DIGIN_NID;
-       spec->front_panel = 1;
-       spec->init_verbs = alc882_init_verbs;
+       spec->init_verbs[0] = alc882_init_verbs;
+       spec->num_init_verbs = 1;
+
        spec->channel_mode = alc882_ch_modes;
        spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
new file mode 100644 (file)
index 0000000..013be2e
--- /dev/null
@@ -0,0 +1,666 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for SigmaTel STAC92xx
+ *
+ * Copyright (c) 2005 Embedded Alley Solutions, Inc.
+ * <matt@embeddedalley.com>
+ *
+ * Based on patch_cmedia.c and patch_realtek.c
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *  This driver is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This driver is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+#undef STAC_TEST
+
+struct sigmatel_spec {
+       /* playback */
+       struct hda_multi_out multiout;
+       hda_nid_t playback_nid;
+
+       /* capture */
+       hda_nid_t *adc_nids;
+       unsigned int num_adcs;
+       hda_nid_t *mux_nids;
+       unsigned int num_muxes;
+       hda_nid_t capture_nid;
+       hda_nid_t dig_in_nid;
+
+       /* power management*/
+       hda_nid_t *pstate_nids;
+       unsigned int num_pstates;
+
+       /* pin widgets */
+       hda_nid_t *pin_nids;
+       unsigned int num_pins;
+#ifdef STAC_TEST
+       unsigned int *pin_configs;
+#endif
+
+       /* codec specific stuff */
+       struct hda_verb *init;
+       snd_kcontrol_new_t *mixer;
+
+       /* capture source */
+       struct hda_input_mux input_mux;
+       char input_labels[HDA_MAX_NUM_INPUTS][16];
+       unsigned int cur_mux[2];
+
+       /* channel mode */
+       unsigned int num_ch_modes;
+       unsigned int cur_ch_mode;
+       const struct sigmatel_channel_mode *channel_modes;
+
+       struct hda_pcm pcm_rec[1];      /* PCM information */
+};
+
+static hda_nid_t stac9200_adc_nids[1] = {
+        0x03,
+};
+
+static hda_nid_t stac9200_mux_nids[1] = {
+        0x0c,
+};
+
+static hda_nid_t stac9200_dac_nids[1] = {
+        0x02,
+};
+
+static hda_nid_t stac9200_pstate_nids[3] = {
+       0x01, 0x02, 0x03,
+};
+
+static hda_nid_t stac9200_pin_nids[8] = {
+       0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+};
+
+static hda_nid_t stac922x_adc_nids[2] = {
+        0x06, 0x07,
+};
+
+static hda_nid_t stac922x_mux_nids[2] = {
+        0x12, 0x13,
+};
+
+static hda_nid_t stac922x_dac_nids[4] = {
+        0x02, 0x03, 0x04, 0x05,
+};
+
+static hda_nid_t stac922x_pstate_nids[8] = {
+       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x11,
+};
+
+static hda_nid_t stac922x_pin_nids[10] = {
+       0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+       0x0f, 0x10, 0x11, 0x15, 0x1b,
+};
+
+static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct sigmatel_spec *spec = codec->spec;
+       return snd_hda_input_mux_info(&spec->input_mux, uinfo);
+}
+
+static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct sigmatel_spec *spec = codec->spec;
+       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+       ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+       return 0;
+}
+
+static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct sigmatel_spec *spec = codec->spec;
+       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+       return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
+                                    spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
+}
+
+static struct hda_verb stac9200_ch2_init[] = {
+       /* set dac0mux for dac converter */
+       { 0x07, 0x701, 0x00},
+       {}
+};
+
+static struct hda_verb stac922x_ch2_init[] = {
+       /* set master volume and direct control */      
+       { 0x16, 0x70f, 0xff},
+       {}
+};
+
+struct sigmatel_channel_mode {
+       unsigned int channels;
+       const struct hda_verb *sequence;
+};
+
+static snd_kcontrol_new_t stac9200_mixer[] = {
+       HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Input Source",
+               .count = 1,
+               .info = stac92xx_mux_enum_info,
+               .get = stac92xx_mux_enum_get,
+               .put = stac92xx_mux_enum_put,
+       },
+       HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT),
+       { } /* end */
+};
+
+static snd_kcontrol_new_t stac922x_mixer[] = {
+       HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Input Source",
+               .count = 1,
+               .info = stac92xx_mux_enum_info,
+               .get = stac92xx_mux_enum_get,
+               .put = stac92xx_mux_enum_put,
+       },
+       HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
+       { } /* end */
+};
+
+static int stac92xx_build_controls(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       int err;
+
+       err = snd_hda_add_new_ctls(codec, spec->mixer);
+       if (err < 0)
+               return err;
+       if (spec->multiout.dig_out_nid) {
+               err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+               if (err < 0)
+                       return err;
+       }
+       if (spec->dig_in_nid) {
+               err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+               if (err < 0)
+                       return err;
+       }
+       return 0;       
+}
+
+#ifdef STAC_TEST
+static unsigned int stac9200_pin_configs[8] = {
+       0x01c47010, 0x01447010, 0x0221401f, 0x01114010,
+       0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
+};
+
+static unsigned int stac922x_pin_configs[14] = {
+       0x40000100, 0x40000100, 0x40000100, 0x01114010,
+       0x01813122, 0x40000100, 0x01447010, 0x01c47010,
+       0x40000100, 0x40000100,
+};
+
+static void stac92xx_set_config_regs(struct hda_codec *codec)
+{
+       int i;
+       struct sigmatel_spec *spec = codec->spec;
+       unsigned int pin_cfg;
+
+       for (i=0; i < spec->num_pins; i++) {
+               snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+                                   AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
+                                   spec->pin_configs[i] & 0x000000ff);
+               snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+                                   AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
+                                   (spec->pin_configs[i] & 0x0000ff00) >> 8);
+               snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+                                   AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
+                                   (spec->pin_configs[i] & 0x00ff0000) >> 16);
+               snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+                                   AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
+                                   spec->pin_configs[i] >> 24);
+               pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
+                                            AC_VERB_GET_CONFIG_DEFAULT,
+                                            0x00);     
+               printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
+       }
+}
+#endif
+
+static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value)
+{
+       unsigned int pin_ctl;
+
+       pin_ctl = snd_hda_codec_read(codec, nid, 0,
+                                    AC_VERB_GET_PIN_WIDGET_CONTROL,
+                                    0x00);
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+                           pin_ctl | value);
+
+       return 0;
+}
+
+static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid)
+{
+       unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT;
+       unsigned int vref_ctl = AC_PINCTL_VREF_HIZ;
+
+       if (vref_caps & AC_PINCAP_VREF_100)
+               vref_ctl = AC_PINCTL_VREF_100;
+       else if (vref_caps & AC_PINCAP_VREF_80)
+               vref_ctl = AC_PINCTL_VREF_80;
+       else if (vref_caps & AC_PINCAP_VREF_50)
+               vref_ctl = AC_PINCTL_VREF_50;
+       else if (vref_caps & AC_PINCAP_VREF_GRD)
+               vref_ctl = AC_PINCTL_VREF_GRD;
+
+       stac92xx_set_pinctl(codec, nid, vref_ctl);
+       
+       return 0;
+}
+
+/*
+ * retrieve the default device type from the default config value
+ */
+#define get_defcfg_type(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+
+static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       u32 location = get_defcfg_location(pin_cfg);
+       char *label;
+       const char *type = NULL;
+       int ainput = 0;
+
+       switch(get_defcfg_type(pin_cfg)) {
+               case AC_JACK_HP_OUT:
+                       /* Enable HP amp */
+                       stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN);
+                       /* Fall through */
+               case AC_JACK_SPDIF_OUT:
+               case AC_JACK_LINE_OUT:
+               case AC_JACK_SPEAKER:
+                       /* Enable output */
+                       stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+                       break;
+               case AC_JACK_SPDIF_IN:
+                       stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+                       break;
+               case AC_JACK_MIC_IN:
+                       if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+                               type = "Front Mic";
+                       else
+                               type = "Mic";
+                       ainput = 1;
+                       /* Set vref */
+                       stac92xx_set_vref(codec, nid);
+                       stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+                       break;
+               case AC_JACK_CD:
+                       type = "CD";
+                       ainput = 1;
+                       stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+                       break;
+               case AC_JACK_LINE_IN:
+                       if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+                               type = "Front Line";
+                       else
+                               type = "Line";
+                       ainput = 1;
+                       stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+                       break;
+               case AC_JACK_AUX:
+                       if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+                               type = "Front Aux";
+                       else
+                               type = "Aux";
+                       ainput = 1;
+                       stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+                       break;
+       }
+
+       if (ainput) {
+               hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
+               int i, j, num_cons, index = -1;
+               if (!type)
+                       type = "Input";
+               label = spec->input_labels[spec->input_mux.num_items];
+               strcpy(label, type);
+               spec->input_mux.items[spec->input_mux.num_items].label = label;
+               for (i=0; i<spec->num_muxes; i++) {
+                       num_cons = snd_hda_get_connections(codec, spec->mux_nids[i], con_lst, HDA_MAX_NUM_INPUTS);
+                       for (j=0; j<num_cons; j++)
+                               if (con_lst[j] == nid) {
+                                       index = j;
+                                       break;
+                               }
+                       if (index >= 0)
+                               break;
+               }
+               spec->input_mux.items[spec->input_mux.num_items].index = index;
+               spec->input_mux.num_items++;
+       }
+
+       return 0;
+}
+
+static int stac92xx_config_pins(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       int i;
+       unsigned int pin_cfg;
+
+       for (i=0; i < spec->num_pins; i++) {
+               /* Default to disabled */
+               snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                   0x00);
+
+               pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
+                                            AC_VERB_GET_CONFIG_DEFAULT,
+                                            0x00);
+               if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE)
+                       continue;       /* Move on */
+
+               stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg);
+       }
+
+       return 0;
+}
+
+static int stac92xx_init(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       int i;
+
+       for (i=0; i < spec->num_pstates; i++)
+               snd_hda_codec_write(codec, spec->pstate_nids[i], 0,
+                                   AC_VERB_SET_POWER_STATE, 0x00);
+
+       mdelay(100);
+
+       snd_hda_sequence_write(codec, spec->init);
+
+#ifdef STAC_TEST
+       stac92xx_set_config_regs(codec);
+#endif
+
+       stac92xx_config_pins(codec);
+
+       return 0;
+}
+
+/*
+ * Analog playback callbacks
+ */
+static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
+                                     struct hda_codec *codec,
+                                     snd_pcm_substream_t *substream)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                        struct hda_codec *codec,
+                                        unsigned int stream_tag,
+                                        unsigned int format,
+                                        snd_pcm_substream_t *substream)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+                                               format, substream);
+}
+
+static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+                                       struct hda_codec *codec,
+                                       snd_pcm_substream_t *substream)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital playback callbacks
+ */
+static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+                                         struct hda_codec *codec,
+                                         snd_pcm_substream_t *substream)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+                                          struct hda_codec *codec,
+                                          snd_pcm_substream_t *substream)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+
+/*
+ * Analog capture callbacks
+ */
+static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                       struct hda_codec *codec,
+                                       unsigned int stream_tag,
+                                       unsigned int format,
+                                       snd_pcm_substream_t *substream)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+                                   stream_tag, 0, format);
+       return 0;
+}
+
+static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+                                       struct hda_codec *codec,
+                                       snd_pcm_substream_t *substream)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+       return 0;
+}
+
+static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in stac92xx_build_pcms */
+       .ops = {
+               .open = stac92xx_dig_playback_pcm_open,
+               .close = stac92xx_dig_playback_pcm_close
+       },
+};
+
+static struct hda_pcm_stream stac92xx_pcm_digital_capture = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in stac92xx_build_pcms */
+};
+
+static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       .nid = 0x02, /* NID to query formats and rates */
+       .ops = {
+               .open = stac92xx_playback_pcm_open,
+               .prepare = stac92xx_playback_pcm_prepare,
+               .cleanup = stac92xx_playback_pcm_cleanup
+       },
+};
+
+static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
+       .substreams = 2,
+       .channels_min = 2,
+       .channels_max = 2,
+       .nid = 0x06, /* NID to query formats and rates */
+       .ops = {
+               .prepare = stac92xx_capture_pcm_prepare,
+               .cleanup = stac92xx_capture_pcm_cleanup
+       },
+};
+
+static int stac92xx_build_pcms(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       struct hda_pcm *info = spec->pcm_rec;
+
+       codec->num_pcms = 1;
+       codec->pcm_info = info;
+
+       info->name = "STAC92xx";
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid;
+       info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
+       info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid;
+
+       if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+               codec->num_pcms++;
+               info++;
+               info->name = "STAC92xx Digital";
+               if (spec->multiout.dig_out_nid) {
+                       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
+                       info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+               }
+               if (spec->dig_in_nid) {
+                       info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture;
+                       info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+               }
+       }
+
+       return 0;
+}
+
+static void stac92xx_free(struct hda_codec *codec)
+{
+       kfree(codec->spec);
+}
+
+static struct hda_codec_ops stac92xx_patch_ops = {
+       .build_controls = stac92xx_build_controls,
+       .build_pcms = stac92xx_build_pcms,
+       .init = stac92xx_init,
+       .free = stac92xx_free,
+};
+
+static int patch_stac9200(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec;
+
+       spec  = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       codec->spec = spec;
+
+       spec->multiout.max_channels = 2;
+       spec->multiout.num_dacs = 1;
+       spec->multiout.dac_nids = stac9200_dac_nids;
+       spec->multiout.dig_out_nid = 0x05;
+       spec->dig_in_nid = 0x04;
+       spec->adc_nids = stac9200_adc_nids;
+       spec->mux_nids = stac9200_mux_nids;
+       spec->num_muxes = 1;
+       spec->input_mux.num_items = 0;
+       spec->pstate_nids = stac9200_pstate_nids;
+       spec->num_pstates = 3;
+       spec->pin_nids = stac9200_pin_nids;
+#ifdef STAC_TEST
+       spec->pin_configs = stac9200_pin_configs;
+#endif
+       spec->num_pins = 8;
+       spec->init = stac9200_ch2_init;
+       spec->mixer = stac9200_mixer;
+       spec->playback_nid = 0x02;
+       spec->capture_nid = 0x03;
+
+       codec->patch_ops = stac92xx_patch_ops;
+
+       return 0;
+}
+
+static int patch_stac922x(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec;
+
+       spec  = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       codec->spec = spec;
+
+       spec->multiout.max_channels = 2;
+       spec->multiout.num_dacs = 4;
+       spec->multiout.dac_nids = stac922x_dac_nids;
+       spec->multiout.dig_out_nid = 0x08;
+       spec->dig_in_nid = 0x09;
+       spec->adc_nids = stac922x_adc_nids;
+       spec->mux_nids = stac922x_mux_nids;
+       spec->num_muxes = 2;
+       spec->input_mux.num_items = 0;
+       spec->pstate_nids = stac922x_pstate_nids;
+       spec->num_pstates = 8;
+       spec->pin_nids = stac922x_pin_nids;
+#ifdef STAC_TEST
+       spec->pin_configs = stac922x_pin_configs;
+#endif
+       spec->num_pins = 10;
+       spec->init = stac922x_ch2_init;
+       spec->mixer = stac922x_mixer;
+       spec->playback_nid = 0x02;
+       spec->capture_nid = 0x06;
+
+       codec->patch_ops = stac92xx_patch_ops;
+
+       return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+       { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
+       { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
+       { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
+       { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x },
+       { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },
+       { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },
+       { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },
+       {} /* terminator */
+};
index 779951725e1e44acdc1317e4dc0092a5ff4b7aaf..289b0b5711e47fb6a53b1eeb5e8ada875242652d 100644 (file)
 #include <sound/core.h>
 
 #include "ice1712.h"
+#include "envy24ht.h"
 #include "amp.h"
 
+static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+{
+       unsigned short cval;
+       cval = (reg << 9) | val;
+       snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
+}
 
 static int __devinit snd_vt1724_amp_init(ice1712_t *ice)
 {
+       static unsigned short wm_inits[] = {
+               WM_ATTEN_L,     0x0000, /* 0 db */
+               WM_ATTEN_R,     0x0000, /* 0 db */
+               WM_DAC_CTRL,    0x0008, /* 24bit I2S */
+               WM_INT_CTRL,    0x0001, /* 24bit I2S */ 
+       };
+
+       unsigned int i;
+
        /* only use basic functionality for now */
 
        ice->num_total_dacs = 2;        /* only PSDOUT0 is connected */
        ice->num_total_adcs = 2;
 
+       /* Chaintech AV-710 has another codecs, which need initialization */
+       /* initialize WM8728 codec */
+       if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) {
+               for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
+                       wm_put(ice, wm_inits[i], wm_inits[i+1]);
+       }
+
        return 0;
 }
 
@@ -53,6 +76,13 @@ static int __devinit snd_vt1724_amp_add_controls(ice1712_t *ice)
 
 /* entry point */
 struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
+       {
+               .subvendor = VT1724_SUBDEVICE_AV710,
+               .name = "Chaintech AV-710",
+               .model = "av710",
+               .chip_init = snd_vt1724_amp_init,
+               .build_controls = snd_vt1724_amp_add_controls,
+       },
        {
                .subvendor = VT1724_SUBDEVICE_AUDIO2000,
                .name = "AMP Ltd AUDIO2000",
index d58d43383e839fbe5c67992fa31c5941f8ed356f..a0fc89b48122d4a65779acec06542eb90d90a293 100644 (file)
  *
  */      
 
-#define  AMP_AUDIO2000_DEVICE_DESC            "{AMP Ltd,AUDIO2000},"
+#define  AMP_AUDIO2000_DEVICE_DESC            "{AMP Ltd,AUDIO2000},"\
+                                              "{Chaintech,AV-710},"
 
+#if 0
 #define VT1724_SUBDEVICE_AUDIO2000     0x12142417      /* Advanced Micro Peripherals Ltd AUDIO2000 */
+#else
+#define VT1724_SUBDEVICE_AUDIO2000     0x00030003      /* a dummy ID for AMP Audio2000 */
+#endif
+#define VT1724_SUBDEVICE_AV710         0x12142417      /* AV710 - the same ID with Audio2000! */
+
+/* WM8728 on I2C for AV710 */
+#define WM_DEV         0x36
+
+#define WM_ATTEN_L     0x00
+#define WM_ATTEN_R     0x01
+#define WM_DAC_CTRL    0x02
+#define WM_INT_CTRL    0x03
 
 extern struct snd_ice1712_card_info  snd_vt1724_amp_cards[];
 
index 79fba6be3503a0cbe25ddf5a207286bd67024aca..a2545a5b26c48b1546ea9d35b6a0c31cbeff069b 100644 (file)
@@ -2748,7 +2748,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_ice1712_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ice1712_exit(void)
index 8bb1c58c26a005950b90c0f07115709d4ee0eb02..5ad4728daa7b83fb3cef05ec5e47793b31d6e1ed 100644 (file)
@@ -373,6 +373,11 @@ struct _snd_ice1712 {
                        unsigned short master[2];
                        unsigned short vol[8];
                } aureon;
+               /* AC97 register cache for Phase28 */
+               struct phase28_spec {
+                       unsigned short master[2];
+                       unsigned short vol[8];
+               } phase28;
                /* Hoontech-specific setting */
                struct hoontech_spec {
                        unsigned char boxbits[4];
index 95500f06f0c62375b391bd79615b2719dfc667f6..79b5f12e06fc4afba100a65e8eacefbefa697b52 100644 (file)
@@ -2328,7 +2328,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_ice1724_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ice1724_exit(void)
index d1f90832443c44cfe0b7b745b63d8dfb1249be33..5bf734b04fa065f0e6999828ee177f8479e0967e 100644 (file)
 #include "envy24ht.h"
 #include "phase.h"
 
+/* WM8770 registers */
+#define WM_DAC_ATTEN           0x00    /* DAC1-8 analog attenuation */
+#define WM_DAC_MASTER_ATTEN    0x08    /* DAC master analog attenuation */
+#define WM_DAC_DIG_ATTEN       0x09    /* DAC1-8 digital attenuation */
+#define WM_DAC_DIG_MASTER_ATTEN        0x11    /* DAC master digital attenuation */
+#define WM_PHASE_SWAP          0x12    /* DAC phase */
+#define WM_DAC_CTRL1           0x13    /* DAC control bits */
+#define WM_MUTE                        0x14    /* mute controls */
+#define WM_DAC_CTRL2           0x15    /* de-emphasis and zefo-flag */
+#define WM_INT_CTRL            0x16    /* interface control */
+#define WM_MASTER              0x17    /* master clock and mode */
+#define WM_POWERDOWN           0x18    /* power-down controls */
+#define WM_ADC_GAIN            0x19    /* ADC gain L(19)/R(1a) */
+#define WM_ADC_MUX             0x1b    /* input MUX */
+#define WM_OUT_MUX1            0x1c    /* output MUX */
+#define WM_OUT_MUX2            0x1e    /* output MUX */
+#define WM_RESET               0x1f    /* software reset */
+
+
+/*
+ * Logarithmic volume values for WM8770
+ * Computed as 20 * Log10(255 / x)
+ */
+static unsigned char wm_vol[256] = {
+       127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
+       23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
+       17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
+       13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
+       11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
+       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0
+};
+
+#define WM_VOL_MAX     (sizeof(wm_vol) - 1)
+#define WM_VOL_MUTE    0x8000
+
 static akm4xxx_t akm_phase22 __devinitdata = {
        .type = SND_AK4524,
        .num_dacs = 2,
@@ -124,6 +165,684 @@ static unsigned char phase22_eeprom[] __devinitdata = {
        0x00,   /* GPIO_STATE2 */
 };
 
+static unsigned char phase28_eeprom[] __devinitdata = {
+       0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
+       0x80,   /* ACLINK: I2S */
+       0xfc,   /* I2S: vol, 96k, 24bit, 192k */
+       0xc3,   /* SPDIF: out-en, out-int, spdif-in */
+       0xff,   /* GPIO_DIR */
+       0xff,   /* GPIO_DIR1 */
+       0x5f,   /* GPIO_DIR2 */
+       0x00,   /* GPIO_MASK */
+       0x00,   /* GPIO_MASK1 */
+       0x00,   /* GPIO_MASK2 */
+       0x00,   /* GPIO_STATE */
+       0x00,   /* GPIO_STATE1 */
+       0x00,   /* GPIO_STATE2 */
+};
+
+/*
+ * write data in the SPI mode
+ */
+static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
+{
+       unsigned int tmp;
+       int i;
+
+       tmp = snd_ice1712_gpio_read(ice);
+
+       snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|PHASE28_SPI_CLK|
+                                        PHASE28_WM_CS));
+       tmp |= PHASE28_WM_RW;
+       tmp &= ~cs;
+       snd_ice1712_gpio_write(ice, tmp);
+       udelay(1);
+
+       for (i = bits - 1; i >= 0; i--) {
+               tmp &= ~PHASE28_SPI_CLK;
+               snd_ice1712_gpio_write(ice, tmp);
+               udelay(1);
+               if (data & (1 << i))
+                       tmp |= PHASE28_SPI_MOSI;
+               else
+                       tmp &= ~PHASE28_SPI_MOSI;
+               snd_ice1712_gpio_write(ice, tmp);
+               udelay(1);
+               tmp |= PHASE28_SPI_CLK;
+               snd_ice1712_gpio_write(ice, tmp);
+               udelay(1);
+       }
+
+       tmp &= ~PHASE28_SPI_CLK;
+       tmp |= cs;
+       snd_ice1712_gpio_write(ice, tmp);
+       udelay(1);
+       tmp |= PHASE28_SPI_CLK;
+       snd_ice1712_gpio_write(ice, tmp);
+       udelay(1);
+}
+
+/*
+ * get the current register value of WM codec
+ */
+static unsigned short wm_get(ice1712_t *ice, int reg)
+{
+       reg <<= 1;
+       return ((unsigned short)ice->akm[0].images[reg] << 8) |
+               ice->akm[0].images[reg + 1];
+}
+
+/*
+ * set the register value of WM codec
+ */
+static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+{
+       phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
+}
+
+/*
+ * set the register value of WM codec and remember it
+ */
+static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+{
+       wm_put_nocache(ice, reg, val);
+       reg <<= 1;
+       ice->akm[0].images[reg] = val >> 8;
+       ice->akm[0].images[reg + 1] = val;
+}
+
+static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
+{
+       unsigned char nvol;
+
+       if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
+               nvol = 0;
+       else
+               nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
+
+       wm_put(ice, index, nvol);
+       wm_put_nocache(ice, index, 0x180 | nvol);
+}
+
+/*
+ * DAC mute control
+ */
+#define wm_pcm_mute_info       phase28_mono_bool_info
+
+static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+       down(&ice->gpio_mutex);
+       ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short nval, oval;
+       int change;
+
+       snd_ice1712_save_gpio_status(ice);
+       oval = wm_get(ice, WM_MUTE);
+       nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
+       if ((change = (nval != oval)))
+               wm_put(ice, WM_MUTE, nval);
+       snd_ice1712_restore_gpio_status(ice);
+
+       return change;
+}
+
+/*
+ * Master volume attenuation mixer control
+ */
+static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = WM_VOL_MAX;
+       return 0;
+}
+
+static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int i;
+       for (i=0; i<2; i++)
+               ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE;
+       return 0;
+}
+
+static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int ch, change = 0;
+
+       snd_ice1712_save_gpio_status(ice);
+       for (ch = 0; ch < 2; ch++) {
+               if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) {
+                       int dac;
+                       ice->spec.phase28.master[ch] &= WM_VOL_MUTE;
+                       ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch];
+                       for (dac = 0; dac < ice->num_total_dacs; dac += 2)
+                               wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
+                                          ice->spec.phase28.vol[dac + ch],
+                                          ice->spec.phase28.master[ch]);
+                       change = 1;
+               }
+       }
+       snd_ice1712_restore_gpio_status(ice);
+       return change;
+}
+
+static int __devinit phase28_init(ice1712_t *ice)
+{
+       static unsigned short wm_inits_phase28[] = {
+               /* These come first to reduce init pop noise */
+               0x1b, 0x044,            /* ADC Mux (AC'97 source) */
+               0x1c, 0x00B,            /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
+               0x1d, 0x009,            /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
+
+               0x18, 0x000,            /* All power-up */
+
+               0x16, 0x122,            /* I2S, normal polarity, 24bit */
+               0x17, 0x022,            /* 256fs, slave mode */
+               0x00, 0,                /* DAC1 analog mute */
+               0x01, 0,                /* DAC2 analog mute */
+               0x02, 0,                /* DAC3 analog mute */
+               0x03, 0,                /* DAC4 analog mute */
+               0x04, 0,                /* DAC5 analog mute */
+               0x05, 0,                /* DAC6 analog mute */
+               0x06, 0,                /* DAC7 analog mute */
+               0x07, 0,                /* DAC8 analog mute */
+               0x08, 0x100,            /* master analog mute */
+               0x09, 0xff,             /* DAC1 digital full */
+               0x0a, 0xff,             /* DAC2 digital full */
+               0x0b, 0xff,             /* DAC3 digital full */
+               0x0c, 0xff,             /* DAC4 digital full */
+               0x0d, 0xff,             /* DAC5 digital full */
+               0x0e, 0xff,             /* DAC6 digital full */
+               0x0f, 0xff,             /* DAC7 digital full */
+               0x10, 0xff,             /* DAC8 digital full */
+               0x11, 0x1ff,            /* master digital full */
+               0x12, 0x000,            /* phase normal */
+               0x13, 0x090,            /* unmute DAC L/R */
+               0x14, 0x000,            /* all unmute */
+               0x15, 0x000,            /* no deemphasis, no ZFLG */
+               0x19, 0x000,            /* -12dB ADC/L */
+               0x1a, 0x000,            /* -12dB ADC/R */
+               (unsigned short)-1
+       };
+
+       unsigned int tmp;
+       akm4xxx_t *ak;
+       unsigned short *p;
+       int i;
+
+       ice->num_total_dacs = 8;
+       ice->num_total_adcs = 2;
+
+       // Initialize analog chips
+       ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+       if (!ak)
+               return -ENOMEM;
+       ice->akm_codecs = 1;
+
+       snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
+
+       /* reset the wm codec as the SPI mode */
+       snd_ice1712_save_gpio_status(ice);
+       snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL));
+
+       tmp = snd_ice1712_gpio_read(ice);
+       tmp &= ~PHASE28_WM_RESET;
+       snd_ice1712_gpio_write(ice, tmp);
+       udelay(1);
+       tmp |= PHASE28_WM_CS;
+       snd_ice1712_gpio_write(ice, tmp);
+       udelay(1);
+       tmp |= PHASE28_WM_RESET;
+       snd_ice1712_gpio_write(ice, tmp);
+       udelay(1);
+
+       p = wm_inits_phase28;
+       for (; *p != (unsigned short)-1; p += 2)
+               wm_put(ice, p[0], p[1]);
+
+       snd_ice1712_restore_gpio_status(ice);
+
+       ice->spec.phase28.master[0] = WM_VOL_MUTE;
+       ice->spec.phase28.master[1] = WM_VOL_MUTE;
+       for (i = 0; i < ice->num_total_dacs; i++) {
+               ice->spec.phase28.vol[i] = WM_VOL_MUTE;
+               wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]);
+       }
+
+       return 0;
+}
+
+/*
+ * DAC volume attenuation mixer control
+ */
+static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       int voices = kcontrol->private_value >> 8;
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = voices;
+       uinfo->value.integer.min = 0;           /* mute (-101dB) */
+       uinfo->value.integer.max = 0x7F;        /* 0dB */
+       return 0;
+}
+
+static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int i, ofs, voices;
+
+       voices = kcontrol->private_value >> 8;
+       ofs = kcontrol->private_value & 0xff;
+       for (i = 0; i < voices; i++)
+               ucontrol->value.integer.value[i] = ice->spec.phase28.vol[ofs+i] & ~WM_VOL_MUTE;
+       return 0;
+}
+
+static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int i, idx, ofs, voices;
+       int change = 0;
+
+       voices = kcontrol->private_value >> 8;
+       ofs = kcontrol->private_value & 0xff;
+       snd_ice1712_save_gpio_status(ice);
+       for (i = 0; i < voices; i++) {
+               idx  = WM_DAC_ATTEN + ofs + i;
+               if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) {
+                       ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE;
+                       ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i];
+                       wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i],
+                                  ice->spec.phase28.master[i]);
+                       change = 1;
+               }
+       }
+       snd_ice1712_restore_gpio_status(ice);
+       return change;
+}
+
+/*
+ * WM8770 mute control
+ */
+static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = kcontrol->private_value >> 8;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int voices, ofs, i;
+
+       voices = kcontrol->private_value >> 8;
+       ofs = kcontrol->private_value & 0xFF;
+
+       for (i = 0; i < voices; i++)
+               ucontrol->value.integer.value[i] = (ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
+       return 0;
+}
+
+static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int change = 0, voices, ofs, i;
+
+       voices = kcontrol->private_value >> 8;
+       ofs = kcontrol->private_value & 0xFF;
+
+       snd_ice1712_save_gpio_status(ice);
+       for (i = 0; i < voices; i++) {
+               int val = (ice->spec.phase28.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
+               if (ucontrol->value.integer.value[i] != val) {
+                       ice->spec.phase28.vol[ofs + i] &= ~WM_VOL_MUTE;
+                       ice->spec.phase28.vol[ofs + i] |=
+                               ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
+                       wm_set_vol(ice, ofs + i, ice->spec.phase28.vol[ofs + i],
+                                  ice->spec.phase28.master[i]);
+                       change = 1;
+               }
+       }
+       snd_ice1712_restore_gpio_status(ice);
+
+       return change;
+}
+
+/*
+ * WM8770 master mute control
+ */
+static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1;
+       ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1;
+       return 0;
+}
+
+static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int change = 0, i;
+
+       snd_ice1712_save_gpio_status(ice);
+       for (i = 0; i < 2; i++) {
+               int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1;
+               if (ucontrol->value.integer.value[i] != val) {
+                       int dac;
+                       ice->spec.phase28.master[i] &= ~WM_VOL_MUTE;
+                       ice->spec.phase28.master[i] |=
+                               ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
+                       for (dac = 0; dac < ice->num_total_dacs; dac += 2)
+                               wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
+                                          ice->spec.phase28.vol[dac + i],
+                                          ice->spec.phase28.master[i]);
+                       change = 1;
+               }
+       }
+       snd_ice1712_restore_gpio_status(ice);
+
+       return change;
+}
+
+/* digital master volume */
+#define PCM_0dB 0xff
+#define PCM_RES 128    /* -64dB */
+#define PCM_MIN (PCM_0dB - PCM_RES)
+static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;           /* mute (-64dB) */
+       uinfo->value.integer.max = PCM_RES;     /* 0dB */
+       return 0;
+}
+
+static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short val;
+
+       down(&ice->gpio_mutex);
+       val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+       val = val > PCM_MIN ? (val - PCM_MIN) : 0;
+       ucontrol->value.integer.value[0] = val;
+       up(&ice->gpio_mutex);
+       return 0;
+}
+
+static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       unsigned short ovol, nvol;
+       int change = 0;
+
+       snd_ice1712_save_gpio_status(ice);
+       nvol = ucontrol->value.integer.value[0];
+       nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
+       ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+       if (ovol != nvol) {
+               wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
+               wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
+               change = 1;
+       }
+       snd_ice1712_restore_gpio_status(ice);
+       return change;
+}
+
+/*
+ */
+static int phase28_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+/*
+ * Deemphasis
+ */
+#define phase28_deemp_info     phase28_mono_bool_info
+
+static int phase28_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
+       return 0;
+}
+
+static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       int temp, temp2;
+       temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
+       if (ucontrol->value.integer.value[0])
+               temp |= 0xf;
+       else
+               temp &= ~0xf;
+       if (temp != temp2) {
+               wm_put(ice, WM_DAC_CTRL2, temp);
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * ADC Oversampling
+ */
+static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+{
+       static char *texts[2] = { "128x", "64x" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+
+        return 0;
+}
+
+static int phase28_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
+       return 0;
+}
+
+static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       int temp, temp2;
+       ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+       temp2 = temp = wm_get(ice, WM_MASTER);
+
+       if (ucontrol->value.enumerated.item[0])
+               temp |= 0x8;
+       else
+               temp &= ~0x8;
+
+       if (temp != temp2) {
+               wm_put(ice, WM_MASTER, temp);
+               return 1;
+       }
+       return 0;
+}
+
+static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Master Playback Switch",
+               .info = wm_master_mute_info,
+               .get = wm_master_mute_get,
+               .put = wm_master_mute_put
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Master Playback Volume",
+               .info = wm_master_vol_info,
+               .get = wm_master_vol_get,
+               .put = wm_master_vol_put
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Front Playback Switch",
+               .info = wm_mute_info,
+               .get = wm_mute_get,
+               .put = wm_mute_put,
+               .private_value = (2 << 8) | 0
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Front Playback Volume",
+               .info = wm_vol_info,
+               .get = wm_vol_get,
+               .put = wm_vol_put,
+               .private_value = (2 << 8) | 0
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Rear Playback Switch",
+               .info = wm_mute_info,
+               .get = wm_mute_get,
+               .put = wm_mute_put,
+               .private_value = (2 << 8) | 2
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Rear Playback Volume",
+               .info = wm_vol_info,
+               .get = wm_vol_get,
+               .put = wm_vol_put,
+               .private_value = (2 << 8) | 2
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Center Playback Switch",
+               .info = wm_mute_info,
+               .get = wm_mute_get,
+               .put = wm_mute_put,
+               .private_value = (1 << 8) | 4
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Center Playback Volume",
+               .info = wm_vol_info,
+               .get = wm_vol_get,
+               .put = wm_vol_put,
+               .private_value = (1 << 8) | 4
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "LFE Playback Switch",
+               .info = wm_mute_info,
+               .get = wm_mute_get,
+               .put = wm_mute_put,
+               .private_value = (1 << 8) | 5
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "LFE Playback Volume",
+               .info = wm_vol_info,
+               .get = wm_vol_get,
+               .put = wm_vol_put,
+               .private_value = (1 << 8) | 5
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Side Playback Switch",
+               .info = wm_mute_info,
+               .get = wm_mute_get,
+               .put = wm_mute_put,
+               .private_value = (2 << 8) | 6
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Side Playback Volume",
+               .info = wm_vol_info,
+               .get = wm_vol_get,
+               .put = wm_vol_put,
+               .private_value = (2 << 8) | 6
+       }
+};
+
+static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "PCM Playback Switch",
+               .info = wm_pcm_mute_info,
+               .get = wm_pcm_mute_get,
+               .put = wm_pcm_mute_put
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "PCM Playback Volume",
+               .info = wm_pcm_vol_info,
+               .get = wm_pcm_vol_get,
+               .put = wm_pcm_vol_put
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "DAC Deemphasis Switch",
+               .info = phase28_deemp_info,
+               .get = phase28_deemp_get,
+               .put = phase28_deemp_put
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "ADC Oversampling",
+               .info = phase28_oversampling_info,
+               .get = phase28_oversampling_get,
+               .put = phase28_oversampling_put
+       }
+};
+
+static int __devinit phase28_add_controls(ice1712_t *ice)
+{
+       unsigned int i, counts;
+       int err;
+
+       counts = ARRAY_SIZE(phase28_dac_controls);
+       for (i = 0; i < counts; i++) {
+               err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice));
+               if (err < 0)
+                       return err;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
+               err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
 struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
        {
                .subvendor = VT1724_SUBDEVICE_PHASE22,
@@ -134,5 +853,14 @@ struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
                .eeprom_size = sizeof(phase22_eeprom),
                .eeprom_data = phase22_eeprom,
        },
+       {
+               .subvendor = VT1724_SUBDEVICE_PHASE28,
+               .name = "Terratec PHASE 28",
+               .model = "phase28",
+               .chip_init = phase28_init,
+               .build_controls = phase28_add_controls,
+               .eeprom_size = sizeof(phase28_eeprom),
+               .eeprom_data = phase28_eeprom,
+       },
        { } /* terminator */
 };
index 6230cf16989f74dfb5abe518cf0c194eff3e79ab..13e841b554887a8c6b8ae9eac8ff3d17c762087c 100644 (file)
  *
  */      
 
-#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"
+#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\
+                          "{Terratec,Phase 28},"
 
 #define VT1724_SUBDEVICE_PHASE22       0x3b155011
+#define VT1724_SUBDEVICE_PHASE28       0x3b154911
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
 
+/* PHASE28 GPIO bits */
+#define PHASE28_SPI_MISO       (1 << 21)
+#define PHASE28_WM_RESET       (1 << 20)
+#define PHASE28_SPI_CLK                (1 << 19)
+#define PHASE28_SPI_MOSI       (1 << 18)
+#define PHASE28_WM_RW          (1 << 17)
+#define PHASE28_AC97_RESET     (1 << 16)
+#define PHASE28_DIGITAL_SEL1   (1 << 15)
+#define PHASE28_HP_SEL         (1 << 14)
+#define PHASE28_WM_CS          (1 << 12)
+#define PHASE28_AC97_COMMIT    (1 << 11)
+#define PHASE28_AC97_ADDR      (1 << 10)
+#define PHASE28_AC97_DATA_LOW  (1 << 9)
+#define PHASE28_AC97_DATA_HIGH (1 << 8)
+#define PHASE28_AC97_DATA_MASK 0xFF
 #endif /* __SOUND_PHASE */
index 3bd92627231c6e0beb1d4b1472c3712a900f26c5..ab61e383024f2218315332cac7213a585e902553 100644 (file)
@@ -110,6 +110,15 @@ struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
                .eeprom_size = sizeof(k8x800_eeprom),
                .eeprom_data = k8x800_eeprom,
        },
+       {
+               .subvendor = VT1720_SUBDEVICE_SN25P,
+               .name = "Shuttle SN25P",
+               /* identical with k8x800 */
+               .chip_init = k8x800_init,
+               .build_controls = k8x800_add_controls,
+               .eeprom_size = sizeof(k8x800_eeprom),
+               .eeprom_data = k8x800_eeprom,
+       },
        { } /* terminator */
 };
 
index f949eb804cae03b182551e40006d93d2dc9b0b72..0b1b0ee1bea7aba566eec6206793009a44dd718c 100644 (file)
 #define VT1720_MOBO_DEVICE_DESC        "{Albatron,K8X800 Pro II},"\
                                       "{Chaintech,ZNF3-150},"\
                                       "{Chaintech,ZNF3-250},"\
-                                      "{Chaintech,9CJS},"
+                                      "{Chaintech,9CJS},"\
+                                      "{Shuttle,SN25P},"
 
 #define VT1720_SUBDEVICE_K8X800                0xf217052c
 #define VT1720_SUBDEVICE_ZNF3_150      0x0f2741f6
 #define VT1720_SUBDEVICE_ZNF3_250      0x0f2745f6
 #define VT1720_SUBDEVICE_9CJS          0x0f272327
+#define VT1720_SUBDEVICE_SN25P         0x97123650
 
 extern struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
 
index 8b33b12fa5dc7e65fa438efebcbdd88ab65be118..cc16f95f9ceff2b71cda1e227956cdc851b93daf 100644 (file)
@@ -1725,229 +1725,235 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
 
 static struct ac97_quirk ac97_quirks[] __devinitdata = {
        {
-               .vendor = 0x0e11,
-               .device = 0x008a,
+               .subvendor = 0x0e11,
+               .subdevice = 0x008a,
                .name = "Compaq Evo W4000",     /* AD1885 */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x0e11,
-               .device = 0x00b8,
+               .subvendor = 0x0e11,
+               .subdevice = 0x00b8,
                .name = "Compaq Evo D510C",
                .type = AC97_TUNE_HP_ONLY
        },
         {
-               .vendor = 0x0e11,
-               .device = 0x0860,
+               .subvendor = 0x0e11,
+               .subdevice = 0x0860,
                .name = "HP/Compaq nx7010",
                .type = AC97_TUNE_MUTE_LED
         },
        {
-               .vendor = 0x1014,
-               .device = 0x1f00,
+               .subvendor = 0x1014,
+               .subdevice = 0x1f00,
                .name = "MS-9128",
                .type = AC97_TUNE_ALC_JACK
        },
        {
-               .vendor = 0x1028,
-               .device = 0x00d8,
+               .subvendor = 0x1028,
+               .subdevice = 0x00d8,
                .name = "Dell Precision 530",   /* AD1885 */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1028,
-               .device = 0x010d,
+               .subvendor = 0x1028,
+               .subdevice = 0x010d,
                .name = "Dell", /* which model?  AD1885 */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1028,
-               .device = 0x0126,
+               .subvendor = 0x1028,
+               .subdevice = 0x0126,
                .name = "Dell Optiplex GX260",  /* AD1981A */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1028,
-               .device = 0x012c,
+               .subvendor = 0x1028,
+               .subdevice = 0x012c,
                .name = "Dell Precision 650",   /* AD1981A */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1028,
-               .device = 0x012d,
+               .subvendor = 0x1028,
+               .subdevice = 0x012d,
                .name = "Dell Precision 450",   /* AD1981B*/
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1028,
-               .device = 0x0147,
+               .subvendor = 0x1028,
+               .subdevice = 0x0147,
                .name = "Dell", /* which model?  AD1981B*/
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1028,
-               .device = 0x0163,
+               .subvendor = 0x1028,
+               .subdevice = 0x0163,
                .name = "Dell Unknown", /* STAC9750/51 */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x103c,
-               .device = 0x006d,
+               .subvendor = 0x103c,
+               .subdevice = 0x006d,
                .name = "HP zv5000",
                .type = AC97_TUNE_MUTE_LED      /*AD1981B*/
        },
        {       /* FIXME: which codec? */
-               .vendor = 0x103c,
-               .device = 0x00c3,
+               .subvendor = 0x103c,
+               .subdevice = 0x00c3,
                .name = "HP xw6000",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x103c,
-               .device = 0x088c,
+               .subvendor = 0x103c,
+               .subdevice = 0x088c,
                .name = "HP nc8000",
                .type = AC97_TUNE_MUTE_LED
        },
        {
-               .vendor = 0x103c,
-               .device = 0x0890,
+               .subvendor = 0x103c,
+               .subdevice = 0x0890,
                .name = "HP nc6000",
                .type = AC97_TUNE_MUTE_LED
        },
        {
-               .vendor = 0x103c,
-               .device = 0x129d,
+               .subvendor = 0x103c,
+               .subdevice = 0x129d,
                .name = "HP xw8000",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x103c,
-               .device = 0x12f1,
+               .subvendor = 0x103c,
+               .subdevice = 0x12f1,
                .name = "HP xw8200",    /* AD1981B*/
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x103c,
-               .device = 0x12f2,
+               .subvendor = 0x103c,
+               .subdevice = 0x12f2,
                .name = "HP xw6200",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x103c,
-               .device = 0x3008,
+               .subvendor = 0x103c,
+               .subdevice = 0x3008,
                .name = "HP xw4200",    /* AD1981B*/
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x104d,
-               .device = 0x8197,
+               .subvendor = 0x104d,
+               .subdevice = 0x8197,
                .name = "Sony S1XP",
                .type = AC97_TUNE_INV_EAPD
        },
        {
-               .vendor = 0x1043,
-               .device = 0x80f3,
+               .subvendor = 0x1043,
+               .subdevice = 0x80f3,
                .name = "ASUS ICH5/AD1985",
                .type = AC97_TUNE_AD_SHARING
        },
        {
-               .vendor = 0x10cf,
-               .device = 0x11c3,
+               .subvendor = 0x10cf,
+               .subdevice = 0x11c3,
                .name = "Fujitsu-Siemens E4010",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x10cf,
-               .device = 0x1253,
+               .subvendor = 0x10cf,
+               .subdevice = 0x1225,
+               .name = "Fujitsu-Siemens T3010",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .subvendor = 0x10cf,
+               .subdevice = 0x1253,
                .name = "Fujitsu S6210",        /* STAC9750/51 */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x10f1,
-               .device = 0x2665,
+               .subvendor = 0x10f1,
+               .subdevice = 0x2665,
                .name = "Fujitsu-Siemens Celsius",      /* AD1981? */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x10f1,
-               .device = 0x2885,
+               .subvendor = 0x10f1,
+               .subdevice = 0x2885,
                .name = "AMD64 Mobo",   /* ALC650 */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x110a,
-               .device = 0x0056,
+               .subvendor = 0x110a,
+               .subdevice = 0x0056,
                .name = "Fujitsu-Siemens Scenic",       /* AD1981? */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x11d4,
-               .device = 0x5375,
+               .subvendor = 0x11d4,
+               .subdevice = 0x5375,
                .name = "ADI AD1985 (discrete)",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1462,
-               .device = 0x5470,
+               .subvendor = 0x1462,
+               .subdevice = 0x5470,
                .name = "MSI P4 ATX 645 Ultra",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1734,
-               .device = 0x0088,
+               .subvendor = 0x1734,
+               .subdevice = 0x0088,
                .name = "Fujitsu-Siemens D1522",        /* AD1981 */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x8086,
-               .device = 0x2000,
+               .subvendor = 0x8086,
+               .subdevice = 0x2000,
                .mask = 0xfff0,
                .name = "Intel ICH5/AD1985",
                .type = AC97_TUNE_AD_SHARING
        },
        {
-               .vendor = 0x8086,
-               .device = 0x4000,
+               .subvendor = 0x8086,
+               .subdevice = 0x4000,
                .mask = 0xfff0,
                .name = "Intel ICH5/AD1985",
                .type = AC97_TUNE_AD_SHARING
        },
        {
-               .vendor = 0x8086,
-               .device = 0x4856,
+               .subvendor = 0x8086,
+               .subdevice = 0x4856,
                .name = "Intel D845WN (82801BA)",
                .type = AC97_TUNE_SWAP_HP
        },
        {
-               .vendor = 0x8086,
-               .device = 0x4d44,
+               .subvendor = 0x8086,
+               .subdevice = 0x4d44,
                .name = "Intel D850EMV2",       /* AD1885 */
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x8086,
-               .device = 0x4d56,
+               .subvendor = 0x8086,
+               .subdevice = 0x4d56,
                .name = "Intel ICH/AD1885",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x8086,
-               .device = 0x6000,
+               .subvendor = 0x8086,
+               .subdevice = 0x6000,
                .mask = 0xfff0,
                .name = "Intel ICH5/AD1985",
                .type = AC97_TUNE_AD_SHARING
        },
        {
-               .vendor = 0x8086,
-               .device = 0xe000,
+               .subvendor = 0x8086,
+               .subdevice = 0xe000,
                .mask = 0xfff0,
                .name = "Intel ICH5/AD1985",
                .type = AC97_TUNE_AD_SHARING
        },
 #if 0 /* FIXME: this seems wrong on most boards */
        {
-               .vendor = 0x8086,
-               .device = 0xa000,
+               .subvendor = 0x8086,
+               .subdevice = 0xa000,
                .mask = 0xfff0,
                .name = "Intel ICH5/AD1985",
                .type = AC97_TUNE_HP_ONLY
@@ -2849,7 +2855,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_intel8x0_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_intel8x0_exit(void)
index 67da096d659b3d2e35ce894f0979d0b353bf9d27..bb758c77d211067ab49979f0fb962f7db654ae2c 100644 (file)
@@ -35,7 +35,6 @@
 #include <sound/pcm.h>
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
-#include <sound/control.h>
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -292,60 +291,9 @@ static struct pci_device_id snd_intel8x0m_ids[] = {
 #endif
        { 0, }
 };
-static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
-                                           snd_ctl_elem_value_t *ucontrol);
-static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
-                                           snd_ctl_elem_value_t *ucontrol);
-static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
-                                            snd_ctl_elem_info_t *uinfo);
-
-#define PRIVATE_VALUE_INITIALIZER(r,m) (((r) & 0xffff) << 16 | ((m) & 0xffff))
-#define PRIVATE_VALUE_MASK(control) ((control)->private_value & 0xffff)
-#define PRIVATE_VALUE_REG(control) (((control)->private_value >> 16) & 0xffff)
-
-static snd_kcontrol_new_t snd_intel8x0m_mixer_switches[] __devinitdata = {
-  { .name  = "Off-hook Switch",
-    .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-    .info  = snd_intel8x0m_switch_default_info,
-    .get   = snd_intel8x0m_switch_default_get,
-    .put   = snd_intel8x0m_switch_default_put,
-    .private_value = PRIVATE_VALUE_INITIALIZER(AC97_GPIO_STATUS,AC97_GPIO_LINE1_OH)
-  }
-};
 
 MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
 
-static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
-                                            snd_ctl_elem_info_t *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
-}
-
-static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
-                                           snd_ctl_elem_value_t *ucontrol)
-{
-       unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
-       unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
-       intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
-       unsigned int status;
-       status = snd_ac97_read(chip->ac97, reg) & mask ? 1 : 0;
-       ucontrol->value.integer.value[0] = status;
-       return 0;
-}
-static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
-                                           snd_ctl_elem_value_t *ucontrol)
-{
-       unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
-       unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
-       intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
-       unsigned short new_status = ucontrol->value.integer.value[0] ? mask : ~mask;
-       return snd_ac97_update_bits(chip->ac97, reg,
-                                   mask, new_status);
-}
 /*
  *  Lowlevel I/O - busmaster
  */
@@ -500,6 +448,8 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
                        res = 0xffff;
                }
        }
+       if (reg == AC97_GPIO_STATUS)
+               iagetword(chip, 0); /* clear semaphore */
        return res;
 }
 
@@ -698,21 +648,6 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
        return bytes_to_frames(substream->runtime, ptr);
 }
 
-static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
-{
-       /* hook off/on on start/stop */
-       /* Moved this to mixer control */
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-               break;
-       default:
-               return -EINVAL;
-       }
-       return snd_intel8x0_pcm_trigger(substream,cmd);
-}
-
 static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream)
 {
        intel8x0_t *chip = snd_pcm_substream_chip(substream);
@@ -808,7 +743,7 @@ static snd_pcm_ops_t snd_intel8x0m_playback_ops = {
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0m_pcm_prepare,
-       .trigger =      snd_intel8x0m_pcm_trigger,
+       .trigger =      snd_intel8x0_pcm_trigger,
        .pointer =      snd_intel8x0_pcm_pointer,
 };
 
@@ -819,7 +754,7 @@ static snd_pcm_ops_t snd_intel8x0m_capture_ops = {
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0m_pcm_prepare,
-       .trigger =      snd_intel8x0m_pcm_trigger,
+       .trigger =      snd_intel8x0_pcm_trigger,
        .pointer =      snd_intel8x0_pcm_pointer,
 };
 
@@ -947,7 +882,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
        ac97_t *x97;
        int err;
        unsigned int glob_sta = 0;
-       unsigned int idx;
        static ac97_bus_ops_t ops = {
                .write = snd_intel8x0_codec_write,
                .read = snd_intel8x0_codec_read,
@@ -983,10 +917,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
                chip->ichd[ICHD_MDMIN].ac97 = x97;
                chip->ichd[ICHD_MDMOUT].ac97 = x97;
        }
-       for (idx = 0; idx < ARRAY_SIZE(snd_intel8x0m_mixer_switches); idx++) {
-               if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_intel8x0m_mixer_switches[idx], chip))) < 0)
-                       goto __err;
-       }
 
        chip->in_ac97_init = 0;
        return 0;
@@ -1450,7 +1380,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_intel8x0m_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_intel8x0m_exit(void)
index bb1de20081760d7857652b85e2db3164c305e3c0..79d8eda54f0d48dfa60690db217f7251d451bcfd 100644 (file)
@@ -2541,7 +2541,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_korg1212_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_korg1212_exit(void)
index 2cf33083d7ccb0b3a7c04090bec1f63fc4f2e969..096f15132853b49e61d7e8c13b361d3f2c0e5334 100644 (file)
@@ -779,6 +779,12 @@ struct m3_quirk {
                                   (e.g. for IrDA on Dell Inspirons) */
 };
 
+struct m3_hv_quirk {
+       u16 vendor, device, subsystem_vendor, subsystem_device;
+       u32 config;             /* ALLEGRO_CONFIG hardware volume bits */
+       int is_omnibook;        /* Do HP OmniBook GPIO magic? */
+};
+
 struct m3_list {
        int curlen;
        int mem_addr;
@@ -828,6 +834,7 @@ struct snd_m3 {
 
        struct pci_dev *pci;
        struct m3_quirk *quirk;
+       struct m3_hv_quirk *hv_quirk;
 
        int dacs_active;
        int timer_users;
@@ -851,6 +858,11 @@ struct snd_m3 {
        m3_dma_t *substreams;
 
        spinlock_t reg_lock;
+       spinlock_t ac97_lock;
+
+       snd_kcontrol_t *master_switch;
+       snd_kcontrol_t *master_volume;
+       struct tasklet_struct hwvol_tq;
 
 #ifdef CONFIG_PM
        u16 *suspend_mem;
@@ -968,6 +980,71 @@ static struct m3_quirk m3_quirk_list[] = {
        { NULL }
 };
 
+/* These values came from the Windows driver. */
+static struct m3_hv_quirk m3_hv_quirk_list[] = {
+       /* Allegro chips */
+       { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+       { 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */
+       { 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 },
+       /* Maestro3 chips */
+       { 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */
+       { 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */
+       { 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 },
+       { 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+       { 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+       { 0 }
+};
 
 /*
  * lowlevel functions
@@ -1565,6 +1642,68 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s)
        }
 }
 
+static void snd_m3_update_hw_volume(unsigned long private_data)
+{
+       m3_t *chip = (m3_t *) private_data;
+       int x, val;
+       unsigned long flags;
+
+       /* Figure out which volume control button was pushed,
+          based on differences from the default register
+          values. */
+       x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee;
+
+       /* Reset the volume control registers. */
+       outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE);
+       outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE);
+       outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER);
+       outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER);
+
+       if (!chip->master_switch || !chip->master_volume)
+               return;
+
+       /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */
+       spin_lock_irqsave(&chip->ac97_lock, flags);
+
+       val = chip->ac97->regs[AC97_MASTER_VOL];
+       switch (x) {
+       case 0x88:
+               /* mute */
+               val ^= 0x8000;
+               chip->ac97->regs[AC97_MASTER_VOL] = val;
+               outw(val, chip->iobase + CODEC_DATA);
+               outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                              &chip->master_switch->id);
+               break;
+       case 0xaa:
+               /* volume up */
+               if ((val & 0x7f) > 0)
+                       val--;
+               if ((val & 0x7f00) > 0)
+                       val -= 0x0100;
+               chip->ac97->regs[AC97_MASTER_VOL] = val;
+               outw(val, chip->iobase + CODEC_DATA);
+               outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                              &chip->master_volume->id);
+               break;
+       case 0x66:
+               /* volume down */
+               if ((val & 0x7f) < 0x1f)
+                       val++;
+               if ((val & 0x7f00) < 0x1f00)
+                       val += 0x0100;
+               chip->ac97->regs[AC97_MASTER_VOL] = val;
+               outw(val, chip->iobase + CODEC_DATA);
+               outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+               snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                              &chip->master_volume->id);
+               break;
+       }
+       spin_unlock_irqrestore(&chip->ac97_lock, flags);
+}
+
 static irqreturn_t
 snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -1576,7 +1715,10 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        if (status == 0xff)
                return IRQ_NONE;
-   
+
+       if (status & HV_INT_PENDING)
+               tasklet_hi_schedule(&chip->hwvol_tq);
+
        /*
         * ack an assp int if its running
         * and has an int pending
@@ -1605,7 +1747,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #endif
 
        /* ack ints */
-       snd_m3_outw(chip, HOST_INT_STATUS, status);
+       outb(status, chip->iobase + HOST_INT_STATUS);
 
        return IRQ_HANDLED;
 }
@@ -1842,24 +1984,32 @@ static unsigned short
 snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
 {
        m3_t *chip = ac97->private_data;
+       unsigned long flags;
+       unsigned short data;
 
        if (snd_m3_ac97_wait(chip))
                return 0xffff;
+       spin_lock_irqsave(&chip->ac97_lock, flags);
        snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
        if (snd_m3_ac97_wait(chip))
                return 0xffff;
-       return snd_m3_inw(chip, CODEC_DATA);
+       data = snd_m3_inw(chip, CODEC_DATA);
+       spin_unlock_irqrestore(&chip->ac97_lock, flags);
+       return data;
 }
 
 static void
 snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
        m3_t *chip = ac97->private_data;
+       unsigned long flags;
 
        if (snd_m3_ac97_wait(chip))
                return;
+       spin_lock_irqsave(&chip->ac97_lock, flags);
        snd_m3_outw(chip, val, CODEC_DATA);
        snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
+       spin_unlock_irqrestore(&chip->ac97_lock, flags);
 }
 
 
@@ -1968,6 +2118,7 @@ static int __devinit snd_m3_mixer(m3_t *chip)
 {
        ac97_bus_t *pbus;
        ac97_template_t ac97;
+       snd_ctl_elem_id_t id;
        int err;
        static ac97_bus_ops_t ops = {
                .write = snd_m3_ac97_write,
@@ -1988,6 +2139,15 @@ static int __devinit snd_m3_mixer(m3_t *chip)
        schedule_timeout(HZ / 10);
        snd_ac97_write(chip->ac97, AC97_PCM, 0);
 
+       memset(&id, 0, sizeof(id));
+       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strcpy(id.name, "Master Playback Switch");
+       chip->master_switch = snd_ctl_find_id(chip->card, &id);
+       memset(&id, 0, sizeof(id));
+       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strcpy(id.name, "Master Playback Volume");
+       chip->master_volume = snd_ctl_find_id(chip->card, &id);
+
        return 0;
 }
 
@@ -2293,6 +2453,7 @@ static int
 snd_m3_chip_init(m3_t *chip)
 {
        struct pci_dev *pcidev = chip->pci;
+       unsigned long io = chip->iobase;
        u32 n;
        u16 w;
        u8 t; /* makes as much sense as 'n', no? */
@@ -2303,8 +2464,27 @@ snd_m3_chip_init(m3_t *chip)
               DISABLE_LEGACY);
        pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
 
+       if (chip->hv_quirk && chip->hv_quirk->is_omnibook) {
+               /*
+                * Volume buttons on some HP OmniBook laptops don't work
+                * correctly. This makes them work for the most part.
+                *
+                * Volume up and down buttons on the laptop side work.
+                * Fn+cursor_up (volme up) works.
+                * Fn+cursor_down (volume down) doesn't work.
+                * Fn+F7 (mute) works acts as volume up.
+                */
+               outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK);
+               outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION);
+               outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA);
+               outw(0xffff, io + GPIO_MASK);
+       }
        pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
-       n &= REDUCED_DEBOUNCE;
+       n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
+       if (chip->hv_quirk)
+               n |= chip->hv_quirk->config;
+       /* For some reason we must always use reduced debounce. */
+       n |= REDUCED_DEBOUNCE;
        n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
        pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n);
 
@@ -2332,6 +2512,12 @@ snd_m3_chip_init(m3_t *chip)
 
        outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); 
 
+       outb(0x00, io + HARDWARE_VOL_CTRL);
+       outb(0x88, io + SHADOW_MIX_REG_VOICE);
+       outb(0x88, io + HW_VOL_COUNTER_VOICE);
+       outb(0x88, io + SHADOW_MIX_REG_MASTER);
+       outb(0x88, io + HW_VOL_COUNTER_MASTER);
+
        return 0;
 } 
 
@@ -2341,7 +2527,7 @@ snd_m3_enable_ints(m3_t *chip)
        unsigned long io = chip->iobase;
 
        /* TODO: MPU401 not supported yet */
-       outw(ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
+       outw(ASSP_INT_ENABLE | HV_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
        outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
             io + ASSP_CONTROL_C);
 }
@@ -2367,7 +2553,7 @@ static int snd_m3_free(m3_t *chip)
                kfree(chip->substreams);
        }
        if (chip->iobase) {
-               snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */
+               outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */
        }
 
 #ifdef CONFIG_PM
@@ -2486,7 +2672,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
        m3_t *chip;
        int i, err;
        struct m3_quirk *quirk;
-       u16 subsystem_vendor, subsystem_device;
+       struct m3_hv_quirk *hv_quirk;
        static snd_device_ops_t ops = {
                .dev_free =     snd_m3_dev_free,
        };
@@ -2524,18 +2710,25 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
        chip->pci = pci;
        chip->irq = -1;
 
-       pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
-       pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-
        for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
-               if (subsystem_vendor == quirk->vendor &&
-                   subsystem_device == quirk->device) {
+               if (pci->subsystem_vendor == quirk->vendor &&
+                   pci->subsystem_device == quirk->device) {
                        printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name);
                        chip->quirk = quirk;
                        break;
                }
        }
 
+       for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) {
+               if (pci->vendor == hv_quirk->vendor &&
+                   pci->device == hv_quirk->device &&
+                   pci->subsystem_vendor == hv_quirk->subsystem_vendor &&
+                   pci->subsystem_device == hv_quirk->subsystem_device) {
+                       chip->hv_quirk = hv_quirk;
+                       break;
+               }
+       }
+
        chip->external_amp = enable_amp;
        if (amp_gpio >= 0 && amp_gpio <= 0x0f)
                chip->amp_gpio = amp_gpio;
@@ -2593,6 +2786,9 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
                return err;
        }
 
+       spin_lock_init(&chip->ac97_lock);
+       tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
+
        if ((err = snd_m3_mixer(chip)) < 0)
                return err;
 
@@ -2702,7 +2898,7 @@ static struct pci_driver driver = {
        
 static int __init alsa_card_m3_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_m3_exit(void)
index 65bb0f47af2c1fffb0bfe641441ece2d06823d7b..082c0d0f73d2ff6afea55c342d9517483efbeed3 100644 (file)
@@ -1431,7 +1431,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_mixart_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_mixart_exit(void)
index 356fbeac6f9e025143f724bb13402830f7e4560a..8a52091f8552a2b1f42bafb821368eb5755adc41 100644 (file)
@@ -1645,7 +1645,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_nm256_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_nm256_exit(void)
index b96acd5a57dbdfbf246efdbc36820249153ea7e2..b7b554df6705b368e4610e71ad9552dc6e79965e 100644 (file)
@@ -2031,7 +2031,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_rme32_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_rme32_exit(void)
index 8e2666841d21154204b6158282e8586d283881ba..10c4f45a913c7bc449c8403d03edb3f7f987cfac 100644 (file)
@@ -2437,7 +2437,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_rme96_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_rme96_exit(void)
index 917374c9cd40763c7013b669f14ca2152a520158..d2c294e136f9c05f225e74e2661b4c39698faa22 100644 (file)
@@ -5,7 +5,9 @@
 
 snd-rme9652-objs := rme9652.o
 snd-hdsp-objs := hdsp.o
+snd-hdspm-objs := hdspm.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_RME9652) += snd-rme9652.o
 obj-$(CONFIG_SND_HDSP) += snd-hdsp.o
+obj-$(CONFIG_SND_HDSPM) +=snd-hdspm.o
index 12efbf0fab549241de4fdfb32f129a1d87eefb4b..a673cc438b917fb0f5ced486e4ceab17c7e53e27 100644 (file)
@@ -559,18 +559,22 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
 {
        dmab->dev.type = SNDRV_DMA_TYPE_DEV;
        dmab->dev.dev = snd_dma_pci_data(pci);
-       if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
-               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-                                       size, dmab) < 0)
-                       return -ENOMEM;
+       if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+               if (dmab->bytes >= size)
+                       return 0;
        }
+       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+                               size, dmab) < 0)
+               return -ENOMEM;
        return 0;
 }
 
 static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-       if (dmab->area)
+       if (dmab->area) {
+               dmab->dev.dev = NULL; /* make it anonymous */
                snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
+       }
 }
 
 
@@ -4912,19 +4916,9 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
                release_firmware(fw);
                return -EINVAL;
        }
-#ifdef SNDRV_BIG_ENDIAN
-       {
-               int i;
-               u32 *src = (u32*)fw->data;
-               for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++)
-                       hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) |
-                               ((*src & 0x0000ff00) << 8)  |
-                               ((*src & 0x00ff0000) >> 8)  |
-                               ((*src & 0xff000000) >> 16);
-       }
-#else
+
        memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
-#endif
+
        release_firmware(fw);
                
        hdsp->state |= HDSP_FirmwareCached;
@@ -5194,7 +5188,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_hdsp_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_hdsp_exit(void)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
new file mode 100644 (file)
index 0000000..9e86d0e
--- /dev/null
@@ -0,0 +1,3671 @@
+/*   -*- linux-c -*-
+ *
+ *   ALSA driver for RME Hammerfall DSP MADI audio interface(s)
+ *
+ *      Copyright (c) 2003 Winfried Ritsch (IEM)
+ *      code based on hdsp.c   Paul Davis
+ *                             Marcus Andersson
+ *                             Thomas Charbonnel
+ *
+ *   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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/info.h>
+#include <sound/asoundef.h>
+#include <sound/rawmidi.h>
+#include <sound/hwdep.h>
+#include <sound/initval.h>
+
+#include <sound/hdspm.h>
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;       /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;        /* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+
+/* Disable precise pointer at start */
+static int precise_ptr[SNDRV_CARDS];
+
+/* Send all playback to line outs */
+static int line_outs_monitor[SNDRV_CARDS];
+
+/* Enable Analog Outs on Channel 63/64 by default */
+static int enable_monitor[SNDRV_CARDS];
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
+
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
+
+module_param_array(precise_ptr, bool, NULL, 0444);
+MODULE_PARM_DESC(precise_ptr, "Enable precise pointer, or disable.");
+
+module_param_array(line_outs_monitor, bool, NULL, 0444);
+MODULE_PARM_DESC(line_outs_monitor,
+                "Send playback streams to analog outs by default.");
+
+module_param_array(enable_monitor, bool, NULL, 0444);
+MODULE_PARM_DESC(enable_monitor,
+                "Enable Analog Out on Channel 63/64 by default.");
+
+MODULE_AUTHOR
+      ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
+       "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
+MODULE_DESCRIPTION("RME HDSPM");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
+
+/* --- Write registers. --- 
+  These are defined as byte-offsets from the iobase value.  */
+
+#define HDSPM_controlRegister       64
+#define HDSPM_interruptConfirmation  96
+#define HDSPM_control2Reg           256  /* not in specs ???????? */
+#define HDSPM_midiDataOut0          352  /* just believe in old code */
+#define HDSPM_midiDataOut1          356
+
+/* DMA enable for 64 channels, only Bit 0 is relevant */
+#define HDSPM_outputEnableBase       512  /* 512-767  input  DMA */ 
+#define HDSPM_inputEnableBase        768  /* 768-1023 output DMA */
+
+/* 16 page addresses for each of the 64 channels DMA buffer in and out 
+   (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
+#define HDSPM_pageAddressBufferOut       8192
+#define HDSPM_pageAddressBufferIn        (HDSPM_pageAddressBufferOut+64*16*4)
+
+#define HDSPM_MADI_mixerBase    32768  /* 32768-65535 for 2x64x64 Fader */
+
+#define HDSPM_MATRIX_MIXER_SIZE  8192  /* = 2*64*64 * 4 Byte => 32kB */
+
+/* --- Read registers. ---
+   These are defined as byte-offsets from the iobase value */
+#define HDSPM_statusRegister    0
+#define HDSPM_statusRegister2  96
+
+#define HDSPM_midiDataIn0     360
+#define HDSPM_midiDataIn1     364
+
+/* status is data bytes in MIDI-FIFO (0-128) */
+#define HDSPM_midiStatusOut0  384      
+#define HDSPM_midiStatusOut1  388      
+#define HDSPM_midiStatusIn0   392      
+#define HDSPM_midiStatusIn1   396      
+
+
+/* the meters are regular i/o-mapped registers, but offset
+   considerably from the rest. the peak registers are reset
+   when read; the least-significant 4 bits are full-scale counters; 
+   the actual peak value is in the most-significant 24 bits.
+*/
+#define HDSPM_MADI_peakrmsbase         4096    /* 4096-8191 2x64x32Bit Meters */
+
+/* --- Control Register bits --------- */
+#define HDSPM_Start                (1<<0) /* start engine */
+
+#define HDSPM_Latency0             (1<<1) /* buffer size = 2^n */
+#define HDSPM_Latency1             (1<<2) /* where n is defined */
+#define HDSPM_Latency2             (1<<3) /* by Latency{2,1,0} */
+
+#define HDSPM_ClockModeMaster      (1<<4) /* 1=Master, 0=Slave/Autosync */
+
+#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
+
+#define HDSPM_Frequency0  (1<<6)  /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
+#define HDSPM_Frequency1  (1<<7)  /* 0=32kHz/64kHz */
+#define HDSPM_DoubleSpeed (1<<8)  /* 0=normal speed, 1=double speed */
+#define HDSPM_QuadSpeed   (1<<31) /* quad speed bit, not implemented now */
+
+#define HDSPM_TX_64ch     (1<<10) /* Output 64channel MODE=1,
+                                    56channelMODE=0 */
+
+#define HDSPM_AutoInp     (1<<11) /* Auto Input (takeover) == Safe Mode, 
+                                     0=off, 1=on  */
+
+#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */
+#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
+
+#define HDSPM_SyncRef0     (1<<16) /* 0=WOrd, 1=MADI */
+#define HDSPM_SyncRef1     (1<<17) /* should be 0 */
+
+#define HDSPM_clr_tms      (1<<19) /* clear track marker, do not use 
+                                      AES additional bits in
+                                     lower 5 Audiodatabits ??? */
+
+#define HDSPM_Midi0InterruptEnable (1<<22)
+#define HDSPM_Midi1InterruptEnable (1<<23)
+
+#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
+
+
+/* --- bit helper defines */
+#define HDSPM_LatencyMask    (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
+#define HDSPM_FrequencyMask  (HDSPM_Frequency0|HDSPM_Frequency1)
+#define HDSPM_InputMask      (HDSPM_InputSelect0|HDSPM_InputSelect1)
+#define HDSPM_InputOptical   0
+#define HDSPM_InputCoaxial   (HDSPM_InputSelect0)
+#define HDSPM_SyncRefMask    (HDSPM_SyncRef0|HDSPM_SyncRef1)
+#define HDSPM_SyncRef_Word   0
+#define HDSPM_SyncRef_MADI   (HDSPM_SyncRef0)
+
+#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
+#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
+
+#define HDSPM_Frequency32KHz    HDSPM_Frequency0
+#define HDSPM_Frequency44_1KHz  HDSPM_Frequency1
+#define HDSPM_Frequency48KHz   (HDSPM_Frequency1|HDSPM_Frequency0)
+#define HDSPM_Frequency64KHz   (HDSPM_DoubleSpeed|HDSPM_Frequency0)
+#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
+#define HDSPM_Frequency96KHz   (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
+
+/* --- for internal discrimination */
+#define HDSPM_CLOCK_SOURCE_AUTOSYNC          0 /* Sample Clock Sources */
+#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ    1
+#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ  2
+#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ    3
+#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ    4
+#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ  5
+#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ    6
+#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ   7
+#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
+#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ   9
+
+/* Synccheck Status */
+#define HDSPM_SYNC_CHECK_NO_LOCK 0
+#define HDSPM_SYNC_CHECK_LOCK    1
+#define HDSPM_SYNC_CHECK_SYNC   2
+
+/* AutoSync References - used by "autosync_ref" control switch */
+#define HDSPM_AUTOSYNC_FROM_WORD      0
+#define HDSPM_AUTOSYNC_FROM_MADI      1
+#define HDSPM_AUTOSYNC_FROM_NONE      2
+
+/* Possible sources of MADI input */
+#define HDSPM_OPTICAL 0                /* optical   */
+#define HDSPM_COAXIAL 1                /* BNC */
+
+#define hdspm_encode_latency(x)       (((x)<<1) & HDSPM_LatencyMask)
+#define hdspm_decode_latency(x)       (((x) & HDSPM_LatencyMask)>>1)
+
+#define hdspm_encode_in(x) (((x)&0x3)<<14)
+#define hdspm_decode_in(x) (((x)>>14)&0x3)
+
+/* --- control2 register bits --- */
+#define HDSPM_TMS             (1<<0)
+#define HDSPM_TCK             (1<<1)
+#define HDSPM_TDI             (1<<2)
+#define HDSPM_JTAG            (1<<3)
+#define HDSPM_PWDN            (1<<4)
+#define HDSPM_PROGRAM        (1<<5)
+#define HDSPM_CONFIG_MODE_0   (1<<6)
+#define HDSPM_CONFIG_MODE_1   (1<<7)
+/*#define HDSPM_VERSION_BIT     (1<<8) not defined any more*/
+#define HDSPM_BIGENDIAN_MODE  (1<<9)
+#define HDSPM_RD_MULTIPLE     (1<<10)
+
+/* --- Status Register bits --- */
+#define HDSPM_audioIRQPending    (1<<0)        /* IRQ is high and pending */
+#define HDSPM_RX_64ch            (1<<1)        /* Input 64chan. MODE=1, 56chn. MODE=0 */
+#define HDSPM_AB_int             (1<<2)        /* InputChannel Opt=0, Coax=1 (like inp0) */
+#define HDSPM_madiLock           (1<<3)        /* MADI Locked =1, no=0 */
+
+#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
+                                           /* since 64byte accurate last 6 bits 
+                                              are not used */
+
+#define HDSPM_madiSync          (1<<18) /* MADI is in sync */
+#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
+
+#define HDSPM_madiFreq0         (1<<22)        /* system freq 0=error */
+#define HDSPM_madiFreq1         (1<<23)        /* 1=32, 2=44.1 3=48 */
+#define HDSPM_madiFreq2         (1<<24)        /* 4=64, 5=88.2 6=96 */
+#define HDSPM_madiFreq3         (1<<25)        /* 7=128, 8=176.4 9=192 */
+
+#define HDSPM_BufferID          (1<<26)        /* (Double)Buffer ID toggles with Interrupt */
+#define HDSPM_midi0IRQPending   (1<<30)        /* MIDI IRQ is pending  */
+#define HDSPM_midi1IRQPending   (1<<31)        /* and aktiv */
+
+/* --- status bit helpers */
+#define HDSPM_madiFreqMask  (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3)
+#define HDSPM_madiFreq32    (HDSPM_madiFreq0)
+#define HDSPM_madiFreq44_1  (HDSPM_madiFreq1)
+#define HDSPM_madiFreq48    (HDSPM_madiFreq0|HDSPM_madiFreq1)
+#define HDSPM_madiFreq64    (HDSPM_madiFreq2)
+#define HDSPM_madiFreq88_2  (HDSPM_madiFreq0|HDSPM_madiFreq2)
+#define HDSPM_madiFreq96    (HDSPM_madiFreq1|HDSPM_madiFreq2)
+#define HDSPM_madiFreq128   (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
+#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
+#define HDSPM_madiFreq192   (HDSPM_madiFreq3|HDSPM_madiFreq0)
+
+/* Status2 Register bits */
+
+#define HDSPM_version0 (1<<0)  /* not realy defined but I guess */
+#define HDSPM_version1 (1<<1)  /* in former cards it was ??? */
+#define HDSPM_version2 (1<<2)
+
+#define HDSPM_wcLock (1<<3)    /* Wordclock is detected and locked */
+#define HDSPM_wcSync (1<<4)    /* Wordclock is in sync with systemclock */
+
+#define HDSPM_wc_freq0 (1<<5)  /* input freq detected via autosync  */
+#define HDSPM_wc_freq1 (1<<6)  /* 001=32, 010==44.1, 011=48, */
+#define HDSPM_wc_freq2 (1<<7)  /* 100=64, 101=88.2, 110=96, */
+/* missing Bit   for               111=128, 1000=176.4, 1001=192 */
+
+#define HDSPM_SelSyncRef0 (1<<8)       /* Sync Source in slave mode */
+#define HDSPM_SelSyncRef1 (1<<9)       /* 000=word, 001=MADI, */
+#define HDSPM_SelSyncRef2 (1<<10)      /* 111=no valid signal */
+
+#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
+
+#define HDSPM_wcFreqMask  (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
+#define HDSPM_wcFreq32    (HDSPM_wc_freq0)
+#define HDSPM_wcFreq44_1  (HDSPM_wc_freq1)
+#define HDSPM_wcFreq48    (HDSPM_wc_freq0|HDSPM_wc_freq1)
+#define HDSPM_wcFreq64    (HDSPM_wc_freq2)
+#define HDSPM_wcFreq88_2  (HDSPM_wc_freq0|HDSPM_wc_freq2)
+#define HDSPM_wcFreq96    (HDSPM_wc_freq1|HDSPM_wc_freq2)
+
+
+#define HDSPM_SelSyncRefMask       (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
+#define HDSPM_SelSyncRef_WORD      0
+#define HDSPM_SelSyncRef_MADI      (HDSPM_SelSyncRef0)
+#define HDSPM_SelSyncRef_NVALID    (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
+
+/* Mixer Values */
+#define UNITY_GAIN          32768      /* = 65536/2 */
+#define MINUS_INFINITY_GAIN 0
+
+/* PCI info */
+#ifndef PCI_VENDOR_ID_XILINX
+#define PCI_VENDOR_ID_XILINX           0x10ee
+#endif
+#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
+#endif
+#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
+#endif
+
+
+/* Number of channels for different Speed Modes */
+#define MADI_SS_CHANNELS       64
+#define MADI_DS_CHANNELS       32
+#define MADI_QS_CHANNELS       16
+
+/* the size of a substream (1 mono data stream) */
+#define HDSPM_CHANNEL_BUFFER_SAMPLES  (16*1024)
+#define HDSPM_CHANNEL_BUFFER_BYTES    (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
+
+/* the size of the area we need to allocate for DMA transfers. the
+   size is the same regardless of the number of channels, and
+   also the latency to use. 
+   for one direction !!!
+*/
+#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
+#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
+
+typedef struct _hdspm hdspm_t;
+typedef struct _hdspm_midi hdspm_midi_t;
+
+struct _hdspm_midi {
+       hdspm_t *hdspm;
+       int id;
+       snd_rawmidi_t *rmidi;
+       snd_rawmidi_substream_t *input;
+       snd_rawmidi_substream_t *output;
+       char istimer;           /* timer in use */
+       struct timer_list timer;
+       spinlock_t lock;
+       int pending;
+};
+
+struct _hdspm {
+        spinlock_t lock;
+        snd_pcm_substream_t *capture_substream;         /* only one playback */
+        snd_pcm_substream_t *playback_substream; /* and/or capture stream */
+
+       char *card_name;             /* for procinfo */
+       unsigned short firmware_rev; /* dont know if relevant */
+
+       int precise_ptr;        /* use precise pointers, to be tested */
+       int monitor_outs;       /* set up monitoring outs init flag */
+
+       u32 control_register;   /* cached value */
+       u32 control2_register;  /* cached value */
+
+       hdspm_midi_t midi[2];
+       struct tasklet_struct midi_tasklet;
+
+       size_t period_bytes;
+       unsigned char ss_channels;      /* channels of card in single speed */
+       unsigned char ds_channels;      /* Double Speed */
+       unsigned char qs_channels;      /* Quad Speed */
+
+       unsigned char *playback_buffer; /* suitably aligned address */
+       unsigned char *capture_buffer;  /* suitably aligned address */
+
+       pid_t capture_pid;      /* process id which uses capture */
+       pid_t playback_pid;     /* process id which uses capture */
+       int running;            /* running status */
+
+       int last_external_sample_rate;  /* samplerate mystic ... */
+       int last_internal_sample_rate;
+       int system_sample_rate;
+
+       char *channel_map;      /* channel map for DS and Quadspeed */
+
+       int dev;                /* Hardware vars... */
+       int irq;
+       unsigned long port;
+       void __iomem *iobase;
+
+       int irq_count;          /* for debug */
+
+       snd_card_t *card;       /* one card */
+       snd_pcm_t *pcm;         /* has one pcm */
+       snd_hwdep_t *hwdep;     /* and a hwdep for additional ioctl */
+       struct pci_dev *pci;    /* and an pci info */
+
+       /* Mixer vars */
+       snd_kcontrol_t *playback_mixer_ctls[HDSPM_MAX_CHANNELS];        /* fast alsa mixer */
+       snd_kcontrol_t *input_mixer_ctls[HDSPM_MAX_CHANNELS];   /* but input to much, so not used */
+       hdspm_mixer_t *mixer;   /* full mixer accessable over mixer ioctl or hwdep-device */
+
+};
+
+/* These tables map the ALSA channels 1..N to the channels that we
+   need to use in order to find the relevant channel buffer. RME
+   refer to this kind of mapping as between "the ADAT channel and
+   the DMA channel." We index it using the logical audio channel,
+   and the value is the DMA channel (i.e. channel buffer number)
+   where the data for that channel can be read/written from/to.
+*/
+
+static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
+   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,
+   32, 33, 34, 35, 36, 37, 38, 39,
+   40, 41, 42, 43, 44, 45, 46, 47,
+   48, 49, 50, 51, 52, 53, 54, 55,
+   56, 57, 58, 59, 60, 61, 62, 63
+};
+
+static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = {
+  0, 2, 4, 6, 8, 10, 12, 14,
+  16, 18, 20, 22, 24, 26, 28, 30,
+  32, 34, 36, 38, 40, 42, 44, 46,
+  48, 50, 52, 54, 56, 58, 60, 62,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
+  0,   4,  8, 12, 16, 20, 24,  28,  
+  32, 36, 40, 44, 48, 52, 56,  60
+  -1, -1, -1, -1, -1, -1, -1, -1,  
+  -1, -1, -1, -1, -1, -1, -1, -1,  
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+
+static struct pci_device_id snd_hdspm_ids[] = {
+       {
+        .vendor = PCI_VENDOR_ID_XILINX,
+        .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
+        .subvendor = PCI_ANY_ID,
+        .subdevice = PCI_ANY_ID,
+        .class = 0,
+        .class_mask = 0,
+        .driver_data = 0},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
+
+/* prototypes */
+static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
+                                                  hdspm_t * hdspm);
+static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
+                                         hdspm_t * hdspm);
+
+static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm);
+static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm);
+static int hdspm_autosync_ref(hdspm_t * hdspm);
+static int snd_hdspm_set_defaults(hdspm_t * hdspm);
+static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
+                            unsigned int reg, int channels);
+
+/* Write/read to/from HDSPM with Adresses in Bytes
+   not words but only 32Bit writes are allowed */
+
+static inline void hdspm_write(hdspm_t * hdspm, unsigned int reg,
+                              unsigned int val)
+{
+       writel(val, hdspm->iobase + reg);
+}
+
+static inline unsigned int hdspm_read(hdspm_t * hdspm, unsigned int reg)
+{
+       return readl(hdspm->iobase + reg);
+}
+
+/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader 
+   mixer is write only on hardware so we have to cache him for read 
+   each fader is a u32, but uses only the first 16 bit */
+
+static inline int hdspm_read_in_gain(hdspm_t * hdspm, unsigned int chan,
+                                    unsigned int in)
+{
+       if (chan > HDSPM_MIXER_CHANNELS || in > HDSPM_MIXER_CHANNELS)
+               return 0;
+
+       return hdspm->mixer->ch[chan].in[in];
+}
+
+static inline int hdspm_read_pb_gain(hdspm_t * hdspm, unsigned int chan,
+                                    unsigned int pb)
+{
+       if (chan > HDSPM_MIXER_CHANNELS || pb > HDSPM_MIXER_CHANNELS)
+               return 0;
+       return hdspm->mixer->ch[chan].pb[pb];
+}
+
+static inline int hdspm_write_in_gain(hdspm_t * hdspm, unsigned int chan,
+                                     unsigned int in, unsigned short data)
+{
+       if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
+               return -1;
+
+       hdspm_write(hdspm,
+                   HDSPM_MADI_mixerBase +
+                   ((in + 128 * chan) * sizeof(u32)),
+                   (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
+       return 0;
+}
+
+static inline int hdspm_write_pb_gain(hdspm_t * hdspm, unsigned int chan,
+                                     unsigned int pb, unsigned short data)
+{
+       if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
+               return -1;
+
+       hdspm_write(hdspm,
+                   HDSPM_MADI_mixerBase +
+                   ((64 + pb + 128 * chan) * sizeof(u32)),
+                   (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
+       return 0;
+}
+
+
+/* enable DMA for specific channels, now available for DSP-MADI */
+static inline void snd_hdspm_enable_in(hdspm_t * hdspm, int i, int v)
+{
+       hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
+}
+
+static inline void snd_hdspm_enable_out(hdspm_t * hdspm, int i, int v)
+{
+       hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
+}
+
+/* check if same process is writing and reading */
+static inline int snd_hdspm_use_is_exclusive(hdspm_t * hdspm)
+{
+       unsigned long flags;
+       int ret = 1;
+
+       spin_lock_irqsave(&hdspm->lock, flags);
+       if ((hdspm->playback_pid != hdspm->capture_pid) &&
+           (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&hdspm->lock, flags);
+       return ret;
+}
+
+/* check for external sample rate */
+static inline int hdspm_external_sample_rate(hdspm_t * hdspm)
+{
+       unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+       unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
+       unsigned int rate_bits;
+       int rate = 0;
+
+       /* if wordclock has synced freq and wordclock is valid */
+       if ((status2 & HDSPM_wcLock) != 0 &&
+           (status & HDSPM_SelSyncRef0) == 0) {
+
+               rate_bits = status2 & HDSPM_wcFreqMask;
+
+               switch (rate_bits) {
+               case HDSPM_wcFreq32:
+                       rate = 32000;
+                       break;
+               case HDSPM_wcFreq44_1:
+                       rate = 44100;
+                       break;
+               case HDSPM_wcFreq48:
+                       rate = 48000;
+                       break;
+               case HDSPM_wcFreq64:
+                       rate = 64000;
+                       break;
+               case HDSPM_wcFreq88_2:
+                       rate = 88200;
+                       break;
+               case HDSPM_wcFreq96:
+                       rate = 96000;
+                       break;
+                       /* Quadspeed Bit missing ???? */
+               default:
+                       rate = 0;
+                       break;
+               }
+       }
+
+       /* if rate detected and Syncref is Word than have it, word has priority to MADI */
+       if (rate != 0
+           && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
+               return rate;
+
+       /* maby a madi input (which is taken if sel sync is madi) */
+       if (status & HDSPM_madiLock) {
+               rate_bits = status & HDSPM_madiFreqMask;
+
+               switch (rate_bits) {
+               case HDSPM_madiFreq32:
+                       rate = 32000;
+                       break;
+               case HDSPM_madiFreq44_1:
+                       rate = 44100;
+                       break;
+               case HDSPM_madiFreq48:
+                       rate = 48000;
+                       break;
+               case HDSPM_madiFreq64:
+                       rate = 64000;
+                       break;
+               case HDSPM_madiFreq88_2:
+                       rate = 88200;
+                       break;
+               case HDSPM_madiFreq96:
+                       rate = 96000;
+                       break;
+               case HDSPM_madiFreq128:
+                       rate = 128000;
+                       break;
+               case HDSPM_madiFreq176_4:
+                       rate = 176400;
+                       break;
+               case HDSPM_madiFreq192:
+                       rate = 192000;
+                       break;
+               default:
+                       rate = 0;
+                       break;
+               }
+       }
+       return rate;
+}
+
+/* Latency function */
+static inline void hdspm_compute_period_size(hdspm_t * hdspm)
+{
+       hdspm->period_bytes =
+           1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
+}
+
+static snd_pcm_uframes_t hdspm_hw_pointer(hdspm_t * hdspm)
+{
+       int position;
+
+       position = hdspm_read(hdspm, HDSPM_statusRegister);
+
+       if (!hdspm->precise_ptr) {
+               return (position & HDSPM_BufferID) ? (hdspm->period_bytes /
+                                                     4) : 0;
+       }
+
+       /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)
+          i have experimented that it is at most 64 Byte to much for playing 
+          so substraction of 64 byte should be ok for ALSA, but use it only
+          for application where you know what you do since if you come to
+          near with record pointer it can be a disaster */
+
+       position &= HDSPM_BufferPositionMask;
+       position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
+
+       return position;
+}
+
+
+static inline void hdspm_start_audio(hdspm_t * s)
+{
+       s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
+       hdspm_write(s, HDSPM_controlRegister, s->control_register);
+}
+
+static inline void hdspm_stop_audio(hdspm_t * s)
+{
+       s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
+       hdspm_write(s, HDSPM_controlRegister, s->control_register);
+}
+
+/* should I silence all or only opened ones ? doit all for first even is 4MB*/
+static inline void hdspm_silence_playback(hdspm_t * hdspm)
+{
+       int i;
+       int n = hdspm->period_bytes;
+       void *buf = hdspm->playback_buffer;
+
+       snd_assert(buf != NULL, return);
+
+       for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
+               memset(buf, 0, n);
+               buf += HDSPM_CHANNEL_BUFFER_BYTES;
+       }
+}
+
+static int hdspm_set_interrupt_interval(hdspm_t * s, unsigned int frames)
+{
+       int n;
+
+       spin_lock_irq(&s->lock);
+
+       frames >>= 7;
+       n = 0;
+       while (frames) {
+               n++;
+               frames >>= 1;
+       }
+       s->control_register &= ~HDSPM_LatencyMask;
+       s->control_register |= hdspm_encode_latency(n);
+
+       hdspm_write(s, HDSPM_controlRegister, s->control_register);
+
+       hdspm_compute_period_size(s);
+
+       spin_unlock_irq(&s->lock);
+
+       return 0;
+}
+
+
+/* dummy set rate lets see what happens */
+static int hdspm_set_rate(hdspm_t * hdspm, int rate, int called_internally)
+{
+       int reject_if_open = 0;
+       int current_rate;
+       int rate_bits;
+       int not_set = 0;
+
+       /* ASSUMPTION: hdspm->lock is either set, or there is no need for
+          it (e.g. during module initialization).
+        */
+
+       if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
+
+               /* SLAVE --- */ 
+               if (called_internally) {
+
+                 /* request from ctl or card initialization 
+                    just make a warning an remember setting 
+                    for future master mode switching */
+    
+                       snd_printk
+                           (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");
+                       not_set = 1;
+               } else {
+
+                       /* hw_param request while in AutoSync mode */
+                       int external_freq =
+                           hdspm_external_sample_rate(hdspm);
+
+                       if ((hdspm_autosync_ref(hdspm) ==
+                            HDSPM_AUTOSYNC_FROM_NONE)) {
+
+                               snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");
+                               not_set = 1;
+
+                       } else if (rate != external_freq) {
+
+                               snd_printk
+                                   (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");
+                               not_set = 1;
+                       }
+               }
+       }
+
+       current_rate = hdspm->system_sample_rate;
+
+       /* Changing between Singe, Double and Quad speed is not
+          allowed if any substreams are open. This is because such a change
+          causes a shift in the location of the DMA buffers and a reduction
+          in the number of available buffers.
+
+          Note that a similar but essentially insoluble problem exists for
+          externally-driven rate changes. All we can do is to flag rate
+          changes in the read/write routines.  
+        */
+
+       switch (rate) {
+       case 32000:
+               if (current_rate > 48000) {
+                       reject_if_open = 1;
+               }
+               rate_bits = HDSPM_Frequency32KHz;
+               break;
+       case 44100:
+               if (current_rate > 48000) {
+                       reject_if_open = 1;
+               }
+               rate_bits = HDSPM_Frequency44_1KHz;
+               break;
+       case 48000:
+               if (current_rate > 48000) {
+                       reject_if_open = 1;
+               }
+               rate_bits = HDSPM_Frequency48KHz;
+               break;
+       case 64000:
+               if (current_rate <= 48000) {
+                       reject_if_open = 1;
+               }
+               rate_bits = HDSPM_Frequency64KHz;
+               break;
+       case 88200:
+               if (current_rate <= 48000) {
+                       reject_if_open = 1;
+               }
+               rate_bits = HDSPM_Frequency88_2KHz;
+               break;
+       case 96000:
+               if (current_rate <= 48000) {
+                       reject_if_open = 1;
+               }
+               rate_bits = HDSPM_Frequency96KHz;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (reject_if_open
+           && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
+               snd_printk
+                   (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
+                    hdspm->capture_pid, hdspm->playback_pid);
+               return -EBUSY;
+       }
+
+       hdspm->control_register &= ~HDSPM_FrequencyMask;
+       hdspm->control_register |= rate_bits;
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+       if (rate > 64000)
+               hdspm->channel_map = channel_map_madi_qs;
+       else if (rate > 48000)
+               hdspm->channel_map = channel_map_madi_ds;
+       else 
+               hdspm->channel_map = channel_map_madi_ss;
+
+       hdspm->system_sample_rate = rate;
+
+       if (not_set != 0)
+               return -1;
+
+       return 0;
+}
+
+/* mainly for init to 0 on load */
+static void all_in_all_mixer(hdspm_t * hdspm, int sgain)
+{
+       int i, j;
+       unsigned int gain =
+           (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;
+
+       for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
+               for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
+                       hdspm_write_in_gain(hdspm, i, j, gain);
+                       hdspm_write_pb_gain(hdspm, i, j, gain);
+               }
+}
+
+/*----------------------------------------------------------------------------
+   MIDI
+  ----------------------------------------------------------------------------*/
+
+static inline unsigned char snd_hdspm_midi_read_byte (hdspm_t *hdspm, int id)
+{
+       /* the hardware already does the relevant bit-mask with 0xff */
+       if (id)
+               return hdspm_read(hdspm, HDSPM_midiDataIn1);
+       else
+               return hdspm_read(hdspm, HDSPM_midiDataIn0);
+}
+
+static inline void snd_hdspm_midi_write_byte (hdspm_t *hdspm, int id, int val)
+{
+       /* the hardware already does the relevant bit-mask with 0xff */
+       if (id)
+               return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
+       else
+               return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
+}
+
+static inline int snd_hdspm_midi_input_available (hdspm_t *hdspm, int id)
+{
+       if (id)
+               return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
+       else
+               return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
+}
+
+static inline int snd_hdspm_midi_output_possible (hdspm_t *hdspm, int id)
+{
+       int fifo_bytes_used;
+
+       if (id)
+               fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;
+       else
+               fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;
+
+       if (fifo_bytes_used < 128)
+               return  128 - fifo_bytes_used;
+       else
+               return 0;
+}
+
+static inline void snd_hdspm_flush_midi_input (hdspm_t *hdspm, int id)
+{
+       while (snd_hdspm_midi_input_available (hdspm, id))
+               snd_hdspm_midi_read_byte (hdspm, id);
+}
+
+static int snd_hdspm_midi_output_write (hdspm_midi_t *hmidi)
+{
+       unsigned long flags;
+       int n_pending;
+       int to_write;
+       int i;
+       unsigned char buf[128];
+
+       /* Output is not interrupt driven */
+               
+       spin_lock_irqsave (&hmidi->lock, flags);
+       if (hmidi->output) {
+               if (!snd_rawmidi_transmit_empty (hmidi->output)) {
+                       if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {
+                               if (n_pending > (int)sizeof (buf))
+                                       n_pending = sizeof (buf);
+                               
+                               if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
+                                       for (i = 0; i < to_write; ++i) 
+                                               snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);
+                               }
+                       }
+               }
+       }
+       spin_unlock_irqrestore (&hmidi->lock, flags);
+       return 0;
+}
+
+static int snd_hdspm_midi_input_read (hdspm_midi_t *hmidi)
+{
+       unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
+       unsigned long flags;
+       int n_pending;
+       int i;
+
+       spin_lock_irqsave (&hmidi->lock, flags);
+       if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) {
+               if (hmidi->input) {
+                       if (n_pending > (int)sizeof (buf)) {
+                               n_pending = sizeof (buf);
+                       }
+                       for (i = 0; i < n_pending; ++i) {
+                               buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
+                       }
+                       if (n_pending) {
+                               snd_rawmidi_receive (hmidi->input, buf, n_pending);
+                       }
+               } else {
+                       /* flush the MIDI input FIFO */
+                       while (n_pending--) {
+                               snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
+                       }
+               }
+       }
+       hmidi->pending = 0;
+       if (hmidi->id) {
+               hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
+       } else {
+               hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
+       }
+       hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register);
+       spin_unlock_irqrestore (&hmidi->lock, flags);
+       return snd_hdspm_midi_output_write (hmidi);
+}
+
+static void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+       hdspm_t *hdspm;
+       hdspm_midi_t *hmidi;
+       unsigned long flags;
+       u32 ie;
+
+       hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+       hdspm = hmidi->hdspm;
+       ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
+       spin_lock_irqsave (&hdspm->lock, flags);
+       if (up) {
+               if (!(hdspm->control_register & ie)) {
+                       snd_hdspm_flush_midi_input (hdspm, hmidi->id);
+                       hdspm->control_register |= ie;
+               }
+       } else {
+               hdspm->control_register &= ~ie;
+       }
+
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+       spin_unlock_irqrestore (&hdspm->lock, flags);
+}
+
+static void snd_hdspm_midi_output_timer(unsigned long data)
+{
+       hdspm_midi_t *hmidi = (hdspm_midi_t *) data;
+       unsigned long flags;
+       
+       snd_hdspm_midi_output_write(hmidi);
+       spin_lock_irqsave (&hmidi->lock, flags);
+
+       /* this does not bump hmidi->istimer, because the
+          kernel automatically removed the timer when it
+          expired, and we are now adding it back, thus
+          leaving istimer wherever it was set before.  
+       */
+
+       if (hmidi->istimer) {
+               hmidi->timer.expires = 1 + jiffies;
+               add_timer(&hmidi->timer);
+       }
+
+       spin_unlock_irqrestore (&hmidi->lock, flags);
+}
+
+static void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+       hdspm_midi_t *hmidi;
+       unsigned long flags;
+
+       hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+       spin_lock_irqsave (&hmidi->lock, flags);
+       if (up) {
+               if (!hmidi->istimer) {
+                       init_timer(&hmidi->timer);
+                       hmidi->timer.function = snd_hdspm_midi_output_timer;
+                       hmidi->timer.data = (unsigned long) hmidi;
+                       hmidi->timer.expires = 1 + jiffies;
+                       add_timer(&hmidi->timer);
+                       hmidi->istimer++;
+               }
+       } else {
+               if (hmidi->istimer && --hmidi->istimer <= 0) {
+                       del_timer (&hmidi->timer);
+               }
+       }
+       spin_unlock_irqrestore (&hmidi->lock, flags);
+       if (up)
+               snd_hdspm_midi_output_write(hmidi);
+}
+
+static int snd_hdspm_midi_input_open(snd_rawmidi_substream_t * substream)
+{
+       hdspm_midi_t *hmidi;
+
+       hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+       spin_lock_irq (&hmidi->lock);
+       snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
+       hmidi->input = substream;
+       spin_unlock_irq (&hmidi->lock);
+
+       return 0;
+}
+
+static int snd_hdspm_midi_output_open(snd_rawmidi_substream_t * substream)
+{
+       hdspm_midi_t *hmidi;
+
+       hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+       spin_lock_irq (&hmidi->lock);
+       hmidi->output = substream;
+       spin_unlock_irq (&hmidi->lock);
+
+       return 0;
+}
+
+static int snd_hdspm_midi_input_close(snd_rawmidi_substream_t * substream)
+{
+       hdspm_midi_t *hmidi;
+
+       snd_hdspm_midi_input_trigger (substream, 0);
+
+       hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+       spin_lock_irq (&hmidi->lock);
+       hmidi->input = NULL;
+       spin_unlock_irq (&hmidi->lock);
+
+       return 0;
+}
+
+static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream)
+{
+       hdspm_midi_t *hmidi;
+
+       snd_hdspm_midi_output_trigger (substream, 0);
+
+       hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+       spin_lock_irq (&hmidi->lock);
+       hmidi->output = NULL;
+       spin_unlock_irq (&hmidi->lock);
+
+       return 0;
+}
+
+snd_rawmidi_ops_t snd_hdspm_midi_output =
+{
+       .open =         snd_hdspm_midi_output_open,
+       .close =        snd_hdspm_midi_output_close,
+       .trigger =      snd_hdspm_midi_output_trigger,
+};
+
+snd_rawmidi_ops_t snd_hdspm_midi_input =
+{
+       .open =         snd_hdspm_midi_input_open,
+       .close =        snd_hdspm_midi_input_close,
+       .trigger =      snd_hdspm_midi_input_trigger,
+};
+
+static int __devinit snd_hdspm_create_midi (snd_card_t *card, hdspm_t *hdspm, int id)
+{
+       int err;
+       char buf[32];
+
+       hdspm->midi[id].id = id;
+       hdspm->midi[id].rmidi = NULL;
+       hdspm->midi[id].input = NULL;
+       hdspm->midi[id].output = NULL;
+       hdspm->midi[id].hdspm = hdspm;
+       hdspm->midi[id].istimer = 0;
+       hdspm->midi[id].pending = 0;
+       spin_lock_init (&hdspm->midi[id].lock);
+
+       sprintf (buf, "%s MIDI %d", card->shortname, id+1);
+       if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0)
+               return err;
+
+       sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
+       hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
+
+       snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output);
+       snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input);
+
+       hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
+               SNDRV_RAWMIDI_INFO_INPUT |
+               SNDRV_RAWMIDI_INFO_DUPLEX;
+
+       return 0;
+}
+
+
+static void hdspm_midi_tasklet(unsigned long arg)
+{
+       hdspm_t *hdspm = (hdspm_t *)arg;
+       
+       if (hdspm->midi[0].pending)
+               snd_hdspm_midi_input_read (&hdspm->midi[0]);
+       if (hdspm->midi[1].pending)
+               snd_hdspm_midi_input_read (&hdspm->midi[1]);
+} 
+
+
+/*-----------------------------------------------------------------------------
+  Status Interface
+  ----------------------------------------------------------------------------*/
+
+/* get the system sample rate which is set */
+
+#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+  .info = snd_hdspm_info_system_sample_rate, \
+  .get = snd_hdspm_get_system_sample_rate \
+}
+
+static int snd_hdspm_info_system_sample_rate(snd_kcontrol_t * kcontrol,
+                                            snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       return 0;
+}
+
+static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol,
+                                           snd_ctl_elem_value_t *
+                                           ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
+       return 0;
+}
+
+#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+  .info = snd_hdspm_info_autosync_sample_rate, \
+  .get = snd_hdspm_get_autosync_sample_rate \
+}
+
+static int snd_hdspm_info_autosync_sample_rate(snd_kcontrol_t * kcontrol,
+                                              snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[] = { "32000", "44100", "48000",
+               "64000", "88200", "96000",
+               "128000", "176400", "192000",
+               "None"
+       };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 10;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol,
+                                             snd_ctl_elem_value_t *
+                                             ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       switch (hdspm_external_sample_rate(hdspm)) {
+       case 32000:
+               ucontrol->value.enumerated.item[0] = 0;
+               break;
+       case 44100:
+               ucontrol->value.enumerated.item[0] = 1;
+               break;
+       case 48000:
+               ucontrol->value.enumerated.item[0] = 2;
+               break;
+       case 64000:
+               ucontrol->value.enumerated.item[0] = 3;
+               break;
+       case 88200:
+               ucontrol->value.enumerated.item[0] = 4;
+               break;
+       case 96000:
+               ucontrol->value.enumerated.item[0] = 5;
+               break;
+       case 128000:
+               ucontrol->value.enumerated.item[0] = 6;
+               break;
+       case 176400:
+               ucontrol->value.enumerated.item[0] = 7;
+               break;
+       case 192000:
+               ucontrol->value.enumerated.item[0] = 8;
+               break;
+
+       default:
+               ucontrol->value.enumerated.item[0] = 9;
+       }
+       return 0;
+}
+
+#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+  .info = snd_hdspm_info_system_clock_mode, \
+  .get = snd_hdspm_get_system_clock_mode, \
+}
+
+
+
+static int hdspm_system_clock_mode(hdspm_t * hdspm)
+{
+        /* Always reflect the hardware info, rme is never wrong !!!! */
+
+       if (hdspm->control_register & HDSPM_ClockModeMaster)
+               return 0;
+       return 1;
+}
+
+static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol,
+                                           snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[] = { "Master", "Slave" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol,
+                                          snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] =
+           hdspm_system_clock_mode(hdspm);
+       return 0;
+}
+
+#define HDSPM_CLOCK_SOURCE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_clock_source, \
+  .get = snd_hdspm_get_clock_source, \
+  .put = snd_hdspm_put_clock_source \
+}
+
+static int hdspm_clock_source(hdspm_t * hdspm)
+{
+       if (hdspm->control_register & HDSPM_ClockModeMaster) {
+               switch (hdspm->system_sample_rate) {
+               case 32000:
+                       return 1;
+               case 44100:
+                       return 2;
+               case 48000:
+                       return 3;
+               case 64000:
+                       return 4;
+               case 88200:
+                       return 5;
+               case 96000:
+                       return 6;
+               case 128000:
+                       return 7;
+               case 176400:
+                       return 8;
+               case 192000:
+                       return 9;
+               default:
+                       return 3;
+               }
+       } else {
+               return 0;
+       }
+}
+
+static int hdspm_set_clock_source(hdspm_t * hdspm, int mode)
+{
+       int rate;
+       switch (mode) {
+
+       case HDSPM_CLOCK_SOURCE_AUTOSYNC:
+               if (hdspm_external_sample_rate(hdspm) != 0) {
+                       hdspm->control_register &= ~HDSPM_ClockModeMaster;
+                       hdspm_write(hdspm, HDSPM_controlRegister,
+                                   hdspm->control_register);
+                       return 0;
+               }
+               return -1;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
+               rate = 32000;
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
+               rate = 44100;
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
+               rate = 48000;
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
+               rate = 64000;
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
+               rate = 88200;
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
+               rate = 96000;
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
+               rate = 128000;
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
+               rate = 176400;
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
+               rate = 192000;
+               break;
+
+       default:
+               rate = 44100;
+       }
+       hdspm->control_register |= HDSPM_ClockModeMaster;
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+       hdspm_set_rate(hdspm, rate, 1);
+       return 0;
+}
+
+static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol,
+                                      snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[] = { "AutoSync",
+               "Internal 32.0 kHz", "Internal 44.1 kHz",
+                   "Internal 48.0 kHz",
+               "Internal 64.0 kHz", "Internal 88.2 kHz",
+                   "Internal 96.0 kHz",
+               "Internal 128.0 kHz", "Internal 176.4 kHz",
+                   "Internal 192.0 kHz"
+       };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 10;
+
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+
+       return 0;
+}
+
+static int snd_hdspm_get_clock_source(snd_kcontrol_t * kcontrol,
+                                     snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
+       return 0;
+}
+
+static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol,
+                                     snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       int val;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+       val = ucontrol->value.enumerated.item[0];
+       if (val < 0)
+               val = 0;
+       if (val > 6)
+               val = 6;
+       spin_lock_irq(&hdspm->lock);
+       if (val != hdspm_clock_source(hdspm))
+               change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
+       else
+               change = 0;
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
+
+#define HDSPM_PREF_SYNC_REF(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_pref_sync_ref, \
+  .get = snd_hdspm_get_pref_sync_ref, \
+  .put = snd_hdspm_put_pref_sync_ref \
+}
+
+static int hdspm_pref_sync_ref(hdspm_t * hdspm)
+{
+       /* Notice that this looks at the requested sync source,
+          not the one actually in use.
+        */
+       switch (hdspm->control_register & HDSPM_SyncRefMask) {
+       case HDSPM_SyncRef_Word:
+               return HDSPM_SYNC_FROM_WORD;
+       case HDSPM_SyncRef_MADI:
+               return HDSPM_SYNC_FROM_MADI;
+       }
+
+       return HDSPM_SYNC_FROM_WORD;
+}
+
+static int hdspm_set_pref_sync_ref(hdspm_t * hdspm, int pref)
+{
+       hdspm->control_register &= ~HDSPM_SyncRefMask;
+
+       switch (pref) {
+       case HDSPM_SYNC_FROM_MADI:
+               hdspm->control_register |= HDSPM_SyncRef_MADI;
+               break;
+       case HDSPM_SYNC_FROM_WORD:
+               hdspm->control_register |= HDSPM_SyncRef_Word;
+               break;
+       default:
+               return -1;
+       }
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+       return 0;
+}
+
+static int snd_hdspm_info_pref_sync_ref(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[] = { "Word", "MADI" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+
+       uinfo->value.enumerated.items = 2;
+
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_hdspm_get_pref_sync_ref(snd_kcontrol_t * kcontrol,
+                                      snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
+       return 0;
+}
+
+static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol,
+                                      snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change, max;
+       unsigned int val;
+
+       max = 2;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+
+       val = ucontrol->value.enumerated.item[0] % max;
+
+       spin_lock_irq(&hdspm->lock);
+       change = (int) val != hdspm_pref_sync_ref(hdspm);
+       hdspm_set_pref_sync_ref(hdspm, val);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
+
+#define HDSPM_AUTOSYNC_REF(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+  .info = snd_hdspm_info_autosync_ref, \
+  .get = snd_hdspm_get_autosync_ref, \
+}
+
+static int hdspm_autosync_ref(hdspm_t * hdspm)
+{
+       /* This looks at the autosync selected sync reference */
+       unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+
+       switch (status2 & HDSPM_SelSyncRefMask) {
+
+       case HDSPM_SelSyncRef_WORD:
+               return HDSPM_AUTOSYNC_FROM_WORD;
+
+       case HDSPM_SelSyncRef_MADI:
+               return HDSPM_AUTOSYNC_FROM_MADI;
+
+       case HDSPM_SelSyncRef_NVALID:
+               return HDSPM_AUTOSYNC_FROM_NONE;
+
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
+static int snd_hdspm_info_autosync_ref(snd_kcontrol_t * kcontrol,
+                                      snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[] = { "WordClock", "MADI", "None" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 3;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol,
+                                     snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
+       return 0;
+}
+
+#define HDSPM_LINE_OUT(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_line_out, \
+  .get = snd_hdspm_get_line_out, \
+  .put = snd_hdspm_put_line_out \
+}
+
+static int hdspm_line_out(hdspm_t * hdspm)
+{
+       return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
+}
+
+
+static int hdspm_set_line_output(hdspm_t * hdspm, int out)
+{
+       if (out)
+               hdspm->control_register |= HDSPM_LineOut;
+       else
+               hdspm->control_register &= ~HDSPM_LineOut;
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+       return 0;
+}
+
+static int snd_hdspm_info_line_out(snd_kcontrol_t * kcontrol,
+                                  snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_hdspm_get_line_out(snd_kcontrol_t * kcontrol,
+                                 snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       spin_lock_irq(&hdspm->lock);
+       ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
+       spin_unlock_irq(&hdspm->lock);
+       return 0;
+}
+
+static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol,
+                                 snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       unsigned int val;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+       val = ucontrol->value.integer.value[0] & 1;
+       spin_lock_irq(&hdspm->lock);
+       change = (int) val != hdspm_line_out(hdspm);
+       hdspm_set_line_output(hdspm, val);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
+
+#define HDSPM_TX_64(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_tx_64, \
+  .get = snd_hdspm_get_tx_64, \
+  .put = snd_hdspm_put_tx_64 \
+}
+
+static int hdspm_tx_64(hdspm_t * hdspm)
+{
+       return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
+}
+
+static int hdspm_set_tx_64(hdspm_t * hdspm, int out)
+{
+       if (out)
+               hdspm->control_register |= HDSPM_TX_64ch;
+       else
+               hdspm->control_register &= ~HDSPM_TX_64ch;
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+       return 0;
+}
+
+static int snd_hdspm_info_tx_64(snd_kcontrol_t * kcontrol,
+                               snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_hdspm_get_tx_64(snd_kcontrol_t * kcontrol,
+                              snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       spin_lock_irq(&hdspm->lock);
+       ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
+       spin_unlock_irq(&hdspm->lock);
+       return 0;
+}
+
+static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol,
+                              snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       unsigned int val;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+       val = ucontrol->value.integer.value[0] & 1;
+       spin_lock_irq(&hdspm->lock);
+       change = (int) val != hdspm_tx_64(hdspm);
+       hdspm_set_tx_64(hdspm, val);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
+
+#define HDSPM_C_TMS(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_c_tms, \
+  .get = snd_hdspm_get_c_tms, \
+  .put = snd_hdspm_put_c_tms \
+}
+
+static int hdspm_c_tms(hdspm_t * hdspm)
+{
+       return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
+}
+
+static int hdspm_set_c_tms(hdspm_t * hdspm, int out)
+{
+       if (out)
+               hdspm->control_register |= HDSPM_clr_tms;
+       else
+               hdspm->control_register &= ~HDSPM_clr_tms;
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+       return 0;
+}
+
+static int snd_hdspm_info_c_tms(snd_kcontrol_t * kcontrol,
+                               snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_hdspm_get_c_tms(snd_kcontrol_t * kcontrol,
+                              snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       spin_lock_irq(&hdspm->lock);
+       ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
+       spin_unlock_irq(&hdspm->lock);
+       return 0;
+}
+
+static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol,
+                              snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       unsigned int val;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+       val = ucontrol->value.integer.value[0] & 1;
+       spin_lock_irq(&hdspm->lock);
+       change = (int) val != hdspm_c_tms(hdspm);
+       hdspm_set_c_tms(hdspm, val);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
+
+#define HDSPM_SAFE_MODE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_safe_mode, \
+  .get = snd_hdspm_get_safe_mode, \
+  .put = snd_hdspm_put_safe_mode \
+}
+
+static int hdspm_safe_mode(hdspm_t * hdspm)
+{
+       return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
+}
+
+static int hdspm_set_safe_mode(hdspm_t * hdspm, int out)
+{
+       if (out)
+               hdspm->control_register |= HDSPM_AutoInp;
+       else
+               hdspm->control_register &= ~HDSPM_AutoInp;
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+       return 0;
+}
+
+static int snd_hdspm_info_safe_mode(snd_kcontrol_t * kcontrol,
+                                   snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_hdspm_get_safe_mode(snd_kcontrol_t * kcontrol,
+                                  snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       spin_lock_irq(&hdspm->lock);
+       ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
+       spin_unlock_irq(&hdspm->lock);
+       return 0;
+}
+
+static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol,
+                                  snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       unsigned int val;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+       val = ucontrol->value.integer.value[0] & 1;
+       spin_lock_irq(&hdspm->lock);
+       change = (int) val != hdspm_safe_mode(hdspm);
+       hdspm_set_safe_mode(hdspm, val);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
+
+#define HDSPM_INPUT_SELECT(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_input_select, \
+  .get = snd_hdspm_get_input_select, \
+  .put = snd_hdspm_put_input_select \
+}
+
+static int hdspm_input_select(hdspm_t * hdspm)
+{
+       return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
+}
+
+static int hdspm_set_input_select(hdspm_t * hdspm, int out)
+{
+       if (out)
+               hdspm->control_register |= HDSPM_InputSelect0;
+       else
+               hdspm->control_register &= ~HDSPM_InputSelect0;
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+       return 0;
+}
+
+static int snd_hdspm_info_input_select(snd_kcontrol_t * kcontrol,
+                                      snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[] = { "optical", "coaxial" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+
+       return 0;
+}
+
+static int snd_hdspm_get_input_select(snd_kcontrol_t * kcontrol,
+                                     snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       spin_lock_irq(&hdspm->lock);
+       ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
+       spin_unlock_irq(&hdspm->lock);
+       return 0;
+}
+
+static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol,
+                                     snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       unsigned int val;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+       val = ucontrol->value.integer.value[0] & 1;
+       spin_lock_irq(&hdspm->lock);
+       change = (int) val != hdspm_input_select(hdspm);
+       hdspm_set_input_select(hdspm, val);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
+
+/*           Simple Mixer
+  deprecated since to much faders ???
+  MIXER interface says output (source, destination, value)
+   where source > MAX_channels are playback channels 
+   on MADICARD 
+  - playback mixer matrix: [channelout+64] [output] [value]
+  - input(thru) mixer matrix: [channelin] [output] [value]
+  (better do 2 kontrols for seperation ?)
+*/
+
+#define HDSPM_MIXER(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_mixer, \
+  .get = snd_hdspm_get_mixer, \
+  .put = snd_hdspm_put_mixer \
+}
+
+static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol,
+                               snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 3;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 65535;
+       uinfo->value.integer.step = 1;
+       return 0;
+}
+
+static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol,
+                              snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int source;
+       int destination;
+
+       source = ucontrol->value.integer.value[0];
+       if (source < 0)
+               source = 0;
+       else if (source >= 2 * HDSPM_MAX_CHANNELS)
+               source = 2 * HDSPM_MAX_CHANNELS - 1;
+
+       destination = ucontrol->value.integer.value[1];
+       if (destination < 0)
+               destination = 0;
+       else if (destination >= HDSPM_MAX_CHANNELS)
+               destination = HDSPM_MAX_CHANNELS - 1;
+
+       spin_lock_irq(&hdspm->lock);
+       if (source >= HDSPM_MAX_CHANNELS)
+               ucontrol->value.integer.value[2] =
+                   hdspm_read_pb_gain(hdspm, destination,
+                                      source - HDSPM_MAX_CHANNELS);
+       else
+               ucontrol->value.integer.value[2] =
+                   hdspm_read_in_gain(hdspm, destination, source);
+
+       spin_unlock_irq(&hdspm->lock);
+
+       return 0;
+}
+
+static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol,
+                              snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       int source;
+       int destination;
+       int gain;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+
+       source = ucontrol->value.integer.value[0];
+       destination = ucontrol->value.integer.value[1];
+
+       if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
+               return -1;
+       if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
+               return -1;
+
+       gain = ucontrol->value.integer.value[2];
+
+       spin_lock_irq(&hdspm->lock);
+
+       if (source >= HDSPM_MAX_CHANNELS)
+               change = gain != hdspm_read_pb_gain(hdspm, destination,
+                                                   source -
+                                                   HDSPM_MAX_CHANNELS);
+       else
+               change =
+                   gain != hdspm_read_in_gain(hdspm, destination, source);
+
+       if (change) {
+               if (source >= HDSPM_MAX_CHANNELS)
+                       hdspm_write_pb_gain(hdspm, destination,
+                                           source - HDSPM_MAX_CHANNELS,
+                                           gain);
+               else
+                       hdspm_write_in_gain(hdspm, destination, source,
+                                           gain);
+       }
+       spin_unlock_irq(&hdspm->lock);
+
+       return change;
+}
+
+/* The simple mixer control(s) provide gain control for the
+   basic 1:1 mappings of playback streams to output
+   streams. 
+*/
+
+#define HDSPM_PLAYBACK_MIXER \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
+                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_playback_mixer, \
+  .get = snd_hdspm_get_playback_mixer, \
+  .put = snd_hdspm_put_playback_mixer \
+}
+
+static int snd_hdspm_info_playback_mixer(snd_kcontrol_t * kcontrol,
+                                        snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 65536;
+       uinfo->value.integer.step = 1;
+       return 0;
+}
+
+static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int channel;
+       int mapped_channel;
+
+       channel = ucontrol->id.index - 1;
+
+       snd_assert(channel >= 0
+                  || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+       if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+               return -EINVAL;
+
+       spin_lock_irq(&hdspm->lock);
+       ucontrol->value.integer.value[0] =
+           hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
+       spin_unlock_irq(&hdspm->lock);
+
+       /*    snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",
+          ucontrol->id.index,        channel, mapped_channel,  ucontrol->value.integer.value[0]); 
+        */
+
+       return 0;
+}
+
+static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       int channel;
+       int mapped_channel;
+       int gain;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+
+       channel = ucontrol->id.index - 1;
+
+       snd_assert(channel >= 0
+                  || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+       if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+               return -EINVAL;
+
+       gain = ucontrol->value.integer.value[0];
+
+       spin_lock_irq(&hdspm->lock);
+       change =
+           gain != hdspm_read_pb_gain(hdspm, mapped_channel,
+                                      mapped_channel);
+       if (change)
+               hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
+                                   gain);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
+
+#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_sync_check, \
+  .get = snd_hdspm_get_wc_sync_check \
+}
+
+static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol,
+                                    snd_ctl_elem_info_t * uinfo)
+{
+       static char *texts[] = { "No Lock", "Lock", "Sync" };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 3;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item =
+                   uinfo->value.enumerated.items - 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int hdspm_wc_sync_check(hdspm_t * hdspm)
+{
+       int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+       if (status2 & HDSPM_wcLock) {
+               if (status2 & HDSPM_wcSync)
+                       return 2;
+               else
+                       return 1;
+       }
+       return 0;
+}
+
+static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol,
+                                      snd_ctl_elem_value_t * ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
+       return 0;
+}
+
+
+#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_sync_check, \
+  .get = snd_hdspm_get_madisync_sync_check \
+}
+
+static int hdspm_madisync_sync_check(hdspm_t * hdspm)
+{
+       int status = hdspm_read(hdspm, HDSPM_statusRegister);
+       if (status & HDSPM_madiLock) {
+               if (status & HDSPM_madiSync)
+                       return 2;
+               else
+                       return 1;
+       }
+       return 0;
+}
+
+static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol,
+                                            snd_ctl_elem_value_t *
+                                            ucontrol)
+{
+       hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] =
+           hdspm_madisync_sync_check(hdspm);
+       return 0;
+}
+
+
+
+
+static snd_kcontrol_new_t snd_hdspm_controls[] = {
+
+       HDSPM_MIXER("Mixer", 0),
+/* 'Sample Clock Source' complies with the alsa control naming scheme */
+       HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
+
+       HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
+       HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
+       HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
+       HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+/* 'External Rate' complies with the alsa control naming scheme */
+       HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
+       HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
+       HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
+       HDSPM_LINE_OUT("Line Out", 0),
+       HDSPM_TX_64("TX 64 channels mode", 0),
+       HDSPM_C_TMS("Clear Track Marker", 0),
+       HDSPM_SAFE_MODE("Safe Mode", 0),
+       HDSPM_INPUT_SELECT("Input Select", 0),
+};
+
+static snd_kcontrol_new_t snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
+
+
+static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm)
+{
+       int i;
+
+       for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
+               if (hdspm->system_sample_rate > 48000) {
+                       hdspm->playback_mixer_ctls[i]->vd[0].access =
+                           SNDRV_CTL_ELEM_ACCESS_INACTIVE |
+                           SNDRV_CTL_ELEM_ACCESS_READ |
+                           SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+               } else {
+                       hdspm->playback_mixer_ctls[i]->vd[0].access =
+                           SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                           SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+               }
+               snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
+                              SNDRV_CTL_EVENT_MASK_INFO,
+                              &hdspm->playback_mixer_ctls[i]->id);
+       }
+
+       return 0;
+}
+
+
+static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm)
+{
+       unsigned int idx, limit;
+       int err;
+       snd_kcontrol_t *kctl;
+
+       /* add control list first */
+
+       for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) {
+               if ((err =
+                    snd_ctl_add(card, kctl =
+                                snd_ctl_new1(&snd_hdspm_controls[idx],
+                                             hdspm))) < 0) {
+                       return err;
+               }
+       }
+
+       /* Channel playback mixer as default control 
+          Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer 
+          they are accesible via special IOCTL on hwdep
+          and the mixer 2dimensional mixer control */
+
+       snd_hdspm_playback_mixer.name = "Chn";
+       limit = HDSPM_MAX_CHANNELS;
+
+       /* The index values are one greater than the channel ID so that alsamixer
+          will display them correctly. We want to use the index for fast lookup
+          of the relevant channel, but if we use it at all, most ALSA software
+          does the wrong thing with it ...
+        */
+
+       for (idx = 0; idx < limit; ++idx) {
+               snd_hdspm_playback_mixer.index = idx + 1;
+               if ((err = snd_ctl_add(card,
+                                      kctl =
+                                      snd_ctl_new1
+                                      (&snd_hdspm_playback_mixer,
+                                       hdspm)))) {
+                       return err;
+               }
+               hdspm->playback_mixer_ctls[idx] = kctl;
+       }
+
+       return 0;
+}
+
+/*------------------------------------------------------------
+   /proc interface 
+ ------------------------------------------------------------*/
+
+static void
+snd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
+{
+       hdspm_t *hdspm = (hdspm_t *) entry->private_data;
+       unsigned int status;
+       unsigned int status2;
+       char *pref_sync_ref;
+       char *autosync_ref;
+       char *system_clock_mode;
+       char *clock_source;
+       char *insel;
+       char *syncref;
+       int x, x2;
+
+       status = hdspm_read(hdspm, HDSPM_statusRegister);
+       status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+
+       snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
+                   hdspm->card_name, hdspm->card->number + 1,
+                   hdspm->firmware_rev,
+                   (status2 & HDSPM_version0) |
+                   (status2 & HDSPM_version1) | (status2 &
+                                                 HDSPM_version2));
+
+       snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
+                   hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
+
+       snd_iprintf(buffer, "--- System ---\n");
+
+       snd_iprintf(buffer,
+                   "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
+                   status & HDSPM_audioIRQPending,
+                   (status & HDSPM_midi0IRQPending) ? 1 : 0,
+                   (status & HDSPM_midi1IRQPending) ? 1 : 0,
+                   hdspm->irq_count);
+       snd_iprintf(buffer,
+                   "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
+                   ((status & HDSPM_BufferID) ? 1 : 0),
+                   (status & HDSPM_BufferPositionMask),
+                   (status & HDSPM_BufferPositionMask) % (2 *
+                                                          (int)hdspm->
+                                                          period_bytes),
+                   ((status & HDSPM_BufferPositionMask) -
+                    64) % (2 * (int)hdspm->period_bytes),
+                   (long) hdspm_hw_pointer(hdspm) * 4);
+
+       snd_iprintf(buffer,
+                   "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
+                   hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
+                   hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
+                   hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
+                   hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
+       snd_iprintf(buffer,
+                   "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n",
+                   hdspm->control_register, hdspm->control2_register,
+                   status, status2);
+
+       snd_iprintf(buffer, "--- Settings ---\n");
+
+       x = 1 << (6 +
+                 hdspm_decode_latency(hdspm->
+                                      control_register &
+                                      HDSPM_LatencyMask));
+
+       snd_iprintf(buffer,
+                   "Size (Latency): %d samples (2 periods of %lu bytes)\n",
+                   x, (unsigned long) hdspm->period_bytes);
+
+       snd_iprintf(buffer, "Line out: %s,   Precise Pointer: %s\n",
+                   (hdspm->
+                    control_register & HDSPM_LineOut) ? "on " : "off",
+                   (hdspm->precise_ptr) ? "on" : "off");
+
+       switch (hdspm->control_register & HDSPM_InputMask) {
+       case HDSPM_InputOptical:
+               insel = "Optical";
+               break;
+       case HDSPM_InputCoaxial:
+               insel = "Coaxial";
+               break;
+       default:
+               insel = "Unkown";
+       }
+
+       switch (hdspm->control_register & HDSPM_SyncRefMask) {
+       case HDSPM_SyncRef_Word:
+               syncref = "WordClock";
+               break;
+       case HDSPM_SyncRef_MADI:
+               syncref = "MADI";
+               break;
+       default:
+               syncref = "Unkown";
+       }
+       snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
+                   syncref);
+
+       snd_iprintf(buffer,
+                   "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n",
+                   (hdspm->
+                    control_register & HDSPM_clr_tms) ? "on" : "off",
+                   (hdspm->
+                    control_register & HDSPM_TX_64ch) ? "64" : "56",
+                   (hdspm->
+                    control_register & HDSPM_AutoInp) ? "on" : "off");
+
+       switch (hdspm_clock_source(hdspm)) {
+       case HDSPM_CLOCK_SOURCE_AUTOSYNC:
+               clock_source = "AutoSync";
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
+               clock_source = "Internal 32 kHz";
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
+               clock_source = "Internal 44.1 kHz";
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
+               clock_source = "Internal 48 kHz";
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
+               clock_source = "Internal 64 kHz";
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
+               clock_source = "Internal 88.2 kHz";
+               break;
+       case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
+               clock_source = "Internal 96 kHz";
+               break;
+       default:
+               clock_source = "Error";
+       }
+       snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
+       if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
+               system_clock_mode = "Slave";
+       } else {
+               system_clock_mode = "Master";
+       }
+       snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
+
+       switch (hdspm_pref_sync_ref(hdspm)) {
+       case HDSPM_SYNC_FROM_WORD:
+               pref_sync_ref = "Word Clock";
+               break;
+       case HDSPM_SYNC_FROM_MADI:
+               pref_sync_ref = "MADI Sync";
+               break;
+       default:
+               pref_sync_ref = "XXXX Clock";
+               break;
+       }
+       snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
+                   pref_sync_ref);
+
+       snd_iprintf(buffer, "System Clock Frequency: %d\n",
+                   hdspm->system_sample_rate);
+
+
+       snd_iprintf(buffer, "--- Status:\n");
+
+       x = status & HDSPM_madiSync;
+       x2 = status2 & HDSPM_wcSync;
+
+       snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
+                   (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
+                   "NoLock",
+                   (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
+                   "NoLock");
+
+       switch (hdspm_autosync_ref(hdspm)) {
+       case HDSPM_AUTOSYNC_FROM_WORD:
+               autosync_ref = "Word Clock";
+               break;
+       case HDSPM_AUTOSYNC_FROM_MADI:
+               autosync_ref = "MADI Sync";
+               break;
+       case HDSPM_AUTOSYNC_FROM_NONE:
+               autosync_ref = "Input not valid";
+               break;
+       default:
+               autosync_ref = "---";
+               break;
+       }
+       snd_iprintf(buffer,
+                   "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
+                   autosync_ref, hdspm_external_sample_rate(hdspm),
+                   (status & HDSPM_madiFreqMask) >> 22,
+                   (status2 & HDSPM_wcFreqMask) >> 5);
+
+       snd_iprintf(buffer, "Input: %s, Mode=%s\n",
+                   (status & HDSPM_AB_int) ? "Coax" : "Optical",
+                   (status & HDSPM_RX_64ch) ? "64 channels" :
+                   "56 channels");
+
+       snd_iprintf(buffer, "\n");
+}
+
+static void __devinit snd_hdspm_proc_init(hdspm_t * hdspm)
+{
+       snd_info_entry_t *entry;
+
+       if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
+               snd_info_set_text_ops(entry, hdspm, 1024,
+                                     snd_hdspm_proc_read);
+}
+
+/*------------------------------------------------------------
+   hdspm intitialize 
+ ------------------------------------------------------------*/
+
+static int snd_hdspm_set_defaults(hdspm_t * hdspm)
+{
+       unsigned int i;
+
+       /* ASSUMPTION: hdspm->lock is either held, or there is no need to
+          hold it (e.g. during module initalization).
+        */
+
+       /* set defaults:       */
+
+       hdspm->control_register = HDSPM_ClockModeMaster |       /* Master Cloack Mode on */
+           hdspm_encode_latency(7) |   /* latency maximum = 8192 samples */
+           HDSPM_InputCoaxial |        /* Input Coax not Optical */
+           HDSPM_SyncRef_MADI |        /* Madi is syncclock */
+           HDSPM_LineOut |     /* Analog output in */
+           HDSPM_TX_64ch |     /* transmit in 64ch mode */
+           HDSPM_AutoInp;      /* AutoInput chossing (takeover) */
+
+       /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
+       /* !  HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
+       /* ! HDSPM_clr_tms = do not clear bits in track marks */
+
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+#ifdef SNDRV_BIG_ENDIAN
+       hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
+#else
+       hdspm->control2_register = 0;
+#endif
+
+       hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
+       hdspm_compute_period_size(hdspm);
+
+       /* silence everything */
+
+       all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
+
+       if (line_outs_monitor[hdspm->dev]) {
+
+               snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n");
+
+               for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
+                       if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
+                               return -EIO;
+               }
+       }
+
+       /* set a default rate so that the channel map is set up. */
+       hdspm->channel_map = channel_map_madi_ss;
+       hdspm_set_rate(hdspm, 44100, 1);
+
+       return 0;
+}
+
+
+/*------------------------------------------------------------
+   interupt 
+ ------------------------------------------------------------*/
+
+static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id,
+                                      struct pt_regs *regs)
+{
+       hdspm_t *hdspm = (hdspm_t *) dev_id;
+       unsigned int status;
+       int audio;
+       int midi0;
+       int midi1;
+       unsigned int midi0status;
+       unsigned int midi1status;
+       int schedule = 0;
+
+       status = hdspm_read(hdspm, HDSPM_statusRegister);
+
+       audio = status & HDSPM_audioIRQPending;
+       midi0 = status & HDSPM_midi0IRQPending;
+       midi1 = status & HDSPM_midi1IRQPending;
+
+       if (!audio && !midi0 && !midi1)
+               return IRQ_NONE;
+
+       hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
+       hdspm->irq_count++;
+
+       midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
+       midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
+
+       if (audio) {
+
+               if (hdspm->capture_substream)
+                       snd_pcm_period_elapsed(hdspm->pcm->
+                                              streams
+                                              [SNDRV_PCM_STREAM_CAPTURE].
+                                              substream);
+
+               if (hdspm->playback_substream)
+                       snd_pcm_period_elapsed(hdspm->pcm->
+                                              streams
+                                              [SNDRV_PCM_STREAM_PLAYBACK].
+                                              substream);
+       }
+
+       if (midi0 && midi0status) {
+               /* we disable interrupts for this input until processing is done */
+               hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
+               hdspm_write(hdspm, HDSPM_controlRegister,
+                           hdspm->control_register);
+               hdspm->midi[0].pending = 1;
+               schedule = 1;
+       }
+       if (midi1 && midi1status) {
+               /* we disable interrupts for this input until processing is done */
+               hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
+               hdspm_write(hdspm, HDSPM_controlRegister,
+                           hdspm->control_register);
+               hdspm->midi[1].pending = 1;
+               schedule = 1;
+       }
+       if (schedule)
+               tasklet_hi_schedule(&hdspm->midi_tasklet);
+       return IRQ_HANDLED;
+}
+
+/*------------------------------------------------------------
+   pcm interface 
+  ------------------------------------------------------------*/
+
+
+static snd_pcm_uframes_t snd_hdspm_hw_pointer(snd_pcm_substream_t *
+                                             substream)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       return hdspm_hw_pointer(hdspm);
+}
+
+static char *hdspm_channel_buffer_location(hdspm_t * hdspm,
+                                          int stream, int channel)
+{
+       int mapped_channel;
+
+       snd_assert(channel >= 0
+                  || channel < HDSPM_MAX_CHANNELS, return NULL);
+
+       if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+               return NULL;
+
+       if (stream == SNDRV_PCM_STREAM_CAPTURE) {
+               return hdspm->capture_buffer +
+                   mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+       } else {
+               return hdspm->playback_buffer +
+                   mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+       }
+}
+
+
+/* dont know why need it ??? */
+static int snd_hdspm_playback_copy(snd_pcm_substream_t * substream,
+                                  int channel, snd_pcm_uframes_t pos,
+                                  void __user *src, snd_pcm_uframes_t count)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       char *channel_buf;
+
+       snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
+                  return -EINVAL);
+
+       channel_buf = hdspm_channel_buffer_location(hdspm,
+                                                   substream->pstr->
+                                                   stream, channel);
+
+       snd_assert(channel_buf != NULL, return -EIO);
+
+       return copy_from_user(channel_buf + pos * 4, src, count * 4);
+}
+
+static int snd_hdspm_capture_copy(snd_pcm_substream_t * substream,
+                                 int channel, snd_pcm_uframes_t pos,
+                                 void __user *dst, snd_pcm_uframes_t count)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       char *channel_buf;
+
+       snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
+                  return -EINVAL);
+
+       channel_buf = hdspm_channel_buffer_location(hdspm,
+                                                   substream->pstr->
+                                                   stream, channel);
+       snd_assert(channel_buf != NULL, return -EIO);
+       return copy_to_user(dst, channel_buf + pos * 4, count * 4);
+}
+
+static int snd_hdspm_hw_silence(snd_pcm_substream_t * substream,
+                               int channel, snd_pcm_uframes_t pos,
+                               snd_pcm_uframes_t count)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       char *channel_buf;
+
+       channel_buf =
+           hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
+                                         channel);
+       snd_assert(channel_buf != NULL, return -EIO);
+       memset(channel_buf + pos * 4, 0, count * 4);
+       return 0;
+}
+
+static int snd_hdspm_reset(snd_pcm_substream_t * substream)
+{
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       snd_pcm_substream_t *other;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               other = hdspm->capture_substream;
+       else
+               other = hdspm->playback_substream;
+
+       if (hdspm->running)
+               runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
+       else
+               runtime->status->hw_ptr = 0;
+       if (other) {
+               struct list_head *pos;
+               snd_pcm_substream_t *s;
+               snd_pcm_runtime_t *oruntime = other->runtime;
+               snd_pcm_group_for_each(pos, substream) {
+                       s = snd_pcm_group_substream_entry(pos);
+                       if (s == other) {
+                               oruntime->status->hw_ptr =
+                                   runtime->status->hw_ptr;
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int snd_hdspm_hw_params(snd_pcm_substream_t * substream,
+                              snd_pcm_hw_params_t * params)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       int err;
+       int i;
+       pid_t this_pid;
+       pid_t other_pid;
+       struct snd_sg_buf *sgbuf;
+
+
+       spin_lock_irq(&hdspm->lock);
+
+       if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               this_pid = hdspm->playback_pid;
+               other_pid = hdspm->capture_pid;
+       } else {
+               this_pid = hdspm->capture_pid;
+               other_pid = hdspm->playback_pid;
+       }
+
+       if ((other_pid > 0) && (this_pid != other_pid)) {
+
+               /* The other stream is open, and not by the same
+                  task as this one. Make sure that the parameters
+                  that matter are the same.
+                */
+
+               if (params_rate(params) != hdspm->system_sample_rate) {
+                       spin_unlock_irq(&hdspm->lock);
+                       _snd_pcm_hw_param_setempty(params,
+                                                  SNDRV_PCM_HW_PARAM_RATE);
+                       return -EBUSY;
+               }
+
+               if (params_period_size(params) != hdspm->period_bytes / 4) {
+                       spin_unlock_irq(&hdspm->lock);
+                       _snd_pcm_hw_param_setempty(params,
+                                                  SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+                       return -EBUSY;
+               }
+
+       }
+       /* We're fine. */
+       spin_unlock_irq(&hdspm->lock);
+
+       /* how to make sure that the rate matches an externally-set one ?   */
+
+       spin_lock_irq(&hdspm->lock);
+       if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) {
+               spin_unlock_irq(&hdspm->lock);
+               _snd_pcm_hw_param_setempty(params,
+                                          SNDRV_PCM_HW_PARAM_RATE);
+               return err;
+       }
+       spin_unlock_irq(&hdspm->lock);
+
+       if ((err =
+            hdspm_set_interrupt_interval(hdspm,
+                                         params_period_size(params))) <
+           0) {
+               _snd_pcm_hw_param_setempty(params,
+                                          SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+               return err;
+       }
+
+       /* Memory allocation, takashi's method, dont know if we should spinlock  */
+       /* malloc all buffer even if not enabled to get sure */
+       /* malloc only needed bytes */
+       err =
+           snd_pcm_lib_malloc_pages(substream,
+                                    HDSPM_CHANNEL_BUFFER_BYTES *
+                                    params_channels(params));
+       if (err < 0)
+               return err;
+
+       sgbuf = snd_pcm_substream_sgbuf(substream);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+               hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
+                               params_channels(params));
+
+               for (i = 0; i < params_channels(params); ++i)
+                       snd_hdspm_enable_out(hdspm, i, 1);
+
+               hdspm->playback_buffer =
+                   (unsigned char *) substream->runtime->dma_area;
+       } else {
+               hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
+                               params_channels(params));
+
+               for (i = 0; i < params_channels(params); ++i)
+                       snd_hdspm_enable_in(hdspm, i, 1);
+
+               hdspm->capture_buffer =
+                   (unsigned char *) substream->runtime->dma_area;
+       }
+       return 0;
+}
+
+static int snd_hdspm_hw_free(snd_pcm_substream_t * substream)
+{
+       int i;
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+               /* params_channels(params) should be enough, 
+                  but to get sure in case of error */
+               for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+                       snd_hdspm_enable_out(hdspm, i, 0);
+
+               hdspm->playback_buffer = NULL;
+       } else {
+               for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+                       snd_hdspm_enable_in(hdspm, i, 0);
+
+               hdspm->capture_buffer = NULL;
+
+       }
+
+       snd_pcm_lib_free_pages(substream);
+
+       return 0;
+}
+
+static int snd_hdspm_channel_info(snd_pcm_substream_t * substream,
+                                 snd_pcm_channel_info_t * info)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       int mapped_channel;
+
+       snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+       if ((mapped_channel = hdspm->channel_map[info->channel]) < 0)
+               return -EINVAL;
+
+       info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+       info->first = 0;
+       info->step = 32;
+       return 0;
+}
+
+static int snd_hdspm_ioctl(snd_pcm_substream_t * substream,
+                          unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case SNDRV_PCM_IOCTL1_RESET:
+               {
+                       return snd_hdspm_reset(substream);
+               }
+
+       case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
+               {
+                       snd_pcm_channel_info_t *info = arg;
+                       return snd_hdspm_channel_info(substream, info);
+               }
+       default:
+               break;
+       }
+
+       return snd_pcm_lib_ioctl(substream, cmd, arg);
+}
+
+static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       snd_pcm_substream_t *other;
+       int running;
+
+       spin_lock(&hdspm->lock);
+       running = hdspm->running;
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               running |= 1 << substream->stream;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               running &= ~(1 << substream->stream);
+               break;
+       default:
+               snd_BUG();
+               spin_unlock(&hdspm->lock);
+               return -EINVAL;
+       }
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               other = hdspm->capture_substream;
+       else
+               other = hdspm->playback_substream;
+
+       if (other) {
+               struct list_head *pos;
+               snd_pcm_substream_t *s;
+               snd_pcm_group_for_each(pos, substream) {
+                       s = snd_pcm_group_substream_entry(pos);
+                       if (s == other) {
+                               snd_pcm_trigger_done(s, substream);
+                               if (cmd == SNDRV_PCM_TRIGGER_START)
+                                       running |= 1 << s->stream;
+                               else
+                                       running &= ~(1 << s->stream);
+                               goto _ok;
+                       }
+               }
+               if (cmd == SNDRV_PCM_TRIGGER_START) {
+                       if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
+                           && substream->stream ==
+                           SNDRV_PCM_STREAM_CAPTURE)
+                               hdspm_silence_playback(hdspm);
+               } else {
+                       if (running &&
+                           substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                               hdspm_silence_playback(hdspm);
+               }
+       } else {
+               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+                       hdspm_silence_playback(hdspm);
+       }
+      _ok:
+       snd_pcm_trigger_done(substream, substream);
+       if (!hdspm->running && running)
+               hdspm_start_audio(hdspm);
+       else if (hdspm->running && !running)
+               hdspm_stop_audio(hdspm);
+       hdspm->running = running;
+       spin_unlock(&hdspm->lock);
+
+       return 0;
+}
+
+static int snd_hdspm_prepare(snd_pcm_substream_t * substream)
+{
+       return 0;
+}
+
+static unsigned int period_sizes[] =
+    { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
+
+static snd_pcm_hardware_t snd_hdspm_playback_subinfo = {
+       .info = (SNDRV_PCM_INFO_MMAP |
+                SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_NONINTERLEAVED |
+                SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
+       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+       .rates = (SNDRV_PCM_RATE_32000 |
+                 SNDRV_PCM_RATE_44100 |
+                 SNDRV_PCM_RATE_48000 |
+                 SNDRV_PCM_RATE_64000 |
+                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
+       .rate_min = 32000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = HDSPM_MAX_CHANNELS,
+       .buffer_bytes_max =
+           HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
+       .period_bytes_min = (64 * 4),
+       .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
+       .periods_min = 2,
+       .periods_max = 2,
+       .fifo_size = 0
+};
+
+static snd_pcm_hardware_t snd_hdspm_capture_subinfo = {
+       .info = (SNDRV_PCM_INFO_MMAP |
+                SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_NONINTERLEAVED |
+                SNDRV_PCM_INFO_SYNC_START),
+       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+       .rates = (SNDRV_PCM_RATE_32000 |
+                 SNDRV_PCM_RATE_44100 |
+                 SNDRV_PCM_RATE_48000 |
+                 SNDRV_PCM_RATE_64000 |
+                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
+       .rate_min = 32000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = HDSPM_MAX_CHANNELS,
+       .buffer_bytes_max =
+           HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
+       .period_bytes_min = (64 * 4),
+       .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
+       .periods_min = 2,
+       .periods_max = 2,
+       .fifo_size = 0
+};
+
+static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
+       .count = ARRAY_SIZE(period_sizes),
+       .list = period_sizes,
+       .mask = 0
+};
+
+
+static int snd_hdspm_hw_rule_channels_rate(snd_pcm_hw_params_t * params,
+                                          snd_pcm_hw_rule_t * rule)
+{
+       hdspm_t *hdspm = rule->private;
+       snd_interval_t *c =
+           hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+       snd_interval_t *r =
+           hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+
+       if (r->min > 48000) {
+               snd_interval_t t = {
+                       .min = 1,
+                       .max = hdspm->ds_channels,
+                       .integer = 1,
+               };
+               return snd_interval_refine(c, &t);
+       } else if (r->max < 64000) {
+               snd_interval_t t = {
+                       .min = 1,
+                       .max = hdspm->ss_channels,
+                       .integer = 1,
+               };
+               return snd_interval_refine(c, &t);
+       }
+       return 0;
+}
+
+static int snd_hdspm_hw_rule_rate_channels(snd_pcm_hw_params_t * params,
+                                          snd_pcm_hw_rule_t * rule)
+{
+       hdspm_t *hdspm = rule->private;
+       snd_interval_t *c =
+           hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+       snd_interval_t *r =
+           hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+
+       if (c->min <= hdspm->ss_channels) {
+               snd_interval_t t = {
+                       .min = 32000,
+                       .max = 48000,
+                       .integer = 1,
+               };
+               return snd_interval_refine(r, &t);
+       } else if (c->max > hdspm->ss_channels) {
+               snd_interval_t t = {
+                       .min = 64000,
+                       .max = 96000,
+                       .integer = 1,
+               };
+
+               return snd_interval_refine(r, &t);
+       }
+       return 0;
+}
+
+static int snd_hdspm_playback_open(snd_pcm_substream_t * substream)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+
+       snd_printdd("Open device substream %d\n", substream->stream);
+
+       spin_lock_irq(&hdspm->lock);
+
+       snd_pcm_set_sync(substream);
+
+       runtime->hw = snd_hdspm_playback_subinfo;
+
+       if (hdspm->capture_substream == NULL)
+               hdspm_stop_audio(hdspm);
+
+       hdspm->playback_pid = current->pid;
+       hdspm->playback_substream = substream;
+
+       spin_unlock_irq(&hdspm->lock);
+
+       snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+
+       snd_pcm_hw_constraint_list(runtime, 0,
+                                  SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                  &hw_constraints_period_sizes);
+
+       snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                           snd_hdspm_hw_rule_channels_rate, hdspm,
+                           SNDRV_PCM_HW_PARAM_RATE, -1);
+
+       snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+                           snd_hdspm_hw_rule_rate_channels, hdspm,
+                           SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+
+       return 0;
+}
+
+static int snd_hdspm_playback_release(snd_pcm_substream_t * substream)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+       spin_lock_irq(&hdspm->lock);
+
+       hdspm->playback_pid = -1;
+       hdspm->playback_substream = NULL;
+
+       spin_unlock_irq(&hdspm->lock);
+
+       return 0;
+}
+
+
+static int snd_hdspm_capture_open(snd_pcm_substream_t * substream)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+
+       spin_lock_irq(&hdspm->lock);
+       snd_pcm_set_sync(substream);
+       runtime->hw = snd_hdspm_capture_subinfo;
+
+       if (hdspm->playback_substream == NULL)
+               hdspm_stop_audio(hdspm);
+
+       hdspm->capture_pid = current->pid;
+       hdspm->capture_substream = substream;
+
+       spin_unlock_irq(&hdspm->lock);
+
+       snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+       snd_pcm_hw_constraint_list(runtime, 0,
+                                  SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                  &hw_constraints_period_sizes);
+
+       snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                           snd_hdspm_hw_rule_channels_rate, hdspm,
+                           SNDRV_PCM_HW_PARAM_RATE, -1);
+
+       snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+                           snd_hdspm_hw_rule_rate_channels, hdspm,
+                           SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+       return 0;
+}
+
+static int snd_hdspm_capture_release(snd_pcm_substream_t * substream)
+{
+       hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+       spin_lock_irq(&hdspm->lock);
+
+       hdspm->capture_pid = -1;
+       hdspm->capture_substream = NULL;
+
+       spin_unlock_irq(&hdspm->lock);
+       return 0;
+}
+
+static int snd_hdspm_hwdep_dummy_op(snd_hwdep_t * hw, struct file *file)
+{
+       /* we have nothing to initialize but the call is required */
+       return 0;
+}
+
+
+static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file,
+                                unsigned int cmd, unsigned long arg)
+{
+       hdspm_t *hdspm = (hdspm_t *) hw->private_data;
+       struct sndrv_hdspm_mixer_ioctl mixer;
+       hdspm_config_info_t info;
+       hdspm_version_t hdspm_version;
+       struct sndrv_hdspm_peak_rms_ioctl rms;
+
+       switch (cmd) {
+
+               
+       case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
+               if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
+                       return -EFAULT;
+               /* maybe there is a chance to memorymap in future so dont touch just copy */
+               if(copy_to_user_fromio((void __user *)rms.peak,
+                                      hdspm->iobase+HDSPM_MADI_peakrmsbase,
+                                      sizeof(hdspm_peak_rms_t)) != 0 )
+                       return -EFAULT;
+
+               break;
+               
+
+       case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
+
+               spin_lock_irq(&hdspm->lock);
+               info.pref_sync_ref =
+                   (unsigned char) hdspm_pref_sync_ref(hdspm);
+               info.wordclock_sync_check =
+                   (unsigned char) hdspm_wc_sync_check(hdspm);
+
+               info.system_sample_rate = hdspm->system_sample_rate;
+               info.autosync_sample_rate =
+                   hdspm_external_sample_rate(hdspm);
+               info.system_clock_mode =
+                   (unsigned char) hdspm_system_clock_mode(hdspm);
+               info.clock_source =
+                   (unsigned char) hdspm_clock_source(hdspm);
+               info.autosync_ref =
+                   (unsigned char) hdspm_autosync_ref(hdspm);
+               info.line_out = (unsigned char) hdspm_line_out(hdspm);
+               info.passthru = 0;
+               spin_unlock_irq(&hdspm->lock);
+               if (copy_to_user((void __user *) arg, &info, sizeof(info)))
+                       return -EFAULT;
+               break;
+
+       case SNDRV_HDSPM_IOCTL_GET_VERSION:
+               hdspm_version.firmware_rev = hdspm->firmware_rev;
+               if (copy_to_user((void __user *) arg, &hdspm_version,
+                                sizeof(hdspm_version)))
+                       return -EFAULT;
+               break;
+
+       case SNDRV_HDSPM_IOCTL_GET_MIXER:
+               if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
+                       return -EFAULT;
+               if (copy_to_user
+                   ((void __user *)mixer.mixer, hdspm->mixer, sizeof(hdspm_mixer_t)))
+                       return -EFAULT;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static snd_pcm_ops_t snd_hdspm_playback_ops = {
+       .open = snd_hdspm_playback_open,
+       .close = snd_hdspm_playback_release,
+       .ioctl = snd_hdspm_ioctl,
+       .hw_params = snd_hdspm_hw_params,
+       .hw_free = snd_hdspm_hw_free,
+       .prepare = snd_hdspm_prepare,
+       .trigger = snd_hdspm_trigger,
+       .pointer = snd_hdspm_hw_pointer,
+       .copy = snd_hdspm_playback_copy,
+       .silence = snd_hdspm_hw_silence,
+       .page = snd_pcm_sgbuf_ops_page,
+};
+
+static snd_pcm_ops_t snd_hdspm_capture_ops = {
+       .open = snd_hdspm_capture_open,
+       .close = snd_hdspm_capture_release,
+       .ioctl = snd_hdspm_ioctl,
+       .hw_params = snd_hdspm_hw_params,
+       .hw_free = snd_hdspm_hw_free,
+       .prepare = snd_hdspm_prepare,
+       .trigger = snd_hdspm_trigger,
+       .pointer = snd_hdspm_hw_pointer,
+       .copy = snd_hdspm_capture_copy,
+       .page = snd_pcm_sgbuf_ops_page,
+};
+
+static int __devinit snd_hdspm_create_hwdep(snd_card_t * card,
+                                           hdspm_t * hdspm)
+{
+       snd_hwdep_t *hw;
+       int err;
+
+       if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
+               return err;
+
+       hdspm->hwdep = hw;
+       hw->private_data = hdspm;
+       strcpy(hw->name, "HDSPM hwdep interface");
+
+       hw->ops.open = snd_hdspm_hwdep_dummy_op;
+       hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
+       hw->ops.release = snd_hdspm_hwdep_dummy_op;
+
+       return 0;
+}
+
+
+/*------------------------------------------------------------
+   memory interface 
+ ------------------------------------------------------------*/
+static int __devinit snd_hdspm_preallocate_memory(hdspm_t * hdspm)
+{
+       int err;
+       snd_pcm_t *pcm;
+       size_t wanted;
+
+       pcm = hdspm->pcm;
+
+       wanted = HDSPM_DMA_AREA_BYTES + 4096;   /* dont know why, but it works */
+
+       if ((err =
+            snd_pcm_lib_preallocate_pages_for_all(pcm,
+                                                  SNDRV_DMA_TYPE_DEV_SG,
+                                                  snd_dma_pci_data(hdspm->pci),
+                                                  wanted,
+                                                  wanted)) < 0) {
+               snd_printdd("Could not preallocate %d  Bytes\n", wanted);
+
+               return err;
+       } else
+               snd_printdd(" Preallocated %d  Bytes\n", wanted);
+
+       return 0;
+}
+
+static int snd_hdspm_memory_free(hdspm_t * hdspm)
+{
+       snd_printdd("memory_free_for_all %p\n", hdspm->pcm);
+
+       snd_pcm_lib_preallocate_free_for_all(hdspm->pcm);
+       return 0;
+}
+
+
+static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
+                            unsigned int reg, int channels)
+{
+       int i;
+       for (i = 0; i < (channels * 16); i++)
+               hdspm_write(hdspm, reg + 4 * i,
+                           snd_pcm_sgbuf_get_addr(sgbuf,
+                                                  (size_t) 4096 * i));
+}
+
+/* ------------- ALSA Devices ---------------------------- */
+static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
+                                         hdspm_t * hdspm)
+{
+       snd_pcm_t *pcm;
+       int err;
+
+       if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
+               return err;
+
+       hdspm->pcm = pcm;
+       pcm->private_data = hdspm;
+       strcpy(pcm->name, hdspm->card_name);
+
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                       &snd_hdspm_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                       &snd_hdspm_capture_ops);
+
+       pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
+
+       if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0)
+               return err;
+
+       return 0;
+}
+
+static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm)
+{
+       snd_hdspm_flush_midi_input(hdspm, 0);
+       snd_hdspm_flush_midi_input(hdspm, 1);
+}
+
+static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
+                                                  hdspm_t * hdspm)
+{
+       int err;
+
+       snd_printdd("Create card...\n");
+       if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0)
+               return err;
+
+       if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0)
+               return err;
+
+       if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0)
+               return err;
+
+       if ((err = snd_hdspm_create_controls(card, hdspm)) < 0)
+               return err;
+
+       if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0)
+               return err;
+
+       snd_printdd("proc init...\n");
+       snd_hdspm_proc_init(hdspm);
+
+       hdspm->system_sample_rate = -1;
+       hdspm->last_external_sample_rate = -1;
+       hdspm->last_internal_sample_rate = -1;
+       hdspm->playback_pid = -1;
+       hdspm->capture_pid = -1;
+       hdspm->capture_substream = NULL;
+       hdspm->playback_substream = NULL;
+
+       snd_printdd("Set defaults...\n");
+       if ((err = snd_hdspm_set_defaults(hdspm)) < 0)
+               return err;
+
+       snd_printdd("Update mixer controls...\n");
+       hdspm_update_simple_mixer_controls(hdspm);
+
+       snd_printdd("Initializeing complete ???\n");
+
+       if ((err = snd_card_register(card)) < 0) {
+               snd_printk(KERN_ERR "HDSPM: error registering card\n");
+               return err;
+       }
+
+       snd_printdd("... yes now\n");
+
+       return 0;
+}
+
+static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm,
+                                     int precise_ptr, int enable_monitor)
+{
+       struct pci_dev *pci = hdspm->pci;
+       int err;
+       int i;
+
+       unsigned long io_extent;
+
+       hdspm->irq = -1;
+       hdspm->irq_count = 0;
+
+       hdspm->midi[0].rmidi = NULL;
+       hdspm->midi[1].rmidi = NULL;
+       hdspm->midi[0].input = NULL;
+       hdspm->midi[1].input = NULL;
+       hdspm->midi[0].output = NULL;
+       hdspm->midi[1].output = NULL;
+       spin_lock_init(&hdspm->midi[0].lock);
+       spin_lock_init(&hdspm->midi[1].lock);
+       hdspm->iobase = NULL;
+       hdspm->control_register = 0;
+       hdspm->control2_register = 0;
+
+       hdspm->playback_buffer = NULL;
+       hdspm->capture_buffer = NULL;
+
+       for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+               hdspm->playback_mixer_ctls[i] = NULL;
+       hdspm->mixer = NULL;
+
+       hdspm->card = card;
+
+       spin_lock_init(&hdspm->lock);
+
+       tasklet_init(&hdspm->midi_tasklet,
+                    hdspm_midi_tasklet, (unsigned long) hdspm);
+
+       pci_read_config_word(hdspm->pci,
+                            PCI_CLASS_REVISION, &hdspm->firmware_rev);
+
+       strcpy(card->driver, "HDSPM");
+       strcpy(card->mixername, "Xilinx FPGA");
+       hdspm->card_name = "RME HDSPM MADI";
+
+       if ((err = pci_enable_device(pci)) < 0)
+               return err;
+
+       pci_set_master(hdspm->pci);
+
+       if ((err = pci_request_regions(pci, "hdspm")) < 0)
+               return err;
+
+       hdspm->port = pci_resource_start(pci, 0);
+       io_extent = pci_resource_len(pci, 0);
+
+       snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
+                  hdspm->port, hdspm->port + io_extent - 1);
+
+
+       if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) {
+               snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n",
+                          hdspm->port, hdspm->port + io_extent - 1);
+               return -EBUSY;
+       }
+       snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
+                  (unsigned long)hdspm->iobase, hdspm->port,
+                  hdspm->port + io_extent - 1);
+
+       if (request_irq(pci->irq, snd_hdspm_interrupt,
+                       SA_INTERRUPT | SA_SHIRQ, "hdspm",
+                       (void *) hdspm)) {
+               snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
+               return -EBUSY;
+       }
+
+       snd_printdd("use IRQ %d\n", pci->irq);
+
+       hdspm->irq = pci->irq;
+       hdspm->precise_ptr = precise_ptr;
+
+       hdspm->monitor_outs = enable_monitor;
+
+       snd_printdd("kmalloc Mixer memory of %d Bytes\n",
+                  sizeof(hdspm_mixer_t));
+       if ((hdspm->mixer =
+            (hdspm_mixer_t *) kmalloc(sizeof(hdspm_mixer_t), GFP_KERNEL))
+           == NULL) {
+               snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
+                          (int)sizeof(hdspm_mixer_t));
+               return err;
+       }
+
+       hdspm->ss_channels = MADI_SS_CHANNELS;
+       hdspm->ds_channels = MADI_DS_CHANNELS;
+       hdspm->qs_channels = MADI_QS_CHANNELS;
+
+       snd_printdd("create alsa devices.\n");
+       if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0)
+               return err;
+
+       snd_hdspm_initialize_midi_flush(hdspm);
+
+       return 0;
+}
+
+static int snd_hdspm_free(hdspm_t * hdspm)
+{
+
+       if (hdspm->port) {
+
+               /* stop th audio, and cancel all interrupts */
+               hdspm->control_register &=
+                   ~(HDSPM_Start | HDSPM_AudioInterruptEnable
+                     | HDSPM_Midi0InterruptEnable |
+                     HDSPM_Midi1InterruptEnable);
+               hdspm_write(hdspm, HDSPM_controlRegister,
+                           hdspm->control_register);
+       }
+
+       if (hdspm->irq >= 0)
+               free_irq(hdspm->irq, (void *) hdspm);
+
+
+       if (hdspm->mixer)
+               kfree(hdspm->mixer);
+
+       if (hdspm->iobase)
+               iounmap(hdspm->iobase);
+
+       snd_hdspm_memory_free(hdspm);
+
+       if (hdspm->port)
+               pci_release_regions(hdspm->pci);
+
+       pci_disable_device(hdspm->pci);
+       return 0;
+}
+
+static void snd_hdspm_card_free(snd_card_t * card)
+{
+       hdspm_t *hdspm = (hdspm_t *) card->private_data;
+
+       if (hdspm)
+               snd_hdspm_free(hdspm);
+}
+
+static int __devinit snd_hdspm_probe(struct pci_dev *pci,
+                                    const struct pci_device_id *pci_id)
+{
+       static int dev;
+       hdspm_t *hdspm;
+       snd_card_t *card;
+       int err;
+
+       if (dev >= SNDRV_CARDS)
+               return -ENODEV;
+       if (!enable[dev]) {
+               dev++;
+               return -ENOENT;
+       }
+
+       if (!(card = snd_card_new(index[dev], id[dev],
+                                 THIS_MODULE, sizeof(hdspm_t))))
+               return -ENOMEM;
+
+       hdspm = (hdspm_t *) card->private_data;
+       card->private_free = snd_hdspm_card_free;
+       hdspm->dev = dev;
+       hdspm->pci = pci;
+
+       if ((err =
+            snd_hdspm_create(card, hdspm, precise_ptr[dev],
+                             enable_monitor[dev])) < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       strcpy(card->shortname, "HDSPM MADI");
+       sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
+               hdspm->port, hdspm->irq);
+
+       if ((err = snd_card_register(card)) < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       pci_set_drvdata(pci, card);
+
+       dev++;
+       return 0;
+}
+
+static void __devexit snd_hdspm_remove(struct pci_dev *pci)
+{
+       snd_card_free(pci_get_drvdata(pci));
+       pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+       .name = "RME Hammerfall DSP MADI",
+       .id_table = snd_hdspm_ids,
+       .probe = snd_hdspm_probe,
+       .remove = __devexit_p(snd_hdspm_remove),
+};
+
+
+static int __init alsa_card_hdspm_init(void)
+{
+       return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_hdspm_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_hdspm_init)
+module_exit(alsa_card_hdspm_exit)
index 69cd81eaa111bc976932fd2a5838ff81b662add3..f3037402d58fd199bb05c78f7669b84d4ecb4bf2 100644 (file)
@@ -303,18 +303,22 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
 {
        dmab->dev.type = SNDRV_DMA_TYPE_DEV;
        dmab->dev.dev = snd_dma_pci_data(pci);
-       if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
-               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-                                       size, dmab) < 0)
-                       return -ENOMEM;
+       if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+               if (dmab->bytes >= size)
+                       return 0;
        }
+       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+                               size, dmab) < 0)
+               return -ENOMEM;
        return 0;
 }
 
 static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-       if (dmab->area)
+       if (dmab->area) {
+               dmab->dev.dev = NULL; /* make it anonymous */
                snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
+       }
 }
 
 
@@ -2664,7 +2668,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_hammerfall_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_hammerfall_exit(void)
index cfd2c5fd6ddf5ae77c20579fb11e959edf897e89..60ecb2bdb65e79231e6bc888d7d51a98734c4f20 100644 (file)
@@ -1522,7 +1522,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_sonicvibes_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_sonicvibes_exit(void)
index ad58e08d66e2cdf7f058b0ef75a20bc91318386d..940d531575c098cd736776420b0b674c45094e3d 100644 (file)
@@ -143,7 +143,8 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
                        return err;
                }
        }
-       if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
+       if (trident->device != TRIDENT_DEVICE_ID_SI7018 &&
+           (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
                                       trident->midi_port, 1,
                                       trident->irq, 0, &trident->rmidi)) < 0) {
                snd_card_free(card);
@@ -184,7 +185,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_trident_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_trident_exit(void)
index 9b4d74d49f984c9d6a19bc9fd4ccd5c35df1d49b..42c48f0ce8e829e2cf8ceb7068c9cab31e54c73b 100644 (file)
@@ -101,7 +101,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
 module_param_array(ac97_quirk, charp, NULL, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
 module_param_array(dxs_support, int, NULL, 0444);
-MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)");
+MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
 
 
 /* pci ids */
@@ -302,6 +302,7 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);
 #define VIA_DXS_DISABLE        2
 #define VIA_DXS_48K    3
 #define VIA_DXS_NO_VRA 4
+#define VIA_DXS_SRC    5
 
 
 /*
@@ -380,6 +381,7 @@ struct _snd_via82xx {
        struct via_rate_lock rates[2]; /* playback and capture */
        unsigned int dxs_fixed: 1;      /* DXS channel accepts only 48kHz */
        unsigned int no_vra: 1;         /* no need to set VRA on DXS channels */
+       unsigned int dxs_src: 1;        /* use full SRC capabilities of DXS */
        unsigned int spdif_on: 1;       /* only spdif rates work to external DACs */
 
        snd_pcm_t *pcms[2];
@@ -489,10 +491,8 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
                snd_dma_free_pages(&dev->table);
                dev->table.area = NULL;
        }
-       if (dev->idx_table) {
-               kfree(dev->idx_table);
-               dev->idx_table = NULL;
-       }
+       kfree(dev->idx_table);
+       dev->idx_table = NULL;
        return 0;
 }
 
@@ -924,15 +924,17 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
        via82xx_t *chip = snd_pcm_substream_chip(substream);
        viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
        snd_pcm_runtime_t *runtime = substream->runtime;
+       int ac97_rate = chip->dxs_src ? 48000 : runtime->rate;
        int rate_changed;
        u32 rbits;
 
-       if ((rate_changed = via_lock_rate(&chip->rates[0], runtime->rate)) < 0)
+       if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0)
                return rate_changed;
        if (rate_changed) {
                snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,
                                  chip->no_vra ? 48000 : runtime->rate);
-               snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
+               snd_ac97_set_rate(chip->ac97, AC97_SPDIF,
+                                 chip->no_vra ? 48000 : runtime->rate);
        }
        if (runtime->rate == 48000)
                rbits = 0xfffff;
@@ -1074,6 +1076,12 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst
                /* fixed DXS playback rate */
                runtime->hw.rates = SNDRV_PCM_RATE_48000;
                runtime->hw.rate_min = runtime->hw.rate_max = 48000;
+       } else if (chip->dxs_src && viadev->reg_offset < 0x40) {
+               /* use full SRC capabilities of DXS */
+               runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS |
+                                    SNDRV_PCM_RATE_8000_48000);
+               runtime->hw.rate_min = 8000;
+               runtime->hw.rate_max = 48000;
        } else if (! ratep->rate) {
                int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
                runtime->hw.rates = chip->ac97->rates[idx];
@@ -1550,51 +1558,51 @@ static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
 
 static struct ac97_quirk ac97_quirks[] = {
        {
-               .vendor = 0x1106,
-               .device = 0x4161,
+               .subvendor = 0x1106,
+               .subdevice = 0x4161,
                .codec_id = 0x56494161, /* VT1612A */
                .name = "Soltek SL-75DRV5",
                .type = AC97_TUNE_NONE
        },
        {       /* FIXME: which codec? */
-               .vendor = 0x1106,
-               .device = 0x4161,
+               .subvendor = 0x1106,
+               .subdevice = 0x4161,
                .name = "ASRock K7VT2",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1019,
-               .device = 0x0a81,
+               .subvendor = 0x1019,
+               .subdevice = 0x0a81,
                .name = "ECS K7VTA3",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1019,
-               .device = 0x0a85,
+               .subvendor = 0x1019,
+               .subdevice = 0x0a85,
                .name = "ECS L7VMM2",
                .type = AC97_TUNE_HP_ONLY
        },
        {
-               .vendor = 0x1849,
-               .device = 0x3059,
+               .subvendor = 0x1849,
+               .subdevice = 0x3059,
                .name = "ASRock K7VM2",
                .type = AC97_TUNE_HP_ONLY       /* VT1616 */
        },
        {
-               .vendor = 0x14cd,
-               .device = 0x7002,
+               .subvendor = 0x14cd,
+               .subdevice = 0x7002,
                .name = "Unknown",
                .type = AC97_TUNE_ALC_JACK
        },
        {
-               .vendor = 0x1071,
-               .device = 0x8590,
+               .subvendor = 0x1071,
+               .subdevice = 0x8590,
                .name = "Mitac Mobo",
                .type = AC97_TUNE_ALC_JACK
        },
        {
-               .vendor = 0x161f,
-               .device = 0x202b,
+               .subvendor = 0x161f,
+               .subdevice = 0x202b,
                .name = "Arima Notebook",
                .type = AC97_TUNE_HP_ONLY,
        },
@@ -2132,8 +2140,8 @@ static struct via823x_info via823x_cards[] __devinitdata = {
  * auto detection of DXS channel supports.
  */
 struct dxs_whitelist {
-       unsigned short vendor;
-       unsigned short device; 
+       unsigned short subvendor;
+       unsigned short subdevice; 
        unsigned short mask; 
        short action;   /* new dxs_support value */
 };
@@ -2141,38 +2149,44 @@ struct dxs_whitelist {
 static int __devinit check_dxs_list(struct pci_dev *pci)
 {
        static struct dxs_whitelist whitelist[] = {
-               { .vendor = 0x1005, .device = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
-               { .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K },
-               { .vendor = 0x1019, .device = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
-               { .vendor = 0x1019, .device = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
-               { .vendor = 0x1025, .device = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
-               { .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
-               { .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
-               { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
-               { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
-               { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
-               { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
-               { .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
-               { .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
-               { .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
-               { .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
-               { .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
-               { .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
-               { .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
-               { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
-               { .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
-               { .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
-               { .vendor = 0x147b, .device = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
-               { .vendor = 0x147b, .device = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
-               { .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
-               { .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
-               { .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
-               { .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
-               { .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
-               { .vendor = 0x161f, .device = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
-               { .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
-               { .vendor = 0x1695, .device = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
-               { .vendor = 0x1849, .device = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
+               { .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
+               { .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K },
+               { .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
+               { .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
+               { .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
+               { .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
+               { .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
+               { .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
+               { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC    }, /* ASUS A8V Deluxe */ 
+               { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
+               { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
+               { .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
+               { .subvendor = 0x1106, .subdevice = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
+               { .subvendor = 0x1106, .subdevice = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
+               { .subvendor = 0x1106, .subdevice = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
+               { .subvendor = 0x1106, .subdevice = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */
+               { .subvendor = 0x1297, .subdevice = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
+               { .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
+               { .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
+               { .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */
+               { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
+               { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
+               { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
+               { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
+               { .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
+               { .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
+               { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
+               { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
+               { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
+               { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_NO_VRA }, /* Twinhead mobo */
+               { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
+               { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
+               { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
+               { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
+               { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
+               { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
+               { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
+               { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
                { } /* terminator */
        };
        struct dxs_whitelist *w;
@@ -2182,14 +2196,14 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
        pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
        pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
 
-       for (w = whitelist; w->vendor; w++) {
-               if (w->vendor != subsystem_vendor)
+       for (w = whitelist; w->subvendor; w++) {
+               if (w->subvendor != subsystem_vendor)
                        continue;
                if (w->mask) {
-                       if ((w->mask & subsystem_device) == w->device)
+                       if ((w->mask & subsystem_device) == w->subdevice)
                                return w->action;
                } else {
-                       if (subsystem_device == w->device)
+                       if (subsystem_device == w->subdevice)
                                return w->action;
                }
        }
@@ -2198,8 +2212,9 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
         * not detected, try 48k rate only to be sure.
         */
        printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n");
-       printk(KERN_INFO "         Please try dxs_support=1 or dxs_support=4 option\n");
+       printk(KERN_INFO "         Please try dxs_support=5 option\n");
        printk(KERN_INFO "         and report if it works on your machine.\n");
+       printk(KERN_INFO "         For more details, read ALSA-Configuration.txt.\n");
        return VIA_DXS_48K;
 };
 
@@ -2288,6 +2303,10 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
                                chip->dxs_fixed = 1;
                        else if (dxs_support[dev] == VIA_DXS_NO_VRA)
                                chip->no_vra = 1;
+                       else if (dxs_support[dev] == VIA_DXS_SRC) {
+                               chip->no_vra = 1;
+                               chip->dxs_src = 1;
+                       }
                }
                if ((err = snd_via8233_init_misc(chip, dev)) < 0)
                        goto __error;
@@ -2334,7 +2353,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_via82xx_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_via82xx_exit(void)
index ea5c6f6401593fc150b8dfcc1236f6d012eb5fdd..5896d289f9ac3d28238b40dc913e30e03347d9c5 100644 (file)
@@ -352,10 +352,8 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
                snd_dma_free_pages(&dev->table);
                dev->table.area = NULL;
        }
-       if (dev->idx_table) {
-               kfree(dev->idx_table);
-               dev->idx_table = NULL;
-       }
+       kfree(dev->idx_table);
+       dev->idx_table = NULL;
        return 0;
 }
 
@@ -420,7 +418,10 @@ static void snd_via82xx_codec_write(ac97_t *ac97,
 {
        via82xx_t *chip = ac97->private_data;
        unsigned int xval;
-       
+       if(reg == AC97_GPIO_STATUS) {
+               outl(val, VIAREG(chip, GPI_STATUS));
+               return;
+       }       
        xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY;
        xval <<= VIA_REG_AC97_CODEC_ID_SHIFT;
        xval |= reg << VIA_REG_AC97_CMD_SHIFT;
@@ -544,25 +545,6 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
        return 0;
 }
 
-static int snd_via82xx_modem_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
-{
-       via82xx_t *chip = snd_pcm_substream_chip(substream);
-       unsigned int val = 0;
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS);
-               outl(val|AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS));
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-               val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS);
-               outl(val&~AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS));
-               break;
-       default:
-               break;
-       }
-       return snd_via82xx_pcm_trigger(substream, cmd);
-}
-
 /*
  * pointer callbacks
  */
@@ -806,7 +788,7 @@ static snd_pcm_ops_t snd_via686_playback_ops = {
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via82xx_pcm_prepare,
-       .trigger =      snd_via82xx_modem_pcm_trigger,
+       .trigger =      snd_via82xx_pcm_trigger,
        .pointer =      snd_via686_pcm_pointer,
        .page =         snd_pcm_sgbuf_ops_page,
 };
@@ -819,7 +801,7 @@ static snd_pcm_ops_t snd_via686_capture_ops = {
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via82xx_pcm_prepare,
-       .trigger =      snd_via82xx_modem_pcm_trigger,
+       .trigger =      snd_via82xx_pcm_trigger,
        .pointer =      snd_via686_pcm_pointer,
        .page =         snd_pcm_sgbuf_ops_page,
 };
@@ -938,7 +920,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
  *
  */
 
-static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
+static int snd_via82xx_chip_init(via82xx_t *chip)
 {
        unsigned int val;
        int max_count;
@@ -1233,7 +1215,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_via82xx_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_via82xx_exit(void)
index 4ffbb25658a57807115e641bbb0140b823f5661e..dca6bd2c75806298eeacf5e5468f7141a7141240 100644 (file)
@@ -260,7 +260,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_vx222_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_vx222_exit(void)
index 9f3ef22df08dd1fec6bf3cba29b8135b02c8f6f5..5b5b624b47d0c6623f79c39893de23fe2d9451f8 100644 (file)
@@ -360,7 +360,7 @@ static struct pci_driver driver = {
 
 static int __init alsa_card_ymfpci_init(void)
 {
-       return pci_module_init(&driver);
+       return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ymfpci_exit(void)
index 05f1629760bc7cc38ca1bd71daa6c1e42979b7d3..2ae79610ecb58cad4d4af120d0826a3ecaf01591 100644 (file)
@@ -829,9 +829,7 @@ static snd_pcm_hardware_t snd_ymfpci_capture =
 
 static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-       ymfpci_pcm_t *ypcm = runtime->private_data;
-       
-       kfree(ypcm);
+       kfree(runtime->private_data);
 }
 
 static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
@@ -1421,17 +1419,15 @@ static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = {
 
 static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-       unsigned int mask = 1;
-
        switch (kcontrol->private_value) {
        case YDSXGR_SPDIFOUTCTRL: break;
        case YDSXGR_SPDIFINCTRL: break;
        default: return -EINVAL;
        }
-       uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
        uinfo->count = 1;
        uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = mask;
+       uinfo->value.integer.max = 1;
        return 0;
 }
 
@@ -1439,7 +1435,7 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 {
        ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
        int reg = kcontrol->private_value;
-       unsigned int shift = 0, mask = 1, invert = 0;
+       unsigned int shift = 0, mask = 1;
        
        switch (kcontrol->private_value) {
        case YDSXGR_SPDIFOUTCTRL: break;
@@ -1447,8 +1443,6 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
        default: return -EINVAL;
        }
        ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask;
-       if (invert)
-               ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
        return 0;
 }
 
@@ -1456,7 +1450,7 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 {
        ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
        int reg = kcontrol->private_value;
-       unsigned int shift = 0, mask = 1, invert = 0;
+       unsigned int shift = 0, mask = 1;
        int change;
        unsigned int val, oval;
        
@@ -1466,8 +1460,6 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
        default: return -EINVAL;
        }
        val = (ucontrol->value.integer.value[0] & mask);
-       if (invert)
-               val = mask - val;
        val <<= shift;
        spin_lock_irq(&chip->reg_lock);
        oval = snd_ymfpci_readl(chip, reg);
@@ -1487,14 +1479,13 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
        unsigned int reg = kcontrol->private_value;
-       unsigned int mask = 16383;
 
        if (reg < 0x80 || reg >= 0xc0)
                return -EINVAL;
-       uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 2;
        uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = mask;
+       uinfo->value.integer.max = 16383;
        return 0;
 }
 
@@ -1502,7 +1493,7 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 {
        ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
        unsigned int reg = kcontrol->private_value;
-       unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
+       unsigned int shift_left = 0, shift_right = 16, mask = 16383;
        unsigned int val;
        
        if (reg < 0x80 || reg >= 0xc0)
@@ -1512,10 +1503,6 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
        spin_unlock_irq(&chip->reg_lock);
        ucontrol->value.integer.value[0] = (val >> shift_left) & mask;
        ucontrol->value.integer.value[1] = (val >> shift_right) & mask;
-       if (invert) {
-               ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-               ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
-       }
        return 0;
 }
 
@@ -1523,7 +1510,7 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 {
        ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
        unsigned int reg = kcontrol->private_value;
-       unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
+       unsigned int shift_left = 0, shift_right = 16, mask = 16383;
        int change;
        unsigned int val1, val2, oval;
        
@@ -1531,10 +1518,6 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
                return -EINVAL;
        val1 = ucontrol->value.integer.value[0] & mask;
        val2 = ucontrol->value.integer.value[1] & mask;
-       if (invert) {
-               val1 = mask - val1;
-               val2 = mask - val2;
-       }
        val1 <<= shift_left;
        val2 <<= shift_right;
        spin_lock_irq(&chip->reg_lock);
index 53d8172c52ae328a024a1bd14be54e7d086977f8..332bbca3dfc4ff0459ca7b57526204c90e4a268c 100644 (file)
@@ -68,8 +68,7 @@ static int snd_vxpocket_free(vx_core_t *chip)
        if (hw)
                hw->card_list[vxp->index] = NULL;
        chip->card = NULL;
-       if (chip->dev)
-               kfree(chip->dev);
+       kfree(chip->dev);
 
        snd_vx_free_firmware(chip);
        kfree(chip);
index ec3fc1ba7fcabfe9a948bf8b5c05416b83979dec..4764940f11a050cff04f9e44690ea3338d1f1a9f 100644 (file)
@@ -291,10 +291,8 @@ snd_emux_create_effect(snd_emux_port_t *p)
 void
 snd_emux_delete_effect(snd_emux_port_t *p)
 {
-       if (p->effect) {
-               kfree(p->effect);
-               p->effect = NULL;
-       }
+       kfree(p->effect);
+       p->effect = NULL;
 }
 
 void
index 9329e992c841936c00a4b8522e9b4db803fb5380..f05d02f5b69f9233aca85c8927446db08b2fd27e 100644 (file)
@@ -6,6 +6,7 @@ menu "USB devices"
 config SND_USB_AUDIO
        tristate "USB Audio/MIDI driver"
        depends on SND && USB
+       select SND_HWDEP
        select SND_RAWMIDI
        select SND_PCM
        help
index aae66144d411ce579eee7185b8e3cca84e730d9e..a75695045f2924709009aa910c77eaed3715cd48 100644 (file)
@@ -98,7 +98,7 @@ MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
 #define MAX_PACKS      10
 #define MAX_PACKS_HS   (MAX_PACKS * 8) /* in high speed mode */
 #define MAX_URBS       5       /* max. 20ms long packets */
-#define SYNC_URBS      2       /* always two urbs for sync */
+#define SYNC_URBS      4       /* always four urbs for sync */
 #define MIN_PACKS_URB  1       /* minimum 1 packet per urb */
 
 typedef struct snd_usb_substream snd_usb_substream_t;
@@ -177,7 +177,7 @@ struct snd_usb_substream {
        unsigned int nurbs;                     /* # urbs */
        snd_urb_ctx_t dataurb[MAX_URBS];        /* data urb table */
        snd_urb_ctx_t syncurb[SYNC_URBS];       /* sync urb table */
-       char syncbuf[SYNC_URBS * MAX_PACKS * 4]; /* sync buffer; it's so small - let's get static */
+       char syncbuf[SYNC_URBS * 4];    /* sync buffer; it's so small - let's get static */
        char *tmpbuf;                   /* temporary buffer for playback */
 
        u64 formats;                    /* format bitmasks (all or'ed) */
@@ -251,17 +251,13 @@ static int prepare_capture_sync_urb(snd_usb_substream_t *subs,
 {
        unsigned char *cp = urb->transfer_buffer;
        snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
-       int i, offs;
 
-       urb->number_of_packets = ctx->packets;
        urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) {
-               urb->iso_frame_desc[i].length = 3;
-               urb->iso_frame_desc[i].offset = offs;
-               cp[0] = subs->freqn >> 2;
-               cp[1] = subs->freqn >> 10;
-               cp[2] = subs->freqn >> 18;
-       }
+       urb->iso_frame_desc[0].length = 3;
+       urb->iso_frame_desc[0].offset = 0;
+       cp[0] = subs->freqn >> 2;
+       cp[1] = subs->freqn >> 10;
+       cp[2] = subs->freqn >> 18;
        return 0;
 }
 
@@ -277,18 +273,14 @@ static int prepare_capture_sync_urb_hs(snd_usb_substream_t *subs,
 {
        unsigned char *cp = urb->transfer_buffer;
        snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
-       int i, offs;
 
-       urb->number_of_packets = ctx->packets;
        urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) {
-               urb->iso_frame_desc[i].length = 4;
-               urb->iso_frame_desc[i].offset = offs;
-               cp[0] = subs->freqn;
-               cp[1] = subs->freqn >> 8;
-               cp[2] = subs->freqn >> 16;
-               cp[3] = subs->freqn >> 24;
-       }
+       urb->iso_frame_desc[0].length = 4;
+       urb->iso_frame_desc[0].offset = 0;
+       cp[0] = subs->freqn;
+       cp[1] = subs->freqn >> 8;
+       cp[2] = subs->freqn >> 16;
+       cp[3] = subs->freqn >> 24;
        return 0;
 }
 
@@ -418,15 +410,11 @@ static int prepare_playback_sync_urb(snd_usb_substream_t *subs,
                                     snd_pcm_runtime_t *runtime,
                                     struct urb *urb)
 {
-       int i, offs;
        snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
 
-       urb->number_of_packets = ctx->packets;
        urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) {
-               urb->iso_frame_desc[i].length = 3;
-               urb->iso_frame_desc[i].offset = offs;
-       }
+       urb->iso_frame_desc[0].length = 3;
+       urb->iso_frame_desc[0].offset = 0;
        return 0;
 }
 
@@ -440,15 +428,11 @@ static int prepare_playback_sync_urb_hs(snd_usb_substream_t *subs,
                                        snd_pcm_runtime_t *runtime,
                                        struct urb *urb)
 {
-       int i, offs;
        snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
 
-       urb->number_of_packets = ctx->packets;
        urb->dev = ctx->subs->dev; /* we need to set this at each time */
-       for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) {
-               urb->iso_frame_desc[i].length = 4;
-               urb->iso_frame_desc[i].offset = offs;
-       }
+       urb->iso_frame_desc[0].length = 4;
+       urb->iso_frame_desc[0].offset = 0;
        return 0;
 }
 
@@ -462,31 +446,17 @@ static int retire_playback_sync_urb(snd_usb_substream_t *subs,
                                    snd_pcm_runtime_t *runtime,
                                    struct urb *urb)
 {
-       int i;
-       unsigned int f, found;
-       unsigned char *cp = urb->transfer_buffer;
+       unsigned int f;
        unsigned long flags;
 
-       found = 0;
-       for (i = 0; i < urb->number_of_packets; i++, cp += 4) {
-               if (urb->iso_frame_desc[i].status ||
-                   urb->iso_frame_desc[i].actual_length < 3)
-                       continue;
-               f = combine_triple(cp) << 2;
-#if 0
-               if (f < subs->freqn - (subs->freqn>>3) || f > subs->freqmax) {
-                       snd_printd(KERN_WARNING "requested frequency %d (%u,%03uHz) out of range (current nominal %d (%u,%03uHz))\n",
-                                  f, f >> 14, (f & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1),
-                                  subs->freqn, subs->freqn >> 14, (subs->freqn & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1));
-                       continue;
+       if (urb->iso_frame_desc[0].status == 0 &&
+           urb->iso_frame_desc[0].actual_length == 3) {
+               f = combine_triple((u8*)urb->transfer_buffer) << 2;
+               if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
+                       spin_lock_irqsave(&subs->lock, flags);
+                       subs->freqm = f;
+                       spin_unlock_irqrestore(&subs->lock, flags);
                }
-#endif
-               found = f;
-       }
-       if (found) {
-               spin_lock_irqsave(&subs->lock, flags);
-               subs->freqm = found;
-               spin_unlock_irqrestore(&subs->lock, flags);
        }
 
        return 0;
@@ -502,22 +472,17 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs,
                                       snd_pcm_runtime_t *runtime,
                                       struct urb *urb)
 {
-       int i;
-       unsigned int found;
-       unsigned char *cp = urb->transfer_buffer;
+       unsigned int f;
        unsigned long flags;
 
-       found = 0;
-       for (i = 0; i < urb->number_of_packets; i++, cp += 4) {
-               if (urb->iso_frame_desc[i].status ||
-                   urb->iso_frame_desc[i].actual_length < 4)
-                       continue;
-               found = combine_quad(cp) & 0x0fffffff;
-       }
-       if (found) {
-               spin_lock_irqsave(&subs->lock, flags);
-               subs->freqm = found;
-               spin_unlock_irqrestore(&subs->lock, flags);
+       if (urb->iso_frame_desc[0].status == 0 &&
+           urb->iso_frame_desc[0].actual_length == 4) {
+               f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
+               if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
+                       spin_lock_irqsave(&subs->lock, flags);
+                       subs->freqm = f;
+                       spin_unlock_irqrestore(&subs->lock, flags);
+               }
        }
 
        return 0;
@@ -600,6 +565,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
                /* set the buffer pointer */
                urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride;
                subs->hwptr += offs;
+               if (subs->hwptr == runtime->buffer_size)
+                       subs->hwptr = 0;
        }
        spin_unlock_irqrestore(&subs->lock, flags);
        urb->transfer_buffer_length = offs * stride;
@@ -892,10 +859,8 @@ static void release_urb_ctx(snd_urb_ctx_t *u)
                usb_free_urb(u->urb);
                u->urb = NULL;
        }
-       if (u->buf) {
-               kfree(u->buf);
-               u->buf = NULL;
-       }
+       kfree(u->buf);
+       u->buf = NULL;
 }
 
 /*
@@ -913,10 +878,8 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force)
                release_urb_ctx(&subs->dataurb[i]);
        for (i = 0; i < SYNC_URBS; i++)
                release_urb_ctx(&subs->syncurb[i]);
-       if (subs->tmpbuf) {
-               kfree(subs->tmpbuf);
-               subs->tmpbuf = NULL;
-       }
+       kfree(subs->tmpbuf);
+       subs->tmpbuf = NULL;
        subs->nurbs = 0;
 }
 
@@ -1039,22 +1002,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
                        snd_urb_ctx_t *u = &subs->syncurb[i];
                        u->index = i;
                        u->subs = subs;
-                       u->packets = nrpacks;
-                       u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+                       u->packets = 1;
+                       u->urb = usb_alloc_urb(1, GFP_KERNEL);
                        if (! u->urb) {
                                release_substream_urbs(subs, 0);
                                return -ENOMEM;
                        }
-                       u->urb->transfer_buffer = subs->syncbuf + i * nrpacks * 4;
-                       u->urb->transfer_buffer_length = nrpacks * 4;
+                       u->urb->transfer_buffer = subs->syncbuf + i * 4;
+                       u->urb->transfer_buffer_length = 4;
                        u->urb->dev = subs->dev;
                        u->urb->pipe = subs->syncpipe;
                        u->urb->transfer_flags = URB_ISO_ASAP;
-                       u->urb->number_of_packets = u->packets;
-                       if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
-                               u->urb->interval = 8;
-                       else
-                               u->urb->interval = 1;
+                       u->urb->number_of_packets = 1;
+                       u->urb->interval = 1 << subs->syncinterval;
                        u->urb->context = u;
                        u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb);
                }
@@ -1272,7 +1232,17 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
                        subs->syncpipe = usb_rcvisocpipe(dev, ep);
                else
                        subs->syncpipe = usb_sndisocpipe(dev, ep);
-               subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
+               if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
+                   get_endpoint(alts, 1)->bRefresh >= 1 &&
+                   get_endpoint(alts, 1)->bRefresh <= 9)
+                       subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
+               else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+                       subs->syncinterval = 1;
+               else if (get_endpoint(alts, 1)->bInterval >= 1 &&
+                        get_endpoint(alts, 1)->bInterval <= 16)
+                       subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
+               else
+                       subs->syncinterval = 3;
        }
 
        /* always fill max packet size */
@@ -1990,10 +1960,11 @@ static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffe
                        snd_iprintf(buffer, "%d ", subs->dataurb[i].packets);
                snd_iprintf(buffer, "]\n");
                snd_iprintf(buffer, "    Packet Size = %d\n", subs->curpacksize);
-               snd_iprintf(buffer, "    Momentary freq = %u Hz\n",
+               snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n",
                            snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
                            ? get_full_speed_hz(subs->freqm)
-                           : get_high_speed_hz(subs->freqm));
+                           : get_high_speed_hz(subs->freqm),
+                           subs->freqm >> 16, subs->freqm & 0xffff);
        } else {
                snd_iprintf(buffer, "  Status: Stop\n");
        }
@@ -2183,17 +2154,15 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
 /*
  * check if the device uses big-endian samples
  */
-static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
+static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp)
 {
-       /* M-Audio */
-       if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) {
-               /* Quattro: captured data only */
-               if (le16_to_cpu(dev->descriptor.idProduct) == 0x2001 &&
-                   fp->endpoint & USB_DIR_IN)
-                       return 1;
-               /* Audiophile USB */
-               if (le16_to_cpu(dev->descriptor.idProduct) == 0x2003)
+       switch (chip->usb_id) {
+       case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
+               if (fp->endpoint & USB_DIR_IN)
                        return 1;
+               break;
+       case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+               return 1;
        }
        return 0;
 }
@@ -2207,7 +2176,7 @@ static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
  * @format: the format tag (wFormatTag)
  * @fmt: the format type descriptor
  */
-static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp,
                                     int format, unsigned char *fmt)
 {
        int pcm_format;
@@ -2220,12 +2189,12 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
        switch (format) {
        case 0: /* some devices don't define this correctly... */
                snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
-                           dev->devnum, fp->iface, fp->altsetting);
+                           chip->dev->devnum, fp->iface, fp->altsetting);
                /* fall-through */
        case USB_AUDIO_FORMAT_PCM:
                if (sample_width > sample_bytes * 8) {
                        snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
-                                  dev->devnum, fp->iface, fp->altsetting,
+                                  chip->dev->devnum, fp->iface, fp->altsetting,
                                   sample_width, sample_bytes);
                }
                /* check the format byte size */
@@ -2234,13 +2203,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
                        pcm_format = SNDRV_PCM_FORMAT_S8;
                        break;
                case 2:
-                       if (is_big_endian_format(dev, fp))
+                       if (is_big_endian_format(chip, fp))
                                pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
                        else
                                pcm_format = SNDRV_PCM_FORMAT_S16_LE;
                        break;
                case 3:
-                       if (is_big_endian_format(dev, fp))
+                       if (is_big_endian_format(chip, fp))
                                pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
                        else
                                pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
@@ -2250,14 +2219,14 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
                        break;
                default:
                        snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
-                                  dev->devnum, fp->iface, fp->altsetting, sample_width, sample_bytes);
+                                  chip->dev->devnum, fp->iface,
+                                  fp->altsetting, sample_width, sample_bytes);
                        break;
                }
                break;
        case USB_AUDIO_FORMAT_PCM8:
                /* Dallas DS4201 workaround */
-               if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa &&
-                   le16_to_cpu(dev->descriptor.idProduct) == 0x4201)
+               if (chip->usb_id == USB_ID(0x04fa, 0x4201))
                        pcm_format = SNDRV_PCM_FORMAT_S8;
                else
                        pcm_format = SNDRV_PCM_FORMAT_U8;
@@ -2273,7 +2242,7 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
                break;
        default:
                snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n",
-                          dev->devnum, fp->iface, fp->altsetting, format);
+                          chip->dev->devnum, fp->iface, fp->altsetting, format);
                break;
        }
        return pcm_format;
@@ -2290,13 +2259,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
  * @offset: the start offset of descriptor pointing the rate type
  *          (7 for type I and II, 8 for type II)
  */
-static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp,
                                    unsigned char *fmt, int offset)
 {
        int nr_rates = fmt[offset];
        if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
                snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
-                                  dev->devnum, fp->iface, fp->altsetting);
+                                  chip->dev->devnum, fp->iface, fp->altsetting);
                return -1;
        }
 
@@ -2343,7 +2312,7 @@ static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *
 /*
  * parse the format type I and III descriptors
  */
-static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
                                int format, unsigned char *fmt)
 {
        int pcm_format;
@@ -2355,7 +2324,7 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
                 */
                pcm_format = SNDRV_PCM_FORMAT_S16_LE;
        } else {
-               pcm_format = parse_audio_format_i_type(dev, fp, format, fmt);
+               pcm_format = parse_audio_format_i_type(chip, fp, format, fmt);
                if (pcm_format < 0)
                        return -1;
        }
@@ -2363,16 +2332,16 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
        fp->channels = fmt[4];
        if (fp->channels < 1) {
                snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
-                          dev->devnum, fp->iface, fp->altsetting, fp->channels);
+                          chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
                return -1;
        }
-       return parse_audio_format_rates(dev, fp, fmt, 7);
+       return parse_audio_format_rates(chip, fp, fmt, 7);
 }
 
 /*
  * prase the format type II descriptor
  */
-static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
                                 int format, unsigned char *fmt)
 {
        int brate, framesize;
@@ -2387,7 +2356,7 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
                break;
        default:
                snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected.  processed as MPEG.\n",
-                          dev->devnum, fp->iface, fp->altsetting, format);
+                          chip->dev->devnum, fp->iface, fp->altsetting, format);
                fp->format = SNDRV_PCM_FORMAT_MPEG;
                break;
        }
@@ -2396,10 +2365,10 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
        framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */
        snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
        fp->frame_size = framesize;
-       return parse_audio_format_rates(dev, fp, fmt, 8); /* fmt[8..] sample rates */
+       return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */
 }
 
-static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
                              int format, unsigned char *fmt, int stream)
 {
        int err;
@@ -2407,29 +2376,30 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
        switch (fmt[3]) {
        case USB_FORMAT_TYPE_I:
        case USB_FORMAT_TYPE_III:
-               err = parse_audio_format_i(dev, fp, format, fmt);
+               err = parse_audio_format_i(chip, fp, format, fmt);
                break;
        case USB_FORMAT_TYPE_II:
-               err = parse_audio_format_ii(dev, fp, format, fmt);
+               err = parse_audio_format_ii(chip, fp, format, fmt);
                break;
        default:
                snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
-                          dev->devnum, fp->iface, fp->altsetting, fmt[3]);
+                          chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]);
                return -1;
        }
        fp->fmt_type = fmt[3];
        if (err < 0)
                return err;
 #if 1
-       /* FIXME: temporary hack for extigy */
+       /* FIXME: temporary hack for extigy/audigy 2 nx */
        /* extigy apparently supports sample rates other than 48k
         * but not in ordinary way.  so we enable only 48k atm.
         */
-       if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && 
-           le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
+       if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
+           chip->usb_id == USB_ID(0x041e, 0x3020)) {
                if (fmt[3] == USB_FORMAT_TYPE_I &&
                    stream == SNDRV_PCM_STREAM_PLAYBACK &&
-                   fp->rates != SNDRV_PCM_RATE_48000)
+                   fp->rates != SNDRV_PCM_RATE_48000 &&
+                   fp->rates != SNDRV_PCM_RATE_96000)
                        return -1; /* use 48k only */
        }
 #endif
@@ -2528,40 +2498,35 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
 
                /* some quirks for attributes here */
 
-               /* workaround for AudioTrak Optoplay */
-               if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 &&
-                   le16_to_cpu(dev->descriptor.idProduct) == 0x0053) {
+               switch (chip->usb_id) {
+               case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
                        /* Optoplay sets the sample rate attribute although
                         * it seems not supporting it in fact.
                         */
                        fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE;
-               }
-
-               /* workaround for M-Audio Audiophile USB */
-               if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763 &&
-                   le16_to_cpu(dev->descriptor.idProduct) == 0x2003) {
+                       break;
+               case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
+               case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
                        /* doesn't set the sample rate attribute, but supports it */
                        fp->attributes |= EP_CS_ATTR_SAMPLE_RATE;
-               }
-
+                       break;
+               case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
+               case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
+                                               an older model 77d:223) */
                /*
                 * plantronics headset and Griffin iMic have set adaptive-in
                 * although it's really not...
                 */
-               if ((le16_to_cpu(dev->descriptor.idVendor) == 0x047f &&
-                    le16_to_cpu(dev->descriptor.idProduct) == 0x0ca1) ||
-                   /* Griffin iMic (note that there is an older model 77d:223) */
-                   (le16_to_cpu(dev->descriptor.idVendor) == 0x077d &&
-                    le16_to_cpu(dev->descriptor.idProduct) == 0x07af)) {
                        fp->ep_attr &= ~EP_ATTR_MASK;
                        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
                                fp->ep_attr |= EP_ATTR_ADAPTIVE;
                        else
                                fp->ep_attr |= EP_ATTR_SYNC;
+                       break;
                }
 
                /* ok, let's parse further... */
-               if (parse_audio_format(dev, fp, format, fmt, stream) < 0) {
+               if (parse_audio_format(chip, fp, format, fmt, stream) < 0) {
                        kfree(fp->rate_table);
                        kfree(fp);
                        continue;
@@ -2587,7 +2552,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
  * disconnect streams
  * called from snd_usb_audio_disconnect()
  */
-static void snd_usb_stream_disconnect(struct list_head *head, struct usb_driver *driver)
+static void snd_usb_stream_disconnect(struct list_head *head)
 {
        int idx;
        snd_usb_stream_t *as;
@@ -2796,7 +2761,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
                        .type = QUIRK_MIDI_FIXED_ENDPOINT,
                        .data = &ua25_ep
                };
-               if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b)
+               if (chip->usb_id == USB_ID(0x0582, 0x002b))
                        return snd_usb_create_midi_interface(chip, iface,
                                                             &ua700_quirk);
                else
@@ -2959,6 +2924,25 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
        return 0;
 }
 
+static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
+{
+#if 0
+       /* TODO: enable this when high speed synchronization actually works */
+       u8 buf = 1;
+
+       snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+                       0, 0, &buf, 1, 1000);
+       if (buf == 0) {
+               snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29,
+                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+                               1, 2000, NULL, 0, 1000);
+               return -ENODEV;
+       }
+#endif
+       return 0;
+}
+
 
 /*
  * audio-interface quirks
@@ -3015,8 +2999,8 @@ static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *bu
        snd_usb_audio_t *chip = entry->private_data;
        if (! chip->shutdown)
                snd_iprintf(buffer, "%04x:%04x\n", 
-                           le16_to_cpu(chip->dev->descriptor.idVendor),
-                           le16_to_cpu(chip->dev->descriptor.idProduct));
+                           USB_ID_VENDOR(chip->usb_id),
+                           USB_ID_PRODUCT(chip->usb_id));
 }
 
 static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
@@ -3086,8 +3070,11 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
        chip->index = idx;
        chip->dev = dev;
        chip->card = card;
+       chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
+                             le16_to_cpu(dev->descriptor.idProduct));
        INIT_LIST_HEAD(&chip->pcm_list);
        INIT_LIST_HEAD(&chip->midi_list);
+       INIT_LIST_HEAD(&chip->mixer_list);
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
                snd_usb_audio_free(chip);
@@ -3097,8 +3084,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 
        strcpy(card->driver, "USB-Audio");
        sprintf(component, "USB%04x:%04x",
-               le16_to_cpu(dev->descriptor.idVendor),
-               le16_to_cpu(dev->descriptor.idProduct));
+               USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
        snd_component_add(card, component);
 
        /* retrieve the device string as shortname */
@@ -3110,8 +3096,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
                               card->shortname, sizeof(card->shortname)) <= 0) {
                        /* no name available from anywhere, so use ID */
                        sprintf(card->shortname, "USB Device %#04x:%#04x",
-                               le16_to_cpu(dev->descriptor.idVendor),
-                               le16_to_cpu(dev->descriptor.idProduct));
+                               USB_ID_VENDOR(chip->usb_id),
+                               USB_ID_PRODUCT(chip->usb_id));
                }
        }
 
@@ -3142,8 +3128,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 
        snd_usb_audio_create_proc(chip);
 
-       snd_card_set_dev(card, &dev->dev);
-
        *rchip = chip;
        return 0;
 }
@@ -3169,21 +3153,28 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
        snd_usb_audio_t *chip;
        struct usb_host_interface *alts;
        int ifnum;
+       u32 id;
 
        alts = &intf->altsetting[0];
        ifnum = get_iface_desc(alts)->bInterfaceNumber;
+       id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
+                   le16_to_cpu(dev->descriptor.idProduct));
 
        if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
                goto __err_val;
 
        /* SB Extigy needs special boot-up sequence */
        /* if more models come, this will go to the quirk list. */
-       if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && 
-           le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
+       if (id == USB_ID(0x041e, 0x3000)) {
                if (snd_usb_extigy_boot_quirk(dev, intf) < 0)
                        goto __err_val;
                config = dev->actconfig;
        }
+       /* SB Audigy 2 NX needs its own boot-up magic, too */
+       if (id == USB_ID(0x041e, 0x3020)) {
+               if (snd_usb_audigy2nx_boot_quirk(dev) < 0)
+                       goto __err_val;
+       }
 
        /*
         * found a config.  now register to ALSA
@@ -3213,11 +3204,12 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
                }
                for (i = 0; i < SNDRV_CARDS; i++)
                        if (enable[i] && ! usb_chip[i] &&
-                           (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) &&
-                           (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) {
+                           (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
+                           (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
                                if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
                                        goto __error;
                                }
+                               snd_card_set_dev(chip->card, &intf->dev);
                                break;
                        }
                if (! chip) {
@@ -3281,11 +3273,15 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
                snd_card_disconnect(card);
                /* release the pcm resources */
                list_for_each(p, &chip->pcm_list) {
-                       snd_usb_stream_disconnect(p, &usb_audio_driver);
+                       snd_usb_stream_disconnect(p);
                }
                /* release the midi resources */
                list_for_each(p, &chip->midi_list) {
-                       snd_usbmidi_disconnect(p, &usb_audio_driver);
+                       snd_usbmidi_disconnect(p);
+               }
+               /* release mixer resources */
+               list_for_each(p, &chip->mixer_list) {
+                       snd_usb_mixer_disconnect(p);
                }
                usb_chip[chip->index] = NULL;
                up(&register_mutex);
index eecbf19fcb6fc7ed887b6de6eb82e41923f86c1d..aedb42aaa74947e8bbf992fa2e5e873aa2fa01ff 100644 (file)
 /* maximum number of endpoints per interface */
 #define MIDI_MAX_ENDPOINTS 2
 
+/* handling of USB vendor/product ID pairs as 32-bit numbers */
+#define USB_ID(vendor, product) (((vendor) << 16) | (product))
+#define USB_ID_VENDOR(id) ((id) >> 16)
+#define USB_ID_PRODUCT(id) ((u16)(id))
+
 /*
  */
 
@@ -127,6 +132,7 @@ struct snd_usb_audio {
        int index;
        struct usb_device *dev;
        snd_card_t *card;
+       u32 usb_id;
        int shutdown;
        int num_interfaces;
 
@@ -136,7 +142,7 @@ struct snd_usb_audio {
        struct list_head midi_list;     /* list of midi interfaces */
        int next_midi_device;
 
-       unsigned int ignore_ctl_error;  /* for mixer */
+       struct list_head mixer_list;    /* list of mixer interfaces */
 };
 
 /*
@@ -219,11 +225,12 @@ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsub
 int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
 
 int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
+void snd_usb_mixer_disconnect(struct list_head *p);
 
 int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
 void snd_usbmidi_input_stop(struct list_head* p);
 void snd_usbmidi_input_start(struct list_head* p);
-void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver);
+void snd_usbmidi_disconnect(struct list_head *p);
 
 /*
  * retrieve usb_interface descriptor from the host interface
index 5d32857ff9554b0c4d7b8c9dbc037f67b241508d..bee70068dce083726a13a4c18481fe7abec11726 100644 (file)
@@ -912,7 +912,7 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi)
 /*
  * Unlinks all URBs (must be done before the usb_device is deleted).
  */
-void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
+void snd_usbmidi_disconnect(struct list_head* p)
 {
        snd_usb_midi_t* umidi;
        int i;
@@ -955,88 +955,87 @@ static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi
  * such as internal control or synthesizer ports.
  */
 static struct {
-       __u16 vendor;
-       __u16 product;
+       u32 id;
        int port;
        const char *name_format;
 } snd_usbmidi_port_names[] = {
        /* Roland UA-100 */
-       {0x0582, 0x0000, 2, "%s Control"},
+       { USB_ID(0x0582, 0x0000), 2, "%s Control" },
        /* Roland SC-8850 */
-       {0x0582, 0x0003, 0, "%s Part A"},
-       {0x0582, 0x0003, 1, "%s Part B"},
-       {0x0582, 0x0003, 2, "%s Part C"},
-       {0x0582, 0x0003, 3, "%s Part D"},
-       {0x0582, 0x0003, 4, "%s MIDI 1"},
-       {0x0582, 0x0003, 5, "%s MIDI 2"},
+       { USB_ID(0x0582, 0x0003), 0, "%s Part A" },
+       { USB_ID(0x0582, 0x0003), 1, "%s Part B" },
+       { USB_ID(0x0582, 0x0003), 2, "%s Part C" },
+       { USB_ID(0x0582, 0x0003), 3, "%s Part D" },
+       { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" },
+       { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" },
        /* Roland U-8 */
-       {0x0582, 0x0004, 0, "%s MIDI"},
-       {0x0582, 0x0004, 1, "%s Control"},
+       { USB_ID(0x0582, 0x0004), 0, "%s MIDI" },
+       { USB_ID(0x0582, 0x0004), 1, "%s Control" },
        /* Roland SC-8820 */
-       {0x0582, 0x0007, 0, "%s Part A"},
-       {0x0582, 0x0007, 1, "%s Part B"},
-       {0x0582, 0x0007, 2, "%s MIDI"},
+       { USB_ID(0x0582, 0x0007), 0, "%s Part A" },
+       { USB_ID(0x0582, 0x0007), 1, "%s Part B" },
+       { USB_ID(0x0582, 0x0007), 2, "%s MIDI" },
        /* Roland SK-500 */
-       {0x0582, 0x000b, 0, "%s Part A"},
-       {0x0582, 0x000b, 1, "%s Part B"},
-       {0x0582, 0x000b, 2, "%s MIDI"},
+       { USB_ID(0x0582, 0x000b), 0, "%s Part A" },
+       { USB_ID(0x0582, 0x000b), 1, "%s Part B" },
+       { USB_ID(0x0582, 0x000b), 2, "%s MIDI" },
        /* Roland SC-D70 */
-       {0x0582, 0x000c, 0, "%s Part A"},
-       {0x0582, 0x000c, 1, "%s Part B"},
-       {0x0582, 0x000c, 2, "%s MIDI"},
+       { USB_ID(0x0582, 0x000c), 0, "%s Part A" },
+       { USB_ID(0x0582, 0x000c), 1, "%s Part B" },
+       { USB_ID(0x0582, 0x000c), 2, "%s MIDI" },
        /* Edirol UM-880 */
-       {0x0582, 0x0014, 8, "%s Control"},
+       { USB_ID(0x0582, 0x0014), 8, "%s Control" },
        /* Edirol SD-90 */
-       {0x0582, 0x0016, 0, "%s Part A"},
-       {0x0582, 0x0016, 1, "%s Part B"},
-       {0x0582, 0x0016, 2, "%s MIDI 1"},
-       {0x0582, 0x0016, 3, "%s MIDI 2"},
+       { USB_ID(0x0582, 0x0016), 0, "%s Part A" },
+       { USB_ID(0x0582, 0x0016), 1, "%s Part B" },
+       { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" },
+       { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" },
        /* Edirol UM-550 */
-       {0x0582, 0x0023, 5, "%s Control"},
+       { USB_ID(0x0582, 0x0023), 5, "%s Control" },
        /* Edirol SD-20 */
-       {0x0582, 0x0027, 0, "%s Part A"},
-       {0x0582, 0x0027, 1, "%s Part B"},
-       {0x0582, 0x0027, 2, "%s MIDI"},
+       { USB_ID(0x0582, 0x0027), 0, "%s Part A" },
+       { USB_ID(0x0582, 0x0027), 1, "%s Part B" },
+       { USB_ID(0x0582, 0x0027), 2, "%s MIDI" },
        /* Edirol SD-80 */
-       {0x0582, 0x0029, 0, "%s Part A"},
-       {0x0582, 0x0029, 1, "%s Part B"},
-       {0x0582, 0x0029, 2, "%s MIDI 1"},
-       {0x0582, 0x0029, 3, "%s MIDI 2"},
+       { USB_ID(0x0582, 0x0029), 0, "%s Part A" },
+       { USB_ID(0x0582, 0x0029), 1, "%s Part B" },
+       { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" },
+       { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" },
        /* Edirol UA-700 */
-       {0x0582, 0x002b, 0, "%s MIDI"},
-       {0x0582, 0x002b, 1, "%s Control"},
+       { USB_ID(0x0582, 0x002b), 0, "%s MIDI" },
+       { USB_ID(0x0582, 0x002b), 1, "%s Control" },
        /* Roland VariOS */
-       {0x0582, 0x002f, 0, "%s MIDI"},
-       {0x0582, 0x002f, 1, "%s External MIDI"},
-       {0x0582, 0x002f, 2, "%s Sync"},
+       { USB_ID(0x0582, 0x002f), 0, "%s MIDI" },
+       { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" },
+       { USB_ID(0x0582, 0x002f), 2, "%s Sync" },
        /* Edirol PCR */
-       {0x0582, 0x0033, 0, "%s MIDI"},
-       {0x0582, 0x0033, 1, "%s 1"},
-       {0x0582, 0x0033, 2, "%s 2"},
+       { USB_ID(0x0582, 0x0033), 0, "%s MIDI" },
+       { USB_ID(0x0582, 0x0033), 1, "%s 1" },
+       { USB_ID(0x0582, 0x0033), 2, "%s 2" },
        /* BOSS GS-10 */
-       {0x0582, 0x003b, 0, "%s MIDI"},
-       {0x0582, 0x003b, 1, "%s Control"},
+       { USB_ID(0x0582, 0x003b), 0, "%s MIDI" },
+       { USB_ID(0x0582, 0x003b), 1, "%s Control" },
        /* Edirol UA-1000 */
-       {0x0582, 0x0044, 0, "%s MIDI"},
-       {0x0582, 0x0044, 1, "%s Control"},
+       { USB_ID(0x0582, 0x0044), 0, "%s MIDI" },
+       { USB_ID(0x0582, 0x0044), 1, "%s Control" },
        /* Edirol UR-80 */
-       {0x0582, 0x0048, 0, "%s MIDI"},
-       {0x0582, 0x0048, 1, "%s 1"},
-       {0x0582, 0x0048, 2, "%s 2"},
+       { USB_ID(0x0582, 0x0048), 0, "%s MIDI" },
+       { USB_ID(0x0582, 0x0048), 1, "%s 1" },
+       { USB_ID(0x0582, 0x0048), 2, "%s 2" },
        /* Edirol PCR-A */
-       {0x0582, 0x004d, 0, "%s MIDI"},
-       {0x0582, 0x004d, 1, "%s 1"},
-       {0x0582, 0x004d, 2, "%s 2"},
+       { USB_ID(0x0582, 0x004d), 0, "%s MIDI" },
+       { USB_ID(0x0582, 0x004d), 1, "%s 1" },
+       { USB_ID(0x0582, 0x004d), 2, "%s 2" },
        /* M-Audio MidiSport 8x8 */
-       {0x0763, 0x1031, 8, "%s Control"},
-       {0x0763, 0x1033, 8, "%s Control"},
+       { USB_ID(0x0763, 0x1031), 8, "%s Control" },
+       { USB_ID(0x0763, 0x1033), 8, "%s Control" },
        /* MOTU Fastlane */
-       {0x07fd, 0x0001, 0, "%s MIDI A"},
-       {0x07fd, 0x0001, 1, "%s MIDI B"},
+       { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" },
+       { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" },
        /* Emagic Unitor8/AMT8/MT4 */
-       {0x086a, 0x0001, 8, "%s Broadcast"},
-       {0x086a, 0x0002, 8, "%s Broadcast"},
-       {0x086a, 0x0003, 4, "%s Broadcast"},
+       { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" },
+       { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" },
+       { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" },
 };
 
 static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
@@ -1044,7 +1043,6 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
                                       snd_rawmidi_substream_t** rsubstream)
 {
        int i;
-       __u16 vendor, product;
        const char *name_format;
 
        snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number);
@@ -1055,11 +1053,8 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
 
        /* TODO: read port name from jack descriptor */
        name_format = "%s MIDI %d";
-       vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor);
-       product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct);
        for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
-               if (snd_usbmidi_port_names[i].vendor == vendor &&
-                   snd_usbmidi_port_names[i].product == product &&
+               if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id &&
                    snd_usbmidi_port_names[i].port == number) {
                        name_format = snd_usbmidi_port_names[i].name_format;
                        break;
@@ -1226,9 +1221,12 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi,
        struct usb_endpoint_descriptor* epd;
        int i, out_eps = 0, in_eps = 0;
 
-       if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582)
+       if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582)
                snd_usbmidi_switch_roland_altsetting(umidi);
 
+       if (endpoint[0].out_ep || endpoint[0].in_ep)
+               return 0;       
+
        intf = umidi->iface;
        if (!intf || intf->num_altsetting < 1)
                return -ENOENT;
index 5f1906915aa626f66cd6e527e2484d92772c6530..e73c1c9d3e735a50c9b1edc56c31830c600f28b5 100644 (file)
 #include <linux/usb.h>
 #include <sound/core.h>
 #include <sound/control.h>
+#include <sound/hwdep.h>
+#include <sound/info.h>
 
 #include "usbaudio.h"
 
-
 /*
  */
 
@@ -50,6 +51,31 @@ typedef struct usb_audio_term usb_audio_term_t;
 typedef struct usb_mixer_elem_info usb_mixer_elem_info_t;
 
 
+struct usb_mixer_interface {
+       snd_usb_audio_t *chip;
+       unsigned int ctrlif;
+       struct list_head list;
+       unsigned int ignore_ctl_error;
+       struct urb *urb;
+       usb_mixer_elem_info_t **id_elems; /* array[256], indexed by unit id */
+
+       /* Sound Blaster remote control stuff */
+       enum {
+               RC_NONE,
+               RC_EXTIGY,
+               RC_AUDIGY2NX,
+       } rc_type;
+       unsigned long rc_hwdep_open;
+       u32 rc_code;
+       wait_queue_head_t rc_waitq;
+       struct urb *rc_urb;
+       struct usb_ctrlrequest *rc_setup_packet;
+       u8 rc_buffer[6];
+
+       u8 audigy2nx_leds[3];
+};
+
+
 struct usb_audio_term {
        int id;
        int type;
@@ -62,26 +88,26 @@ struct usbmix_name_map;
 
 struct usb_mixer_build {
        snd_usb_audio_t *chip;
+       struct usb_mixer_interface *mixer;
        unsigned char *buffer;
        unsigned int buflen;
-       unsigned int ctrlif;
-       unsigned short vendor;
-       unsigned short product;
-       DECLARE_BITMAP(unitbitmap, 32*32);
+       DECLARE_BITMAP(unitbitmap, 256);
        usb_audio_term_t oterm;
        const struct usbmix_name_map *map;
+       const struct usbmix_selector_map *selector_map;
 };
 
 struct usb_mixer_elem_info {
-       snd_usb_audio_t *chip;
-       unsigned int ctrlif;
+       struct usb_mixer_interface *mixer;
+       usb_mixer_elem_info_t *next_id_elem; /* list of controls with same id */
+       snd_ctl_elem_id_t *elem_id;
        unsigned int id;
        unsigned int control;   /* CS or ICN (high byte) */
        unsigned int cmask; /* channel mask bitmap: 0 = master */
        int channels;
        int val_type;
        int min, max, res;
-       unsigned int initialized: 1;
+       u8 initialized;
 };
 
 
@@ -187,6 +213,21 @@ static int check_ignored_ctl(mixer_build_t *state, int unitid, int control)
        return 0;
 }
 
+/* get the mapped selector source name */
+static int check_mapped_selector_name(mixer_build_t *state, int unitid,
+                                     int index, char *buf, int buflen)
+{
+       const struct usbmix_selector_map *p;
+
+       if (! state->selector_map)
+               return 0;
+       for (p = state->selector_map; p->id; p++) {
+               if (p->id == unitid && index < p->count)
+                       return strlcpy(buf, p->names[index], buflen);
+       }
+       return 0;
+}
+
 /*
  * find an audio control unit with the given unit id
  */
@@ -301,16 +342,18 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
        int timeout = 10;
 
        while (timeout-- > 0) {
-               if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0),
+               if (snd_usb_ctl_msg(cval->mixer->chip->dev,
+                                   usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
                                    request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                                   validx, cval->ctrlif | (cval->id << 8),
+                                   validx, cval->mixer->ctrlif | (cval->id << 8),
                                    buf, val_len, 100) >= 0) {
                        *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
                        return 0;
                }
        }
-       snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type);
+       snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
+                   request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
        return -EINVAL;
 }
 
@@ -339,13 +382,15 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
        buf[0] = value_set & 0xff;
        buf[1] = (value_set >> 8) & 0xff;
        while (timeout -- > 0)
-               if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0),
+               if (snd_usb_ctl_msg(cval->mixer->chip->dev,
+                                   usb_sndctrlpipe(cval->mixer->chip->dev, 0),
                                    request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                                   validx, cval->ctrlif | (cval->id << 8),
+                                   validx, cval->mixer->ctrlif | (cval->id << 8),
                                    buf, val_len, 100) >= 0)
                        return 0;
-       snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
+       snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
+                   request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
        return -EINVAL;
 }
 
@@ -385,16 +430,22 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou
  * if failed, give up and free the control instance.
  */
 
-static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl)
+static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl)
 {
+       usb_mixer_elem_info_t *cval = kctl->private_data;
        int err;
-       while (snd_ctl_find_id(card, &kctl->id))
+
+       while (snd_ctl_find_id(state->chip->card, &kctl->id))
                kctl->id.index++;
-       if ((err = snd_ctl_add(card, kctl)) < 0) {
+       if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) {
                snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
                snd_ctl_free_one(kctl);
+               return err;
        }
-       return err;
+       cval->elem_id = &kctl->id;
+       cval->next_id_elem = state->mixer->id_elems[cval->id];
+       state->mixer->id_elems[cval->id] = cval;
+       return 0;
 }
 
 
@@ -572,10 +623,8 @@ static struct usb_feature_control_info audio_feature_info[] = {
 /* private_free callback */
 static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
 {
-       if (kctl->private_data) {
-               kfree(kctl->private_data);
-               kctl->private_data = NULL;
-       }
+       kfree(kctl->private_data);
+       kctl->private_data = NULL;
 }
 
 
@@ -608,7 +657,8 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min)
                }
                if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
                    get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
-                       snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id);
+                       snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
+                                  cval->id, cval->mixer->ctrlif, cval->control, cval->id);
                        return -EINVAL;
                }
                if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -668,7 +718,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
                        if (cval->cmask & (1 << c)) {
                                err = get_cur_mix_value(cval, c + 1, &val);
                                if (err < 0) {
-                                       if (cval->chip->ignore_ctl_error) {
+                                       if (cval->mixer->ignore_ctl_error) {
                                                ucontrol->value.integer.value[0] = cval->min;
                                                return 0;
                                        }
@@ -684,7 +734,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
                /* master channel */
                err = get_cur_mix_value(cval, 0, &val);
                if (err < 0) {
-                       if (cval->chip->ignore_ctl_error) {
+                       if (cval->mixer->ignore_ctl_error) {
                                ucontrol->value.integer.value[0] = cval->min;
                                return 0;
                        }
@@ -710,7 +760,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
                        if (cval->cmask & (1 << c)) {
                                err = get_cur_mix_value(cval, c + 1, &oval);
                                if (err < 0) {
-                                       if (cval->chip->ignore_ctl_error)
+                                       if (cval->mixer->ignore_ctl_error)
                                                return 0;
                                        return err;
                                }
@@ -727,7 +777,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
        } else {
                /* master channel */
                err = get_cur_mix_value(cval, 0, &oval);
-               if (err < 0 && cval->chip->ignore_ctl_error)
+               if (err < 0 && cval->mixer->ignore_ctl_error)
                        return 0;
                if (err < 0)
                        return err;
@@ -779,8 +829,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
                snd_printk(KERN_ERR "cannot malloc kcontrol\n");
                return;
        }
-       cval->chip = state->chip;
-       cval->ctrlif = state->ctrlif;
+       cval->mixer = state->mixer;
        cval->id = unitid;
        cval->control = control;
        cval->cmask = ctl_mask;
@@ -855,16 +904,21 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
        /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
        /* is not very clear from datasheets */
        /* I hope that the min value is -15360 for newer firmware --jk */
-       if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) ||
-            (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") &&
-            cval->min == -15616) {
-               snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n");
-               cval->max = -256;
+       switch (state->chip->usb_id) {
+       case USB_ID(0x0471, 0x0101):
+       case USB_ID(0x0471, 0x0104):
+       case USB_ID(0x0471, 0x0105):
+       case USB_ID(0x0672, 0x1041):
+               if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
+                   cval->min == -15616) {
+                       snd_printk("using volume control quirk for the UDA1321/N101 chip\n");
+                       cval->max = -256;
+               }
        }
 
        snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
                    cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
-       add_control_to_empty(state->chip->card, kctl);
+       add_control_to_empty(state, kctl);
 }
 
 
@@ -947,8 +1001,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
        if (! cval)
                return;
 
-       cval->chip = state->chip;
-       cval->ctrlif = state->ctrlif;
+       cval->mixer = state->mixer;
        cval->id = unitid;
        cval->control = in_ch + 1; /* based on 1 */
        cval->val_type = USB_MIXER_S16;
@@ -979,7 +1032,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
 
        snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
                    cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
-       add_control_to_empty(state->chip->card, kctl);
+       add_control_to_empty(state, kctl);
 }
 
 
@@ -1042,7 +1095,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
        int err, val;
 
        err = get_cur_ctl_value(cval, cval->control << 8, &val);
-       if (err < 0 && cval->chip->ignore_ctl_error) {
+       if (err < 0 && cval->mixer->ignore_ctl_error) {
                ucontrol->value.integer.value[0] = cval->min;
                return 0;
        }
@@ -1061,7 +1114,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 
        err = get_cur_ctl_value(cval, cval->control << 8, &oval);
        if (err < 0) {
-               if (cval->chip->ignore_ctl_error)
+               if (cval->mixer->ignore_ctl_error)
                        return 0;
                return err;
        }
@@ -1179,9 +1232,6 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
        }
 
        type = combine_word(&dsc[4]);
-       if (! type)
-               return 0; /* undefined? */
-
        for (info = list; info && info->type; info++)
                if (info->type == type)
                        break;
@@ -1199,8 +1249,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
                        snd_printk(KERN_ERR "cannot malloc kcontrol\n");
                        return -ENOMEM;
                }
-               cval->chip = state->chip;
-               cval->ctrlif = state->ctrlif;
+               cval->mixer = state->mixer;
                cval->id = unitid;
                cval->control = valinfo->control;
                cval->val_type = valinfo->val_type;
@@ -1241,7 +1290,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
 
                snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
                            cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
-               if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
+               if ((err = add_control_to_empty(state, kctl)) < 0)
                        return err;
        }
        return 0;
@@ -1289,7 +1338,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 
        err = get_cur_ctl_value(cval, 0, &val);
        if (err < 0) {
-               if (cval->chip->ignore_ctl_error) {
+               if (cval->mixer->ignore_ctl_error) {
                        ucontrol->value.enumerated.item[0] = 0;
                        return 0;
                }
@@ -1308,7 +1357,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 
        err = get_cur_ctl_value(cval, 0, &oval);
        if (err < 0) {
-               if (cval->chip->ignore_ctl_error)
+               if (cval->mixer->ignore_ctl_error)
                        return 0;
                return err;
        }
@@ -1386,8 +1435,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
                snd_printk(KERN_ERR "cannot malloc kcontrol\n");
                return -ENOMEM;
        }
-       cval->chip = state->chip;
-       cval->ctrlif = state->ctrlif;
+       cval->mixer = state->mixer;
        cval->id = unitid;
        cval->val_type = USB_MIXER_U8;
        cval->channels = 1;
@@ -1415,7 +1463,9 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
                        kfree(cval);
                        return -ENOMEM;
                }
-               if (check_input_term(state, desc[5 + i], &iterm) >= 0)
+               len = check_mapped_selector_name(state, unitid, i, namelist[i],
+                                                MAX_ITEM_NAME_LEN);
+               if (! len && check_input_term(state, desc[5 + i], &iterm) >= 0)
                        len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0);
                if (! len)
                        sprintf(namelist[i], "Input %d", i);
@@ -1450,7 +1500,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
 
        snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
                    cval->id, kctl->id.name, num_ins);
-       if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
+       if ((err = add_control_to_empty(state, kctl)) < 0)
                return err;
 
        return 0;
@@ -1493,41 +1543,55 @@ static int parse_audio_unit(mixer_build_t *state, int unitid)
        }
 }
 
+static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
+{
+       kfree(mixer->id_elems);
+       if (mixer->urb) {
+               kfree(mixer->urb->transfer_buffer);
+               usb_free_urb(mixer->urb);
+       }
+       if (mixer->rc_urb)
+               usb_free_urb(mixer->rc_urb);
+       kfree(mixer->rc_setup_packet);
+       kfree(mixer);
+}
+
+static int snd_usb_mixer_dev_free(snd_device_t *device)
+{
+       struct usb_mixer_interface *mixer = device->device_data;
+       snd_usb_mixer_free(mixer);
+       return 0;
+}
+
 /*
  * create mixer controls
  *
  * walk through all OUTPUT_TERMINAL descriptors to search for mixers
  */
-int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
+static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
 {
        unsigned char *desc;
        mixer_build_t state;
        int err;
        const struct usbmix_ctl_map *map;
-       struct usb_device_descriptor *dev = &chip->dev->descriptor;
-       struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
-
-       strcpy(chip->card->mixername, "USB Mixer");
+       struct usb_host_interface *hostif;
 
+       hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
        memset(&state, 0, sizeof(state));
-       state.chip = chip;
+       state.chip = mixer->chip;
+       state.mixer = mixer;
        state.buffer = hostif->extra;
        state.buflen = hostif->extralen;
-       state.ctrlif = ctrlif;
-       state.vendor = le16_to_cpu(dev->idVendor);
-       state.product = le16_to_cpu(dev->idProduct);
 
        /* check the mapping table */
-       for (map = usbmix_ctl_maps; map->vendor; map++) {
-               if (map->vendor == state.vendor && map->product == state.product) {
+       for (map = usbmix_ctl_maps; map->id; map++) {
+               if (map->id == state.chip->usb_id) {
                        state.map = map->map;
-                       chip->ignore_ctl_error = map->ignore_ctl_error;
+                       state.selector_map = map->selector_map;
+                       mixer->ignore_ctl_error = map->ignore_ctl_error;
                        break;
                }
        }
-#ifdef IGNORE_CTL_ERROR
-       chip->ignore_ctl_error = 1;
-#endif
 
        desc = NULL;
        while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) {
@@ -1543,3 +1607,393 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
        }
        return 0;
 }
+
+static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
+                                   int unitid)
+{
+       usb_mixer_elem_info_t *info;
+
+       for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem)
+               snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+                              info->elem_id);
+}
+
+static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
+                                       int unitid)
+{
+       if (mixer->rc_type == RC_NONE)
+               return;
+       /* unit ids specific to Extigy/Audigy 2 NX: */
+       switch (unitid) {
+       case 0: /* remote control */
+               mixer->rc_urb->dev = mixer->chip->dev;
+               usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
+               break;
+       case 4: /* digital in jack */
+       case 7: /* line in jacks */
+       case 19: /* speaker out jacks */
+       case 20: /* headphones out jack */
+               break;
+       default:
+               snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
+               break;
+       }
+}
+
+static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_mixer_interface *mixer = urb->context;
+
+       if (urb->status == 0) {
+               u8 *buf = urb->transfer_buffer;
+               int i;
+
+               for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) {
+                       snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n",
+                                  buf[0], buf[1]);
+                       /* ignore any notifications not from the control interface */
+                       if ((buf[0] & 0x0f) != 0)
+                               continue;
+                       if (!(buf[0] & 0x40))
+                               snd_usb_mixer_notify_id(mixer, buf[1]);
+                       else
+                               snd_usb_mixer_memory_change(mixer, buf[1]);
+               }
+       }
+       if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
+               urb->dev = mixer->chip->dev;
+               usb_submit_urb(urb, GFP_ATOMIC);
+       }
+}
+
+/* create the handler for the optional status interrupt endpoint */
+static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
+{
+       struct usb_host_interface *hostif;
+       struct usb_endpoint_descriptor *ep;
+       void *transfer_buffer;
+       int buffer_length;
+       unsigned int epnum;
+
+       hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
+       /* we need one interrupt input endpoint */
+       if (get_iface_desc(hostif)->bNumEndpoints < 1)
+               return 0;
+       ep = get_endpoint(hostif, 0);
+       if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN ||
+           (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+               return 0;
+
+       epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       buffer_length = le16_to_cpu(ep->wMaxPacketSize);
+       transfer_buffer = kmalloc(buffer_length, GFP_KERNEL);
+       if (!transfer_buffer)
+               return -ENOMEM;
+       mixer->urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!mixer->urb) {
+               kfree(transfer_buffer);
+               return -ENOMEM;
+       }
+       usb_fill_int_urb(mixer->urb, mixer->chip->dev,
+                        usb_rcvintpipe(mixer->chip->dev, epnum),
+                        transfer_buffer, buffer_length,
+                        snd_usb_mixer_status_complete, mixer, ep->bInterval);
+       usb_submit_urb(mixer->urb, GFP_KERNEL);
+       return 0;
+}
+
+static void snd_usb_soundblaster_remote_complete(struct urb *urb,
+                                                struct pt_regs *regs)
+{
+       struct usb_mixer_interface *mixer = urb->context;
+       /*
+        * format of remote control data:
+        * Extigy:      xx 00
+        * Audigy 2 NX: 06 80 xx 00 00 00
+        */
+       int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2;
+       u32 code;
+
+       if (urb->status < 0 || urb->actual_length <= offset)
+               return;
+       code = mixer->rc_buffer[offset];
+       /* the Mute button actually changes the mixer control */
+       if (code == 13)
+               snd_usb_mixer_notify_id(mixer, 18);
+       mixer->rc_code = code;
+       wmb();
+       wake_up(&mixer->rc_waitq);
+}
+
+static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file)
+{
+       struct usb_mixer_interface *mixer = hw->private_data;
+
+       if (test_and_set_bit(0, &mixer->rc_hwdep_open))
+               return -EBUSY;
+       return 0;
+}
+
+static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file)
+{
+       struct usb_mixer_interface *mixer = hw->private_data;
+
+       clear_bit(0, &mixer->rc_hwdep_open);
+       smp_mb__after_clear_bit();
+       return 0;
+}
+
+static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf,
+                                    long count, loff_t *offset)
+{
+       struct usb_mixer_interface *mixer = hw->private_data;
+       int err;
+       u32 rc_code;
+
+       if (count != 1 && count != 4)
+               return -EINVAL;
+       err = wait_event_interruptible(mixer->rc_waitq,
+                                      (rc_code = xchg(&mixer->rc_code, 0)) != 0);
+       if (err == 0) {
+               if (count == 1)
+                       err = put_user(rc_code, buf);
+               else
+                       err = put_user(rc_code, (u32 __user *)buf);
+       }
+       return err < 0 ? err : count;
+}
+
+static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file,
+                                           poll_table *wait)
+{
+       struct usb_mixer_interface *mixer = hw->private_data;
+
+       poll_wait(file, &mixer->rc_waitq, wait);
+       return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
+}
+
+static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
+{
+       snd_hwdep_t *hwdep;
+       int err, len;
+
+       switch (mixer->chip->usb_id) {
+       case USB_ID(0x041e, 0x3000):
+               mixer->rc_type = RC_EXTIGY;
+               len = 2;
+               break;
+       case USB_ID(0x041e, 0x3020):
+               mixer->rc_type = RC_AUDIGY2NX;
+               len = 6;
+               break;
+       default:
+               return 0;
+       }
+
+       init_waitqueue_head(&mixer->rc_waitq);
+       err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
+       if (err < 0)
+               return err;
+       snprintf(hwdep->name, sizeof(hwdep->name),
+                "%s remote control", mixer->chip->card->shortname);
+       hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
+       hwdep->private_data = mixer;
+       hwdep->ops.read = snd_usb_sbrc_hwdep_read;
+       hwdep->ops.open = snd_usb_sbrc_hwdep_open;
+       hwdep->ops.release = snd_usb_sbrc_hwdep_release;
+       hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
+
+       mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!mixer->rc_urb)
+               return -ENOMEM;
+       mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
+       if (!mixer->rc_setup_packet) {
+               usb_free_urb(mixer->rc_urb);
+               mixer->rc_urb = NULL;
+               return -ENOMEM;
+       }
+       mixer->rc_setup_packet->bRequestType =
+               USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+       mixer->rc_setup_packet->bRequest = GET_MEM;
+       mixer->rc_setup_packet->wValue = cpu_to_le16(0);
+       mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
+       mixer->rc_setup_packet->wLength = cpu_to_le16(len);
+       usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
+                            usb_rcvctrlpipe(mixer->chip->dev, 0),
+                            (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
+                            snd_usb_soundblaster_remote_complete, mixer);
+       return 0;
+}
+
+static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+       int index = kcontrol->private_value;
+
+       ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
+       return 0;
+}
+
+static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+       int index = kcontrol->private_value;
+       int value = ucontrol->value.integer.value[0];
+       int err, changed;
+
+       if (value > 1)
+               return -EINVAL;
+       changed = value != mixer->audigy2nx_leds[index];
+       err = snd_usb_ctl_msg(mixer->chip->dev,
+                             usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+                             value, index + 2, NULL, 0, 100);
+       if (err < 0)
+               return err;
+       mixer->audigy2nx_leds[index] = value;
+       return changed;
+}
+
+static snd_kcontrol_new_t snd_audigy2nx_controls[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "CMSS LED Switch",
+               .info = snd_audigy2nx_led_info,
+               .get = snd_audigy2nx_led_get,
+               .put = snd_audigy2nx_led_put,
+               .private_value = 0,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Power LED Switch",
+               .info = snd_audigy2nx_led_info,
+               .get = snd_audigy2nx_led_get,
+               .put = snd_audigy2nx_led_put,
+               .private_value = 1,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Dolby Digital LED Switch",
+               .info = snd_audigy2nx_led_info,
+               .get = snd_audigy2nx_led_get,
+               .put = snd_audigy2nx_led_put,
+               .private_value = 2,
+       },
+};
+
+static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
+{
+       int i, err;
+
+       for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
+               err = snd_ctl_add(mixer->chip->card,
+                                 snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
+               if (err < 0)
+                       return err;
+       }
+       mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
+       return 0;
+}
+
+static void snd_audigy2nx_proc_read(snd_info_entry_t *entry,
+                                   snd_info_buffer_t *buffer)
+{
+       static const struct {
+               int unitid;
+               const char *name;
+       } jacks[] = {
+               {4,  "dig in "},
+               {7,  "line in"},
+               {19, "spk out"},
+               {20, "hph out"},
+       };
+       struct usb_mixer_interface *mixer = entry->private_data;
+       int i, err;
+       u8 buf[3];
+
+       snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
+       for (i = 0; i < ARRAY_SIZE(jacks); ++i) {
+               snd_iprintf(buffer, "%s: ", jacks[i].name);
+               err = snd_usb_ctl_msg(mixer->chip->dev,
+                                     usb_rcvctrlpipe(mixer->chip->dev, 0),
+                                     GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
+                                     USB_RECIP_INTERFACE, 0,
+                                     jacks[i].unitid << 8, buf, 3, 100);
+               if (err == 3 && buf[0] == 3)
+                       snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
+               else
+                       snd_iprintf(buffer, "?\n");
+       }
+}
+
+int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
+{
+       static snd_device_ops_t dev_ops = {
+               .dev_free = snd_usb_mixer_dev_free
+       };
+       struct usb_mixer_interface *mixer;
+       int err;
+
+       strcpy(chip->card->mixername, "USB Mixer");
+
+       mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL);
+       if (!mixer)
+               return -ENOMEM;
+       mixer->chip = chip;
+       mixer->ctrlif = ctrlif;
+#ifdef IGNORE_CTL_ERROR
+       mixer->ignore_ctl_error = 1;
+#endif
+       mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL);
+       if (!mixer->id_elems) {
+               kfree(mixer);
+               return -ENOMEM;
+       }
+
+       if ((err = snd_usb_mixer_controls(mixer)) < 0 ||
+           (err = snd_usb_mixer_status_create(mixer)) < 0)
+               goto _error;
+
+       if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
+               goto _error;
+
+       if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) {
+               snd_info_entry_t *entry;
+
+               if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
+                       goto _error;
+               if (!snd_card_proc_new(chip->card, "audigy2nx", &entry))
+                       snd_info_set_text_ops(entry, mixer, 1024,
+                                             snd_audigy2nx_proc_read);
+       }
+
+       err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
+       if (err < 0)
+               goto _error;
+       list_add(&mixer->list, &chip->mixer_list);
+       return 0;
+
+_error:
+       snd_usb_mixer_free(mixer);
+       return err;
+}
+
+void snd_usb_mixer_disconnect(struct list_head *p)
+{
+       struct usb_mixer_interface *mixer;
+       
+       mixer = list_entry(p, struct usb_mixer_interface, list);
+       if (mixer->urb)
+               usb_kill_urb(mixer->urb);
+       if (mixer->rc_urb)
+               usb_kill_urb(mixer->rc_urb);
+}
index c69b4b0875f8724aed7f13341f4477e98fa180d8..f05500b05ec0a70c0dbc84306dbf44e18094723d 100644 (file)
@@ -26,10 +26,16 @@ struct usbmix_name_map {
        int control;
 };
 
+struct usbmix_selector_map {
+       int id;
+       int count;
+       const char **names;
+};
+
 struct usbmix_ctl_map {
-       int vendor;
-       int product;
+       u32 id;
        const struct usbmix_name_map *map;
+       const struct usbmix_selector_map *selector_map;
        int ignore_ctl_error;
 };
 
@@ -91,6 +97,96 @@ static struct usbmix_name_map extigy_map[] = {
        { 0 } /* terminator */
 };
 
+/* Sound Blaster MP3+ controls mapping
+ * The default mixer channels have totally misleading names,
+ * e.g. no Master and fake PCM volume
+ *                     Pavel Mihaylov <bin@bash.info>
+ */
+static struct usbmix_name_map mp3plus_map[] = {
+       /* 1: IT pcm */
+       /* 2: IT mic */
+       /* 3: IT line */
+       /* 4: IT digital in */
+       /* 5: OT digital out */
+       /* 6: OT speaker */
+       /* 7: OT pcm capture */
+       { 8, "Capture Input Source" }, /* FU, default PCM Capture Source */
+               /* (Mic, Input 1 = Line input, Input 2 = Optical input) */
+       { 9, "Master Playback" }, /* FU, default Speaker 1 */
+       /* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */
+       /* { 10, "Mic Capture", 2 }, */ /* FU, Mic Capture */
+       { 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */
+       { 11, "Line Capture" }, /* FU, default PCM Capture */
+       { 12, "Digital In Playback" }, /* FU, default PCM 1 */
+       /* { 13, "Mic Playback" }, */ /* FU, default Mic Playback */
+       { 14, "Line Playback" }, /* FU, default Speaker */
+       /* 15: MU */
+       { 0 } /* terminator */
+};
+
+/* Topology of SB Audigy 2 NX
+
+          +----------------------------->EU[27]--+
+          |                                      v
+          | +----------------------------------->SU[29]---->FU[22]-->Dig_OUT[24]
+          | |                                    ^
+USB_IN[1]-+------------+              +->EU[17]->+->FU[11]-+
+            |          v              |          v         |
+Dig_IN[4]---+->FU[6]-->MU[16]->FU[18]-+->EU[21]->SU[31]----->FU[30]->Hph_OUT[20]
+            |          ^              |                    |
+Lin_IN[7]-+--->FU[8]---+              +->EU[23]->FU[28]------------->Spk_OUT[19]
+          | |                                              v
+          +--->FU[12]------------------------------------->SU[14]--->USB_OUT[15]
+            |                                              ^
+            +->FU[13]--------------------------------------+
+*/
+static struct usbmix_name_map audigy2nx_map[] = {
+       /* 1: IT pcm playback */
+       /* 4: IT digital in */
+       { 6, "Digital In Playback" }, /* FU */
+       /* 7: IT line in */
+       { 8, "Line Playback" }, /* FU */
+       { 11, "What-U-Hear Capture" }, /* FU */
+       { 12, "Line Capture" }, /* FU */
+       { 13, "Digital In Capture" }, /* FU */
+       { 14, "Capture Source" }, /* SU */
+       /* 15: OT pcm capture */
+       /* 16: MU w/o controls */
+       { 17, NULL }, /* DISABLED: EU (for what?) */
+       { 18, "Master Playback" }, /* FU */
+       /* 19: OT speaker */
+       /* 20: OT headphone */
+       { 21, NULL }, /* DISABLED: EU (for what?) */
+       { 22, "Digital Out Playback" }, /* FU */
+       { 23, NULL }, /* DISABLED: EU (for what?) */
+       /* 24: OT digital out */
+       { 27, NULL }, /* DISABLED: EU (for what?) */
+       { 28, "Speaker Playback" }, /* FU */
+       { 29, "Digital Out Source" }, /* SU */
+       { 30, "Headphone Playback" }, /* FU */
+       { 31, "Headphone Source" }, /* SU */
+       { 0 } /* terminator */
+};
+
+static struct usbmix_selector_map audigy2nx_selectors[] = {
+       {
+               .id = 14, /* Capture Source */
+               .count = 3,
+               .names = (const char*[]) {"Line", "Digital In", "What-U-Hear"}
+       },
+       {
+               .id = 29, /* Digital Out Source */
+               .count = 3,
+               .names = (const char*[]) {"Front", "PCM", "Digital In"}
+       },
+       {
+               .id = 31, /* Headphone Source */
+               .count = 2,
+               .names = (const char*[]) {"Front", "Side"}
+       },
+       { 0 } /* terminator */
+};
+
 /* LineX FM Transmitter entry - needed to bypass controls bug */
 static struct usbmix_name_map linex_map[] = {
        /* 1: IT pcm */
@@ -127,9 +223,29 @@ static struct usbmix_name_map justlink_map[] = {
  */
 
 static struct usbmix_ctl_map usbmix_ctl_maps[] = {
-       { 0x41e, 0x3000, extigy_map, 1 },
-       { 0x8bb, 0x2702, linex_map, 1 },
-       { 0xc45, 0x1158, justlink_map, 0 },
+       {
+               .id = USB_ID(0x041e, 0x3000),
+               .map = extigy_map,
+               .ignore_ctl_error = 1,
+       },
+       {
+               .id = USB_ID(0x041e, 0x3010),
+               .map = mp3plus_map,
+       },
+       {
+               .id = USB_ID(0x041e, 0x3020),
+               .map = audigy2nx_map,
+               .selector_map = audigy2nx_selectors,
+       },
+       {
+               .id = USB_ID(0x08bb, 0x2702),
+               .map = linex_map,
+               .ignore_ctl_error = 1,
+       },
+       {
+               .id = USB_ID(0x0c45, 0x1158),
+               .map = justlink_map,
+       },
        { 0 } /* terminator */
 };
 
index 88bbd944d4be997b1a672b3f504e15568b983855..f5135641b3e2e50a283630b7acc7a7fd52c381e0 100644 (file)
@@ -203,11 +203,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "EDIROL",
                .product_name = "UM-4",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x000f,
-                       .in_cables  = 0x000f
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x000f,
+                                       .in_cables  = 0x000f
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -216,11 +233,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "Roland",
                .product_name = "SC-8850",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x003f,
-                       .in_cables  = 0x003f
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x003f,
+                                       .in_cables  = 0x003f
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -229,11 +263,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "Roland",
                .product_name = "U-8",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x0005,
-                       .in_cables  = 0x0005
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x0005,
+                                       .in_cables  = 0x0005
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -242,11 +293,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "EDIROL",
                .product_name = "UM-2",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x0003,
-                       .in_cables  = 0x0003
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x0003,
+                                       .in_cables  = 0x0003
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -255,11 +323,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "Roland",
                .product_name = "SC-8820",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x0013,
-                       .in_cables  = 0x0013
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x0013,
+                                       .in_cables  = 0x0013
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -268,11 +353,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "Roland",
                .product_name = "PC-300",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x0001,
-                       .in_cables  = 0x0001
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -281,11 +383,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "EDIROL",
                .product_name = "UM-1",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x0001,
-                       .in_cables  = 0x0001
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -294,11 +413,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "Roland",
                .product_name = "SK-500",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x0013,
-                       .in_cables  = 0x0013
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x0013,
+                                       .in_cables  = 0x0013
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -421,11 +557,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "EDIROL",
                .product_name = "SD-90",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x000f,
-                       .in_cables  = 0x000f
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x000f,
+                                       .in_cables  = 0x000f
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -434,11 +587,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "Roland",
                .product_name = "MMP-2",
-               .ifnum = 2,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x0001,
-                       .in_cables  = 0x0001
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const snd_usb_midi_endpoint_info_t) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
@@ -609,15 +779,33 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 {
+       /*
+        * This quirk is for the "Advanced Driver" mode.  If off, the GS-10
+        * has ID 0x003c and is standard compliant, but has only 16-bit PCM
+        * and no MIDI.
+        */
        USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b),
        .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
                .vendor_name = "BOSS",
                .product_name = "GS-10",
-               .ifnum = 3,
-               .type = QUIRK_MIDI_FIXED_ENDPOINT,
-               .data = & (const snd_usb_midi_endpoint_info_t) {
-                       .out_cables = 0x0003,
-                       .in_cables  = 0x0003
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = & (const snd_usb_audio_quirk_t[]) {
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_MIDI_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = -1
+                       }
                }
        }
 },
index 89ee8b7320134fdf97b02a03f9e30457d32099f3..e6e6da1596712633b0383293fd3203a066b37d0b 100644 (file)
@@ -442,7 +442,7 @@ static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr)
                snd_card_disconnect((snd_card_t*)ptr);
                /* release the midi resources */
                list_for_each(p, &usX2Y->chip.midi_list) {
-                       snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver);
+                       snd_usbmidi_disconnect(p);
                }
                if (usX2Y->us428ctls_sharedmem) 
                        wake_up(&usX2Y->us428ctls_wait_queue_head);
index 4c292e0900699e3e33a64416a57b4fda4351b785..62dfd28b3b07f909ec66bfebca5a9c1de614a9ac 100644 (file)
@@ -401,10 +401,8 @@ static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs)
        for (i = 0; i < NRURBS; i++)
                usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]);
 
-       if (subs->tmpbuf) {
-               kfree(subs->tmpbuf);
-               subs->tmpbuf = NULL;
-       }
+       kfree(subs->tmpbuf);
+       subs->tmpbuf = NULL;
 }
 /*
  * initialize a substream's urbs