aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/Changes2
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/kernel-api.tmpl2
-rw-r--r--Documentation/DocBook/stylesheet.xsl1
-rw-r--r--Documentation/IPMI.txt146
-rw-r--r--Documentation/basic_profiling.txt10
-rw-r--r--Documentation/dvb/README.dvb-usb (renamed from Documentation/dvb/README.dibusb)195
-rw-r--r--Documentation/filesystems/ext2.txt2
-rw-r--r--Documentation/filesystems/xip.txt67
-rw-r--r--Documentation/keys.txt319
-rw-r--r--Documentation/video4linux/CARDLIST.bttv14
-rw-r--r--Documentation/video4linux/CARDLIST.cx8829
-rw-r--r--Documentation/video4linux/CARDLIST.saa713429
-rw-r--r--Documentation/video4linux/CARDLIST.tuner15
-rw-r--r--Documentation/video4linux/hauppauge-wintv-cx88-ir.txt54
-rw-r--r--Documentation/video4linux/lifeview.txt42
-rw-r--r--Documentation/video4linux/not-in-cx2388x-datasheet.txt37
-rw-r--r--MAINTAINERS5
-rw-r--r--arch/ppc64/kernel/ptrace.c4
-rw-r--r--arch/xtensa/Kconfig258
-rw-r--r--arch/xtensa/Kconfig.debug7
-rw-r--r--arch/xtensa/Makefile102
-rw-r--r--arch/xtensa/boot/Makefile37
-rw-r--r--arch/xtensa/boot/boot-elf/Makefile52
-rw-r--r--arch/xtensa/boot/boot-elf/boot.ld71
-rw-r--r--arch/xtensa/boot/boot-elf/bootstrap.S37
-rw-r--r--arch/xtensa/boot/boot-redboot/Makefile35
-rw-r--r--arch/xtensa/boot/boot-redboot/boot.ld66
-rw-r--r--arch/xtensa/boot/boot-redboot/bootstrap.S246
-rw-r--r--arch/xtensa/boot/include/zlib.h433
-rw-r--r--arch/xtensa/boot/lib/Makefile6
-rw-r--r--arch/xtensa/boot/lib/memcpy.S36
-rw-r--r--arch/xtensa/boot/lib/zlib.c2150
-rw-r--r--arch/xtensa/boot/lib/zmem.c87
-rw-r--r--arch/xtensa/boot/ramdisk/Makefile23
-rw-r--r--arch/xtensa/configs/common_defconfig662
-rw-r--r--arch/xtensa/configs/iss_defconfig531
-rw-r--r--arch/xtensa/kernel/Makefile18
-rw-r--r--arch/xtensa/kernel/align.S459
-rw-r--r--arch/xtensa/kernel/asm-offsets.c94
-rw-r--r--arch/xtensa/kernel/coprocessor.S201
-rw-r--r--arch/xtensa/kernel/entry.S1996
-rw-r--r--arch/xtensa/kernel/head.S237
-rw-r--r--arch/xtensa/kernel/irq.c192
-rw-r--r--arch/xtensa/kernel/module.c78
-rw-r--r--arch/xtensa/kernel/pci-dma.c73
-rw-r--r--arch/xtensa/kernel/pci.c563
-rw-r--r--arch/xtensa/kernel/platform.c49
-rw-r--r--arch/xtensa/kernel/process.c482
-rw-r--r--arch/xtensa/kernel/ptrace.c407
-rw-r--r--arch/xtensa/kernel/semaphore.c226
-rw-r--r--arch/xtensa/kernel/setup.c520
-rw-r--r--arch/xtensa/kernel/signal.c713
-rw-r--r--arch/xtensa/kernel/syscalls.c418
-rw-r--r--arch/xtensa/kernel/syscalls.h248
-rw-r--r--arch/xtensa/kernel/time.c227
-rw-r--r--arch/xtensa/kernel/traps.c498
-rw-r--r--arch/xtensa/kernel/vectors.S464
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S341
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c123
-rw-r--r--arch/xtensa/lib/Makefile7
-rw-r--r--arch/xtensa/lib/checksum.S410
-rw-r--r--arch/xtensa/lib/memcopy.S315
-rw-r--r--arch/xtensa/lib/memset.S160
-rw-r--r--arch/xtensa/lib/pci-auto.c352
-rw-r--r--arch/xtensa/lib/strcasecmp.c32
-rw-r--r--arch/xtensa/lib/strncpy_user.S224
-rw-r--r--arch/xtensa/lib/strnlen_user.S147
-rw-r--r--arch/xtensa/lib/usercopy.S321
-rw-r--r--arch/xtensa/mm/Makefile13
-rw-r--r--arch/xtensa/mm/fault.c241
-rw-r--r--arch/xtensa/mm/init.c551
-rw-r--r--arch/xtensa/mm/misc.S374
-rw-r--r--arch/xtensa/mm/pgtable.c76
-rw-r--r--arch/xtensa/mm/tlb.c545
-rw-r--r--arch/xtensa/platform-iss/Makefile13
-rw-r--r--arch/xtensa/platform-iss/console.c303
-rw-r--r--arch/xtensa/platform-iss/io.c32
-rw-r--r--arch/xtensa/platform-iss/network.c855
-rw-r--r--arch/xtensa/platform-iss/setup.c112
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c196
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c46
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c137
-rw-r--r--drivers/char/tpm/tpm.c350
-rw-r--r--drivers/char/tpm/tpm.h26
-rw-r--r--drivers/char/tpm/tpm_atmel.c51
-rw-r--r--drivers/char/tpm/tpm_nsc.c120
-rw-r--r--drivers/media/common/ir-common.c72
-rw-r--r--drivers/media/common/saa7146_fops.c2
-rw-r--r--drivers/media/dvb/Kconfig2
-rw-r--r--drivers/media/dvb/Makefile2
-rw-r--r--drivers/media/dvb/b2c2/Kconfig1
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c26
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c11
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h3
-rw-r--r--drivers/media/dvb/dibusb/Kconfig62
-rw-r--r--drivers/media/dvb/dibusb/Makefile11
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-core.c558
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-dvb.c185
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c582
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-firmware.c87
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-remote.c316
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-usb.c303
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb.h327
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c4
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig99
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile30
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c176
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c272
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c316
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c116
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb.h122
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c282
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.h65
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c (renamed from drivers/media/dvb/dibusb/dvb-fe-dtt200u.c)113
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c171
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.h66
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-common.h44
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c210
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c100
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c118
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h83
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c211
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c175
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c211
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h315
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c236
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c162
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c196
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c263
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.h78
-rw-r--r--drivers/media/dvb/frontends/Kconfig8
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c853
-rw-r--r--drivers/media/dvb/frontends/bcm3510.h40
-rw-r--r--drivers/media/dvb/frontends/bcm3510_priv.h460
-rw-r--r--drivers/media/dvb/frontends/dib3000-common.c2
-rw-r--r--drivers/media/dvb/frontends/dib3000.h5
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c20
-rw-r--r--drivers/media/dvb/frontends/dib3000mb_priv.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c29
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c94
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h9
-rw-r--r--drivers/media/video/Kconfig14
-rw-r--r--drivers/media/video/bt832.c46
-rw-r--r--drivers/media/video/bt832.h36
-rw-r--r--drivers/media/video/bttv-cards.c100
-rw-r--r--drivers/media/video/bttv-driver.c2
-rw-r--r--drivers/media/video/bttv-i2c.c2
-rw-r--r--drivers/media/video/bttv.h3
-rw-r--r--drivers/media/video/bttvp.h8
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c488
-rw-r--r--drivers/media/video/cx88/cx88-cards.c230
-rw-r--r--drivers/media/video/cx88/cx88-core.c28
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c2
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c18
-rw-r--r--drivers/media/video/cx88/cx88-input.c11
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c52
-rw-r--r--drivers/media/video/cx88/cx88-reg.h3
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c103
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c6
-rw-r--r--drivers/media/video/cx88/cx88-video.c59
-rw-r--r--drivers/media/video/cx88/cx88.h23
-rw-r--r--drivers/media/video/ir-kbd-gpio.c34
-rw-r--r--drivers/media/video/msp3400.c12
-rw-r--r--drivers/media/video/msp3400.h4
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c20
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c163
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c8
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c112
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c16
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c21
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c14
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c92
-rw-r--r--drivers/media/video/saa7134/saa7134.h17
-rw-r--r--drivers/media/video/tda9887.c40
-rw-r--r--drivers/media/video/tuner-core.c194
-rw-r--r--drivers/media/video/tuner-simple.c53
-rw-r--r--drivers/media/video/tvaudio.c23
-rw-r--r--drivers/media/video/tveeprom.c2
-rw-r--r--drivers/media/video/tvmixer.c4
-rw-r--r--drivers/media/video/v4l1-compat.c10
-rw-r--r--drivers/message/i2o/Kconfig46
-rw-r--r--drivers/message/i2o/Makefile3
-rw-r--r--drivers/message/i2o/bus-osm.c164
-rw-r--r--drivers/message/i2o/config-osm.c579
-rw-r--r--drivers/message/i2o/core.h58
-rw-r--r--drivers/message/i2o/debug.c3
-rw-r--r--drivers/message/i2o/device.c40
-rw-r--r--drivers/message/i2o/driver.c130
-rw-r--r--drivers/message/i2o/exec-osm.c131
-rw-r--r--drivers/message/i2o/i2o_block.c453
-rw-r--r--drivers/message/i2o/i2o_block.h34
-rw-r--r--drivers/message/i2o/i2o_config.c124
-rw-r--r--drivers/message/i2o/i2o_proc.c6
-rw-r--r--drivers/message/i2o/i2o_scsi.c505
-rw-r--r--drivers/message/i2o/iop.c566
-rw-r--r--drivers/message/i2o/pci.c246
-rw-r--r--drivers/oprofile/buffer_sync.c29
-rw-r--r--drivers/oprofile/event_buffer.h3
-rw-r--r--drivers/pnp/card.c3
-rw-r--r--drivers/pnp/manager.c1
-rw-r--r--drivers/s390/block/dcssblk.c44
-rw-r--r--drivers/scsi/hosts.c2
-rw-r--r--drivers/scsi/scsi.c6
-rw-r--r--drivers/scsi/scsi_debug.c2
-rw-r--r--drivers/scsi/scsi_lib.c2
-rw-r--r--drivers/scsi/scsi_priv.h4
-rw-r--r--drivers/scsi/scsi_sysfs.c4
-rw-r--r--fs/Kconfig19
-rw-r--r--fs/direct-io.c2
-rw-r--r--fs/ext2/Makefile1
-rw-r--r--fs/ext2/ext2.h2
-rw-r--r--fs/ext2/file.c14
-rw-r--r--fs/ext2/inode.c31
-rw-r--r--fs/ext2/namei.c12
-rw-r--r--fs/ext2/super.c27
-rw-r--r--fs/ext2/xip.c80
-rw-r--r--fs/ext2/xip.h25
-rw-r--r--fs/ext3/acl.c5
-rw-r--r--fs/ext3/inode.c7
-rw-r--r--fs/ext3/namei.c25
-rw-r--r--fs/ext3/super.c37
-rw-r--r--fs/ext3/xattr.c2
-rw-r--r--fs/lockd/svc.c4
-rw-r--r--fs/namespace.c2
-rw-r--r--fs/nfsd/Makefile2
-rw-r--r--fs/nfsd/nfs4acl.c4
-rw-r--r--fs/nfsd/nfs4callback.c13
-rw-r--r--fs/nfsd/nfs4idmap.c12
-rw-r--r--fs/nfsd/nfs4proc.c26
-rw-r--r--fs/nfsd/nfs4recover.c431
-rw-r--r--fs/nfsd/nfs4state.c1028
-rw-r--r--fs/nfsd/nfs4xdr.c11
-rw-r--r--fs/nfsd/nfsctl.c28
-rw-r--r--fs/nfsd/nfssvc.c2
-rw-r--r--fs/open.c4
-rw-r--r--fs/reiserfs/file.c4
-rw-r--r--fs/reiserfs/inode.c13
-rw-r--r--fs/reiserfs/journal.c2
-rw-r--r--fs/reiserfs/namei.c25
-rw-r--r--fs/reiserfs/stree.c2
-rw-r--r--fs/reiserfs/super.c81
-rw-r--r--fs/sysfs/file.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c3
-rw-r--r--include/asm-xtensa/a.out.h33
-rw-r--r--include/asm-xtensa/atomic.h272
-rw-r--r--include/asm-xtensa/bitops.h446
-rw-r--r--include/asm-xtensa/bootparam.h61
-rw-r--r--include/asm-xtensa/bug.h41
-rw-r--r--include/asm-xtensa/bugs.h22
-rw-r--r--include/asm-xtensa/byteorder.h82
-rw-r--r--include/asm-xtensa/cache.h32
-rw-r--r--include/asm-xtensa/cacheflush.h122
-rw-r--r--include/asm-xtensa/checksum.h264
-rw-r--r--include/asm-xtensa/coprocessor.h70
-rw-r--r--include/asm-xtensa/cpumask.h16
-rw-r--r--include/asm-xtensa/cputime.h6
-rw-r--r--include/asm-xtensa/current.h38
-rw-r--r--include/asm-xtensa/delay.h50
-rw-r--r--include/asm-xtensa/div64.h19
-rw-r--r--include/asm-xtensa/dma-mapping.h182
-rw-r--r--include/asm-xtensa/dma.h61
-rw-r--r--include/asm-xtensa/elf.h222
-rw-r--r--include/asm-xtensa/errno.h142
-rw-r--r--include/asm-xtensa/fcntl.h101
-rw-r--r--include/asm-xtensa/fixmap.h252
-rw-r--r--include/asm-xtensa/hardirq.h28
-rw-r--r--include/asm-xtensa/hdreg.h17
-rw-r--r--include/asm-xtensa/highmem.h17
-rw-r--r--include/asm-xtensa/hw_irq.h18
-rw-r--r--include/asm-xtensa/ide.h36
-rw-r--r--include/asm-xtensa/io.h197
-rw-r--r--include/asm-xtensa/ioctl.h83
-rw-r--r--include/asm-xtensa/ioctls.h112
-rw-r--r--include/asm-xtensa/ipc.h34
-rw-r--r--include/asm-xtensa/ipcbuf.h37
-rw-r--r--include/asm-xtensa/irq.h37
-rw-r--r--include/asm-xtensa/kmap_types.h31
-rw-r--r--include/asm-xtensa/linkage.h16
-rw-r--r--include/asm-xtensa/local.h16
-rw-r--r--include/asm-xtensa/mman.h80
-rw-r--r--include/asm-xtensa/mmu.h17
-rw-r--r--include/asm-xtensa/mmu_context.h330
-rw-r--r--include/asm-xtensa/module.h25
-rw-r--r--include/asm-xtensa/msgbuf.h48
-rw-r--r--include/asm-xtensa/namei.h26
-rw-r--r--include/asm-xtensa/page.h133
-rw-r--r--include/asm-xtensa/page.h.n135
-rw-r--r--include/asm-xtensa/param.h34
-rw-r--r--include/asm-xtensa/pci-bridge.h88
-rw-r--r--include/asm-xtensa/pci.h89
-rw-r--r--include/asm-xtensa/percpu.h16
-rw-r--r--include/asm-xtensa/pgalloc.h116
-rw-r--r--include/asm-xtensa/pgtable.h468
-rw-r--r--include/asm-xtensa/platform-iss/hardware.h29
-rw-r--r--include/asm-xtensa/platform.h92
-rw-r--r--include/asm-xtensa/poll.h37
-rw-r--r--include/asm-xtensa/posix_types.h123
-rw-r--r--include/asm-xtensa/processor.h205
-rw-r--r--include/asm-xtensa/ptrace.h135
-rw-r--r--include/asm-xtensa/resource.h16
-rw-r--r--include/asm-xtensa/rmap.h16
-rw-r--r--include/asm-xtensa/rwsem.h175
-rw-r--r--include/asm-xtensa/scatterlist.h34
-rw-r--r--include/asm-xtensa/sections.h16
-rw-r--r--include/asm-xtensa/segment.h16
-rw-r--r--include/asm-xtensa/semaphore.h129
-rw-r--r--include/asm-xtensa/sembuf.h44
-rw-r--r--include/asm-xtensa/serial.h18
-rw-r--r--include/asm-xtensa/setup.h16
-rw-r--r--include/asm-xtensa/shmbuf.h50
-rw-r--r--include/asm-xtensa/shmparam.h23
-rw-r--r--include/asm-xtensa/sigcontext.h44
-rw-r--r--include/asm-xtensa/siginfo.h16
-rw-r--r--include/asm-xtensa/signal.h187
-rw-r--r--include/asm-xtensa/smp.h27
-rw-r--r--include/asm-xtensa/socket.h61
-rw-r--r--include/asm-xtensa/sockios.h30
-rw-r--r--include/asm-xtensa/spinlock.h16
-rw-r--r--include/asm-xtensa/stat.h105
-rw-r--r--include/asm-xtensa/statfs.h17
-rw-r--r--include/asm-xtensa/string.h124
-rw-r--r--include/asm-xtensa/system.h252
-rw-r--r--include/asm-xtensa/termbits.h194
-rw-r--r--include/asm-xtensa/termios.h122
-rw-r--r--include/asm-xtensa/thread_info.h146
-rw-r--r--include/asm-xtensa/timex.h94
-rw-r--r--include/asm-xtensa/tlb.h25
-rw-r--r--include/asm-xtensa/tlbflush.h200
-rw-r--r--include/asm-xtensa/topology.h16
-rw-r--r--include/asm-xtensa/types.h66
-rw-r--r--include/asm-xtensa/uaccess.h532
-rw-r--r--include/asm-xtensa/ucontext.h22
-rw-r--r--include/asm-xtensa/unaligned.h28
-rw-r--r--include/asm-xtensa/unistd.h537
-rw-r--r--include/asm-xtensa/user.h20
-rw-r--r--include/asm-xtensa/vga.h19
-rw-r--r--include/asm-xtensa/xor.h16
-rw-r--r--include/asm-xtensa/xtensa/cacheasm.h708
-rw-r--r--include/asm-xtensa/xtensa/cacheattrasm.h432
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/core.h1270
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/defs.h270
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/specreg.h99
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/system.h198
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/tie.h275
-rw-r--r--include/asm-xtensa/xtensa/coreasm.h526
-rw-r--r--include/asm-xtensa/xtensa/corebits.h77
-rw-r--r--include/asm-xtensa/xtensa/hal.h822
-rw-r--r--include/asm-xtensa/xtensa/simcall.h130
-rw-r--r--include/asm-xtensa/xtensa/xt2000-uart.h155
-rw-r--r--include/asm-xtensa/xtensa/xt2000.h408
-rw-r--r--include/asm-xtensa/xtensa/xtboard.h120
-rw-r--r--include/linux/dqblk_v1.h6
-rw-r--r--include/linux/dqblk_v2.h6
-rw-r--r--include/linux/ext2_fs.h25
-rw-r--r--include/linux/ext3_fs.h1
-rw-r--r--include/linux/ext3_jbd.h19
-rw-r--r--include/linux/fs.h24
-rw-r--r--include/linux/i2o-dev.h43
-rw-r--r--include/linux/i2o.h497
-rw-r--r--include/linux/ipmi.h5
-rw-r--r--include/linux/irq.h1
-rw-r--r--include/linux/key-ui.h47
-rw-r--r--include/linux/key.h44
-rw-r--r--include/linux/keyctl.h11
-rw-r--r--include/linux/kmod.h13
-rw-r--r--include/linux/module.h5
-rw-r--r--include/linux/namespace.h1
-rw-r--r--include/linux/nfs4.h2
-rw-r--r--include/linux/nfsd/nfsd.h8
-rw-r--r--include/linux/nfsd/state.h47
-rw-r--r--include/linux/nfsd/xdr4.h1
-rw-r--r--include/linux/nfsd_idmap.h5
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/quota.h7
-rw-r--r--include/linux/reiserfs_fs.h15
-rw-r--r--include/linux/reiserfs_fs_sb.h2
-rw-r--r--include/linux/rmap.h6
-rw-r--r--include/linux/sched.h8
-rw-r--r--include/media/audiochip.h4
-rw-r--r--include/media/id.h4
-rw-r--r--include/media/ir-common.h3
-rw-r--r--include/media/tuner.h29
-rw-r--r--include/media/tveeprom.h4
-rw-r--r--include/net/sctp/sm.h6
-rw-r--r--include/scsi/sg_request.h26
-rw-r--r--kernel/irq/spurious.c2
-rw-r--r--kernel/kmod.c17
-rw-r--r--kernel/module.c97
-rw-r--r--kernel/power/swsusp.c2
-rw-r--r--kernel/sys.c2
-rw-r--r--mm/Makefile1
-rw-r--r--mm/fadvise.c4
-rw-r--r--mm/filemap.c74
-rw-r--r--mm/filemap.h94
-rw-r--r--mm/filemap_xip.c447
-rw-r--r--mm/madvise.c5
-rw-r--r--mm/memory.c2
-rw-r--r--mm/rmap.c4
-rw-r--r--net/sctp/sm_statefuns.c16
-rw-r--r--net/sunrpc/sunrpc_syms.c1
-rw-r--r--security/keys/Makefile5
-rw-r--r--security/keys/compat.c7
-rw-r--r--security/keys/internal.h45
-rw-r--r--security/keys/key.c118
-rw-r--r--security/keys/keyctl.c199
-rw-r--r--security/keys/keyring.c312
-rw-r--r--security/keys/proc.c21
-rw-r--r--security/keys/process_keys.c213
-rw-r--r--security/keys/request_key.c221
-rw-r--r--security/keys/request_key_auth.c180
-rw-r--r--security/keys/user_defined.c87
416 files changed, 47337 insertions, 6178 deletions
diff --git a/Documentation/Changes b/Documentation/Changes
index 57542bc25e..b376007547 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -63,7 +63,7 @@ o PPP 2.4.0 # pppd --version
63o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version 63o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version
64o nfs-utils 1.0.5 # showmount --version 64o nfs-utils 1.0.5 # showmount --version
65o procps 3.2.0 # ps --version 65o procps 3.2.0 # ps --version
66o oprofile 0.5.3 # oprofiled --version 66o oprofile 0.9 # oprofiled --version
67 67
68Kernel compilation 68Kernel compilation
69================== 69==================
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 87da3478fa..fa3e29ad8a 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -49,7 +49,7 @@ installmandocs: mandocs
49KERNELDOC = scripts/kernel-doc 49KERNELDOC = scripts/kernel-doc
50DOCPROC = scripts/basic/docproc 50DOCPROC = scripts/basic/docproc
51 51
52XMLTOFLAGS = -m Documentation/DocBook/stylesheet.xsl 52XMLTOFLAGS = -m $(srctree)/Documentation/DocBook/stylesheet.xsl
53#XMLTOFLAGS += --skip-validation 53#XMLTOFLAGS += --skip-validation
54 54
55### 55###
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index bb6a0106be..d650ce3648 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -266,7 +266,7 @@ X!Ekernel/module.c
266 <chapter id="hardware"> 266 <chapter id="hardware">
267 <title>Hardware Interfaces</title> 267 <title>Hardware Interfaces</title>
268 <sect1><title>Interrupt Handling</title> 268 <sect1><title>Interrupt Handling</title>
269!Iarch/i386/kernel/irq.c 269!Ikernel/irq/manage.c
270 </sect1> 270 </sect1>
271 271
272 <sect1><title>Resources Management</title> 272 <sect1><title>Resources Management</title>
diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl
index e14c21dda4..64be9f7ee3 100644
--- a/Documentation/DocBook/stylesheet.xsl
+++ b/Documentation/DocBook/stylesheet.xsl
@@ -2,4 +2,5 @@
2<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"> 2<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
3<param name="chunk.quietly">1</param> 3<param name="chunk.quietly">1</param>
4<param name="funcsynopsis.style">ansi</param> 4<param name="funcsynopsis.style">ansi</param>
5<param name="funcsynopsis.tabular.threshold">80</param>
5</stylesheet> 6</stylesheet>
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index 90d10e708c..84d3d4d10c 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -25,9 +25,10 @@ subject and I can't cover it all here!
25Configuration 25Configuration
26------------- 26-------------
27 27
28The LinuxIPMI driver is modular, which means you have to pick several 28The Linux IPMI driver is modular, which means you have to pick several
29things to have it work right depending on your hardware. Most of 29things to have it work right depending on your hardware. Most of
30these are available in the 'Character Devices' menu. 30these are available in the 'Character Devices' menu then the IPMI
31menu.
31 32
32No matter what, you must pick 'IPMI top-level message handler' to use 33No matter what, you must pick 'IPMI top-level message handler' to use
33IPMI. What you do beyond that depends on your needs and hardware. 34IPMI. What you do beyond that depends on your needs and hardware.
@@ -35,33 +36,30 @@ IPMI. What you do beyond that depends on your needs and hardware.
35The message handler does not provide any user-level interfaces. 36The message handler does not provide any user-level interfaces.
36Kernel code (like the watchdog) can still use it. If you need access 37Kernel code (like the watchdog) can still use it. If you need access
37from userland, you need to select 'Device interface for IPMI' if you 38from userland, you need to select 'Device interface for IPMI' if you
38want access through a device driver. Another interface is also 39want access through a device driver.
39available, you may select 'IPMI sockets' in the 'Networking Support' 40
40main menu. This provides a socket interface to IPMI. You may select 41The driver interface depends on your hardware. If your system
41both of these at the same time, they will both work together. 42properly provides the SMBIOS info for IPMI, the driver will detect it
42 43and just work. If you have a board with a standard interface (These
43The driver interface depends on your hardware. If you have a board 44will generally be either "KCS", "SMIC", or "BT", consult your hardware
44with a standard interface (These will generally be either "KCS", 45manual), choose the 'IPMI SI handler' option. A driver also exists
45"SMIC", or "BT", consult your hardware manual), choose the 'IPMI SI 46for direct I2C access to the IPMI management controller. Some boards
46handler' option. A driver also exists for direct I2C access to the 47support this, but it is unknown if it will work on every board. For
47IPMI management controller. Some boards support this, but it is 48this, choose 'IPMI SMBus handler', but be ready to try to do some
48unknown if it will work on every board. For this, choose 'IPMI SMBus 49figuring to see if it will work on your system if the SMBIOS/APCI
49handler', but be ready to try to do some figuring to see if it will 50information is wrong or not present. It is fairly safe to have both
50work. 51these enabled and let the drivers auto-detect what is present.
51
52There is also a KCS-only driver interface supplied, but it is
53depracated in favor of the SI interface.
54 52
55You should generally enable ACPI on your system, as systems with IPMI 53You should generally enable ACPI on your system, as systems with IPMI
56should have ACPI tables describing them. 54can have ACPI tables describing them.
57 55
58If you have a standard interface and the board manufacturer has done 56If you have a standard interface and the board manufacturer has done
59their job correctly, the IPMI controller should be automatically 57their job correctly, the IPMI controller should be automatically
60detect (via ACPI or SMBIOS tables) and should just work. Sadly, many 58detected (via ACPI or SMBIOS tables) and should just work. Sadly,
61boards do not have this information. The driver attempts standard 59many boards do not have this information. The driver attempts
62defaults, but they may not work. If you fall into this situation, you 60standard defaults, but they may not work. If you fall into this
63need to read the section below named 'The SI Driver' on how to 61situation, you need to read the section below named 'The SI Driver' or
64hand-configure your system. 62"The SMBus Driver" on how to hand-configure your system.
65 63
66IPMI defines a standard watchdog timer. You can enable this with the 64IPMI defines a standard watchdog timer. You can enable this with the
67'IPMI Watchdog Timer' config option. If you compile the driver into 65'IPMI Watchdog Timer' config option. If you compile the driver into
@@ -73,6 +71,18 @@ closed (by default it is disabled on close). Go into the 'Watchdog
73Cards' menu, enable 'Watchdog Timer Support', and enable the option 71Cards' menu, enable 'Watchdog Timer Support', and enable the option
74'Disable watchdog shutdown on close'. 72'Disable watchdog shutdown on close'.
75 73
74IPMI systems can often be powered off using IPMI commands. Select
75'IPMI Poweroff' to do this. The driver will auto-detect if the system
76can be powered off by IPMI. It is safe to enable this even if your
77system doesn't support this option. This works on ATCA systems, the
78Radisys CPI1 card, and any IPMI system that supports standard chassis
79management commands.
80
81If you want the driver to put an event into the event log on a panic,
82enable the 'Generate a panic event to all BMCs on a panic' option. If
83you want the whole panic string put into the event log using OEM
84events, enable the 'Generate OEM events containing the panic string'
85option.
76 86
77Basic Design 87Basic Design
78------------ 88------------
@@ -80,7 +90,7 @@ Basic Design
80The Linux IPMI driver is designed to be very modular and flexible, you 90The Linux IPMI driver is designed to be very modular and flexible, you
81only need to take the pieces you need and you can use it in many 91only need to take the pieces you need and you can use it in many
82different ways. Because of that, it's broken into many chunks of 92different ways. Because of that, it's broken into many chunks of
83code. These chunks are: 93code. These chunks (by module name) are:
84 94
85ipmi_msghandler - This is the central piece of software for the IPMI 95ipmi_msghandler - This is the central piece of software for the IPMI
86system. It handles all messages, message timing, and responses. The 96system. It handles all messages, message timing, and responses. The
@@ -93,18 +103,26 @@ ipmi_devintf - This provides a userland IOCTL interface for the IPMI
93driver, each open file for this device ties in to the message handler 103driver, each open file for this device ties in to the message handler
94as an IPMI user. 104as an IPMI user.
95 105
96ipmi_si - A driver for various system interfaces. This supports 106ipmi_si - A driver for various system interfaces. This supports KCS,
97KCS, SMIC, and may support BT in the future. Unless you have your own 107SMIC, and BT interfaces. Unless you have an SMBus interface or your
98custom interface, you probably need to use this. 108own custom interface, you probably need to use this.
99 109
100ipmi_smb - A driver for accessing BMCs on the SMBus. It uses the 110ipmi_smb - A driver for accessing BMCs on the SMBus. It uses the
101I2C kernel driver's SMBus interfaces to send and receive IPMI messages 111I2C kernel driver's SMBus interfaces to send and receive IPMI messages
102over the SMBus. 112over the SMBus.
103 113
104af_ipmi - A network socket interface to IPMI. This doesn't take up 114ipmi_watchdog - IPMI requires systems to have a very capable watchdog
105a character device in your system. 115timer. This driver implements the standard Linux watchdog timer
116interface on top of the IPMI message handler.
117
118ipmi_poweroff - Some systems support the ability to be turned off via
119IPMI commands.
106 120
107Note that the KCS-only interface ahs been removed. 121These are all individually selectable via configuration options.
122
123Note that the KCS-only interface has been removed. The af_ipmi driver
124is no longer supported and has been removed because it was impossible
125to do 32 bit emulation on 64-bit kernels with it.
108 126
109Much documentation for the interface is in the include files. The 127Much documentation for the interface is in the include files. The
110IPMI include files are: 128IPMI include files are:
@@ -424,7 +442,7 @@ at module load time (for a module) with:
424 modprobe ipmi_smb.o 442 modprobe ipmi_smb.o
425 addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]] 443 addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
426 dbg=<flags1>,<flags2>... 444 dbg=<flags1>,<flags2>...
427 [defaultprobe=0] [dbg_probe=1] 445 [defaultprobe=1] [dbg_probe=1]
428 446
429The addresses are specified in pairs, the first is the adapter ID and the 447The addresses are specified in pairs, the first is the adapter ID and the
430second is the I2C address on that adapter. 448second is the I2C address on that adapter.
@@ -532,3 +550,67 @@ Once you open the watchdog timer, you must write a 'V' character to the
532device to close it, or the timer will not stop. This is a new semantic 550device to close it, or the timer will not stop. This is a new semantic
533for the driver, but makes it consistent with the rest of the watchdog 551for the driver, but makes it consistent with the rest of the watchdog
534drivers in Linux. 552drivers in Linux.
553
554
555Panic Timeouts
556--------------
557
558The OpenIPMI driver supports the ability to put semi-custom and custom
559events in the system event log if a panic occurs. if you enable the
560'Generate a panic event to all BMCs on a panic' option, you will get
561one event on a panic in a standard IPMI event format. If you enable
562the 'Generate OEM events containing the panic string' option, you will
563also get a bunch of OEM events holding the panic string.
564
565
566The field settings of the events are:
567* Generator ID: 0x21 (kernel)
568* EvM Rev: 0x03 (this event is formatting in IPMI 1.0 format)
569* Sensor Type: 0x20 (OS critical stop sensor)
570* Sensor #: The first byte of the panic string (0 if no panic string)
571* Event Dir | Event Type: 0x6f (Assertion, sensor-specific event info)
572* Event Data 1: 0xa1 (Runtime stop in OEM bytes 2 and 3)
573* Event data 2: second byte of panic string
574* Event data 3: third byte of panic string
575See the IPMI spec for the details of the event layout. This event is
576always sent to the local management controller. It will handle routing
577the message to the right place
578
579Other OEM events have the following format:
580Record ID (bytes 0-1): Set by the SEL.
581Record type (byte 2): 0xf0 (OEM non-timestamped)
582byte 3: The slave address of the card saving the panic
583byte 4: A sequence number (starting at zero)
584The rest of the bytes (11 bytes) are the panic string. If the panic string
585is longer than 11 bytes, multiple messages will be sent with increasing
586sequence numbers.
587
588Because you cannot send OEM events using the standard interface, this
589function will attempt to find an SEL and add the events there. It
590will first query the capabilities of the local management controller.
591If it has an SEL, then they will be stored in the SEL of the local
592management controller. If not, and the local management controller is
593an event generator, the event receiver from the local management
594controller will be queried and the events sent to the SEL on that
595device. Otherwise, the events go nowhere since there is nowhere to
596send them.
597
598
599Poweroff
600--------
601
602If the poweroff capability is selected, the IPMI driver will install
603a shutdown function into the standard poweroff function pointer. This
604is in the ipmi_poweroff module. When the system requests a powerdown,
605it will send the proper IPMI commands to do this. This is supported on
606several platforms.
607
608There is a module parameter named "poweroff_control" that may either be zero
609(do a power down) or 2 (do a power cycle, power the system off, then power
610it on in a few seconds). Setting ipmi_poweroff.poweroff_control=x will do
611the same thing on the kernel command line. The parameter is also available
612via the proc filesystem in /proc/ipmi/poweroff_control. Note that if the
613system does not support power cycling, it will always to the power off.
614
615Note that if you have ACPI enabled, the system will prefer using ACPI to
616power off.
diff --git a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt
index 65e3dc2d44..8764e9f708 100644
--- a/Documentation/basic_profiling.txt
+++ b/Documentation/basic_profiling.txt
@@ -27,9 +27,13 @@ dump output readprofile -m /boot/System.map > captured_profile
27 27
28Oprofile 28Oprofile
29-------- 29--------
30Get the source (I use 0.8) from http://oprofile.sourceforge.net/ 30
31and add "idle=poll" to the kernel command line 31Get the source (see Changes for required version) from
32http://oprofile.sourceforge.net/ and add "idle=poll" to the kernel command
33line.
34
32Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel 35Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
36
33./configure --with-kernel-support 37./configure --with-kernel-support
34make install 38make install
35 39
@@ -46,7 +50,7 @@ start opcontrol --start
46stop opcontrol --stop 50stop opcontrol --stop
47dump output opreport > output_file 51dump output opreport > output_file
48 52
49To only report on the kernel, run opreport /boot/vmlinux > output_file 53To only report on the kernel, run opreport -l /boot/vmlinux > output_file
50 54
51A reset is needed to clear old statistics, which survive a reboot. 55A reset is needed to clear old statistics, which survive a reboot.
52 56
diff --git a/Documentation/dvb/README.dibusb b/Documentation/dvb/README.dvb-usb
index 7a9e958513..c7ed01b9f8 100644
--- a/Documentation/dvb/README.dibusb
+++ b/Documentation/dvb/README.dvb-usb
@@ -1,16 +1,40 @@
1Documentation for dib3000* frontend drivers and dibusb device driver 1Documentation for dvb-usb-framework module and its devices
2====================================================================
3 2
4Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de), 3Idea behind the dvb-usb-framework
4=================================
5 5
6dibusb and dib3000mb/mc drivers based on GPL code, which has 6In March 2005 I got the new Twinhan USB2.0 DVB-T device. They provided specs and a firmware.
7 7
8Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) 8Quite keen I wanted to put the driver (with some quirks of course) into dibusb.
9After reading some specs and doing some USB snooping, it realized, that the
10dibusb-driver would be a complete mess afterwards. So I decided to do it in a
11different way: With the help of a dvb-usb-framework.
9 12
10This program is free software; you can redistribute it and/or 13The framework provides generic functions (mostly kernel API calls), such as:
11modify it under the terms of the GNU General Public License as
12published by the Free Software Foundation, version 2.
13 14
15- Transport Stream URB handling in conjunction with dvb-demux-feed-control
16 (bulk and isoc (TODO) are supported)
17- registering the device for the DVB-API
18- registering an I2C-adapter if applicable
19- remote-control/input-device handling
20- firmware requesting and loading (currently just for the Cypress USB
21 controller)
22- other functions/methods which can be shared by several drivers (such as
23 functions for bulk-control-commands)
24
25The source code of the particular DVB USB devices does just the communication
26with the device via the bus. The connection between the DVB-API-functionality
27is done via callbacks, assigned in a static device-description (struct
28dvb_usb_device) each device-driver has to have.
29
30For an example have a look in drivers/media/dvb/dvb-usb/vp7045*.
31
32Objective is to migrate all the usb-devices (dibusb, cinergyT2, maybe the
33ttusb; flexcop-usb already benefits from the generic flexcop-device) to use
34the dvb-usb-lib.
35
36TODO: dynamic enabling and disabling of the pid-filter in regard to number of
37feeds requested.
14 38
15Supported devices USB1.1 39Supported devices USB1.1
16======================== 40========================
@@ -55,22 +79,34 @@ Others:
55- Grandtec USB DVB-T 79- Grandtec USB DVB-T
56 http://www.grand.com.tw/ 80 http://www.grand.com.tw/
57 81
58- Avermedia AverTV DVBT USB (2) 82- AVerMedia AverTV DVBT USB
59 http://www.avermedia.com/ 83 http://www.avermedia.com/
60 84
61- DiBcom USB DVB-T reference device (non-public) 85- DiBcom USB DVB-T reference device (non-public)
62 86
63 87
64Supported devices USB2.0 88Supported devices USB2.0-only
65======================== 89=============================
66- Twinhan MagicBox II (2) 90- Twinhan MagicBox II
67 http://www.twinhan.com/product_terrestrial_7.asp 91 http://www.twinhan.com/product_terrestrial_7.asp
68 92
69- Hanftek UMT-010 (1) 93- TwinhanDTV Alpha
94 http://www.twinhan.com/product_terrestrial_8.asp
95
96- DigitalNow TinyUSB 2 DVB-t Receiver
97 http://www.digitalnow.com.au/DigitalNow%20tinyUSB2%20Specifications.html
98
99- Hanftek UMT-010
70 http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529 100 http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529
71 101
72- Typhoon/Yakumo/HAMA DVB-T mobile USB2.0 (1) 102
103Supported devices USB2.0 and USB1.1
104=============================
105- Typhoon/Yakumo/HAMA/Yuan DVB-T mobile USB2.0
73 http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T 106 http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
107 http://www.yuan.com.tw/en/products/vdo_ub300.html
108 http://www.hama.de/portal/articleId*114663/action*2563
109 http://www.anubisline.com/english/articlec.asp?id=50502&catid=002
74 110
75- Artec T1 USB TVBOX (FX2) (2) 111- Artec T1 USB TVBOX (FX2) (2)
76 112
@@ -81,14 +117,24 @@ Supported devices USB2.0
81 117
82- DiBcom USB2.0 DVB-T reference device (non-public) 118- DiBcom USB2.0 DVB-T reference device (non-public)
83 119
841) It is working almost. 120- AVerMedia AverTV A800 DVB-T USB2.0
121
1221) It is working almost - work-in-progress.
852) No test reports received yet. 1232) No test reports received yet.
86 124
1250. History & News:
126 2005-04-17 - all dibusb devices ported to make use of the dvb-usb-framework
127 2005-04-02 - re-enabled and improved remote control code.
128 2005-03-31 - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb.
129 2005-03-30 - first commit of the dvb-usb-module based on the dibusb-source. First device is a new driver for the
130 TwinhanDTV Alpha / MagicBox II USB2.0-only DVB-T device.
87 131
880. NEWS: 132 (change from dvb-dibusb to dvb-usb)
133 2005-03-28 - added support for the AVerMedia AverTV DVB-T USB2.0 device (Thanks to Glen Harris and Jiun-Kuei Jung, AVerMedia)
134 2005-03-14 - added support for the Typhoon/Yakumo/HAMA DVB-T mobile USB2.0
89 2005-02-11 - added support for the KWorld/ADSTech Instant DVB-T USB2.0. Thanks a lot to Joachim von Caron 135 2005-02-11 - added support for the KWorld/ADSTech Instant DVB-T USB2.0. Thanks a lot to Joachim von Caron
90 2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2 136 2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2
91 2005-01-31 - distorted streaming is finally gone for USB1.1 devices 137 2005-01-31 - distorted streaming is gone for USB1.1 devices
92 2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb 138 2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
93 - first almost working version for HanfTek UMT-010 139 - first almost working version for HanfTek UMT-010
94 - found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010 140 - found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
@@ -99,7 +145,7 @@ Supported devices USB2.0
99 2004-12-26 - refactored the dibusb-driver, splitted into separate files 145 2004-12-26 - refactored the dibusb-driver, splitted into separate files
100 - i2c-probing enabled 146 - i2c-probing enabled
101 2004-12-06 - possibility for demod i2c-address probing 147 2004-12-06 - possibility for demod i2c-address probing
102 - new usb IDs (Compro,Artec) 148 - new usb IDs (Compro, Artec)
103 2004-11-23 - merged changes from DiB3000MC_ver2.1 149 2004-11-23 - merged changes from DiB3000MC_ver2.1
104 - revised the debugging 150 - revised the debugging
105 - possibility to deliver the complete TS for USB2.0 151 - possibility to deliver the complete TS for USB2.0
@@ -127,8 +173,8 @@ Supported devices USB2.0
127 CTS Portable (Chinese Television System) 173 CTS Portable (Chinese Television System)
128 2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working 174 2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working
129 properly with firmware extracted from 2.422 175 properly with firmware extracted from 2.422
130 - #if for 2.6.4 (dvb), compile issue 176 - #if for 2.6.4 (dvb), compile issue
131 - changed firmware handling, see vp7041.txt sec 1.1 177 - changed firmware handling, see vp7041.txt sec 1.1
132 2004-07-02 - some tuner modifications, v0.1, cleanups, first public 178 2004-07-02 - some tuner modifications, v0.1, cleanups, first public
133 2004-06-28 - now using the dvb_dmx_swfilter_packets, everything 179 2004-06-28 - now using the dvb_dmx_swfilter_packets, everything
134 runs fine now 180 runs fine now
@@ -139,38 +185,27 @@ Supported devices USB2.0
139 2004-05-11 - start writing the driver 185 2004-05-11 - start writing the driver
140 186
1411. How to use? 1871. How to use?
142NOTE: This driver was developed using Linux 2.6.6.,
143it is working with 2.6.7 and above.
144
145Linux 2.4.x support is not planned, but patches are very welcome.
146
147NOTE: I'm using Debian testing, so the following explaination (especially
148the hotplug-path) needn't match your system, but probably it will :).
149
150The driver is included in the kernel since Linux 2.6.10.
151
1521.1. Firmware 1881.1. Firmware
153 189
154The USB driver needs to download a firmware to start working. 190Most of the USB drivers need to download a firmware to start working.
155
156You can either use "get_dvb_firmware dibusb" to download the firmware or you
157can get it directly via
158 191
159for USB1.1 (AN2135) 192for USB1.1 (AN2135) you need: dvb-usb-dibusb-5.0.0.11.fw
160http://www.linuxtv.org/downloads/firmware/dvb-dibusb-5.0.0.11.fw 193for USB2.0 HanfTek: dvb-usb-umt-010-02.fw
194for USB2.0 DiBcom: dvb-usb-dibusb-6.0.0.8.fw
195for USB2.0 AVerMedia AverTV DVB-T USB2: dvb-usb-avertv-a800-01.fw
196for USB2.0 TwinhanDTV Alpha/MagicBox II: dvb-usb-vp7045-01.fw
161 197
162for USB1.1 (AN2235) (a few Artec T1 devices) 198The files can be found on http://www.linuxtv.org/download/firmware/ .
163http://www.linuxtv.org/downloads/firmware/dvb-dibusb-an2235-1.fw
164 199
165for USB2.0 (FX2) Hauppauge, DiBcom 200We do not have the permission (yet) to publish the following firmware-files.
166http://www.linuxtv.org/downloads/firmware/dvb-dibusb-6.0.0.5.fw 201You'll need to extract them from the windows drivers.
167 202
168for USB2.0 ADSTech/Kworld USB2.0 203You should be able to use "get_dvb_firmware dvb-usb" to get the firmware:
169http://www.linuxtv.org/downloads/firmware/dvb-dibusb-adstech-usb2-1.fw
170
171for USB2.0 HanfTek
172http://www.linuxtv.org/downloads/firmware/dvb-dibusb-an2235-1.fw
173 204
205for USB1.1 (AN2235) (a few Artec T1 devices): dvb-usb-dibusb-an2235-01.fw
206for USB2.0 Hauppauge: dvb-usb-nova-t-usb2-01.fw
207for USB2.0 ADSTech/Kworld USB2.0: dvb-usb-adstech-usb2-01.fw
208for USB2.0 Yakumo/Typhoon/Hama: dvb-usb-dtt200u-01.fw
174 209
1751.2. Compiling 2101.2. Compiling
176 211
@@ -178,6 +213,9 @@ Since the driver is in the linux kernel, activating the driver in
178your favorite config-environment should sufficient. I recommend 213your favorite config-environment should sufficient. I recommend
179to compile the driver as module. Hotplug does the rest. 214to compile the driver as module. Hotplug does the rest.
180 215
216If you use dvb-kernel enter the build-2.6 directory run 'make' and 'insmod.sh
217load' afterwards.
218
1811.3. Loading the drivers 2191.3. Loading the drivers
182 220
183Hotplug is able to load the driver, when it is needed (because you plugged 221Hotplug is able to load the driver, when it is needed (because you plugged
@@ -188,15 +226,13 @@ from withing the dvb-kernel cvs repository.
188 226
189first have a look, which debug level are available: 227first have a look, which debug level are available:
190 228
191modinfo dib3000mb 229modinfo dvb-usb
192modinfo dib3000-common 230modinfo dvb-usb-vp7045
193modinfo dib3000mc 231etc.
194modinfo dvb-dibusb
195 232
196modprobe dib3000-common debug=<level> 233modprobe dvb-usb debug=<level>
197modprobe dib3000mb debug=<level> 234modprobe dvb-usb-vp7045 debug=<level>
198modprobe dib3000mc debug=<level> 235etc.
199modprobe dvb-dibusb debug=<level>
200 236
201should do the trick. 237should do the trick.
202 238
@@ -204,52 +240,32 @@ When the driver is loaded successfully, the firmware file was in
204the right place and the device is connected, the "Power"-LED should be 240the right place and the device is connected, the "Power"-LED should be
205turned on. 241turned on.
206 242
207At this point you should be able to start a dvb-capable application. For myself 243At this point you should be able to start a dvb-capable application. I'm use
208I used mplayer, dvbscan, tzap and kaxtv, they are working. Using the device 244(t|s)zap, mplayer and dvbscan to test the basics. VDR-xine provides the
209in vdr is working now also. 245long-term test scenario.
210 246
2112. Known problems and bugs 2472. Known problems and bugs
212 248
213- Don't remove the USB device while running an DVB application, your system will die. 249- Don't remove the USB device while running an DVB application, your system
250 will go crazy or die most likely.
214 251
2152.1. Adding support for devices 2522.1. Adding support for devices
216 253
217It is not possible to determine the range of devices based on the DiBcom 254TODO
218reference designs. This is because the reference design of DiBcom can be sold
219to thirds, without telling DiBcom (so done with the Twinhan VP7041 and
220the HAMA device).
221
222When you think you have a device like this and the driver does not recognizes it,
223please send the ****load*.inf and the ****cap*.inf of the Windows driver to me.
224
225Sometimes the Vendor or Product ID is identical to the ones of Twinhan, even
226though it is not a Twinhan device (e.g. HAMA), then please send me the name
227of the device. I will add it to this list in order to make this clear to
228others.
229
230If you are familar with C you can also add the VID and PID of the device to
231the dvb-dibusb-core.c-file and create a patch and send it over to me or to
232the linux-dvb mailing list, _after_ you have tried compiling and modprobing
233it.
234 255
2352.2. USB1.1 Bandwidth limitation 2562.2. USB1.1 Bandwidth limitation
236 257
237Most of the currently supported devices are USB1.1 and thus they have a 258A lot of the currently supported devices are USB1.1 and thus they have a
238maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub. 259maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub.
239This is not enough for receiving the complete transport stream of a 260This is not enough for receiving the complete transport stream of a
240DVB-T channel (which can be about 16 MBit/s). Normally this is not a 261DVB-T channel (which is about 16 MBit/s). Normally this is not a
241problem, if you only want to watch TV (this does not apply for HDTV), 262problem, if you only want to watch TV (this does not apply for HDTV),
242but watching a channel while recording another channel on the same 263but watching a channel while recording another channel on the same
243frequency simply does not work very well. This applies to all USB1.1 264frequency simply does not work very well. This applies to all USB1.1
244DVB-T devices, not just dibusb) 265DVB-T devices, not just the dvb-usb-devices)
245
246Update: For the USB1.1 and VDR some work has been done (patches and comments
247are still very welcome). Maybe the problem is solved in the meantime because I
248now use the dmx_sw_filter function instead of dmx_sw_filter_packet. I hope the
249linux-dvb software filter is able to get the best of the garbled TS.
250 266
251The bug, where the TS is distorted by a heavy usage of the device is gone 267The bug, where the TS is distorted by a heavy usage of the device is gone
252definitely. All dibusb-devices I was using (Twinhan, Kworld, DiBcom) are 268definitely. All dvb-usb-devices I was using (Twinhan, Kworld, DiBcom) are
253working like charm now with VDR. Sometimes I even was able to record a channel 269working like charm now with VDR. Sometimes I even was able to record a channel
254and watch another one. 270and watch another one.
255 271
@@ -258,7 +274,7 @@ and watch another one.
258Patches, comments and suggestions are very very welcome. 274Patches, comments and suggestions are very very welcome.
259 275
2603. Acknowledgements 2763. Acknowledgements
261 Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for 277 Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
262 providing specs, code and help, on which the dvb-dibusb, dib3000mb and 278 providing specs, code and help, on which the dvb-dibusb, dib3000mb and
263 dib3000mc are based. 279 dib3000mc are based.
264 280
@@ -270,9 +286,16 @@ Patches, comments and suggestions are very very welcome.
270 286
271 Bernd Wagner for helping with huge bug reports and discussions. 287 Bernd Wagner for helping with huge bug reports and discussions.
272 288
273 Gunnar Wittich and Joachim von Caron for their trust for giving me 289 Gunnar Wittich and Joachim von Caron for their trust for providing
274 root-shells on their machines to implement support for new devices. 290 root-shells on their machines to implement support for new devices.
275 291
292 Glen Harris for bringing up, that there is a new dibusb-device and Jiun-Kuei
293 Jung from AVerMedia who kindly provided a special firmware to get the device
294 up and running in Linux.
295
296 Jennifer Chen, Jeff and Jack from Twinhan for kindly supporting by
297 writing the vp7045-driver.
298
276 Some guys on the linux-dvb mailing list for encouraging me 299 Some guys on the linux-dvb mailing list for encouraging me
277 300
278 Peter Schildmann >peter.schildmann-nospam-at-web.de< for his 301 Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
@@ -282,4 +305,4 @@ Patches, comments and suggestions are very very welcome.
282 Ulf Hermenau for helping me out with traditional chinese. 305 Ulf Hermenau for helping me out with traditional chinese.
283 306
284 André Smoktun and Christian Frömmel for supporting me with 307 André Smoktun and Christian Frömmel for supporting me with
285 hardware and listening to my problems very patient 308 hardware and listening to my problems very patient.
diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt
index b5cb9110cc..d16334ec48 100644
--- a/Documentation/filesystems/ext2.txt
+++ b/Documentation/filesystems/ext2.txt
@@ -58,6 +58,8 @@ noacl Don't support POSIX ACLs.
58 58
59nobh Do not attach buffer_heads to file pagecache. 59nobh Do not attach buffer_heads to file pagecache.
60 60
61xip Use execute in place (no caching) if possible
62
61grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. 63grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
62 64
63 65
diff --git a/Documentation/filesystems/xip.txt b/Documentation/filesystems/xip.txt
new file mode 100644
index 0000000000..6c0cef10eb
--- /dev/null
+++ b/Documentation/filesystems/xip.txt
@@ -0,0 +1,67 @@
1Execute-in-place for file mappings
2----------------------------------
3
4Motivation
5----------
6File mappings are performed by mapping page cache pages to userspace. In
7addition, read&write type file operations also transfer data from/to the page
8cache.
9
10For memory backed storage devices that use the block device interface, the page
11cache pages are in fact copies of the original storage. Various approaches
12exist to work around the need for an extra copy. The ramdisk driver for example
13does read the data into the page cache, keeps a reference, and discards the
14original data behind later on.
15
16Execute-in-place solves this issue the other way around: instead of keeping
17data in the page cache, the need to have a page cache copy is eliminated
18completely. With execute-in-place, read&write type operations are performed
19directly from/to the memory backed storage device. For file mappings, the
20storage device itself is mapped directly into userspace.
21
22This implementation was initialy written for shared memory segments between
23different virtual machines on s390 hardware to allow multiple machines to
24share the same binaries and libraries.
25
26Implementation
27--------------
28Execute-in-place is implemented in three steps: block device operation,
29address space operation, and file operations.
30
31A block device operation named direct_access is used to retrieve a
32reference (pointer) to a block on-disk. The reference is supposed to be
33cpu-addressable, physical address and remain valid until the release operation
34is performed. A struct block_device reference is used to address the device,
35and a sector_t argument is used to identify the individual block. As an
36alternative, memory technology devices can be used for this.
37
38The block device operation is optional, these block devices support it as of
39today:
40- dcssblk: s390 dcss block device driver
41
42An address space operation named get_xip_page is used to retrieve reference
43to a struct page. To address the target page, a reference to an address_space,
44and a sector number is provided. A 3rd argument indicates whether the
45function should allocate blocks if needed.
46
47This address space operation is mutually exclusive with readpage&writepage that
48do page cache read/write operations.
49The following filesystems support it as of today:
50- ext2: the second extended filesystem, see Documentation/filesystems/ext2.txt
51
52A set of file operations that do utilize get_xip_page can be found in
53mm/filemap_xip.c . The following file operation implementations are provided:
54- aio_read/aio_write
55- readv/writev
56- sendfile
57
58The generic file operations do_sync_read/do_sync_write can be used to implement
59classic synchronous IO calls.
60
61Shortcomings
62------------
63This implementation is limited to storage devices that are cpu addressable at
64all times (no highmem or such). It works well on rom/ram, but enhancements are
65needed to make it work with flash in read+write mode.
66Putting the Linux kernel and/or its modules on a xip filesystem does not mean
67they are not copied.
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 36d80aeeaf..0321ded4b9 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -22,6 +22,7 @@ This document has the following sections:
22 - New procfs files 22 - New procfs files
23 - Userspace system call interface 23 - Userspace system call interface
24 - Kernel services 24 - Kernel services
25 - Notes on accessing payload contents
25 - Defining a key type 26 - Defining a key type
26 - Request-key callback service 27 - Request-key callback service
27 - Key access filesystem 28 - Key access filesystem
@@ -45,27 +46,26 @@ Each key has a number of attributes:
45 - State. 46 - State.
46 47
47 48
48 (*) Each key is issued a serial number of type key_serial_t that is unique 49 (*) Each key is issued a serial number of type key_serial_t that is unique for
49 for the lifetime of that key. All serial numbers are positive non-zero 50 the lifetime of that key. All serial numbers are positive non-zero 32-bit
50 32-bit integers. 51 integers.
51 52
52 Userspace programs can use a key's serial numbers as a way to gain access 53 Userspace programs can use a key's serial numbers as a way to gain access
53 to it, subject to permission checking. 54 to it, subject to permission checking.
54 55
55 (*) Each key is of a defined "type". Types must be registered inside the 56 (*) Each key is of a defined "type". Types must be registered inside the
56 kernel by a kernel service (such as a filesystem) before keys of that 57 kernel by a kernel service (such as a filesystem) before keys of that type
57 type can be added or used. Userspace programs cannot define new types 58 can be added or used. Userspace programs cannot define new types directly.
58 directly.
59 59
60 Key types are represented in the kernel by struct key_type. This defines 60 Key types are represented in the kernel by struct key_type. This defines a
61 a number of operations that can be performed on a key of that type. 61 number of operations that can be performed on a key of that type.
62 62
63 Should a type be removed from the system, all the keys of that type will 63 Should a type be removed from the system, all the keys of that type will
64 be invalidated. 64 be invalidated.
65 65
66 (*) Each key has a description. This should be a printable string. The key 66 (*) Each key has a description. This should be a printable string. The key
67 type provides an operation to perform a match between the description on 67 type provides an operation to perform a match between the description on a
68 a key and a criterion string. 68 key and a criterion string.
69 69
70 (*) Each key has an owner user ID, a group ID and a permissions mask. These 70 (*) Each key has an owner user ID, a group ID and a permissions mask. These
71 are used to control what a process may do to a key from userspace, and 71 are used to control what a process may do to a key from userspace, and
@@ -74,10 +74,10 @@ Each key has a number of attributes:
74 (*) Each key can be set to expire at a specific time by the key type's 74 (*) Each key can be set to expire at a specific time by the key type's
75 instantiation function. Keys can also be immortal. 75 instantiation function. Keys can also be immortal.
76 76
77 (*) Each key can have a payload. This is a quantity of data that represent 77 (*) Each key can have a payload. This is a quantity of data that represent the
78 the actual "key". In the case of a keyring, this is a list of keys to 78 actual "key". In the case of a keyring, this is a list of keys to which
79 which the keyring links; in the case of a user-defined key, it's an 79 the keyring links; in the case of a user-defined key, it's an arbitrary
80 arbitrary blob of data. 80 blob of data.
81 81
82 Having a payload is not required; and the payload can, in fact, just be a 82 Having a payload is not required; and the payload can, in fact, just be a
83 value stored in the struct key itself. 83 value stored in the struct key itself.
@@ -92,8 +92,8 @@ Each key has a number of attributes:
92 92
93 (*) Each key can be in one of a number of basic states: 93 (*) Each key can be in one of a number of basic states:
94 94
95 (*) Uninstantiated. The key exists, but does not have any data 95 (*) Uninstantiated. The key exists, but does not have any data attached.
96 attached. Keys being requested from userspace will be in this state. 96 Keys being requested from userspace will be in this state.
97 97
98 (*) Instantiated. This is the normal state. The key is fully formed, and 98 (*) Instantiated. This is the normal state. The key is fully formed, and
99 has data attached. 99 has data attached.
@@ -140,10 +140,10 @@ The key service provides a number of features besides keys:
140 clone, fork, vfork or execve occurs. A new keyring is created only when 140 clone, fork, vfork or execve occurs. A new keyring is created only when
141 required. 141 required.
142 142
143 The process-specific keyring is replaced with an empty one in the child 143 The process-specific keyring is replaced with an empty one in the child on
144 on clone, fork, vfork unless CLONE_THREAD is supplied, in which case it 144 clone, fork, vfork unless CLONE_THREAD is supplied, in which case it is
145 is shared. execve also discards the process's process keyring and creates 145 shared. execve also discards the process's process keyring and creates a
146 a new one. 146 new one.
147 147
148 The session-specific keyring is persistent across clone, fork, vfork and 148 The session-specific keyring is persistent across clone, fork, vfork and
149 execve, even when the latter executes a set-UID or set-GID binary. A 149 execve, even when the latter executes a set-UID or set-GID binary. A
@@ -177,11 +177,11 @@ The key service provides a number of features besides keys:
177 If a system call that modifies a key or keyring in some way would put the 177 If a system call that modifies a key or keyring in some way would put the
178 user over quota, the operation is refused and error EDQUOT is returned. 178 user over quota, the operation is refused and error EDQUOT is returned.
179 179
180 (*) There's a system call interface by which userspace programs can create 180 (*) There's a system call interface by which userspace programs can create and
181 and manipulate keys and keyrings. 181 manipulate keys and keyrings.
182 182
183 (*) There's a kernel interface by which services can register types and 183 (*) There's a kernel interface by which services can register types and search
184 search for keys. 184 for keys.
185 185
186 (*) There's a way for the a search done from the kernel to call back to 186 (*) There's a way for the a search done from the kernel to call back to
187 userspace to request a key that can't be found in a process's keyrings. 187 userspace to request a key that can't be found in a process's keyrings.
@@ -194,9 +194,9 @@ The key service provides a number of features besides keys:
194KEY ACCESS PERMISSIONS 194KEY ACCESS PERMISSIONS
195====================== 195======================
196 196
197Keys have an owner user ID, a group access ID, and a permissions mask. The 197Keys have an owner user ID, a group access ID, and a permissions mask. The mask
198mask has up to eight bits each for user, group and other access. Only five of 198has up to eight bits each for user, group and other access. Only five of each
199each set of eight bits are defined. These permissions granted are: 199set of eight bits are defined. These permissions granted are:
200 200
201 (*) View 201 (*) View
202 202
@@ -210,8 +210,8 @@ each set of eight bits are defined. These permissions granted are:
210 210
211 (*) Write 211 (*) Write
212 212
213 This permits a key's payload to be instantiated or updated, or it allows 213 This permits a key's payload to be instantiated or updated, or it allows a
214 a link to be added to or removed from a keyring. 214 link to be added to or removed from a keyring.
215 215
216 (*) Search 216 (*) Search
217 217
@@ -238,8 +238,8 @@ about the status of the key service:
238 (*) /proc/keys 238 (*) /proc/keys
239 239
240 This lists all the keys on the system, giving information about their 240 This lists all the keys on the system, giving information about their
241 type, description and permissions. The payload of the key is not 241 type, description and permissions. The payload of the key is not available
242 available this way: 242 this way:
243 243
244 SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY 244 SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
245 00000001 I----- 39 perm 1f0000 0 0 keyring _uid_ses.0: 1/4 245 00000001 I----- 39 perm 1f0000 0 0 keyring _uid_ses.0: 1/4
@@ -318,21 +318,21 @@ The main syscalls are:
318 If a key of the same type and description as that proposed already exists 318 If a key of the same type and description as that proposed already exists
319 in the keyring, this will try to update it with the given payload, or it 319 in the keyring, this will try to update it with the given payload, or it
320 will return error EEXIST if that function is not supported by the key 320 will return error EEXIST if that function is not supported by the key
321 type. The process must also have permission to write to the key to be 321 type. The process must also have permission to write to the key to be able
322 able to update it. The new key will have all user permissions granted and 322 to update it. The new key will have all user permissions granted and no
323 no group or third party permissions. 323 group or third party permissions.
324 324
325 Otherwise, this will attempt to create a new key of the specified type 325 Otherwise, this will attempt to create a new key of the specified type and
326 and description, and to instantiate it with the supplied payload and 326 description, and to instantiate it with the supplied payload and attach it
327 attach it to the keyring. In this case, an error will be generated if the 327 to the keyring. In this case, an error will be generated if the process
328 process does not have permission to write to the keyring. 328 does not have permission to write to the keyring.
329 329
330 The payload is optional, and the pointer can be NULL if not required by 330 The payload is optional, and the pointer can be NULL if not required by
331 the type. The payload is plen in size, and plen can be zero for an empty 331 the type. The payload is plen in size, and plen can be zero for an empty
332 payload. 332 payload.
333 333
334 A new keyring can be generated by setting type "keyring", the keyring 334 A new keyring can be generated by setting type "keyring", the keyring name
335 name as the description (or NULL) and setting the payload to NULL. 335 as the description (or NULL) and setting the payload to NULL.
336 336
337 User defined keys can be created by specifying type "user". It is 337 User defined keys can be created by specifying type "user". It is
338 recommended that a user defined key's description by prefixed with a type 338 recommended that a user defined key's description by prefixed with a type
@@ -369,9 +369,9 @@ The keyctl syscall functions are:
369 key_serial_t keyctl(KEYCTL_GET_KEYRING_ID, key_serial_t id, 369 key_serial_t keyctl(KEYCTL_GET_KEYRING_ID, key_serial_t id,
370 int create); 370 int create);
371 371
372 The special key specified by "id" is looked up (with the key being 372 The special key specified by "id" is looked up (with the key being created
373 created if necessary) and the ID of the key or keyring thus found is 373 if necessary) and the ID of the key or keyring thus found is returned if
374 returned if it exists. 374 it exists.
375 375
376 If the key does not yet exist, the key will be created if "create" is 376 If the key does not yet exist, the key will be created if "create" is
377 non-zero; and the error ENOKEY will be returned if "create" is zero. 377 non-zero; and the error ENOKEY will be returned if "create" is zero.
@@ -402,8 +402,8 @@ The keyctl syscall functions are:
402 402
403 This will try to update the specified key with the given payload, or it 403 This will try to update the specified key with the given payload, or it
404 will return error EOPNOTSUPP if that function is not supported by the key 404 will return error EOPNOTSUPP if that function is not supported by the key
405 type. The process must also have permission to write to the key to be 405 type. The process must also have permission to write to the key to be able
406 able to update it. 406 to update it.
407 407
408 The payload is of length plen, and may be absent or empty as for 408 The payload is of length plen, and may be absent or empty as for
409 add_key(). 409 add_key().
@@ -422,8 +422,8 @@ The keyctl syscall functions are:
422 422
423 long keyctl(KEYCTL_CHOWN, key_serial_t key, uid_t uid, gid_t gid); 423 long keyctl(KEYCTL_CHOWN, key_serial_t key, uid_t uid, gid_t gid);
424 424
425 This function permits a key's owner and group ID to be changed. Either 425 This function permits a key's owner and group ID to be changed. Either one
426 one of uid or gid can be set to -1 to suppress that change. 426 of uid or gid can be set to -1 to suppress that change.
427 427
428 Only the superuser can change a key's owner to something other than the 428 Only the superuser can change a key's owner to something other than the
429 key's current owner. Similarly, only the superuser can change a key's 429 key's current owner. Similarly, only the superuser can change a key's
@@ -484,12 +484,12 @@ The keyctl syscall functions are:
484 484
485 long keyctl(KEYCTL_LINK, key_serial_t keyring, key_serial_t key); 485 long keyctl(KEYCTL_LINK, key_serial_t keyring, key_serial_t key);
486 486
487 This function creates a link from the keyring to the key. The process 487 This function creates a link from the keyring to the key. The process must
488 must have write permission on the keyring and must have link permission 488 have write permission on the keyring and must have link permission on the
489 on the key. 489 key.
490 490
491 Should the keyring not be a keyring, error ENOTDIR will result; and if 491 Should the keyring not be a keyring, error ENOTDIR will result; and if the
492 the keyring is full, error ENFILE will result. 492 keyring is full, error ENFILE will result.
493 493
494 The link procedure checks the nesting of the keyrings, returning ELOOP if 494 The link procedure checks the nesting of the keyrings, returning ELOOP if
495 it appears to deep or EDEADLK if the link would introduce a cycle. 495 it appears to deep or EDEADLK if the link would introduce a cycle.
@@ -503,8 +503,8 @@ The keyctl syscall functions are:
503 specified key, and removes it if found. Subsequent links to that key are 503 specified key, and removes it if found. Subsequent links to that key are
504 ignored. The process must have write permission on the keyring. 504 ignored. The process must have write permission on the keyring.
505 505
506 If the keyring is not a keyring, error ENOTDIR will result; and if the 506 If the keyring is not a keyring, error ENOTDIR will result; and if the key
507 key is not present, error ENOENT will be the result. 507 is not present, error ENOENT will be the result.
508 508
509 509
510 (*) Search a keyring tree for a key: 510 (*) Search a keyring tree for a key:
@@ -513,9 +513,9 @@ The keyctl syscall functions are:
513 const char *type, const char *description, 513 const char *type, const char *description,
514 key_serial_t dest_keyring); 514 key_serial_t dest_keyring);
515 515
516 This searches the keyring tree headed by the specified keyring until a 516 This searches the keyring tree headed by the specified keyring until a key
517 key is found that matches the type and description criteria. Each keyring 517 is found that matches the type and description criteria. Each keyring is
518 is checked for keys before recursion into its children occurs. 518 checked for keys before recursion into its children occurs.
519 519
520 The process must have search permission on the top level keyring, or else 520 The process must have search permission on the top level keyring, or else
521 error EACCES will result. Only keyrings that the process has search 521 error EACCES will result. Only keyrings that the process has search
@@ -549,8 +549,8 @@ The keyctl syscall functions are:
549 As much of the data as can be fitted into the buffer will be copied to 549 As much of the data as can be fitted into the buffer will be copied to
550 userspace if the buffer pointer is not NULL. 550 userspace if the buffer pointer is not NULL.
551 551
552 On a successful return, the function will always return the amount of 552 On a successful return, the function will always return the amount of data
553 data available rather than the amount copied. 553 available rather than the amount copied.
554 554
555 555
556 (*) Instantiate a partially constructed key. 556 (*) Instantiate a partially constructed key.
@@ -568,8 +568,8 @@ The keyctl syscall functions are:
568 it, and the key must be uninstantiated. 568 it, and the key must be uninstantiated.
569 569
570 If a keyring is specified (non-zero), the key will also be linked into 570 If a keyring is specified (non-zero), the key will also be linked into
571 that keyring, however all the constraints applying in KEYCTL_LINK apply 571 that keyring, however all the constraints applying in KEYCTL_LINK apply in
572 in this case too. 572 this case too.
573 573
574 The payload and plen arguments describe the payload data as for add_key(). 574 The payload and plen arguments describe the payload data as for add_key().
575 575
@@ -587,8 +587,39 @@ The keyctl syscall functions are:
587 it, and the key must be uninstantiated. 587 it, and the key must be uninstantiated.
588 588
589 If a keyring is specified (non-zero), the key will also be linked into 589 If a keyring is specified (non-zero), the key will also be linked into
590 that keyring, however all the constraints applying in KEYCTL_LINK apply 590 that keyring, however all the constraints applying in KEYCTL_LINK apply in
591 in this case too. 591 this case too.
592
593
594 (*) Set the default request-key destination keyring.
595
596 long keyctl(KEYCTL_SET_REQKEY_KEYRING, int reqkey_defl);
597
598 This sets the default keyring to which implicitly requested keys will be
599 attached for this thread. reqkey_defl should be one of these constants:
600
601 CONSTANT VALUE NEW DEFAULT KEYRING
602 ====================================== ====== =======================
603 KEY_REQKEY_DEFL_NO_CHANGE -1 No change
604 KEY_REQKEY_DEFL_DEFAULT 0 Default[1]
605 KEY_REQKEY_DEFL_THREAD_KEYRING 1 Thread keyring
606 KEY_REQKEY_DEFL_PROCESS_KEYRING 2 Process keyring
607 KEY_REQKEY_DEFL_SESSION_KEYRING 3 Session keyring
608 KEY_REQKEY_DEFL_USER_KEYRING 4 User keyring
609 KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5 User session keyring
610 KEY_REQKEY_DEFL_GROUP_KEYRING 6 Group keyring
611
612 The old default will be returned if successful and error EINVAL will be
613 returned if reqkey_defl is not one of the above values.
614
615 The default keyring can be overridden by the keyring indicated to the
616 request_key() system call.
617
618 Note that this setting is inherited across fork/exec.
619
620 [1] The default default is: the thread keyring if there is one, otherwise
621 the process keyring if there is one, otherwise the session keyring if
622 there is one, otherwise the user default session keyring.
592 623
593 624
594=============== 625===============
@@ -601,17 +632,14 @@ be broken down into two areas: keys and key types.
601Dealing with keys is fairly straightforward. Firstly, the kernel service 632Dealing with keys is fairly straightforward. Firstly, the kernel service
602registers its type, then it searches for a key of that type. It should retain 633registers its type, then it searches for a key of that type. It should retain
603the key as long as it has need of it, and then it should release it. For a 634the key as long as it has need of it, and then it should release it. For a
604filesystem or device file, a search would probably be performed during the 635filesystem or device file, a search would probably be performed during the open
605open call, and the key released upon close. How to deal with conflicting keys 636call, and the key released upon close. How to deal with conflicting keys due to
606due to two different users opening the same file is left to the filesystem 637two different users opening the same file is left to the filesystem author to
607author to solve. 638solve.
608 639
609When accessing a key's payload data, key->lock should be at least read locked, 640When accessing a key's payload contents, certain precautions must be taken to
610or else the data may be changed by an update being performed from userspace 641prevent access vs modification races. See the section "Notes on accessing
611whilst the driver or filesystem is trying to access it. If no update method is 642payload contents" for more information.
612supplied, then the key's payload may be accessed without holding a lock as
613there is no way to change it, provided it can be guaranteed that the key's
614type definition won't go away.
615 643
616(*) To search for a key, call: 644(*) To search for a key, call:
617 645
@@ -629,6 +657,9 @@ type definition won't go away.
629 Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be 657 Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be
630 returned. 658 returned.
631 659
660 If successful, the key will have been attached to the default keyring for
661 implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING.
662
632 663
633(*) When it is no longer required, the key should be released using: 664(*) When it is no longer required, the key should be released using:
634 665
@@ -690,6 +721,54 @@ type definition won't go away.
690 void unregister_key_type(struct key_type *type); 721 void unregister_key_type(struct key_type *type);
691 722
692 723
724===================================
725NOTES ON ACCESSING PAYLOAD CONTENTS
726===================================
727
728The simplest payload is just a number in key->payload.value. In this case,
729there's no need to indulge in RCU or locking when accessing the payload.
730
731More complex payload contents must be allocated and a pointer to them set in
732key->payload.data. One of the following ways must be selected to access the
733data:
734
735 (1) Unmodifyable key type.
736
737 If the key type does not have a modify method, then the key's payload can
738 be accessed without any form of locking, provided that it's known to be
739 instantiated (uninstantiated keys cannot be "found").
740
741 (2) The key's semaphore.
742
743 The semaphore could be used to govern access to the payload and to control
744 the payload pointer. It must be write-locked for modifications and would
745 have to be read-locked for general access. The disadvantage of doing this
746 is that the accessor may be required to sleep.
747
748 (3) RCU.
749
750 RCU must be used when the semaphore isn't already held; if the semaphore
751 is held then the contents can't change under you unexpectedly as the
752 semaphore must still be used to serialise modifications to the key. The
753 key management code takes care of this for the key type.
754
755 However, this means using:
756
757 rcu_read_lock() ... rcu_dereference() ... rcu_read_unlock()
758
759 to read the pointer, and:
760
761 rcu_dereference() ... rcu_assign_pointer() ... call_rcu()
762
763 to set the pointer and dispose of the old contents after a grace period.
764 Note that only the key type should ever modify a key's payload.
765
766 Furthermore, an RCU controlled payload must hold a struct rcu_head for the
767 use of call_rcu() and, if the payload is of variable size, the length of
768 the payload. key->datalen cannot be relied upon to be consistent with the
769 payload just dereferenced if the key's semaphore is not held.
770
771
693=================== 772===================
694DEFINING A KEY TYPE 773DEFINING A KEY TYPE
695=================== 774===================
@@ -717,15 +796,15 @@ The structure has a number of fields, some of which are mandatory:
717 796
718 int key_payload_reserve(struct key *key, size_t datalen); 797 int key_payload_reserve(struct key *key, size_t datalen);
719 798
720 With the revised data length. Error EDQUOT will be returned if this is 799 With the revised data length. Error EDQUOT will be returned if this is not
721 not viable. 800 viable.
722 801
723 802
724 (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); 803 (*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
725 804
726 This method is called to attach a payload to a key during construction. 805 This method is called to attach a payload to a key during construction.
727 The payload attached need not bear any relation to the data passed to 806 The payload attached need not bear any relation to the data passed to this
728 this function. 807 function.
729 808
730 If the amount of data attached to the key differs from the size in 809 If the amount of data attached to the key differs from the size in
731 keytype->def_datalen, then key_payload_reserve() should be called. 810 keytype->def_datalen, then key_payload_reserve() should be called.
@@ -734,38 +813,47 @@ The structure has a number of fields, some of which are mandatory:
734 The fact that KEY_FLAG_INSTANTIATED is not set in key->flags prevents 813 The fact that KEY_FLAG_INSTANTIATED is not set in key->flags prevents
735 anything else from gaining access to the key. 814 anything else from gaining access to the key.
736 815
737 This method may sleep if it wishes. 816 It is safe to sleep in this method.
738 817
739 818
740 (*) int (*duplicate)(struct key *key, const struct key *source); 819 (*) int (*duplicate)(struct key *key, const struct key *source);
741 820
742 If this type of key can be duplicated, then this method should be 821 If this type of key can be duplicated, then this method should be
743 provided. It is called to copy the payload attached to the source into 822 provided. It is called to copy the payload attached to the source into the
744 the new key. The data length on the new key will have been updated and 823 new key. The data length on the new key will have been updated and the
745 the quota adjusted already. 824 quota adjusted already.
746 825
747 This method will be called with the source key's semaphore read-locked to 826 This method will be called with the source key's semaphore read-locked to
748 prevent its payload from being changed. It is safe to sleep here. 827 prevent its payload from being changed, thus RCU constraints need not be
828 applied to the source key.
829
830 This method does not have to lock the destination key in order to attach a
831 payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags
832 prevents anything else from gaining access to the key.
833
834 It is safe to sleep in this method.
749 835
750 836
751 (*) int (*update)(struct key *key, const void *data, size_t datalen); 837 (*) int (*update)(struct key *key, const void *data, size_t datalen);
752 838
753 If this type of key can be updated, then this method should be 839 If this type of key can be updated, then this method should be provided.
754 provided. It is called to update a key's payload from the blob of data 840 It is called to update a key's payload from the blob of data provided.
755 provided.
756 841
757 key_payload_reserve() should be called if the data length might change 842 key_payload_reserve() should be called if the data length might change
758 before any changes are actually made. Note that if this succeeds, the 843 before any changes are actually made. Note that if this succeeds, the type
759 type is committed to changing the key because it's already been altered, 844 is committed to changing the key because it's already been altered, so all
760 so all memory allocation must be done first. 845 memory allocation must be done first.
846
847 The key will have its semaphore write-locked before this method is called,
848 but this only deters other writers; any changes to the key's payload must
849 be made under RCU conditions, and call_rcu() must be used to dispose of
850 the old payload.
761 851
762 key_payload_reserve() should be called with the key->lock write locked, 852 key_payload_reserve() should be called before the changes are made, but
763 and the changes to the key's attached payload should be made before the 853 after all allocations and other potentially failing function calls are
764 key is locked. 854 made.
765 855
766 The key will have its semaphore write-locked before this method is 856 It is safe to sleep in this method.
767 called. Any changes to the key should be made with the key's rwlock
768 write-locked also. It is safe to sleep here.
769 857
770 858
771 (*) int (*match)(const struct key *key, const void *desc); 859 (*) int (*match)(const struct key *key, const void *desc);
@@ -782,12 +870,12 @@ The structure has a number of fields, some of which are mandatory:
782 870
783 (*) void (*destroy)(struct key *key); 871 (*) void (*destroy)(struct key *key);
784 872
785 This method is optional. It is called to discard the payload data on a 873 This method is optional. It is called to discard the payload data on a key
786 key when it is being destroyed. 874 when it is being destroyed.
787 875
788 This method does not need to lock the key; it can consider the key as 876 This method does not need to lock the key to access the payload; it can
789 being inaccessible. Note that the key's type may have changed before this 877 consider the key as being inaccessible at this time. Note that the key's
790 function is called. 878 type may have been changed before this function is called.
791 879
792 It is not safe to sleep in this method; the caller may hold spinlocks. 880 It is not safe to sleep in this method; the caller may hold spinlocks.
793 881
@@ -797,26 +885,31 @@ The structure has a number of fields, some of which are mandatory:
797 This method is optional. It is called during /proc/keys reading to 885 This method is optional. It is called during /proc/keys reading to
798 summarise a key's description and payload in text form. 886 summarise a key's description and payload in text form.
799 887
800 This method will be called with the key's rwlock read-locked. This will 888 This method will be called with the RCU read lock held. rcu_dereference()
801 prevent the key's payload and state changing; also the description should 889 should be used to read the payload pointer if the payload is to be
802 not change. This also means it is not safe to sleep in this method. 890 accessed. key->datalen cannot be trusted to stay consistent with the
891 contents of the payload.
892
893 The description will not change, though the key's state may.
894
895 It is not safe to sleep in this method; the RCU read lock is held by the
896 caller.
803 897
804 898
805 (*) long (*read)(const struct key *key, char __user *buffer, size_t buflen); 899 (*) long (*read)(const struct key *key, char __user *buffer, size_t buflen);
806 900
807 This method is optional. It is called by KEYCTL_READ to translate the 901 This method is optional. It is called by KEYCTL_READ to translate the
808 key's payload into something a blob of data for userspace to deal 902 key's payload into something a blob of data for userspace to deal with.
809 with. Ideally, the blob should be in the same format as that passed in to 903 Ideally, the blob should be in the same format as that passed in to the
810 the instantiate and update methods. 904 instantiate and update methods.
811 905
812 If successful, the blob size that could be produced should be returned 906 If successful, the blob size that could be produced should be returned
813 rather than the size copied. 907 rather than the size copied.
814 908
815 This method will be called with the key's semaphore read-locked. This 909 This method will be called with the key's semaphore read-locked. This will
816 will prevent the key's payload changing. It is not necessary to also 910 prevent the key's payload changing. It is not necessary to use RCU locking
817 read-lock key->lock when accessing the key's payload. It is safe to sleep 911 when accessing the key's payload. It is safe to sleep in this method, such
818 in this method, such as might happen when the userspace buffer is 912 as might happen when the userspace buffer is accessed.
819 accessed.
820 913
821 914
822============================ 915============================
@@ -853,8 +946,8 @@ If it returns with the key remaining in the unconstructed state, the key will
853be marked as being negative, it will be added to the session keyring, and an 946be marked as being negative, it will be added to the session keyring, and an
854error will be returned to the key requestor. 947error will be returned to the key requestor.
855 948
856Supplementary information may be provided from whoever or whatever invoked 949Supplementary information may be provided from whoever or whatever invoked this
857this service. This will be passed as the <callout_info> parameter. If no such 950service. This will be passed as the <callout_info> parameter. If no such
858information was made available, then "-" will be passed as this parameter 951information was made available, then "-" will be passed as this parameter
859instead. 952instead.
860 953
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index e46761c39e..aeeafec059 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -119,3 +119,17 @@ card=117 - NGS NGSTV+
119card=118 - LMLBT4 119card=118 - LMLBT4
120card=119 - Tekram M205 PRO 120card=119 - Tekram M205 PRO
121card=120 - Conceptronic CONTVFMi 121card=120 - Conceptronic CONTVFMi
122card=121 - Euresys Picolo Tetra
123card=122 - Spirit TV Tuner
124card=123 - AVerMedia AVerTV DVB-T 771
125card=124 - AverMedia AverTV DVB-T 761
126card=125 - MATRIX Vision Sigma-SQ
127card=126 - MATRIX Vision Sigma-SLC
128card=127 - APAC Viewcomp 878(AMAX)
129card=128 - DVICO FusionHDTV DVB-T Lite
130card=129 - V-Gear MyVCD
131card=130 - Super TV Tuner
132card=131 - Tibet Systems 'Progress DVR' CS16
133card=132 - Kodicom 4400R (master)
134card=133 - Kodicom 4400R (slave)
135card=134 - Adlink RTV24
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
new file mode 100644
index 0000000000..216f705495
--- /dev/null
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -0,0 +1,29 @@
1card=0 - UNKNOWN/GENERIC
2card=1 - Hauppauge WinTV 34xxx models
3card=2 - GDI Black Gold
4card=3 - PixelView
5card=4 - ATI TV Wonder Pro
6card=5 - Leadtek Winfast 2000XP Expert
7card=6 - AverTV Studio 303 (M126)
8card=7 - MSI TV-@nywhere Master
9card=8 - Leadtek Winfast DV2000
10card=9 - Leadtek PVR 2000
11card=10 - IODATA GV-VCP3/PCI
12card=11 - Prolink PlayTV PVR
13card=12 - ASUS PVR-416
14card=13 - MSI TV-@nywhere
15card=14 - KWorld/VStream XPert DVB-T
16card=15 - DVICO FusionHDTV DVB-T1
17card=16 - KWorld LTV883RF
18card=17 - DViCO - FusionHDTV 3 Gold
19card=18 - Hauppauge Nova-T DVB-T
20card=19 - Conexant DVB-T reference design
21card=20 - Provideo PV259
22card=21 - DVICO FusionHDTV DVB-T Plus
23card=22 - digitalnow DNTV Live! DVB-T
24card=23 - pcHDTV HD3000 HDTV
25card=24 - Hauppauge WinTV 28xxx (Roslyn) models
26card=25 - Digital-Logic MICROSPACE Entertainment Center (MEC)
27card=26 - IODATA GV/BCTV7E
28card=27 - PixelView PlayTV Ultra Pro (Stereo)
29card=28 - DViCO - FusionHDTV 3 Gold-T
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index a6c82fa4de..d5ed95d285 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -20,16 +20,37 @@
20 19 -> Compro VideoMate TV [185b:c100] 20 19 -> Compro VideoMate TV [185b:c100]
21 20 -> Matrox CronosPlus [102B:48d0] 21 20 -> Matrox CronosPlus [102B:48d0]
22 21 -> 10MOONS PCI TV CAPTURE CARD [1131:2001] 22 21 -> 10MOONS PCI TV CAPTURE CARD [1131:2001]
23 22 -> Medion 2819/ AverMedia M156 [1461:a70b,1461:2115] 23 22 -> AverMedia M156 / Medion 2819 [1461:a70b]
24 23 -> BMK MPEX Tuner 24 23 -> BMK MPEX Tuner
25 24 -> KNC One TV-Station DVR [1894:a006] 25 24 -> KNC One TV-Station DVR [1894:a006]
26 25 -> ASUS TV-FM 7133 [1043:4843] 26 25 -> ASUS TV-FM 7133 [1043:4843]
27 26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b] 27 26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b]
28 27 -> Manli MuchTV M-TV002 28 27 -> Manli MuchTV M-TV002/Behold TV 403 FM
29 28 -> Manli MuchTV M-TV001 29 28 -> Manli MuchTV M-TV001/Behold TV 401
30 29 -> Nagase Sangyo TransGear 3000TV [1461:050c] 30 29 -> Nagase Sangyo TransGear 3000TV [1461:050c]
31 30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4] 31 30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4]
32 31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5] 32 31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
33 32 -> AVACS SmartTV 33 32 -> AVACS SmartTV
34 33 -> AVerMedia DVD EZMaker [1461:10ff] 34 33 -> AVerMedia DVD EZMaker [1461:10ff]
35 34 -> LifeView FlyTV Platinum33 mini [5168:0212] 35 34 -> Noval Prime TV 7133
36 35 -> AverMedia AverTV Studio 305 [1461:2115]
37 37 -> Items MuchTV Plus / IT-005
38 38 -> Terratec Cinergy 200 TV [153B:1152]
39 39 -> LifeView FlyTV Platinum Mini [5168:0212]
40 40 -> Compro VideoMate TV PVR/FM [185b:c100]
41 41 -> Compro VideoMate TV Gold+ [185b:c100]
42 42 -> Sabrent SBT-TVFM (saa7130)
43 43 -> :Zolid Xpert TV7134
44 44 -> Empire PCI TV-Radio LE
45 45 -> Avermedia AVerTV Studio 307 [1461:9715]
46 46 -> AVerMedia Cardbus TV/Radio [1461:d6ee]
47 47 -> Terratec Cinergy 400 mobile [153b:1162]
48 48 -> Terratec Cinergy 600 TV MK3 [153B:1158]
49 49 -> Compro VideoMate Gold+ Pal [185b:c200]
50 50 -> Pinnacle PCTV 300i DVB-T + PAL [11bd:002d]
51 51 -> ProVideo PV952 [1540:9524]
52 52 -> AverMedia AverTV/305 [1461:2108]
53 54 -> LifeView FlyTV Platinum FM [5168:0214,1489:0214]
54 55 -> LifeView FlyDVB-T DUO [5168:0306]
55 56 -> Avermedia AVerTV 307 [1461:a70a]
56 57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
index f7bafe862b..aeb8df8ce8 100644
--- a/Documentation/video4linux/CARDLIST.tuner
+++ b/Documentation/video4linux/CARDLIST.tuner
@@ -44,3 +44,18 @@ tuner=42 - Philips 1236D ATSC/NTSC daul in
44tuner=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F) 44tuner=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F)
45tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant) 45tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
46tuner=45 - Microtune 4049 FM5 46tuner=45 - Microtune 4049 FM5
47tuner=46 - Panasonic VP27s/ENGE4324D
48tuner=47 - LG NTSC (TAPE series)
49tuner=48 - Tenna TNF 8831 BGFF)
50tuner=49 - Microtune 4042 FI5 ATSC/NTSC dual in
51tuner=50 - TCL 2002N
52tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
53tuner=52 - Thomson DDT 7610 (ATSC/NTSC)
54tuner=53 - Philips FQ1286
55tuner=54 - tda8290+75
56tuner=55 - LG PAL (TAPE series)
57tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
58tuner=57 - Philips FQ1236A MK4
59tuner=58 - Ymec TVision TVF-8531MF
60tuner=59 - Ymec TVision TVF-5533MF
61tuner=60 - Thomson DDT 7611 (ATSC/NTSC)
diff --git a/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt
new file mode 100644
index 0000000000..93fec32a11
--- /dev/null
+++ b/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt
@@ -0,0 +1,54 @@
1The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting.
2
3GPIO0 GPIO1
4 0 0 TV Audio
5 1 0 FM radio
6 0 1 Line-In
7 1 1 Mono tuner bypass or CD passthru (tuner specific)
8
9GPIO 16(i believe) is tied to the IR port (if present).
10
11------------------------------------------------------------------------------------
12
13>From the data sheet:
14 Register 24'h20004 PCI Interrupt Status
15 bit [18] IR_SMP_INT Set when 32 input samples have been collected over
16 gpio[16] pin into GP_SAMPLE register.
17
18What's missing from the data sheet:
19
20Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5
21compat remote)
22set register 0x35C050 to 0xa80a80
23
24enable sampling
25set register 0x35C054 to 0x5
26
27Of course, enable the IRQ bit 18 in the interrupt mask register .(and
28provide for a handler)
29
30GP_SAMPLE register is at 0x35C058
31
32Bits are then right shifted into the GP_SAMPLE register at the specified
33rate; you get an interrupt when a full DWORD is recieved.
34You need to recover the actual RC5 bits out of the (oversampled) IR sensor
35bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data) An
36actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment.
37
38I'm pretty sure when no IR signal is present the receiver is always in a
39marking state(1); but stray light, etc can cause intermittent noise values
40as well. Remember, this is a free running sample of the IR receiver state
41over time, so don't assume any sample starts at any particular place.
42
43http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf
44This data sheet (google search) seems to have a lovely description of the
45RC5 basics
46
47http://users.pandora.be/nenya/electronics/rc5/ and more data
48
49http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt
50and even a reference to how to decode a bi-phase data stream.
51
52http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm
53still more info
54
diff --git a/Documentation/video4linux/lifeview.txt b/Documentation/video4linux/lifeview.txt
new file mode 100644
index 0000000000..b07ea79c2b
--- /dev/null
+++ b/Documentation/video4linux/lifeview.txt
@@ -0,0 +1,42 @@
1collecting data about the lifeview models and the config coding on
2gpio pins 0-9 ...
3==================================================================
4
5bt878:
6 LR50 rev. Q ("PARTS: 7031505116), Tuner wurde als Nr. 5 erkannt, Eingänge
7 SVideo, TV, Composite, Audio, Remote. CP9..1=100001001 (1: 0-Ohm-Widerstand
8 gegen GND unbestückt; 0: bestückt)
9
10------------------------------------------------------------------------------
11
12saa7134:
13 /* LifeView FlyTV Platinum FM (LR214WF) */
14 /* "Peter Missel <peter.missel@onlinehome.de> */
15 .name = "LifeView FlyTV Platinum FM",
16 /* GP27 MDT2005 PB4 pin 10 */
17 /* GP26 MDT2005 PB3 pin 9 */
18 /* GP25 MDT2005 PB2 pin 8 */
19 /* GP23 MDT2005 PB1 pin 7 */
20 /* GP22 MDT2005 PB0 pin 6 */
21 /* GP21 MDT2005 PB5 pin 11 */
22 /* GP20 MDT2005 PB6 pin 12 */
23 /* GP19 MDT2005 PB7 pin 13 */
24 /* nc MDT2005 PA3 pin 2 */
25 /* Remote MDT2005 PA2 pin 1 */
26 /* GP18 MDT2005 PA1 pin 18 */
27 /* nc MDT2005 PA0 pin 17 strap low */
28
29 /* GP17 Strap "GP7"=High */
30 /* GP16 Strap "GP6"=High
31 0=Radio 1=TV
32 Drives SA630D ENCH1 and HEF4052 A1 pins
33 to do FM radio through SIF input */
34 /* GP15 nc */
35 /* GP14 nc */
36 /* GP13 nc */
37 /* GP12 Strap "GP5" = High */
38 /* GP11 Strap "GP4" = High */
39 /* GP10 Strap "GP3" = High */
40 /* GP09 Strap "GP2" = Low */
41 /* GP08 Strap "GP1" = Low */
42 /* GP07.00 nc */
diff --git a/Documentation/video4linux/not-in-cx2388x-datasheet.txt b/Documentation/video4linux/not-in-cx2388x-datasheet.txt
new file mode 100644
index 0000000000..96b638b5ba
--- /dev/null
+++ b/Documentation/video4linux/not-in-cx2388x-datasheet.txt
@@ -0,0 +1,37 @@
1=================================================================================
2MO_OUTPUT_FORMAT (0x310164)
3
4 Previous default from DScaler: 0x1c1f0008
5 Digit 8: 31-28
6 28: PREVREMOD = 1
7
8 Digit 7: 27-24 (0xc = 12 = b1100 )
9 27: COMBALT = 1
10 26: PAL_INV_PHASE
11 (DScaler apparently set this to 1, resulted in sucky picture)
12
13 Digits 6,5: 23-16
14 25-16: COMB_RANGE = 0x1f [default] (9 bits -> max 512)
15
16 Digit 4: 15-12
17 15: DISIFX = 0
18 14: INVCBF = 0
19 13: DISADAPT = 0
20 12: NARROWADAPT = 0
21
22 Digit 3: 11-8
23 11: FORCE2H
24 10: FORCEREMD
25 9: NCHROMAEN
26 8: NREMODEN
27
28 Digit 2: 7-4
29 7-6: YCORE
30 5-4: CCORE
31
32 Digit 1: 3-0
33 3: RANGE = 1
34 2: HACTEXT
35 1: HSFMT
36
37=================================================================================
diff --git a/MAINTAINERS b/MAINTAINERS
index 651af5012c..a07eeb4113 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2145,6 +2145,11 @@ W: http://tpmdd.sourceforge.net
2145L: tpmdd-devel@lists.sourceforge.net 2145L: tpmdd-devel@lists.sourceforge.net
2146S: Maintained 2146S: Maintained
2147 2147
2148TENSILICA XTENSA PORT (xtensa):
2149P: Chris Zankel
2150M: chris@zankel.net
2151S: Maintained
2152
2148UltraSPARC (sparc64): 2153UltraSPARC (sparc64):
2149P: David S. Miller 2154P: David S. Miller
2150M: davem@davemloft.net 2155M: davem@davemloft.net
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index 9f8c6087ae..2993f108d9 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -305,6 +305,8 @@ static void do_syscall_trace(void)
305 305
306void do_syscall_trace_enter(struct pt_regs *regs) 306void do_syscall_trace_enter(struct pt_regs *regs)
307{ 307{
308 secure_computing(regs->gpr[0]);
309
308 if (test_thread_flag(TIF_SYSCALL_TRACE) 310 if (test_thread_flag(TIF_SYSCALL_TRACE)
309 && (current->ptrace & PT_PTRACED)) 311 && (current->ptrace & PT_PTRACED))
310 do_syscall_trace(); 312 do_syscall_trace();
@@ -320,8 +322,6 @@ void do_syscall_trace_enter(struct pt_regs *regs)
320 322
321void do_syscall_trace_leave(struct pt_regs *regs) 323void do_syscall_trace_leave(struct pt_regs *regs)
322{ 324{
323 secure_computing(regs->gpr[0]);
324
325 if (unlikely(current->audit_context)) 325 if (unlikely(current->audit_context))
326 audit_syscall_exit(current, 326 audit_syscall_exit(current,
327 (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, 327 (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
new file mode 100644
index 0000000000..3e89767cea
--- /dev/null
+++ b/arch/xtensa/Kconfig
@@ -0,0 +1,258 @@
1# For a description of the syntax of this configuration file,
2# see Documentation/kbuild/config-language.txt.
3
4mainmenu "Linux/Xtensa Kernel Configuration"
5
6config FRAME_POINTER
7 bool
8 default n
9
10config XTENSA
11 bool
12 default y
13 help
14 Xtensa processors are 32-bit RISC machines designed by Tensilica
15 primarily for embedded systems. These processors are both
16 configurable and extensible. The Linux port to the Xtensa
17 architecture supports all processor configurations and extensions,
18 with reasonable minimum requirements. The Xtensa Linux project has
19 a home page at <http://xtensa.sourceforge.net/>.
20
21config UID16
22 bool
23 default n
24
25config RWSEM_XCHGADD_ALGORITHM
26 bool
27 default y
28
29config HAVE_DEC_LOCK
30 bool
31 default y
32
33config GENERIC_HARDIRQS
34 bool
35 default y
36
37source "init/Kconfig"
38
39menu "Processor type and features"
40
41choice
42 prompt "Xtensa Processor Configuration"
43 default XTENSA_CPU_LINUX_BE
44
45config XTENSA_CPU_LINUX_BE
46 bool "linux_be"
47 ---help---
48 The linux_be processor configuration is the baseline Xtensa
49 configurations included in this kernel and also used by
50 binutils, gcc, and gdb. It contains no TIE, no coprocessors,
51 and the following configuration options:
52
53 Code Density Option 2 Misc Special Registers
54 NSA/NSAU Instructions 128-bit Data Bus Width
55 Processor ID 8K, 2-way I and D Caches
56 Zero-Overhead Loops 2 Inst Address Break Registers
57 Big Endian 2 Data Address Break Registers
58 64 General-Purpose Registers JTAG Interface and Trace Port
59 17 Interrupts MMU w/ TLBs and Autorefill
60 3 Interrupt Levels 8 Autorefill Ways (I/D TLBs)
61 3 Timers Unaligned Exceptions
62endchoice
63
64config MMU
65 bool
66 default y
67
68config XTENSA_UNALIGNED_USER
69 bool "Unaligned memory access in use space"
70 ---help---
71 The Xtensa architecture currently does not handle unaligned
72 memory accesses in hardware but through an exception handler.
73 Per default, unaligned memory accesses are disabled in user space.
74
75 Say Y here to enable unaligned memory access in user space.
76
77config PREEMPT
78 bool "Preemptible Kernel"
79 ---help---
80 This option reduces the latency of the kernel when reacting to
81 real-time or interactive events by allowing a low priority process to
82 be preempted even if it is in kernel mode executing a system call.
83 Unfortunately the kernel code has some race conditions if both
84 CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is
85 currently disabled if you are building an SMP kernel.
86
87 Say Y here if you are building a kernel for a desktop, embedded
88 or real-time system. Say N if you are unsure.
89
90config MATH_EMULATION
91 bool "Math emulation"
92 help
93 Can we use information of configuration file?
94
95config HIGHMEM
96 bool "High memory support"
97
98endmenu
99
100menu "Platform options"
101
102choice
103 prompt "Xtensa System Type"
104 default XTENSA_PLATFORM_ISS
105
106config XTENSA_PLATFORM_ISS
107 bool "ISS"
108 help
109 ISS is an acronym for Tensilica's Instruction Set Simulator.
110
111config XTENSA_PLATFORM_XT2000
112 bool "XT2000"
113 help
114 XT2000 is the name of Tensilica's feature-rich emulation platform.
115 This hardware is capable of running a full Linux distribution.
116
117endchoice
118
119
120config XTENSA_CALIBRATE_CCOUNT
121 bool "Auto calibration of the CPU clock rate"
122 ---help---
123 On some platforms (XT2000, for example), the CPU clock rate can
124 vary. The frequency can be determined, however, by measuring
125 against a well known, fixed frequency, such as an UART oscillator.
126
127config XTENSA_CPU_CLOCK
128 int "CPU clock rate [MHz]"
129 depends on !XTENSA_CALIBRATE_CCOUNT
130 default "16"
131
132config GENERIC_CALIBRATE_DELAY
133 bool "Auto calibration of the BogoMIPS value"
134 ---help---
135 The BogoMIPS value can easily derived from the CPU frequency.
136
137config CMDLINE_BOOL
138 bool "Default bootloader kernel arguments"
139
140config CMDLINE
141 string "Initial kernel command string"
142 depends on CMDLINE_BOOL
143 default "console=ttyS0,38400 root=/dev/ram"
144 help
145 On some architectures (EBSA110 and CATS), there is currently no way
146 for the boot loader to pass arguments to the kernel. For these
147 architectures, you should supply some command-line options at build
148 time by entering them here. As a minimum, you should specify the
149 memory size and the root device (e.g., mem=64M root=/dev/nfs).
150
151config SERIAL_CONSOLE
152 bool
153 depends on XTENSA_PLATFORM_ISS
154 default y
155
156config XTENSA_ISS_NETWORK
157 bool
158 depends on XTENSA_PLATFORM_ISS
159 default y
160
161endmenu
162
163menu "Bus options"
164
165config PCI
166 bool "PCI support" if !XTENSA_PLATFORM_ISS
167 depends on !XTENSA_PLATFORM_ISS
168 default y
169 help
170 Find out whether you have a PCI motherboard. PCI is the name of a
171 bus system, i.e. the way the CPU talks to the other stuff inside
172 your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
173 VESA. If you have PCI, say Y, otherwise N.
174
175 The PCI-HOWTO, available from
176 <http://www.linuxdoc.org/docs.html#howto>, contains valuable
177 information about which PCI hardware does work under Linux and which
178 doesn't
179
180source "drivers/pci/Kconfig"
181
182config HOTPLUG
183
184 bool "Support for hot-pluggable devices"
185 ---help---
186 Say Y here if you want to plug devices into your computer while
187 the system is running, and be able to use them quickly. In many
188 cases, the devices can likewise be unplugged at any time too.
189
190 One well known example of this is PCMCIA- or PC-cards, credit-card
191 size devices such as network cards, modems or hard drives which are
192 plugged into slots found on all modern laptop computers. Another
193 example, used on modern desktops as well as laptops, is USB.
194
195 Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
196 software (at <http://linux-hotplug.sourceforge.net/>) and install it.
197 Then your kernel will automatically call out to a user mode "policy
198 agent" (/sbin/hotplug) to load modules and set up software needed
199 to use devices as you hotplug them.
200
201source "drivers/pcmcia/Kconfig"
202
203source "drivers/pci/hotplug/Kconfig"
204
205endmenu
206
207menu "Exectuable file formats"
208
209# only elf supported
210config KCORE_ELF
211 bool
212 depends on PROC_FS
213 default y
214 help
215 If you enabled support for /proc file system then the file
216 /proc/kcore will contain the kernel core image in ELF format. This
217 can be used in gdb:
218
219 $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
220
221 This is especially useful if you have compiled the kernel with the
222 "-g" option to preserve debugging information. It is mainly used
223 for examining kernel data structures on the live kernel.
224
225source "fs/Kconfig.binfmt"
226
227endmenu
228
229source "drivers/Kconfig"
230
231source "fs/Kconfig"
232
233menu "Xtensa initrd options"
234 depends on BLK_DEV_INITRD
235
236 config EMBEDDED_RAMDISK
237 bool "Embed root filesystem ramdisk into the kernel"
238
239config EMBEDDED_RAMDISK_IMAGE
240 string "Filename of gziped ramdisk image"
241 depends on EMBEDDED_RAMDISK
242 default "ramdisk.gz"
243 help
244 This is the filename of the ramdisk image to be built into the
245 kernel. Relative pathnames are relative to arch/xtensa/boot/ramdisk/.
246 The ramdisk image is not part of the kernel distribution; you must
247 provide one yourself.
248endmenu
249
250source "arch/xtensa/Kconfig.debug"
251
252source "security/Kconfig"
253
254source "crypto/Kconfig"
255
256source "lib/Kconfig"
257
258
diff --git a/arch/xtensa/Kconfig.debug b/arch/xtensa/Kconfig.debug
new file mode 100644
index 0000000000..11c585295d
--- /dev/null
+++ b/arch/xtensa/Kconfig.debug
@@ -0,0 +1,7 @@
1menu "Kernel hacking"
2
3source "lib/Kconfig.debug"
4
5endmenu
6
7
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
new file mode 100644
index 0000000000..4fa27453b1
--- /dev/null
+++ b/arch/xtensa/Makefile
@@ -0,0 +1,102 @@
1#
2# This file is subject to the terms and conditions of the GNU General Public
3# License. See the file "COPYING" in the main directory of this archive
4# for more details.
5#
6# Copyright (C) 2001 - 2005 Tensilica Inc.
7#
8# This file is included by the global makefile so that you can add your own
9# architecture-specific flags and dependencies. Remember to do have actions
10# for "archclean" and "archdep" for cleaning up and making dependencies for
11# this architecture
12
13# Core configuration.
14# (Use CPU=<xtensa_config> to use another default compiler.)
15
16cpu-$(CONFIG_XTENSA_CPU_LINUX_BE) := linux_be
17cpu-$(CONFIG_XTENSA_CPU_LINUX_CUSTOM) := linux_custom
18
19CPU = $(cpu-y)
20export CPU
21
22# Platform configuration
23
24platform-y := common
25platform-$(CONFIG_XTENSA_PLATFORM_XT2000) := xt2000
26platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss
27
28PLATFORM = $(platform-y)
29export PLATFORM
30
31#LDFLAGS_vmlinux := -T$(word 1,$(LINKSCRIPT))
32AFLAGS_vmlinux.lds.o := -Uxtensa
33CPPFLAGS += -Iarch/xtensa -Iinclude/asm -mlongcalls -g
34AFLAGS += -Iarch/xtensa -Iinclude/asm
35CPP = $(CC) -E $(CFLAGS)
36
37cflags-y += -Iarch/xtensa -pipe -mlongcalls
38
39
40KBUILD_DEFCONFIG := common_defconfig
41
42# ramdisk/initrd support
43# You need a compressed ramdisk image, named ramdisk.gz in
44# arch/xtensa/boot/ramdisk
45
46core-$(CONFIG_EMBEDDED_RAMDISK) += arch/xtensa/boot/ramdisk/
47
48# Test for cross compiling
49
50ifneq ($(CPU),)
51 COMPILE_ARCH = $(shell uname -m)
52
53 ifneq ($(COMPILE_ARCH), xtensa)
54 ifndef CROSS_COMPILE
55 CROSS_COMPILE = xtensa_$(CPU)-
56 endif
57 endif
58endif
59
60#
61
62LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
63
64head-y := arch/xtensa/kernel/head.o
65core-y += arch/xtensa/kernel/ \
66 arch/xtensa/mm/ arch/xtensa/platform-$(PLATFORM)/
67libs-y += arch/xtensa/lib/ $(LIBGCC)
68
69boot := arch/xtensa/boot
70
71arch/xtensa/kernel/asm-offsets.s: \
72 arch/xtensa/kernel/asm-offsets.c \
73 include/asm-xtensa/.platform
74
75include/asm-xtensa/offsets.h: arch/xtensa/kernel/asm-offsets.s
76 $(call filechk,gen-asm-offsets)
77
78prepare: include/asm-xtensa/.platform include/asm-xtensa/offsets.h
79
80# Update machine cpu and platform symlinks if something which affects
81# them changed.
82
83include/asm-xtensa/.platform: $(wildcard include/config/arch/*.h)
84 @echo ' Setting up cpu ($(CPU)) and platform ($(PLATFORM)) symlinks'
85 $(Q)rm -f include/asm-xtensa/platform
86 $(Q)rm -f include/asm-xtensa/xtensa/config
87 $(Q)(cd include/asm-xtensa/; ln -sf platform-$(PLATFORM) platform)
88 $(Q)(cd include/asm-xtensa/xtensa; ln -sf config-$(CPU) config)
89
90all: zImage
91
92bzImage : zImage
93
94zImage zImage.initrd: vmlinux
95 $(Q)$(MAKE) $(build)=$(boot) $@
96
97CLEAN_FILES += arch/xtensa/vmlinux.lds include/asm-xtensa/offset.h
98
99define archhelp
100 @echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)'
101endef
102
diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile
new file mode 100644
index 0000000000..260f456ccf
--- /dev/null
+++ b/arch/xtensa/boot/Makefile
@@ -0,0 +1,37 @@
1#
2# arch/xtensa/boot/Makefile
3#
4# This file is subject to the terms and conditions of the GNU General Public
5# License. See the file "COPYING" in the main directory of this archive
6# for more details.
7#
8#
9
10
11CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include
12HOSTFLAGS += -Iarch/$(ARCH)/boot/include
13
14BIG_ENDIAN := $(shell echo -e "\#ifdef __XTENSA_EL__\nint little;\n\#else\nint big;\n\#endif" | $(CC) -E -|grep -c big)
15
16
17export CFLAGS
18export AFLAGS
19export BIG_ENDIAN
20
21# Subdirs for the boot loader(s)
22
23bootdir-$(CONFIG_XTENSA_PLATFORM_ISS) += boot-elf
24bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf
25
26subdir-y := lib/
27
28subdir-y += boot-elf/ boot-redboot/
29
30zImage zImage.initrd Image Image.initrd: $(bootdir-y)
31
32$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
33 $(addprefix $(obj)/,$(host-progs))
34 $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
35
36
37
diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile
new file mode 100644
index 0000000000..f6ef6a3696
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/Makefile
@@ -0,0 +1,52 @@
1#
2# This file is subject to the terms and conditions of the GNU General Public
3# License. See the file "COPYING" in the main directory of this archive
4# for more details.
5#
6
7GZIP = gzip
8GZIP_FLAGS = -v9fc
9
10ifeq ($(BIG_ENDIAN),1)
11OBJCOPY_ARGS := -O elf32-xtensa-be
12else
13OBJCOPY_ARGS := -O elf32-xtensa-le
14endif
15
16export OBJCOPY_ARGS
17
18boot-y := bootstrap.o
19
20OBJS := $(addprefix $(obj)/,$(boot-y))
21
22Image: vmlinux $(OBJS)
23 $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
24 vmlinux vmlinux.tmp
25 $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
26 --add-section image=vmlinux.tmp \
27 --set-section-flags image=contents,alloc,load,load,data \
28 $(OBJS) $@.tmp
29 $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
30 -T arch/$(ARCH)/boot/boot-elf/boot.ld \
31 -o arch/$(ARCH)/boot/$@.elf $@.tmp
32 rm -f $@.tmp vmlinux.tmp
33
34Image.initrd: vmlinux $(OBJS)
35 $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
36 --add-section .initrd=arch/$(ARCH)/boot/ramdisk \
37 --set-section-flags .initrd=contents,alloc,load,load,data \
38 vmlinux vmlinux.tmp
39 $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
40 --add-section image=vmlinux.tmp \
41 --set-section-flags image=contents,alloc,load,load,data \
42 $(OBJS) $@.tmp
43 $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
44 -T arch/$(ARCH)/boot/boot-elf/boot.ld \
45 -o arch/$(ARCH)/boot/$@.elf $@.tmp
46 rm -f $@.tmp vmlinux.tmp
47
48
49zImage: Image
50
51zImage.initrd: Image.initrd
52
diff --git a/arch/xtensa/boot/boot-elf/boot.ld b/arch/xtensa/boot/boot-elf/boot.ld
new file mode 100644
index 0000000000..4ab06a0a7a
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/boot.ld
@@ -0,0 +1,71 @@
1OUTPUT_ARCH(xtensa)
2
3SECTIONS
4{
5 .start 0xD0000000 : { *(.start) }
6
7 .text 0xD0000000:
8 {
9 __reloc_start = . ;
10 _text_start = . ;
11 *(.literal .text.literal .text)
12 _text_end = . ;
13 }
14
15 .rodata ALIGN(0x04):
16 {
17 *(.rodata)
18 *(.rodata1)
19 }
20
21 .data ALIGN(0x04):
22 {
23 *(.data)
24 *(.data1)
25 *(.sdata)
26 *(.sdata2)
27 *(.got.plt)
28 *(.got)
29 *(.dynamic)
30 }
31
32 __reloc_end = . ;
33
34 .initrd ALIGN(0x10) :
35 {
36 boot_initrd_start = . ;
37 *(.initrd)
38 boot_initrd_end = .;
39 }
40
41 . = ALIGN(0x10);
42 __image_load = . ;
43 .image 0xd0001000:
44 {
45 _image_start = .;
46 *(image)
47 . = (. + 3) & ~ 3;
48 _image_end = . ;
49 }
50
51
52 .bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3):
53 {
54 __bss_start = .;
55 *(.sbss)
56 *(.scommon)
57 *(.dynbss)
58 *(.bss)
59 __bss_end = .;
60 }
61 _end = .;
62 _param_start = .;
63
64 .ResetVector.text 0xfe000020 :
65 {
66 *(.ResetVector.text)
67 }
68
69
70 PROVIDE (end = .);
71}
diff --git a/arch/xtensa/boot/boot-elf/bootstrap.S b/arch/xtensa/boot/boot-elf/bootstrap.S
new file mode 100644
index 0000000000..7cba94abda
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/bootstrap.S
@@ -0,0 +1,37 @@
1
2#include <xtensa/config/specreg.h>
3#include <xtensa/config/core.h>
4
5#include <linux/config.h>
6#include <asm/bootparam.h>
7
8
9/* ResetVector
10 */
11 .section .ResetVector.text, "ax"
12 .global _ResetVector
13_ResetVector:
14 _j reset
15 .align 4
16RomInitAddr:
17 .word 0xd0001000
18RomBootParam:
19 .word _bootparam
20reset:
21 l32r a0, RomInitAddr
22 l32r a2, RomBootParam
23 movi a3, 0
24 movi a4, 0
25 jx a0
26
27 .align 4
28 .section .bootstrap.data, "aw"
29
30 .globl _bootparam
31_bootparam:
32 .short BP_TAG_FIRST
33 .short 4
34 .long BP_VERSION
35 .short BP_TAG_LAST
36 .short 0
37 .long 0
diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile
new file mode 100644
index 0000000000..ca8a68bc84
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/Makefile
@@ -0,0 +1,35 @@
1#
2# This file is subject to the terms and conditions of the GNU General Public
3# License. See the file "COPYING" in the main directory of this archive
4# for more details.
5#
6
7GZIP = gzip
8GZIP_FLAGS = -v9fc
9ifeq ($(BIG_ENDIAN),1)
10OBJCOPY_ARGS := -O elf32-xtensa-be
11else
12OBJCOPY_ARGS := -O elf32-xtensa-le
13endif
14
15LD_ARGS = -T $(obj)/boot.ld
16
17boot-y := bootstrap.o
18
19OBJS := $(addprefix $(obj)/,$(boot-y))
20LIBS := arch/$(ARCH)/boot/lib/lib.a arch/$(ARCH)/lib/lib.a
21
22LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
23
24zImage: vmlinux $(OBJS) $(LIBS)
25 $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
26 $(TOPDIR)/vmlinux vmlinux.tmp
27 gzip -vf9 vmlinux.tmp
28 $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
29 --add-section image=vmlinux.tmp.gz \
30 --set-section-flags image=contents,alloc,load,load,data \
31 $(OBJS) $@.tmp
32 $(LD) $(LD_ARGS) -o $@.elf $@.tmp $(LIBS) -L/xtensa-elf/lib $(LIBGCC)
33 $(OBJCOPY) -S -O binary $@.elf arch/$(ARCH)/boot/images/$@.redboot
34# rm -f $@.tmp $@.elf vmlinux.tmp.gz
35
diff --git a/arch/xtensa/boot/boot-redboot/boot.ld b/arch/xtensa/boot/boot-redboot/boot.ld
new file mode 100644
index 0000000000..65b726410e
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/boot.ld
@@ -0,0 +1,66 @@
1OUTPUT_ARCH(xtensa)
2
3SECTIONS
4{
5 .start 0xD0200000 : { *(.start) }
6
7 .text :
8 {
9 __reloc_start = . ;
10 _text_start = . ;
11 *(.literal .text.literal .text)
12 _text_end = . ;
13 }
14
15 .rodata ALIGN(0x04):
16 {
17 *(.rodata)
18 *(.rodata1)
19 }
20
21 .data ALIGN(0x04):
22 {
23 *(.data)
24 *(.data1)
25 *(.sdata)
26 *(.sdata2)
27 *(.got.plt)
28 *(.got)
29 *(.dynamic)
30 }
31
32 __reloc_end = . ;
33
34 .initrd ALIGN(0x10) :
35 {
36 boot_initrd_start = . ;
37 *(.initrd)
38 boot_initrd_end = .;
39 }
40
41 . = ALIGN(0x10);
42 __image_load = . ;
43 .image 0xd0001000: AT(__image_load)
44 {
45 _image_start = .;
46 *(image)
47 . = (. + 3) & ~ 3;
48 _image_end = . ;
49 }
50
51
52 .bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3):
53 {
54 __bss_start = .;
55 *(.sbss)
56 *(.scommon)
57 *(.dynbss)
58 *(.bss)
59 __bss_end = .;
60 }
61 _end = .;
62 _param_start = .;
63
64
65 PROVIDE (end = .);
66}
diff --git a/arch/xtensa/boot/boot-redboot/bootstrap.S b/arch/xtensa/boot/boot-redboot/bootstrap.S
new file mode 100644
index 0000000000..ee636b0da8
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/bootstrap.S
@@ -0,0 +1,246 @@
1
2#define _ASMLANGUAGE
3#include <xtensa/config/specreg.h>
4#include <xtensa/config/core.h>
5#include <xtensa/cacheasm.h>
6
7 /*
8 * RB-Data: RedBoot data/bss
9 * P: Boot-Parameters
10 * L: Kernel-Loader
11 *
12 * The Linux-Kernel image including the loader must be loaded
13 * to a position so that the kernel and the boot parameters
14 * can fit in the space before the load address.
15 * ______________________________________________________
16 * |_RB-Data_|_P_|__________|_L_|___Linux-Kernel___|______|
17 * ^
18 * ^ Load address
19 * ______________________________________________________
20 * |___Linux-Kernel___|_P_|_L_|___________________________|
21 *
22 * The loader copies the parameter to the position that will
23 * be the end of the kernel and itself to the end of the
24 * parameter list.
25 */
26
27/* Make sure we have enough space for the 'uncompressor' */
28
29#define STACK_SIZE 32768
30#define HEAP_SIZE (131072*4)
31
32 # a2: Parameter list
33 # a3: Size of parameter list
34
35 .section .start, "ax"
36
37 .globl __start
38 /* this must be the first byte of the loader! */
39__start:
40 entry sp, 32 # we do not intend to return
41 _call0 _start
42__start_a0:
43 .align 4
44
45 .section .text, "ax"
46 .begin literal_prefix .text
47
48 /* put literals in here! */
49
50 .globl _start
51_start:
52
53 /* 'reset' window registers */
54
55 movi a4, 1
56 wsr a4, PS
57 rsync
58
59 rsr a5, WINDOWBASE
60 ssl a5
61 sll a4, a4
62 wsr a4, WINDOWSTART
63 rsync
64
65 movi a4, 0x00040000
66 wsr a4, PS
67 rsync
68
69 /* copy the loader to its address
70 * Note: The loader itself is a very small piece, so we assume we
71 * don't partially overlap. We also assume (even more important)
72 * that the kernel image is out of the way. Usually, when the
73 * load address of this image is not at an arbitrary address,
74 * but aligned to some 10K's we shouldn't overlap.
75 */
76
77 /* Note: The assembler cannot relax "addi a0, a0, ..." to an
78 l32r, so we load to a4 first. */
79
80 addi a4, a0, __start - __start_a0
81 mov a0, a4
82 movi a4, __start
83 movi a5, __reloc_end
84
85 # a0: address where this code has been loaded
86 # a4: compiled address of __start
87 # a5: compiled end address
88
89 mov.n a7, a0
90 mov.n a8, a4
91
921:
93 l32i a10, a7, 0
94 l32i a11, a7, 4
95 s32i a10, a8, 0
96 s32i a11, a8, 4
97 l32i a10, a7, 8
98 l32i a11, a7, 12
99 s32i a10, a8, 8
100 s32i a11, a8, 12
101 addi a8, a8, 16
102 addi a7, a7, 16
103 blt a8, a5, 1b
104
105
106 /* We have to flush and invalidate the caches here before we jump. */
107
108#if XCHAL_DCACHE_IS_WRITEBACK
109 dcache_writeback_all a5, a6
110#endif
111 icache_invalidate_all a5, a6
112
113 movi a11, _reloc
114 jx a11
115
116 .globl _reloc
117_reloc:
118
119 /* RedBoot is now at the end of the memory, so we don't have
120 * to copy the parameter list. Keep the code around; in case
121 * we need it again. */
122#if 0
123 # a0: load address
124 # a2: start address of parameter list
125 # a3: length of parameter list
126 # a4: __start
127
128 /* copy the parameter list out of the way */
129
130 movi a6, _param_start
131 add a3, a2, a3
1322:
133 l32i a8, a2, 0
134 s32i a8, a6, 0
135 addi a2, a2, 4
136 addi a6, a6, 4
137 blt a2, a3, 2b
138#endif
139
140 /* clear BSS section */
141 movi a6, __bss_start
142 movi a7, __bss_end
143 movi.n a5, 0
1443:
145 s32i a5, a6, 0
146 addi a6, a6, 4
147 blt a6, a7, 3b
148
149 movi a5, -16
150 movi a1, _stack + STACK_SIZE
151 and a1, a1, a5
152
153 /* Uncompress the kernel */
154
155 # a0: load address
156 # a2: boot parameter
157 # a4: __start
158
159 movi a3, __image_load
160 sub a4, a3, a4
161 add a8, a0, a4
162
163 # a1 Stack
164 # a8(a4) Load address of the image
165
166 movi a6, _image_start
167 movi a10, _image_end
168 movi a7, 0x1000000
169 sub a11, a10, a6
170 movi a9, complen
171 s32i a11, a9, 0
172
173 movi a0, 0
174
175 # a6 destination
176 # a7 maximum size of destination
177 # a8 source
178 # a9 ptr to length
179
180 .extern gunzip
181 movi a4, gunzip
182 beqz a4, 1f
183
184 callx4 a4
185
186 j 2f
187
188
189 # a6 destination start
190 # a7 maximum size of destination
191 # a8 source start
192 # a9 ptr to length
193 # a10 destination end
194
1951:
196 l32i a9, a8, 0
197 l32i a11, a8, 4
198 s32i a9, a6, 0
199 s32i a11, a6, 4
200 l32i a9, a8, 8
201 l32i a11, a8, 12
202 s32i a9, a6, 8
203 s32i a11, a6, 12
204 addi a6, a6, 16
205 addi a8, a8, 16
206 blt a6, a10, 1b
207
208
209 /* jump to the kernel */
2102:
211#if XCHAL_DCACHE_IS_WRITEBACK
212 dcache_writeback_all a5, a6
213#endif
214 icache_invalidate_all a5, a6
215
216 movi a5, __start
217 movi a3, boot_initrd_start
218 movi a4, boot_initrd_end
219 sub a3, a3, a5
220 sub a4, a4, a5
221 add a3, a0, a3
222 add a4, a0, a4
223
224 # a2 Boot parameter list
225 # a3 initrd_start (virtual load address)
226 # a4 initrd_end (virtual load address)
227
228 movi a0, _image_start
229 jx a0
230
231 .align 16
232 .data
233 .globl avail_ram
234avail_ram:
235 .long _heap
236 .globl end_avail
237end_avail:
238 .long _heap + HEAP_SIZE
239
240 .comm _stack, STACK_SIZE
241 .comm _heap, HEAP_SIZE
242
243 .globl end_avail
244 .comm complen, 4
245
246 .end literal_prefix
diff --git a/arch/xtensa/boot/include/zlib.h b/arch/xtensa/boot/include/zlib.h
new file mode 100644
index 0000000000..ea29b62378
--- /dev/null
+++ b/arch/xtensa/boot/include/zlib.h
@@ -0,0 +1,433 @@
1/*
2 * BK Id: SCCS/s.zlib.h 1.8 05/18/01 15:17:23 cort
3 */
4/*
5 * This file is derived from zlib.h and zconf.h from the zlib-0.95
6 * distribution by Jean-loup Gailly and Mark Adler, with some additions
7 * by Paul Mackerras to aid in implementing Deflate compression and
8 * decompression for PPP packets.
9 */
10
11/*
12 * ==FILEVERSION 960122==
13 *
14 * This marker is used by the Linux installation script to determine
15 * whether an up-to-date version of this file is already installed.
16 */
17
18/* zlib.h -- interface of the 'zlib' general purpose compression library
19 version 0.95, Aug 16th, 1995.
20
21 Copyright (C) 1995 Jean-loup Gailly and Mark Adler
22
23 This software is provided 'as-is', without any express or implied
24 warranty. In no event will the authors be held liable for any damages
25 arising from the use of this software.
26
27 Permission is granted to anyone to use this software for any purpose,
28 including commercial applications, and to alter it and redistribute it
29 freely, subject to the following restrictions:
30
31 1. The origin of this software must not be misrepresented; you must not
32 claim that you wrote the original software. If you use this software
33 in a product, an acknowledgment in the product documentation would be
34 appreciated but is not required.
35 2. Altered source versions must be plainly marked as such, and must not be
36 misrepresented as being the original software.
37 3. This notice may not be removed or altered from any source distribution.
38
39 Jean-loup Gailly Mark Adler
40 gzip@prep.ai.mit.edu madler@alumni.caltech.edu
41 */
42
43#ifndef _ZLIB_H
44#define _ZLIB_H
45
46/* #include "zconf.h" */ /* included directly here */
47
48/* zconf.h -- configuration of the zlib compression library
49 * Copyright (C) 1995 Jean-loup Gailly.
50 * For conditions of distribution and use, see copyright notice in zlib.h
51 */
52
53/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
54
55/*
56 The library does not install any signal handler. It is recommended to
57 add at least a handler for SIGSEGV when decompressing; the library checks
58 the consistency of the input data whenever possible but may go nuts
59 for some forms of corrupted input.
60 */
61
62/*
63 * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
64 * than 64k bytes at a time (needed on systems with 16-bit int).
65 * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
66 * at addresses which are not a multiple of their size.
67 * Under DOS, -DFAR=far or -DFAR=__far may be needed.
68 */
69
70#ifndef STDC
71# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
72# define STDC
73# endif
74#endif
75
76#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
77# include <unix.h>
78#endif
79
80/* Maximum value for memLevel in deflateInit2 */
81#ifndef MAX_MEM_LEVEL
82# ifdef MAXSEG_64K
83# define MAX_MEM_LEVEL 8
84# else
85# define MAX_MEM_LEVEL 9
86# endif
87#endif
88
89#ifndef FAR
90# define FAR
91#endif
92
93/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
94#ifndef MAX_WBITS
95# define MAX_WBITS 15 /* 32K LZ77 window */
96#endif
97
98/* The memory requirements for deflate are (in bytes):
99 1 << (windowBits+2) + 1 << (memLevel+9)
100 that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
101 plus a few kilobytes for small objects. For example, if you want to reduce
102 the default memory requirements from 256K to 128K, compile with
103 make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
104 Of course this will generally degrade compression (there's no free lunch).
105
106 The memory requirements for inflate are (in bytes) 1 << windowBits
107 that is, 32K for windowBits=15 (default value) plus a few kilobytes
108 for small objects.
109*/
110
111 /* Type declarations */
112
113#ifndef OF /* function prototypes */
114# ifdef STDC
115# define OF(args) args
116# else
117# define OF(args) ()
118# endif
119#endif
120
121typedef unsigned char Byte; /* 8 bits */
122typedef unsigned int uInt; /* 16 bits or more */
123typedef unsigned long uLong; /* 32 bits or more */
124
125typedef Byte FAR Bytef;
126typedef char FAR charf;
127typedef int FAR intf;
128typedef uInt FAR uIntf;
129typedef uLong FAR uLongf;
130
131#ifdef STDC
132 typedef void FAR *voidpf;
133 typedef void *voidp;
134#else
135 typedef Byte FAR *voidpf;
136 typedef Byte *voidp;
137#endif
138
139/* end of original zconf.h */
140
141#define ZLIB_VERSION "0.95P"
142
143/*
144 The 'zlib' compression library provides in-memory compression and
145 decompression functions, including integrity checks of the uncompressed
146 data. This version of the library supports only one compression method
147 (deflation) but other algorithms may be added later and will have the same
148 stream interface.
149
150 For compression the application must provide the output buffer and
151 may optionally provide the input buffer for optimization. For decompression,
152 the application must provide the input buffer and may optionally provide
153 the output buffer for optimization.
154
155 Compression can be done in a single step if the buffers are large
156 enough (for example if an input file is mmap'ed), or can be done by
157 repeated calls of the compression function. In the latter case, the
158 application must provide more input and/or consume the output
159 (providing more output space) before each call.
160*/
161
162typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
163typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
164
165struct internal_state;
166
167typedef struct z_stream_s {
168 Bytef *next_in; /* next input byte */
169 uInt avail_in; /* number of bytes available at next_in */
170 uLong total_in; /* total nb of input bytes read so far */
171
172 Bytef *next_out; /* next output byte should be put there */
173 uInt avail_out; /* remaining free space at next_out */
174 uLong total_out; /* total nb of bytes output so far */
175
176 char *msg; /* last error message, NULL if no error */
177 struct internal_state FAR *state; /* not visible by applications */
178
179 alloc_func zalloc; /* used to allocate the internal state */
180 free_func zfree; /* used to free the internal state */
181 voidp opaque; /* private data object passed to zalloc and zfree */
182
183 Byte data_type; /* best guess about the data type: ascii or binary */
184
185} z_stream;
186
187/*
188 The application must update next_in and avail_in when avail_in has
189 dropped to zero. It must update next_out and avail_out when avail_out
190 has dropped to zero. The application must initialize zalloc, zfree and
191 opaque before calling the init function. All other fields are set by the
192 compression library and must not be updated by the application.
193
194 The opaque value provided by the application will be passed as the first
195 parameter for calls of zalloc and zfree. This can be useful for custom
196 memory management. The compression library attaches no meaning to the
197 opaque value.
198
199 zalloc must return Z_NULL if there is not enough memory for the object.
200 On 16-bit systems, the functions zalloc and zfree must be able to allocate
201 exactly 65536 bytes, but will not be required to allocate more than this
202 if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
203 pointers returned by zalloc for objects of exactly 65536 bytes *must*
204 have their offset normalized to zero. The default allocation function
205 provided by this library ensures this (see zutil.c). To reduce memory
206 requirements and avoid any allocation of 64K objects, at the expense of
207 compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
208
209 The fields total_in and total_out can be used for statistics or
210 progress reports. After compression, total_in holds the total size of
211 the uncompressed data and may be saved for use in the decompressor
212 (particularly if the decompressor wants to decompress everything in
213 a single step).
214*/
215
216 /* constants */
217
218#define Z_NO_FLUSH 0
219#define Z_PARTIAL_FLUSH 1
220#define Z_FULL_FLUSH 2
221#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
222#define Z_FINISH 4
223#define Z_PACKET_FLUSH 5
224/* See deflate() below for the usage of these constants */
225
226#define Z_OK 0
227#define Z_STREAM_END 1
228#define Z_ERRNO (-1)
229#define Z_STREAM_ERROR (-2)
230#define Z_DATA_ERROR (-3)
231#define Z_MEM_ERROR (-4)
232#define Z_BUF_ERROR (-5)
233/* error codes for the compression/decompression functions */
234
235#define Z_BEST_SPEED 1
236#define Z_BEST_COMPRESSION 9
237#define Z_DEFAULT_COMPRESSION (-1)
238/* compression levels */
239
240#define Z_FILTERED 1
241#define Z_HUFFMAN_ONLY 2
242#define Z_DEFAULT_STRATEGY 0
243
244#define Z_BINARY 0
245#define Z_ASCII 1
246#define Z_UNKNOWN 2
247/* Used to set the data_type field */
248
249#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
250
251extern char *zlib_version;
252/* The application can compare zlib_version and ZLIB_VERSION for consistency.
253 If the first character differs, the library code actually used is
254 not compatible with the zlib.h header file used by the application.
255 */
256
257 /* basic functions */
258
259extern int inflateInit OF((z_stream *strm));
260/*
261 Initializes the internal stream state for decompression. The fields
262 zalloc and zfree must be initialized before by the caller. If zalloc and
263 zfree are set to Z_NULL, inflateInit updates them to use default allocation
264 functions.
265
266 inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
267 enough memory. msg is set to null if there is no error message.
268 inflateInit does not perform any decompression: this will be done by
269 inflate().
270*/
271
272
273extern int inflate OF((z_stream *strm, int flush));
274/*
275 Performs one or both of the following actions:
276
277 - Decompress more input starting at next_in and update next_in and avail_in
278 accordingly. If not all input can be processed (because there is not
279 enough room in the output buffer), next_in is updated and processing
280 will resume at this point for the next call of inflate().
281
282 - Provide more output starting at next_out and update next_out and avail_out
283 accordingly. inflate() always provides as much output as possible
284 (until there is no more input data or no more space in the output buffer).
285
286 Before the call of inflate(), the application should ensure that at least
287 one of the actions is possible, by providing more input and/or consuming
288 more output, and updating the next_* and avail_* values accordingly.
289 The application can consume the uncompressed output when it wants, for
290 example when the output buffer is full (avail_out == 0), or after each
291 call of inflate().
292
293 If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
294 inflate flushes as much output as possible to the output buffer. The
295 flushing behavior of inflate is not specified for values of the flush
296 parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
297 current implementation actually flushes as much output as possible
298 anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
299 has been consumed, it is expecting to see the length field of a stored
300 block; if not, it returns Z_DATA_ERROR.
301
302 inflate() should normally be called until it returns Z_STREAM_END or an
303 error. However if all decompression is to be performed in a single step
304 (a single call of inflate), the parameter flush should be set to
305 Z_FINISH. In this case all pending input is processed and all pending
306 output is flushed; avail_out must be large enough to hold all the
307 uncompressed data. (The size of the uncompressed data may have been saved
308 by the compressor for this purpose.) The next operation on this stream must
309 be inflateEnd to deallocate the decompression state. The use of Z_FINISH
310 is never required, but can be used to inform inflate that a faster routine
311 may be used for the single inflate() call.
312
313 inflate() returns Z_OK if some progress has been made (more input
314 processed or more output produced), Z_STREAM_END if the end of the
315 compressed data has been reached and all uncompressed output has been
316 produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
317 the stream structure was inconsistent (for example if next_in or next_out
318 was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
319 progress is possible or if there was not enough room in the output buffer
320 when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
321 call inflateSync to look for a good compression block. */
322
323
324extern int inflateEnd OF((z_stream *strm));
325/*
326 All dynamically allocated data structures for this stream are freed.
327 This function discards any unprocessed input and does not flush any
328 pending output.
329
330 inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
331 was inconsistent. In the error case, msg may be set but then points to a
332 static string (which must not be deallocated).
333*/
334
335 /* advanced functions */
336
337extern int inflateInit2 OF((z_stream *strm,
338 int windowBits));
339/*
340 This is another version of inflateInit with more compression options. The
341 fields next_out, zalloc and zfree must be initialized before by the caller.
342
343 The windowBits parameter is the base two logarithm of the maximum window
344 size (the size of the history buffer). It should be in the range 8..15 for
345 this version of the library (the value 16 will be allowed soon). The
346 default value is 15 if inflateInit is used instead. If a compressed stream
347 with a larger window size is given as input, inflate() will return with
348 the error code Z_DATA_ERROR instead of trying to allocate a larger window.
349
350 If next_out is not null, the library will use this buffer for the history
351 buffer; the buffer must either be large enough to hold the entire output
352 data, or have at least 1<<windowBits bytes. If next_out is null, the
353 library will allocate its own buffer (and leave next_out null). next_in
354 need not be provided here but must be provided by the application for the
355 next call of inflate().
356
357 If the history buffer is provided by the application, next_out must
358 never be changed by the application since the decompressor maintains
359 history information inside this buffer from call to call; the application
360 can only reset next_out to the beginning of the history buffer when
361 avail_out is zero and all output has been consumed.
362
363 inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
364 not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
365 windowBits < 8). msg is set to null if there is no error message.
366 inflateInit2 does not perform any decompression: this will be done by
367 inflate().
368*/
369
370extern int inflateSync OF((z_stream *strm));
371/*
372 Skips invalid compressed data until the special marker (see deflate()
373 above) can be found, or until all available input is skipped. No output
374 is provided.
375
376 inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
377 if no more input was provided, Z_DATA_ERROR if no marker has been found,
378 or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
379 case, the application may save the current current value of total_in which
380 indicates where valid compressed data was found. In the error case, the
381 application may repeatedly call inflateSync, providing more input each time,
382 until success or end of the input data.
383*/
384
385extern int inflateReset OF((z_stream *strm));
386/*
387 This function is equivalent to inflateEnd followed by inflateInit,
388 but does not free and reallocate all the internal decompression state.
389 The stream will keep attributes that may have been set by inflateInit2.
390
391 inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
392 stream state was inconsistent (such as zalloc or state being NULL).
393*/
394
395extern int inflateIncomp OF((z_stream *strm));
396/*
397 This function adds the data at next_in (avail_in bytes) to the output
398 history without performing any output. There must be no pending output,
399 and the decompressor must be expecting to see the start of a block.
400 Calling this function is equivalent to decompressing a stored block
401 containing the data at next_in (except that the data is not output).
402*/
403
404 /* checksum functions */
405
406/*
407 This function is not related to compression but is exported
408 anyway because it might be useful in applications using the
409 compression library.
410*/
411
412extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
413
414/*
415 Update a running Adler-32 checksum with the bytes buf[0..len-1] and
416 return the updated checksum. If buf is NULL, this function returns
417 the required initial value for the checksum.
418 An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
419 much faster. Usage example:
420
421 uLong adler = adler32(0L, Z_NULL, 0);
422
423 while (read_buffer(buffer, length) != EOF) {
424 adler = adler32(adler, buffer, length);
425 }
426 if (adler != original_adler) error();
427*/
428
429#ifndef _Z_UTIL_H
430 struct internal_state {int dummy;}; /* hack for buggy compilers */
431#endif
432
433#endif /* _ZLIB_H */
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile
new file mode 100644
index 0000000000..c0a74dc3a0
--- /dev/null
+++ b/arch/xtensa/boot/lib/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for some libs needed by zImage.
3#
4
5
6lib-y := zlib.o zmem.o
diff --git a/arch/xtensa/boot/lib/memcpy.S b/arch/xtensa/boot/lib/memcpy.S
new file mode 100644
index 0000000000..a029f5df2d
--- /dev/null
+++ b/arch/xtensa/boot/lib/memcpy.S
@@ -0,0 +1,36 @@
1/*
2 * arch/xtensa/lib/memcpy.S
3 *
4 * ANSI C standard library function memcpy
5 *
6 * This file is subject to the terms and conditions of the GNU General
7 * Public License. See the file "COPYING" in the main directory of
8 * this archive for more details.
9 *
10 * Copyright (C) 2002 Tensilica Inc.
11 */
12
13#define _ASMLANGUAGE
14#include <xtensa/config/core.h>
15
16.text
17.align 4
18.global bcopy
19.type bcopy,@function
20bcopy:
21 movi a14, xthal_bcopy // a14 safe to use regardless of whether caller
22 // used call4 or call8 (can't have used call12)
23 jx a14 // let the Core HAL do the work
24
25.text
26.align 4
27.global memcpy
28.type memcpy,@function
29memcpy:
30.global memmove
31.type memmove,@function
32memmove:
33 movi a14, xthal_memcpy // a14 safe to use regardless of whether caller
34 // used call4 or call8 (can't have used call12)
35 jx a14 // let the Core HAL do the work
36
diff --git a/arch/xtensa/boot/lib/zlib.c b/arch/xtensa/boot/lib/zlib.c
new file mode 100644
index 0000000000..e3859f6310
--- /dev/null
+++ b/arch/xtensa/boot/lib/zlib.c
@@ -0,0 +1,2150 @@
1/*
2 * BK Id: SCCS/s.zlib.c 1.8 05/18/01 15:17:24 cort
3 */
4/*
5 * This file is derived from various .h and .c files from the zlib-0.95
6 * distribution by Jean-loup Gailly and Mark Adler, with some additions
7 * by Paul Mackerras to aid in implementing Deflate compression and
8 * decompression for PPP packets. See zlib.h for conditions of
9 * distribution and use.
10 *
11 * Changes that have been made include:
12 * - changed functions not used outside this file to "local"
13 * - added minCompression parameter to deflateInit2
14 * - added Z_PACKET_FLUSH (see zlib.h for details)
15 * - added inflateIncomp
16 *
17 */
18
19/*+++++*/
20/* zutil.h -- internal interface and configuration of the compression library
21 * Copyright (C) 1995 Jean-loup Gailly.
22 * For conditions of distribution and use, see copyright notice in zlib.h
23 */
24
25/* WARNING: this file should *not* be used by applications. It is
26 part of the implementation of the compression library and is
27 subject to change. Applications should only use zlib.h.
28 */
29
30/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
31
32#define _Z_UTIL_H
33
34#include "zlib.h"
35
36#ifndef local
37# define local static
38#endif
39/* compile with -Dlocal if your debugger can't find static symbols */
40
41#define FAR
42
43typedef unsigned char uch;
44typedef uch FAR uchf;
45typedef unsigned short ush;
46typedef ush FAR ushf;
47typedef unsigned long ulg;
48
49extern char *z_errmsg[]; /* indexed by 1-zlib_error */
50
51#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
52/* To be used only when the state is known to be valid */
53
54#ifndef NULL
55#define NULL ((void *) 0)
56#endif
57
58 /* common constants */
59
60#define DEFLATED 8
61
62#ifndef DEF_WBITS
63# define DEF_WBITS MAX_WBITS
64#endif
65/* default windowBits for decompression. MAX_WBITS is for compression only */
66
67#if MAX_MEM_LEVEL >= 8
68# define DEF_MEM_LEVEL 8
69#else
70# define DEF_MEM_LEVEL MAX_MEM_LEVEL
71#endif
72/* default memLevel */
73
74#define STORED_BLOCK 0
75#define STATIC_TREES 1
76#define DYN_TREES 2
77/* The three kinds of block type */
78
79#define MIN_MATCH 3
80#define MAX_MATCH 258
81/* The minimum and maximum match lengths */
82
83 /* functions */
84
85#include <linux/string.h>
86#define zmemcpy memcpy
87#define zmemzero(dest, len) memset(dest, 0, len)
88
89/* Diagnostic functions */
90#ifdef DEBUG_ZLIB
91# include <stdio.h>
92# ifndef verbose
93# define verbose 0
94# endif
95# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
96# define Trace(x) fprintf x
97# define Tracev(x) {if (verbose) fprintf x ;}
98# define Tracevv(x) {if (verbose>1) fprintf x ;}
99# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
100# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
101#else
102# define Assert(cond,msg)
103# define Trace(x)
104# define Tracev(x)
105# define Tracevv(x)
106# define Tracec(c,x)
107# define Tracecv(c,x)
108#endif
109
110
111typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
112
113/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
114/* void zcfree OF((voidpf opaque, voidpf ptr)); */
115
116#define ZALLOC(strm, items, size) \
117 (*((strm)->zalloc))((strm)->opaque, (items), (size))
118#define ZFREE(strm, addr, size) \
119 (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
120#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
121
122/* deflate.h -- internal compression state
123 * Copyright (C) 1995 Jean-loup Gailly
124 * For conditions of distribution and use, see copyright notice in zlib.h
125 */
126
127/* WARNING: this file should *not* be used by applications. It is
128 part of the implementation of the compression library and is
129 subject to change. Applications should only use zlib.h.
130 */
131
132/*+++++*/
133/* infblock.h -- header to use infblock.c
134 * Copyright (C) 1995 Mark Adler
135 * For conditions of distribution and use, see copyright notice in zlib.h
136 */
137
138/* WARNING: this file should *not* be used by applications. It is
139 part of the implementation of the compression library and is
140 subject to change. Applications should only use zlib.h.
141 */
142
143struct inflate_blocks_state;
144typedef struct inflate_blocks_state FAR inflate_blocks_statef;
145
146local inflate_blocks_statef * inflate_blocks_new OF((
147 z_stream *z,
148 check_func c, /* check function */
149 uInt w)); /* window size */
150
151local int inflate_blocks OF((
152 inflate_blocks_statef *,
153 z_stream *,
154 int)); /* initial return code */
155
156local void inflate_blocks_reset OF((
157 inflate_blocks_statef *,
158 z_stream *,
159 uLongf *)); /* check value on output */
160
161local int inflate_blocks_free OF((
162 inflate_blocks_statef *,
163 z_stream *,
164 uLongf *)); /* check value on output */
165
166local int inflate_addhistory OF((
167 inflate_blocks_statef *,
168 z_stream *));
169
170local int inflate_packet_flush OF((
171 inflate_blocks_statef *));
172
173/*+++++*/
174/* inftrees.h -- header to use inftrees.c
175 * Copyright (C) 1995 Mark Adler
176 * For conditions of distribution and use, see copyright notice in zlib.h
177 */
178
179/* WARNING: this file should *not* be used by applications. It is
180 part of the implementation of the compression library and is
181 subject to change. Applications should only use zlib.h.
182 */
183
184/* Huffman code lookup table entry--this entry is four bytes for machines
185 that have 16-bit pointers (e.g. PC's in the small or medium model). */
186
187typedef struct inflate_huft_s FAR inflate_huft;
188
189struct inflate_huft_s {
190 union {
191 struct {
192 Byte Exop; /* number of extra bits or operation */
193 Byte Bits; /* number of bits in this code or subcode */
194 } what;
195 uInt Nalloc; /* number of these allocated here */
196 Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
197 } word; /* 16-bit, 8 bytes for 32-bit machines) */
198 union {
199 uInt Base; /* literal, length base, or distance base */
200 inflate_huft *Next; /* pointer to next level of table */
201 } more;
202};
203
204#ifdef DEBUG_ZLIB
205 local uInt inflate_hufts;
206#endif
207
208local int inflate_trees_bits OF((
209 uIntf *, /* 19 code lengths */
210 uIntf *, /* bits tree desired/actual depth */
211 inflate_huft * FAR *, /* bits tree result */
212 z_stream *)); /* for zalloc, zfree functions */
213
214local int inflate_trees_dynamic OF((
215 uInt, /* number of literal/length codes */
216 uInt, /* number of distance codes */
217 uIntf *, /* that many (total) code lengths */
218 uIntf *, /* literal desired/actual bit depth */
219 uIntf *, /* distance desired/actual bit depth */
220 inflate_huft * FAR *, /* literal/length tree result */
221 inflate_huft * FAR *, /* distance tree result */
222 z_stream *)); /* for zalloc, zfree functions */
223
224local int inflate_trees_fixed OF((
225 uIntf *, /* literal desired/actual bit depth */
226 uIntf *, /* distance desired/actual bit depth */
227 inflate_huft * FAR *, /* literal/length tree result */
228 inflate_huft * FAR *)); /* distance tree result */
229
230local int inflate_trees_free OF((
231 inflate_huft *, /* tables to free */
232 z_stream *)); /* for zfree function */
233
234
235/*+++++*/
236/* infcodes.h -- header to use infcodes.c
237 * Copyright (C) 1995 Mark Adler
238 * For conditions of distribution and use, see copyright notice in zlib.h
239 */
240
241/* WARNING: this file should *not* be used by applications. It is
242 part of the implementation of the compression library and is
243 subject to change. Applications should only use zlib.h.
244 */
245
246struct inflate_codes_state;
247typedef struct inflate_codes_state FAR inflate_codes_statef;
248
249local inflate_codes_statef *inflate_codes_new OF((
250 uInt, uInt,
251 inflate_huft *, inflate_huft *,
252 z_stream *));
253
254local int inflate_codes OF((
255 inflate_blocks_statef *,
256 z_stream *,
257 int));
258
259local void inflate_codes_free OF((
260 inflate_codes_statef *,
261 z_stream *));
262
263
264/*+++++*/
265/* inflate.c -- zlib interface to inflate modules
266 * Copyright (C) 1995 Mark Adler
267 * For conditions of distribution and use, see copyright notice in zlib.h
268 */
269
270/* inflate private state */
271struct internal_state {
272
273 /* mode */
274 enum {
275 METHOD, /* waiting for method byte */
276 FLAG, /* waiting for flag byte */
277 BLOCKS, /* decompressing blocks */
278 CHECK4, /* four check bytes to go */
279 CHECK3, /* three check bytes to go */
280 CHECK2, /* two check bytes to go */
281 CHECK1, /* one check byte to go */
282 DONE, /* finished check, done */
283 BAD} /* got an error--stay here */
284 mode; /* current inflate mode */
285
286 /* mode dependent information */
287 union {
288 uInt method; /* if FLAGS, method byte */
289 struct {
290 uLong was; /* computed check value */
291 uLong need; /* stream check value */
292 } check; /* if CHECK, check values to compare */
293 uInt marker; /* if BAD, inflateSync's marker bytes count */
294 } sub; /* submode */
295
296 /* mode independent information */
297 int nowrap; /* flag for no wrapper */
298 uInt wbits; /* log2(window size) (8..15, defaults to 15) */
299 inflate_blocks_statef
300 *blocks; /* current inflate_blocks state */
301
302};
303
304
305int inflateReset(z)
306z_stream *z;
307{
308 uLong c;
309
310 if (z == Z_NULL || z->state == Z_NULL)
311 return Z_STREAM_ERROR;
312 z->total_in = z->total_out = 0;
313 z->msg = Z_NULL;
314 z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
315 inflate_blocks_reset(z->state->blocks, z, &c);
316 Trace((stderr, "inflate: reset\n"));
317 return Z_OK;
318}
319
320
321int inflateEnd(z)
322z_stream *z;
323{
324 uLong c;
325
326 if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
327 return Z_STREAM_ERROR;
328 if (z->state->blocks != Z_NULL)
329 inflate_blocks_free(z->state->blocks, z, &c);
330 ZFREE(z, z->state, sizeof(struct internal_state));
331 z->state = Z_NULL;
332 Trace((stderr, "inflate: end\n"));
333 return Z_OK;
334}
335
336
337int inflateInit2(z, w)
338z_stream *z;
339int w;
340{
341 /* initialize state */
342 if (z == Z_NULL)
343 return Z_STREAM_ERROR;
344/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
345/* if (z->zfree == Z_NULL) z->zfree = zcfree; */
346 if ((z->state = (struct internal_state FAR *)
347 ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
348 return Z_MEM_ERROR;
349 z->state->blocks = Z_NULL;
350
351 /* handle undocumented nowrap option (no zlib header or check) */
352 z->state->nowrap = 0;
353 if (w < 0)
354 {
355 w = - w;
356 z->state->nowrap = 1;
357 }
358
359 /* set window size */
360 if (w < 8 || w > 15)
361 {
362 inflateEnd(z);
363 return Z_STREAM_ERROR;
364 }
365 z->state->wbits = (uInt)w;
366
367 /* create inflate_blocks state */
368 if ((z->state->blocks =
369 inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
370 == Z_NULL)
371 {
372 inflateEnd(z);
373 return Z_MEM_ERROR;
374 }
375 Trace((stderr, "inflate: allocated\n"));
376
377 /* reset state */
378 inflateReset(z);
379 return Z_OK;
380}
381
382
383int inflateInit(z)
384z_stream *z;
385{
386 return inflateInit2(z, DEF_WBITS);
387}
388
389
390#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
391#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
392
393int inflate(z, f)
394z_stream *z;
395int f;
396{
397 int r;
398 uInt b;
399
400 if (z == Z_NULL || z->next_in == Z_NULL)
401 return Z_STREAM_ERROR;
402 r = Z_BUF_ERROR;
403 while (1) switch (z->state->mode)
404 {
405 case METHOD:
406 NEEDBYTE
407 if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
408 {
409 z->state->mode = BAD;
410 z->msg = "unknown compression method";
411 z->state->sub.marker = 5; /* can't try inflateSync */
412 break;
413 }
414 if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
415 {
416 z->state->mode = BAD;
417 z->msg = "invalid window size";
418 z->state->sub.marker = 5; /* can't try inflateSync */
419 break;
420 }
421 z->state->mode = FLAG;
422 case FLAG:
423 NEEDBYTE
424 if ((b = NEXTBYTE) & 0x20)
425 {
426 z->state->mode = BAD;
427 z->msg = "invalid reserved bit";
428 z->state->sub.marker = 5; /* can't try inflateSync */
429 break;
430 }
431 if (((z->state->sub.method << 8) + b) % 31)
432 {
433 z->state->mode = BAD;
434 z->msg = "incorrect header check";
435 z->state->sub.marker = 5; /* can't try inflateSync */
436 break;
437 }
438 Trace((stderr, "inflate: zlib header ok\n"));
439 z->state->mode = BLOCKS;
440 case BLOCKS:
441 r = inflate_blocks(z->state->blocks, z, r);
442 if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
443 r = inflate_packet_flush(z->state->blocks);
444 if (r == Z_DATA_ERROR)
445 {
446 z->state->mode = BAD;
447 z->state->sub.marker = 0; /* can try inflateSync */
448 break;
449 }
450 if (r != Z_STREAM_END)
451 return r;
452 r = Z_OK;
453 inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
454 if (z->state->nowrap)
455 {
456 z->state->mode = DONE;
457 break;
458 }
459 z->state->mode = CHECK4;
460 case CHECK4:
461 NEEDBYTE
462 z->state->sub.check.need = (uLong)NEXTBYTE << 24;
463 z->state->mode = CHECK3;
464 case CHECK3:
465 NEEDBYTE
466 z->state->sub.check.need += (uLong)NEXTBYTE << 16;
467 z->state->mode = CHECK2;
468 case CHECK2:
469 NEEDBYTE
470 z->state->sub.check.need += (uLong)NEXTBYTE << 8;
471 z->state->mode = CHECK1;
472 case CHECK1:
473 NEEDBYTE
474 z->state->sub.check.need += (uLong)NEXTBYTE;
475
476 if (z->state->sub.check.was != z->state->sub.check.need)
477 {
478 z->state->mode = BAD;
479 z->msg = "incorrect data check";
480 z->state->sub.marker = 5; /* can't try inflateSync */
481 break;
482 }
483 Trace((stderr, "inflate: zlib check ok\n"));
484 z->state->mode = DONE;
485 case DONE:
486 return Z_STREAM_END;
487 case BAD:
488 return Z_DATA_ERROR;
489 default:
490 return Z_STREAM_ERROR;
491 }
492
493 empty:
494 if (f != Z_PACKET_FLUSH)
495 return r;
496 z->state->mode = BAD;
497 z->state->sub.marker = 0; /* can try inflateSync */
498 return Z_DATA_ERROR;
499}
500
501/*
502 * This subroutine adds the data at next_in/avail_in to the output history
503 * without performing any output. The output buffer must be "caught up";
504 * i.e. no pending output (hence s->read equals s->write), and the state must
505 * be BLOCKS (i.e. we should be willing to see the start of a series of
506 * BLOCKS). On exit, the output will also be caught up, and the checksum
507 * will have been updated if need be.
508 */
509
510int inflateIncomp(z)
511z_stream *z;
512{
513 if (z->state->mode != BLOCKS)
514 return Z_DATA_ERROR;
515 return inflate_addhistory(z->state->blocks, z);
516}
517
518
519int inflateSync(z)
520z_stream *z;
521{
522 uInt n; /* number of bytes to look at */
523 Bytef *p; /* pointer to bytes */
524 uInt m; /* number of marker bytes found in a row */
525 uLong r, w; /* temporaries to save total_in and total_out */
526
527 /* set up */
528 if (z == Z_NULL || z->state == Z_NULL)
529 return Z_STREAM_ERROR;
530 if (z->state->mode != BAD)
531 {
532 z->state->mode = BAD;
533 z->state->sub.marker = 0;
534 }
535 if ((n = z->avail_in) == 0)
536 return Z_BUF_ERROR;
537 p = z->next_in;
538 m = z->state->sub.marker;
539
540 /* search */
541 while (n && m < 4)
542 {
543 if (*p == (Byte)(m < 2 ? 0 : 0xff))
544 m++;
545 else if (*p)
546 m = 0;
547 else
548 m = 4 - m;
549 p++, n--;
550 }
551
552 /* restore */
553 z->total_in += p - z->next_in;
554 z->next_in = p;
555 z->avail_in = n;
556 z->state->sub.marker = m;
557
558 /* return no joy or set up to restart on a new block */
559 if (m != 4)
560 return Z_DATA_ERROR;
561 r = z->total_in; w = z->total_out;
562 inflateReset(z);
563 z->total_in = r; z->total_out = w;
564 z->state->mode = BLOCKS;
565 return Z_OK;
566}
567
568#undef NEEDBYTE
569#undef NEXTBYTE
570
571/*+++++*/
572/* infutil.h -- types and macros common to blocks and codes
573 * Copyright (C) 1995 Mark Adler
574 * For conditions of distribution and use, see copyright notice in zlib.h
575 */
576
577/* WARNING: this file should *not* be used by applications. It is
578 part of the implementation of the compression library and is
579 subject to change. Applications should only use zlib.h.
580 */
581
582/* inflate blocks semi-private state */
583struct inflate_blocks_state {
584
585 /* mode */
586 enum {
587 TYPE, /* get type bits (3, including end bit) */
588 LENS, /* get lengths for stored */
589 STORED, /* processing stored block */
590 TABLE, /* get table lengths */
591 BTREE, /* get bit lengths tree for a dynamic block */
592 DTREE, /* get length, distance trees for a dynamic block */
593 CODES, /* processing fixed or dynamic block */
594 DRY, /* output remaining window bytes */
595 DONEB, /* finished last block, done */
596 BADB} /* got a data error--stuck here */
597 mode; /* current inflate_block mode */
598
599 /* mode dependent information */
600 union {
601 uInt left; /* if STORED, bytes left to copy */
602 struct {
603 uInt table; /* table lengths (14 bits) */
604 uInt index; /* index into blens (or border) */
605 uIntf *blens; /* bit lengths of codes */
606 uInt bb; /* bit length tree depth */
607 inflate_huft *tb; /* bit length decoding tree */
608 int nblens; /* # elements allocated at blens */
609 } trees; /* if DTREE, decoding info for trees */
610 struct {
611 inflate_huft *tl, *td; /* trees to free */
612 inflate_codes_statef
613 *codes;
614 } decode; /* if CODES, current state */
615 } sub; /* submode */
616 uInt last; /* true if this block is the last block */
617
618 /* mode independent information */
619 uInt bitk; /* bits in bit buffer */
620 uLong bitb; /* bit buffer */
621 Bytef *window; /* sliding window */
622 Bytef *end; /* one byte after sliding window */
623 Bytef *read; /* window read pointer */
624 Bytef *write; /* window write pointer */
625 check_func checkfn; /* check function */
626 uLong check; /* check on output */
627
628};
629
630
631/* defines for inflate input/output */
632/* update pointers and return */
633#define UPDBITS {s->bitb=b;s->bitk=k;}
634#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
635#define UPDOUT {s->write=q;}
636#define UPDATE {UPDBITS UPDIN UPDOUT}
637#define LEAVE {UPDATE return inflate_flush(s,z,r);}
638/* get bytes and bits */
639#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
640#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
641#define NEXTBYTE (n--,*p++)
642#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
643#define DUMPBITS(j) {b>>=(j);k-=(j);}
644/* output bytes */
645#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
646#define LOADOUT {q=s->write;m=WAVAIL;}
647#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
648#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
649#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
650#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
651/* load local pointers */
652#define LOAD {LOADIN LOADOUT}
653
654/*
655 * The IBM 150 firmware munges the data right after _etext[]. This
656 * protects it. -- Cort
657 */
658local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
659/* And'ing with mask[n] masks the lower n bits */
660local uInt inflate_mask[] = {
661 0x0000,
662 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
663 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
664};
665
666/* copy as much as possible from the sliding window to the output area */
667local int inflate_flush OF((
668 inflate_blocks_statef *,
669 z_stream *,
670 int));
671
672/*+++++*/
673/* inffast.h -- header to use inffast.c
674 * Copyright (C) 1995 Mark Adler
675 * For conditions of distribution and use, see copyright notice in zlib.h
676 */
677
678/* WARNING: this file should *not* be used by applications. It is
679 part of the implementation of the compression library and is
680 subject to change. Applications should only use zlib.h.
681 */
682
683local int inflate_fast OF((
684 uInt,
685 uInt,
686 inflate_huft *,
687 inflate_huft *,
688 inflate_blocks_statef *,
689 z_stream *));
690
691
692/*+++++*/
693/* infblock.c -- interpret and process block types to last block
694 * Copyright (C) 1995 Mark Adler
695 * For conditions of distribution and use, see copyright notice in zlib.h
696 */
697
698/* Table for deflate from PKZIP's appnote.txt. */
699local uInt border[] = { /* Order of the bit length code lengths */
700 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
701
702/*
703 Notes beyond the 1.93a appnote.txt:
704
705 1. Distance pointers never point before the beginning of the output
706 stream.
707 2. Distance pointers can point back across blocks, up to 32k away.
708 3. There is an implied maximum of 7 bits for the bit length table and
709 15 bits for the actual data.
710 4. If only one code exists, then it is encoded using one bit. (Zero
711 would be more efficient, but perhaps a little confusing.) If two
712 codes exist, they are coded using one bit each (0 and 1).
713 5. There is no way of sending zero distance codes--a dummy must be
714 sent if there are none. (History: a pre 2.0 version of PKZIP would
715 store blocks with no distance codes, but this was discovered to be
716 too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
717 zero distance codes, which is sent as one code of zero bits in
718 length.
719 6. There are up to 286 literal/length codes. Code 256 represents the
720 end-of-block. Note however that the static length tree defines
721 288 codes just to fill out the Huffman codes. Codes 286 and 287
722 cannot be used though, since there is no length base or extra bits
723 defined for them. Similarily, there are up to 30 distance codes.
724 However, static trees define 32 codes (all 5 bits) to fill out the
725 Huffman codes, but the last two had better not show up in the data.
726 7. Unzip can check dynamic Huffman blocks for complete code sets.
727 The exception is that a single code would not be complete (see #4).
728 8. The five bits following the block type is really the number of
729 literal codes sent minus 257.
730 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
731 (1+6+6). Therefore, to output three times the length, you output
732 three codes (1+1+1), whereas to output four times the same length,
733 you only need two codes (1+3). Hmm.
734 10. In the tree reconstruction algorithm, Code = Code + Increment
735 only if BitLength(i) is not zero. (Pretty obvious.)
736 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
737 12. Note: length code 284 can represent 227-258, but length code 285
738 really is 258. The last length deserves its own, short code
739 since it gets used a lot in very redundant files. The length
740 258 is special since 258 - 3 (the min match length) is 255.
741 13. The literal/length and distance code bit lengths are read as a
742 single stream of lengths. It is possible (and advantageous) for
743 a repeat code (16, 17, or 18) to go across the boundary between
744 the two sets of lengths.
745 */
746
747
748local void inflate_blocks_reset(s, z, c)
749inflate_blocks_statef *s;
750z_stream *z;
751uLongf *c;
752{
753 if (s->checkfn != Z_NULL)
754 *c = s->check;
755 if (s->mode == BTREE || s->mode == DTREE)
756 ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
757 if (s->mode == CODES)
758 {
759 inflate_codes_free(s->sub.decode.codes, z);
760 inflate_trees_free(s->sub.decode.td, z);
761 inflate_trees_free(s->sub.decode.tl, z);
762 }
763 s->mode = TYPE;
764 s->bitk = 0;
765 s->bitb = 0;
766 s->read = s->write = s->window;
767 if (s->checkfn != Z_NULL)
768 s->check = (*s->checkfn)(0L, Z_NULL, 0);
769 Trace((stderr, "inflate: blocks reset\n"));
770}
771
772
773local inflate_blocks_statef *inflate_blocks_new(z, c, w)
774z_stream *z;
775check_func c;
776uInt w;
777{
778 inflate_blocks_statef *s;
779
780 if ((s = (inflate_blocks_statef *)ZALLOC
781 (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
782 return s;
783 if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
784 {
785 ZFREE(z, s, sizeof(struct inflate_blocks_state));
786 return Z_NULL;
787 }
788 s->end = s->window + w;
789 s->checkfn = c;
790 s->mode = TYPE;
791 Trace((stderr, "inflate: blocks allocated\n"));
792 inflate_blocks_reset(s, z, &s->check);
793 return s;
794}
795
796
797local int inflate_blocks(s, z, r)
798inflate_blocks_statef *s;
799z_stream *z;
800int r;
801{
802 uInt t; /* temporary storage */
803 uLong b; /* bit buffer */
804 uInt k; /* bits in bit buffer */
805 Bytef *p; /* input data pointer */
806 uInt n; /* bytes available there */
807 Bytef *q; /* output window write pointer */
808 uInt m; /* bytes to end of window or read pointer */
809
810 /* copy input/output information to locals (UPDATE macro restores) */
811 LOAD
812
813 /* process input based on current state */
814 while (1) switch (s->mode)
815 {
816 case TYPE:
817 NEEDBITS(3)
818 t = (uInt)b & 7;
819 s->last = t & 1;
820 switch (t >> 1)
821 {
822 case 0: /* stored */
823 Trace((stderr, "inflate: stored block%s\n",
824 s->last ? " (last)" : ""));
825 DUMPBITS(3)
826 t = k & 7; /* go to byte boundary */
827 DUMPBITS(t)
828 s->mode = LENS; /* get length of stored block */
829 break;
830 case 1: /* fixed */
831 Trace((stderr, "inflate: fixed codes block%s\n",
832 s->last ? " (last)" : ""));
833 {
834 uInt bl, bd;
835 inflate_huft *tl, *td;
836
837 inflate_trees_fixed(&bl, &bd, &tl, &td);
838 s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
839 if (s->sub.decode.codes == Z_NULL)
840 {
841 r = Z_MEM_ERROR;
842 LEAVE
843 }
844 s->sub.decode.tl = Z_NULL; /* don't try to free these */
845 s->sub.decode.td = Z_NULL;
846 }
847 DUMPBITS(3)
848 s->mode = CODES;
849 break;
850 case 2: /* dynamic */
851 Trace((stderr, "inflate: dynamic codes block%s\n",
852 s->last ? " (last)" : ""));
853 DUMPBITS(3)
854 s->mode = TABLE;
855 break;
856 case 3: /* illegal */
857 DUMPBITS(3)
858 s->mode = BADB;
859 z->msg = "invalid block type";
860 r = Z_DATA_ERROR;
861 LEAVE
862 }
863 break;
864 case LENS:
865 NEEDBITS(32)
866 if (((~b) >> 16) != (b & 0xffff))
867 {
868 s->mode = BADB;
869 z->msg = "invalid stored block lengths";
870 r = Z_DATA_ERROR;
871 LEAVE
872 }
873 s->sub.left = (uInt)b & 0xffff;
874 b = k = 0; /* dump bits */
875 Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
876 s->mode = s->sub.left ? STORED : TYPE;
877 break;
878 case STORED:
879 if (n == 0)
880 LEAVE
881 NEEDOUT
882 t = s->sub.left;
883 if (t > n) t = n;
884 if (t > m) t = m;
885 zmemcpy(q, p, t);
886 p += t; n -= t;
887 q += t; m -= t;
888 if ((s->sub.left -= t) != 0)
889 break;
890 Tracev((stderr, "inflate: stored end, %lu total out\n",
891 z->total_out + (q >= s->read ? q - s->read :
892 (s->end - s->read) + (q - s->window))));
893 s->mode = s->last ? DRY : TYPE;
894 break;
895 case TABLE:
896 NEEDBITS(14)
897 s->sub.trees.table = t = (uInt)b & 0x3fff;
898#ifndef PKZIP_BUG_WORKAROUND
899 if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
900 {
901 s->mode = BADB;
902 z->msg = "too many length or distance symbols";
903 r = Z_DATA_ERROR;
904 LEAVE
905 }
906#endif
907 t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
908 if (t < 19)
909 t = 19;
910 if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
911 {
912 r = Z_MEM_ERROR;
913 LEAVE
914 }
915 s->sub.trees.nblens = t;
916 DUMPBITS(14)
917 s->sub.trees.index = 0;
918 Tracev((stderr, "inflate: table sizes ok\n"));
919 s->mode = BTREE;
920 case BTREE:
921 while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
922 {
923 NEEDBITS(3)
924 s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
925 DUMPBITS(3)
926 }
927 while (s->sub.trees.index < 19)
928 s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
929 s->sub.trees.bb = 7;
930 t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
931 &s->sub.trees.tb, z);
932 if (t != Z_OK)
933 {
934 r = t;
935 if (r == Z_DATA_ERROR)
936 s->mode = BADB;
937 LEAVE
938 }
939 s->sub.trees.index = 0;
940 Tracev((stderr, "inflate: bits tree ok\n"));
941 s->mode = DTREE;
942 case DTREE:
943 while (t = s->sub.trees.table,
944 s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
945 {
946 inflate_huft *h;
947 uInt i, j, c;
948
949 t = s->sub.trees.bb;
950 NEEDBITS(t)
951 h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
952 t = h->word.what.Bits;
953 c = h->more.Base;
954 if (c < 16)
955 {
956 DUMPBITS(t)
957 s->sub.trees.blens[s->sub.trees.index++] = c;
958 }
959 else /* c == 16..18 */
960 {
961 i = c == 18 ? 7 : c - 14;
962 j = c == 18 ? 11 : 3;
963 NEEDBITS(t + i)
964 DUMPBITS(t)
965 j += (uInt)b & inflate_mask[i];
966 DUMPBITS(i)
967 i = s->sub.trees.index;
968 t = s->sub.trees.table;
969 if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
970 (c == 16 && i < 1))
971 {
972 s->mode = BADB;
973 z->msg = "invalid bit length repeat";
974 r = Z_DATA_ERROR;
975 LEAVE
976 }
977 c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
978 do {
979 s->sub.trees.blens[i++] = c;
980 } while (--j);
981 s->sub.trees.index = i;
982 }
983 }
984 inflate_trees_free(s->sub.trees.tb, z);
985 s->sub.trees.tb = Z_NULL;
986 {
987 uInt bl, bd;
988 inflate_huft *tl, *td;
989 inflate_codes_statef *c;
990
991 bl = 9; /* must be <= 9 for lookahead assumptions */
992 bd = 6; /* must be <= 9 for lookahead assumptions */
993 t = s->sub.trees.table;
994 t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
995 s->sub.trees.blens, &bl, &bd, &tl, &td, z);
996 if (t != Z_OK)
997 {
998 if (t == (uInt)Z_DATA_ERROR)
999 s->mode = BADB;
1000 r = t;
1001 LEAVE
1002 }
1003 Tracev((stderr, "inflate: trees ok\n"));
1004 if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
1005 {
1006 inflate_trees_free(td, z);
1007 inflate_trees_free(tl, z);
1008 r = Z_MEM_ERROR;
1009 LEAVE
1010 }
1011 ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
1012 s->sub.decode.codes = c;
1013 s->sub.decode.tl = tl;
1014 s->sub.decode.td = td;
1015 }
1016 s->mode = CODES;
1017 case CODES:
1018 UPDATE
1019 if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
1020 return inflate_flush(s, z, r);
1021 r = Z_OK;
1022 inflate_codes_free(s->sub.decode.codes, z);
1023 inflate_trees_free(s->sub.decode.td, z);
1024 inflate_trees_free(s->sub.decode.tl, z);
1025 LOAD
1026 Tracev((stderr, "inflate: codes end, %lu total out\n",
1027 z->total_out + (q >= s->read ? q - s->read :
1028 (s->end - s->read) + (q - s->window))));
1029 if (!s->last)
1030 {
1031 s->mode = TYPE;
1032 break;
1033 }
1034 if (k > 7) /* return unused byte, if any */
1035 {
1036 Assert(k < 16, "inflate_codes grabbed too many bytes")
1037 k -= 8;
1038 n++;
1039 p--; /* can always return one */
1040 }
1041 s->mode = DRY;
1042 case DRY:
1043 FLUSH
1044 if (s->read != s->write)
1045 LEAVE
1046 s->mode = DONEB;
1047 case DONEB:
1048 r = Z_STREAM_END;
1049 LEAVE
1050 case BADB:
1051 r = Z_DATA_ERROR;
1052 LEAVE
1053 default:
1054 r = Z_STREAM_ERROR;
1055 LEAVE
1056 }
1057}
1058
1059
1060local int inflate_blocks_free(s, z, c)
1061inflate_blocks_statef *s;
1062z_stream *z;
1063uLongf *c;
1064{
1065 inflate_blocks_reset(s, z, c);
1066 ZFREE(z, s->window, s->end - s->window);
1067 ZFREE(z, s, sizeof(struct inflate_blocks_state));
1068 Trace((stderr, "inflate: blocks freed\n"));
1069 return Z_OK;
1070}
1071
1072/*
1073 * This subroutine adds the data at next_in/avail_in to the output history
1074 * without performing any output. The output buffer must be "caught up";
1075 * i.e. no pending output (hence s->read equals s->write), and the state must
1076 * be BLOCKS (i.e. we should be willing to see the start of a series of
1077 * BLOCKS). On exit, the output will also be caught up, and the checksum
1078 * will have been updated if need be.
1079 */
1080local int inflate_addhistory(s, z)
1081inflate_blocks_statef *s;
1082z_stream *z;
1083{
1084 uLong b; /* bit buffer */ /* NOT USED HERE */
1085 uInt k; /* bits in bit buffer */ /* NOT USED HERE */
1086 uInt t; /* temporary storage */
1087 Bytef *p; /* input data pointer */
1088 uInt n; /* bytes available there */
1089 Bytef *q; /* output window write pointer */
1090 uInt m; /* bytes to end of window or read pointer */
1091
1092 if (s->read != s->write)
1093 return Z_STREAM_ERROR;
1094 if (s->mode != TYPE)
1095 return Z_DATA_ERROR;
1096
1097 /* we're ready to rock */
1098 LOAD
1099 /* while there is input ready, copy to output buffer, moving
1100 * pointers as needed.
1101 */
1102 while (n) {
1103 t = n; /* how many to do */
1104 /* is there room until end of buffer? */
1105 if (t > m) t = m;
1106 /* update check information */
1107 if (s->checkfn != Z_NULL)
1108 s->check = (*s->checkfn)(s->check, q, t);
1109 zmemcpy(q, p, t);
1110 q += t;
1111 p += t;
1112 n -= t;
1113 z->total_out += t;
1114 s->read = q; /* drag read pointer forward */
1115/* WRAP */ /* expand WRAP macro by hand to handle s->read */
1116 if (q == s->end) {
1117 s->read = q = s->window;
1118 m = WAVAIL;
1119 }
1120 }
1121 UPDATE
1122 return Z_OK;
1123}
1124
1125
1126/*
1127 * At the end of a Deflate-compressed PPP packet, we expect to have seen
1128 * a `stored' block type value but not the (zero) length bytes.
1129 */
1130local int inflate_packet_flush(s)
1131 inflate_blocks_statef *s;
1132{
1133 if (s->mode != LENS)
1134 return Z_DATA_ERROR;
1135 s->mode = TYPE;
1136 return Z_OK;
1137}
1138
1139
1140/*+++++*/
1141/* inftrees.c -- generate Huffman trees for efficient decoding
1142 * Copyright (C) 1995 Mark Adler
1143 * For conditions of distribution and use, see copyright notice in zlib.h
1144 */
1145
1146/* simplify the use of the inflate_huft type with some defines */
1147#define base more.Base
1148#define next more.Next
1149#define exop word.what.Exop
1150#define bits word.what.Bits
1151
1152
1153local int huft_build OF((
1154 uIntf *, /* code lengths in bits */
1155 uInt, /* number of codes */
1156 uInt, /* number of "simple" codes */
1157 uIntf *, /* list of base values for non-simple codes */
1158 uIntf *, /* list of extra bits for non-simple codes */
1159 inflate_huft * FAR*,/* result: starting table */
1160 uIntf *, /* maximum lookup bits (returns actual) */
1161 z_stream *)); /* for zalloc function */
1162
1163local voidpf falloc OF((
1164 voidpf, /* opaque pointer (not used) */
1165 uInt, /* number of items */
1166 uInt)); /* size of item */
1167
1168local void ffree OF((
1169 voidpf q, /* opaque pointer (not used) */
1170 voidpf p, /* what to free (not used) */
1171 uInt n)); /* number of bytes (not used) */
1172
1173/* Tables for deflate from PKZIP's appnote.txt. */
1174local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
1175 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
1176 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
1177 /* actually lengths - 2; also see note #13 above about 258 */
1178local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
1179 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
1180 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
1181local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
1182 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
1183 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
1184 8193, 12289, 16385, 24577};
1185local uInt cpdext[] = { /* Extra bits for distance codes */
1186 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
1187 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
1188 12, 12, 13, 13};
1189
1190/*
1191 Huffman code decoding is performed using a multi-level table lookup.
1192 The fastest way to decode is to simply build a lookup table whose
1193 size is determined by the longest code. However, the time it takes
1194 to build this table can also be a factor if the data being decoded
1195 is not very long. The most common codes are necessarily the
1196 shortest codes, so those codes dominate the decoding time, and hence
1197 the speed. The idea is you can have a shorter table that decodes the
1198 shorter, more probable codes, and then point to subsidiary tables for
1199 the longer codes. The time it costs to decode the longer codes is
1200 then traded against the time it takes to make longer tables.
1201
1202 This results of this trade are in the variables lbits and dbits
1203 below. lbits is the number of bits the first level table for literal/
1204 length codes can decode in one step, and dbits is the same thing for
1205 the distance codes. Subsequent tables are also less than or equal to
1206 those sizes. These values may be adjusted either when all of the
1207 codes are shorter than that, in which case the longest code length in
1208 bits is used, or when the shortest code is *longer* than the requested
1209 table size, in which case the length of the shortest code in bits is
1210 used.
1211
1212 There are two different values for the two tables, since they code a
1213 different number of possibilities each. The literal/length table
1214 codes 286 possible values, or in a flat code, a little over eight
1215 bits. The distance table codes 30 possible values, or a little less
1216 than five bits, flat. The optimum values for speed end up being
1217 about one bit more than those, so lbits is 8+1 and dbits is 5+1.
1218 The optimum values may differ though from machine to machine, and
1219 possibly even between compilers. Your mileage may vary.
1220 */
1221
1222
1223/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
1224#define BMAX 15 /* maximum bit length of any code */
1225#define N_MAX 288 /* maximum number of codes in any set */
1226
1227#ifdef DEBUG_ZLIB
1228 uInt inflate_hufts;
1229#endif
1230
1231local int huft_build(b, n, s, d, e, t, m, zs)
1232uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
1233uInt n; /* number of codes (assumed <= N_MAX) */
1234uInt s; /* number of simple-valued codes (0..s-1) */
1235uIntf *d; /* list of base values for non-simple codes */
1236uIntf *e; /* list of extra bits for non-simple codes */
1237inflate_huft * FAR *t; /* result: starting table */
1238uIntf *m; /* maximum lookup bits, returns actual */
1239z_stream *zs; /* for zalloc function */
1240/* Given a list of code lengths and a maximum table size, make a set of
1241 tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
1242 if the given code set is incomplete (the tables are still built in this
1243 case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
1244 over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
1245{
1246
1247 uInt a; /* counter for codes of length k */
1248 uInt c[BMAX+1]; /* bit length count table */
1249 uInt f; /* i repeats in table every f entries */
1250 int g; /* maximum code length */
1251 int h; /* table level */
1252 register uInt i; /* counter, current code */
1253 register uInt j; /* counter */
1254 register int k; /* number of bits in current code */
1255 int l; /* bits per table (returned in m) */
1256 register uIntf *p; /* pointer into c[], b[], or v[] */
1257 inflate_huft *q; /* points to current table */
1258 struct inflate_huft_s r; /* table entry for structure assignment */
1259 inflate_huft *u[BMAX]; /* table stack */
1260 uInt v[N_MAX]; /* values in order of bit length */
1261 register int w; /* bits before this table == (l * h) */
1262 uInt x[BMAX+1]; /* bit offsets, then code stack */
1263 uIntf *xp; /* pointer into x */
1264 int y; /* number of dummy codes added */
1265 uInt z; /* number of entries in current table */
1266
1267
1268 /* Generate counts for each bit length */
1269 p = c;
1270#define C0 *p++ = 0;
1271#define C2 C0 C0 C0 C0
1272#define C4 C2 C2 C2 C2
1273 C4 /* clear c[]--assume BMAX+1 is 16 */
1274 p = b; i = n;
1275 do {
1276 c[*p++]++; /* assume all entries <= BMAX */
1277 } while (--i);
1278 if (c[0] == n) /* null input--all zero length codes */
1279 {
1280 *t = (inflate_huft *)Z_NULL;
1281 *m = 0;
1282 return Z_OK;
1283 }
1284
1285
1286 /* Find minimum and maximum length, bound *m by those */
1287 l = *m;
1288 for (j = 1; j <= BMAX; j++)
1289 if (c[j])
1290 break;
1291 k = j; /* minimum code length */
1292 if ((uInt)l < j)
1293 l = j;
1294 for (i = BMAX; i; i--)
1295 if (c[i])
1296 break;
1297 g = i; /* maximum code length */
1298 if ((uInt)l > i)
1299 l = i;
1300 *m = l;
1301
1302
1303 /* Adjust last length count to fill out codes, if needed */
1304 for (y = 1 << j; j < i; j++, y <<= 1)
1305 if ((y -= c[j]) < 0)
1306 return Z_DATA_ERROR;
1307 if ((y -= c[i]) < 0)
1308 return Z_DATA_ERROR;
1309 c[i] += y;
1310
1311
1312 /* Generate starting offsets into the value table for each length */
1313 x[1] = j = 0;
1314 p = c + 1; xp = x + 2;
1315 while (--i) { /* note that i == g from above */
1316 *xp++ = (j += *p++);
1317 }
1318
1319
1320 /* Make a table of values in order of bit lengths */
1321 p = b; i = 0;
1322 do {
1323 if ((j = *p++) != 0)
1324 v[x[j]++] = i;
1325 } while (++i < n);
1326
1327
1328 /* Generate the Huffman codes and for each, make the table entries */
1329 x[0] = i = 0; /* first Huffman code is zero */
1330 p = v; /* grab values in bit order */
1331 h = -1; /* no tables yet--level -1 */
1332 w = -l; /* bits decoded == (l * h) */
1333 u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
1334 q = (inflate_huft *)Z_NULL; /* ditto */
1335 z = 0; /* ditto */
1336
1337 /* go through the bit lengths (k already is bits in shortest code) */
1338 for (; k <= g; k++)
1339 {
1340 a = c[k];
1341 while (a--)
1342 {
1343 /* here i is the Huffman code of length k bits for value *p */
1344 /* make tables up to required level */
1345 while (k > w + l)
1346 {
1347 h++;
1348 w += l; /* previous table always l bits */
1349
1350 /* compute minimum size table less than or equal to l bits */
1351 z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */
1352 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
1353 { /* too few codes for k-w bit table */
1354 f -= a + 1; /* deduct codes from patterns left */
1355 xp = c + k;
1356 if (j < z)
1357 while (++j < z) /* try smaller tables up to z bits */
1358 {
1359 if ((f <<= 1) <= *++xp)
1360 break; /* enough codes to use up j bits */
1361 f -= *xp; /* else deduct codes from patterns */
1362 }
1363 }
1364 z = 1 << j; /* table entries for j-bit table */
1365
1366 /* allocate and link in new table */
1367 if ((q = (inflate_huft *)ZALLOC
1368 (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
1369 {
1370 if (h)
1371 inflate_trees_free(u[0], zs);
1372 return Z_MEM_ERROR; /* not enough memory */
1373 }
1374 q->word.Nalloc = z + 1;
1375#ifdef DEBUG_ZLIB
1376 inflate_hufts += z + 1;
1377#endif
1378 *t = q + 1; /* link to list for huft_free() */
1379 *(t = &(q->next)) = Z_NULL;
1380 u[h] = ++q; /* table starts after link */
1381
1382 /* connect to last table, if there is one */
1383 if (h)
1384 {
1385 x[h] = i; /* save pattern for backing up */
1386 r.bits = (Byte)l; /* bits to dump before this table */
1387 r.exop = (Byte)j; /* bits in this table */
1388 r.next = q; /* pointer to this table */
1389 j = i >> (w - l); /* (get around Turbo C bug) */
1390 u[h-1][j] = r; /* connect to last table */
1391 }
1392 }
1393
1394 /* set up table entry in r */
1395 r.bits = (Byte)(k - w);
1396 if (p >= v + n)
1397 r.exop = 128 + 64; /* out of values--invalid code */
1398 else if (*p < s)
1399 {
1400 r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
1401 r.base = *p++; /* simple code is just the value */
1402 }
1403 else
1404 {
1405 r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
1406 r.base = d[*p++ - s];
1407 }
1408
1409 /* fill code-like entries with r */
1410 f = 1 << (k - w);
1411 for (j = i >> w; j < z; j += f)
1412 q[j] = r;
1413
1414 /* backwards increment the k-bit code i */
1415 for (j = 1 << (k - 1); i & j; j >>= 1)
1416 i ^= j;
1417 i ^= j;
1418
1419 /* backup over finished tables */
1420 while ((i & ((1 << w) - 1)) != x[h])
1421 {
1422 h--; /* don't need to update q */
1423 w -= l;
1424 }
1425 }
1426 }
1427
1428
1429 /* Return Z_BUF_ERROR if we were given an incomplete table */
1430 return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
1431}
1432
1433
1434local int inflate_trees_bits(c, bb, tb, z)
1435uIntf *c; /* 19 code lengths */
1436uIntf *bb; /* bits tree desired/actual depth */
1437inflate_huft * FAR *tb; /* bits tree result */
1438z_stream *z; /* for zfree function */
1439{
1440 int r;
1441
1442 r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
1443 if (r == Z_DATA_ERROR)
1444 z->msg = "oversubscribed dynamic bit lengths tree";
1445 else if (r == Z_BUF_ERROR)
1446 {
1447 inflate_trees_free(*tb, z);
1448 z->msg = "incomplete dynamic bit lengths tree";
1449 r = Z_DATA_ERROR;
1450 }
1451 return r;
1452}
1453
1454
1455local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
1456uInt nl; /* number of literal/length codes */
1457uInt nd; /* number of distance codes */
1458uIntf *c; /* that many (total) code lengths */
1459uIntf *bl; /* literal desired/actual bit depth */
1460uIntf *bd; /* distance desired/actual bit depth */
1461inflate_huft * FAR *tl; /* literal/length tree result */
1462inflate_huft * FAR *td; /* distance tree result */
1463z_stream *z; /* for zfree function */
1464{
1465 int r;
1466
1467 /* build literal/length tree */
1468 if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
1469 {
1470 if (r == Z_DATA_ERROR)
1471 z->msg = "oversubscribed literal/length tree";
1472 else if (r == Z_BUF_ERROR)
1473 {
1474 inflate_trees_free(*tl, z);
1475 z->msg = "incomplete literal/length tree";
1476 r = Z_DATA_ERROR;
1477 }
1478 return r;
1479 }
1480
1481 /* build distance tree */
1482 if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
1483 {
1484 if (r == Z_DATA_ERROR)
1485 z->msg = "oversubscribed literal/length tree";
1486 else if (r == Z_BUF_ERROR) {
1487#ifdef PKZIP_BUG_WORKAROUND
1488 r = Z_OK;
1489 }
1490#else
1491 inflate_trees_free(*td, z);
1492 z->msg = "incomplete literal/length tree";
1493 r = Z_DATA_ERROR;
1494 }
1495 inflate_trees_free(*tl, z);
1496 return r;
1497#endif
1498 }
1499
1500 /* done */
1501 return Z_OK;
1502}
1503
1504
1505/* build fixed tables only once--keep them here */
1506local int fixed_lock = 0;
1507local int fixed_built = 0;
1508#define FIXEDH 530 /* number of hufts used by fixed tables */
1509local uInt fixed_left = FIXEDH;
1510local inflate_huft fixed_mem[FIXEDH];
1511local uInt fixed_bl;
1512local uInt fixed_bd;
1513local inflate_huft *fixed_tl;
1514local inflate_huft *fixed_td;
1515
1516
1517local voidpf falloc(q, n, s)
1518voidpf q; /* opaque pointer (not used) */
1519uInt n; /* number of items */
1520uInt s; /* size of item */
1521{
1522 Assert(s == sizeof(inflate_huft) && n <= fixed_left,
1523 "inflate_trees falloc overflow");
1524 if (q) s++; /* to make some compilers happy */
1525 fixed_left -= n;
1526 return (voidpf)(fixed_mem + fixed_left);
1527}
1528
1529
1530local void ffree(q, p, n)
1531voidpf q;
1532voidpf p;
1533uInt n;
1534{
1535 Assert(0, "inflate_trees ffree called!");
1536 if (q) q = p; /* to make some compilers happy */
1537}
1538
1539
1540local int inflate_trees_fixed(bl, bd, tl, td)
1541uIntf *bl; /* literal desired/actual bit depth */
1542uIntf *bd; /* distance desired/actual bit depth */
1543inflate_huft * FAR *tl; /* literal/length tree result */
1544inflate_huft * FAR *td; /* distance tree result */
1545{
1546 /* build fixed tables if not built already--lock out other instances */
1547 while (++fixed_lock > 1)
1548 fixed_lock--;
1549 if (!fixed_built)
1550 {
1551 int k; /* temporary variable */
1552 unsigned c[288]; /* length list for huft_build */
1553 z_stream z; /* for falloc function */
1554
1555 /* set up fake z_stream for memory routines */
1556 z.zalloc = falloc;
1557 z.zfree = ffree;
1558 z.opaque = Z_NULL;
1559
1560 /* literal table */
1561 for (k = 0; k < 144; k++)
1562 c[k] = 8;
1563 for (; k < 256; k++)
1564 c[k] = 9;
1565 for (; k < 280; k++)
1566 c[k] = 7;
1567 for (; k < 288; k++)
1568 c[k] = 8;
1569 fixed_bl = 7;
1570 huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
1571
1572 /* distance table */
1573 for (k = 0; k < 30; k++)
1574 c[k] = 5;
1575 fixed_bd = 5;
1576 huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
1577
1578 /* done */
1579 fixed_built = 1;
1580 }
1581 fixed_lock--;
1582 *bl = fixed_bl;
1583 *bd = fixed_bd;
1584 *tl = fixed_tl;
1585 *td = fixed_td;
1586 return Z_OK;
1587}
1588
1589
1590local int inflate_trees_free(t, z)
1591inflate_huft *t; /* table to free */
1592z_stream *z; /* for zfree function */
1593/* Free the malloc'ed tables built by huft_build(), which makes a linked
1594 list of the tables it made, with the links in a dummy first entry of
1595 each table. */
1596{
1597 register inflate_huft *p, *q;
1598
1599 /* Go through linked list, freeing from the malloced (t[-1]) address. */
1600 p = t;
1601 while (p != Z_NULL)
1602 {
1603 q = (--p)->next;
1604 ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
1605 p = q;
1606 }
1607 return Z_OK;
1608}
1609
1610/*+++++*/
1611/* infcodes.c -- process literals and length/distance pairs
1612 * Copyright (C) 1995 Mark Adler
1613 * For conditions of distribution and use, see copyright notice in zlib.h
1614 */
1615
1616/* simplify the use of the inflate_huft type with some defines */
1617#define base more.Base
1618#define next more.Next
1619#define exop word.what.Exop
1620#define bits word.what.Bits
1621
1622/* inflate codes private state */
1623struct inflate_codes_state {
1624
1625 /* mode */
1626 enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
1627 START, /* x: set up for LEN */
1628 LEN, /* i: get length/literal/eob next */
1629 LENEXT, /* i: getting length extra (have base) */
1630 DIST, /* i: get distance next */
1631 DISTEXT, /* i: getting distance extra */
1632 COPY, /* o: copying bytes in window, waiting for space */
1633 LIT, /* o: got literal, waiting for output space */
1634 WASH, /* o: got eob, possibly still output waiting */
1635 END, /* x: got eob and all data flushed */
1636 BADCODE} /* x: got error */
1637 mode; /* current inflate_codes mode */
1638
1639 /* mode dependent information */
1640 uInt len;
1641 union {
1642 struct {
1643 inflate_huft *tree; /* pointer into tree */
1644 uInt need; /* bits needed */
1645 } code; /* if LEN or DIST, where in tree */
1646 uInt lit; /* if LIT, literal */
1647 struct {
1648 uInt get; /* bits to get for extra */
1649 uInt dist; /* distance back to copy from */
1650 } copy; /* if EXT or COPY, where and how much */
1651 } sub; /* submode */
1652
1653 /* mode independent information */
1654 Byte lbits; /* ltree bits decoded per branch */
1655 Byte dbits; /* dtree bits decoder per branch */
1656 inflate_huft *ltree; /* literal/length/eob tree */
1657 inflate_huft *dtree; /* distance tree */
1658
1659};
1660
1661
1662local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
1663uInt bl, bd;
1664inflate_huft *tl, *td;
1665z_stream *z;
1666{
1667 inflate_codes_statef *c;
1668
1669 if ((c = (inflate_codes_statef *)
1670 ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
1671 {
1672 c->mode = START;
1673 c->lbits = (Byte)bl;
1674 c->dbits = (Byte)bd;
1675 c->ltree = tl;
1676 c->dtree = td;
1677 Tracev((stderr, "inflate: codes new\n"));
1678 }
1679 return c;
1680}
1681
1682
1683local int inflate_codes(s, z, r)
1684inflate_blocks_statef *s;
1685z_stream *z;
1686int r;
1687{
1688 uInt j; /* temporary storage */
1689 inflate_huft *t; /* temporary pointer */
1690 uInt e; /* extra bits or operation */
1691 uLong b; /* bit buffer */
1692 uInt k; /* bits in bit buffer */
1693 Bytef *p; /* input data pointer */
1694 uInt n; /* bytes available there */
1695 Bytef *q; /* output window write pointer */
1696 uInt m; /* bytes to end of window or read pointer */
1697 Bytef *f; /* pointer to copy strings from */
1698 inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
1699
1700 /* copy input/output information to locals (UPDATE macro restores) */
1701 LOAD
1702
1703 /* process input and output based on current state */
1704 while (1) switch (c->mode)
1705 { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
1706 case START: /* x: set up for LEN */
1707#ifndef SLOW
1708 if (m >= 258 && n >= 10)
1709 {
1710 UPDATE
1711 r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
1712 LOAD
1713 if (r != Z_OK)
1714 {
1715 c->mode = r == Z_STREAM_END ? WASH : BADCODE;
1716 break;
1717 }
1718 }
1719#endif /* !SLOW */
1720 c->sub.code.need = c->lbits;
1721 c->sub.code.tree = c->ltree;
1722 c->mode = LEN;
1723 case LEN: /* i: get length/literal/eob next */
1724 j = c->sub.code.need;
1725 NEEDBITS(j)
1726 t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
1727 DUMPBITS(t->bits)
1728 e = (uInt)(t->exop);
1729 if (e == 0) /* literal */
1730 {
1731 c->sub.lit = t->base;
1732 Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
1733 "inflate: literal '%c'\n" :
1734 "inflate: literal 0x%02x\n", t->base));
1735 c->mode = LIT;
1736 break;
1737 }
1738 if (e & 16) /* length */
1739 {
1740 c->sub.copy.get = e & 15;
1741 c->len = t->base;
1742 c->mode = LENEXT;
1743 break;
1744 }
1745 if ((e & 64) == 0) /* next table */
1746 {
1747 c->sub.code.need = e;
1748 c->sub.code.tree = t->next;
1749 break;
1750 }
1751 if (e & 32) /* end of block */
1752 {
1753 Tracevv((stderr, "inflate: end of block\n"));
1754 c->mode = WASH;
1755 break;
1756 }
1757 c->mode = BADCODE; /* invalid code */
1758 z->msg = "invalid literal/length code";
1759 r = Z_DATA_ERROR;
1760 LEAVE
1761 case LENEXT: /* i: getting length extra (have base) */
1762 j = c->sub.copy.get;
1763 NEEDBITS(j)
1764 c->len += (uInt)b & inflate_mask[j];
1765 DUMPBITS(j)
1766 c->sub.code.need = c->dbits;
1767 c->sub.code.tree = c->dtree;
1768 Tracevv((stderr, "inflate: length %u\n", c->len));
1769 c->mode = DIST;
1770 case DIST: /* i: get distance next */
1771 j = c->sub.code.need;
1772 NEEDBITS(j)
1773 t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
1774 DUMPBITS(t->bits)
1775 e = (uInt)(t->exop);
1776 if (e & 16) /* distance */
1777 {
1778 c->sub.copy.get = e & 15;
1779 c->sub.copy.dist = t->base;
1780 c->mode = DISTEXT;
1781 break;
1782 }
1783 if ((e & 64) == 0) /* next table */
1784 {
1785 c->sub.code.need = e;
1786 c->sub.code.tree = t->next;
1787 break;
1788 }
1789 c->mode = BADCODE; /* invalid code */
1790 z->msg = "invalid distance code";
1791 r = Z_DATA_ERROR;
1792 LEAVE
1793 case DISTEXT: /* i: getting distance extra */
1794 j = c->sub.copy.get;
1795 NEEDBITS(j)
1796 c->sub.copy.dist += (uInt)b & inflate_mask[j];
1797 DUMPBITS(j)
1798 Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
1799 c->mode = COPY;
1800 case COPY: /* o: copying bytes in window, waiting for space */
1801#ifndef __TURBOC__ /* Turbo C bug for following expression */
1802 f = (uInt)(q - s->window) < c->sub.copy.dist ?
1803 s->end - (c->sub.copy.dist - (q - s->window)) :
1804 q - c->sub.copy.dist;
1805#else
1806 f = q - c->sub.copy.dist;
1807 if ((uInt)(q - s->window) < c->sub.copy.dist)
1808 f = s->end - (c->sub.copy.dist - (q - s->window));
1809#endif
1810 while (c->len)
1811 {
1812 NEEDOUT
1813 OUTBYTE(*f++)
1814 if (f == s->end)
1815 f = s->window;
1816 c->len--;
1817 }
1818 c->mode = START;
1819 break;
1820 case LIT: /* o: got literal, waiting for output space */
1821 NEEDOUT
1822 OUTBYTE(c->sub.lit)
1823 c->mode = START;
1824 break;
1825 case WASH: /* o: got eob, possibly more output */
1826 FLUSH
1827 if (s->read != s->write)
1828 LEAVE
1829 c->mode = END;
1830 case END:
1831 r = Z_STREAM_END;
1832 LEAVE
1833 case BADCODE: /* x: got error */
1834 r = Z_DATA_ERROR;
1835 LEAVE
1836 default:
1837 r = Z_STREAM_ERROR;
1838 LEAVE
1839 }
1840}
1841
1842
1843local void inflate_codes_free(c, z)
1844inflate_codes_statef *c;
1845z_stream *z;
1846{
1847 ZFREE(z, c, sizeof(struct inflate_codes_state));
1848 Tracev((stderr, "inflate: codes free\n"));
1849}
1850
1851/*+++++*/
1852/* inflate_util.c -- data and routines common to blocks and codes
1853 * Copyright (C) 1995 Mark Adler
1854 * For conditions of distribution and use, see copyright notice in zlib.h
1855 */
1856
1857/* copy as much as possible from the sliding window to the output area */
1858local int inflate_flush(s, z, r)
1859inflate_blocks_statef *s;
1860z_stream *z;
1861int r;
1862{
1863 uInt n;
1864 Bytef *p, *q;
1865
1866 /* local copies of source and destination pointers */
1867 p = z->next_out;
1868 q = s->read;
1869
1870 /* compute number of bytes to copy as far as end of window */
1871 n = (uInt)((q <= s->write ? s->write : s->end) - q);
1872 if (n > z->avail_out) n = z->avail_out;
1873 if (n && r == Z_BUF_ERROR) r = Z_OK;
1874
1875 /* update counters */
1876 z->avail_out -= n;
1877 z->total_out += n;
1878
1879 /* update check information */
1880 if (s->checkfn != Z_NULL)
1881 s->check = (*s->checkfn)(s->check, q, n);
1882
1883 /* copy as far as end of window */
1884 zmemcpy(p, q, n);
1885 p += n;
1886 q += n;
1887
1888 /* see if more to copy at beginning of window */
1889 if (q == s->end)
1890 {
1891 /* wrap pointers */
1892 q = s->window;
1893 if (s->write == s->end)
1894 s->write = s->window;
1895
1896 /* compute bytes to copy */
1897 n = (uInt)(s->write - q);
1898 if (n > z->avail_out) n = z->avail_out;
1899 if (n && r == Z_BUF_ERROR) r = Z_OK;
1900
1901 /* update counters */
1902 z->avail_out -= n;
1903 z->total_out += n;
1904
1905 /* update check information */
1906 if (s->checkfn != Z_NULL)
1907 s->check = (*s->checkfn)(s->check, q, n);
1908
1909 /* copy */
1910 zmemcpy(p, q, n);
1911 p += n;
1912 q += n;
1913 }
1914
1915 /* update pointers */
1916 z->next_out = p;
1917 s->read = q;
1918
1919 /* done */
1920 return r;
1921}
1922
1923
1924/*+++++*/
1925/* inffast.c -- process literals and length/distance pairs fast
1926 * Copyright (C) 1995 Mark Adler
1927 * For conditions of distribution and use, see copyright notice in zlib.h
1928 */
1929
1930/* simplify the use of the inflate_huft type with some defines */
1931#define base more.Base
1932#define next more.Next
1933#define exop word.what.Exop
1934#define bits word.what.Bits
1935
1936/* macros for bit input with no checking and for returning unused bytes */
1937#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
1938#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
1939
1940/* Called with number of bytes left to write in window at least 258
1941 (the maximum string length) and number of input bytes available
1942 at least ten. The ten bytes are six bytes for the longest length/
1943 distance pair plus four bytes for overloading the bit buffer. */
1944
1945local int inflate_fast(bl, bd, tl, td, s, z)
1946uInt bl, bd;
1947inflate_huft *tl, *td;
1948inflate_blocks_statef *s;
1949z_stream *z;
1950{
1951 inflate_huft *t; /* temporary pointer */
1952 uInt e; /* extra bits or operation */
1953 uLong b; /* bit buffer */
1954 uInt k; /* bits in bit buffer */
1955 Bytef *p; /* input data pointer */
1956 uInt n; /* bytes available there */
1957 Bytef *q; /* output window write pointer */
1958 uInt m; /* bytes to end of window or read pointer */
1959 uInt ml; /* mask for literal/length tree */
1960 uInt md; /* mask for distance tree */
1961 uInt c; /* bytes to copy */
1962 uInt d; /* distance back to copy from */
1963 Bytef *r; /* copy source pointer */
1964
1965 /* load input, output, bit values */
1966 LOAD
1967
1968 /* initialize masks */
1969 ml = inflate_mask[bl];
1970 md = inflate_mask[bd];
1971
1972 /* do until not enough input or output space for fast loop */
1973 do { /* assume called with m >= 258 && n >= 10 */
1974 /* get literal/length code */
1975 GRABBITS(20) /* max bits for literal/length code */
1976 if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
1977 {
1978 DUMPBITS(t->bits)
1979 Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
1980 "inflate: * literal '%c'\n" :
1981 "inflate: * literal 0x%02x\n", t->base));
1982 *q++ = (Byte)t->base;
1983 m--;
1984 continue;
1985 }
1986 do {
1987 DUMPBITS(t->bits)
1988 if (e & 16)
1989 {
1990 /* get extra bits for length */
1991 e &= 15;
1992 c = t->base + ((uInt)b & inflate_mask[e]);
1993 DUMPBITS(e)
1994 Tracevv((stderr, "inflate: * length %u\n", c));
1995
1996 /* decode distance base of block to copy */
1997 GRABBITS(15); /* max bits for distance code */
1998 e = (t = td + ((uInt)b & md))->exop;
1999 do {
2000 DUMPBITS(t->bits)
2001 if (e & 16)
2002 {
2003 /* get extra bits to add to distance base */
2004 e &= 15;
2005 GRABBITS(e) /* get extra bits (up to 13) */
2006 d = t->base + ((uInt)b & inflate_mask[e]);
2007 DUMPBITS(e)
2008 Tracevv((stderr, "inflate: * distance %u\n", d));
2009
2010 /* do the copy */
2011 m -= c;
2012 if ((uInt)(q - s->window) >= d) /* offset before dest */
2013 { /* just copy */
2014 r = q - d;
2015 *q++ = *r++; c--; /* minimum count is three, */
2016 *q++ = *r++; c--; /* so unroll loop a little */
2017 }
2018 else /* else offset after destination */
2019 {
2020 e = d - (q - s->window); /* bytes from offset to end */
2021 r = s->end - e; /* pointer to offset */
2022 if (c > e) /* if source crosses, */
2023 {
2024 c -= e; /* copy to end of window */
2025 do {
2026 *q++ = *r++;
2027 } while (--e);
2028 r = s->window; /* copy rest from start of window */
2029 }
2030 }
2031 do { /* copy all or what's left */
2032 *q++ = *r++;
2033 } while (--c);
2034 break;
2035 }
2036 else if ((e & 64) == 0)
2037 e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
2038 else
2039 {
2040 z->msg = "invalid distance code";
2041 UNGRAB
2042 UPDATE
2043 return Z_DATA_ERROR;
2044 }
2045 } while (1);
2046 break;
2047 }
2048 if ((e & 64) == 0)
2049 {
2050 if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
2051 {
2052 DUMPBITS(t->bits)
2053 Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
2054 "inflate: * literal '%c'\n" :
2055 "inflate: * literal 0x%02x\n", t->base));
2056 *q++ = (Byte)t->base;
2057 m--;
2058 break;
2059 }
2060 }
2061 else if (e & 32)
2062 {
2063 Tracevv((stderr, "inflate: * end of block\n"));
2064 UNGRAB
2065 UPDATE
2066 return Z_STREAM_END;
2067 }
2068 else
2069 {
2070 z->msg = "invalid literal/length code";
2071 UNGRAB
2072 UPDATE
2073 return Z_DATA_ERROR;
2074 }
2075 } while (1);
2076 } while (m >= 258 && n >= 10);
2077
2078 /* not enough input or output--restore pointers and return */
2079 UNGRAB
2080 UPDATE
2081 return Z_OK;
2082}
2083
2084
2085/*+++++*/
2086/* zutil.c -- target dependent utility functions for the compression library
2087 * Copyright (C) 1995 Jean-loup Gailly.
2088 * For conditions of distribution and use, see copyright notice in zlib.h
2089 */
2090
2091/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
2092
2093char *zlib_version = ZLIB_VERSION;
2094
2095char *z_errmsg[] = {
2096"stream end", /* Z_STREAM_END 1 */
2097"", /* Z_OK 0 */
2098"file error", /* Z_ERRNO (-1) */
2099"stream error", /* Z_STREAM_ERROR (-2) */
2100"data error", /* Z_DATA_ERROR (-3) */
2101"insufficient memory", /* Z_MEM_ERROR (-4) */
2102"buffer error", /* Z_BUF_ERROR (-5) */
2103""};
2104
2105
2106/*+++++*/
2107/* adler32.c -- compute the Adler-32 checksum of a data stream
2108 * Copyright (C) 1995 Mark Adler
2109 * For conditions of distribution and use, see copyright notice in zlib.h
2110 */
2111
2112/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
2113
2114#define BASE 65521L /* largest prime smaller than 65536 */
2115#define NMAX 5552
2116/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
2117
2118#define DO1(buf) {s1 += *buf++; s2 += s1;}
2119#define DO2(buf) DO1(buf); DO1(buf);
2120#define DO4(buf) DO2(buf); DO2(buf);
2121#define DO8(buf) DO4(buf); DO4(buf);
2122#define DO16(buf) DO8(buf); DO8(buf);
2123
2124/* ========================================================================= */
2125uLong adler32(adler, buf, len)
2126 uLong adler;
2127 Bytef *buf;
2128 uInt len;
2129{
2130 unsigned long s1 = adler & 0xffff;
2131 unsigned long s2 = (adler >> 16) & 0xffff;
2132 int k;
2133
2134 if (buf == Z_NULL) return 1L;
2135
2136 while (len > 0) {
2137 k = len < NMAX ? len : NMAX;
2138 len -= k;
2139 while (k >= 16) {
2140 DO16(buf);
2141 k -= 16;
2142 }
2143 if (k != 0) do {
2144 DO1(buf);
2145 } while (--k);
2146 s1 %= BASE;
2147 s2 %= BASE;
2148 }
2149 return (s2 << 16) | s1;
2150}
diff --git a/arch/xtensa/boot/lib/zmem.c b/arch/xtensa/boot/lib/zmem.c
new file mode 100644
index 0000000000..7848f126d6
--- /dev/null
+++ b/arch/xtensa/boot/lib/zmem.c
@@ -0,0 +1,87 @@
1#include "zlib.h"
2
3/* bits taken from ppc */
4
5extern void *avail_ram, *end_avail;
6
7void exit (void)
8{
9 for (;;);
10}
11
12void *zalloc(void *x, unsigned items, unsigned size)
13{
14 void *p = avail_ram;
15
16 size *= items;
17 size = (size + 7) & -8;
18 avail_ram += size;
19 if (avail_ram > end_avail) {
20 //puts("oops... out of memory\n");
21 //pause();
22 exit ();
23 }
24 return p;
25}
26
27void zfree(void *x, void *addr, unsigned nb)
28{
29}
30
31
32#define HEAD_CRC 2
33#define EXTRA_FIELD 4
34#define ORIG_NAME 8
35#define COMMENT 0x10
36#define RESERVED 0xe0
37
38#define DEFLATED 8
39
40void gunzip (void *dst, int dstlen, unsigned char *src, int *lenp)
41{
42 z_stream s;
43 int r, i, flags;
44
45 /* skip header */
46
47 i = 10;
48 flags = src[3];
49 if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
50 //puts("bad gzipped data\n");
51 exit();
52 }
53 if ((flags & EXTRA_FIELD) != 0)
54 i = 12 + src[10] + (src[11] << 8);
55 if ((flags & ORIG_NAME) != 0)
56 while (src[i++] != 0)
57 ;
58 if ((flags & COMMENT) != 0)
59 while (src[i++] != 0)
60 ;
61 if ((flags & HEAD_CRC) != 0)
62 i += 2;
63 if (i >= *lenp) {
64 //puts("gunzip: ran out of data in header\n");
65 exit();
66 }
67
68 s.zalloc = zalloc;
69 s.zfree = zfree;
70 r = inflateInit2(&s, -MAX_WBITS);
71 if (r != Z_OK) {
72 //puts("inflateInit2 returned "); puthex(r); puts("\n");
73 exit();
74 }
75 s.next_in = src + i;
76 s.avail_in = *lenp - i;
77 s.next_out = dst;
78 s.avail_out = dstlen;
79 r = inflate(&s, Z_FINISH);
80 if (r != Z_OK && r != Z_STREAM_END) {
81 //puts("inflate returned "); puthex(r); puts("\n");
82 exit();
83 }
84 *lenp = s.next_out - (unsigned char *) dst;
85 inflateEnd(&s);
86}
87
diff --git a/arch/xtensa/boot/ramdisk/Makefile b/arch/xtensa/boot/ramdisk/Makefile
new file mode 100644
index 0000000000..b12f763524
--- /dev/null
+++ b/arch/xtensa/boot/ramdisk/Makefile
@@ -0,0 +1,23 @@
1#
2# Makefile for a ramdisk image
3#
4
5BIG_ENDIAN := $(shell echo -e "\#ifdef __XTENSA_EL__\nint little;\n\#else\nint big;\n\#endif" | $(CC) -E -|grep -c big)
6
7ifeq ($(BIG_ENDIAN),1)
8OBJCOPY_ARGS := -O elf32-xtensa-be
9else
10OBJCOPY_ARGS := -O elf32-xtensa-le
11endif
12
13obj-y = ramdisk.o
14
15RAMDISK_IMAGE = arch/$(ARCH)/boot/ramdisk/$(CONFIG_EMBEDDED_RAMDISK_IMAGE)
16
17arch/$(ARCH)/boot/ramdisk/ramdisk.o:
18 $(Q)echo -e "dummy:" | $(AS) -o $@;
19 $(Q)$(OBJCOPY) $(OBJCOPY_ARGS) \
20 --add-section .initrd=$(RAMDISK_IMAGE) \
21 --set-section-flags .initrd=contents,alloc,load,load,data \
22 arch/$(ARCH)/boot/ramdisk/ramdisk.o $@
23
diff --git a/arch/xtensa/configs/common_defconfig b/arch/xtensa/configs/common_defconfig
new file mode 100644
index 0000000000..1d230ee081
--- /dev/null
+++ b/arch/xtensa/configs/common_defconfig
@@ -0,0 +1,662 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.11-rc2
4# Tue Mar 1 16:36:53 2005
5#
6# CONFIG_FRAME_POINTER is not set
7CONFIG_XTENSA=y
8# CONFIG_UID16 is not set
9CONFIG_RWSEM_XCHGADD_ALGORITHM=y
10CONFIG_HAVE_DEC_LOCK=y
11CONFIG_GENERIC_HARDIRQS=y
12
13#
14# Code maturity level options
15#
16CONFIG_EXPERIMENTAL=y
17CONFIG_CLEAN_COMPILE=y
18CONFIG_BROKEN_ON_SMP=y
19
20#
21# General setup
22#
23CONFIG_LOCALVERSION=""
24CONFIG_SWAP=y
25CONFIG_SYSVIPC=y
26# CONFIG_POSIX_MQUEUE is not set
27CONFIG_BSD_PROCESS_ACCT=y
28# CONFIG_BSD_PROCESS_ACCT_V3 is not set
29CONFIG_SYSCTL=y
30# CONFIG_AUDIT is not set
31CONFIG_LOG_BUF_SHIFT=14
32# CONFIG_HOTPLUG is not set
33CONFIG_KOBJECT_UEVENT=y
34# CONFIG_IKCONFIG is not set
35# CONFIG_EMBEDDED is not set
36CONFIG_KALLSYMS=y
37# CONFIG_KALLSYMS_ALL is not set
38# CONFIG_KALLSYMS_EXTRA_PASS is not set
39CONFIG_FUTEX=y
40CONFIG_EPOLL=y
41# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
42CONFIG_SHMEM=y
43CONFIG_CC_ALIGN_FUNCTIONS=0
44CONFIG_CC_ALIGN_LABELS=0
45CONFIG_CC_ALIGN_LOOPS=0
46CONFIG_CC_ALIGN_JUMPS=0
47# CONFIG_TINY_SHMEM is not set
48
49#
50# Loadable module support
51#
52CONFIG_MODULES=y
53# CONFIG_MODULE_UNLOAD is not set
54CONFIG_OBSOLETE_MODPARM=y
55CONFIG_MODVERSIONS=y
56# CONFIG_MODULE_SRCVERSION_ALL is not set
57CONFIG_KMOD=y
58
59#
60# Processor type and features
61#
62CONFIG_XTENSA_ARCH_LINUX_BE=y
63# CONFIG_XTENSA_ARCH_LINUX_LE is not set
64# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
65# CONFIG_XTENSA_ARCH_S5 is not set
66# CONFIG_XTENSA_CUSTOM is not set
67CONFIG_MMU=y
68# CONFIG_XTENSA_UNALIGNED_USER is not set
69# CONFIG_PREEMPT is not set
70# CONFIG_MATH_EMULATION is not set
71# CONFIG_HIGHMEM is not set
72
73#
74# Platform options
75#
76# CONFIG_XTENSA_PLATFORM_ISS is not set
77CONFIG_XTENSA_PLATFORM_XT2000=y
78CONFIG_XTENSA_CALIBRATE_CCOUNT=y
79CONFIG_GENERIC_CALIBRATE_DELAY=y
80CONFIG_CMDLINE_BOOL=y
81CONFIG_CMDLINE="console=ttyS0,38400 ip=bootp root=nfs nfsroot=/opt/montavista/pro/devkit/xtensa/linux_be/target"
82
83#
84# Bus options
85#
86CONFIG_PCI=y
87# CONFIG_PCI_LEGACY_PROC is not set
88# CONFIG_PCI_NAMES is not set
89
90#
91# PCCARD (PCMCIA/CardBus) support
92#
93# CONFIG_PCCARD is not set
94
95#
96# PC-card bridges
97#
98
99#
100# PCI Hotplug Support
101#
102# CONFIG_HOTPLUG_PCI is not set
103
104#
105# Exectuable file formats
106#
107CONFIG_KCORE_ELF=y
108CONFIG_BINFMT_ELF=y
109CONFIG_BINFMT_MISC=y
110
111#
112# Device Drivers
113#
114
115#
116# Generic Driver Options
117#
118CONFIG_STANDALONE=y
119CONFIG_PREVENT_FIRMWARE_BUILD=y
120# CONFIG_FW_LOADER is not set
121# CONFIG_DEBUG_DRIVER is not set
122
123#
124# Memory Technology Devices (MTD)
125#
126# CONFIG_MTD is not set
127
128#
129# Parallel port support
130#
131# CONFIG_PARPORT is not set
132
133#
134# Plug and Play support
135#
136
137#
138# Block devices
139#
140# CONFIG_BLK_DEV_FD is not set
141# CONFIG_BLK_CPQ_DA is not set
142# CONFIG_BLK_CPQ_CISS_DA is not set
143# CONFIG_BLK_DEV_DAC960 is not set
144# CONFIG_BLK_DEV_UMEM is not set
145# CONFIG_BLK_DEV_COW_COMMON is not set
146# CONFIG_BLK_DEV_LOOP is not set
147# CONFIG_BLK_DEV_NBD is not set
148# CONFIG_BLK_DEV_SX8 is not set
149# CONFIG_BLK_DEV_RAM is not set
150CONFIG_BLK_DEV_RAM_COUNT=16
151CONFIG_INITRAMFS_SOURCE=""
152# CONFIG_CDROM_PKTCDVD is not set
153
154#
155# IO Schedulers
156#
157CONFIG_IOSCHED_NOOP=y
158CONFIG_IOSCHED_AS=y
159CONFIG_IOSCHED_DEADLINE=y
160CONFIG_IOSCHED_CFQ=y
161# CONFIG_ATA_OVER_ETH is not set
162
163#
164# ATA/ATAPI/MFM/RLL support
165#
166# CONFIG_IDE is not set
167
168#
169# SCSI device support
170#
171# CONFIG_SCSI is not set
172
173#
174# Multi-device support (RAID and LVM)
175#
176# CONFIG_MD is not set
177
178#
179# Fusion MPT device support
180#
181
182#
183# IEEE 1394 (FireWire) support
184#
185# CONFIG_IEEE1394 is not set
186
187#
188# I2O device support
189#
190# CONFIG_I2O is not set
191
192#
193# Networking support
194#
195CONFIG_NET=y
196
197#
198# Networking options
199#
200# CONFIG_PACKET is not set
201# CONFIG_NETLINK_DEV is not set
202CONFIG_UNIX=y
203# CONFIG_NET_KEY is not set
204CONFIG_INET=y
205CONFIG_IP_MULTICAST=y
206CONFIG_IP_ADVANCED_ROUTER=y
207CONFIG_IP_MULTIPLE_TABLES=y
208CONFIG_IP_ROUTE_MULTIPATH=y
209CONFIG_IP_ROUTE_VERBOSE=y
210CONFIG_IP_PNP=y
211CONFIG_IP_PNP_DHCP=y
212CONFIG_IP_PNP_BOOTP=y
213CONFIG_IP_PNP_RARP=y
214# CONFIG_NET_IPIP is not set
215# CONFIG_NET_IPGRE is not set
216# CONFIG_IP_MROUTE is not set
217# CONFIG_ARPD is not set
218# CONFIG_SYN_COOKIES is not set
219# CONFIG_INET_AH is not set
220# CONFIG_INET_ESP is not set
221# CONFIG_INET_IPCOMP is not set
222# CONFIG_INET_TUNNEL is not set
223# CONFIG_IP_TCPDIAG is not set
224# CONFIG_IP_TCPDIAG_IPV6 is not set
225# CONFIG_IPV6 is not set
226# CONFIG_NETFILTER is not set
227
228#
229# SCTP Configuration (EXPERIMENTAL)
230#
231# CONFIG_IP_SCTP is not set
232# CONFIG_ATM is not set
233# CONFIG_BRIDGE is not set
234# CONFIG_VLAN_8021Q is not set
235# CONFIG_DECNET is not set
236# CONFIG_LLC2 is not set
237# CONFIG_IPX is not set
238# CONFIG_ATALK is not set
239# CONFIG_X25 is not set
240# CONFIG_LAPB is not set
241# CONFIG_NET_DIVERT is not set
242# CONFIG_ECONET is not set
243# CONFIG_WAN_ROUTER is not set
244
245#
246# QoS and/or fair queueing
247#
248CONFIG_NET_SCHED=y
249CONFIG_NET_SCH_CLK_JIFFIES=y
250# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
251# CONFIG_NET_SCH_CLK_CPU is not set
252CONFIG_NET_SCH_CBQ=m
253CONFIG_NET_SCH_HTB=m
254# CONFIG_NET_SCH_HFSC is not set
255CONFIG_NET_SCH_PRIO=m
256CONFIG_NET_SCH_RED=m
257CONFIG_NET_SCH_SFQ=m
258CONFIG_NET_SCH_TEQL=m
259CONFIG_NET_SCH_TBF=m
260CONFIG_NET_SCH_GRED=m
261CONFIG_NET_SCH_DSMARK=m
262# CONFIG_NET_SCH_NETEM is not set
263CONFIG_NET_SCH_INGRESS=m
264CONFIG_NET_QOS=y
265CONFIG_NET_ESTIMATOR=y
266CONFIG_NET_CLS=y
267CONFIG_NET_CLS_TCINDEX=m
268CONFIG_NET_CLS_ROUTE4=m
269CONFIG_NET_CLS_ROUTE=y
270CONFIG_NET_CLS_FW=m
271CONFIG_NET_CLS_U32=m
272# CONFIG_CLS_U32_PERF is not set
273# CONFIG_NET_CLS_IND is not set
274CONFIG_NET_CLS_RSVP=m
275CONFIG_NET_CLS_RSVP6=m
276# CONFIG_NET_CLS_ACT is not set
277CONFIG_NET_CLS_POLICE=y
278
279#
280# Network testing
281#
282# CONFIG_NET_PKTGEN is not set
283# CONFIG_NETPOLL is not set
284# CONFIG_NET_POLL_CONTROLLER is not set
285# CONFIG_HAMRADIO is not set
286# CONFIG_IRDA is not set
287# CONFIG_BT is not set
288CONFIG_NETDEVICES=y
289CONFIG_DUMMY=y
290# CONFIG_BONDING is not set
291# CONFIG_EQUALIZER is not set
292# CONFIG_TUN is not set
293
294#
295# ARCnet devices
296#
297# CONFIG_ARCNET is not set
298
299#
300# Ethernet (10 or 100Mbit)
301#
302CONFIG_NET_ETHERNET=y
303# CONFIG_MII is not set
304CONFIG_XT2000_SONIC=y
305# CONFIG_HAPPYMEAL is not set
306# CONFIG_SUNGEM is not set
307# CONFIG_NET_VENDOR_3COM is not set
308
309#
310# Tulip family network device support
311#
312# CONFIG_NET_TULIP is not set
313# CONFIG_HP100 is not set
314# CONFIG_NET_PCI is not set
315
316#
317# Ethernet (1000 Mbit)
318#
319# CONFIG_ACENIC is not set
320# CONFIG_DL2K is not set
321# CONFIG_E1000 is not set
322# CONFIG_NS83820 is not set
323# CONFIG_HAMACHI is not set
324# CONFIG_YELLOWFIN is not set
325# CONFIG_R8169 is not set
326# CONFIG_SK98LIN is not set
327# CONFIG_TIGON3 is not set
328
329#
330# Ethernet (10000 Mbit)
331#
332# CONFIG_IXGB is not set
333# CONFIG_S2IO is not set
334
335#
336# Token Ring devices
337#
338# CONFIG_TR is not set
339
340#
341# Wireless LAN (non-hamradio)
342#
343CONFIG_NET_RADIO=y
344
345#
346# Obsolete Wireless cards support (pre-802.11)
347#
348CONFIG_STRIP=m
349
350#
351# Wireless 802.11b ISA/PCI cards support
352#
353CONFIG_HERMES=m
354# CONFIG_PLX_HERMES is not set
355# CONFIG_TMD_HERMES is not set
356# CONFIG_PCI_HERMES is not set
357# CONFIG_ATMEL is not set
358
359#
360# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
361#
362# CONFIG_PRISM54 is not set
363CONFIG_NET_WIRELESS=y
364
365#
366# Wan interfaces
367#
368# CONFIG_WAN is not set
369# CONFIG_FDDI is not set
370# CONFIG_HIPPI is not set
371# CONFIG_PPP is not set
372# CONFIG_SLIP is not set
373# CONFIG_SHAPER is not set
374# CONFIG_NETCONSOLE is not set
375
376#
377# ISDN subsystem
378#
379# CONFIG_ISDN is not set
380
381#
382# Telephony Support
383#
384# CONFIG_PHONE is not set
385
386#
387# Input device support
388#
389CONFIG_INPUT=y
390
391#
392# Userland interfaces
393#
394CONFIG_INPUT_MOUSEDEV=y
395# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
396CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
397CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
398# CONFIG_INPUT_JOYDEV is not set
399# CONFIG_INPUT_TSDEV is not set
400# CONFIG_INPUT_EVDEV is not set
401# CONFIG_INPUT_EVBUG is not set
402
403#
404# Input I/O drivers
405#
406# CONFIG_GAMEPORT is not set
407CONFIG_SOUND_GAMEPORT=y
408CONFIG_SERIO=y
409# CONFIG_SERIO_I8042 is not set
410# CONFIG_SERIO_SERPORT is not set
411# CONFIG_SERIO_CT82C710 is not set
412# CONFIG_SERIO_PCIPS2 is not set
413# CONFIG_SERIO_RAW is not set
414
415#
416# Input Device Drivers
417#
418# CONFIG_INPUT_KEYBOARD is not set
419# CONFIG_INPUT_MOUSE is not set
420# CONFIG_INPUT_JOYSTICK is not set
421# CONFIG_INPUT_TOUCHSCREEN is not set
422# CONFIG_INPUT_MISC is not set
423
424#
425# Character devices
426#
427CONFIG_VT=y
428CONFIG_VT_CONSOLE=y
429CONFIG_HW_CONSOLE=y
430# CONFIG_SERIAL_NONSTANDARD is not set
431
432#
433# Serial drivers
434#
435CONFIG_SERIAL_8250=y
436CONFIG_SERIAL_8250_CONSOLE=y
437CONFIG_SERIAL_8250_NR_UARTS=4
438# CONFIG_SERIAL_8250_EXTENDED is not set
439
440#
441# Non-8250 serial port support
442#
443CONFIG_SERIAL_CORE=y
444CONFIG_SERIAL_CORE_CONSOLE=y
445CONFIG_UNIX98_PTYS=y
446CONFIG_LEGACY_PTYS=y
447CONFIG_LEGACY_PTY_COUNT=256
448
449#
450# IPMI
451#
452# CONFIG_IPMI_HANDLER is not set
453
454#
455# Watchdog Cards
456#
457# CONFIG_WATCHDOG is not set
458# CONFIG_RTC is not set
459# CONFIG_GEN_RTC is not set
460# CONFIG_DTLK is not set
461# CONFIG_R3964 is not set
462# CONFIG_APPLICOM is not set
463
464#
465# Ftape, the floppy tape device driver
466#
467# CONFIG_DRM is not set
468# CONFIG_RAW_DRIVER is not set
469
470#
471# I2C support
472#
473# CONFIG_I2C is not set
474
475#
476# Dallas's 1-wire bus
477#
478# CONFIG_W1 is not set
479
480#
481# Misc devices
482#
483
484#
485# Multimedia devices
486#
487# CONFIG_VIDEO_DEV is not set
488
489#
490# Digital Video Broadcasting Devices
491#
492# CONFIG_DVB is not set
493
494#
495# Graphics support
496#
497# CONFIG_FB is not set
498
499#
500# Console display driver support
501#
502# CONFIG_VGA_CONSOLE is not set
503CONFIG_DUMMY_CONSOLE=y
504# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
505
506#
507# Sound
508#
509# CONFIG_SOUND is not set
510
511#
512# USB support
513#
514# CONFIG_USB is not set
515CONFIG_USB_ARCH_HAS_HCD=y
516CONFIG_USB_ARCH_HAS_OHCI=y
517
518#
519# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
520#
521
522#
523# USB Gadget Support
524#
525# CONFIG_USB_GADGET is not set
526
527#
528# MMC/SD Card support
529#
530# CONFIG_MMC is not set
531
532#
533# InfiniBand support
534#
535# CONFIG_INFINIBAND is not set
536
537#
538# File systems
539#
540# CONFIG_EXT2_FS is not set
541# CONFIG_EXT3_FS is not set
542# CONFIG_JBD is not set
543# CONFIG_REISERFS_FS is not set
544# CONFIG_JFS_FS is not set
545# CONFIG_XFS_FS is not set
546# CONFIG_MINIX_FS is not set
547# CONFIG_ROMFS_FS is not set
548# CONFIG_QUOTA is not set
549CONFIG_DNOTIFY=y
550# CONFIG_AUTOFS_FS is not set
551# CONFIG_AUTOFS4_FS is not set
552
553#
554# CD-ROM/DVD Filesystems
555#
556# CONFIG_ISO9660_FS is not set
557# CONFIG_UDF_FS is not set
558
559#
560# DOS/FAT/NT Filesystems
561#
562# CONFIG_MSDOS_FS is not set
563# CONFIG_VFAT_FS is not set
564# CONFIG_NTFS_FS is not set
565
566#
567# Pseudo filesystems
568#
569CONFIG_PROC_FS=y
570# CONFIG_PROC_KCORE is not set
571CONFIG_SYSFS=y
572CONFIG_DEVFS_FS=y
573# CONFIG_DEVFS_MOUNT is not set
574# CONFIG_DEVFS_DEBUG is not set
575# CONFIG_DEVPTS_FS_XATTR is not set
576# CONFIG_TMPFS is not set
577# CONFIG_HUGETLB_PAGE is not set
578CONFIG_RAMFS=y
579
580#
581# Miscellaneous filesystems
582#
583# CONFIG_ADFS_FS is not set
584# CONFIG_AFFS_FS is not set
585# CONFIG_HFS_FS is not set
586# CONFIG_HFSPLUS_FS is not set
587# CONFIG_BEFS_FS is not set
588# CONFIG_BFS_FS is not set
589# CONFIG_EFS_FS is not set
590# CONFIG_CRAMFS is not set
591# CONFIG_VXFS_FS is not set
592# CONFIG_HPFS_FS is not set
593# CONFIG_QNX4FS_FS is not set
594# CONFIG_SYSV_FS is not set
595# CONFIG_UFS_FS is not set
596
597#
598# Network File Systems
599#
600CONFIG_NFS_FS=y
601CONFIG_NFS_V3=y
602# CONFIG_NFS_V4 is not set
603# CONFIG_NFS_DIRECTIO is not set
604# CONFIG_NFSD is not set
605CONFIG_ROOT_NFS=y
606CONFIG_LOCKD=y
607CONFIG_LOCKD_V4=y
608# CONFIG_EXPORTFS is not set
609CONFIG_SUNRPC=y
610# CONFIG_RPCSEC_GSS_KRB5 is not set
611# CONFIG_RPCSEC_GSS_SPKM3 is not set
612# CONFIG_SMB_FS is not set
613# CONFIG_CIFS is not set
614# CONFIG_NCP_FS is not set
615# CONFIG_CODA_FS is not set
616# CONFIG_AFS_FS is not set
617
618#
619# Partition Types
620#
621# CONFIG_PARTITION_ADVANCED is not set
622CONFIG_MSDOS_PARTITION=y
623
624#
625# Native Language Support
626#
627# CONFIG_NLS is not set
628
629#
630# Kernel hacking
631#
632CONFIG_DEBUG_KERNEL=y
633# CONFIG_DEBUG_STACKOVERFLOW is not set
634# CONFIG_DEBUG_SLAB is not set
635CONFIG_MAGIC_SYSRQ=y
636# CONFIG_DEBUG_SPINLOCK is not set
637# CONFIG_DEBUG_PAGEALLOC is not set
638# CONFIG_DEBUG_INFO is not set
639# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
640# CONFIG_KGDB is not set
641
642#
643# Security options
644#
645# CONFIG_KEYS is not set
646# CONFIG_SECURITY is not set
647
648#
649# Cryptographic options
650#
651# CONFIG_CRYPTO is not set
652
653#
654# Hardware crypto devices
655#
656
657#
658# Library routines
659#
660# CONFIG_CRC_CCITT is not set
661# CONFIG_CRC32 is not set
662# CONFIG_LIBCRC32C is not set
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig
new file mode 100644
index 0000000000..802621dd48
--- /dev/null
+++ b/arch/xtensa/configs/iss_defconfig
@@ -0,0 +1,531 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.11-rc2
4# Fri Feb 25 19:21:24 2005
5#
6CONFIG_FRAME_POINTER=y
7CONFIG_XTENSA=y
8# CONFIG_UID16 is not set
9CONFIG_RWSEM_XCHGADD_ALGORITHM=y
10CONFIG_HAVE_DEC_LOCK=y
11CONFIG_GENERIC_HARDIRQS=y
12
13#
14# Code maturity level options
15#
16CONFIG_EXPERIMENTAL=y
17CONFIG_CLEAN_COMPILE=y
18CONFIG_BROKEN_ON_SMP=y
19
20#
21# General setup
22#
23CONFIG_LOCALVERSION=""
24CONFIG_SWAP=y
25CONFIG_SYSVIPC=y
26# CONFIG_POSIX_MQUEUE is not set
27# CONFIG_BSD_PROCESS_ACCT is not set
28CONFIG_SYSCTL=y
29# CONFIG_AUDIT is not set
30CONFIG_LOG_BUF_SHIFT=14
31# CONFIG_HOTPLUG is not set
32# CONFIG_KOBJECT_UEVENT is not set
33# CONFIG_IKCONFIG is not set
34CONFIG_EMBEDDED=y
35CONFIG_KALLSYMS=y
36# CONFIG_KALLSYMS_ALL is not set
37# CONFIG_KALLSYMS_EXTRA_PASS is not set
38CONFIG_FUTEX=y
39CONFIG_EPOLL=y
40# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
41CONFIG_SHMEM=y
42CONFIG_CC_ALIGN_FUNCTIONS=0
43CONFIG_CC_ALIGN_LABELS=0
44CONFIG_CC_ALIGN_LOOPS=0
45CONFIG_CC_ALIGN_JUMPS=0
46# CONFIG_TINY_SHMEM is not set
47
48#
49# Loadable module support
50#
51# CONFIG_MODULES is not set
52
53#
54# Processor type and features
55#
56CONFIG_XTENSA_ARCH_LINUX_BE=y
57# CONFIG_XTENSA_ARCH_LINUX_LE is not set
58# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
59# CONFIG_XTENSA_ARCH_S5 is not set
60# CONFIG_XTENSA_CUSTOM is not set
61CONFIG_MMU=y
62# CONFIG_XTENSA_UNALIGNED_USER is not set
63# CONFIG_PREEMPT is not set
64# CONFIG_MATH_EMULATION is not set
65# CONFIG_HIGHMEM is not set
66
67#
68# Platform options
69#
70CONFIG_XTENSA_PLATFORM_ISS=y
71# CONFIG_XTENSA_PLATFORM_XT2000 is not set
72# CONFIG_XTENSA_PLATFORM_ARUBA is not set
73# CONFIG_XTENSA_CALIBRATE_CCOUNT is not set
74CONFIG_XTENSA_CPU_CLOCK=10
75# CONFIG_GENERIC_CALIBRATE_DELAY is not set
76CONFIG_CMDLINE_BOOL=y
77CONFIG_CMDLINE="console=ttyS0,38400 eth0=tuntap,,tap0 ip=192.168.168.5:192.168.168.1 root=nfs nfsroot=192.168.168.1:/opt/montavista/pro/devkit/xtensa/linux_be/target"
78CONFIG_SERIAL_CONSOLE=y
79CONFIG_XTENSA_ISS_NETWORK=y
80
81#
82# Bus options
83#
84
85#
86# PCCARD (PCMCIA/CardBus) support
87#
88# CONFIG_PCCARD is not set
89
90#
91# PC-card bridges
92#
93
94#
95# PCI Hotplug Support
96#
97
98#
99# Exectuable file formats
100#
101CONFIG_KCORE_ELF=y
102CONFIG_BINFMT_ELF=y
103# CONFIG_BINFMT_MISC is not set
104
105#
106# Device Drivers
107#
108
109#
110# Generic Driver Options
111#
112# CONFIG_STANDALONE is not set
113CONFIG_PREVENT_FIRMWARE_BUILD=y
114# CONFIG_FW_LOADER is not set
115# CONFIG_DEBUG_DRIVER is not set
116
117#
118# Memory Technology Devices (MTD)
119#
120# CONFIG_MTD is not set
121
122#
123# Parallel port support
124#
125# CONFIG_PARPORT is not set
126
127#
128# Plug and Play support
129#
130
131#
132# Block devices
133#
134# CONFIG_BLK_DEV_FD is not set
135# CONFIG_BLK_DEV_COW_COMMON is not set
136# CONFIG_BLK_DEV_LOOP is not set
137# CONFIG_BLK_DEV_NBD is not set
138# CONFIG_BLK_DEV_RAM is not set
139CONFIG_BLK_DEV_RAM_COUNT=16
140CONFIG_INITRAMFS_SOURCE=""
141# CONFIG_CDROM_PKTCDVD is not set
142
143#
144# IO Schedulers
145#
146CONFIG_IOSCHED_NOOP=y
147# CONFIG_IOSCHED_AS is not set
148# CONFIG_IOSCHED_DEADLINE is not set
149# CONFIG_IOSCHED_CFQ is not set
150# CONFIG_ATA_OVER_ETH is not set
151
152#
153# ATA/ATAPI/MFM/RLL support
154#
155# CONFIG_IDE is not set
156
157#
158# SCSI device support
159#
160# CONFIG_SCSI is not set
161
162#
163# Multi-device support (RAID and LVM)
164#
165# CONFIG_MD is not set
166
167#
168# Fusion MPT device support
169#
170
171#
172# IEEE 1394 (FireWire) support
173#
174
175#
176# I2O device support
177#
178
179#
180# Networking support
181#
182CONFIG_NET=y
183
184#
185# Networking options
186#
187CONFIG_PACKET=y
188# CONFIG_PACKET_MMAP is not set
189# CONFIG_NETLINK_DEV is not set
190CONFIG_UNIX=y
191# CONFIG_NET_KEY is not set
192CONFIG_INET=y
193# CONFIG_IP_MULTICAST is not set
194# CONFIG_IP_ADVANCED_ROUTER is not set
195CONFIG_IP_PNP=y
196CONFIG_IP_PNP_DHCP=y
197CONFIG_IP_PNP_BOOTP=y
198CONFIG_IP_PNP_RARP=y
199# CONFIG_NET_IPIP is not set
200# CONFIG_NET_IPGRE is not set
201# CONFIG_ARPD is not set
202# CONFIG_SYN_COOKIES is not set
203# CONFIG_INET_AH is not set
204# CONFIG_INET_ESP is not set
205# CONFIG_INET_IPCOMP is not set
206# CONFIG_INET_TUNNEL is not set
207# CONFIG_IP_TCPDIAG is not set
208# CONFIG_IP_TCPDIAG_IPV6 is not set
209# CONFIG_IPV6 is not set
210# CONFIG_NETFILTER is not set
211
212#
213# SCTP Configuration (EXPERIMENTAL)
214#
215# CONFIG_IP_SCTP is not set
216# CONFIG_SCTP_HMAC_NONE is not set
217# CONFIG_SCTP_HMAC_SHA1 is not set
218# CONFIG_SCTP_HMAC_MD5 is not set
219# CONFIG_ATM is not set
220# CONFIG_BRIDGE is not set
221# CONFIG_VLAN_8021Q is not set
222# CONFIG_DECNET is not set
223# CONFIG_LLC2 is not set
224# CONFIG_IPX is not set
225# CONFIG_ATALK is not set
226# CONFIG_X25 is not set
227# CONFIG_LAPB is not set
228# CONFIG_NET_DIVERT is not set
229# CONFIG_ECONET is not set
230# CONFIG_WAN_ROUTER is not set
231
232#
233# QoS and/or fair queueing
234#
235# CONFIG_NET_SCHED is not set
236# CONFIG_NET_SCH_CLK_JIFFIES is not set
237# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
238# CONFIG_NET_SCH_CLK_CPU is not set
239# CONFIG_NET_CLS_ROUTE is not set
240
241#
242# Network testing
243#
244# CONFIG_NET_PKTGEN is not set
245# CONFIG_NETPOLL is not set
246# CONFIG_NET_POLL_CONTROLLER is not set
247# CONFIG_HAMRADIO is not set
248# CONFIG_IRDA is not set
249# CONFIG_BT is not set
250# CONFIG_NETDEVICES is not set
251
252#
253# ISDN subsystem
254#
255# CONFIG_ISDN is not set
256
257#
258# Telephony Support
259#
260# CONFIG_PHONE is not set
261
262#
263# Input device support
264#
265CONFIG_INPUT=y
266
267#
268# Userland interfaces
269#
270# CONFIG_INPUT_MOUSEDEV is not set
271# CONFIG_INPUT_JOYDEV is not set
272# CONFIG_INPUT_TSDEV is not set
273# CONFIG_INPUT_EVDEV is not set
274# CONFIG_INPUT_EVBUG is not set
275
276#
277# Input I/O drivers
278#
279# CONFIG_GAMEPORT is not set
280CONFIG_SOUND_GAMEPORT=y
281# CONFIG_SERIO is not set
282# CONFIG_SERIO_I8042 is not set
283
284#
285# Input Device Drivers
286#
287# CONFIG_INPUT_KEYBOARD is not set
288# CONFIG_INPUT_MOUSE is not set
289# CONFIG_INPUT_JOYSTICK is not set
290# CONFIG_INPUT_TOUCHSCREEN is not set
291# CONFIG_INPUT_MISC is not set
292
293#
294# Character devices
295#
296CONFIG_VT=y
297CONFIG_VT_CONSOLE=y
298CONFIG_HW_CONSOLE=y
299# CONFIG_SERIAL_NONSTANDARD is not set
300
301#
302# Serial drivers
303#
304# CONFIG_SERIAL_8250 is not set
305
306#
307# Non-8250 serial port support
308#
309CONFIG_UNIX98_PTYS=y
310CONFIG_LEGACY_PTYS=y
311CONFIG_LEGACY_PTY_COUNT=256
312
313#
314# IPMI
315#
316# CONFIG_IPMI_HANDLER is not set
317
318#
319# Watchdog Cards
320#
321CONFIG_WATCHDOG=y
322CONFIG_WATCHDOG_NOWAYOUT=y
323
324#
325# Watchdog Device Drivers
326#
327CONFIG_SOFT_WATCHDOG=y
328# CONFIG_RTC is not set
329# CONFIG_GEN_RTC is not set
330# CONFIG_DTLK is not set
331# CONFIG_R3964 is not set
332
333#
334# Ftape, the floppy tape device driver
335#
336# CONFIG_DRM is not set
337# CONFIG_RAW_DRIVER is not set
338
339#
340# I2C support
341#
342# CONFIG_I2C is not set
343
344#
345# Dallas's 1-wire bus
346#
347# CONFIG_W1 is not set
348
349#
350# Misc devices
351#
352
353#
354# Multimedia devices
355#
356# CONFIG_VIDEO_DEV is not set
357
358#
359# Digital Video Broadcasting Devices
360#
361# CONFIG_DVB is not set
362
363#
364# Graphics support
365#
366# CONFIG_FB is not set
367
368#
369# Console display driver support
370#
371# CONFIG_VGA_CONSOLE is not set
372CONFIG_DUMMY_CONSOLE=y
373# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
374
375#
376# Sound
377#
378# CONFIG_SOUND is not set
379
380#
381# USB support
382#
383# CONFIG_USB_ARCH_HAS_HCD is not set
384# CONFIG_USB_ARCH_HAS_OHCI is not set
385
386#
387# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
388#
389
390#
391# USB Gadget Support
392#
393# CONFIG_USB_GADGET is not set
394
395#
396# MMC/SD Card support
397#
398# CONFIG_MMC is not set
399
400#
401# InfiniBand support
402#
403# CONFIG_INFINIBAND is not set
404
405#
406# File systems
407#
408# CONFIG_EXT2_FS is not set
409# CONFIG_EXT3_FS is not set
410# CONFIG_JBD is not set
411# CONFIG_REISERFS_FS is not set
412# CONFIG_JFS_FS is not set
413# CONFIG_XFS_FS is not set
414# CONFIG_MINIX_FS is not set
415# CONFIG_ROMFS_FS is not set
416# CONFIG_QUOTA is not set
417# CONFIG_DNOTIFY is not set
418# CONFIG_AUTOFS_FS is not set
419# CONFIG_AUTOFS4_FS is not set
420
421#
422# CD-ROM/DVD Filesystems
423#
424# CONFIG_ISO9660_FS is not set
425# CONFIG_UDF_FS is not set
426
427#
428# DOS/FAT/NT Filesystems
429#
430# CONFIG_MSDOS_FS is not set
431# CONFIG_VFAT_FS is not set
432# CONFIG_NTFS_FS is not set
433
434#
435# Pseudo filesystems
436#
437CONFIG_PROC_FS=y
438CONFIG_PROC_KCORE=y
439CONFIG_SYSFS=y
440CONFIG_DEVFS_FS=y
441CONFIG_DEVFS_MOUNT=y
442# CONFIG_DEVFS_DEBUG is not set
443# CONFIG_DEVPTS_FS_XATTR is not set
444CONFIG_TMPFS=y
445# CONFIG_TMPFS_XATTR is not set
446# CONFIG_HUGETLB_PAGE is not set
447CONFIG_RAMFS=y
448
449#
450# Miscellaneous filesystems
451#
452# CONFIG_ADFS_FS is not set
453# CONFIG_AFFS_FS is not set
454# CONFIG_HFS_FS is not set
455# CONFIG_HFSPLUS_FS is not set
456# CONFIG_BEFS_FS is not set
457# CONFIG_BFS_FS is not set
458# CONFIG_EFS_FS is not set
459# CONFIG_CRAMFS is not set
460# CONFIG_VXFS_FS is not set
461# CONFIG_HPFS_FS is not set
462# CONFIG_QNX4FS_FS is not set
463# CONFIG_SYSV_FS is not set
464# CONFIG_UFS_FS is not set
465
466#
467# Network File Systems
468#
469CONFIG_NFS_FS=y
470CONFIG_NFS_V3=y
471# CONFIG_NFS_V4 is not set
472CONFIG_NFS_DIRECTIO=y
473# CONFIG_NFSD is not set
474CONFIG_ROOT_NFS=y
475CONFIG_LOCKD=y
476CONFIG_LOCKD_V4=y
477# CONFIG_EXPORTFS is not set
478CONFIG_SUNRPC=y
479# CONFIG_RPCSEC_GSS_KRB5 is not set
480# CONFIG_RPCSEC_GSS_SPKM3 is not set
481# CONFIG_SMB_FS is not set
482# CONFIG_CIFS is not set
483# CONFIG_NCP_FS is not set
484# CONFIG_CODA_FS is not set
485# CONFIG_AFS_FS is not set
486
487#
488# Partition Types
489#
490# CONFIG_PARTITION_ADVANCED is not set
491CONFIG_MSDOS_PARTITION=y
492
493#
494# Native Language Support
495#
496# CONFIG_NLS is not set
497
498#
499# Kernel hacking
500#
501CONFIG_DEBUG_KERNEL=y
502# CONFIG_DEBUG_STACKOVERFLOW is not set
503# CONFIG_DEBUG_SLAB is not set
504# CONFIG_MAGIC_SYSRQ is not set
505# CONFIG_DEBUG_SPINLOCK is not set
506# CONFIG_DEBUG_PAGEALLOC is not set
507# CONFIG_DEBUG_INFO is not set
508# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
509# CONFIG_KGDB is not set
510
511#
512# Security options
513#
514# CONFIG_KEYS is not set
515# CONFIG_SECURITY is not set
516
517#
518# Cryptographic options
519#
520# CONFIG_CRYPTO is not set
521
522#
523# Hardware crypto devices
524#
525
526#
527# Library routines
528#
529# CONFIG_CRC_CCITT is not set
530# CONFIG_CRC32 is not set
531# CONFIG_LIBCRC32C is not set
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
new file mode 100644
index 0000000000..d573017a5d
--- /dev/null
+++ b/arch/xtensa/kernel/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for the Linux/Xtensa kernel.
3#
4
5extra-y := head.o vmlinux.lds
6
7
8obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \
9 setup.o signal.o syscalls.o time.o traps.o vectors.o platform.o \
10 pci-dma.o
11
12## windowspill.o
13
14obj-$(CONFIG_KGDB) += xtensa-stub.o
15obj-$(CONFIG_PCI) += pci.o
16obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
17
18
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
new file mode 100644
index 0000000000..74b1e90ef0
--- /dev/null
+++ b/arch/xtensa/kernel/align.S
@@ -0,0 +1,459 @@
1/*
2 * arch/xtensa/kernel/align.S
3 *
4 * Handle unalignment exceptions in kernel space.
5 *
6 * This file is subject to the terms and conditions of the GNU General
7 * Public License. See the file "COPYING" in the main directory of
8 * this archive for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica, Inc.
11 *
12 * Rewritten by Chris Zankel <chris@zankel.net>
13 *
14 * Based on work from Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
15 * and Marc Gauthier <marc@tensilica.com, marc@alimni.uwaterloo.ca>
16 */
17
18#include <linux/linkage.h>
19#include <asm/ptrace.h>
20#include <asm/ptrace.h>
21#include <asm/current.h>
22#include <asm/offsets.h>
23#include <asm/pgtable.h>
24#include <asm/processor.h>
25#include <asm/page.h>
26#include <asm/thread_info.h>
27
28#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
29
30/* First-level exception handler for unaligned exceptions.
31 *
32 * Note: This handler works only for kernel exceptions. Unaligned user
33 * access should get a seg fault.
34 */
35
36/* Big and little endian 16-bit values are located in
37 * different halves of a register. HWORD_START helps to
38 * abstract the notion of extracting a 16-bit value from a
39 * register.
40 * We also have to define new shifting instructions because
41 * lsb and msb are on 'opposite' ends in a register for
42 * different endian machines.
43 *
44 * Assume a memory region in ascending address:
45 * 0 1 2 3|4 5 6 7
46 *
47 * When loading one word into a register, the content of that register is:
48 * LE 3 2 1 0, 7 6 5 4
49 * BE 0 1 2 3, 4 5 6 7
50 *
51 * Masking the bits of the higher/lower address means:
52 * LE X X 0 0, 0 0 X X
53 * BE 0 0 X X, X X 0 0
54 *
55 * Shifting to higher/lower addresses, means:
56 * LE shift left / shift right
57 * BE shift right / shift left
58 *
59 * Extracting 16 bits from a 32 bit reg. value to higher/lower address means:
60 * LE mask 0 0 X X / shift left
61 * BE shift left / mask 0 0 X X
62 */
63
64#define UNALIGNED_USER_EXCEPTION
65
66#if XCHAL_HAVE_BE
67
68#define HWORD_START 16
69#define INSN_OP0 28
70#define INSN_T 24
71#define INSN_OP1 16
72
73.macro __src_b r, w0, w1; src \r, \w0, \w1; .endm
74.macro __ssa8 r; ssa8b \r; .endm
75.macro __ssa8r r; ssa8l \r; .endm
76.macro __sh r, s; srl \r, \s; .endm
77.macro __sl r, s; sll \r, \s; .endm
78.macro __exth r, s; extui \r, \s, 0, 16; .endm
79.macro __extl r, s; slli \r, \s, 16; .endm
80
81#else
82
83#define HWORD_START 0
84#define INSN_OP0 0
85#define INSN_T 4
86#define INSN_OP1 12
87
88.macro __src_b r, w0, w1; src \r, \w1, \w0; .endm
89.macro __ssa8 r; ssa8l \r; .endm
90.macro __ssa8r r; ssa8b \r; .endm
91.macro __sh r, s; sll \r, \s; .endm
92.macro __sl r, s; srl \r, \s; .endm
93.macro __exth r, s; slli \r, \s, 16; .endm
94.macro __extl r, s; extui \r, \s, 0, 16; .endm
95
96#endif
97
98/*
99 * xxxx xxxx = imm8 field
100 * yyyy = imm4 field
101 * ssss = s field
102 * tttt = t field
103 *
104 * 16 0
105 * -------------------
106 * L32I.N yyyy ssss tttt 1000
107 * S32I.N yyyy ssss tttt 1001
108 *
109 * 23 0
110 * -----------------------------
111 * res 0000 0010
112 * L16UI xxxx xxxx 0001 ssss tttt 0010
113 * L32I xxxx xxxx 0010 ssss tttt 0010
114 * XXX 0011 ssss tttt 0010
115 * XXX 0100 ssss tttt 0010
116 * S16I xxxx xxxx 0101 ssss tttt 0010
117 * S32I xxxx xxxx 0110 ssss tttt 0010
118 * XXX 0111 ssss tttt 0010
119 * XXX 1000 ssss tttt 0010
120 * L16SI xxxx xxxx 1001 ssss tttt 0010
121 * XXX 1010 0010
122 * **L32AI xxxx xxxx 1011 ssss tttt 0010 unsupported
123 * XXX 1100 0010
124 * XXX 1101 0010
125 * XXX 1110 0010
126 * **S32RI xxxx xxxx 1111 ssss tttt 0010 unsupported
127 * -----------------------------
128 * ^ ^ ^
129 * sub-opcode (NIBBLE_R) -+ | |
130 * t field (NIBBLE_T) -----------+ |
131 * major opcode (NIBBLE_OP0) --------------+
132 */
133
134#define OP0_L32I_N 0x8 /* load immediate narrow */
135#define OP0_S32I_N 0x9 /* store immediate narrow */
136#define OP1_SI_MASK 0x4 /* OP1 bit set for stores */
137#define OP1_SI_BIT 2 /* OP1 bit number for stores */
138
139#define OP1_L32I 0x2
140#define OP1_L16UI 0x1
141#define OP1_L16SI 0x9
142#define OP1_L32AI 0xb
143
144#define OP1_S32I 0x6
145#define OP1_S16I 0x5
146#define OP1_S32RI 0xf
147
148/*
149 * Entry condition:
150 *
151 * a0: trashed, original value saved on stack (PT_AREG0)
152 * a1: a1
153 * a2: new stack pointer, original in DEPC
154 * a3: dispatch table
155 * depc: a2, original value saved on stack (PT_DEPC)
156 * excsave_1: a3
157 *
158 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
159 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
160 */
161
162
163ENTRY(fast_unaligned)
164
165 /* Note: We don't expect the address to be aligned on a word
166 * boundary. After all, the processor generated that exception
167 * and it would be a hardware fault.
168 */
169
170 /* Save some working register */
171
172 s32i a4, a2, PT_AREG4
173 s32i a5, a2, PT_AREG5
174 s32i a6, a2, PT_AREG6
175 s32i a7, a2, PT_AREG7
176 s32i a8, a2, PT_AREG8
177
178 rsr a0, DEPC
179 xsr a3, EXCSAVE_1
180 s32i a0, a2, PT_AREG2
181 s32i a3, a2, PT_AREG3
182
183 /* Keep value of SAR in a0 */
184
185 rsr a0, SAR
186 rsr a8, EXCVADDR # load unaligned memory address
187
188 /* Now, identify one of the following load/store instructions.
189 *
190 * The only possible danger of a double exception on the
191 * following l32i instructions is kernel code in vmalloc
192 * memory. The processor was just executing at the EPC_1
193 * address, and indeed, already fetched the instruction. That
194 * guarantees a TLB mapping, which hasn't been replaced by
195 * this unaligned exception handler that uses only static TLB
196 * mappings. However, high-level interrupt handlers might
197 * modify TLB entries, so for the generic case, we register a
198 * TABLE_FIXUP handler here, too.
199 */
200
201 /* a3...a6 saved on stack, a2 = SP */
202
203 /* Extract the instruction that caused the unaligned access. */
204
205 rsr a7, EPC_1 # load exception address
206 movi a3, ~3
207 and a3, a3, a7 # mask lower bits
208
209 l32i a4, a3, 0 # load 2 words
210 l32i a5, a3, 4
211
212 __ssa8 a7
213 __src_b a4, a4, a5 # a4 has the instruction
214
215 /* Analyze the instruction (load or store?). */
216
217 extui a5, a4, INSN_OP0, 4 # get insn.op0 nibble
218
219#if XCHAL_HAVE_NARROW
220 _beqi a5, OP0_L32I_N, .Lload # L32I.N, jump
221 addi a6, a5, -OP0_S32I_N
222 _beqz a6, .Lstore # S32I.N, do a store
223#endif
224 /* 'store indicator bit' not set, jump */
225 _bbci.l a4, OP1_SI_BIT + INSN_OP1, .Lload
226
227 /* Store: Jump to table entry to get the value in the source register.*/
228
229.Lstore:movi a5, .Lstore_table # table
230 extui a6, a4, INSN_T, 4 # get source register
231 addx8 a5, a6, a5
232 jx a5 # jump into table
233
234 /* Invalid instruction, CRITICAL! */
235.Linvalid_instruction_load:
236 j .Linvalid_instruction
237
238 /* Load: Load memory address. */
239
240.Lload: movi a3, ~3
241 and a3, a3, a8 # align memory address
242
243 __ssa8 a8
244#ifdef UNALIGNED_USER_EXCEPTION
245 addi a3, a3, 8
246 l32e a5, a3, -8
247 l32e a6, a3, -4
248#else
249 l32i a5, a3, 0
250 l32i a6, a3, 4
251#endif
252 __src_b a3, a5, a6 # a3 has the data word
253
254#if XCHAL_HAVE_NARROW
255 addi a7, a7, 2 # increment PC (assume 16-bit insn)
256
257 extui a5, a4, INSN_OP0, 4
258 _beqi a5, OP0_L32I_N, 1f # l32i.n: jump
259
260 addi a7, a7, 1
261#else
262 addi a7, a7, 3
263#endif
264
265 extui a5, a4, INSN_OP1, 4
266 _beqi a5, OP1_L32I, 1f # l32i: jump
267
268 extui a3, a3, 0, 16 # extract lower 16 bits
269 _beqi a5, OP1_L16UI, 1f
270 addi a5, a5, -OP1_L16SI
271 _bnez a5, .Linvalid_instruction_load
272
273 /* sign extend value */
274
275 slli a3, a3, 16
276 srai a3, a3, 16
277
278 /* Set target register. */
279
2801:
281
282#if XCHAL_HAVE_LOOP
283 rsr a3, LEND # check if we reached LEND
284 bne a7, a3, 1f
285 rsr a3, LCOUNT # and LCOUNT != 0
286 beqz a3, 1f
287 addi a3, a3, -1 # decrement LCOUNT and set
288 rsr a7, LBEG # set PC to LBEGIN
289 wsr a3, LCOUNT
290#endif
291
2921: wsr a7, EPC_1 # skip load instruction
293 extui a4, a4, INSN_T, 4 # extract target register
294 movi a5, .Lload_table
295 addx8 a4, a4, a5
296 jx a4 # jump to entry for target register
297
298 .align 8
299.Lload_table:
300 s32i a3, a2, PT_AREG0; _j .Lexit; .align 8
301 mov a1, a3; _j .Lexit; .align 8 # fishy??
302 s32i a3, a2, PT_AREG2; _j .Lexit; .align 8
303 s32i a3, a2, PT_AREG3; _j .Lexit; .align 8
304 s32i a3, a2, PT_AREG4; _j .Lexit; .align 8
305 s32i a3, a2, PT_AREG5; _j .Lexit; .align 8
306 s32i a3, a2, PT_AREG6; _j .Lexit; .align 8
307 s32i a3, a2, PT_AREG7; _j .Lexit; .align 8
308 s32i a3, a2, PT_AREG8; _j .Lexit; .align 8
309 mov a9, a3 ; _j .Lexit; .align 8
310 mov a10, a3 ; _j .Lexit; .align 8
311 mov a11, a3 ; _j .Lexit; .align 8
312 mov a12, a3 ; _j .Lexit; .align 8
313 mov a13, a3 ; _j .Lexit; .align 8
314 mov a14, a3 ; _j .Lexit; .align 8
315 mov a15, a3 ; _j .Lexit; .align 8
316
317.Lstore_table:
318 l32i a3, a2, PT_AREG0; _j 1f; .align 8
319 mov a3, a1; _j 1f; .align 8 # fishy??
320 l32i a3, a2, PT_AREG2; _j 1f; .align 8
321 l32i a3, a2, PT_AREG3; _j 1f; .align 8
322 l32i a3, a2, PT_AREG4; _j 1f; .align 8
323 l32i a3, a2, PT_AREG5; _j 1f; .align 8
324 l32i a3, a2, PT_AREG6; _j 1f; .align 8
325 l32i a3, a2, PT_AREG7; _j 1f; .align 8
326 l32i a3, a2, PT_AREG8; _j 1f; .align 8
327 mov a3, a9 ; _j 1f; .align 8
328 mov a3, a10 ; _j 1f; .align 8
329 mov a3, a11 ; _j 1f; .align 8
330 mov a3, a12 ; _j 1f; .align 8
331 mov a3, a13 ; _j 1f; .align 8
332 mov a3, a14 ; _j 1f; .align 8
333 mov a3, a15 ; _j 1f; .align 8
334
3351: # a7: instruction pointer, a4: instruction, a3: value
336
337 movi a6, 0 # mask: ffffffff:00000000
338
339#if XCHAL_HAVE_NARROW
340 addi a7, a7, 2 # incr. PC,assume 16-bit instruction
341
342 extui a5, a4, INSN_OP0, 4 # extract OP0
343 addi a5, a5, -OP0_S32I_N
344 _beqz a5, 1f # s32i.n: jump
345
346 addi a7, a7, 1 # increment PC, 32-bit instruction
347#else
348 addi a7, a7, 3 # increment PC, 32-bit instruction
349#endif
350
351 extui a5, a4, INSN_OP1, 4 # extract OP1
352 _beqi a5, OP1_S32I, 1f # jump if 32 bit store
353 _bnei a5, OP1_S16I, .Linvalid_instruction_store
354
355 movi a5, -1
356 __extl a3, a3 # get 16-bit value
357 __exth a6, a5 # get 16-bit mask ffffffff:ffff0000
358
359 /* Get memory address */
360
3611:
362#if XCHAL_HAVE_LOOP
363 rsr a3, LEND # check if we reached LEND
364 bne a7, a3, 1f
365 rsr a3, LCOUNT # and LCOUNT != 0
366 beqz a3, 1f
367 addi a3, a3, -1 # decrement LCOUNT and set
368 rsr a7, LBEG # set PC to LBEGIN
369 wsr a3, LCOUNT
370#endif
371
3721: wsr a7, EPC_1 # skip store instruction
373 movi a4, ~3
374 and a4, a4, a8 # align memory address
375
376 /* Insert value into memory */
377
378 movi a5, -1 # mask: ffffffff:XXXX0000
379#ifdef UNALIGNED_USER_EXCEPTION
380 addi a4, a4, 8
381#endif
382
383 __ssa8r a8
384 __src_b a7, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE)
385 __src_b a6, a6, a5 # hi-mask 0..0F..F (BE) F..F0..0 (LE)
386#ifdef UNALIGNED_USER_EXCEPTION
387 l32e a5, a4, -8
388#else
389 l32i a5, a4, 0 # load lower address word
390#endif
391 and a5, a5, a7 # mask
392 __sh a7, a3 # shift value
393 or a5, a5, a7 # or with original value
394#ifdef UNALIGNED_USER_EXCEPTION
395 s32e a5, a4, -8
396 l32e a7, a4, -4
397#else
398 s32i a5, a4, 0 # store
399 l32i a7, a4, 4 # same for upper address word
400#endif
401 __sl a5, a3
402 and a6, a7, a6
403 or a6, a6, a5
404#ifdef UNALIGNED_USER_EXCEPTION
405 s32e a6, a4, -4
406#else
407 s32i a6, a4, 4
408#endif
409
410 /* Done. restore stack and return */
411
412.Lexit:
413 movi a4, 0
414 rsr a3, EXCSAVE_1
415 s32i a4, a3, EXC_TABLE_FIXUP
416
417 /* Restore working register */
418
419 l32i a7, a2, PT_AREG7
420 l32i a6, a2, PT_AREG6
421 l32i a5, a2, PT_AREG5
422 l32i a4, a2, PT_AREG4
423 l32i a3, a2, PT_AREG3
424
425 /* restore SAR and return */
426
427 wsr a0, SAR
428 l32i a0, a2, PT_AREG0
429 l32i a2, a2, PT_AREG2
430 rfe
431
432 /* We cannot handle this exception. */
433
434 .extern _kernel_exception
435.Linvalid_instruction_store:
436.Linvalid_instruction:
437
438 /* Restore a4...a8 and SAR, set SP, and jump to default exception. */
439
440 l32i a8, a2, PT_AREG8
441 l32i a7, a2, PT_AREG7
442 l32i a6, a2, PT_AREG6
443 l32i a5, a2, PT_AREG5
444 l32i a4, a2, PT_AREG4
445 wsr a0, SAR
446 mov a1, a2
447
448 rsr a0, PS
449 bbsi.l a2, PS_UM_SHIFT, 1f # jump if user mode
450
451 movi a0, _kernel_exception
452 jx a0
453
4541: movi a0, _user_exception
455 jx a0
456
457
458#endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */
459
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
new file mode 100644
index 0000000000..840cd9a1d3
--- /dev/null
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -0,0 +1,94 @@
1/*
2 * arch/xtensa/kernel/asm-offsets.c
3 *
4 * Generates definitions from c-type structures used by assembly sources.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2005 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 */
14
15#include <asm/processor.h>
16
17#include <linux/types.h>
18#include <linux/sched.h>
19#include <linux/stddef.h>
20#include <linux/thread_info.h>
21#include <linux/ptrace.h>
22#include <asm/ptrace.h>
23#include <asm/processor.h>
24#include <asm/uaccess.h>
25
26#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
27#define BLANK() asm volatile("\n->" : : )
28
29int main(void)
30{
31 /* struct pt_regs */
32 DEFINE(PT_PC, offsetof (struct pt_regs, pc));
33 DEFINE(PT_PS, offsetof (struct pt_regs, ps));
34 DEFINE(PT_DEPC, offsetof (struct pt_regs, depc));
35 DEFINE(PT_EXCCAUSE, offsetof (struct pt_regs, exccause));
36 DEFINE(PT_EXCVADDR, offsetof (struct pt_regs, excvaddr));
37 DEFINE(PT_DEBUGCAUSE, offsetof (struct pt_regs, debugcause));
38 DEFINE(PT_WMASK, offsetof (struct pt_regs, wmask));
39 DEFINE(PT_LBEG, offsetof (struct pt_regs, lbeg));
40 DEFINE(PT_LEND, offsetof (struct pt_regs, lend));
41 DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount));
42 DEFINE(PT_SAR, offsetof (struct pt_regs, sar));
43 DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall));
44 DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0]));
45 DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
46 DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1]));
47 DEFINE(PT_AREG2, offsetof (struct pt_regs, areg[2]));
48 DEFINE(PT_AREG3, offsetof (struct pt_regs, areg[3]));
49 DEFINE(PT_AREG4, offsetof (struct pt_regs, areg[4]));
50 DEFINE(PT_AREG5, offsetof (struct pt_regs, areg[5]));
51 DEFINE(PT_AREG6, offsetof (struct pt_regs, areg[6]));
52 DEFINE(PT_AREG7, offsetof (struct pt_regs, areg[7]));
53 DEFINE(PT_AREG8, offsetof (struct pt_regs, areg[8]));
54 DEFINE(PT_AREG9, offsetof (struct pt_regs, areg[9]));
55 DEFINE(PT_AREG10, offsetof (struct pt_regs, areg[10]));
56 DEFINE(PT_AREG11, offsetof (struct pt_regs, areg[11]));
57 DEFINE(PT_AREG12, offsetof (struct pt_regs, areg[12]));
58 DEFINE(PT_AREG13, offsetof (struct pt_regs, areg[13]));
59 DEFINE(PT_AREG14, offsetof (struct pt_regs, areg[14]));
60 DEFINE(PT_AREG15, offsetof (struct pt_regs, areg[15]));
61 DEFINE(PT_WINDOWBASE, offsetof (struct pt_regs, windowbase));
62 DEFINE(PT_WINDOWSTART, offsetof(struct pt_regs, windowstart));
63 DEFINE(PT_SIZE, sizeof(struct pt_regs));
64 DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS]));
65 DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS]));
66 BLANK();
67
68 /* struct task_struct */
69 DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace));
70 DEFINE(TASK_MM, offsetof (struct task_struct, mm));
71 DEFINE(TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
72 DEFINE(TASK_PID, offsetof (struct task_struct, pid));
73 DEFINE(TASK_THREAD, offsetof (struct task_struct, thread));
74 DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
75 DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct));
76 BLANK();
77
78 /* struct thread_info (offset from start_struct) */
79 DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
80 DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
81 DEFINE(THREAD_CP_SAVE, offsetof (struct task_struct, thread.cp_save));
82 DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds));
83 BLANK();
84
85 /* struct mm_struct */
86 DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users));
87 DEFINE(MM_PGD, offsetof (struct mm_struct, pgd));
88 DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
89 BLANK();
90 DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT);
91 return 0;
92}
93
94
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
new file mode 100644
index 0000000000..356192a4d3
--- /dev/null
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -0,0 +1,201 @@
1/*
2 * arch/xtensa/kernel/coprocessor.S
3 *
4 * Xtensa processor configuration-specific table of coprocessor and
5 * other custom register layout information.
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 *
11 * Copyright (C) 2003 - 2005 Tensilica Inc.
12 *
13 * Marc Gauthier <marc@tensilica.com> <marc@alumni.uwaterloo.ca>
14 */
15
16/*
17 * This module contains a table that describes the layout of the various
18 * custom registers and states associated with each coprocessor, as well
19 * as those not associated with any coprocessor ("extra state").
20 * This table is included with core dumps and is available via the ptrace
21 * interface, allowing the layout of such register/state information to
22 * be modified in the kernel without affecting the debugger. Each
23 * register or state is identified using a 32-bit "libdb target number"
24 * assigned when the Xtensa processor is generated.
25 */
26
27#include <linux/config.h>
28#include <linux/linkage.h>
29#include <asm/processor.h>
30
31#if XCHAL_HAVE_CP
32
33#define CP_LAST ((XCHAL_CP_MAX - 1) * COPROCESSOR_INFO_SIZE)
34
35ENTRY(release_coprocessors)
36
37 entry a1, 16
38 # a2: task
39 movi a3, 1 << XCHAL_CP_MAX # a3: coprocessor-bit
40 movi a4, coprocessor_info+CP_LAST # a4: owner-table
41 # a5: tmp
42 movi a6, 0 # a6: 0
43 rsil a7, LOCKLEVEL # a7: PS
44
451: /* Check if task is coprocessor owner of coprocessor[i]. */
46
47 l32i a5, a4, COPROCESSOR_INFO_OWNER
48 srli a3, a3, 1
49 beqz a3, 1f
50 addi a4, a4, -8
51 beq a2, a5, 1b
52
53 /* Found an entry: Clear entry CPENABLE bit to disable CP. */
54
55 rsr a5, CPENABLE
56 s32i a6, a4, COPROCESSOR_INFO_OWNER
57 xor a5, a3, a5
58 wsr a5, CPENABLE
59
60 bnez a3, 1b
61
621: wsr a7, PS
63 rsync
64 retw
65
66
67ENTRY(disable_coprocessor)
68 entry sp, 16
69 rsil a7, LOCKLEVEL
70 rsr a3, CPENABLE
71 movi a4, 1
72 ssl a2
73 sll a4, a4
74 and a4, a3, a4
75 xor a3, a3, a4
76 wsr a3, CPENABLE
77 wsr a7, PS
78 rsync
79 retw
80
81ENTRY(enable_coprocessor)
82 entry sp, 16
83 rsil a7, LOCKLEVEL
84 rsr a3, CPENABLE
85 movi a4, 1
86 ssl a2
87 sll a4, a4
88 or a3, a3, a4
89 wsr a3, CPENABLE
90 wsr a7, PS
91 rsync
92 retw
93
94#endif
95
96ENTRY(save_coprocessor_extra)
97 entry sp, 16
98 xchal_extra_store_funcbody
99 retw
100
101ENTRY(restore_coprocessor_extra)
102 entry sp, 16
103 xchal_extra_load_funcbody
104 retw
105
106ENTRY(save_coprocessor_registers)
107 entry sp, 16
108 xchal_cpi_store_funcbody
109 retw
110
111ENTRY(restore_coprocessor_registers)
112 entry sp, 16
113 xchal_cpi_load_funcbody
114 retw
115
116
117/*
118 * The Xtensa compile-time HAL (core.h) XCHAL_*_SA_CONTENTS_LIBDB macros
119 * describe the contents of coprocessor & extra save areas in terms of
120 * undefined CONTENTS_LIBDB_{SREG,UREG,REGF} macros. We define these
121 * latter macros here; they expand into a table of the format we want.
122 * The general format is:
123 *
124 * CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum,
125 * bitmask, rsv2, rsv3)
126 * CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum,
127 * bitmask, rsv2, rsv3)
128 * CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index,
129 * numentries, contentsize, regname_base,
130 * regfile_name, rsv2, rsv3)
131 *
132 * For this table, we only care about the <libdbnum>, <offset> and <size>
133 * fields.
134 */
135
136/* Map all XCHAL CONTENTS macros to the reg_entry asm macro defined below: */
137
138#define CONTENTS_LIBDB_SREG(libdbnum,offset,size,align,rsv1,name,sregnum, \
139 bitmask, rsv2, rsv3) \
140 reg_entry libdbnum, offset, size ;
141#define CONTENTS_LIBDB_UREG(libdbnum,offset,size,align,rsv1,name,uregnum, \
142 bitmask, rsv2, rsv3) \
143 reg_entry libdbnum, offset, size ;
144#define CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, \
145 numentries, contentsize, regname_base, \
146 regfile_name, rsv2, rsv3) \
147 reg_entry libdbnum, offset, size ;
148
149/* A single table entry: */
150 .macro reg_entry libdbnum, offset, size
151 .ifne (__last_offset-(__last_group_offset+\offset))
152 /* padding entry */
153 .word (0xFC000000+__last_offset-(__last_group_offset+\offset))
154 .endif
155 .word \libdbnum /* actual entry */
156 .set __last_offset, __last_group_offset+\offset+\size
157 .endm /* reg_entry */
158
159
160/* Table entry that marks the beginning of a group (coprocessor or "extra"): */
161 .macro reg_group cpnum, num_entries, align
162 .set __last_group_offset, (__last_offset + \align- 1) & -\align
163 .ifne \num_entries
164 .word 0xFD000000+(\cpnum<<16)+\num_entries
165 .endif
166 .endm /* reg_group */
167
168/*
169 * Register info tables.
170 */
171
172 .section .rodata, "a"
173 .globl _xtensa_reginfo_tables
174 .globl _xtensa_reginfo_table_size
175 .align 4
176_xtensa_reginfo_table_size:
177 .word _xtensa_reginfo_table_end - _xtensa_reginfo_tables
178
179_xtensa_reginfo_tables:
180 .set __last_offset, 0
181 reg_group 0xFF, XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM, XCHAL_EXTRA_SA_ALIGN
182 XCHAL_EXTRA_SA_CONTENTS_LIBDB
183 reg_group 0, XCHAL_CP0_SA_CONTENTS_LIBDB_NUM, XCHAL_CP0_SA_ALIGN
184 XCHAL_CP0_SA_CONTENTS_LIBDB
185 reg_group 1, XCHAL_CP1_SA_CONTENTS_LIBDB_NUM, XCHAL_CP1_SA_ALIGN
186 XCHAL_CP1_SA_CONTENTS_LIBDB
187 reg_group 2, XCHAL_CP2_SA_CONTENTS_LIBDB_NUM, XCHAL_CP2_SA_ALIGN
188 XCHAL_CP2_SA_CONTENTS_LIBDB
189 reg_group 3, XCHAL_CP3_SA_CONTENTS_LIBDB_NUM, XCHAL_CP3_SA_ALIGN
190 XCHAL_CP3_SA_CONTENTS_LIBDB
191 reg_group 4, XCHAL_CP4_SA_CONTENTS_LIBDB_NUM, XCHAL_CP4_SA_ALIGN
192 XCHAL_CP4_SA_CONTENTS_LIBDB
193 reg_group 5, XCHAL_CP5_SA_CONTENTS_LIBDB_NUM, XCHAL_CP5_SA_ALIGN
194 XCHAL_CP5_SA_CONTENTS_LIBDB
195 reg_group 6, XCHAL_CP6_SA_CONTENTS_LIBDB_NUM, XCHAL_CP6_SA_ALIGN
196 XCHAL_CP6_SA_CONTENTS_LIBDB
197 reg_group 7, XCHAL_CP7_SA_CONTENTS_LIBDB_NUM, XCHAL_CP7_SA_ALIGN
198 XCHAL_CP7_SA_CONTENTS_LIBDB
199 .word 0xFC000000 /* invalid register number,marks end of table*/
200_xtensa_reginfo_table_end:
201
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
new file mode 100644
index 0000000000..c64a01f71d
--- /dev/null
+++ b/arch/xtensa/kernel/entry.S
@@ -0,0 +1,1996 @@
1/*
2 * arch/xtensa/kernel/entry.S
3 *
4 * Low-level exception handling
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2004-2005 by Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 *
14 */
15
16#include <linux/linkage.h>
17#include <asm/offsets.h>
18#include <asm/processor.h>
19#include <asm/thread_info.h>
20#include <asm/uaccess.h>
21#include <asm/unistd.h>
22#include <asm/ptrace.h>
23#include <asm/current.h>
24#include <asm/pgtable.h>
25#include <asm/page.h>
26#include <asm/signal.h>
27#include <xtensa/coreasm.h>
28
29/* Unimplemented features. */
30
31#undef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
32#undef KERNEL_STACK_OVERFLOW_CHECK
33#undef PREEMPTIBLE_KERNEL
34#undef ALLOCA_EXCEPTION_IN_IRAM
35
36/* Not well tested.
37 *
38 * - fast_coprocessor
39 */
40
41/*
42 * Macro to find first bit set in WINDOWBASE from the left + 1
43 *
44 * 100....0 -> 1
45 * 010....0 -> 2
46 * 000....1 -> WSBITS
47 */
48
49 .macro ffs_ws bit mask
50
51#if XCHAL_HAVE_NSA
52 nsau \bit, \mask # 32-WSBITS ... 31 (32 iff 0)
53 addi \bit, \bit, WSBITS - 32 + 1 # uppest bit set -> return 1
54#else
55 movi \bit, WSBITS
56#if WSBITS > 16
57 _bltui \mask, 0x10000, 99f
58 addi \bit, \bit, -16
59 extui \mask, \mask, 16, 16
60#endif
61#if WSBITS > 8
6299: _bltui \mask, 0x100, 99f
63 addi \bit, \bit, -8
64 srli \mask, \mask, 8
65#endif
6699: _bltui \mask, 0x10, 99f
67 addi \bit, \bit, -4
68 srli \mask, \mask, 4
6999: _bltui \mask, 0x4, 99f
70 addi \bit, \bit, -2
71 srli \mask, \mask, 2
7299: _bltui \mask, 0x2, 99f
73 addi \bit, \bit, -1
7499:
75
76#endif
77 .endm
78
79/* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- */
80
81/*
82 * First-level exception handler for user exceptions.
83 * Save some special registers, extra states and all registers in the AR
84 * register file that were in use in the user task, and jump to the common
85 * exception code.
86 * We save SAR (used to calculate WMASK), and WB and WS (we don't have to
87 * save them for kernel exceptions).
88 *
89 * Entry condition for user_exception:
90 *
91 * a0: trashed, original value saved on stack (PT_AREG0)
92 * a1: a1
93 * a2: new stack pointer, original value in depc
94 * a3: dispatch table
95 * depc: a2, original value saved on stack (PT_DEPC)
96 * excsave1: a3
97 *
98 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
99 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
100 *
101 * Entry condition for _user_exception:
102 *
103 * a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
104 * excsave has been restored, and
105 * stack pointer (a1) has been set.
106 *
107 * Note: _user_exception might be at an odd adress. Don't use call0..call12
108 */
109
110ENTRY(user_exception)
111
112 /* Save a2, a3, and depc, restore excsave_1 and set SP. */
113
114 xsr a3, EXCSAVE_1
115 rsr a0, DEPC
116 s32i a1, a2, PT_AREG1
117 s32i a0, a2, PT_AREG2
118 s32i a3, a2, PT_AREG3
119 mov a1, a2
120
121 .globl _user_exception
122_user_exception:
123
124 /* Save SAR and turn off single stepping */
125
126 movi a2, 0
127 rsr a3, SAR
128 wsr a2, ICOUNTLEVEL
129 s32i a3, a1, PT_SAR
130
131 /* Rotate ws so that the current windowbase is at bit0. */
132 /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
133
134 rsr a2, WINDOWBASE
135 rsr a3, WINDOWSTART
136 ssr a2
137 s32i a2, a1, PT_WINDOWBASE
138 s32i a3, a1, PT_WINDOWSTART
139 slli a2, a3, 32-WSBITS
140 src a2, a3, a2
141 srli a2, a2, 32-WSBITS
142 s32i a2, a1, PT_WMASK # needed for restoring registers
143
144 /* Save only live registers. */
145
146 _bbsi.l a2, 1, 1f
147 s32i a4, a1, PT_AREG4
148 s32i a5, a1, PT_AREG5
149 s32i a6, a1, PT_AREG6
150 s32i a7, a1, PT_AREG7
151 _bbsi.l a2, 2, 1f
152 s32i a8, a1, PT_AREG8
153 s32i a9, a1, PT_AREG9
154 s32i a10, a1, PT_AREG10
155 s32i a11, a1, PT_AREG11
156 _bbsi.l a2, 3, 1f
157 s32i a12, a1, PT_AREG12
158 s32i a13, a1, PT_AREG13
159 s32i a14, a1, PT_AREG14
160 s32i a15, a1, PT_AREG15
161 _bnei a2, 1, 1f # only one valid frame?
162
163 /* Only one valid frame, skip saving regs. */
164
165 j 2f
166
167 /* Save the remaining registers.
168 * We have to save all registers up to the first '1' from
169 * the right, except the current frame (bit 0).
170 * Assume a2 is: 001001000110001
171 * All regiser frames starting from the top fiel to the marked '1'
172 * must be saved.
173 */
174
1751: addi a3, a2, -1 # eliminate '1' in bit 0: yyyyxxww0
176 neg a3, a3 # yyyyxxww0 -> YYYYXXWW1+1
177 and a3, a3, a2 # max. only one bit is set
178
179 /* Find number of frames to save */
180
181 ffs_ws a0, a3 # number of frames to the '1' from left
182
183 /* Store information into WMASK:
184 * bits 0..3: xxx1 masked lower 4 bits of the rotated windowstart,
185 * bits 4...: number of valid 4-register frames
186 */
187
188 slli a3, a0, 4 # number of frames to save in bits 8..4
189 extui a2, a2, 0, 4 # mask for the first 16 registers
190 or a2, a3, a2
191 s32i a2, a1, PT_WMASK # needed when we restore the reg-file
192
193 /* Save 4 registers at a time */
194
1951: rotw -1
196 s32i a0, a5, PT_AREG_END - 16
197 s32i a1, a5, PT_AREG_END - 12
198 s32i a2, a5, PT_AREG_END - 8
199 s32i a3, a5, PT_AREG_END - 4
200 addi a0, a4, -1
201 addi a1, a5, -16
202 _bnez a0, 1b
203
204 /* WINDOWBASE still in SAR! */
205
206 rsr a2, SAR # original WINDOWBASE
207 movi a3, 1
208 ssl a2
209 sll a3, a3
210 wsr a3, WINDOWSTART # set corresponding WINDOWSTART bit
211 wsr a2, WINDOWBASE # and WINDOWSTART
212 rsync
213
214 /* We are back to the original stack pointer (a1) */
215
2162:
217#if XCHAL_EXTRA_SA_SIZE
218
219 /* For user exceptions, save the extra state into the user's TCB.
220 * Note: We must assume that xchal_extra_store_funcbody destroys a2..a15
221 */
222
223 GET_CURRENT(a2,a1)
224 addi a2, a2, THREAD_CP_SAVE
225 xchal_extra_store_funcbody
226#endif
227
228 /* Now, jump to the common exception handler. */
229
230 j common_exception
231
232
233/*
234 * First-level exit handler for kernel exceptions
235 * Save special registers and the live window frame.
236 * Note: Even though we changes the stack pointer, we don't have to do a
237 * MOVSP here, as we do that when we return from the exception.
238 * (See comment in the kernel exception exit code)
239 *
240 * Entry condition for kernel_exception:
241 *
242 * a0: trashed, original value saved on stack (PT_AREG0)
243 * a1: a1
244 * a2: new stack pointer, original in DEPC
245 * a3: dispatch table
246 * depc: a2, original value saved on stack (PT_DEPC)
247 * excsave_1: a3
248 *
249 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
250 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
251 *
252 * Entry condition for _kernel_exception:
253 *
254 * a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
255 * excsave has been restored, and
256 * stack pointer (a1) has been set.
257 *
258 * Note: _kernel_exception might be at an odd adress. Don't use call0..call12
259 */
260
261ENTRY(kernel_exception)
262
263 /* Save a0, a2, a3, DEPC and set SP. */
264
265 xsr a3, EXCSAVE_1 # restore a3, excsave_1
266 rsr a0, DEPC # get a2
267 s32i a1, a2, PT_AREG1
268 s32i a0, a2, PT_AREG2
269 s32i a3, a2, PT_AREG3
270 mov a1, a2
271
272 .globl _kernel_exception
273_kernel_exception:
274
275 /* Save SAR and turn off single stepping */
276
277 movi a2, 0
278 rsr a3, SAR
279 wsr a2, ICOUNTLEVEL
280 s32i a3, a1, PT_SAR
281
282 /* Rotate ws so that the current windowbase is at bit0. */
283 /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
284
285 rsr a2, WINDOWBASE # don't need to save these, we only
286 rsr a3, WINDOWSTART # need shifted windowstart: windowmask
287 ssr a2
288 slli a2, a3, 32-WSBITS
289 src a2, a3, a2
290 srli a2, a2, 32-WSBITS
291 s32i a2, a1, PT_WMASK # needed for kernel_exception_exit
292
293 /* Save only the live window-frame */
294
295 _bbsi.l a2, 1, 1f
296 s32i a4, a1, PT_AREG4
297 s32i a5, a1, PT_AREG5
298 s32i a6, a1, PT_AREG6
299 s32i a7, a1, PT_AREG7
300 _bbsi.l a2, 2, 1f
301 s32i a8, a1, PT_AREG8
302 s32i a9, a1, PT_AREG9
303 s32i a10, a1, PT_AREG10
304 s32i a11, a1, PT_AREG11
305 _bbsi.l a2, 3, 1f
306 s32i a12, a1, PT_AREG12
307 s32i a13, a1, PT_AREG13
308 s32i a14, a1, PT_AREG14
309 s32i a15, a1, PT_AREG15
310
3111:
312
313#ifdef KERNEL_STACK_OVERFLOW_CHECK
314
315 /* Stack overflow check, for debugging */
316 extui a2, a1, TASK_SIZE_BITS,XX
317 movi a3, SIZE??
318 _bge a2, a3, out_of_stack_panic
319
320#endif
321
322/*
323 * This is the common exception handler.
324 * We get here from the user exception handler or simply by falling through
325 * from the kernel exception handler.
326 * Save the remaining special registers, switch to kernel mode, and jump
327 * to the second-level exception handler.
328 *
329 */
330
331common_exception:
332
333 /* Save EXCVADDR, DEBUGCAUSE, and PC, and clear LCOUNT */
334
335 rsr a2, DEBUGCAUSE
336 rsr a3, EPC_1
337 s32i a2, a1, PT_DEBUGCAUSE
338 s32i a3, a1, PT_PC
339
340 rsr a3, EXCVADDR
341 movi a2, 0
342 s32i a3, a1, PT_EXCVADDR
343 xsr a2, LCOUNT
344 s32i a2, a1, PT_LCOUNT
345
346 /* It is now save to restore the EXC_TABLE_FIXUP variable. */
347
348 rsr a0, EXCCAUSE
349 movi a3, 0
350 rsr a2, EXCSAVE_1
351 s32i a0, a1, PT_EXCCAUSE
352 s32i a3, a2, EXC_TABLE_FIXUP
353
354 /* All unrecoverable states are saved on stack, now, and a1 is valid,
355 * so we can allow exceptions and interrupts (*) again.
356 * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
357 *
358 * (*) We only allow interrupts if PS.INTLEVEL was not set to 1 before
359 * (interrupts disabled) and if this exception is not an interrupt.
360 */
361
362 rsr a3, PS
363 addi a0, a0, -4
364 movi a2, 1
365 extui a3, a3, 0, 1 # a3 = PS.INTLEVEL[0]
366 moveqz a3, a2, a0 # a3 = 1 iff interrupt exception
367 movi a2, PS_WOE_MASK
368 or a3, a3, a2
369 rsr a0, EXCCAUSE
370 xsr a3, PS
371
372 s32i a3, a1, PT_PS # save ps
373
374 /* Save LBEG, LEND */
375
376 rsr a2, LBEG
377 rsr a3, LEND
378 s32i a2, a1, PT_LBEG
379 s32i a3, a1, PT_LEND
380
381 /* Go to second-level dispatcher. Set up parameters to pass to the
382 * exception handler and call the exception handler.
383 */
384
385 movi a4, exc_table
386 mov a6, a1 # pass stack frame
387 mov a7, a0 # pass EXCCAUSE
388 addx4 a4, a0, a4
389 l32i a4, a4, EXC_TABLE_DEFAULT # load handler
390
391 /* Call the second-level handler */
392
393 callx4 a4
394
395 /* Jump here for exception exit */
396
397common_exception_return:
398
399 /* Jump if we are returning from kernel exceptions. */
400
4011: l32i a3, a1, PT_PS
402 _bbsi.l a3, PS_UM_SHIFT, 2f
403 j kernel_exception_exit
404
405 /* Specific to a user exception exit:
406 * We need to check some flags for signal handling and rescheduling,
407 * and have to restore WB and WS, extra states, and all registers
408 * in the register file that were in use in the user task.
409 */
410
4112: wsr a3, PS /* disable interrupts */
412
413 /* Check for signals (keep interrupts disabled while we read TI_FLAGS)
414 * Note: PS.INTLEVEL = 0, PS.EXCM = 1
415 */
416
417 GET_THREAD_INFO(a2,a1)
418 l32i a4, a2, TI_FLAGS
419
420 /* Enable interrupts again.
421 * Note: When we get here, we certainly have handled any interrupts.
422 * (Hint: There is only one user exception frame on stack)
423 */
424
425 movi a3, PS_WOE_MASK
426
427 _bbsi.l a4, TIF_NEED_RESCHED, 3f
428 _bbci.l a4, TIF_SIGPENDING, 4f
429
430#ifndef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
431 l32i a4, a1, PT_DEPC
432 bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
433#endif
434
435 /* Reenable interrupts and call do_signal() */
436
437 wsr a3, PS
438 movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*)
439 mov a6, a1
440 movi a7, 0
441 callx4 a4
442 j 1b
443
4443: /* Reenable interrupts and reschedule */
445
446 wsr a3, PS
447 movi a4, schedule # void schedule (void)
448 callx4 a4
449 j 1b
450
451 /* Restore the state of the task and return from the exception. */
452
453
454 /* If we are returning from a user exception, and the process
455 * to run next has PT_SINGLESTEP set, we want to setup
456 * ICOUNT and ICOUNTLEVEL to step one instruction.
457 * PT_SINGLESTEP is set by sys_ptrace (ptrace.c)
458 */
459
4604: /* a2 holds GET_CURRENT(a2,a1) */
461
462 l32i a3, a2, TI_TASK
463 l32i a3, a3, TASK_PTRACE
464 bbci.l a3, PT_SINGLESTEP_BIT, 1f # jump if single-step flag is not set
465
466 movi a3, -2 # PT_SINGLESTEP flag is set,
467 movi a4, 1 # icountlevel of 1 means it won't
468 wsr a3, ICOUNT # start counting until after rfe
469 wsr a4, ICOUNTLEVEL # so setup icount & icountlevel.
470 isync
471
4721:
473
474#if XCHAL_EXTRA_SA_SIZE
475
476 /* For user exceptions, restore the extra state from the user's TCB. */
477
478 /* Note: a2 still contains GET_CURRENT(a2,a1) */
479 addi a2, a2, THREAD_CP_SAVE
480 xchal_extra_load_funcbody
481
482 /* We must assume that xchal_extra_store_funcbody destroys
483 * registers a2..a15. FIXME, this list can eventually be
484 * reduced once real register requirements of the macro are
485 * finalized. */
486
487#endif /* XCHAL_EXTRA_SA_SIZE */
488
489
490 /* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */
491
492 l32i a2, a1, PT_WINDOWBASE
493 l32i a3, a1, PT_WINDOWSTART
494 wsr a1, DEPC # use DEPC as temp storage
495 wsr a3, WINDOWSTART # restore WINDOWSTART
496 ssr a2 # preserve user's WB in the SAR
497 wsr a2, WINDOWBASE # switch to user's saved WB
498 rsync
499 rsr a1, DEPC # restore stack pointer
500 l32i a2, a1, PT_WMASK # register frames saved (in bits 4...9)
501 rotw -1 # we restore a4..a7
502 _bltui a6, 16, 1f # only have to restore current window?
503
504 /* The working registers are a0 and a3. We are restoring to
505 * a4..a7. Be careful not to destroy what we have just restored.
506 * Note: wmask has the format YYYYM:
507 * Y: number of registers saved in groups of 4
508 * M: 4 bit mask of first 16 registers
509 */
510
511 mov a2, a6
512 mov a3, a5
513
5142: rotw -1 # a0..a3 become a4..a7
515 addi a3, a7, -4*4 # next iteration
516 addi a2, a6, -16 # decrementing Y in WMASK
517 l32i a4, a3, PT_AREG_END + 0
518 l32i a5, a3, PT_AREG_END + 4
519 l32i a6, a3, PT_AREG_END + 8
520 l32i a7, a3, PT_AREG_END + 12
521 _bgeui a2, 16, 2b
522
523 /* Clear unrestored registers (don't leak anything to user-land */
524
5251: rsr a0, WINDOWBASE
526 rsr a3, SAR
527 sub a3, a0, a3
528 beqz a3, 2f
529 extui a3, a3, 0, WBBITS
530
5311: rotw -1
532 addi a3, a7, -1
533 movi a4, 0
534 movi a5, 0
535 movi a6, 0
536 movi a7, 0
537 bgei a3, 1, 1b
538
539 /* We are back were we were when we started.
540 * Note: a2 still contains WMASK (if we've returned to the original
541 * frame where we had loaded a2), or at least the lower 4 bits
542 * (if we have restored WSBITS-1 frames).
543 */
544
5452: j common_exception_exit
546
547 /* This is the kernel exception exit.
548 * We avoided to do a MOVSP when we entered the exception, but we
549 * have to do it here.
550 */
551
552kernel_exception_exit:
553
554 /* Disable interrupts (a3 holds PT_PS) */
555
556 wsr a3, PS
557
558#ifdef PREEMPTIBLE_KERNEL
559
560#ifdef CONFIG_PREEMPT
561
562 /*
563 * Note: We've just returned from a call4, so we have
564 * at least 4 addt'l regs.
565 */
566
567 /* Check current_thread_info->preempt_count */
568
569 GET_THREAD_INFO(a2)
570 l32i a3, a2, TI_PREEMPT
571 bnez a3, 1f
572
573 l32i a2, a2, TI_FLAGS
574
5751:
576
577#endif
578
579#endif
580
581 /* Check if we have to do a movsp.
582 *
583 * We only have to do a movsp if the previous window-frame has
584 * been spilled to the *temporary* exception stack instead of the
585 * task's stack. This is the case if the corresponding bit in
586 * WINDOWSTART for the previous window-frame was set before
587 * (not spilled) but is zero now (spilled).
588 * If this bit is zero, all other bits except the one for the
589 * current window frame are also zero. So, we can use a simple test:
590 * 'and' WINDOWSTART and WINDOWSTART-1:
591 *
592 * (XXXXXX1[0]* - 1) AND XXXXXX1[0]* = XXXXXX0[0]*
593 *
594 * The result is zero only if one bit was set.
595 *
596 * (Note: We might have gone through several task switches before
597 * we come back to the current task, so WINDOWBASE might be
598 * different from the time the exception occurred.)
599 */
600
601 /* Test WINDOWSTART before and after the exception.
602 * We actually have WMASK, so we only have to test if it is 1 or not.
603 */
604
605 l32i a2, a1, PT_WMASK
606 _beqi a2, 1, common_exception_exit # Spilled before exception,jump
607
608 /* Test WINDOWSTART now. If spilled, do the movsp */
609
610 rsr a3, WINDOWSTART
611 addi a0, a3, -1
612 and a3, a3, a0
613 _bnez a3, common_exception_exit
614
615 /* Do a movsp (we returned from a call4, so we have at least a0..a7) */
616
617 addi a0, a1, -16
618 l32i a3, a0, 0
619 l32i a4, a0, 4
620 s32i a3, a1, PT_SIZE+0
621 s32i a4, a1, PT_SIZE+4
622 l32i a3, a0, 8
623 l32i a4, a0, 12
624 s32i a3, a1, PT_SIZE+8
625 s32i a4, a1, PT_SIZE+12
626
627 /* Common exception exit.
628 * We restore the special register and the current window frame, and
629 * return from the exception.
630 *
631 * Note: We expect a2 to hold PT_WMASK
632 */
633
634common_exception_exit:
635
636 _bbsi.l a2, 1, 1f
637 l32i a4, a1, PT_AREG4
638 l32i a5, a1, PT_AREG5
639 l32i a6, a1, PT_AREG6
640 l32i a7, a1, PT_AREG7
641 _bbsi.l a2, 2, 1f
642 l32i a8, a1, PT_AREG8
643 l32i a9, a1, PT_AREG9
644 l32i a10, a1, PT_AREG10
645 l32i a11, a1, PT_AREG11
646 _bbsi.l a2, 3, 1f
647 l32i a12, a1, PT_AREG12
648 l32i a13, a1, PT_AREG13
649 l32i a14, a1, PT_AREG14
650 l32i a15, a1, PT_AREG15
651
652 /* Restore PC, SAR */
653
6541: l32i a2, a1, PT_PC
655 l32i a3, a1, PT_SAR
656 wsr a2, EPC_1
657 wsr a3, SAR
658
659 /* Restore LBEG, LEND, LCOUNT */
660
661 l32i a2, a1, PT_LBEG
662 l32i a3, a1, PT_LEND
663 wsr a2, LBEG
664 l32i a2, a1, PT_LCOUNT
665 wsr a3, LEND
666 wsr a2, LCOUNT
667
668 /* Check if it was double exception. */
669
670 l32i a0, a1, PT_DEPC
671 l32i a3, a1, PT_AREG3
672 l32i a2, a1, PT_AREG2
673 _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
674
675 /* Restore a0...a3 and return */
676
677 l32i a0, a1, PT_AREG0
678 l32i a1, a1, PT_AREG1
679 rfe
680
6811: wsr a0, DEPC
682 l32i a0, a1, PT_AREG0
683 l32i a1, a1, PT_AREG1
684 rfde
685
686/*
687 * Debug exception handler.
688 *
689 * Currently, we don't support KGDB, so only user application can be debugged.
690 *
691 * When we get here, a0 is trashed and saved to excsave[debuglevel]
692 */
693
694ENTRY(debug_exception)
695
696 rsr a0, EPS + XCHAL_DEBUGLEVEL
697 bbsi.l a0, PS_EXCM_SHIFT, 1f # exception mode
698
699 /* Set EPC_1 and EXCCAUSE */
700
701 wsr a2, DEPC # save a2 temporarily
702 rsr a2, EPC + XCHAL_DEBUGLEVEL
703 wsr a2, EPC_1
704
705 movi a2, EXCCAUSE_MAPPED_DEBUG
706 wsr a2, EXCCAUSE
707
708 /* Restore PS to the value before the debug exc but with PS.EXCM set.*/
709
710 movi a2, 1 << PS_EXCM_SHIFT
711 or a2, a0, a2
712 movi a0, debug_exception # restore a3, debug jump vector
713 wsr a2, PS
714 xsr a0, EXCSAVE + XCHAL_DEBUGLEVEL
715
716 /* Switch to kernel/user stack, restore jump vector, and save a0 */
717
718 bbsi.l a2, PS_UM_SHIFT, 2f # jump if user mode
719
720 addi a2, a1, -16-PT_SIZE # assume kernel stack
721 s32i a0, a2, PT_AREG0
722 movi a0, 0
723 s32i a1, a2, PT_AREG1
724 s32i a0, a2, PT_DEPC # mark it as a regular exception
725 xsr a0, DEPC
726 s32i a3, a2, PT_AREG3
727 s32i a0, a2, PT_AREG2
728 mov a1, a2
729 j _kernel_exception
730
7312: rsr a2, EXCSAVE_1
732 l32i a2, a2, EXC_TABLE_KSTK # load kernel stack pointer
733 s32i a0, a2, PT_AREG0
734 movi a0, 0
735 s32i a1, a2, PT_AREG1
736 s32i a0, a2, PT_DEPC
737 xsr a0, DEPC
738 s32i a3, a2, PT_AREG3
739 s32i a0, a2, PT_AREG2
740 mov a1, a2
741 j _user_exception
742
743 /* Debug exception while in exception mode. */
7441: j 1b // FIXME!!
745
746
747/*
748 * We get here in case of an unrecoverable exception.
749 * The only thing we can do is to be nice and print a panic message.
750 * We only produce a single stack frame for panic, so ???
751 *
752 *
753 * Entry conditions:
754 *
755 * - a0 contains the caller address; original value saved in excsave1.
756 * - the original a0 contains a valid return address (backtrace) or 0.
757 * - a2 contains a valid stackpointer
758 *
759 * Notes:
760 *
761 * - If the stack pointer could be invalid, the caller has to setup a
762 * dummy stack pointer (e.g. the stack of the init_task)
763 *
764 * - If the return address could be invalid, the caller has to set it
765 * to 0, so the backtrace would stop.
766 *
767 */
768 .align 4
769unrecoverable_text:
770 .ascii "Unrecoverable error in exception handler\0"
771
772ENTRY(unrecoverable_exception)
773
774 movi a0, 1
775 movi a1, 0
776
777 wsr a0, WINDOWSTART
778 wsr a1, WINDOWBASE
779 rsync
780
781 movi a1, PS_WOE_MASK | 1
782 wsr a1, PS
783 rsync
784
785 movi a1, init_task
786 movi a0, 0
787 addi a1, a1, PT_REGS_OFFSET
788
789 movi a4, panic
790 movi a6, unrecoverable_text
791
792 callx4 a4
793
7941: j 1b
795
796
797/* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
798
799/*
800 * Fast-handler for alloca exceptions
801 *
802 * The ALLOCA handler is entered when user code executes the MOVSP
803 * instruction and the caller's frame is not in the register file.
804 * In this case, the caller frame's a0..a3 are on the stack just
805 * below sp (a1), and this handler moves them.
806 *
807 * For "MOVSP <ar>,<as>" without destination register a1, this routine
808 * simply moves the value from <as> to <ar> without moving the save area.
809 *
810 * Entry condition:
811 *
812 * a0: trashed, original value saved on stack (PT_AREG0)
813 * a1: a1
814 * a2: new stack pointer, original in DEPC
815 * a3: dispatch table
816 * depc: a2, original value saved on stack (PT_DEPC)
817 * excsave_1: a3
818 *
819 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
820 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
821 */
822
823#if XCHAL_HAVE_BE
824#define _EXTUI_MOVSP_SRC(ar) extui ar, ar, 4, 4
825#define _EXTUI_MOVSP_DST(ar) extui ar, ar, 0, 4
826#else
827#define _EXTUI_MOVSP_SRC(ar) extui ar, ar, 0, 4
828#define _EXTUI_MOVSP_DST(ar) extui ar, ar, 4, 4
829#endif
830
831ENTRY(fast_alloca)
832
833 /* We shouldn't be in a double exception. */
834
835 l32i a0, a2, PT_DEPC
836 _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double
837
838 rsr a0, DEPC # get a2
839 s32i a4, a2, PT_AREG4 # save a4 and
840 s32i a0, a2, PT_AREG2 # a2 to stack
841
842 /* Exit critical section. */
843
844 movi a0, 0
845 s32i a0, a3, EXC_TABLE_FIXUP
846
847 /* Restore a3, excsave_1 */
848
849 xsr a3, EXCSAVE_1 # make sure excsave_1 is valid for dbl.
850 rsr a4, EPC_1 # get exception address
851 s32i a3, a2, PT_AREG3 # save a3 to stack
852
853#ifdef ALLOCA_EXCEPTION_IN_IRAM
854#error iram not supported
855#else
856 /* Note: l8ui not allowed in IRAM/IROM!! */
857 l8ui a0, a4, 1 # read as(src) from MOVSP instruction
858#endif
859 movi a3, .Lmovsp_src
860 _EXTUI_MOVSP_SRC(a0) # extract source register number
861 addx8 a3, a0, a3
862 jx a3
863
864.Lunhandled_double:
865 wsr a0, EXCSAVE_1
866 movi a0, unrecoverable_exception
867 callx0 a0
868
869 .align 8
870.Lmovsp_src:
871 l32i a3, a2, PT_AREG0; _j 1f; .align 8
872 mov a3, a1; _j 1f; .align 8
873 l32i a3, a2, PT_AREG2; _j 1f; .align 8
874 l32i a3, a2, PT_AREG3; _j 1f; .align 8
875 l32i a3, a2, PT_AREG4; _j 1f; .align 8
876 mov a3, a5; _j 1f; .align 8
877 mov a3, a6; _j 1f; .align 8
878 mov a3, a7; _j 1f; .align 8
879 mov a3, a8; _j 1f; .align 8
880 mov a3, a9; _j 1f; .align 8
881 mov a3, a10; _j 1f; .align 8
882 mov a3, a11; _j 1f; .align 8
883 mov a3, a12; _j 1f; .align 8
884 mov a3, a13; _j 1f; .align 8
885 mov a3, a14; _j 1f; .align 8
886 mov a3, a15; _j 1f; .align 8
887
8881:
889
890#ifdef ALLOCA_EXCEPTION_IN_IRAM
891#error iram not supported
892#else
893 l8ui a0, a4, 0 # read ar(dst) from MOVSP instruction
894#endif
895 addi a4, a4, 3 # step over movsp
896 _EXTUI_MOVSP_DST(a0) # extract destination register
897 wsr a4, EPC_1 # save new epc_1
898
899 _bnei a0, 1, 1f # no 'movsp a1, ax': jump
900
901 /* Move the save area. This implies the use of the L32E
902 * and S32E instructions, because this move must be done with
903 * the user's PS.RING privilege levels, not with ring 0
904 * (kernel's) privileges currently active with PS.EXCM
905 * set. Note that we have stil registered a fixup routine with the
906 * double exception vector in case a double exception occurs.
907 */
908
909 /* a0,a4:avail a1:old user stack a2:exc. stack a3:new user stack. */
910
911 l32e a0, a1, -16
912 l32e a4, a1, -12
913 s32e a0, a3, -16
914 s32e a4, a3, -12
915 l32e a0, a1, -8
916 l32e a4, a1, -4
917 s32e a0, a3, -8
918 s32e a4, a3, -4
919
920 /* Restore stack-pointer and all the other saved registers. */
921
922 mov a1, a3
923
924 l32i a4, a2, PT_AREG4
925 l32i a3, a2, PT_AREG3
926 l32i a0, a2, PT_AREG0
927 l32i a2, a2, PT_AREG2
928 rfe
929
930 /* MOVSP <at>,<as> was invoked with <at> != a1.
931 * Because the stack pointer is not being modified,
932 * we should be able to just modify the pointer
933 * without moving any save area.
934 * The processor only traps these occurrences if the
935 * caller window isn't live, so unfortunately we can't
936 * use this as an alternate trap mechanism.
937 * So we just do the move. This requires that we
938 * resolve the destination register, not just the source,
939 * so there's some extra work.
940 * (PERHAPS NOT REALLY NEEDED, BUT CLEANER...)
941 */
942
943 /* a0 dst-reg, a1 user-stack, a2 stack, a3 value of src reg. */
944
9451: movi a4, .Lmovsp_dst
946 addx8 a4, a0, a4
947 jx a4
948
949 .align 8
950.Lmovsp_dst:
951 s32i a3, a2, PT_AREG0; _j 1f; .align 8
952 mov a1, a3; _j 1f; .align 8
953 s32i a3, a2, PT_AREG2; _j 1f; .align 8
954 s32i a3, a2, PT_AREG3; _j 1f; .align 8
955 s32i a3, a2, PT_AREG4; _j 1f; .align 8
956 mov a5, a3; _j 1f; .align 8
957 mov a6, a3; _j 1f; .align 8
958 mov a7, a3; _j 1f; .align 8
959 mov a8, a3; _j 1f; .align 8
960 mov a9, a3; _j 1f; .align 8
961 mov a10, a3; _j 1f; .align 8
962 mov a11, a3; _j 1f; .align 8
963 mov a12, a3; _j 1f; .align 8
964 mov a13, a3; _j 1f; .align 8
965 mov a14, a3; _j 1f; .align 8
966 mov a15, a3; _j 1f; .align 8
967
9681: l32i a4, a2, PT_AREG4
969 l32i a3, a2, PT_AREG3
970 l32i a0, a2, PT_AREG0
971 l32i a2, a2, PT_AREG2
972 rfe
973
974
975/*
976 * fast system calls.
977 *
978 * WARNING: The kernel doesn't save the entire user context before
979 * handling a fast system call. These functions are small and short,
980 * usually offering some functionality not available to user tasks.
981 *
982 * BE CAREFUL TO PRESERVE THE USER'S CONTEXT.
983 *
984 * Entry condition:
985 *
986 * a0: trashed, original value saved on stack (PT_AREG0)
987 * a1: a1
988 * a2: new stack pointer, original in DEPC
989 * a3: dispatch table
990 * depc: a2, original value saved on stack (PT_DEPC)
991 * excsave_1: a3
992 */
993
994ENTRY(fast_syscall_kernel)
995
996 /* Skip syscall. */
997
998 rsr a0, EPC_1
999 addi a0, a0, 3
1000 wsr a0, EPC_1
1001
1002 l32i a0, a2, PT_DEPC
1003 bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
1004
1005 rsr a0, DEPC # get syscall-nr
1006 _beqz a0, fast_syscall_spill_registers
1007
1008 addi a0, a0, -__NR_sysxtensa
1009 _beqz a0, fast_syscall_sysxtensa
1010
1011 j kernel_exception
1012
1013
1014ENTRY(fast_syscall_user)
1015
1016 /* Skip syscall. */
1017
1018 rsr a0, EPC_1
1019 addi a0, a0, 3
1020 wsr a0, EPC_1
1021
1022 l32i a0, a2, PT_DEPC
1023 bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
1024
1025 rsr a0, DEPC # get syscall-nr
1026 _beqz a0, fast_syscall_spill_registers
1027
1028 addi a0, a0, -__NR_sysxtensa
1029 _beqz a0, fast_syscall_sysxtensa
1030
1031 j user_exception
1032
1033ENTRY(fast_syscall_unrecoverable)
1034
1035 /* Restore all states. */
1036
1037 l32i a0, a2, PT_AREG0 # restore a0
1038 xsr a2, DEPC # restore a2, depc
1039 rsr a3, EXCSAVE_1
1040
1041 wsr a0, EXCSAVE_1
1042 movi a0, unrecoverable_exception
1043 callx0 a0
1044
1045
1046
1047/*
1048 * sysxtensa syscall handler
1049 *
1050 * int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused);
1051 * int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused);
1052 * int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
1053 * int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
1054 * a2 a6 a3 a4 a5
1055 *
1056 * Entry condition:
1057 *
1058 * a0: trashed, original value saved on stack (PT_AREG0)
1059 * a1: a1
1060 * a2: new stack pointer, original in DEPC
1061 * a3: dispatch table
1062 * depc: a2, original value saved on stack (PT_DEPC)
1063 * excsave_1: a3
1064 *
1065 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1066 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
1067 *
1068 * Note: we don't have to save a2; a2 holds the return value
1069 *
1070 * We use the two macros TRY and CATCH:
1071 *
1072 * TRY adds an entry to the __ex_table fixup table for the immediately
1073 * following instruction.
1074 *
1075 * CATCH catches any exception that occurred at one of the preceeding TRY
1076 * statements and continues from there
1077 *
1078 * Usage TRY l32i a0, a1, 0
1079 * <other code>
1080 * done: rfe
1081 * CATCH <set return code>
1082 * j done
1083 */
1084
1085#define TRY \
1086 .section __ex_table, "a"; \
1087 .word 66f, 67f; \
1088 .text; \
108966:
1090
1091#define CATCH \
109267:
1093
1094ENTRY(fast_syscall_sysxtensa)
1095
1096 _beqz a6, 1f
1097 _blti a6, SYSXTENSA_COUNT, 2f
1098
10991: j user_exception
1100
11012: xsr a3, EXCSAVE_1 # restore a3, excsave1
1102 s32i a7, a2, PT_AREG7
1103
1104 movi a7, 4 # sizeof(unsigned int)
1105 verify_area a3, a7, a0, a2, .Leac
1106
1107 _beqi a6, SYSXTENSA_ATOMIC_SET, .Lset
1108 _beqi a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg
1109 _beqi a6, SYSXTENSA_ATOMIC_ADD, .Ladd
1110
1111 /* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */
1112
1113.Lswp: /* Atomic compare and swap */
1114
1115TRY l32i a7, a3, 0 # read old value
1116 bne a7, a4, 1f # same as old value? jump
1117 s32i a5, a3, 0 # different, modify value
1118 movi a7, 1 # and return 1
1119 j .Lret
1120
11211: movi a7, 0 # same values: return 0
1122 j .Lret
1123
1124.Ladd: /* Atomic add */
1125.Lexg: /* Atomic (exchange) add */
1126
1127TRY l32i a7, a3, 0
1128 add a4, a4, a7
1129 s32i a4, a3, 0
1130 j .Lret
1131
1132.Lset: /* Atomic set */
1133
1134TRY l32i a7, a3, 0 # read old value as return value
1135 s32i a4, a3, 0 # write new value
1136
1137.Lret: mov a0, a2
1138 mov a2, a7
1139 l32i a7, a0, PT_AREG7
1140 l32i a3, a0, PT_AREG3
1141 l32i a0, a0, PT_AREG0
1142 rfe
1143
1144CATCH
1145.Leac: movi a7, -EFAULT
1146 j .Lret
1147
1148
1149
1150/* fast_syscall_spill_registers.
1151 *
1152 * Entry condition:
1153 *
1154 * a0: trashed, original value saved on stack (PT_AREG0)
1155 * a1: a1
1156 * a2: new stack pointer, original in DEPC
1157 * a3: dispatch table
1158 * depc: a2, original value saved on stack (PT_DEPC)
1159 * excsave_1: a3
1160 *
1161 * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
1162 * Note: We don't need to save a2 in depc (return value)
1163 */
1164
1165ENTRY(fast_syscall_spill_registers)
1166
1167 /* Register a FIXUP handler (pass current wb as a parameter) */
1168
1169 movi a0, fast_syscall_spill_registers_fixup
1170 s32i a0, a3, EXC_TABLE_FIXUP
1171 rsr a0, WINDOWBASE
1172 s32i a0, a3, EXC_TABLE_PARAM
1173
1174 /* Save a3 and SAR on stack. */
1175
1176 rsr a0, SAR
1177 xsr a3, EXCSAVE_1 # restore a3 and excsave_1
1178 s32i a0, a2, PT_AREG4 # store SAR to PT_AREG4
1179 s32i a3, a2, PT_AREG3
1180
1181 /* The spill routine might clobber a7, a11, and a15. */
1182
1183 s32i a7, a2, PT_AREG5
1184 s32i a11, a2, PT_AREG6
1185 s32i a15, a2, PT_AREG7
1186
1187 call0 _spill_registers # destroys a3, DEPC, and SAR
1188
1189 /* Advance PC, restore registers and SAR, and return from exception. */
1190
1191 l32i a3, a2, PT_AREG4
1192 l32i a0, a2, PT_AREG0
1193 wsr a3, SAR
1194 l32i a3, a2, PT_AREG3
1195
1196 /* Restore clobbered registers. */
1197
1198 l32i a7, a2, PT_AREG5
1199 l32i a11, a2, PT_AREG6
1200 l32i a15, a2, PT_AREG7
1201
1202 movi a2, 0
1203 rfe
1204
1205/* Fixup handler.
1206 *
1207 * We get here if the spill routine causes an exception, e.g. tlb miss.
1208 * We basically restore WINDOWBASE and WINDOWSTART to the condition when
1209 * we entered the spill routine and jump to the user exception handler.
1210 *
1211 * a0: value of depc, original value in depc
1212 * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
1213 * a3: exctable, original value in excsave1
1214 */
1215
1216fast_syscall_spill_registers_fixup:
1217
1218 rsr a2, WINDOWBASE # get current windowbase (a2 is saved)
1219 xsr a0, DEPC # restore depc and a0
1220 ssl a2 # set shift (32 - WB)
1221
1222 /* We need to make sure the current registers (a0-a3) are preserved.
1223 * To do this, we simply set the bit for the current window frame
1224 * in WS, so that the exception handlers save them to the task stack.
1225 */
1226
1227 rsr a3, EXCSAVE_1 # get spill-mask
1228 slli a2, a3, 1 # shift left by one
1229
1230 slli a3, a2, 32-WSBITS
1231 src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy......
1232 wsr a2, WINDOWSTART # set corrected windowstart
1233
1234 movi a3, exc_table
1235 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2
1236 l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task)
1237
1238 /* Return to the original (user task) WINDOWBASE.
1239 * We leave the following frame behind:
1240 * a0, a1, a2 same
1241 * a3: trashed (saved in excsave_1)
1242 * depc: depc (we have to return to that address)
1243 * excsave_1: a3
1244 */
1245
1246 wsr a3, WINDOWBASE
1247 rsync
1248
1249 /* We are now in the original frame when we entered _spill_registers:
1250 * a0: return address
1251 * a1: used, stack pointer
1252 * a2: kernel stack pointer
1253 * a3: available, saved in EXCSAVE_1
1254 * depc: exception address
1255 * excsave: a3
1256 * Note: This frame might be the same as above.
1257 */
1258
1259#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
1260 /* Restore registers we precautiously saved.
1261 * We have the value of the 'right' a3
1262 */
1263
1264 l32i a7, a2, PT_AREG5
1265 l32i a11, a2, PT_AREG6
1266 l32i a15, a2, PT_AREG7
1267#endif
1268
1269 /* Setup stack pointer. */
1270
1271 addi a2, a2, -PT_USER_SIZE
1272 s32i a0, a2, PT_AREG0
1273
1274 /* Make sure we return to this fixup handler. */
1275
1276 movi a3, fast_syscall_spill_registers_fixup_return
1277 s32i a3, a2, PT_DEPC # setup depc
1278
1279 /* Jump to the exception handler. */
1280
1281 movi a3, exc_table
1282 rsr a0, EXCCAUSE
1283 addx4 a0, a0, a3 # find entry in table
1284 l32i a0, a0, EXC_TABLE_FAST_USER # load handler
1285 jx a0
1286
1287fast_syscall_spill_registers_fixup_return:
1288
1289 /* When we return here, all registers have been restored (a2: DEPC) */
1290
1291 wsr a2, DEPC # exception address
1292
1293 /* Restore fixup handler. */
1294
1295 xsr a3, EXCSAVE_1
1296 movi a2, fast_syscall_spill_registers_fixup
1297 s32i a2, a3, EXC_TABLE_FIXUP
1298 rsr a2, WINDOWBASE
1299 s32i a2, a3, EXC_TABLE_PARAM
1300 l32i a2, a3, EXC_TABLE_KSTK
1301
1302#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
1303 /* Save registers again that might be clobbered. */
1304
1305 s32i a7, a2, PT_AREG5
1306 s32i a11, a2, PT_AREG6
1307 s32i a15, a2, PT_AREG7
1308#endif
1309
1310 /* Load WB at the time the exception occurred. */
1311
1312 rsr a3, SAR # WB is still in SAR
1313 neg a3, a3
1314 wsr a3, WINDOWBASE
1315 rsync
1316
1317 /* Restore a3 and return. */
1318
1319 movi a3, exc_table
1320 xsr a3, EXCSAVE_1
1321
1322 rfde
1323
1324
1325/*
1326 * spill all registers.
1327 *
1328 * This is not a real function. The following conditions must be met:
1329 *
1330 * - must be called with call0.
1331 * - uses DEPC, a3 and SAR.
1332 * - the last 'valid' register of each frame are clobbered.
1333 * - the caller must have registered a fixup handler
1334 * (or be inside a critical section)
1335 * - PS_EXCM must be set (PS_WOE cleared?)
1336 */
1337
1338ENTRY(_spill_registers)
1339
1340 /*
1341 * Rotate ws so that the current windowbase is at bit 0.
1342 * Assume ws = xxxwww1yy (www1 current window frame).
1343 * Rotate ws right so that a2 = yyxxxwww1.
1344 */
1345
1346 wsr a2, DEPC # preserve a2
1347 rsr a2, WINDOWBASE
1348 rsr a3, WINDOWSTART
1349 ssr a2 # holds WB
1350 slli a2, a3, WSBITS
1351 or a3, a3, a2 # a2 = xxxwww1yyxxxwww1yy
1352 srl a3, a3
1353
1354 /* We are done if there are no more than the current register frame. */
1355
1356 extui a3, a3, 1, WSBITS-2 # a3 = 0yyxxxwww
1357 movi a2, (1 << (WSBITS-1))
1358 _beqz a3, .Lnospill # only one active frame? jump
1359
1360 /* We want 1 at the top, so that we return to the current windowbase */
1361
1362 or a3, a3, a2 # 1yyxxxwww
1363
1364 /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
1365
1366 wsr a3, WINDOWSTART # save shifted windowstart
1367 neg a2, a3
1368 and a3, a2, a3 # first bit set from right: 000010000
1369
1370 ffs_ws a2, a3 # a2: shifts to skip empty frames
1371 movi a3, WSBITS
1372 sub a2, a3, a2 # WSBITS-a2:number of 0-bits from right
1373 ssr a2 # save in SAR for later.
1374
1375 rsr a3, WINDOWBASE
1376 add a3, a3, a2
1377 rsr a2, DEPC # restore a2
1378 wsr a3, WINDOWBASE
1379 rsync
1380
1381 rsr a3, WINDOWSTART
1382 srl a3, a3 # shift windowstart
1383
1384 /* WB is now just one frame below the oldest frame in the register
1385 window. WS is shifted so the oldest frame is in bit 0, thus, WB
1386 and WS differ by one 4-register frame. */
1387
1388 /* Save frames. Depending what call was used (call4, call8, call12),
1389 * we have to save 4,8. or 12 registers.
1390 */
1391
1392 _bbsi.l a3, 1, .Lc4
1393 _bbsi.l a3, 2, .Lc8
1394
1395 /* Special case: we have a call12-frame starting at a4. */
1396
1397 _bbci.l a3, 3, .Lc12 # bit 3 shouldn't be zero! (Jump to Lc12 first)
1398
1399 s32e a4, a1, -16 # a1 is valid with an empty spill area
1400 l32e a4, a5, -12
1401 s32e a8, a4, -48
1402 mov a8, a4
1403 l32e a4, a1, -16
1404 j .Lc12c
1405
1406.Lloop: _bbsi.l a3, 1, .Lc4
1407 _bbci.l a3, 2, .Lc12
1408
1409.Lc8: s32e a4, a13, -16
1410 l32e a4, a5, -12
1411 s32e a8, a4, -32
1412 s32e a5, a13, -12
1413 s32e a6, a13, -8
1414 s32e a7, a13, -4
1415 s32e a9, a4, -28
1416 s32e a10, a4, -24
1417 s32e a11, a4, -20
1418
1419 srli a11, a3, 2 # shift windowbase by 2
1420 rotw 2
1421 _bnei a3, 1, .Lloop
1422
1423.Lexit: /* Done. Do the final rotation, set WS, and return. */
1424
1425 rotw 1
1426 rsr a3, WINDOWBASE
1427 ssl a3
1428 movi a3, 1
1429 sll a3, a3
1430 wsr a3, WINDOWSTART
1431
1432.Lnospill:
1433 jx a0
1434
1435.Lc4: s32e a4, a9, -16
1436 s32e a5, a9, -12
1437 s32e a6, a9, -8
1438 s32e a7, a9, -4
1439
1440 srli a7, a3, 1
1441 rotw 1
1442 _bnei a3, 1, .Lloop
1443 j .Lexit
1444
1445.Lc12: _bbci.l a3, 3, .Linvalid_mask # bit 2 shouldn't be zero!
1446
1447 /* 12-register frame (call12) */
1448
1449 l32e a2, a5, -12
1450 s32e a8, a2, -48
1451 mov a8, a2
1452
1453.Lc12c: s32e a9, a8, -44
1454 s32e a10, a8, -40
1455 s32e a11, a8, -36
1456 s32e a12, a8, -32
1457 s32e a13, a8, -28
1458 s32e a14, a8, -24
1459 s32e a15, a8, -20
1460 srli a15, a3, 3
1461
1462 /* The stack pointer for a4..a7 is out of reach, so we rotate the
1463 * window, grab the stackpointer, and rotate back.
1464 * Alternatively, we could also use the following approach, but that
1465 * makes the fixup routine much more complicated:
1466 * rotw 1
1467 * s32e a0, a13, -16
1468 * ...
1469 * rotw 2
1470 */
1471
1472 rotw 1
1473 mov a5, a13
1474 rotw -1
1475
1476 s32e a4, a9, -16
1477 s32e a5, a9, -12
1478 s32e a6, a9, -8
1479 s32e a7, a9, -4
1480
1481 rotw 3
1482
1483 _beqi a3, 1, .Lexit
1484 j .Lloop
1485
1486.Linvalid_mask:
1487
1488 /* We get here because of an unrecoverable error in the window
1489 * registers. If we are in user space, we kill the application,
1490 * however, this condition is unrecoverable in kernel space.
1491 */
1492
1493 rsr a0, PS
1494 _bbci.l a0, PS_UM_SHIFT, 1f
1495
1496 /* User space: Setup a dummy frame and kill application.
1497 * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
1498 */
1499
1500 movi a0, 1
1501 movi a1, 0
1502
1503 wsr a0, WINDOWSTART
1504 wsr a1, WINDOWBASE
1505 rsync
1506
1507 movi a0, 0
1508
1509 movi a3, exc_table
1510 l32i a1, a3, EXC_TABLE_KSTK
1511 wsr a3, EXCSAVE_1
1512
1513 movi a4, PS_WOE_MASK | 1
1514 wsr a4, PS
1515 rsync
1516
1517 movi a6, SIGSEGV
1518 movi a4, do_exit
1519 callx4 a4
1520
15211: /* Kernel space: PANIC! */
1522
1523 wsr a0, EXCSAVE_1
1524 movi a0, unrecoverable_exception
1525 callx0 a0 # should not return
15261: j 1b
1527
1528/*
1529 * We should never get here. Bail out!
1530 */
1531
1532ENTRY(fast_second_level_miss_double_kernel)
1533
15341: movi a0, unrecoverable_exception
1535 callx0 a0 # should not return
15361: j 1b
1537
1538/* First-level entry handler for user, kernel, and double 2nd-level
1539 * TLB miss exceptions. Note that for now, user and kernel miss
1540 * exceptions share the same entry point and are handled identically.
1541 *
1542 * An old, less-efficient C version of this function used to exist.
1543 * We include it below, interleaved as comments, for reference.
1544 *
1545 * Entry condition:
1546 *
1547 * a0: trashed, original value saved on stack (PT_AREG0)
1548 * a1: a1
1549 * a2: new stack pointer, original in DEPC
1550 * a3: dispatch table
1551 * depc: a2, original value saved on stack (PT_DEPC)
1552 * excsave_1: a3
1553 *
1554 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1555 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
1556 */
1557
1558ENTRY(fast_second_level_miss)
1559
1560 /* Save a1. Note: we don't expect a double exception. */
1561
1562 s32i a1, a2, PT_AREG1
1563
1564 /* We need to map the page of PTEs for the user task. Find
1565 * the pointer to that page. Also, it's possible for tsk->mm
1566 * to be NULL while tsk->active_mm is nonzero if we faulted on
1567 * a vmalloc address. In that rare case, we must use
1568 * active_mm instead to avoid a fault in this handler. See
1569 *
1570 * http://mail.nl.linux.org/linux-mm/2002-08/msg00258.html
1571 * (or search Internet on "mm vs. active_mm")
1572 *
1573 * if (!mm)
1574 * mm = tsk->active_mm;
1575 * pgd = pgd_offset (mm, regs->excvaddr);
1576 * pmd = pmd_offset (pgd, regs->excvaddr);
1577 * pmdval = *pmd;
1578 */
1579
1580 GET_CURRENT(a1,a2)
1581 l32i a0, a1, TASK_MM # tsk->mm
1582 beqz a0, 9f
1583
15848: rsr a1, EXCVADDR # fault address
1585 _PGD_OFFSET(a0, a1, a1)
1586 l32i a0, a0, 0 # read pmdval
1587 //beqi a0, _PAGE_USER, 2f
1588 beqz a0, 2f
1589
1590 /* Read ptevaddr and convert to top of page-table page.
1591 *
1592 * vpnval = read_ptevaddr_register() & PAGE_MASK;
1593 * vpnval += DTLB_WAY_PGTABLE;
1594 * pteval = mk_pte (virt_to_page(pmd_val(pmdval)), PAGE_KERNEL);
1595 * write_dtlb_entry (pteval, vpnval);
1596 *
1597 * The messy computation for 'pteval' above really simplifies
1598 * into the following:
1599 *
1600 * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_KERNEL
1601 */
1602
1603 movi a1, -PAGE_OFFSET
1604 add a0, a0, a1 # pmdval - PAGE_OFFSET
1605 extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK
1606 xor a0, a0, a1
1607
1608
1609 movi a1, PAGE_DIRECTORY
1610 or a0, a0, a1 # ... | PAGE_DIRECTORY
1611
1612 rsr a1, PTEVADDR
1613 srli a1, a1, PAGE_SHIFT
1614 slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK
1615 addi a1, a1, DTLB_WAY_PGTABLE # ... + way_number
1616
1617 wdtlb a0, a1
1618 dsync
1619
1620 /* Exit critical section. */
1621
1622 movi a0, 0
1623 s32i a0, a3, EXC_TABLE_FIXUP
1624
1625 /* Restore the working registers, and return. */
1626
1627 l32i a0, a2, PT_AREG0
1628 l32i a1, a2, PT_AREG1
1629 l32i a2, a2, PT_DEPC
1630 xsr a3, EXCSAVE_1
1631
1632 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
1633
1634 /* Restore excsave1 and return. */
1635
1636 rsr a2, DEPC
1637 rfe
1638
1639 /* Return from double exception. */
1640
16411: xsr a2, DEPC
1642 esync
1643 rfde
1644
16459: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0
1646 j 8b
1647
16482: /* Invalid PGD, default exception handling */
1649
1650 rsr a1, DEPC
1651 xsr a3, EXCSAVE_1
1652 s32i a1, a2, PT_AREG2
1653 s32i a3, a2, PT_AREG3
1654 mov a1, a2
1655
1656 rsr a2, PS
1657 bbsi.l a2, PS_UM_SHIFT, 1f
1658 j _kernel_exception
16591: j _user_exception
1660
1661
1662/*
1663 * StoreProhibitedException
1664 *
1665 * Update the pte and invalidate the itlb mapping for this pte.
1666 *
1667 * Entry condition:
1668 *
1669 * a0: trashed, original value saved on stack (PT_AREG0)
1670 * a1: a1
1671 * a2: new stack pointer, original in DEPC
1672 * a3: dispatch table
1673 * depc: a2, original value saved on stack (PT_DEPC)
1674 * excsave_1: a3
1675 *
1676 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1677 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
1678 */
1679
1680ENTRY(fast_store_prohibited)
1681
1682 /* Save a1 and a4. */
1683
1684 s32i a1, a2, PT_AREG1
1685 s32i a4, a2, PT_AREG4
1686
1687 GET_CURRENT(a1,a2)
1688 l32i a0, a1, TASK_MM # tsk->mm
1689 beqz a0, 9f
1690
16918: rsr a1, EXCVADDR # fault address
1692 _PGD_OFFSET(a0, a1, a4)
1693 l32i a0, a0, 0
1694 //beqi a0, _PAGE_USER, 2f # FIXME use _PAGE_INVALID
1695 beqz a0, 2f
1696
1697 _PTE_OFFSET(a0, a1, a4)
1698 l32i a4, a0, 0 # read pteval
1699 movi a1, _PAGE_VALID | _PAGE_RW
1700 bnall a4, a1, 2f
1701
1702 movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_WRENABLE
1703 or a4, a4, a1
1704 rsr a1, EXCVADDR
1705 s32i a4, a0, 0
1706
1707 /* We need to flush the cache if we have page coloring. */
1708#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
1709 dhwb a0, 0
1710#endif
1711 pdtlb a0, a1
1712 beqz a0, 1f
1713 idtlb a0 // FIXME do we need this?
1714 wdtlb a4, a0
17151:
1716
1717 /* Exit critical section. */
1718
1719 movi a0, 0
1720 s32i a0, a3, EXC_TABLE_FIXUP
1721
1722 /* Restore the working registers, and return. */
1723
1724 l32i a4, a2, PT_AREG4
1725 l32i a1, a2, PT_AREG1
1726 l32i a0, a2, PT_AREG0
1727 l32i a2, a2, PT_DEPC
1728
1729 /* Restore excsave1 and a3. */
1730
1731 xsr a3, EXCSAVE_1
1732 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
1733
1734 rsr a2, DEPC
1735 rfe
1736
1737 /* Double exception. Restore FIXUP handler and return. */
1738
17391: xsr a2, DEPC
1740 esync
1741 rfde
1742
17439: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0
1744 j 8b
1745
17462: /* If there was a problem, handle fault in C */
1747
1748 rsr a4, DEPC # still holds a2
1749 xsr a3, EXCSAVE_1
1750 s32i a4, a2, PT_AREG2
1751 s32i a3, a2, PT_AREG3
1752 l32i a4, a2, PT_AREG4
1753 mov a1, a2
1754
1755 rsr a2, PS
1756 bbsi.l a2, PS_UM_SHIFT, 1f
1757 j _kernel_exception
17581: j _user_exception
1759
1760
1761#if XCHAL_EXTRA_SA_SIZE
1762
1763#warning fast_coprocessor untested
1764
1765/*
1766 * Entry condition:
1767 *
1768 * a0: trashed, original value saved on stack (PT_AREG0)
1769 * a1: a1
1770 * a2: new stack pointer, original in DEPC
1771 * a3: dispatch table
1772 * depc: a2, original value saved on stack (PT_DEPC)
1773 * excsave_1: a3
1774 *
1775 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1776 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
1777 */
1778
1779ENTRY(fast_coprocessor_double)
1780 wsr a0, EXCSAVE_1
1781 movi a0, unrecoverable_exception
1782 callx0 a0
1783
1784ENTRY(fast_coprocessor)
1785
1786 /* Fatal if we are in a double exception. */
1787
1788 l32i a0, a2, PT_DEPC
1789 _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_coprocessor_double
1790
1791 /* Save some registers a1, a3, a4, SAR */
1792
1793 xsr a3, EXCSAVE_1
1794 s32i a3, a2, PT_AREG3
1795 rsr a3, SAR
1796 s32i a4, a2, PT_AREG4
1797 s32i a1, a2, PT_AREG1
1798 s32i a5, a1, PT_AREG5
1799 s32i a3, a2, PT_SAR
1800 mov a1, a2
1801
1802 /* Currently, the HAL macros only guarantee saving a0 and a1.
1803 * These can and will be refined in the future, but for now,
1804 * just save the remaining registers of a2...a15.
1805 */
1806 s32i a6, a1, PT_AREG6
1807 s32i a7, a1, PT_AREG7
1808 s32i a8, a1, PT_AREG8
1809 s32i a9, a1, PT_AREG9
1810 s32i a10, a1, PT_AREG10
1811 s32i a11, a1, PT_AREG11
1812 s32i a12, a1, PT_AREG12
1813 s32i a13, a1, PT_AREG13
1814 s32i a14, a1, PT_AREG14
1815 s32i a15, a1, PT_AREG15
1816
1817 /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
1818
1819 rsr a0, EXCCAUSE
1820 addi a3, a0, -XCHAL_EXCCAUSE_COPROCESSOR0_DISABLED
1821
1822 /* Set corresponding CPENABLE bit */
1823
1824 movi a4, 1
1825 ssl a3 # SAR: 32 - coprocessor_number
1826 rsr a5, CPENABLE
1827 sll a4, a4
1828 or a4, a5, a4
1829 wsr a4, CPENABLE
1830 rsync
1831 movi a5, coprocessor_info # list of owner and offset into cp_save
1832 addx8 a0, a4, a5 # entry for CP
1833
1834 bne a4, a5, .Lload # bit wasn't set before, cp not in use
1835
1836 /* Now compare the current task with the owner of the coprocessor.
1837 * If they are the same, there is no reason to save or restore any
1838 * coprocessor state. Having already enabled the coprocessor,
1839 * branch ahead to return.
1840 */
1841 GET_CURRENT(a5,a1)
1842 l32i a4, a0, COPROCESSOR_INFO_OWNER # a4: current owner for this CP
1843 beq a4, a5, .Ldone
1844
1845 /* Find location to dump current coprocessor state:
1846 * task_struct->task_cp_save_offset + coprocessor_offset[coprocessor]
1847 *
1848 * Note: a0 pointer to the entry in the coprocessor owner table,
1849 * a3 coprocessor number,
1850 * a4 current owner of coprocessor.
1851 */
1852 l32i a5, a0, COPROCESSOR_INFO_OFFSET
1853 addi a2, a4, THREAD_CP_SAVE
1854 add a2, a2, a5
1855
1856 /* Store current coprocessor states. (a5 still has CP number) */
1857
1858 xchal_cpi_store_funcbody
1859
1860 /* The macro might have destroyed a3 (coprocessor number), but
1861 * SAR still has 32 - coprocessor_number!
1862 */
1863 movi a3, 32
1864 rsr a4, SAR
1865 sub a3, a3, a4
1866
1867.Lload: /* A new task now owns the corpocessors. Save its TCB pointer into
1868 * the coprocessor owner table.
1869 *
1870 * Note: a0 pointer to the entry in the coprocessor owner table,
1871 * a3 coprocessor number.
1872 */
1873 GET_CURRENT(a4,a1)
1874 s32i a4, a0, 0
1875
1876 /* Find location from where to restore the current coprocessor state.*/
1877
1878 l32i a5, a0, COPROCESSOR_INFO_OFFSET
1879 addi a2, a4, THREAD_CP_SAVE
1880 add a2, a2, a4
1881
1882 xchal_cpi_load_funcbody
1883
1884 /* We must assume that the xchal_cpi_store_funcbody macro destroyed
1885 * registers a2..a15.
1886 */
1887
1888.Ldone: l32i a15, a1, PT_AREG15
1889 l32i a14, a1, PT_AREG14
1890 l32i a13, a1, PT_AREG13
1891 l32i a12, a1, PT_AREG12
1892 l32i a11, a1, PT_AREG11
1893 l32i a10, a1, PT_AREG10
1894 l32i a9, a1, PT_AREG9
1895 l32i a8, a1, PT_AREG8
1896 l32i a7, a1, PT_AREG7
1897 l32i a6, a1, PT_AREG6
1898 l32i a5, a1, PT_AREG5
1899 l32i a4, a1, PT_AREG4
1900 l32i a3, a1, PT_AREG3
1901 l32i a2, a1, PT_AREG2
1902 l32i a0, a1, PT_AREG0
1903 l32i a1, a1, PT_AREG1
1904
1905 rfe
1906
1907#endif /* XCHAL_EXTRA_SA_SIZE */
1908
1909/*
1910 * Task switch.
1911 *
1912 * struct task* _switch_to (struct task* prev, struct task* next)
1913 * a2 a2 a3
1914 */
1915
1916ENTRY(_switch_to)
1917
1918 entry a1, 16
1919
1920 mov a4, a3 # preserve a3
1921
1922 s32i a0, a2, THREAD_RA # save return address
1923 s32i a1, a2, THREAD_SP # save stack pointer
1924
1925 /* Disable ints while we manipulate the stack pointer; spill regs. */
1926
1927 movi a5, PS_EXCM_MASK | LOCKLEVEL
1928 xsr a5, PS
1929 rsr a3, EXCSAVE_1
1930 rsync
1931 s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */
1932
1933 call0 _spill_registers
1934
1935 /* Set kernel stack (and leave critical section)
1936 * Note: It's save to set it here. The stack will not be overwritten
1937 * because the kernel stack will only be loaded again after
1938 * we return from kernel space.
1939 */
1940
1941 l32i a0, a4, TASK_THREAD_INFO
1942 rsr a3, EXCSAVE_1 # exc_table
1943 movi a1, 0
1944 addi a0, a0, PT_REGS_OFFSET
1945 s32i a1, a3, EXC_TABLE_FIXUP
1946 s32i a0, a3, EXC_TABLE_KSTK
1947
1948 /* restore context of the task that 'next' addresses */
1949
1950 l32i a0, a4, THREAD_RA /* restore return address */
1951 l32i a1, a4, THREAD_SP /* restore stack pointer */
1952
1953 wsr a5, PS
1954 rsync
1955
1956 retw
1957
1958
1959ENTRY(ret_from_fork)
1960
1961 /* void schedule_tail (struct task_struct *prev)
1962 * Note: prev is still in a6 (return value from fake call4 frame)
1963 */
1964 movi a4, schedule_tail
1965 callx4 a4
1966
1967 movi a4, do_syscall_trace
1968 callx4 a4
1969
1970 j common_exception_return
1971
1972
1973
1974/*
1975 * Table of syscalls
1976 */
1977
1978.data
1979.align 4
1980.global sys_call_table
1981sys_call_table:
1982
1983#define SYSCALL(call, narg) .word call
1984#include "syscalls.h"
1985
1986/*
1987 * Number of arguments of each syscall
1988 */
1989
1990.global sys_narg_table
1991sys_narg_table:
1992
1993#undef SYSCALL
1994#define SYSCALL(call, narg) .byte narg
1995#include "syscalls.h"
1996
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
new file mode 100644
index 0000000000..6e9b5225b8
--- /dev/null
+++ b/arch/xtensa/kernel/head.S
@@ -0,0 +1,237 @@
1/*
2 * arch/xtensa/kernel/head.S
3 *
4 * Xtensa Processor startup code.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
14 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
15 * Kevin Chea
16 */
17
18#include <xtensa/cacheasm.h>
19#include <linux/config.h>
20#include <asm/processor.h>
21#include <asm/page.h>
22
23/*
24 * This module contains the entry code for kernel images. It performs the
25 * minimal setup needed to call the generic C routines.
26 *
27 * Prerequisites:
28 *
29 * - The kernel image has been loaded to the actual address where it was
30 * compiled to.
31 * - a2 contains either 0 or a pointer to a list of boot parameters.
32 * (see setup.c for more details)
33 *
34 */
35
36 .macro iterate from, to , cmd
37 .ifeq ((\to - \from) & ~0xfff)
38 \cmd \from
39 iterate "(\from+1)", \to, \cmd
40 .endif
41 .endm
42
43/*
44 * _start
45 *
46 * The bootloader passes a pointer to a list of boot parameters in a2.
47 */
48
49 /* The first bytes of the kernel image must be an instruction, so we
50 * manually allocate and define the literal constant we need for a jx
51 * instruction.
52 */
53
54 .section .head.text, "ax"
55 .globl _start
56_start: _j 2f
57 .align 4
581: .word _startup
592: l32r a0, 1b
60 jx a0
61
62 .text
63 .align 4
64_startup:
65
66 /* Disable interrupts and exceptions. */
67
68 movi a0, XCHAL_PS_EXCM_MASK
69 wsr a0, PS
70
71 /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
72
73 wsr a2, EXCSAVE_1
74
75 /* Start with a fresh windowbase and windowstart. */
76
77 movi a1, 1
78 movi a0, 0
79 wsr a1, WINDOWSTART
80 wsr a0, WINDOWBASE
81 rsync
82
83 /* Set a0 to 0 for the remaining initialization. */
84
85 movi a0, 0
86
87 /* Clear debugging registers. */
88
89#if XCHAL_HAVE_DEBUG
90 wsr a0, IBREAKENABLE
91 wsr a0, ICOUNT
92 movi a1, 15
93 wsr a0, ICOUNTLEVEL
94
95 .macro reset_dbreak num
96 wsr a0, DBREAKC + \num
97 .endm
98
99 iterate 0, XCHAL_NUM_IBREAK-1, reset_dbreak
100#endif
101
102 /* Clear CCOUNT (not really necessary, but nice) */
103
104 wsr a0, CCOUNT # not really necessary, but nice
105
106 /* Disable zero-loops. */
107
108#if XCHAL_HAVE_LOOPS
109 wsr a0, LCOUNT
110#endif
111
112 /* Disable all timers. */
113
114 .macro reset_timer num
115 wsr a0, CCOMPARE_0 + \num
116 .endm
117 iterate 0, XCHAL_NUM_TIMERS-1, reset_timer
118
119 /* Interrupt initialization. */
120
121 movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE
122 wsr a0, INTENABLE
123 wsr a2, INTCLEAR
124
125 /* Disable coprocessors. */
126
127#if XCHAL_CP_NUM > 0
128 wsr a0, CPENABLE
129#endif
130
131 /* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0
132 *
133 * Note: PS.EXCM must be cleared before using any loop
134 * instructions; otherwise, they are silently disabled, and
135 * at most one iteration of the loop is executed.
136 */
137
138 movi a1, 1
139 wsr a1, PS
140 rsync
141
142 /* Initialize the caches.
143 * Does not include flushing writeback d-cache.
144 * a6, a7 are just working registers (clobbered).
145 */
146
147 icache_reset a2, a3
148 dcache_reset a2, a3
149
150 /* Unpack data sections
151 *
152 * The linker script used to build the Linux kernel image
153 * creates a table located at __boot_reloc_table_start
154 * that contans the information what data needs to be unpacked.
155 *
156 * Uses a2-a7.
157 */
158
159 movi a2, __boot_reloc_table_start
160 movi a3, __boot_reloc_table_end
161
1621: beq a2, a3, 3f # no more entries?
163 l32i a4, a2, 0 # start destination (in RAM)
164 l32i a5, a2, 4 # end desination (in RAM)
165 l32i a6, a2, 8 # start source (in ROM)
166 addi a2, a2, 12 # next entry
167 beq a4, a5, 1b # skip, empty entry
168 beq a4, a6, 1b # skip, source and dest. are the same
169
1702: l32i a7, a6, 0 # load word
171 addi a6, a6, 4
172 s32i a7, a4, 0 # store word
173 addi a4, a4, 4
174 bltu a4, a5, 2b
175 j 1b
176
1773:
178 /* All code and initialized data segments have been copied.
179 * Now clear the BSS segment.
180 */
181
182 movi a2, _bss_start # start of BSS
183 movi a3, _bss_end # end of BSS
184
1851: addi a2, a2, 4
186 s32i a0, a2, 0
187 blt a2, a3, 1b
188
189#if XCHAL_DCACHE_IS_WRITEBACK
190
191 /* After unpacking, flush the writeback cache to memory so the
192 * instructions/data are available.
193 */
194
195 dcache_writeback_all a2, a3
196#endif
197
198 /* Setup stack and enable window exceptions (keep irqs disabled) */
199
200 movi a1, init_thread_union
201 addi a1, a1, KERNEL_STACK_SIZE
202
203 movi a2, 0x00040001 # WOE=1, INTLEVEL=1, UM=0
204 wsr a2, PS # (enable reg-windows; progmode stack)
205 rsync
206
207 /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
208
209 movi a2, debug_exception
210 wsr a2, EXCSAVE + XCHAL_DEBUGLEVEL
211
212 /* Set up EXCSAVE[1] to point to the exc_table. */
213
214 movi a6, exc_table
215 xsr a6, EXCSAVE_1
216
217 /* init_arch kick-starts the linux kernel */
218
219 movi a4, init_arch
220 callx4 a4
221
222 movi a4, start_kernel
223 callx4 a4
224
225should_never_return:
226 j should_never_return
227
228 /* Define some common data structures here. We define them
229 * here in this assembly file due to their unusual alignment
230 * requirements.
231 */
232
233 .comm swapper_pg_dir,PAGE_SIZE,PAGE_SIZE
234 .comm empty_bad_page_table,PAGE_SIZE,PAGE_SIZE
235 .comm empty_bad_page,PAGE_SIZE,PAGE_SIZE
236 .comm empty_zero_page,PAGE_SIZE,PAGE_SIZE
237
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
new file mode 100644
index 0000000000..4cbf6d9157
--- /dev/null
+++ b/arch/xtensa/kernel/irq.c
@@ -0,0 +1,192 @@
1/*
2 * linux/arch/xtensa/kernel/irq.c
3 *
4 * Xtensa built-in interrupt controller and some generic functions copied
5 * from i386.
6 *
7 * Copyright (C) 2002 - 2005 Tensilica, Inc.
8 * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
9 *
10 *
11 * Chris Zankel <chris@zankel.net>
12 * Kevin Chea
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/seq_file.h>
18#include <linux/interrupt.h>
19#include <linux/irq.h>
20#include <linux/kernel_stat.h>
21
22#include <asm/uaccess.h>
23#include <asm/platform.h>
24
25static void enable_xtensa_irq(unsigned int irq);
26static void disable_xtensa_irq(unsigned int irq);
27static void mask_and_ack_xtensa(unsigned int irq);
28static void end_xtensa_irq(unsigned int irq);
29
30static unsigned int cached_irq_mask;
31
32atomic_t irq_err_count;
33
34/*
35 * 'what should we do if we get a hw irq event on an illegal vector'.
36 * each architecture has to answer this themselves.
37 */
38void ack_bad_irq(unsigned int irq)
39{
40 printk("unexpected IRQ trap at vector %02x\n", irq);
41}
42
43/*
44 * do_IRQ handles all normal device IRQ's (the special
45 * SMP cross-CPU interrupts have their own specific
46 * handlers).
47 */
48
49unsigned int do_IRQ(int irq, struct pt_regs *regs)
50{
51 irq_enter();
52
53#ifdef CONFIG_DEBUG_STACKOVERFLOW
54 /* Debugging check for stack overflow: is there less than 1KB free? */
55 {
56 unsigned long sp;
57
58 __asm__ __volatile__ ("mov %0, a1\n" : "=a" (sp));
59 sp &= THREAD_SIZE - 1;
60
61 if (unlikely(sp < (sizeof(thread_info) + 1024)))
62 printk("Stack overflow in do_IRQ: %ld\n",
63 sp - sizeof(struct thread_info));
64 }
65#endif
66
67 __do_IRQ(irq, regs);
68
69 irq_exit();
70
71 return 1;
72}
73
74/*
75 * Generic, controller-independent functions:
76 */
77
78int show_interrupts(struct seq_file *p, void *v)
79{
80 int i = *(loff_t *) v, j;
81 struct irqaction * action;
82 unsigned long flags;
83
84 if (i == 0) {
85 seq_printf(p, " ");
86 for (j=0; j<NR_CPUS; j++)
87 if (cpu_online(j))
88 seq_printf(p, "CPU%d ",j);
89 seq_putc(p, '\n');
90 }
91
92 if (i < NR_IRQS) {
93 spin_lock_irqsave(&irq_desc[i].lock, flags);
94 action = irq_desc[i].action;
95 if (!action)
96 goto skip;
97 seq_printf(p, "%3d: ",i);
98#ifndef CONFIG_SMP
99 seq_printf(p, "%10u ", kstat_irqs(i));
100#else
101 for (j = 0; j < NR_CPUS; j++)
102 if (cpu_online(j))
103 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
104#endif
105 seq_printf(p, " %14s", irq_desc[i].handler->typename);
106 seq_printf(p, " %s", action->name);
107
108 for (action=action->next; action; action = action->next)
109 seq_printf(p, ", %s", action->name);
110
111 seq_putc(p, '\n');
112skip:
113 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
114 } else if (i == NR_IRQS) {
115 seq_printf(p, "NMI: ");
116 for (j = 0; j < NR_CPUS; j++)
117 if (cpu_online(j))
118 seq_printf(p, "%10u ", nmi_count(j));
119 seq_putc(p, '\n');
120 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
121 }
122 return 0;
123}
124/* shutdown is same as "disable" */
125#define shutdown_xtensa_irq disable_xtensa_irq
126
127static unsigned int startup_xtensa_irq(unsigned int irq)
128{
129 enable_xtensa_irq(irq);
130 return 0; /* never anything pending */
131}
132
133static struct hw_interrupt_type xtensa_irq_type = {
134 "Xtensa-IRQ",
135 startup_xtensa_irq,
136 shutdown_xtensa_irq,
137 enable_xtensa_irq,
138 disable_xtensa_irq,
139 mask_and_ack_xtensa,
140 end_xtensa_irq
141};
142
143static inline void mask_irq(unsigned int irq)
144{
145 cached_irq_mask &= ~(1 << irq);
146 set_sr (cached_irq_mask, INTENABLE);
147}
148
149static inline void unmask_irq(unsigned int irq)
150{
151 cached_irq_mask |= 1 << irq;
152 set_sr (cached_irq_mask, INTENABLE);
153}
154
155static void disable_xtensa_irq(unsigned int irq)
156{
157 unsigned long flags;
158 local_save_flags(flags);
159 mask_irq(irq);
160 local_irq_restore(flags);
161}
162
163static void enable_xtensa_irq(unsigned int irq)
164{
165 unsigned long flags;
166 local_save_flags(flags);
167 unmask_irq(irq);
168 local_irq_restore(flags);
169}
170
171static void mask_and_ack_xtensa(unsigned int irq)
172{
173 disable_xtensa_irq(irq);
174}
175
176static void end_xtensa_irq(unsigned int irq)
177{
178 enable_xtensa_irq(irq);
179}
180
181
182void __init init_IRQ(void)
183{
184 int i;
185
186 for (i=0; i < XTENSA_NR_IRQS; i++)
187 irq_desc[i].handler = &xtensa_irq_type;
188
189 cached_irq_mask = 0;
190
191 platform_init_irq();
192}
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c
new file mode 100644
index 0000000000..d1683cfa19
--- /dev/null
+++ b/arch/xtensa/kernel/module.c
@@ -0,0 +1,78 @@
1/*
2 * arch/xtensa/kernel/platform.c
3 *
4 * Module support.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/moduleloader.h>
18#include <linux/elf.h>
19#include <linux/vmalloc.h>
20#include <linux/fs.h>
21#include <linux/string.h>
22#include <linux/kernel.h>
23#include <linux/cache.h>
24
25LIST_HEAD(module_buf_list);
26
27void *module_alloc(unsigned long size)
28{
29 panic("module_alloc not implemented");
30}
31
32void module_free(struct module *mod, void *module_region)
33{
34 panic("module_free not implemented");
35}
36
37int module_frob_arch_sections(Elf32_Ehdr *hdr,
38 Elf32_Shdr *sechdrs,
39 char *secstrings,
40 struct module *me)
41{
42 panic("module_frob_arch_sections not implemented");
43}
44
45int apply_relocate(Elf32_Shdr *sechdrs,
46 const char *strtab,
47 unsigned int symindex,
48 unsigned int relsec,
49 struct module *module)
50{
51 panic ("apply_relocate not implemented");
52}
53
54int apply_relocate_add(Elf32_Shdr *sechdrs,
55 const char *strtab,
56 unsigned int symindex,
57 unsigned int relsec,
58 struct module *module)
59{
60 panic("apply_relocate_add not implemented");
61}
62
63int module_finalize(const Elf_Ehdr *hdr,
64 const Elf_Shdr *sechdrs,
65 struct module *me)
66{
67 panic ("module_finalize not implemented");
68}
69
70void module_arch_cleanup(struct module *mod)
71{
72 panic("module_arch_cleanup not implemented");
73}
74
75struct bug_entry *module_find_bug(unsigned long bugaddr)
76{
77 panic("module_find_bug not implemented");
78}
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
new file mode 100644
index 0000000000..84fde258cf
--- /dev/null
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -0,0 +1,73 @@
1/*
2 * arch/xtensa/pci-dma.c
3 *
4 * DMA coherent memory allocation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Copyright (C) 2002 - 2005 Tensilica Inc.
12 *
13 * Based on version for i386.
14 *
15 * Chris Zankel <chris@zankel.net>
16 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
17 */
18
19#include <linux/types.h>
20#include <linux/mm.h>
21#include <linux/string.h>
22#include <linux/pci.h>
23#include <asm/io.h>
24#include <asm/cacheflush.h>
25
26/*
27 * Note: We assume that the full memory space is always mapped to 'kseg'
28 * Otherwise we have to use page attributes (not implemented).
29 */
30
31void *
32dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
33{
34 void *ret;
35
36 /* ignore region speicifiers */
37 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
38
39 if (dev == NULL || (*dev->dma_mask < 0xffffffff))
40 gfp |= GFP_DMA;
41 ret = (void *)__get_free_pages(gfp, get_order(size));
42
43 if (ret != NULL) {
44 memset(ret, 0, size);
45 *handle = virt_to_bus(ret);
46 }
47 return (void*) BYPASS_ADDR((unsigned long)ret);
48}
49
50void dma_free_coherent(struct device *hwdev, size_t size,
51 void *vaddr, dma_addr_t dma_handle)
52{
53 free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size));
54}
55
56
57void consistent_sync(void *vaddr, size_t size, int direction)
58{
59 switch (direction) {
60 case PCI_DMA_NONE:
61 BUG();
62 case PCI_DMA_FROMDEVICE: /* invalidate only */
63 __invalidate_dcache_range((unsigned long)vaddr,
64 (unsigned long)size);
65 break;
66
67 case PCI_DMA_TODEVICE: /* writeback only */
68 case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */
69 __flush_invalidate_dcache_range((unsigned long)vaddr,
70 (unsigned long)size);
71 break;
72 }
73}
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
new file mode 100644
index 0000000000..d29a816486
--- /dev/null
+++ b/arch/xtensa/kernel/pci.c
@@ -0,0 +1,563 @@
1/*
2 * arch/xtensa/pcibios.c
3 *
4 * PCI bios-type initialisation for PCI machines
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Copyright (C) 2001-2005 Tensilica Inc.
12 *
13 * Based largely on work from Cort (ppc/kernel/pci.c)
14 * IO functions copied from sparc.
15 *
16 * Chris Zankel <chris@zankel.net>
17 *
18 */
19
20#include <linux/config.h>
21#include <linux/kernel.h>
22#include <linux/pci.h>
23#include <linux/delay.h>
24#include <linux/string.h>
25#include <linux/init.h>
26#include <linux/sched.h>
27#include <linux/errno.h>
28#include <linux/bootmem.h>
29
30#include <asm/pci-bridge.h>
31#include <asm/platform.h>
32
33#undef DEBUG
34
35#ifdef DEBUG
36#define DBG(x...) printk(x)
37#else
38#define DBG(x...)
39#endif
40
41/* PCI Controller */
42
43
44/*
45 * pcibios_alloc_controller
46 * pcibios_enable_device
47 * pcibios_fixups
48 * pcibios_align_resource
49 * pcibios_fixup_bus
50 * pcibios_setup
51 * pci_bus_add_device
52 * pci_mmap_page_range
53 */
54
55struct pci_controller* pci_ctrl_head;
56struct pci_controller** pci_ctrl_tail = &pci_ctrl_head;
57
58static int pci_bus_count;
59
60static void pcibios_fixup_resources(struct pci_dev* dev);
61
62#if 0 // FIXME
63struct pci_fixup pcibios_fixups[] = {
64 { DECLARE_PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources },
65 { 0 }
66};
67#endif
68
69void
70pcibios_update_resource(struct pci_dev *dev, struct resource *root,
71 struct resource *res, int resource)
72{
73 u32 new, check, mask;
74 int reg;
75 struct pci_controller* pci_ctrl = dev->sysdata;
76
77 new = res->start;
78 if (pci_ctrl && res->flags & IORESOURCE_IO) {
79 new -= pci_ctrl->io_space.base;
80 }
81 new |= (res->flags & PCI_REGION_FLAG_MASK);
82 if (resource < 6) {
83 reg = PCI_BASE_ADDRESS_0 + 4*resource;
84 } else if (resource == PCI_ROM_RESOURCE) {
85 res->flags |= PCI_ROM_ADDRESS_ENABLE;
86 reg = dev->rom_base_reg;
87 } else {
88 /* Somebody might have asked allocation of a non-standard resource */
89 return;
90 }
91
92 pci_write_config_dword(dev, reg, new);
93 pci_read_config_dword(dev, reg, &check);
94 mask = (new & PCI_BASE_ADDRESS_SPACE_IO) ?
95 PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
96
97 if ((new ^ check) & mask) {
98 printk(KERN_ERR "PCI: Error while updating region "
99 "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
100 new, check);
101 }
102}
103
104/*
105 * We need to avoid collisions with `mirrored' VGA ports
106 * and other strange ISA hardware, so we always want the
107 * addresses to be allocated in the 0x000-0x0ff region
108 * modulo 0x400.
109 *
110 * Why? Because some silly external IO cards only decode
111 * the low 10 bits of the IO address. The 0x00-0xff region
112 * is reserved for motherboard devices that decode all 16
113 * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
114 * but we want to try to avoid allocating at 0x2900-0x2bff
115 * which might have be mirrored at 0x0100-0x03ff..
116 */
117void
118pcibios_align_resource(void *data, struct resource *res, unsigned long size,
119 unsigned long align)
120{
121 struct pci_dev *dev = data;
122
123 if (res->flags & IORESOURCE_IO) {
124 unsigned long start = res->start;
125
126 if (size > 0x100) {
127 printk(KERN_ERR "PCI: I/O Region %s/%d too large"
128 " (%ld bytes)\n", dev->slot_name,
129 dev->resource - res, size);
130 }
131
132 if (start & 0x300) {
133 start = (start + 0x3ff) & ~0x3ff;
134 res->start = start;
135 }
136 }
137}
138
139int
140pcibios_enable_resources(struct pci_dev *dev, int mask)
141{
142 u16 cmd, old_cmd;
143 int idx;
144 struct resource *r;
145
146 pci_read_config_word(dev, PCI_COMMAND, &cmd);
147 old_cmd = cmd;
148 for(idx=0; idx<6; idx++) {
149 r = &dev->resource[idx];
150 if (!r->start && r->end) {
151 printk (KERN_ERR "PCI: Device %s not available because "
152 "of resource collisions\n", dev->slot_name);
153 return -EINVAL;
154 }
155 if (r->flags & IORESOURCE_IO)
156 cmd |= PCI_COMMAND_IO;
157 if (r->flags & IORESOURCE_MEM)
158 cmd |= PCI_COMMAND_MEMORY;
159 }
160 if (dev->resource[PCI_ROM_RESOURCE].start)
161 cmd |= PCI_COMMAND_MEMORY;
162 if (cmd != old_cmd) {
163 printk("PCI: Enabling device %s (%04x -> %04x)\n",
164 dev->slot_name, old_cmd, cmd);
165 pci_write_config_word(dev, PCI_COMMAND, cmd);
166 }
167 return 0;
168}
169
170struct pci_controller * __init pcibios_alloc_controller(void)
171{
172 struct pci_controller *pci_ctrl;
173
174 pci_ctrl = (struct pci_controller *)alloc_bootmem(sizeof(*pci_ctrl));
175 memset(pci_ctrl, 0, sizeof(struct pci_controller));
176
177 *pci_ctrl_tail = pci_ctrl;
178 pci_ctrl_tail = &pci_ctrl->next;
179
180 return pci_ctrl;
181}
182
183static int __init pcibios_init(void)
184{
185 struct pci_controller *pci_ctrl;
186 struct pci_bus *bus;
187 int next_busno = 0, i;
188
189 printk("PCI: Probing PCI hardware\n");
190
191 /* Scan all of the recorded PCI controllers. */
192 for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) {
193 pci_ctrl->last_busno = 0xff;
194 bus = pci_scan_bus(pci_ctrl->first_busno, pci_ctrl->ops,
195 pci_ctrl);
196 if (pci_ctrl->io_resource.flags) {
197 unsigned long offs;
198
199 offs = (unsigned long)pci_ctrl->io_space.base;
200 pci_ctrl->io_resource.start += offs;
201 pci_ctrl->io_resource.end += offs;
202 bus->resource[0] = &pci_ctrl->io_resource;
203 }
204 for (i = 0; i < 3; ++i)
205 if (pci_ctrl->mem_resources[i].flags)
206 bus->resource[i+1] =&pci_ctrl->mem_resources[i];
207 pci_ctrl->bus = bus;
208 pci_ctrl->last_busno = bus->subordinate;
209 if (next_busno <= pci_ctrl->last_busno)
210 next_busno = pci_ctrl->last_busno+1;
211 }
212 pci_bus_count = next_busno;
213
214 return platform_pcibios_fixup();
215}
216
217subsys_initcall(pcibios_init);
218
219void __init pcibios_fixup_bus(struct pci_bus *bus)
220{
221 struct pci_controller *pci_ctrl = bus->sysdata;
222 struct resource *res;
223 unsigned long io_offset;
224 int i;
225
226 io_offset = (unsigned long)pci_ctrl->io_space.base;
227 if (bus->parent == NULL) {
228 /* this is a host bridge - fill in its resources */
229 pci_ctrl->bus = bus;
230
231 bus->resource[0] = res = &pci_ctrl->io_resource;
232 if (!res->flags) {
233 if (io_offset)
234 printk (KERN_ERR "I/O resource not set for host"
235 " bridge %d\n", pci_ctrl->index);
236 res->start = 0;
237 res->end = IO_SPACE_LIMIT;
238 res->flags = IORESOURCE_IO;
239 }
240 res->start += io_offset;
241 res->end += io_offset;
242
243 for (i = 0; i < 3; i++) {
244 res = &pci_ctrl->mem_resources[i];
245 if (!res->flags) {
246 if (i > 0)
247 continue;
248 printk(KERN_ERR "Memory resource not set for "
249 "host bridge %d\n", pci_ctrl->index);
250 res->start = 0;
251 res->end = ~0U;
252 res->flags = IORESOURCE_MEM;
253 }
254 bus->resource[i+1] = res;
255 }
256 } else {
257 /* This is a subordinate bridge */
258 pci_read_bridge_bases(bus);
259
260 for (i = 0; i < 4; i++) {
261 if ((res = bus->resource[i]) == NULL || !res->flags)
262 continue;
263 if (io_offset && (res->flags & IORESOURCE_IO)) {
264 res->start += io_offset;
265 res->end += io_offset;
266 }
267 }
268 }
269}
270
271char __init *pcibios_setup(char *str)
272{
273 return str;
274}
275
276/* the next one is stolen from the alpha port... */
277
278void __init
279pcibios_update_irq(struct pci_dev *dev, int irq)
280{
281 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
282}
283
284int pcibios_enable_device(struct pci_dev *dev, int mask)
285{
286 u16 cmd, old_cmd;
287 int idx;
288 struct resource *r;
289
290 pci_read_config_word(dev, PCI_COMMAND, &cmd);
291 old_cmd = cmd;
292 for (idx=0; idx<6; idx++) {
293 r = &dev->resource[idx];
294 if (!r->start && r->end) {
295 printk(KERN_ERR "PCI: Device %s not available because "
296 "of resource collisions\n", dev->slot_name);
297 return -EINVAL;
298 }
299 if (r->flags & IORESOURCE_IO)
300 cmd |= PCI_COMMAND_IO;
301 if (r->flags & IORESOURCE_MEM)
302 cmd |= PCI_COMMAND_MEMORY;
303 }
304 if (cmd != old_cmd) {
305 printk("PCI: Enabling device %s (%04x -> %04x)\n",
306 dev->slot_name, old_cmd, cmd);
307 pci_write_config_word(dev, PCI_COMMAND, cmd);
308 }
309
310 return 0;
311}
312
313#ifdef CONFIG_PROC_FS
314
315/*
316 * Return the index of the PCI controller for device pdev.
317 */
318
319int
320pci_controller_num(struct pci_dev *dev)
321{
322 struct pci_controller *pci_ctrl = (struct pci_controller*) dev->sysdata;
323 return pci_ctrl->index;
324}
325
326#endif /* CONFIG_PROC_FS */
327
328
329static void
330pcibios_fixup_resources(struct pci_dev *dev)
331{
332 struct pci_controller* pci_ctrl = (struct pci_controller *)dev->sysdata;
333 int i;
334 unsigned long offset;
335
336 if (!pci_ctrl) {
337 printk(KERN_ERR "No pci_ctrl for PCI dev %s!\n",dev->slot_name);
338 return;
339 }
340 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
341 struct resource *res = dev->resource + i;
342 if (!res->start || !res->flags)
343 continue;
344 if (res->end == 0xffffffff) {
345 DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
346 dev->slot_name, i, res->start, res->end);
347 res->end -= res->start;
348 res->start = 0;
349 continue;
350 }
351 offset = 0;
352 if (res->flags & IORESOURCE_IO)
353 offset = (unsigned long) pci_ctrl->io_space.base;
354 else if (res->flags & IORESOURCE_MEM)
355 offset = (unsigned long) pci_ctrl->mem_space.base;
356
357 if (offset != 0) {
358 res->start += offset;
359 res->end += offset;
360#ifdef DEBUG
361 printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
362 i, res->flags, dev->slot_name,
363 res->start - offset, res->start);
364#endif
365 }
366 }
367}
368
369/*
370 * Platform support for /proc/bus/pci/X/Y mmap()s,
371 * modelled on the sparc64 implementation by Dave Miller.
372 * -- paulus.
373 */
374
375/*
376 * Adjust vm_pgoff of VMA such that it is the physical page offset
377 * corresponding to the 32-bit pci bus offset for DEV requested by the user.
378 *
379 * Basically, the user finds the base address for his device which he wishes
380 * to mmap. They read the 32-bit value from the config space base register,
381 * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
382 * offset parameter of mmap on /proc/bus/pci/XXX for that device.
383 *
384 * Returns negative error code on failure, zero on success.
385 */
386static __inline__ int
387__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
388 enum pci_mmap_state mmap_state)
389{
390 struct pci_controller *pci_ctrl = (struct pci_controller*) dev->sysdata;
391 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
392 unsigned long io_offset = 0;
393 int i, res_bit;
394
395 if (pci_ctrl == 0)
396 return -EINVAL; /* should never happen */
397
398 /* If memory, add on the PCI bridge address offset */
399 if (mmap_state == pci_mmap_mem) {
400 res_bit = IORESOURCE_MEM;
401 } else {
402 io_offset = (unsigned long)pci_ctrl->io_space.base;
403 offset += io_offset;
404 res_bit = IORESOURCE_IO;
405 }
406
407 /*
408 * Check that the offset requested corresponds to one of the
409 * resources of the device.
410 */
411 for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
412 struct resource *rp = &dev->resource[i];
413 int flags = rp->flags;
414
415 /* treat ROM as memory (should be already) */
416 if (i == PCI_ROM_RESOURCE)
417 flags |= IORESOURCE_MEM;
418
419 /* Active and same type? */
420 if ((flags & res_bit) == 0)
421 continue;
422
423 /* In the range of this resource? */
424 if (offset < (rp->start & PAGE_MASK) || offset > rp->end)
425 continue;
426
427 /* found it! construct the final physical address */
428 if (mmap_state == pci_mmap_io)
429 offset += pci_ctrl->io_space.start - io_offset;
430 vma->vm_pgoff = offset >> PAGE_SHIFT;
431 return 0;
432 }
433
434 return -EINVAL;
435}
436
437/*
438 * Set vm_flags of VMA, as appropriate for this architecture, for a pci device
439 * mapping.
440 */
441static __inline__ void
442__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
443 enum pci_mmap_state mmap_state)
444{
445 vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
446}
447
448/*
449 * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
450 * device mapping.
451 */
452static __inline__ void
453__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
454 enum pci_mmap_state mmap_state, int write_combine)
455{
456 int prot = pgprot_val(vma->vm_page_prot);
457
458 /* Set to write-through */
459 prot &= ~_PAGE_NO_CACHE;
460#if 0
461 if (!write_combine)
462 prot |= _PAGE_WRITETHRU;
463#endif
464 vma->vm_page_prot = __pgprot(prot);
465}
466
467/*
468 * Perform the actual remap of the pages for a PCI device mapping, as
469 * appropriate for this architecture. The region in the process to map
470 * is described by vm_start and vm_end members of VMA, the base physical
471 * address is found in vm_pgoff.
472 * The pci device structure is provided so that architectures may make mapping
473 * decisions on a per-device or per-bus basis.
474 *
475 * Returns a negative error code on failure, zero on success.
476 */
477int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
478 enum pci_mmap_state mmap_state,
479 int write_combine)
480{
481 int ret;
482
483 ret = __pci_mmap_make_offset(dev, vma, mmap_state);
484 if (ret < 0)
485 return ret;
486
487 __pci_mmap_set_flags(dev, vma, mmap_state);
488 __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
489
490 ret = io_remap_page_range(vma, vma->vm_start, vma->vm_pgoff<<PAGE_SHIFT,
491 vma->vm_end - vma->vm_start, vma->vm_page_prot);
492
493 return ret;
494}
495
496/*
497 * This probably belongs here rather than ioport.c because
498 * we do not want this crud linked into SBus kernels.
499 * Also, think for a moment about likes of floppy.c that
500 * include architecture specific parts. They may want to redefine ins/outs.
501 *
502 * We do not use horroble macroses here because we want to
503 * advance pointer by sizeof(size).
504 */
505void outsb(unsigned long addr, const void *src, unsigned long count) {
506 while (count) {
507 count -= 1;
508 writeb(*(const char *)src, addr);
509 src += 1;
510 addr += 1;
511 }
512}
513
514void outsw(unsigned long addr, const void *src, unsigned long count) {
515 while (count) {
516 count -= 2;
517 writew(*(const short *)src, addr);
518 src += 2;
519 addr += 2;
520 }
521}
522
523void outsl(unsigned long addr, const void *src, unsigned long count) {
524 while (count) {
525 count -= 4;
526 writel(*(const long *)src, addr);
527 src += 4;
528 addr += 4;
529 }
530}
531
532void insb(unsigned long addr, void *dst, unsigned long count) {
533 while (count) {
534 count -= 1;
535 *(unsigned char *)dst = readb(addr);
536 dst += 1;
537 addr += 1;
538 }
539}
540
541void insw(unsigned long addr, void *dst, unsigned long count) {
542 while (count) {
543 count -= 2;
544 *(unsigned short *)dst = readw(addr);
545 dst += 2;
546 addr += 2;
547 }
548}
549
550void insl(unsigned long addr, void *dst, unsigned long count) {
551 while (count) {
552 count -= 4;
553 /*
554 * XXX I am sure we are in for an unaligned trap here.
555 */
556 *(unsigned long *)dst = readl(addr);
557 dst += 4;
558 addr += 4;
559 }
560}
561
562
563
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c
new file mode 100644
index 0000000000..cf13627844
--- /dev/null
+++ b/arch/xtensa/kernel/platform.c
@@ -0,0 +1,49 @@
1/*
2 * arch/xtensa/kernel/platform.c
3 *
4 * Default platform functions.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2005 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 */
14
15#include <linux/config.h>
16#include <linux/types.h>
17#include <linux/pci.h>
18#include <linux/time.h>
19#include <asm/platform.h>
20#include <asm/timex.h>
21
22#define _F(r,f,a,b) \
23 r __platform_##f a b; \
24 r platform_##f a __attribute__((weak, alias("__platform_"#f)))
25
26/*
27 * Default functions that are used if no platform specific function is defined.
28 * (Please, refer to include/asm-xtensa/platform.h for more information)
29 */
30
31_F(void, setup, (char** cmd), { });
32_F(void, init_irq, (void), { });
33_F(void, restart, (void), { while(1); });
34_F(void, halt, (void), { while(1); });
35_F(void, power_off, (void), { while(1); });
36_F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); });
37_F(void, heartbeat, (void), { });
38_F(int, pcibios_fixup, (void), { return 0; });
39_F(int, get_rtc_time, (time_t* t), { return 0; });
40_F(int, set_rtc_time, (time_t t), { return 0; });
41
42#if CONFIG_XTENSA_CALIBRATE_CCOUNT
43_F(void, calibrate_ccount, (void),
44{
45 printk ("ERROR: Cannot calibrate cpu frequency! Assuming 100MHz.\n");
46 ccount_per_jiffy = 100 * (1000000UL/HZ);
47});
48#endif
49
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
new file mode 100644
index 0000000000..4099703b14
--- /dev/null
+++ b/arch/xtensa/kernel/process.c
@@ -0,0 +1,482 @@
1// TODO verify coprocessor handling
2/*
3 * arch/xtensa/kernel/process.c
4 *
5 * Xtensa Processor version.
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 *
11 * Copyright (C) 2001 - 2005 Tensilica Inc.
12 *
13 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
14 * Chris Zankel <chris@zankel.net>
15 * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
16 * Kevin Chea
17 */
18
19#include <linux/config.h>
20#include <linux/errno.h>
21#include <linux/sched.h>
22#include <linux/kernel.h>
23#include <linux/mm.h>
24#include <linux/smp.h>
25#include <linux/smp_lock.h>
26#include <linux/stddef.h>
27#include <linux/unistd.h>
28#include <linux/ptrace.h>
29#include <linux/slab.h>
30#include <linux/elf.h>
31#include <linux/init.h>
32#include <linux/prctl.h>
33#include <linux/init_task.h>
34#include <linux/module.h>
35#include <linux/mqueue.h>
36
37#include <asm/pgtable.h>
38#include <asm/uaccess.h>
39#include <asm/system.h>
40#include <asm/io.h>
41#include <asm/processor.h>
42#include <asm/platform.h>
43#include <asm/mmu.h>
44#include <asm/irq.h>
45#include <asm/atomic.h>
46#include <asm/offsets.h>
47#include <asm/coprocessor.h>
48
49extern void ret_from_fork(void);
50
51static struct fs_struct init_fs = INIT_FS;
52static struct files_struct init_files = INIT_FILES;
53static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
54static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
55struct mm_struct init_mm = INIT_MM(init_mm);
56EXPORT_SYMBOL(init_mm);
57
58union thread_union init_thread_union
59 __attribute__((__section__(".data.init_task"))) =
60{ INIT_THREAD_INFO(init_task) };
61
62struct task_struct init_task = INIT_TASK(init_task);
63EXPORT_SYMBOL(init_task);
64
65struct task_struct *current_set[NR_CPUS] = {&init_task, };
66
67
68#if XCHAL_CP_NUM > 0
69
70/*
71 * Coprocessor ownership.
72 */
73
74coprocessor_info_t coprocessor_info[] = {
75 { 0, XTENSA_CPE_CP0_OFFSET },
76 { 0, XTENSA_CPE_CP1_OFFSET },
77 { 0, XTENSA_CPE_CP2_OFFSET },
78 { 0, XTENSA_CPE_CP3_OFFSET },
79 { 0, XTENSA_CPE_CP4_OFFSET },
80 { 0, XTENSA_CPE_CP5_OFFSET },
81 { 0, XTENSA_CPE_CP6_OFFSET },
82 { 0, XTENSA_CPE_CP7_OFFSET },
83};
84
85#endif
86
87/*
88 * Powermanagement idle function, if any is provided by the platform.
89 */
90
91void cpu_idle(void)
92{
93 local_irq_enable();
94
95 /* endless idle loop with no priority at all */
96 while (1) {
97 while (!need_resched())
98 platform_idle();
99 preempt_enable();
100 schedule();
101 }
102}
103
104/*
105 * Free current thread data structures etc..
106 */
107
108void exit_thread(void)
109{
110 release_coprocessors(current); /* Empty macro if no CPs are defined */
111}
112
113void flush_thread(void)
114{
115 release_coprocessors(current); /* Empty macro if no CPs are defined */
116}
117
118/*
119 * Copy thread.
120 *
121 * The stack layout for the new thread looks like this:
122 *
123 * +------------------------+ <- sp in childregs (= tos)
124 * | childregs |
125 * +------------------------+ <- thread.sp = sp in dummy-frame
126 * | dummy-frame | (saved in dummy-frame spill-area)
127 * +------------------------+
128 *
129 * We create a dummy frame to return to ret_from_fork:
130 * a0 points to ret_from_fork (simulating a call4)
131 * sp points to itself (thread.sp)
132 * a2, a3 are unused.
133 *
134 * Note: This is a pristine frame, so we don't need any spill region on top of
135 * childregs.
136 */
137
138int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
139 unsigned long unused,
140 struct task_struct * p, struct pt_regs * regs)
141{
142 struct pt_regs *childregs;
143 unsigned long tos;
144 int user_mode = user_mode(regs);
145
146 /* Set up new TSS. */
147 tos = (unsigned long)p->thread_info + THREAD_SIZE;
148 if (user_mode)
149 childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
150 else
151 childregs = (struct pt_regs*)tos - 1;
152
153 *childregs = *regs;
154
155 /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
156 *((int*)childregs - 3) = (unsigned long)childregs;
157 *((int*)childregs - 4) = 0;
158
159 childregs->areg[1] = tos;
160 childregs->areg[2] = 0;
161 p->set_child_tid = p->clear_child_tid = NULL;
162 p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
163 p->thread.sp = (unsigned long)childregs;
164 if (user_mode(regs)) {
165
166 int len = childregs->wmask & ~0xf;
167 childregs->areg[1] = usp;
168 memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
169 &regs->areg[XCHAL_NUM_AREGS - len/4], len);
170
171 if (clone_flags & CLONE_SETTLS)
172 childregs->areg[2] = childregs->areg[6];
173
174 } else {
175 /* In kernel space, we start a new thread with a new stack. */
176 childregs->wmask = 1;
177 }
178 return 0;
179}
180
181
182/*
183 * Create a kernel thread
184 */
185
186int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
187{
188 long retval;
189 __asm__ __volatile__
190 ("mov a5, %4\n\t" /* preserve fn in a5 */
191 "mov a6, %3\n\t" /* preserve and setup arg in a6 */
192 "movi a2, %1\n\t" /* load __NR_clone for syscall*/
193 "mov a3, sp\n\t" /* sp check and sys_clone */
194 "mov a4, %5\n\t" /* load flags for syscall */
195 "syscall\n\t"
196 "beq a3, sp, 1f\n\t" /* branch if parent */
197 "callx4 a5\n\t" /* call fn */
198 "movi a2, %2\n\t" /* load __NR_exit for syscall */
199 "mov a3, a6\n\t" /* load fn return value */
200 "syscall\n"
201 "1:\n\t"
202 "mov %0, a2\n\t" /* parent returns zero */
203 :"=r" (retval)
204 :"i" (__NR_clone), "i" (__NR_exit),
205 "r" (arg), "r" (fn),
206 "r" (flags | CLONE_VM)
207 : "a2", "a3", "a4", "a5", "a6" );
208 return retval;
209}
210
211
212/*
213 * These bracket the sleeping functions..
214 */
215
216unsigned long get_wchan(struct task_struct *p)
217{
218 unsigned long sp, pc;
219 unsigned long stack_page = (unsigned long) p->thread_info;
220 int count = 0;
221
222 if (!p || p == current || p->state == TASK_RUNNING)
223 return 0;
224
225 sp = p->thread.sp;
226 pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
227
228 do {
229 if (sp < stack_page + sizeof(struct task_struct) ||
230 sp >= (stack_page + THREAD_SIZE) ||
231 pc == 0)
232 return 0;
233 if (!in_sched_functions(pc))
234 return pc;
235
236 /* Stack layout: sp-4: ra, sp-3: sp' */
237
238 pc = MAKE_PC_FROM_RA(*(unsigned long*)sp - 4, sp);
239 sp = *(unsigned long *)sp - 3;
240 } while (count++ < 16);
241 return 0;
242}
243
244/*
245 * do_copy_regs() gathers information from 'struct pt_regs' and
246 * 'current->thread.areg[]' to fill in the xtensa_gregset_t
247 * structure.
248 *
249 * xtensa_gregset_t and 'struct pt_regs' are vastly different formats
250 * of processor registers. Besides different ordering,
251 * xtensa_gregset_t contains non-live register information that
252 * 'struct pt_regs' does not. Exception handling (primarily) uses
253 * 'struct pt_regs'. Core files and ptrace use xtensa_gregset_t.
254 *
255 */
256
257void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
258 struct task_struct *tsk)
259{
260 int i, n, wb_offset;
261
262 elfregs->xchal_config_id0 = XCHAL_HW_CONFIGID0;
263 elfregs->xchal_config_id1 = XCHAL_HW_CONFIGID1;
264
265 __asm__ __volatile__ ("rsr %0, 176\n" : "=a" (i));
266 elfregs->cpux = i;
267 __asm__ __volatile__ ("rsr %0, 208\n" : "=a" (i));
268 elfregs->cpuy = i;
269
270 /* Note: PS.EXCM is not set while user task is running; its
271 * being set in regs->ps is for exception handling convenience.
272 */
273
274 elfregs->pc = regs->pc;
275 elfregs->ps = (regs->ps & ~XCHAL_PS_EXCM_MASK);
276 elfregs->exccause = regs->exccause;
277 elfregs->excvaddr = regs->excvaddr;
278 elfregs->windowbase = regs->windowbase;
279 elfregs->windowstart = regs->windowstart;
280 elfregs->lbeg = regs->lbeg;
281 elfregs->lend = regs->lend;
282 elfregs->lcount = regs->lcount;
283 elfregs->sar = regs->sar;
284 elfregs->syscall = regs->syscall;
285
286 /* Copy register file.
287 * The layout looks like this:
288 *
289 * | a0 ... a15 | Z ... Z | arX ... arY |
290 * current window unused saved frames
291 */
292
293 memset (elfregs->ar, 0, sizeof(elfregs->ar));
294
295 wb_offset = regs->windowbase * 4;
296 n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
297
298 for (i = 0; i < n; i++)
299 elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
300
301 n = (regs->wmask >> 4) * 4;
302
303 for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
304 elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
305}
306
307void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
308{
309 do_copy_regs ((xtensa_gregset_t *)elfregs, regs, current);
310}
311
312
313/* The inverse of do_copy_regs(). No error or sanity checking. */
314
315void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
316 struct task_struct *tsk)
317{
318 int i, n, wb_offset;
319
320 /* Note: PS.EXCM is not set while user task is running; it
321 * needs to be set in regs->ps is for exception handling convenience.
322 */
323
324 regs->pc = elfregs->pc;
325 regs->ps = (elfregs->ps | XCHAL_PS_EXCM_MASK);
326 regs->exccause = elfregs->exccause;
327 regs->excvaddr = elfregs->excvaddr;
328 regs->windowbase = elfregs->windowbase;
329 regs->windowstart = elfregs->windowstart;
330 regs->lbeg = elfregs->lbeg;
331 regs->lend = elfregs->lend;
332 regs->lcount = elfregs->lcount;
333 regs->sar = elfregs->sar;
334 regs->syscall = elfregs->syscall;
335
336 /* Clear everything. */
337
338 memset (regs->areg, 0, sizeof(regs->areg));
339
340 /* Copy regs from live window frame. */
341
342 wb_offset = regs->windowbase * 4;
343 n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
344
345 for (i = 0; i < n; i++)
346 regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
347
348 n = (regs->wmask >> 4) * 4;
349
350 for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
351 regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
352}
353
354/*
355 * do_save_fpregs() gathers information from 'struct pt_regs' and
356 * 'current->thread' to fill in the elf_fpregset_t structure.
357 *
358 * Core files and ptrace use elf_fpregset_t.
359 */
360
361void do_save_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs,
362 struct task_struct *tsk)
363{
364#if XCHAL_HAVE_CP
365
366 extern unsigned char _xtensa_reginfo_tables[];
367 extern unsigned _xtensa_reginfo_table_size;
368 int i;
369 unsigned long flags;
370
371 /* Before dumping coprocessor state from memory,
372 * ensure any live coprocessor contents for this
373 * task are first saved to memory:
374 */
375 local_irq_save(flags);
376
377 for (i = 0; i < XCHAL_CP_MAX; i++) {
378 if (tsk == coprocessor_info[i].owner) {
379 enable_coprocessor(i);
380 save_coprocessor_registers(
381 tsk->thread.cp_save+coprocessor_info[i].offset,i);
382 disable_coprocessor(i);
383 }
384 }
385
386 local_irq_restore(flags);
387
388 /* Now dump coprocessor & extra state: */
389 memcpy((unsigned char*)fpregs,
390 _xtensa_reginfo_tables, _xtensa_reginfo_table_size);
391 memcpy((unsigned char*)fpregs + _xtensa_reginfo_table_size,
392 tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
393#endif
394}
395
396/*
397 * The inverse of do_save_fpregs().
398 * Copies coprocessor and extra state from fpregs into regs and tsk->thread.
399 * Returns 0 on success, non-zero if layout doesn't match.
400 */
401
402int do_restore_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs,
403 struct task_struct *tsk)
404{
405#if XCHAL_HAVE_CP
406
407 extern unsigned char _xtensa_reginfo_tables[];
408 extern unsigned _xtensa_reginfo_table_size;
409 int i;
410 unsigned long flags;
411
412 /* Make sure save area layouts match.
413 * FIXME: in the future we could allow restoring from
414 * a different layout of the same registers, by comparing
415 * fpregs' table with _xtensa_reginfo_tables and matching
416 * entries and copying registers one at a time.
417 * Not too sure yet whether that's very useful.
418 */
419
420 if( memcmp((unsigned char*)fpregs,
421 _xtensa_reginfo_tables, _xtensa_reginfo_table_size) ) {
422 return -1;
423 }
424
425 /* Before restoring coprocessor state from memory,
426 * ensure any live coprocessor contents for this
427 * task are first invalidated.
428 */
429
430 local_irq_save(flags);
431
432 for (i = 0; i < XCHAL_CP_MAX; i++) {
433 if (tsk == coprocessor_info[i].owner) {
434 enable_coprocessor(i);
435 save_coprocessor_registers(
436 tsk->thread.cp_save+coprocessor_info[i].offset,i);
437 coprocessor_info[i].owner = 0;
438 disable_coprocessor(i);
439 }
440 }
441
442 local_irq_restore(flags);
443
444 /* Now restore coprocessor & extra state: */
445
446 memcpy(tsk->thread.cp_save,
447 (unsigned char*)fpregs + _xtensa_reginfo_table_size,
448 XTENSA_CP_EXTRA_SIZE);
449#endif
450 return 0;
451}
452/*
453 * Fill in the CP structure for a core dump for a particular task.
454 */
455
456int
457dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r)
458{
459/* see asm/coprocessor.h for this magic number 16 */
460#if TOTAL_CPEXTRA_SIZE > 16
461 do_save_fpregs (r, regs, task);
462
463 /* For now, bit 16 means some extra state may be present: */
464// FIXME!! need to track to return more accurate mask
465 return 0x10000 | XCHAL_CP_MASK;
466#else
467 return 0; /* no coprocessors active on this processor */
468#endif
469}
470
471/*
472 * Fill in the CP structure for a core dump.
473 * This includes any FPU coprocessor.
474 * Here, we dump all coprocessors, and other ("extra") custom state.
475 *
476 * This function is called by elf_core_dump() in fs/binfmt_elf.c
477 * (in which case 'regs' comes from calls to do_coredump, see signals.c).
478 */
479int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
480{
481 return dump_task_fpu(regs, current, r);
482}
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
new file mode 100644
index 0000000000..9ef07a4dd2
--- /dev/null
+++ b/arch/xtensa/kernel/ptrace.c
@@ -0,0 +1,407 @@
1// TODO some minor issues
2/*
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 2001 - 2005 Tensilica Inc.
8 *
9 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
10 * Chris Zankel <chris@zankel.net>
11 * Scott Foehner<sfoehner@yahoo.com>,
12 * Kevin Chea
13 * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
14 */
15
16#include <linux/config.h>
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/mm.h>
20#include <linux/errno.h>
21#include <linux/ptrace.h>
22#include <linux/smp.h>
23#include <linux/smp_lock.h>
24#include <linux/security.h>
25
26#include <asm/pgtable.h>
27#include <asm/page.h>
28#include <asm/system.h>
29#include <asm/uaccess.h>
30#include <asm/ptrace.h>
31#include <asm/elf.h>
32
33#define TEST_KERNEL // verify kernel operations FIXME: remove
34
35
36/*
37 * Called by kernel/ptrace.c when detaching..
38 *
39 * Make sure single step bits etc are not set.
40 */
41
42void ptrace_disable(struct task_struct *child)
43{
44 /* Nothing to do.. */
45}
46
47int sys_ptrace(long request, long pid, long addr, long data)
48{
49 struct task_struct *child;
50 int ret = -EPERM;
51
52 lock_kernel();
53
54#if 0
55 if ((int)request != 1)
56 printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
57 (int) request, (int) pid, (unsigned long) addr,
58 (unsigned long) data);
59#endif
60
61 if (request == PTRACE_TRACEME) {
62
63 /* Are we already being traced? */
64
65 if (current->ptrace & PT_PTRACED)
66 goto out;
67
68 if ((ret = security_ptrace(current->parent, current)))
69 goto out;
70
71 /* Set the ptrace bit in the process flags. */
72
73 current->ptrace |= PT_PTRACED;
74 ret = 0;
75 goto out;
76 }
77
78 ret = -ESRCH;
79 read_lock(&tasklist_lock);
80 child = find_task_by_pid(pid);
81 if (child)
82 get_task_struct(child);
83 read_unlock(&tasklist_lock);
84 if (!child)
85 goto out;
86
87 ret = -EPERM;
88 if (pid == 1) /* you may not mess with init */
89 goto out;
90
91 if (request == PTRACE_ATTACH) {
92 ret = ptrace_attach(child);
93 goto out_tsk;
94 }
95
96 if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0)
97 goto out_tsk;
98
99 switch (request) {
100 case PTRACE_PEEKTEXT: /* read word at location addr. */
101 case PTRACE_PEEKDATA:
102 {
103 unsigned long tmp;
104 int copied;
105
106 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
107 ret = -EIO;
108 if (copied != sizeof(tmp))
109 break;
110 ret = put_user(tmp,(unsigned long *) data);
111
112 goto out;
113 }
114
115 /* Read the word at location addr in the USER area. */
116
117 case PTRACE_PEEKUSR:
118 {
119 struct pt_regs *regs;
120 unsigned long tmp;
121
122 regs = xtensa_pt_regs(child);
123 tmp = 0; /* Default return value. */
124
125 switch(addr) {
126
127 case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
128 {
129 int ar = addr - REG_AR_BASE - regs->windowbase * 4;
130 ar &= (XCHAL_NUM_AREGS - 1);
131 if (ar < 16 && ar + (regs->wmask >> 4) * 4 >= 0)
132 tmp = regs->areg[ar];
133 else
134 ret = -EIO;
135 break;
136 }
137 case REG_A_BASE ... REG_A_BASE + 15:
138 tmp = regs->areg[addr - REG_A_BASE];
139 break;
140 case REG_PC:
141 tmp = regs->pc;
142 break;
143 case REG_PS:
144 /* Note: PS.EXCM is not set while user task is running;
145 * its being set in regs is for exception handling
146 * convenience. */
147 tmp = (regs->ps & ~XCHAL_PS_EXCM_MASK);
148 break;
149 case REG_WB:
150 tmp = regs->windowbase;
151 break;
152 case REG_WS:
153 tmp = regs->windowstart;
154 break;
155 case REG_LBEG:
156 tmp = regs->lbeg;
157 break;
158 case REG_LEND:
159 tmp = regs->lend;
160 break;
161 case REG_LCOUNT:
162 tmp = regs->lcount;
163 break;
164 case REG_SAR:
165 tmp = regs->sar;
166 break;
167 case REG_DEPC:
168 tmp = regs->depc;
169 break;
170 case REG_EXCCAUSE:
171 tmp = regs->exccause;
172 break;
173 case REG_EXCVADDR:
174 tmp = regs->excvaddr;
175 break;
176 case SYSCALL_NR:
177 tmp = regs->syscall;
178 break;
179 default:
180 tmp = 0;
181 ret = -EIO;
182 goto out;
183 }
184 ret = put_user(tmp, (unsigned long *) data);
185 goto out;
186 }
187
188 case PTRACE_POKETEXT: /* write the word at location addr. */
189 case PTRACE_POKEDATA:
190 if (access_process_vm(child, addr, &data, sizeof(data), 1)
191 == sizeof(data))
192 break;
193 ret = -EIO;
194 goto out;
195
196 case PTRACE_POKEUSR:
197 {
198 struct pt_regs *regs;
199 regs = xtensa_pt_regs(child);
200
201 switch (addr) {
202 case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
203 {
204 int ar = addr - REG_AR_BASE - regs->windowbase * 4;
205 if (ar < 16 && ar + (regs->wmask >> 4) * 4 >= 0)
206 regs->areg[ar & (XCHAL_NUM_AREGS - 1)] = data;
207 else
208 ret = -EIO;
209 break;
210 }
211 case REG_A_BASE ... REG_A_BASE + 15:
212 regs->areg[addr - REG_A_BASE] = data;
213 break;
214 case REG_PC:
215 regs->pc = data;
216 break;
217 case SYSCALL_NR:
218 regs->syscall = data;
219 break;
220#ifdef TEST_KERNEL
221 case REG_WB:
222 regs->windowbase = data;
223 break;
224 case REG_WS:
225 regs->windowstart = data;
226 break;
227#endif
228
229 default:
230 /* The rest are not allowed. */
231 ret = -EIO;
232 break;
233 }
234 break;
235 }
236
237 /* continue and stop at next (return from) syscall */
238 case PTRACE_SYSCALL:
239 case PTRACE_CONT: /* restart after signal. */
240 {
241 ret = -EIO;
242 if ((unsigned long) data > _NSIG)
243 break;
244 if (request == PTRACE_SYSCALL)
245 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
246 else
247 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
248 child->exit_code = data;
249 /* Make sure the single step bit is not set. */
250 child->ptrace &= ~PT_SINGLESTEP;
251 wake_up_process(child);
252 ret = 0;
253 break;
254 }
255
256 /*
257 * make the child exit. Best I can do is send it a sigkill.
258 * perhaps it should be put in the status that it wants to
259 * exit.
260 */
261 case PTRACE_KILL:
262 ret = 0;
263 if (child->state == EXIT_ZOMBIE) /* already dead */
264 break;
265 child->exit_code = SIGKILL;
266 child->ptrace &= ~PT_SINGLESTEP;
267 wake_up_process(child);
268 break;
269
270 case PTRACE_SINGLESTEP:
271 ret = -EIO;
272 if ((unsigned long) data > _NSIG)
273 break;
274 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
275 child->ptrace |= PT_SINGLESTEP;
276 child->exit_code = data;
277 wake_up_process(child);
278 ret = 0;
279 break;
280
281 case PTRACE_GETREGS:
282 {
283 /* 'data' points to user memory in which to write.
284 * Mainly due to the non-live register values, we
285 * reformat the register values into something more
286 * standard. For convenience, we use the handy
287 * elf_gregset_t format. */
288
289 xtensa_gregset_t format;
290 struct pt_regs *regs = xtensa_pt_regs(child);
291
292 do_copy_regs (&format, regs, child);
293
294 /* Now, copy to user space nice and easy... */
295 ret = 0;
296 if (copy_to_user((void *)data, &format, sizeof(elf_gregset_t)))
297 ret = -EFAULT;
298 break;
299 }
300
301 case PTRACE_SETREGS:
302 {
303 /* 'data' points to user memory that contains the new
304 * values in the elf_gregset_t format. */
305
306 xtensa_gregset_t format;
307 struct pt_regs *regs = xtensa_pt_regs(child);
308
309 if (copy_from_user(&format,(void *)data,sizeof(elf_gregset_t))){
310 ret = -EFAULT;
311 break;
312 }
313
314 /* FIXME: Perhaps we want some sanity checks on
315 * these user-space values? See ARM version. Are
316 * debuggers a security concern? */
317
318 do_restore_regs (&format, regs, child);
319
320 ret = 0;
321 break;
322 }
323
324 case PTRACE_GETFPREGS:
325 {
326 /* 'data' points to user memory in which to write.
327 * For convenience, we use the handy
328 * elf_fpregset_t format. */
329
330 elf_fpregset_t fpregs;
331 struct pt_regs *regs = xtensa_pt_regs(child);
332
333 do_save_fpregs (&fpregs, regs, child);
334
335 /* Now, copy to user space nice and easy... */
336 ret = 0;
337 if (copy_to_user((void *)data, &fpregs, sizeof(elf_fpregset_t)))
338 ret = -EFAULT;
339
340 break;
341 }
342
343 case PTRACE_SETFPREGS:
344 {
345 /* 'data' points to user memory that contains the new
346 * values in the elf_fpregset_t format.
347 */
348 elf_fpregset_t fpregs;
349 struct pt_regs *regs = xtensa_pt_regs(child);
350
351 ret = 0;
352 if (copy_from_user(&fpregs, (void *)data, sizeof(elf_fpregset_t))) {
353 ret = -EFAULT;
354 break;
355 }
356
357 if (do_restore_fpregs (&fpregs, regs, child))
358 ret = -EIO;
359 break;
360 }
361
362 case PTRACE_GETFPREGSIZE:
363 /* 'data' points to 'unsigned long' set to the size
364 * of elf_fpregset_t
365 */
366 ret = put_user(sizeof(elf_fpregset_t), (unsigned long *) data);
367 break;
368
369 case PTRACE_DETACH: /* detach a process that was attached. */
370 ret = ptrace_detach(child, data);
371 break;
372
373 default:
374 ret = ptrace_request(child, request, addr, data);
375 goto out;
376 }
377out_tsk:
378 put_task_struct(child);
379out:
380 unlock_kernel();
381 return ret;
382}
383
384void do_syscall_trace(void)
385{
386 if (!test_thread_flag(TIF_SYSCALL_TRACE))
387 return;
388
389 if (!(current->ptrace & PT_PTRACED))
390 return;
391
392 /*
393 * The 0x80 provides a way for the tracing parent to distinguish
394 * between a syscall stop and SIGTRAP delivery
395 */
396 ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
397
398 /*
399 * this isn't the same as continuing with a signal, but it will do
400 * for normal use. strace only continues with a signal if the
401 * stopping signal is not SIGTRAP. -brl
402 */
403 if (current->exit_code) {
404 send_sig(current->exit_code, current, 1);
405 current->exit_code = 0;
406 }
407}
diff --git a/arch/xtensa/kernel/semaphore.c b/arch/xtensa/kernel/semaphore.c
new file mode 100644
index 0000000000..d40f4b1b75
--- /dev/null
+++ b/arch/xtensa/kernel/semaphore.c
@@ -0,0 +1,226 @@
1/*
2 * arch/xtensa/kernel/semaphore.c
3 *
4 * Generic semaphore code. Buyer beware. Do your own specific changes
5 * in <asm/semaphore-helper.h>
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 *
11 * Copyright (C) 2001 - 2005 Tensilica Inc.
12 *
13 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
14 * Chris Zankel <chris@zankel.net>
15 * Marc Gauthier<marc@tensilica.com, marc@alumni.uwaterloo.ca>
16 * Kevin Chea
17 */
18
19#include <linux/sched.h>
20#include <linux/wait.h>
21#include <linux/init.h>
22#include <asm/semaphore.h>
23#include <asm/errno.h>
24
25/*
26 * These two _must_ execute atomically wrt each other.
27 */
28
29static __inline__ void wake_one_more(struct semaphore * sem)
30{
31 atomic_inc((atomic_t *)&sem->sleepers);
32}
33
34static __inline__ int waking_non_zero(struct semaphore *sem)
35{
36 unsigned long flags;
37 int ret = 0;
38
39 spin_lock_irqsave(&semaphore_wake_lock, flags);
40 if (sem->sleepers > 0) {
41 sem->sleepers--;
42 ret = 1;
43 }
44 spin_unlock_irqrestore(&semaphore_wake_lock, flags);
45 return ret;
46}
47
48/*
49 * waking_non_zero_interruptible:
50 * 1 got the lock
51 * 0 go to sleep
52 * -EINTR interrupted
53 *
54 * We must undo the sem->count down_interruptible() increment while we are
55 * protected by the spinlock in order to make atomic this atomic_inc() with the
56 * atomic_read() in wake_one_more(), otherwise we can race. -arca
57 */
58
59static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
60 struct task_struct *tsk)
61{
62 unsigned long flags;
63 int ret = 0;
64
65 spin_lock_irqsave(&semaphore_wake_lock, flags);
66 if (sem->sleepers > 0) {
67 sem->sleepers--;
68 ret = 1;
69 } else if (signal_pending(tsk)) {
70 atomic_inc(&sem->count);
71 ret = -EINTR;
72 }
73 spin_unlock_irqrestore(&semaphore_wake_lock, flags);
74 return ret;
75}
76
77/*
78 * waking_non_zero_trylock:
79 * 1 failed to lock
80 * 0 got the lock
81 *
82 * We must undo the sem->count down_trylock() increment while we are
83 * protected by the spinlock in order to make atomic this atomic_inc() with the
84 * atomic_read() in wake_one_more(), otherwise we can race. -arca
85 */
86
87static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
88{
89 unsigned long flags;
90 int ret = 1;
91
92 spin_lock_irqsave(&semaphore_wake_lock, flags);
93 if (sem->sleepers <= 0)
94 atomic_inc(&sem->count);
95 else {
96 sem->sleepers--;
97 ret = 0;
98 }
99 spin_unlock_irqrestore(&semaphore_wake_lock, flags);
100 return ret;
101}
102
103spinlock_t semaphore_wake_lock;
104
105/*
106 * Semaphores are implemented using a two-way counter:
107 * The "count" variable is decremented for each process
108 * that tries to sleep, while the "waking" variable is
109 * incremented when the "up()" code goes to wake up waiting
110 * processes.
111 *
112 * Notably, the inline "up()" and "down()" functions can
113 * efficiently test if they need to do any extra work (up
114 * needs to do something only if count was negative before
115 * the increment operation.
116 *
117 * waking_non_zero() (from asm/semaphore.h) must execute
118 * atomically.
119 *
120 * When __up() is called, the count was negative before
121 * incrementing it, and we need to wake up somebody.
122 *
123 * This routine adds one to the count of processes that need to
124 * wake up and exit. ALL waiting processes actually wake up but
125 * only the one that gets to the "waking" field first will gate
126 * through and acquire the semaphore. The others will go back
127 * to sleep.
128 *
129 * Note that these functions are only called when there is
130 * contention on the lock, and as such all this is the
131 * "non-critical" part of the whole semaphore business. The
132 * critical part is the inline stuff in <asm/semaphore.h>
133 * where we want to avoid any extra jumps and calls.
134 */
135
136void __up(struct semaphore *sem)
137{
138 wake_one_more(sem);
139 wake_up(&sem->wait);
140}
141
142/*
143 * Perform the "down" function. Return zero for semaphore acquired,
144 * return negative for signalled out of the function.
145 *
146 * If called from __down, the return is ignored and the wait loop is
147 * not interruptible. This means that a task waiting on a semaphore
148 * using "down()" cannot be killed until someone does an "up()" on
149 * the semaphore.
150 *
151 * If called from __down_interruptible, the return value gets checked
152 * upon return. If the return value is negative then the task continues
153 * with the negative value in the return register (it can be tested by
154 * the caller).
155 *
156 * Either form may be used in conjunction with "up()".
157 *
158 */
159
160#define DOWN_VAR \
161 struct task_struct *tsk = current; \
162 wait_queue_t wait; \
163 init_waitqueue_entry(&wait, tsk);
164
165#define DOWN_HEAD(task_state) \
166 \
167 \
168 tsk->state = (task_state); \
169 add_wait_queue(&sem->wait, &wait); \
170 \
171 /* \
172 * Ok, we're set up. sem->count is known to be less than zero \
173 * so we must wait. \
174 * \
175 * We can let go the lock for purposes of waiting. \
176 * We re-acquire it after awaking so as to protect \
177 * all semaphore operations. \
178 * \
179 * If "up()" is called before we call waking_non_zero() then \
180 * we will catch it right away. If it is called later then \
181 * we will have to go through a wakeup cycle to catch it. \
182 * \
183 * Multiple waiters contend for the semaphore lock to see \
184 * who gets to gate through and who has to wait some more. \
185 */ \
186 for (;;) {
187
188#define DOWN_TAIL(task_state) \
189 tsk->state = (task_state); \
190 } \
191 tsk->state = TASK_RUNNING; \
192 remove_wait_queue(&sem->wait, &wait);
193
194void __sched __down(struct semaphore * sem)
195{
196 DOWN_VAR
197 DOWN_HEAD(TASK_UNINTERRUPTIBLE)
198 if (waking_non_zero(sem))
199 break;
200 schedule();
201 DOWN_TAIL(TASK_UNINTERRUPTIBLE)
202}
203
204int __sched __down_interruptible(struct semaphore * sem)
205{
206 int ret = 0;
207 DOWN_VAR
208 DOWN_HEAD(TASK_INTERRUPTIBLE)
209
210 ret = waking_non_zero_interruptible(sem, tsk);
211 if (ret)
212 {
213 if (ret == 1)
214 /* ret != 0 only if we get interrupted -arca */
215 ret = 0;
216 break;
217 }
218 schedule();
219 DOWN_TAIL(TASK_INTERRUPTIBLE)
220 return ret;
221}
222
223int __down_trylock(struct semaphore * sem)
224{
225 return waking_non_zero_trylock(sem);
226}
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
new file mode 100644
index 0000000000..1f5bf5d624
--- /dev/null
+++ b/arch/xtensa/kernel/setup.c
@@ -0,0 +1,520 @@
1/*
2 * arch/xtensa/setup.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1995 Linus Torvalds
9 * Copyright (C) 2001 - 2005 Tensilica Inc.
10 *
11 * Chris Zankel <chris@zankel.net>
12 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
13 * Kevin Chea
14 * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
15 */
16
17#include <linux/config.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/proc_fs.h>
21#include <linux/tty.h>
22#include <linux/bootmem.h>
23#include <linux/kernel.h>
24
25#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
26# include <linux/console.h>
27#endif
28
29#ifdef CONFIG_RTC
30# include <linux/timex.h>
31#endif
32
33#ifdef CONFIG_PROC_FS
34# include <linux/seq_file.h>
35#endif
36
37#include <asm/system.h>
38#include <asm/bootparam.h>
39#include <asm/pgtable.h>
40#include <asm/processor.h>
41#include <asm/timex.h>
42#include <asm/platform.h>
43#include <asm/page.h>
44#include <asm/setup.h>
45
46#include <xtensa/config/system.h>
47
48#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
49struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
50#endif
51
52#ifdef CONFIG_BLK_DEV_FD
53extern struct fd_ops no_fd_ops;
54struct fd_ops *fd_ops;
55#endif
56
57#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
58extern struct ide_ops no_ide_ops;
59struct ide_ops *ide_ops;
60#endif
61
62extern struct rtc_ops no_rtc_ops;
63struct rtc_ops *rtc_ops;
64
65#ifdef CONFIG_PC_KEYB
66extern struct kbd_ops no_kbd_ops;
67struct kbd_ops *kbd_ops;
68#endif
69
70#ifdef CONFIG_BLK_DEV_INITRD
71extern void *initrd_start;
72extern void *initrd_end;
73extern void *__initrd_start;
74extern void *__initrd_end;
75int initrd_is_mapped = 0;
76extern int initrd_below_start_ok;
77#endif
78
79unsigned char aux_device_present;
80extern unsigned long loops_per_jiffy;
81
82/* Command line specified as configuration option. */
83
84static char command_line[COMMAND_LINE_SIZE];
85
86#ifdef CONFIG_CMDLINE_BOOL
87static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
88#endif
89
90sysmem_info_t __initdata sysmem;
91
92#ifdef CONFIG_BLK_DEV_INITRD
93int initrd_is_mapped;
94#endif
95
96extern void init_mmu(void);
97
98/*
99 * Boot parameter parsing.
100 *
101 * The Xtensa port uses a list of variable-sized tags to pass data to
102 * the kernel. The first tag must be a BP_TAG_FIRST tag for the list
103 * to be recognised. The list is terminated with a zero-sized
104 * BP_TAG_LAST tag.
105 */
106
107typedef struct tagtable {
108 u32 tag;
109 int (*parse)(const bp_tag_t*);
110} tagtable_t;
111
112#define __tagtable(tag, fn) static tagtable_t __tagtable_##fn \
113 __attribute__((unused, __section__(".taglist"))) = { tag, fn }
114
115/* parse current tag */
116
117static int __init parse_tag_mem(const bp_tag_t *tag)
118{
119 meminfo_t *mi = (meminfo_t*)(tag->data);
120
121 if (mi->type != MEMORY_TYPE_CONVENTIONAL)
122 return -1;
123
124 if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
125 printk(KERN_WARNING
126 "Ignoring memory bank 0x%08lx size %ldKB\n",
127 (unsigned long)mi->start,
128 (unsigned long)mi->end - (unsigned long)mi->start);
129 return -EINVAL;
130 }
131 sysmem.bank[sysmem.nr_banks].type = mi->type;
132 sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
133 sysmem.bank[sysmem.nr_banks].end = mi->end & PAGE_SIZE;
134 sysmem.nr_banks++;
135
136 return 0;
137}
138
139__tagtable(BP_TAG_MEMORY, parse_tag_mem);
140
141#ifdef CONFIG_BLK_DEV_INITRD
142
143static int __init parse_tag_initrd(const bp_tag_t* tag)
144{
145 meminfo_t* mi;
146 mi = (meminfo_t*)(tag->data);
147 initrd_start = (void*)(mi->start);
148 initrd_end = (void*)(mi->end);
149
150 return 0;
151}
152
153__tagtable(BP_TAG_INITRD, parse_tag_initrd);
154
155#endif /* CONFIG_BLK_DEV_INITRD */
156
157static int __init parse_tag_cmdline(const bp_tag_t* tag)
158{
159 strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE);
160 command_line[COMMAND_LINE_SIZE - 1] = '\0';
161 return 0;
162}
163
164__tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline);
165
166static int __init parse_bootparam(const bp_tag_t* tag)
167{
168 extern tagtable_t __tagtable_begin, __tagtable_end;
169 tagtable_t *t;
170
171 /* Boot parameters must start with a BP_TAG_FIRST tag. */
172
173 if (tag->id != BP_TAG_FIRST) {
174 printk(KERN_WARNING "Invalid boot parameters!\n");
175 return 0;
176 }
177
178 tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size);
179
180 /* Parse all tags. */
181
182 while (tag != NULL && tag->id != BP_TAG_LAST) {
183 for (t = &__tagtable_begin; t < &__tagtable_end; t++) {
184 if (tag->id == t->tag) {
185 t->parse(tag);
186 break;
187 }
188 }
189 if (t == &__tagtable_end)
190 printk(KERN_WARNING "Ignoring tag "
191 "0x%08x\n", tag->id);
192 tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size);
193 }
194
195 return 0;
196}
197
198/*
199 * Initialize architecture. (Early stage)
200 */
201
202void __init init_arch(bp_tag_t *bp_start)
203{
204
205#ifdef CONFIG_BLK_DEV_INITRD
206 initrd_start = &__initrd_start;
207 initrd_end = &__initrd_end;
208#endif
209
210 sysmem.nr_banks = 0;
211
212#ifdef CONFIG_CMDLINE_BOOL
213 strcpy(command_line, default_command_line);
214#endif
215
216 /* Parse boot parameters */
217
218 if (bp_start)
219 parse_bootparam(bp_start);
220
221 if (sysmem.nr_banks == 0) {
222 sysmem.nr_banks = 1;
223 sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
224 sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
225 + PLATFORM_DEFAULT_MEM_SIZE;
226 }
227
228 /* Early hook for platforms */
229
230 platform_init(bp_start);
231
232 /* Initialize MMU. */
233
234 init_mmu();
235}
236
237/*
238 * Initialize system. Setup memory and reserve regions.
239 */
240
241extern char _end;
242extern char _stext;
243extern char _WindowVectors_text_start;
244extern char _WindowVectors_text_end;
245extern char _DebugInterruptVector_literal_start;
246extern char _DebugInterruptVector_text_end;
247extern char _KernelExceptionVector_literal_start;
248extern char _KernelExceptionVector_text_end;
249extern char _UserExceptionVector_literal_start;
250extern char _UserExceptionVector_text_end;
251extern char _DoubleExceptionVector_literal_start;
252extern char _DoubleExceptionVector_text_end;
253
254void __init setup_arch(char **cmdline_p)
255{
256 extern int mem_reserve(unsigned long, unsigned long, int);
257 extern void bootmem_init(void);
258
259 memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
260 saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
261 *cmdline_p = command_line;
262
263 /* Reserve some memory regions */
264
265#ifdef CONFIG_BLK_DEV_INITRD
266 if (initrd_start < initrd_end) {
267 initrd_is_mapped = mem_reserve(__pa(initrd_start),
268 __pa(initrd_end), 0);
269 initrd_below_start_ok = 1;
270 } else {
271 initrd_start = 0;
272 }
273#endif
274
275 mem_reserve(__pa(&_stext),__pa(&_end), 1);
276
277 mem_reserve(__pa(&_WindowVectors_text_start),
278 __pa(&_WindowVectors_text_end), 0);
279
280 mem_reserve(__pa(&_DebugInterruptVector_literal_start),
281 __pa(&_DebugInterruptVector_text_end), 0);
282
283 mem_reserve(__pa(&_KernelExceptionVector_literal_start),
284 __pa(&_KernelExceptionVector_text_end), 0);
285
286 mem_reserve(__pa(&_UserExceptionVector_literal_start),
287 __pa(&_UserExceptionVector_text_end), 0);
288
289 mem_reserve(__pa(&_DoubleExceptionVector_literal_start),
290 __pa(&_DoubleExceptionVector_text_end), 0);
291
292 bootmem_init();
293
294 platform_setup(cmdline_p);
295
296
297 paging_init();
298
299#ifdef CONFIG_VT
300# if defined(CONFIG_VGA_CONSOLE)
301 conswitchp = &vga_con;
302# elif defined(CONFIG_DUMMY_CONSOLE)
303 conswitchp = &dummy_con;
304# endif
305#endif
306
307#if CONFIG_PCI
308 platform_pcibios_init();
309#endif
310}
311
312void machine_restart(char * cmd)
313{
314 platform_restart();
315}
316
317void machine_halt(void)
318{
319 platform_halt();
320 while (1);
321}
322
323void machine_power_off(void)
324{
325 platform_power_off();
326 while (1);
327}
328#ifdef CONFIG_PROC_FS
329
330/*
331 * Display some core information through /proc/cpuinfo.
332 */
333
334static int
335c_show(struct seq_file *f, void *slot)
336{
337 /* high-level stuff */
338 seq_printf(f,"processor\t: 0\n"
339 "vendor_id\t: Tensilica\n"
340 "model\t\t: Xtensa " XCHAL_HW_RELEASE_NAME "\n"
341 "core ID\t\t: " XCHAL_CORE_ID "\n"
342 "build ID\t: 0x%x\n"
343 "byte order\t: %s\n"
344 "cpu MHz\t\t: %lu.%02lu\n"
345 "bogomips\t: %lu.%02lu\n",
346 XCHAL_BUILD_UNIQUE_ID,
347 XCHAL_HAVE_BE ? "big" : "little",
348 CCOUNT_PER_JIFFY/(1000000/HZ),
349 (CCOUNT_PER_JIFFY/(10000/HZ)) % 100,
350 loops_per_jiffy/(500000/HZ),
351 (loops_per_jiffy/(5000/HZ)) % 100);
352
353 seq_printf(f,"flags\t\t: "
354#if XCHAL_HAVE_NMI
355 "nmi "
356#endif
357#if XCHAL_HAVE_DEBUG
358 "debug "
359# if XCHAL_HAVE_OCD
360 "ocd "
361# endif
362#endif
363#if XCHAL_HAVE_DENSITY
364 "density "
365#endif
366#if XCHAL_HAVE_BOOLEANS
367 "boolean "
368#endif
369#if XCHAL_HAVE_LOOPS
370 "loop "
371#endif
372#if XCHAL_HAVE_NSA
373 "nsa "
374#endif
375#if XCHAL_HAVE_MINMAX
376 "minmax "
377#endif
378#if XCHAL_HAVE_SEXT
379 "sext "
380#endif
381#if XCHAL_HAVE_CLAMPS
382 "clamps "
383#endif
384#if XCHAL_HAVE_MAC16
385 "mac16 "
386#endif
387#if XCHAL_HAVE_MUL16
388 "mul16 "
389#endif
390#if XCHAL_HAVE_MUL32
391 "mul32 "
392#endif
393#if XCHAL_HAVE_MUL32_HIGH
394 "mul32h "
395#endif
396#if XCHAL_HAVE_FP
397 "fpu "
398#endif
399 "\n");
400
401 /* Registers. */
402 seq_printf(f,"physical aregs\t: %d\n"
403 "misc regs\t: %d\n"
404 "ibreak\t\t: %d\n"
405 "dbreak\t\t: %d\n",
406 XCHAL_NUM_AREGS,
407 XCHAL_NUM_MISC_REGS,
408 XCHAL_NUM_IBREAK,
409 XCHAL_NUM_DBREAK);
410
411
412 /* Interrupt. */
413 seq_printf(f,"num ints\t: %d\n"
414 "ext ints\t: %d\n"
415 "int levels\t: %d\n"
416 "timers\t\t: %d\n"
417 "debug level\t: %d\n",
418 XCHAL_NUM_INTERRUPTS,
419 XCHAL_NUM_EXTINTERRUPTS,
420 XCHAL_NUM_INTLEVELS,
421 XCHAL_NUM_TIMERS,
422 XCHAL_DEBUGLEVEL);
423
424 /* Coprocessors */
425#if XCHAL_HAVE_CP
426 seq_printf(f, "coprocessors\t: %d\n", XCHAL_CP_NUM);
427#else
428 seq_printf(f, "coprocessors\t: none\n");
429#endif
430
431 /* {I,D}{RAM,ROM} and XLMI */
432 seq_printf(f,"inst ROMs\t: %d\n"
433 "inst RAMs\t: %d\n"
434 "data ROMs\t: %d\n"
435 "data RAMs\t: %d\n"
436 "XLMI ports\t: %d\n",
437 XCHAL_NUM_IROM,
438 XCHAL_NUM_IRAM,
439 XCHAL_NUM_DROM,
440 XCHAL_NUM_DRAM,
441 XCHAL_NUM_XLMI);
442
443 /* Cache */
444 seq_printf(f,"icache line size: %d\n"
445 "icache ways\t: %d\n"
446 "icache size\t: %d\n"
447 "icache flags\t: "
448#if XCHAL_ICACHE_LINE_LOCKABLE
449 "lock"
450#endif
451 "\n"
452 "dcache line size: %d\n"
453 "dcache ways\t: %d\n"
454 "dcache size\t: %d\n"
455 "dcache flags\t: "
456#if XCHAL_DCACHE_IS_WRITEBACK
457 "writeback"
458#endif
459#if XCHAL_DCACHE_LINE_LOCKABLE
460 "lock"
461#endif
462 "\n",
463 XCHAL_ICACHE_LINESIZE,
464 XCHAL_ICACHE_WAYS,
465 XCHAL_ICACHE_SIZE,
466 XCHAL_DCACHE_LINESIZE,
467 XCHAL_DCACHE_WAYS,
468 XCHAL_DCACHE_SIZE);
469
470 /* MMU */
471 seq_printf(f,"ASID bits\t: %d\n"
472 "ASID invalid\t: %d\n"
473 "ASID kernel\t: %d\n"
474 "rings\t\t: %d\n"
475 "itlb ways\t: %d\n"
476 "itlb AR ways\t: %d\n"
477 "dtlb ways\t: %d\n"
478 "dtlb AR ways\t: %d\n",
479 XCHAL_MMU_ASID_BITS,
480 XCHAL_MMU_ASID_INVALID,
481 XCHAL_MMU_ASID_KERNEL,
482 XCHAL_MMU_RINGS,
483 XCHAL_ITLB_WAYS,
484 XCHAL_ITLB_ARF_WAYS,
485 XCHAL_DTLB_WAYS,
486 XCHAL_DTLB_ARF_WAYS);
487
488 return 0;
489}
490
491/*
492 * We show only CPU #0 info.
493 */
494static void *
495c_start(struct seq_file *f, loff_t *pos)
496{
497 return (void *) ((*pos == 0) ? (void *)1 : NULL);
498}
499
500static void *
501c_next(struct seq_file *f, void *v, loff_t *pos)
502{
503 return NULL;
504}
505
506static void
507c_stop(struct seq_file *f, void *v)
508{
509}
510
511struct seq_operations cpuinfo_op =
512{
513 start: c_start,
514 next: c_next,
515 stop: c_stop,
516 show: c_show
517};
518
519#endif /* CONFIG_PROC_FS */
520
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
new file mode 100644
index 0000000000..df6e1e17b0
--- /dev/null
+++ b/arch/xtensa/kernel/signal.c
@@ -0,0 +1,713 @@
1// TODO coprocessor stuff
2/*
3 * linux/arch/xtensa/kernel/signal.c
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
7 *
8 * Joe Taylor <joe@tensilica.com>
9 * Chris Zankel <chris@zankel.net>
10 *
11 *
12 *
13 */
14
15#include <xtensa/config/core.h>
16#include <xtensa/hal.h>
17#include <linux/sched.h>
18#include <linux/mm.h>
19#include <linux/smp.h>
20#include <linux/smp_lock.h>
21#include <linux/kernel.h>
22#include <linux/signal.h>
23#include <linux/errno.h>
24#include <linux/wait.h>
25#include <linux/ptrace.h>
26#include <linux/unistd.h>
27#include <linux/stddef.h>
28#include <linux/personality.h>
29#include <asm/ucontext.h>
30#include <asm/uaccess.h>
31#include <asm/pgtable.h>
32#include <asm/cacheflush.h>
33
34#define DEBUG_SIG 0
35
36#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
37
38asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options,
39 struct rusage * ru);
40asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
41
42extern struct task_struct *coproc_owners[];
43
44
45/*
46 * Atomically swap in the new signal mask, and wait for a signal.
47 */
48
49int sys_sigsuspend(struct pt_regs *regs)
50{
51 old_sigset_t mask = (old_sigset_t) regs->areg[3];
52 sigset_t saveset;
53
54 mask &= _BLOCKABLE;
55 spin_lock_irq(&current->sighand->siglock);
56 saveset = current->blocked;
57 siginitset(&current->blocked, mask);
58 recalc_sigpending();
59 spin_unlock_irq(&current->sighand->siglock);
60
61 regs->areg[2] = -EINTR;
62 while (1) {
63 current->state = TASK_INTERRUPTIBLE;
64 schedule();
65 if (do_signal(regs, &saveset))
66 return -EINTR;
67 }
68}
69
70asmlinkage int
71sys_rt_sigsuspend(struct pt_regs *regs)
72{
73 sigset_t *unewset = (sigset_t *) regs->areg[4];
74 size_t sigsetsize = (size_t) regs->areg[3];
75 sigset_t saveset, newset;
76 /* XXX: Don't preclude handling different sized sigset_t's. */
77 if (sigsetsize != sizeof(sigset_t))
78 return -EINVAL;
79
80 if (copy_from_user(&newset, unewset, sizeof(newset)))
81 return -EFAULT;
82 sigdelsetmask(&newset, ~_BLOCKABLE);
83 spin_lock_irq(&current->sighand->siglock);
84 saveset = current->blocked;
85 current->blocked = newset;
86 recalc_sigpending();
87 spin_unlock_irq(&current->sighand->siglock);
88
89 regs->areg[2] = -EINTR;
90 while (1) {
91 current->state = TASK_INTERRUPTIBLE;
92 schedule();
93 if (do_signal(regs, &saveset))
94 return -EINTR;
95 }
96}
97
98asmlinkage int
99sys_sigaction(int sig, const struct old_sigaction *act,
100 struct old_sigaction *oact)
101{
102 struct k_sigaction new_ka, old_ka;
103 int ret;
104
105 if (act) {
106 old_sigset_t mask;
107 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
108 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
109 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
110 return -EFAULT;
111 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
112 __get_user(mask, &act->sa_mask);
113 siginitset(&new_ka.sa.sa_mask, mask);
114 }
115
116 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
117
118 if (!ret && oact) {
119 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
120 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
121 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
122 return -EFAULT;
123 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
124 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
125 }
126
127 return ret;
128}
129
130asmlinkage int
131sys_sigaltstack(struct pt_regs *regs)
132{
133 const stack_t *uss = (stack_t *) regs->areg[4];
134 stack_t *uoss = (stack_t *) regs->areg[3];
135
136 if (regs->depc > 64)
137 panic ("Double exception sys_sigreturn\n");
138
139
140 return do_sigaltstack(uss, uoss, regs->areg[1]);
141}
142
143
144/*
145 * Do a signal return; undo the signal stack.
146 */
147
148struct sigframe
149{
150 struct sigcontext sc;
151 struct _cpstate cpstate;
152 unsigned long extramask[_NSIG_WORDS-1];
153 unsigned char retcode[6];
154 unsigned int reserved[4]; /* Reserved area for chaining */
155 unsigned int window[4]; /* Window of 4 registers for initial context */
156};
157
158struct rt_sigframe
159{
160 struct siginfo info;
161 struct ucontext uc;
162 struct _cpstate cpstate;
163 unsigned char retcode[6];
164 unsigned int reserved[4]; /* Reserved area for chaining */
165 unsigned int window[4]; /* Window of 4 registers for initial context */
166};
167
168extern void release_all_cp (struct task_struct *);
169
170
171// FIXME restore_cpextra
172static inline int
173restore_cpextra (struct _cpstate *buf)
174{
175#if 0
176 /* The signal handler may have used coprocessors in which
177 * case they are still enabled. We disable them to force a
178 * reloading of the original task's CP state by the lazy
179 * context-switching mechanisms of CP exception handling.
180 * Also, we essentially discard any coprocessor state that the
181 * signal handler created. */
182
183 struct task_struct *tsk = current;
184 release_all_cp(tsk);
185 return __copy_from_user(tsk->thread.cpextra, buf, TOTAL_CPEXTRA_SIZE);
186#endif
187 return 0;
188}
189
190/* Note: We don't copy double exception 'tregs', we have to finish double exc. first before we return to signal handler! This dbl.exc.handler might cause another double exception, but I think we are fine as the situation is the same as if we had returned to the signal handerl and got an interrupt immediately...
191 */
192
193
194static int
195restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
196{
197 struct thread_struct *thread;
198 unsigned int err = 0;
199 unsigned long ps;
200 struct _cpstate *buf;
201
202#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
203 COPY(pc);
204 COPY(depc);
205 COPY(wmask);
206 COPY(lbeg);
207 COPY(lend);
208 COPY(lcount);
209 COPY(sar);
210 COPY(windowbase);
211 COPY(windowstart);
212#undef COPY
213
214 /* For PS, restore only PS.CALLINC.
215 * Assume that all other bits are either the same as for the signal
216 * handler, or the user mode value doesn't matter (e.g. PS.OWB).
217 */
218 err |= __get_user(ps, &sc->sc_ps);
219 regs->ps = (regs->ps & ~XCHAL_PS_CALLINC_MASK)
220 | (ps & XCHAL_PS_CALLINC_MASK);
221
222 /* Additional corruption checks */
223
224 if ((regs->windowbase >= (XCHAL_NUM_AREGS/4))
225 || ((regs->windowstart & ~((1<<(XCHAL_NUM_AREGS/4)) - 1)) != 0) )
226 err = 1;
227 if ((regs->lcount > 0)
228 && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
229 err = 1;
230
231 /* Restore extended register state.
232 * See struct thread_struct in processor.h.
233 */
234 thread = &current->thread;
235
236 err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4);
237 err |= __get_user(buf, &sc->sc_cpstate);
238 if (buf) {
239 if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
240 goto badframe;
241 err |= restore_cpextra(buf);
242 }
243
244 regs->syscall = -1; /* disable syscall checks */
245 return err;
246
247badframe:
248 return 1;
249}
250
251static inline void
252flush_my_cpstate(struct task_struct *tsk)
253{
254 unsigned long flags;
255 local_irq_save(flags);
256
257#if 0 // FIXME
258 for (i = 0; i < XCHAL_CP_NUM; i++) {
259 if (tsk == coproc_owners[i]) {
260 xthal_validate_cp(i);
261 xthal_save_cpregs(tsk->thread.cpregs_ptr[i], i);
262
263 /* Invalidate and "disown" the cp to allow
264 * callers the chance to reset cp state in the
265 * task_struct. */
266
267 xthal_invalidate_cp(i);
268 coproc_owners[i] = 0;
269 }
270 }
271#endif
272 local_irq_restore(flags);
273}
274
275/* Return codes:
276 0: nothing saved
277 1: stuff to save, successful
278 -1: stuff to save, error happened
279*/
280static int
281save_cpextra (struct _cpstate *buf)
282{
283#if (XCHAL_EXTRA_SA_SIZE == 0) && (XCHAL_CP_NUM == 0)
284 return 0;
285#else
286
287 /* FIXME: If a task has never used a coprocessor, there is
288 * no need to save and restore anything. Tracking this
289 * information would allow us to optimize this section.
290 * Perhaps we can use current->used_math or (current->flags &
291 * PF_USEDFPU) or define a new field in the thread
292 * structure. */
293
294 /* We flush any live, task-owned cp state to the task_struct,
295 * then copy it all to the sigframe. Then we clear all
296 * cp/extra state in the task_struct, effectively
297 * clearing/resetting all cp/extra state for the signal
298 * handler (cp-exception handling will load these new values
299 * into the cp/extra registers.) This step is important for
300 * things like a floating-point cp, where the OS must reset
301 * the FCR to the default rounding mode. */
302
303 int err = 0;
304 struct task_struct *tsk = current;
305
306 flush_my_cpstate(tsk);
307 /* Note that we just copy everything: 'extra' and 'cp' state together.*/
308 err |= __copy_to_user(buf, tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
309 memset(tsk->thread.cp_save, 0, XTENSA_CP_EXTRA_SIZE);
310
311#if (XTENSA_CP_EXTRA_SIZE == 0)
312#error Sanity check on memset above, cpextra_size should not be zero.
313#endif
314
315 return err ? -1 : 1;
316#endif
317}
318
319static int
320setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
321 struct pt_regs *regs, unsigned long mask)
322{
323 struct thread_struct *thread;
324 int err = 0;
325
326//printk("setup_sigcontext\n");
327#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
328 COPY(pc);
329 COPY(ps);
330 COPY(depc);
331 COPY(wmask);
332 COPY(lbeg);
333 COPY(lend);
334 COPY(lcount);
335 COPY(sar);
336 COPY(windowbase);
337 COPY(windowstart);
338#undef COPY
339
340 /* Save extended register state.
341 * See struct thread_struct in processor.h.
342 */
343 thread = &current->thread;
344 err |= __copy_to_user (sc->sc_areg, regs->areg, XCHAL_NUM_AREGS * 4);
345 err |= save_cpextra(cpstate);
346 err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate);
347 /* non-iBCS2 extensions.. */
348 err |= __put_user(mask, &sc->oldmask);
349
350 return err;
351}
352
353asmlinkage int sys_sigreturn(struct pt_regs *regs)
354{
355 struct sigframe *frame = (struct sigframe *)regs->areg[1];
356 sigset_t set;
357 if (regs->depc > 64)
358 panic ("Double exception sys_sigreturn\n");
359
360 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
361 goto badframe;
362
363 if (__get_user(set.sig[0], &frame->sc.oldmask)
364 || (_NSIG_WORDS > 1
365 && __copy_from_user(&set.sig[1], &frame->extramask,
366 sizeof(frame->extramask))))
367 goto badframe;
368
369 sigdelsetmask(&set, ~_BLOCKABLE);
370
371 spin_lock_irq(&current->sighand->siglock);
372 current->blocked = set;
373 recalc_sigpending();
374 spin_unlock_irq(&current->sighand->siglock);
375
376 if (restore_sigcontext(regs, &frame->sc))
377 goto badframe;
378 return regs->areg[2];
379
380badframe:
381 force_sig(SIGSEGV, current);
382 return 0;
383}
384
385asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
386{
387 struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
388 sigset_t set;
389 stack_t st;
390 int ret;
391 if (regs->depc > 64)
392 {
393 printk("!!!!!!! DEPC !!!!!!!\n");
394 return 0;
395 }
396
397 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
398 goto badframe;
399
400 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
401 goto badframe;
402
403 sigdelsetmask(&set, ~_BLOCKABLE);
404 spin_lock_irq(&current->sighand->siglock);
405 current->blocked = set;
406 recalc_sigpending();
407 spin_unlock_irq(&current->sighand->siglock);
408
409 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
410 goto badframe;
411 ret = regs->areg[2];
412
413 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
414 goto badframe;
415 /* It is more difficult to avoid calling this function than to
416 call it and ignore errors. */
417 do_sigaltstack(&st, NULL, regs->areg[1]);
418
419 return ret;
420
421badframe:
422 force_sig(SIGSEGV, current);
423 return 0;
424}
425
426/*
427 * Set up a signal frame.
428 */
429
430/*
431 * Determine which stack to use..
432 */
433static inline void *
434get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
435{
436 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
437 sp = current->sas_ss_sp + current->sas_ss_size;
438
439 return (void *)((sp - frame_size) & -16ul);
440}
441
442#define USE_SIGRETURN 0
443#define USE_RT_SIGRETURN 1
444
445static int
446gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
447{
448 unsigned int retcall;
449 int err = 0;
450
451#if 0
452 /* Ignoring SA_RESTORER for now; it's supposed to be obsolete,
453 * and the xtensa glibc doesn't use it.
454 */
455 if (ka->sa.sa_flags & SA_RESTORER) {
456 regs->pr = (unsigned long) ka->sa.sa_restorer;
457 } else
458#endif /* 0 */
459 {
460
461#if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255)
462
463/* The 12-bit immediate is really split up within the 24-bit MOVI
464 * instruction. As long as the above system call numbers fit within
465 * 8-bits, the following code works fine. See the Xtensa ISA for
466 * details.
467 */
468
469#error Generating the MOVI instruction below breaks!
470#endif
471
472 retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn;
473
474#ifdef __XTENSA_EB__ /* Big Endian version */
475 /* Generate instruction: MOVI a2, retcall */
476 err |= __put_user(0x22, &codemem[0]);
477 err |= __put_user(0x0a, &codemem[1]);
478 err |= __put_user(retcall, &codemem[2]);
479 /* Generate instruction: SYSCALL */
480 err |= __put_user(0x00, &codemem[3]);
481 err |= __put_user(0x05, &codemem[4]);
482 err |= __put_user(0x00, &codemem[5]);
483
484#elif defined __XTENSA_EL__ /* Little Endian version */
485 /* Generate instruction: MOVI a2, retcall */
486 err |= __put_user(0x22, &codemem[0]);
487 err |= __put_user(0xa0, &codemem[1]);
488 err |= __put_user(retcall, &codemem[2]);
489 /* Generate instruction: SYSCALL */
490 err |= __put_user(0x00, &codemem[3]);
491 err |= __put_user(0x50, &codemem[4]);
492 err |= __put_user(0x00, &codemem[5]);
493#else
494#error Must use compiler for Xtensa processors.
495#endif
496 }
497
498 /* Flush generated code out of the data cache */
499
500 if (err == 0)
501 __flush_invalidate_cache_range((unsigned long)codemem, 6UL);
502
503 return err;
504}
505
506static void
507set_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr,
508 void *handler, unsigned long arg1, void *arg2, void *arg3)
509{
510 /* Set up registers for signal handler */
511 start_thread(regs, (unsigned long) handler, (unsigned long) stack);
512
513 /* Set up a stack frame for a call4
514 * Note: PS.CALLINC is set to one by start_thread
515 */
516 regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000;
517 regs->areg[6] = arg1;
518 regs->areg[7] = (unsigned long) arg2;
519 regs->areg[8] = (unsigned long) arg3;
520}
521
522static void setup_frame(int sig, struct k_sigaction *ka,
523 sigset_t *set, struct pt_regs *regs)
524{
525 struct sigframe *frame;
526 int err = 0;
527 int signal;
528
529 frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
530 if (regs->depc > 64)
531 {
532 printk("!!!!!!! DEPC !!!!!!!\n");
533 return;
534 }
535
536
537 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
538 goto give_sigsegv;
539
540 signal = current_thread_info()->exec_domain
541 && current_thread_info()->exec_domain->signal_invmap
542 && sig < 32
543 ? current_thread_info()->exec_domain->signal_invmap[sig]
544 : sig;
545
546 err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]);
547
548 if (_NSIG_WORDS > 1) {
549 err |= __copy_to_user(frame->extramask, &set->sig[1],
550 sizeof(frame->extramask));
551 }
552
553 /* Create sys_sigreturn syscall in stack frame */
554 err |= gen_return_code(frame->retcode, USE_SIGRETURN);
555
556 if (err)
557 goto give_sigsegv;
558
559 /* Create signal handler execution context.
560 * Return context not modified until this point.
561 */
562 set_thread_state(regs, frame, frame->retcode,
563 ka->sa.sa_handler, signal, &frame->sc, NULL);
564
565 /* Set access mode to USER_DS. Nomenclature is outdated, but
566 * functionality is used in uaccess.h
567 */
568 set_fs(USER_DS);
569
570
571#if DEBUG_SIG
572 printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
573 current->comm, current->pid, signal, frame, regs->pc);
574#endif
575
576 return;
577
578give_sigsegv:
579 if (sig == SIGSEGV)
580 ka->sa.sa_handler = SIG_DFL;
581 force_sig(SIGSEGV, current);
582}
583
584static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
585 sigset_t *set, struct pt_regs *regs)
586{
587 struct rt_sigframe *frame;
588 int err = 0;
589 int signal;
590
591 frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
592 if (regs->depc > 64)
593 panic ("Double exception sys_sigreturn\n");
594
595 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
596 goto give_sigsegv;
597
598 signal = current_thread_info()->exec_domain
599 && current_thread_info()->exec_domain->signal_invmap
600 && sig < 32
601 ? current_thread_info()->exec_domain->signal_invmap[sig]
602 : sig;
603
604 err |= copy_siginfo_to_user(&frame->info, info);
605
606 /* Create the ucontext. */
607 err |= __put_user(0, &frame->uc.uc_flags);
608 err |= __put_user(0, &frame->uc.uc_link);
609 err |= __put_user((void *)current->sas_ss_sp,
610 &frame->uc.uc_stack.ss_sp);
611 err |= __put_user(sas_ss_flags(regs->areg[1]),
612 &frame->uc.uc_stack.ss_flags);
613 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
614 err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->cpstate,
615 regs, set->sig[0]);
616 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
617
618 /* Create sys_rt_sigreturn syscall in stack frame */
619 err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN);
620
621 if (err)
622 goto give_sigsegv;
623
624 /* Create signal handler execution context.
625 * Return context not modified until this point.
626 */
627 set_thread_state(regs, frame, frame->retcode,
628 ka->sa.sa_handler, signal, &frame->info, &frame->uc);
629
630 /* Set access mode to USER_DS. Nomenclature is outdated, but
631 * functionality is used in uaccess.h
632 */
633 set_fs(USER_DS);
634
635#if DEBUG_SIG
636 printk("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
637 current->comm, current->pid, signal, frame, regs->pc);
638#endif
639
640 return;
641
642give_sigsegv:
643 if (sig == SIGSEGV)
644 ka->sa.sa_handler = SIG_DFL;
645 force_sig(SIGSEGV, current);
646}
647
648
649
650/*
651 * Note that 'init' is a special process: it doesn't get signals it doesn't
652 * want to handle. Thus you cannot kill init even with a SIGKILL even by
653 * mistake.
654 *
655 * Note that we go through the signals twice: once to check the signals that
656 * the kernel can handle, and then we build all the user-level signal handling
657 * stack-frames in one go after that.
658 */
659int do_signal(struct pt_regs *regs, sigset_t *oldset)
660{
661 siginfo_t info;
662 int signr;
663 struct k_sigaction ka;
664
665 if (!oldset)
666 oldset = &current->blocked;
667
668 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
669
670 /* Are we from a system call? */
671 if (regs->syscall >= 0) {
672 /* If so, check system call restarting.. */
673 switch (regs->areg[2]) {
674 case ERESTARTNOHAND:
675 case ERESTART_RESTARTBLOCK:
676 regs->areg[2] = -EINTR;
677 break;
678
679 case ERESTARTSYS:
680 if (!(ka.sa.sa_flags & SA_RESTART)) {
681 regs->areg[2] = -EINTR;
682 break;
683 }
684 /* fallthrough */
685 case ERESTARTNOINTR:
686 regs->areg[2] = regs->syscall;
687 regs->pc -= 3;
688 }
689 }
690
691 if (signr == 0)
692 return 0; /* no signals delivered */
693
694 /* Whee! Actually deliver the signal. */
695
696 /* Set up the stack frame */
697 if (ka.sa.sa_flags & SA_SIGINFO)
698 setup_rt_frame(signr, &ka, &info, oldset, regs);
699 else
700 setup_frame(signr, &ka, oldset, regs);
701
702 if (ka.sa.sa_flags & SA_ONESHOT)
703 ka.sa.sa_handler = SIG_DFL;
704
705 if (!(ka.sa.sa_flags & SA_NODEFER)) {
706 spin_lock_irq(&current->sighand->siglock);
707 sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
708 sigaddset(&current->blocked, signr);
709 recalc_sigpending();
710 spin_unlock_irq(&current->sighand->siglock);
711 }
712 return 1;
713}
diff --git a/arch/xtensa/kernel/syscalls.c b/arch/xtensa/kernel/syscalls.c
new file mode 100644
index 0000000000..abc8ed6c70
--- /dev/null
+++ b/arch/xtensa/kernel/syscalls.c
@@ -0,0 +1,418 @@
1/*
2 * arch/xtensa/kernel/syscall.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 * Copyright (C) 2000 Silicon Graphics, Inc.
10 * Copyright (C) 1995 - 2000 by Ralf Baechle
11 *
12 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
13 * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
14 * Chris Zankel <chris@zankel.net>
15 * Kevin Chea
16 *
17 */
18
19#define DEBUG 0
20
21#include <linux/config.h>
22#include <linux/linkage.h>
23#include <linux/mm.h>
24#include <linux/smp.h>
25#include <linux/smp_lock.h>
26#include <linux/mman.h>
27#include <linux/sched.h>
28#include <linux/file.h>
29#include <linux/slab.h>
30#include <linux/utsname.h>
31#include <linux/unistd.h>
32#include <linux/stringify.h>
33#include <linux/syscalls.h>
34#include <linux/sem.h>
35#include <linux/msg.h>
36#include <linux/shm.h>
37#include <linux/errno.h>
38#include <asm/ptrace.h>
39#include <asm/signal.h>
40#include <asm/uaccess.h>
41#include <asm/hardirq.h>
42#include <asm/mman.h>
43#include <asm/shmparam.h>
44#include <asm/page.h>
45#include <asm/ipc.h>
46
47extern void do_syscall_trace(void);
48typedef int (*syscall_t)(void *a0,...);
49extern int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
50 int narg);
51extern syscall_t sys_call_table[];
52extern unsigned char sys_narg_table[];
53
54/*
55 * sys_pipe() is the normal C calling standard for creating a pipe. It's not
56 * the way unix traditional does this, though.
57 */
58
59int sys_pipe(int __user *userfds)
60{
61 int fd[2];
62 int error;
63
64 error = do_pipe(fd);
65 if (!error) {
66 if (copy_to_user(userfds, fd, 2 * sizeof(int)))
67 error = -EFAULT;
68 }
69 return error;
70}
71
72/*
73 * Common code for old and new mmaps.
74 */
75
76static inline long do_mmap2(unsigned long addr, unsigned long len,
77 unsigned long prot, unsigned long flags,
78 unsigned long fd, unsigned long pgoff)
79{
80 int error = -EBADF;
81 struct file * file = NULL;
82
83 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
84 if (!(flags & MAP_ANONYMOUS)) {
85 file = fget(fd);
86 if (!file)
87 goto out;
88 }
89
90 down_write(&current->mm->mmap_sem);
91 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
92 up_write(&current->mm->mmap_sem);
93
94 if (file)
95 fput(file);
96out:
97 return error;
98}
99
100unsigned long old_mmap(unsigned long addr, size_t len, int prot,
101 int flags, int fd, off_t offset)
102{
103 return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
104}
105
106long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
107 unsigned long flags, unsigned long fd, unsigned long pgoff)
108{
109 return do_mmap2(addr, len, prot, flags, fd, pgoff);
110}
111
112int sys_fork(struct pt_regs *regs)
113{
114 return do_fork(SIGCHLD, regs->areg[1], regs, 0, NULL, NULL);
115}
116
117int sys_vfork(struct pt_regs *regs)
118{
119 return do_fork(CLONE_VFORK|CLONE_VM|SIGCHLD, regs->areg[1],
120 regs, 0, NULL, NULL);
121}
122
123int sys_clone(struct pt_regs *regs)
124{
125 unsigned long clone_flags;
126 unsigned long newsp;
127 int __user *parent_tidptr, *child_tidptr;
128 clone_flags = regs->areg[4];
129 newsp = regs->areg[3];
130 parent_tidptr = (int __user *)regs->areg[5];
131 child_tidptr = (int __user *)regs->areg[6];
132 if (!newsp)
133 newsp = regs->areg[1];
134 return do_fork(clone_flags,newsp,regs,0,parent_tidptr,child_tidptr);
135}
136
137/*
138 * sys_execve() executes a new program.
139 */
140
141int sys_execve(struct pt_regs *regs)
142{
143 int error;
144 char * filename;
145
146 filename = getname((char *) (long)regs->areg[5]);
147 error = PTR_ERR(filename);
148 if (IS_ERR(filename))
149 goto out;
150 error = do_execve(filename, (char **) (long)regs->areg[3],
151 (char **) (long)regs->areg[4], regs);
152 putname(filename);
153
154out:
155 return error;
156}
157
158int sys_uname(struct old_utsname * name)
159{
160 if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
161 return 0;
162 return -EFAULT;
163}
164
165int sys_olduname(struct oldold_utsname * name)
166{
167 int error;
168
169 if (!name)
170 return -EFAULT;
171 if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
172 return -EFAULT;
173
174 error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
175 error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
176 error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
177 error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
178 error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
179 error -= __put_user(0,name->release+__OLD_UTS_LEN);
180 error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
181 error -= __put_user(0,name->version+__OLD_UTS_LEN);
182 error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
183 error -= __put_user(0,name->machine+__OLD_UTS_LEN);
184
185 return error ? -EFAULT : 0;
186}
187
188
189/*
190 * Build the string table for the builtin "poor man's strace".
191 */
192
193#if DEBUG
194#define SYSCALL(fun, narg) #fun,
195static char *sfnames[] = {
196#include "syscalls.h"
197};
198#undef SYS
199#endif
200
201void system_call (struct pt_regs *regs)
202{
203 syscall_t syscall;
204 unsigned long parm0, parm1, parm2, parm3, parm4, parm5;
205 int nargs, res;
206 unsigned int syscallnr;
207 int ps;
208
209#if DEBUG
210 int i;
211 unsigned long parms[6];
212 char *sysname;
213#endif
214
215 regs->syscall = regs->areg[2];
216
217 do_syscall_trace();
218
219 /* Have to load after syscall_trace because strace
220 * sometimes changes regs->syscall.
221 */
222 syscallnr = regs->syscall;
223
224 parm0 = parm1 = parm2 = parm3 = parm4 = parm5 = 0;
225
226 /* Restore interrupt level to syscall invoker's.
227 * If this were in assembly, we wouldn't disable
228 * interrupts in the first place:
229 */
230 local_save_flags (ps);
231 local_irq_restore((ps & ~XCHAL_PS_INTLEVEL_MASK) |
232 (regs->ps & XCHAL_PS_INTLEVEL_MASK) );
233
234 if (syscallnr > __NR_Linux_syscalls) {
235 regs->areg[2] = -ENOSYS;
236 return;
237 }
238
239 syscall = sys_call_table[syscallnr];
240 nargs = sys_narg_table[syscallnr];
241
242 if (syscall == NULL) {
243 regs->areg[2] = -ENOSYS;
244 return;
245 }
246
247 /* There shouldn't be more than six arguments in the table! */
248
249 if (nargs > 6)
250 panic("Internal error - too many syscall arguments (%d)!\n",
251 nargs);
252
253 /* Linux takes system-call arguments in registers. The ABI
254 * and Xtensa software conventions require the system-call
255 * number in a2. If an argument exists in a2, we move it to
256 * the next available register. Note that for improved
257 * efficiency, we do NOT shift all parameters down one
258 * register to maintain the original order.
259 *
260 * At best case (zero arguments), we just write the syscall
261 * number to a2. At worst case (1 to 6 arguments), we move
262 * the argument in a2 to the next available register, then
263 * write the syscall number to a2.
264 *
265 * For clarity, the following truth table enumerates all
266 * possibilities.
267 *
268 * arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5
269 * --------- -------------- ----------------------------------
270 * 0 a2
271 * 1 a2 a3
272 * 2 a2 a4, a3
273 * 3 a2 a5, a3, a4
274 * 4 a2 a6, a3, a4, a5
275 * 5 a2 a7, a3, a4, a5, a6
276 * 6 a2 a8, a3, a4, a5, a6, a7
277 */
278 if (nargs) {
279 parm0 = regs->areg[nargs+2];
280 parm1 = regs->areg[3];
281 parm2 = regs->areg[4];
282 parm3 = regs->areg[5];
283 parm4 = regs->areg[6];
284 parm5 = regs->areg[7];
285 } else /* nargs == 0 */
286 parm0 = (unsigned long) regs;
287
288#if DEBUG
289 parms[0] = parm0;
290 parms[1] = parm1;
291 parms[2] = parm2;
292 parms[3] = parm3;
293 parms[4] = parm4;
294 parms[5] = parm5;
295
296 sysname = sfnames[syscallnr];
297 if (strncmp(sysname, "sys_", 4) == 0)
298 sysname = sysname + 4;
299
300 printk("\017SYSCALL:I:%x:%d:%s %s(", regs->pc, current->pid,
301 current->comm, sysname);
302 for (i = 0; i < nargs; i++)
303 printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
304 printk(")\n");
305#endif
306
307 res = syscall((void *)parm0, parm1, parm2, parm3, parm4, parm5);
308
309#if DEBUG
310 printk("\017SYSCALL:O:%d:%s %s(",current->pid, current->comm, sysname);
311 for (i = 0; i < nargs; i++)
312 printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
313 if (res < 4096)
314 printk(") = %d\n", res);
315 else
316 printk(") = %#x\n", res);
317#endif /* DEBUG */
318
319 regs->areg[2] = res;
320 do_syscall_trace();
321}
322
323/*
324 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
325 *
326 * This is really horribly ugly.
327 */
328
329int sys_ipc (uint call, int first, int second,
330 int third, void __user *ptr, long fifth)
331{
332 int version, ret;
333
334 version = call >> 16; /* hack for backward compatibility */
335 call &= 0xffff;
336 ret = -ENOSYS;
337
338 switch (call) {
339 case SEMOP:
340 ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
341 second, NULL);
342 break;
343
344 case SEMTIMEDOP:
345 ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
346 second, (const struct timespec *) fifth);
347 break;
348
349 case SEMGET:
350 ret = sys_semget (first, second, third);
351 break;
352
353 case SEMCTL: {
354 union semun fourth;
355
356 if (ptr && !get_user(fourth.__pad, (void *__user *) ptr))
357 ret = sys_semctl (first, second, third, fourth);
358 break;
359 }
360
361 case MSGSND:
362 ret = sys_msgsnd (first, (struct msgbuf __user*) ptr,
363 second, third);
364 break;
365
366 case MSGRCV:
367 switch (version) {
368 case 0: {
369 struct ipc_kludge tmp;
370
371 if (ptr && !copy_from_user(&tmp,
372 (struct ipc_kludge *) ptr,
373 sizeof (tmp)))
374 ret = sys_msgrcv (first, tmp.msgp, second,
375 tmp.msgtyp, third);
376 break;
377 }
378
379 default:
380 ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
381 second, 0, third);
382 break;
383 }
384 break;
385
386 case MSGGET:
387 ret = sys_msgget ((key_t) first, second);
388 break;
389
390 case MSGCTL:
391 ret = sys_msgctl (first, second, (struct msqid_ds __user*) ptr);
392 break;
393
394 case SHMAT: {
395 ulong raddr;
396 ret = do_shmat (first, (char __user *) ptr, second, &raddr);
397
398 if (!ret)
399 ret = put_user (raddr, (ulong __user *) third);
400
401 break;
402 }
403
404 case SHMDT:
405 ret = sys_shmdt ((char __user *)ptr);
406 break;
407
408 case SHMGET:
409 ret = sys_shmget (first, second, third);
410 break;
411
412 case SHMCTL:
413 ret = sys_shmctl (first, second, (struct shmid_ds __user*) ptr);
414 break;
415 }
416 return ret;
417}
418
diff --git a/arch/xtensa/kernel/syscalls.h b/arch/xtensa/kernel/syscalls.h
new file mode 100644
index 0000000000..5b3f75f50f
--- /dev/null
+++ b/arch/xtensa/kernel/syscalls.h
@@ -0,0 +1,248 @@
1/*
2 * arch/xtensa/kernel/syscalls.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
9 * Copyright (C) 2001 - 2005 Tensilica Inc.
10 *
11 * Changes by Joe Taylor <joe@tensilica.com>
12 */
13
14/*
15 * This file is being included twice - once to build a list of all
16 * syscalls and once to build a table of how many arguments each syscall
17 * accepts. Syscalls that receive a pointer to the saved registers are
18 * marked as having zero arguments.
19 *
20 * The binary compatibility calls are in a separate list.
21 *
22 * Entry '0' used to be system_call. It's removed to disable indirect
23 * system calls for now so user tasks can't recurse. See mips'
24 * sys_syscall for a comparable example.
25 */
26
27SYSCALL(0, 0) /* 00 */
28
29SYSCALL(sys_exit, 1)
30SYSCALL(sys_fork, 0)
31SYSCALL(sys_read, 3)
32SYSCALL(sys_write, 3)
33SYSCALL(sys_open, 3) /* 05 */
34SYSCALL(sys_close, 1)
35SYSCALL(sys_waitpid, 3)
36SYSCALL(sys_creat, 2)
37SYSCALL(sys_link, 2)
38SYSCALL(sys_unlink, 1) /* 10 */
39SYSCALL(sys_execve, 0)
40SYSCALL(sys_chdir, 1)
41SYSCALL(sys_time, 1)
42SYSCALL(sys_mknod, 3)
43SYSCALL(sys_chmod, 2) /* 15 */
44SYSCALL(sys_lchown, 3)
45SYSCALL(sys_ni_syscall, 0)
46SYSCALL(sys_stat, 2)
47SYSCALL(sys_lseek, 3)
48SYSCALL(sys_getpid, 0) /* 20 */
49SYSCALL(sys_mount, 5)
50SYSCALL(sys_oldumount, 1)
51SYSCALL(sys_setuid, 1)
52SYSCALL(sys_getuid, 0)
53SYSCALL(sys_stime, 1) /* 25 */
54SYSCALL(sys_ptrace, 4)
55SYSCALL(sys_alarm, 1)
56SYSCALL(sys_fstat, 2)
57SYSCALL(sys_pause, 0)
58SYSCALL(sys_utime, 2) /* 30 */
59SYSCALL(sys_ni_syscall, 0)
60SYSCALL(sys_ni_syscall, 0)
61SYSCALL(sys_access, 2)
62SYSCALL(sys_nice, 1)
63SYSCALL(sys_ni_syscall, 0) /* 35 */
64SYSCALL(sys_sync, 0)
65SYSCALL(sys_kill, 2)
66SYSCALL(sys_rename, 2)
67SYSCALL(sys_mkdir, 2)
68SYSCALL(sys_rmdir, 1) /* 40 */
69SYSCALL(sys_dup, 1)
70SYSCALL(sys_pipe, 1)
71SYSCALL(sys_times, 1)
72SYSCALL(sys_ni_syscall, 0)
73SYSCALL(sys_brk, 1) /* 45 */
74SYSCALL(sys_setgid, 1)
75SYSCALL(sys_getgid, 0)
76SYSCALL(sys_ni_syscall, 0) /* was signal(2) */
77SYSCALL(sys_geteuid, 0)
78SYSCALL(sys_getegid, 0) /* 50 */
79SYSCALL(sys_acct, 1)
80SYSCALL(sys_umount, 2)
81SYSCALL(sys_ni_syscall, 0)
82SYSCALL(sys_ioctl, 3)
83SYSCALL(sys_fcntl, 3) /* 55 */
84SYSCALL(sys_ni_syscall, 2)
85SYSCALL(sys_setpgid, 2)
86SYSCALL(sys_ni_syscall, 0)
87SYSCALL(sys_olduname, 1)
88SYSCALL(sys_umask, 1) /* 60 */
89SYSCALL(sys_chroot, 1)
90SYSCALL(sys_ustat, 2)
91SYSCALL(sys_dup2, 2)
92SYSCALL(sys_getppid, 0)
93SYSCALL(sys_getpgrp, 0) /* 65 */
94SYSCALL(sys_setsid, 0)
95SYSCALL(sys_sigaction, 3)
96SYSCALL(sys_sgetmask, 0)
97SYSCALL(sys_ssetmask, 1)
98SYSCALL(sys_setreuid, 2) /* 70 */
99SYSCALL(sys_setregid, 2)
100SYSCALL(sys_sigsuspend, 0)
101SYSCALL(sys_sigpending, 1)
102SYSCALL(sys_sethostname, 2)
103SYSCALL(sys_setrlimit, 2) /* 75 */
104SYSCALL(sys_getrlimit, 2)
105SYSCALL(sys_getrusage, 2)
106SYSCALL(sys_gettimeofday, 2)
107SYSCALL(sys_settimeofday, 2)
108SYSCALL(sys_getgroups, 2) /* 80 */
109SYSCALL(sys_setgroups, 2)
110SYSCALL(sys_ni_syscall, 0) /* old_select */
111SYSCALL(sys_symlink, 2)
112SYSCALL(sys_lstat, 2)
113SYSCALL(sys_readlink, 3) /* 85 */
114SYSCALL(sys_uselib, 1)
115SYSCALL(sys_swapon, 2)
116SYSCALL(sys_reboot, 3)
117SYSCALL(old_readdir, 3)
118SYSCALL(old_mmap, 6) /* 90 */
119SYSCALL(sys_munmap, 2)
120SYSCALL(sys_truncate, 2)
121SYSCALL(sys_ftruncate, 2)
122SYSCALL(sys_fchmod, 2)
123SYSCALL(sys_fchown, 3) /* 95 */
124SYSCALL(sys_getpriority, 2)
125SYSCALL(sys_setpriority, 3)
126SYSCALL(sys_ni_syscall, 0)
127SYSCALL(sys_statfs, 2)
128SYSCALL(sys_fstatfs, 2) /* 100 */
129SYSCALL(sys_ni_syscall, 3)
130SYSCALL(sys_socketcall, 2)
131SYSCALL(sys_syslog, 3)
132SYSCALL(sys_setitimer, 3)
133SYSCALL(sys_getitimer, 2) /* 105 */
134SYSCALL(sys_newstat, 2)
135SYSCALL(sys_newlstat, 2)
136SYSCALL(sys_newfstat, 2)
137SYSCALL(sys_uname, 1)
138SYSCALL(sys_ni_syscall, 0) /* 110 */
139SYSCALL(sys_vhangup, 0)
140SYSCALL(sys_ni_syscall, 0) /* was sys_idle() */
141SYSCALL(sys_ni_syscall, 0)
142SYSCALL(sys_wait4, 4)
143SYSCALL(sys_swapoff, 1) /* 115 */
144SYSCALL(sys_sysinfo, 1)
145SYSCALL(sys_ipc, 5) /* 6 really, but glibc uses only 5) */
146SYSCALL(sys_fsync, 1)
147SYSCALL(sys_sigreturn, 0)
148SYSCALL(sys_clone, 0) /* 120 */
149SYSCALL(sys_setdomainname, 2)
150SYSCALL(sys_newuname, 1)
151SYSCALL(sys_ni_syscall, 0) /* sys_modify_ldt */
152SYSCALL(sys_adjtimex, 1)
153SYSCALL(sys_mprotect, 3) /* 125 */
154SYSCALL(sys_sigprocmask, 3)
155SYSCALL(sys_ni_syscall, 2) /* old sys_create_module */
156SYSCALL(sys_init_module, 2)
157SYSCALL(sys_delete_module, 1)
158SYSCALL(sys_ni_syscall, 1) /* old sys_get_kernel_sysm */ /* 130 */
159SYSCALL(sys_quotactl, 0)
160SYSCALL(sys_getpgid, 1)
161SYSCALL(sys_fchdir, 1)
162SYSCALL(sys_bdflush, 2)
163SYSCALL(sys_sysfs, 3) /* 135 */
164SYSCALL(sys_personality, 1)
165SYSCALL(sys_ni_syscall, 0) /* for afs_syscall */
166SYSCALL(sys_setfsuid, 1)
167SYSCALL(sys_setfsgid, 1)
168SYSCALL(sys_llseek, 5) /* 140 */
169SYSCALL(sys_getdents, 3)
170SYSCALL(sys_select, 5)
171SYSCALL(sys_flock, 2)
172SYSCALL(sys_msync, 3)
173SYSCALL(sys_readv, 3) /* 145 */
174SYSCALL(sys_writev, 3)
175SYSCALL(sys_ni_syscall, 3)
176SYSCALL(sys_ni_syscall, 3)
177SYSCALL(sys_ni_syscall, 4) /* handled in fast syscall handler. */
178SYSCALL(sys_ni_syscall, 0) /* 150 */
179SYSCALL(sys_getsid, 1)
180SYSCALL(sys_fdatasync, 1)
181SYSCALL(sys_sysctl, 1)
182SYSCALL(sys_mlock, 2)
183SYSCALL(sys_munlock, 2) /* 155 */
184SYSCALL(sys_mlockall, 1)
185SYSCALL(sys_munlockall, 0)
186SYSCALL(sys_sched_setparam,2)
187SYSCALL(sys_sched_getparam,2)
188SYSCALL(sys_sched_setscheduler,3) /* 160 */
189SYSCALL(sys_sched_getscheduler,1)
190SYSCALL(sys_sched_yield,0)
191SYSCALL(sys_sched_get_priority_max,1)
192SYSCALL(sys_sched_get_priority_min,1)
193SYSCALL(sys_sched_rr_get_interval,2) /* 165 */
194SYSCALL(sys_nanosleep,2)
195SYSCALL(sys_mremap,4)
196SYSCALL(sys_accept, 3)
197SYSCALL(sys_bind, 3)
198SYSCALL(sys_connect, 3) /* 170 */
199SYSCALL(sys_getpeername, 3)
200SYSCALL(sys_getsockname, 3)
201SYSCALL(sys_getsockopt, 5)
202SYSCALL(sys_listen, 2)
203SYSCALL(sys_recv, 4) /* 175 */
204SYSCALL(sys_recvfrom, 6)
205SYSCALL(sys_recvmsg, 3)
206SYSCALL(sys_send, 4)
207SYSCALL(sys_sendmsg, 3)
208SYSCALL(sys_sendto, 6) /* 180 */
209SYSCALL(sys_setsockopt, 5)
210SYSCALL(sys_shutdown, 2)
211SYSCALL(sys_socket, 3)
212SYSCALL(sys_socketpair, 4)
213SYSCALL(sys_setresuid, 3) /* 185 */
214SYSCALL(sys_getresuid, 3)
215SYSCALL(sys_ni_syscall, 5) /* old sys_query_module */
216SYSCALL(sys_poll, 3)
217SYSCALL(sys_nfsservctl, 3)
218SYSCALL(sys_setresgid, 3) /* 190 */
219SYSCALL(sys_getresgid, 3)
220SYSCALL(sys_prctl, 5)
221SYSCALL(sys_rt_sigreturn, 0)
222SYSCALL(sys_rt_sigaction, 4)
223SYSCALL(sys_rt_sigprocmask, 4) /* 195 */
224SYSCALL(sys_rt_sigpending, 2)
225SYSCALL(sys_rt_sigtimedwait, 4)
226SYSCALL(sys_rt_sigqueueinfo, 3)
227SYSCALL(sys_rt_sigsuspend, 0)
228SYSCALL(sys_pread64, 5) /* 200 */
229SYSCALL(sys_pwrite64, 5)
230SYSCALL(sys_chown, 3)
231SYSCALL(sys_getcwd, 2)
232SYSCALL(sys_capget, 2)
233SYSCALL(sys_capset, 2) /* 205 */
234SYSCALL(sys_sigaltstack, 0)
235SYSCALL(sys_sendfile, 4)
236SYSCALL(sys_ni_syscall, 0)
237SYSCALL(sys_ni_syscall, 0)
238SYSCALL(sys_mmap2, 6) /* 210 */
239SYSCALL(sys_truncate64, 2)
240SYSCALL(sys_ftruncate64, 2)
241SYSCALL(sys_stat64, 2)
242SYSCALL(sys_lstat64, 2)
243SYSCALL(sys_fstat64, 2) /* 215 */
244SYSCALL(sys_pivot_root, 2)
245SYSCALL(sys_mincore, 3)
246SYSCALL(sys_madvise, 3)
247SYSCALL(sys_getdents64, 3)
248SYSCALL(sys_vfork, 0) /* 220 */
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
new file mode 100644
index 0000000000..e07287db5a
--- /dev/null
+++ b/arch/xtensa/kernel/time.c
@@ -0,0 +1,227 @@
1/*
2 * arch/xtensa/kernel/time.c
3 *
4 * Timer and clock support.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2005 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 */
14
15#include <linux/config.h>
16#include <linux/errno.h>
17#include <linux/time.h>
18#include <linux/timex.h>
19#include <linux/interrupt.h>
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/irq.h>
23#include <linux/profile.h>
24#include <linux/delay.h>
25
26#include <asm/timex.h>
27#include <asm/platform.h>
28
29
30extern volatile unsigned long wall_jiffies;
31
32u64 jiffies_64 = INITIAL_JIFFIES;
33EXPORT_SYMBOL(jiffies_64);
34
35spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
36EXPORT_SYMBOL(rtc_lock);
37
38
39#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
40unsigned long ccount_per_jiffy; /* per 1/HZ */
41unsigned long ccount_nsec; /* nsec per ccount increment */
42#endif
43
44unsigned int last_ccount_stamp;
45static long last_rtc_update = 0;
46
47/*
48 * Scheduler clock - returns current tim in nanosec units.
49 */
50
51unsigned long long sched_clock(void)
52{
53 return (unsigned long long)jiffies * (1000000000 / HZ);
54}
55
56static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
57static struct irqaction timer_irqaction = {
58 .handler = timer_interrupt,
59 .flags = SA_INTERRUPT,
60 .name = "timer",
61};
62
63void __init time_init(void)
64{
65 time_t sec_o, sec_n = 0;
66
67 /* The platform must provide a function to calibrate the processor
68 * speed for the CALIBRATE.
69 */
70
71#if CONFIG_XTENSA_CALIBRATE_CCOUNT
72 printk("Calibrating CPU frequency ");
73 platform_calibrate_ccount();
74 printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ),
75 (int)(ccount_per_jiffy/(10000/HZ))%100);
76#endif
77
78 /* Set time from RTC (if provided) */
79
80 if (platform_get_rtc_time(&sec_o) == 0)
81 while (platform_get_rtc_time(&sec_n))
82 if (sec_o != sec_n)
83 break;
84
85 xtime.tv_nsec = 0;
86 last_rtc_update = xtime.tv_sec = sec_n;
87 last_ccount_stamp = get_ccount();
88
89 set_normalized_timespec(&wall_to_monotonic,
90 -xtime.tv_sec, -xtime.tv_nsec);
91
92 /* Initialize the linux timer interrupt. */
93
94 setup_irq(LINUX_TIMER_INT, &timer_irqaction);
95 set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY);
96}
97
98
99int do_settimeofday(struct timespec *tv)
100{
101 time_t wtm_sec, sec = tv->tv_sec;
102 long wtm_nsec, nsec = tv->tv_nsec;
103 unsigned long ccount;
104
105 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
106 return -EINVAL;
107
108 write_seqlock_irq(&xtime_lock);
109
110 /* This is revolting. We need to set "xtime" correctly. However, the
111 * value in this location is the value at the most recent update of
112 * wall time. Discover what correction gettimeofday() would have
113 * made, and then undo it!
114 */
115 ccount = get_ccount();
116 nsec -= (ccount - last_ccount_stamp) * CCOUNT_NSEC;
117 nsec -= (jiffies - wall_jiffies) * CCOUNT_PER_JIFFY * CCOUNT_NSEC;
118
119 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
120 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
121
122 set_normalized_timespec(&xtime, sec, nsec);
123 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
124
125 time_adjust = 0; /* stop active adjtime() */
126 time_status |= STA_UNSYNC;
127 time_maxerror = NTP_PHASE_LIMIT;
128 time_esterror = NTP_PHASE_LIMIT;
129 write_sequnlock_irq(&xtime_lock);
130 return 0;
131}
132
133EXPORT_SYMBOL(do_settimeofday);
134
135
136void do_gettimeofday(struct timeval *tv)
137{
138 unsigned long flags;
139 unsigned long sec, usec, delta, lost, seq;
140
141 do {
142 seq = read_seqbegin_irqsave(&xtime_lock, flags);
143
144 delta = get_ccount() - last_ccount_stamp;
145 sec = xtime.tv_sec;
146 usec = (xtime.tv_nsec / NSEC_PER_USEC);
147
148 lost = jiffies - wall_jiffies;
149
150 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
151
152 usec += lost * (1000000UL/HZ) + (delta * CCOUNT_NSEC) / NSEC_PER_USEC;
153 for (; usec >= 1000000; sec++, usec -= 1000000)
154 ;
155
156 tv->tv_sec = sec;
157 tv->tv_usec = usec;
158}
159
160EXPORT_SYMBOL(do_gettimeofday);
161
162/*
163 * The timer interrupt is called HZ times per second.
164 */
165
166irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
167{
168
169 unsigned long next;
170
171 next = get_linux_timer();
172
173again:
174 while ((signed long)(get_ccount() - next) > 0) {
175
176 profile_tick(CPU_PROFILING, regs);
177#ifndef CONFIG_SMP
178 update_process_times(user_mode(regs));
179#endif
180
181 write_seqlock(&xtime_lock);
182
183 last_ccount_stamp = next;
184 next += CCOUNT_PER_JIFFY;
185 do_timer (regs); /* Linux handler in kernel/timer.c */
186
187 if ((time_status & STA_UNSYNC) == 0 &&
188 xtime.tv_sec - last_rtc_update >= 659 &&
189 abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ &&
190 jiffies - wall_jiffies == 1) {
191
192 if (platform_set_rtc_time(xtime.tv_sec+1) == 0)
193 last_rtc_update = xtime.tv_sec+1;
194 else
195 /* Do it again in 60 s */
196 last_rtc_update += 60;
197 }
198 write_sequnlock(&xtime_lock);
199 }
200
201 /* NOTE: writing CCOMPAREn clears the interrupt. */
202
203 set_linux_timer (next);
204
205 /* Make sure we didn't miss any tick... */
206
207 if ((signed long)(get_ccount() - next) > 0)
208 goto again;
209
210 /* Allow platform to do something usefull (Wdog). */
211
212 platform_heartbeat();
213
214 return IRQ_HANDLED;
215}
216
217#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
218void __devinit calibrate_delay(void)
219{
220 loops_per_jiffy = CCOUNT_PER_JIFFY;
221 printk("Calibrating delay loop (skipped)... "
222 "%lu.%02lu BogoMIPS preset\n",
223 loops_per_jiffy/(1000000/HZ),
224 (loops_per_jiffy/(10000/HZ)) % 100);
225}
226#endif
227
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
new file mode 100644
index 0000000000..804246e743
--- /dev/null
+++ b/arch/xtensa/kernel/traps.c
@@ -0,0 +1,498 @@
1/*
2 * arch/xtensa/kernel/traps.c
3 *
4 * Exception handling.
5 *
6 * Derived from code with the following copyrights:
7 * Copyright (C) 1994 - 1999 by Ralf Baechle
8 * Modified for R3000 by Paul M. Antoine, 1995, 1996
9 * Complete output from die() by Ulf Carlsson, 1998
10 * Copyright (C) 1999 Silicon Graphics, Inc.
11 *
12 * Essentially rewritten for the Xtensa architecture port.
13 *
14 * Copyright (C) 2001 - 2005 Tensilica Inc.
15 *
16 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
17 * Chris Zankel <chris@zankel.net>
18 * Marc Gauthier<marc@tensilica.com, marc@alumni.uwaterloo.ca>
19 * Kevin Chea
20 *
21 * This file is subject to the terms and conditions of the GNU General Public
22 * License. See the file "COPYING" in the main directory of this archive
23 * for more details.
24 */
25
26#include <linux/kernel.h>
27#include <linux/sched.h>
28#include <linux/init.h>
29#include <linux/module.h>
30#include <linux/stringify.h>
31#include <linux/kallsyms.h>
32
33#include <asm/ptrace.h>
34#include <asm/timex.h>
35#include <asm/uaccess.h>
36#include <asm/pgtable.h>
37#include <asm/processor.h>
38
39#ifdef CONFIG_KGDB
40extern int gdb_enter;
41extern int return_from_debug_flag;
42#endif
43
44/*
45 * Machine specific interrupt handlers
46 */
47
48extern void kernel_exception(void);
49extern void user_exception(void);
50
51extern void fast_syscall_kernel(void);
52extern void fast_syscall_user(void);
53extern void fast_alloca(void);
54extern void fast_unaligned(void);
55extern void fast_second_level_miss(void);
56extern void fast_store_prohibited(void);
57extern void fast_coprocessor(void);
58
59extern void do_illegal_instruction (struct pt_regs*);
60extern void do_interrupt (struct pt_regs*);
61extern void do_unaligned_user (struct pt_regs*);
62extern void do_multihit (struct pt_regs*, unsigned long);
63extern void do_page_fault (struct pt_regs*, unsigned long);
64extern void do_debug (struct pt_regs*);
65extern void system_call (struct pt_regs*);
66
67/*
68 * The vector table must be preceded by a save area (which
69 * implies it must be in RAM, unless one places RAM immediately
70 * before a ROM and puts the vector at the start of the ROM (!))
71 */
72
73#define KRNL 0x01
74#define USER 0x02
75
76#define COPROCESSOR(x) \
77{ XCHAL_EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor }
78
79typedef struct {
80 int cause;
81 int fast;
82 void* handler;
83} dispatch_init_table_t;
84
85dispatch_init_table_t __init dispatch_init_table[] = {
86
87{ XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction},
88{ XCHAL_EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel },
89{ XCHAL_EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user },
90{ XCHAL_EXCCAUSE_SYSTEM_CALL, 0, system_call },
91/* XCHAL_EXCCAUSE_INSTRUCTION_FETCH unhandled */
92/* XCHAL_EXCCAUSE_LOAD_STORE_ERROR unhandled*/
93{ XCHAL_EXCCAUSE_LEVEL1_INTERRUPT, 0, do_interrupt },
94{ XCHAL_EXCCAUSE_ALLOCA, USER|KRNL, fast_alloca },
95/* XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
96/* XCHAL_EXCCAUSE_PRIVILEGED unhandled */
97#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
98#ifdef CONFIG_UNALIGNED_USER
99{ XCHAL_EXCCAUSE_UNALIGNED, USER, fast_unaligned },
100#else
101{ XCHAL_EXCCAUSE_UNALIGNED, 0, do_unaligned_user },
102#endif
103{ XCHAL_EXCCAUSE_UNALIGNED, KRNL, fast_unaligned },
104#endif
105{ XCHAL_EXCCAUSE_ITLB_MISS, 0, do_page_fault },
106{ XCHAL_EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss},
107{ XCHAL_EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit },
108{ XCHAL_EXCCAUSE_ITLB_PRIVILEGE, 0, do_page_fault },
109/* XCHAL_EXCCAUSE_SIZE_RESTRICTION unhandled */
110{ XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE, 0, do_page_fault },
111{ XCHAL_EXCCAUSE_DTLB_MISS, USER|KRNL, fast_second_level_miss},
112{ XCHAL_EXCCAUSE_DTLB_MISS, 0, do_page_fault },
113{ XCHAL_EXCCAUSE_DTLB_MULTIHIT, 0, do_multihit },
114{ XCHAL_EXCCAUSE_DTLB_PRIVILEGE, 0, do_page_fault },
115/* XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */
116{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited },
117{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault },
118{ XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault },
119/* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */
120#if (XCHAL_CP_MASK & 1)
121COPROCESSOR(0),
122#endif
123#if (XCHAL_CP_MASK & 2)
124COPROCESSOR(1),
125#endif
126#if (XCHAL_CP_MASK & 4)
127COPROCESSOR(2),
128#endif
129#if (XCHAL_CP_MASK & 8)
130COPROCESSOR(3),
131#endif
132#if (XCHAL_CP_MASK & 16)
133COPROCESSOR(4),
134#endif
135#if (XCHAL_CP_MASK & 32)
136COPROCESSOR(5),
137#endif
138#if (XCHAL_CP_MASK & 64)
139COPROCESSOR(6),
140#endif
141#if (XCHAL_CP_MASK & 128)
142COPROCESSOR(7),
143#endif
144{ EXCCAUSE_MAPPED_DEBUG, 0, do_debug },
145{ -1, -1, 0 }
146
147};
148
149/* The exception table <exc_table> serves two functions:
150 * 1. it contains three dispatch tables (fast_user, fast_kernel, default-c)
151 * 2. it is a temporary memory buffer for the exception handlers.
152 */
153
154unsigned long exc_table[EXC_TABLE_SIZE/4];
155
156void die(const char*, struct pt_regs*, long);
157
158static inline void
159__die_if_kernel(const char *str, struct pt_regs *regs, long err)
160{
161 if (!user_mode(regs))
162 die(str, regs, err);
163}
164
165/*
166 * Unhandled Exceptions. Kill user task or panic if in kernel space.
167 */
168
169void do_unhandled(struct pt_regs *regs, unsigned long exccause)
170{
171 __die_if_kernel("Caught unhandled exception - should not happen",
172 regs, SIGKILL);
173
174 /* If in user mode, send SIGILL signal to current process */
175 printk("Caught unhandled exception in '%s' "
176 "(pid = %d, pc = %#010lx) - should not happen\n"
177 "\tEXCCAUSE is %ld\n",
178 current->comm, current->pid, regs->pc, exccause);
179 force_sig(SIGILL, current);
180}
181
182/*
183 * Multi-hit exception. This if fatal!
184 */
185
186void do_multihit(struct pt_regs *regs, unsigned long exccause)
187{
188 die("Caught multihit exception", regs, SIGKILL);
189}
190
191/*
192 * Level-1 interrupt.
193 * We currently have no priority encoding.
194 */
195
196unsigned long ignored_level1_interrupts;
197extern void do_IRQ(int, struct pt_regs *);
198
199void do_interrupt (struct pt_regs *regs)
200{
201 unsigned long intread = get_sr (INTREAD);
202 unsigned long intenable = get_sr (INTENABLE);
203 int i, mask;
204
205 /* Handle all interrupts (no priorities).
206 * (Clear the interrupt before processing, in case it's
207 * edge-triggered or software-generated)
208 */
209
210 for (i=0, mask = 1; i < XCHAL_NUM_INTERRUPTS; i++, mask <<= 1) {
211 if (mask & (intread & intenable)) {
212 set_sr (mask, INTCLEAR);
213 do_IRQ (i,regs);
214 }
215 }
216}
217
218/*
219 * Illegal instruction. Fatal if in kernel space.
220 */
221
222void
223do_illegal_instruction(struct pt_regs *regs)
224{
225 __die_if_kernel("Illegal instruction in kernel", regs, SIGKILL);
226
227 /* If in user mode, send SIGILL signal to current process. */
228
229 printk("Illegal Instruction in '%s' (pid = %d, pc = %#010lx)\n",
230 current->comm, current->pid, regs->pc);
231 force_sig(SIGILL, current);
232}
233
234
235/*
236 * Handle unaligned memory accesses from user space. Kill task.
237 *
238 * If CONFIG_UNALIGNED_USER is not set, we don't allow unaligned memory
239 * accesses causes from user space.
240 */
241
242#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
243#ifndef CONFIG_UNALIGNED_USER
244void
245do_unaligned_user (struct pt_regs *regs)
246{
247 siginfo_t info;
248
249 __die_if_kernel("Unhandled unaligned exception in kernel",
250 regs, SIGKILL);
251
252 current->thread.bad_vaddr = regs->excvaddr;
253 current->thread.error_code = -3;
254 printk("Unaligned memory access to %08lx in '%s' "
255 "(pid = %d, pc = %#010lx)\n",
256 regs->excvaddr, current->comm, current->pid, regs->pc);
257 info.si_signo = SIGBUS;
258 info.si_errno = 0;
259 info.si_code = BUS_ADRALN;
260 info.si_addr = (void *) regs->excvaddr;
261 force_sig_info(SIGSEGV, &info, current);
262
263}
264#endif
265#endif
266
267void
268do_debug(struct pt_regs *regs)
269{
270#ifdef CONFIG_KGDB
271 /* If remote debugging is configured AND enabled, we give control to
272 * kgdb. Otherwise, we fall through, perhaps giving control to the
273 * native debugger.
274 */
275
276 if (gdb_enter) {
277 extern void gdb_handle_exception(struct pt_regs *);
278 gdb_handle_exception(regs);
279 return_from_debug_flag = 1;
280 return;
281 }
282#endif
283
284 __die_if_kernel("Breakpoint in kernel", regs, SIGKILL);
285
286 /* If in user mode, send SIGTRAP signal to current process */
287
288 force_sig(SIGTRAP, current);
289}
290
291
292/*
293 * Initialize dispatch tables.
294 *
295 * The exception vectors are stored compressed the __init section in the
296 * dispatch_init_table. This function initializes the following three tables
297 * from that compressed table:
298 * - fast user first dispatch table for user exceptions
299 * - fast kernel first dispatch table for kernel exceptions
300 * - default C-handler C-handler called by the default fast handler.
301 *
302 * See vectors.S for more details.
303 */
304
305#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler))
306
307void trap_init(void)
308{
309 int i;
310
311 /* Setup default vectors. */
312
313 for(i = 0; i < 64; i++) {
314 set_handler(EXC_TABLE_FAST_USER/4 + i, user_exception);
315 set_handler(EXC_TABLE_FAST_KERNEL/4 + i, kernel_exception);
316 set_handler(EXC_TABLE_DEFAULT/4 + i, do_unhandled);
317 }
318
319 /* Setup specific handlers. */
320
321 for(i = 0; dispatch_init_table[i].cause >= 0; i++) {
322
323 int fast = dispatch_init_table[i].fast;
324 int cause = dispatch_init_table[i].cause;
325 void *handler = dispatch_init_table[i].handler;
326
327 if (fast == 0)
328 set_handler (EXC_TABLE_DEFAULT/4 + cause, handler);
329 if (fast && fast & USER)
330 set_handler (EXC_TABLE_FAST_USER/4 + cause, handler);
331 if (fast && fast & KRNL)
332 set_handler (EXC_TABLE_FAST_KERNEL/4 + cause, handler);
333 }
334
335 /* Initialize EXCSAVE_1 to hold the address of the exception table. */
336
337 i = (unsigned long)exc_table;
338 __asm__ __volatile__("wsr %0, "__stringify(EXCSAVE_1)"\n" : : "a" (i));
339}
340
341/*
342 * This function dumps the current valid window frame and other base registers.
343 */
344
345void show_regs(struct pt_regs * regs)
346{
347 int i, wmask;
348
349 wmask = regs->wmask & ~1;
350
351 for (i = 0; i < 32; i++) {
352 if (wmask & (1 << (i / 4)))
353 break;
354 if ((i % 8) == 0)
355 printk ("\n" KERN_INFO "a%02d: ", i);
356 printk("%08lx ", regs->areg[i]);
357 }
358 printk("\n");
359
360 printk("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n",
361 regs->pc, regs->ps, regs->depc, regs->excvaddr);
362 printk("lbeg: %08lx, lend: %08lx lcount: %08lx, sar: %08lx\n",
363 regs->lbeg, regs->lend, regs->lcount, regs->sar);
364 if (user_mode(regs))
365 printk("wb: %08lx, ws: %08lx, wmask: %08lx, syscall: %ld\n",
366 regs->windowbase, regs->windowstart, regs->wmask,
367 regs->syscall);
368}
369
370void show_trace(struct task_struct *task, unsigned long *sp)
371{
372 unsigned long a0, a1, pc;
373 unsigned long sp_start, sp_end;
374
375 a1 = (unsigned long)sp;
376
377 if (a1 == 0)
378 __asm__ __volatile__ ("mov %0, a1\n" : "=a"(a1));
379
380
381 sp_start = a1 & ~(THREAD_SIZE-1);
382 sp_end = sp_start + THREAD_SIZE;
383
384 printk("Call Trace:");
385#ifdef CONFIG_KALLSYMS
386 printk("\n");
387#endif
388 spill_registers();
389
390 while (a1 > sp_start && a1 < sp_end) {
391 sp = (unsigned long*)a1;
392
393 a0 = *(sp - 4);
394 a1 = *(sp - 3);
395
396 if (a1 <= (unsigned long) sp)
397 break;
398
399 pc = MAKE_PC_FROM_RA(a0, a1);
400
401 if (kernel_text_address(pc)) {
402 printk(" [<%08lx>] ", pc);
403 print_symbol("%s\n", pc);
404 }
405 }
406 printk("\n");
407}
408
409/*
410 * This routine abuses get_user()/put_user() to reference pointers
411 * with at least a bit of error checking ...
412 */
413
414static int kstack_depth_to_print = 24;
415
416void show_stack(struct task_struct *task, unsigned long *sp)
417{
418 int i = 0;
419 unsigned long *stack;
420
421 if (sp == 0)
422 __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
423
424 stack = sp;
425
426 printk("\nStack: ");
427
428 for (i = 0; i < kstack_depth_to_print; i++) {
429 if (kstack_end(sp))
430 break;
431 if (i && ((i % 8) == 0))
432 printk("\n ");
433 printk("%08lx ", *sp++);
434 }
435 printk("\n");
436 show_trace(task, stack);
437}
438
439void dump_stack(void)
440{
441 show_stack(current, NULL);
442}
443
444EXPORT_SYMBOL(dump_stack);
445
446
447void show_code(unsigned int *pc)
448{
449 long i;
450
451 printk("\nCode:");
452
453 for(i = -3 ; i < 6 ; i++) {
454 unsigned long insn;
455 if (__get_user(insn, pc + i)) {
456 printk(" (Bad address in pc)\n");
457 break;
458 }
459 printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>'));
460 }
461}
462
463spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
464
465void die(const char * str, struct pt_regs * regs, long err)
466{
467 static int die_counter;
468 int nl = 0;
469
470 console_verbose();
471 spin_lock_irq(&die_lock);
472
473 printk("%s: sig: %ld [#%d]\n", str, err, ++die_counter);
474#ifdef CONFIG_PREEMPT
475 printk("PREEMPT ");
476 nl = 1;
477#endif
478 if (nl)
479 printk("\n");
480 show_regs(regs);
481 if (!user_mode(regs))
482 show_stack(NULL, (unsigned long*)regs->areg[1]);
483
484 spin_unlock_irq(&die_lock);
485
486 if (in_interrupt())
487 panic("Fatal exception in interrupt");
488
489 if (panic_on_oops) {
490 printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
491 set_current_state(TASK_UNINTERRUPTIBLE);
492 schedule_timeout(5 * HZ);
493 panic("Fatal exception");
494 }
495 do_exit(err);
496}
497
498
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
new file mode 100644
index 0000000000..81808f0c67
--- /dev/null
+++ b/arch/xtensa/kernel/vectors.S
@@ -0,0 +1,464 @@
1/*
2 * arch/xtensa/kernel/vectors.S
3 *
4 * This file contains all exception vectors (user, kernel, and double),
5 * as well as the window vectors (overflow and underflow), and the debug
6 * vector. These are the primary vectors executed by the processor if an
7 * exception occurs.
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of
11 * this archive for more details.
12 *
13 * Copyright (C) 2005 Tensilica, Inc.
14 *
15 * Chris Zankel <chris@zankel.net>
16 *
17 */
18
19/*
20 * We use a two-level table approach. The user and kernel exception vectors
21 * use a first-level dispatch table to dispatch the exception to a registered
22 * fast handler or the default handler, if no fast handler was registered.
23 * The default handler sets up a C-stack and dispatches the exception to a
24 * registerd C handler in the second-level dispatch table.
25 *
26 * Fast handler entry condition:
27 *
28 * a0: trashed, original value saved on stack (PT_AREG0)
29 * a1: a1
30 * a2: new stack pointer, original value in depc
31 * a3: dispatch table
32 * depc: a2, original value saved on stack (PT_DEPC)
33 * excsave_1: a3
34 *
35 * The value for PT_DEPC saved to stack also functions as a boolean to
36 * indicate that the exception is either a double or a regular exception:
37 *
38 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception
39 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
40 *
41 * Note: Neither the kernel nor the user exception handler generate literals.
42 *
43 */
44
45#include <linux/linkage.h>
46#include <asm/ptrace.h>
47#include <asm/ptrace.h>
48#include <asm/current.h>
49#include <asm/offsets.h>
50#include <asm/pgtable.h>
51#include <asm/processor.h>
52#include <asm/page.h>
53#include <asm/thread_info.h>
54#include <asm/processor.h>
55
56
57/*
58 * User exception vector. (Exceptions with PS.UM == 1, PS.EXCM == 0)
59 *
60 * We get here when an exception occurred while we were in userland.
61 * We switch to the kernel stack and jump to the first level handler
62 * associated to the exception cause.
63 *
64 * Note: the saved kernel stack pointer (EXC_TABLE_KSTK) is already
65 * decremented by PT_USER_SIZE.
66 */
67
68 .section .UserExceptionVector.text, "ax"
69
70ENTRY(_UserExceptionVector)
71
72 xsr a3, EXCSAVE_1 # save a3 and get dispatch table
73 wsr a2, DEPC # save a2
74 l32i a2, a3, EXC_TABLE_KSTK # load kernel stack to a2
75 s32i a0, a2, PT_AREG0 # save a0 to ESF
76 rsr a0, EXCCAUSE # retrieve exception cause
77 s32i a0, a2, PT_DEPC # mark it as a regular exception
78 addx4 a0, a0, a3 # find entry in table
79 l32i a0, a0, EXC_TABLE_FAST_USER # load handler
80 jx a0
81
82/*
83 * Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0)
84 *
85 * We get this exception when we were already in kernel space.
86 * We decrement the current stack pointer (kernel) by PT_SIZE and
87 * jump to the first-level handler associated with the exception cause.
88 *
89 * Note: we need to preserve space for the spill region.
90 */
91
92 .section .KernelExceptionVector.text, "ax"
93
94ENTRY(_KernelExceptionVector)
95
96 xsr a3, EXCSAVE_1 # save a3, and get dispatch table
97 wsr a2, DEPC # save a2
98 addi a2, a1, -16-PT_SIZE # adjust stack pointer
99 s32i a0, a2, PT_AREG0 # save a0 to ESF
100 rsr a0, EXCCAUSE # retrieve exception cause
101 s32i a0, a2, PT_DEPC # mark it as a regular exception
102 addx4 a0, a0, a3 # find entry in table
103 l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address
104 jx a0
105
106
107/*
108 * Double exception vector (Exceptions with PS.EXCM == 1)
109 * We get this exception when another exception occurs while were are
110 * already in an exception, such as window overflow/underflow exception,
111 * or 'expected' exceptions, for example memory exception when we were trying
112 * to read data from an invalid address in user space.
113 *
114 * Note that this vector is never invoked for level-1 interrupts, because such
115 * interrupts are disabled (masked) when PS.EXCM is set.
116 *
117 * We decode the exception and take the appropriate action. However, the
118 * double exception vector is much more careful, because a lot more error
119 * cases go through the double exception vector than through the user and
120 * kernel exception vectors.
121 *
122 * Occasionally, the kernel expects a double exception to occur. This usually
123 * happens when accessing user-space memory with the user's permissions
124 * (l32e/s32e instructions). The kernel state, though, is not always suitable
125 * for immediate transfer of control to handle_double, where "normal" exception
126 * processing occurs. Also in kernel mode, TLB misses can occur if accessing
127 * vmalloc memory, possibly requiring repair in a double exception handler.
128 *
129 * The variable at TABLE_FIXUP offset from the pointer in EXCSAVE_1 doubles as
130 * a boolean variable and a pointer to a fixup routine. If the variable
131 * EXC_TABLE_FIXUP is non-zero, this handler jumps to that address. A value of
132 * zero indicates to use the default kernel/user exception handler.
133 * There is only one exception, when the value is identical to the exc_table
134 * label, the kernel is in trouble. This mechanism is used to protect critical
135 * sections, mainly when the handler writes to the stack to assert the stack
136 * pointer is valid. Once the fixup/default handler leaves that area, the
137 * EXC_TABLE_FIXUP variable is reset to the fixup handler or zero.
138 *
139 * Procedures wishing to use this mechanism should set EXC_TABLE_FIXUP to the
140 * nonzero address of a fixup routine before it could cause a double exception
141 * and reset it before it returns.
142 *
143 * Some other things to take care of when a fast exception handler doesn't
144 * specify a particular fixup handler but wants to use the default handlers:
145 *
146 * - The original stack pointer (in a1) must not be modified. The fast
147 * exception handler should only use a2 as the stack pointer.
148 *
149 * - If the fast handler manipulates the stack pointer (in a2), it has to
150 * register a valid fixup handler and cannot use the default handlers.
151 *
152 * - The handler can use any other generic register from a3 to a15, but it
153 * must save the content of these registers to stack (PT_AREG3...PT_AREGx)
154 *
155 * - These registers must be saved before a double exception can occur.
156 *
157 * - If we ever implement handling signals while in double exceptions, the
158 * number of registers a fast handler has saved (excluding a0 and a1) must
159 * be written to PT_AREG1. (1 if only a3 is used, 2 for a3 and a4, etc. )
160 *
161 * The fixup handlers are special handlers:
162 *
163 * - Fixup entry conditions differ from regular exceptions:
164 *
165 * a0: DEPC
166 * a1: a1
167 * a2: trashed, original value in EXC_TABLE_DOUBLE_A2
168 * a3: exctable
169 * depc: a0
170 * excsave_1: a3
171 *
172 * - When the kernel enters the fixup handler, it still assumes it is in a
173 * critical section, so EXC_TABLE_FIXUP variable is set to exc_table.
174 * The fixup handler, therefore, has to re-register itself as the fixup
175 * handler before it returns from the double exception.
176 *
177 * - Fixup handler can share the same exception frame with the fast handler.
178 * The kernel stack pointer is not changed when entering the fixup handler.
179 *
180 * - Fixup handlers can jump to the default kernel and user exception
181 * handlers. Before it jumps, though, it has to setup a exception frame
182 * on stack. Because the default handler resets the register fixup handler
183 * the fixup handler must make sure that the default handler returns to
184 * it instead of the exception address, so it can re-register itself as
185 * the fixup handler.
186 *
187 * In case of a critical condition where the kernel cannot recover, we jump
188 * to unrecoverable_exception with the following entry conditions.
189 * All registers a0...a15 are unchanged from the last exception, except:
190 *
191 * a0: last address before we jumped to the unrecoverable_exception.
192 * excsave_1: a0
193 *
194 *
195 * See the handle_alloca_user and spill_registers routines for example clients.
196 *
197 * FIXME: Note: we currently don't allow signal handling coming from a double
198 * exception, so the item markt with (*) is not required.
199 */
200
201 .section .DoubleExceptionVector.text, "ax"
202 .begin literal_prefix .DoubleExceptionVector
203
204ENTRY(_DoubleExceptionVector)
205
206 /* Deliberately destroy excsave (don't assume it's value was valid). */
207
208 wsr a3, EXCSAVE_1 # save a3
209
210 /* Check for kernel double exception (usually fatal). */
211
212 rsr a3, PS
213 _bbci.l a3, PS_UM_SHIFT, .Lksp
214
215 /* Check if we are currently handling a window exception. */
216 /* Note: We don't need to indicate that we enter a critical section. */
217
218 xsr a0, DEPC # get DEPC, save a0
219
220 movi a3, XCHAL_WINDOW_VECTORS_VADDR
221 _bltu a0, a3, .Lfixup
222 addi a3, a3, XSHAL_WINDOW_VECTORS_SIZE
223 _bgeu a0, a3, .Lfixup
224
225 /* Window overflow/underflow exception. Get stack pointer. */
226
227 mov a3, a2
228 movi a2, exc_table
229 l32i a2, a2, EXC_TABLE_KSTK
230
231 /* Check for overflow/underflow exception, jump if overflow. */
232
233 _bbci.l a0, 6, .Lovfl
234
235 /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
236
237 /* Restart window underflow exception.
238 * We return to the instruction in user space that caused the window
239 * underflow exception. Therefore, we change window base to the value
240 * before we entered the window underflow exception and prepare the
241 * registers to return as if we were coming from a regular exception
242 * by changing depc (in a0).
243 * Note: We can trash the current window frame (a0...a3) and depc!
244 */
245
246 wsr a2, DEPC # save stack pointer temporarily
247 rsr a0, PS
248 extui a0, a0, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
249 wsr a0, WINDOWBASE
250 rsync
251
252 /* We are now in the previous window frame. Save registers again. */
253
254 xsr a2, DEPC # save a2 and get stack pointer
255 s32i a0, a2, PT_AREG0
256
257 wsr a3, EXCSAVE_1 # save a3
258 movi a3, exc_table
259
260 rsr a0, EXCCAUSE
261 s32i a0, a2, PT_DEPC # mark it as a regular exception
262 addx4 a0, a0, a3
263 l32i a0, a0, EXC_TABLE_FAST_USER
264 jx a0
265
266.Lfixup:/* Check for a fixup handler or if we were in a critical section. */
267
268 /* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */
269
270 movi a3, exc_table
271 s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable
272
273 /* Enter critical section. */
274
275 l32i a2, a3, EXC_TABLE_FIXUP
276 s32i a3, a3, EXC_TABLE_FIXUP
277 beq a2, a3, .Lunrecoverable_fixup # critical!
278 beqz a2, .Ldflt # no handler was registered
279
280 /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */
281
282 jx a2
283
284.Ldflt: /* Get stack pointer. */
285
286 l32i a3, a3, EXC_TABLE_DOUBLE_SAVE
287 addi a2, a3, -PT_USER_SIZE
288
289.Lovfl: /* Jump to default handlers. */
290
291 /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
292
293 xsr a3, DEPC
294 s32i a0, a2, PT_DEPC
295 s32i a3, a2, PT_AREG0
296
297 /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */
298
299 movi a3, exc_table
300 rsr a0, EXCCAUSE
301 addx4 a0, a0, a3
302 l32i a0, a0, EXC_TABLE_FAST_USER
303 jx a0
304
305 /*
306 * We only allow the ITLB miss exception if we are in kernel space.
307 * All other exceptions are unexpected and thus unrecoverable!
308 */
309
310 .extern fast_second_level_miss_double_kernel
311
312.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
313
314 rsr a3, EXCCAUSE
315 beqi a3, XCHAL_EXCCAUSE_ITLB_MISS, 1f
316 addi a3, a3, -XCHAL_EXCCAUSE_DTLB_MISS
317 bnez a3, .Lunrecoverable
3181: movi a3, fast_second_level_miss_double_kernel
319 jx a3
320
321 /* Critical! We can't handle this situation. PANIC! */
322
323 .extern unrecoverable_exception
324
325.Lunrecoverable_fixup:
326 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
327 xsr a0, DEPC
328
329.Lunrecoverable:
330 rsr a3, EXCSAVE_1
331 wsr a0, EXCSAVE_1
332 movi a0, unrecoverable_exception
333 callx0 a0
334
335 .end literal_prefix
336
337
338/*
339 * Debug interrupt vector
340 *
341 * There is not much space here, so simply jump to another handler.
342 * EXCSAVE[DEBUGLEVEL] has been set to that handler.
343 */
344
345 .section .DebugInterruptVector.text, "ax"
346
347ENTRY(_DebugInterruptVector)
348 xsr a0, EXCSAVE + XCHAL_DEBUGLEVEL
349 jx a0
350
351
352
353/* Window overflow and underflow handlers.
354 * The handlers must be 64 bytes apart, first starting with the underflow
355 * handlers underflow-4 to underflow-12, then the overflow handlers
356 * overflow-4 to overflow-12.
357 *
358 * Note: We rerun the underflow handlers if we hit an exception, so
359 * we try to access any page that would cause a page fault early.
360 */
361
362 .section .WindowVectors.text, "ax"
363
364
365/* 4-Register Window Overflow Vector (Handler) */
366
367 .align 64
368.global _WindowOverflow4
369_WindowOverflow4:
370 s32e a0, a5, -16
371 s32e a1, a5, -12
372 s32e a2, a5, -8
373 s32e a3, a5, -4
374 rfwo
375
376
377/* 4-Register Window Underflow Vector (Handler) */
378
379 .align 64
380.global _WindowUnderflow4
381_WindowUnderflow4:
382 l32e a0, a5, -16
383 l32e a1, a5, -12
384 l32e a2, a5, -8
385 l32e a3, a5, -4
386 rfwu
387
388
389/* 8-Register Window Overflow Vector (Handler) */
390
391 .align 64
392.global _WindowOverflow8
393_WindowOverflow8:
394 s32e a0, a9, -16
395 l32e a0, a1, -12
396 s32e a2, a9, -8
397 s32e a1, a9, -12
398 s32e a3, a9, -4
399 s32e a4, a0, -32
400 s32e a5, a0, -28
401 s32e a6, a0, -24
402 s32e a7, a0, -20
403 rfwo
404
405/* 8-Register Window Underflow Vector (Handler) */
406
407 .align 64
408.global _WindowUnderflow8
409_WindowUnderflow8:
410 l32e a1, a9, -12
411 l32e a0, a9, -16
412 l32e a7, a1, -12
413 l32e a2, a9, -8
414 l32e a4, a7, -32
415 l32e a3, a9, -4
416 l32e a5, a7, -28
417 l32e a6, a7, -24
418 l32e a7, a7, -20
419 rfwu
420
421
422/* 12-Register Window Overflow Vector (Handler) */
423
424 .align 64
425.global _WindowOverflow12
426_WindowOverflow12:
427 s32e a0, a13, -16
428 l32e a0, a1, -12
429 s32e a1, a13, -12
430 s32e a2, a13, -8
431 s32e a3, a13, -4
432 s32e a4, a0, -48
433 s32e a5, a0, -44
434 s32e a6, a0, -40
435 s32e a7, a0, -36
436 s32e a8, a0, -32
437 s32e a9, a0, -28
438 s32e a10, a0, -24
439 s32e a11, a0, -20
440 rfwo
441
442/* 12-Register Window Underflow Vector (Handler) */
443
444 .align 64
445.global _WindowUnderflow12
446_WindowUnderflow12:
447 l32e a1, a13, -12
448 l32e a0, a13, -16
449 l32e a11, a1, -12
450 l32e a2, a13, -8
451 l32e a4, a11, -48
452 l32e a8, a11, -32
453 l32e a3, a13, -4
454 l32e a5, a11, -44
455 l32e a6, a11, -40
456 l32e a7, a11, -36
457 l32e a9, a11, -28
458 l32e a10, a11, -24
459 l32e a11, a11, -20
460 rfwu
461
462 .text
463
464
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
new file mode 100644
index 0000000000..476b2b53cd
--- /dev/null
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -0,0 +1,341 @@
1/*
2 * arch/xtensa/kernel/vmlinux.lds.S
3 *
4 * Xtensa linker script
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
14 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
15 */
16
17#include <asm-generic/vmlinux.lds.h>
18
19#include <linux/config.h>
20#define _NOCLANGUAGE
21#include <xtensa/config/core.h>
22#include <xtensa/config/system.h>
23OUTPUT_ARCH(xtensa)
24ENTRY(_start)
25
26#if XCHAL_MEMORY_ORDER == XTHAL_BIGENDIAN
27jiffies = jiffies_64 + 4;
28#else
29jiffies = jiffies_64;
30#endif
31
32#define KERNELOFFSET 0x1000
33
34/* Note: In the following macros, it would be nice to specify only the
35 vector name and section kind and construct "sym" and "section" using
36 CPP concatenation, but that does not work reliably. Concatenating a
37 string with "." produces an invalid token. CPP will not print a
38 warning because it thinks this is an assembly file, but it leaves
39 them as multiple tokens and there may or may not be whitespace
40 between them. */
41
42/* Macro for a relocation entry */
43
44#define RELOCATE_ENTRY(sym, section) \
45 LONG(sym ## _start); \
46 LONG(sym ## _end); \
47 LONG(LOADADDR(section))
48
49/* Macro to define a section for a vector.
50 *
51 * Use of the MIN function catches the types of errors illustrated in
52 * the following example:
53 *
54 * Assume the section .DoubleExceptionVector.literal is completely
55 * full. Then a programmer adds code to .DoubleExceptionVector.text
56 * that produces another literal. The final literal position will
57 * overlay onto the first word of the adjacent code section
58 * .DoubleExceptionVector.text. (In practice, the literals will
59 * overwrite the code, and the first few instructions will be
60 * garbage.)
61 */
62
63#define SECTION_VECTOR(sym, section, addr, max_prevsec_size, prevsec) \
64 section addr : AT((MIN(LOADADDR(prevsec) + max_prevsec_size, \
65 LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3) \
66 { \
67 . = ALIGN(4); \
68 sym ## _start = ABSOLUTE(.); \
69 *(section) \
70 sym ## _end = ABSOLUTE(.); \
71 }
72
73/*
74 * Mapping of input sections to output sections when linking.
75 */
76
77SECTIONS
78{
79 . = XCHAL_KSEG_CACHED_VADDR + KERNELOFFSET;
80 /* .text section */
81
82 _text = .;
83 _stext = .;
84 _ftext = .;
85
86 .text :
87 {
88 /* The .head.text section must be the first section! */
89 *(.head.text)
90 *(.literal .text)
91 *(.srom.text)
92 VMLINUX_SYMBOL(__sched_text_start) = .;
93 *(.sched.text.literal .sched.text)
94 VMLINUX_SYMBOL(__sched_text_end) = .;
95 VMLINUX_SYMBOL(__lock_text_start) = .;
96 *(.spinlock.text.literal .spinlock.text)
97 VMLINUX_SYMBOL(__lock_text_end) = .;
98
99 }
100 _etext = .;
101
102 . = ALIGN(16);
103
104 RODATA
105
106 /* Relocation table */
107
108 . = ALIGN(16);
109 __boot_reloc_table_start = ABSOLUTE(.);
110
111 __relocate : {
112
113 RELOCATE_ENTRY(_WindowVectors_text,
114 .WindowVectors.text);
115#if 0
116 RELOCATE_ENTRY(_KernelExceptionVector_literal,
117 .KernelExceptionVector.literal);
118#endif
119 RELOCATE_ENTRY(_KernelExceptionVector_text,
120 .KernelExceptionVector.text);
121#if 0
122 RELOCATE_ENTRY(_UserExceptionVector_literal,
123 .UserExceptionVector.literal);
124#endif
125 RELOCATE_ENTRY(_UserExceptionVector_text,
126 .UserExceptionVector.text);
127 RELOCATE_ENTRY(_DoubleExceptionVector_literal,
128 .DoubleExceptionVector.literal);
129 RELOCATE_ENTRY(_DoubleExceptionVector_text,
130 .DoubleExceptionVector.text);
131 }
132 __boot_reloc_table_end = ABSOLUTE(.) ;
133
134 .fixup : { *(.fixup) }
135
136 . = ALIGN(16);
137
138 __ex_table : {
139 __start___ex_table = .;
140 *(__ex_table)
141 __stop___ex_table = .;
142 }
143
144 /* Data section */
145
146 . = ALIGN(XCHAL_ICACHE_LINESIZE);
147 _fdata = .;
148 .data :
149 {
150 *(.data) CONSTRUCTORS
151 . = ALIGN(XCHAL_ICACHE_LINESIZE);
152 *(.data.cacheline_aligned)
153 }
154
155 _edata = .;
156
157 /* The initial task */
158 . = ALIGN(8192);
159 .data.init_task : { *(.data.init_task) }
160
161 /* Initialization code and data: */
162
163 . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
164 __init_begin = .;
165 .init.text : {
166 _sinittext = .;
167 *(.init.text.literal) *(.init.text)
168 _einittext = .;
169 }
170
171 .init.data :
172 {
173 *(.init.data)
174 . = ALIGN(0x4);
175 __tagtable_begin = .;
176 *(.taglist)
177 __tagtable_end = .;
178 }
179
180 . = ALIGN(XCHAL_ICACHE_LINESIZE);
181
182 __setup_start = .;
183 .init.setup : { *(.init.setup) }
184 __setup_end = .;
185
186 __initcall_start = .;
187 .initcall.init : {
188 *(.initcall1.init)
189 *(.initcall2.init)
190 *(.initcall3.init)
191 *(.initcall4.init)
192 *(.initcall5.init)
193 *(.initcall6.init)
194 *(.initcall7.init)
195 }
196 __initcall_end = .;
197
198 __con_initcall_start = .;
199 .con_initcall.init : { *(.con_initcall.init) }
200 __con_initcall_end = .;
201
202 SECURITY_INIT
203
204 . = ALIGN(4);
205
206 __start___ftr_fixup = .;
207 __ftr_fixup : { *(__ftr_fixup) }
208 __stop___ftr_fixup = .;
209
210 . = ALIGN(32);
211 __per_cpu_start = .;
212 .data.percpu : { *(.data.percpu) }
213 __per_cpu_end = .;
214
215 . = ALIGN(4096);
216 __initramfs_start =.;
217 .init.ramfs : { *(.init.ramfs) }
218 __initramfs_end = .;
219
220 /* We need this dummy segment here */
221
222 . = ALIGN(4);
223 .dummy : { LONG(0) }
224
225 /* The vectors are relocated to the real position at startup time */
226
227 SECTION_VECTOR (_WindowVectors_text,
228 .WindowVectors.text,
229 XCHAL_WINDOW_VECTORS_VADDR, 4,
230 .dummy)
231 SECTION_VECTOR (_DebugInterruptVector_literal,
232 .DebugInterruptVector.literal,
233 XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL) - 4,
234 SIZEOF(.WindowVectors.text),
235 .WindowVectors.text)
236 SECTION_VECTOR (_DebugInterruptVector_text,
237 .DebugInterruptVector.text,
238 XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL),
239 4,
240 .DebugInterruptVector.literal)
241 SECTION_VECTOR (_KernelExceptionVector_literal,
242 .KernelExceptionVector.literal,
243 XCHAL_KERNELEXC_VECTOR_VADDR - 4,
244 SIZEOF(.DebugInterruptVector.text),
245 .DebugInterruptVector.text)
246 SECTION_VECTOR (_KernelExceptionVector_text,
247 .KernelExceptionVector.text,
248 XCHAL_KERNELEXC_VECTOR_VADDR,
249 4,
250 .KernelExceptionVector.literal)
251 SECTION_VECTOR (_UserExceptionVector_literal,
252 .UserExceptionVector.literal,
253 XCHAL_USEREXC_VECTOR_VADDR - 4,
254 SIZEOF(.KernelExceptionVector.text),
255 .KernelExceptionVector.text)
256 SECTION_VECTOR (_UserExceptionVector_text,
257 .UserExceptionVector.text,
258 XCHAL_USEREXC_VECTOR_VADDR,
259 4,
260 .UserExceptionVector.literal)
261 SECTION_VECTOR (_DoubleExceptionVector_literal,
262 .DoubleExceptionVector.literal,
263 XCHAL_DOUBLEEXC_VECTOR_VADDR - 16,
264 SIZEOF(.UserExceptionVector.text),
265 .UserExceptionVector.text)
266 SECTION_VECTOR (_DoubleExceptionVector_text,
267 .DoubleExceptionVector.text,
268 XCHAL_DOUBLEEXC_VECTOR_VADDR,
269 32,
270 .DoubleExceptionVector.literal)
271
272 . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
273 . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
274
275 __init_end = .;
276
277 . = ALIGN(8192);
278
279 /* BSS section */
280 _bss_start = .;
281 .sbss : { *(.sbss) *(.scommon) }
282 .bss : { *(COMMON) *(.bss) }
283 _bss_end = .;
284 _end = .;
285
286 /* only used by the boot loader */
287
288 . = ALIGN(0x10);
289 .bootstrap : { *(.bootstrap.literal .bootstrap.text .bootstrap.data) }
290
291 . = ALIGN(0x1000);
292 __initrd_start = .;
293 .initrd : { *(.initrd) }
294 __initrd_end = .;
295
296 .ResetVector.text XCHAL_RESET_VECTOR_VADDR :
297 {
298 *(.ResetVector.text)
299 }
300
301
302 /* Sections to be discarded */
303 /DISCARD/ :
304 {
305 *(.text.exit)
306 *(.text.exit.literal)
307 *(.data.exit)
308 *(.exitcall.exit)
309 }
310
311
312 .debug 0 : { *(.debug) }
313 .line 0 : { *(.line) }
314 .debug_srcinfo 0 : { *(.debug_srcinfo) }
315 .debug_sfnames 0 : { *(.debug_sfnames) }
316 .debug_aranges 0 : { *(.debug_aranges) }
317 .debug_pubnames 0 : { *(.debug_pubnames) }
318 .debug_info 0 : { *(.debug_info) }
319 .debug_abbrev 0 : { *(.debug_abbrev) }
320 .debug_line 0 : { *(.debug_line) }
321 .debug_frame 0 : { *(.debug_frame) }
322 .debug_str 0 : { *(.debug_str) }
323 .debug_loc 0 : { *(.debug_loc) }
324 .debug_macinfo 0 : { *(.debug_macinfo) }
325 .debug_weaknames 0 : { *(.debug_weaknames) }
326 .debug_funcnames 0 : { *(.debug_funcnames) }
327 .debug_typenames 0 : { *(.debug_typenames) }
328 .debug_varnames 0 : { *(.debug_varnames) }
329
330 .xt.insn 0 :
331 {
332 *(.xt.insn)
333 *(.gnu.linkonce.x*)
334 }
335
336 .xt.lit 0 :
337 {
338 *(.xt.lit)
339 *(.gnu.linkonce.p*)
340 }
341}
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
new file mode 100644
index 0000000000..efae56a514
--- /dev/null
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -0,0 +1,123 @@
1/*
2 * arch/xtensa/kernel/xtensa_ksyms.c
3 *
4 * Export Xtensa-specific functions for loadable modules.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 *
12 * Joe Taylor <joe@tensilica.com>
13 */
14
15#include <linux/config.h>
16#include <linux/module.h>
17#include <linux/string.h>
18#include <linux/mm.h>
19#include <linux/interrupt.h>
20#include <asm/irq.h>
21#include <linux/in6.h>
22#include <linux/pci.h>
23#include <linux/ide.h>
24
25#include <asm/uaccess.h>
26#include <asm/checksum.h>
27#include <asm/dma.h>
28#include <asm/io.h>
29#include <asm/page.h>
30#include <asm/pgalloc.h>
31#include <asm/semaphore.h>
32#ifdef CONFIG_BLK_DEV_FD
33#include <asm/floppy.h>
34#endif
35#ifdef CONFIG_NET
36#include <net/checksum.h>
37#endif /* CONFIG_NET */
38
39
40/*
41 * String functions
42 */
43EXPORT_SYMBOL(memcmp);
44EXPORT_SYMBOL(memset);
45EXPORT_SYMBOL(memcpy);
46EXPORT_SYMBOL(memmove);
47EXPORT_SYMBOL(memchr);
48EXPORT_SYMBOL(strcat);
49EXPORT_SYMBOL(strchr);
50EXPORT_SYMBOL(strlen);
51EXPORT_SYMBOL(strpbrk);
52EXPORT_SYMBOL(strncat);
53EXPORT_SYMBOL(strnlen);
54EXPORT_SYMBOL(strrchr);
55EXPORT_SYMBOL(strstr);
56
57EXPORT_SYMBOL(enable_irq);
58EXPORT_SYMBOL(disable_irq);
59EXPORT_SYMBOL(kernel_thread);
60
61/*
62 * gcc internal math functions
63 */
64extern long long __ashrdi3(long long, int);
65extern long long __ashldi3(long long, int);
66extern long long __lshrdi3(long long, int);
67extern int __divsi3(int, int);
68extern int __modsi3(int, int);
69extern long long __muldi3(long long, long long);
70extern int __mulsi3(int, int);
71extern unsigned int __udivsi3(unsigned int, unsigned int);
72extern unsigned int __umodsi3(unsigned int, unsigned int);
73extern unsigned long long __umoddi3(unsigned long long, unsigned long long);
74extern unsigned long long __udivdi3(unsigned long long, unsigned long long);
75
76EXPORT_SYMBOL(__ashldi3);
77EXPORT_SYMBOL(__ashrdi3);
78EXPORT_SYMBOL(__lshrdi3);
79EXPORT_SYMBOL(__divsi3);
80EXPORT_SYMBOL(__modsi3);
81EXPORT_SYMBOL(__muldi3);
82EXPORT_SYMBOL(__mulsi3);
83EXPORT_SYMBOL(__udivsi3);
84EXPORT_SYMBOL(__umodsi3);
85EXPORT_SYMBOL(__udivdi3);
86EXPORT_SYMBOL(__umoddi3);
87
88/*
89 * Semaphore operations
90 */
91EXPORT_SYMBOL(__down);
92EXPORT_SYMBOL(__down_interruptible);
93EXPORT_SYMBOL(__down_trylock);
94EXPORT_SYMBOL(__up);
95
96#ifdef CONFIG_NET
97/*
98 * Networking support
99 */
100EXPORT_SYMBOL(csum_partial_copy_generic);
101#endif /* CONFIG_NET */
102
103/*
104 * Architecture-specific symbols
105 */
106EXPORT_SYMBOL(__xtensa_copy_user);
107
108/*
109 * Kernel hacking ...
110 */
111
112#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
113// FIXME EXPORT_SYMBOL(screen_info);
114#endif
115
116EXPORT_SYMBOL(get_wchan);
117
118EXPORT_SYMBOL(outsb);
119EXPORT_SYMBOL(outsw);
120EXPORT_SYMBOL(outsl);
121EXPORT_SYMBOL(insb);
122EXPORT_SYMBOL(insw);
123EXPORT_SYMBOL(insl);
diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile
new file mode 100644
index 0000000000..ed935b58e8
--- /dev/null
+++ b/arch/xtensa/lib/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for Xtensa-specific library files.
3#
4
5lib-y += memcopy.o memset.o checksum.o strcasecmp.o \
6 usercopy.o strncpy_user.o strnlen_user.o
7lib-$(CONFIG_PCI) += pci-auto.o
diff --git a/arch/xtensa/lib/checksum.S b/arch/xtensa/lib/checksum.S
new file mode 100644
index 0000000000..e2d64dfd53
--- /dev/null
+++ b/arch/xtensa/lib/checksum.S
@@ -0,0 +1,410 @@
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * IP/TCP/UDP checksumming routines
7 *
8 * Xtensa version: Copyright (C) 2001 Tensilica, Inc. by Kevin Chea
9 * Optimized by Joe Taylor
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
17#include <asm/errno.h>
18#include <linux/linkage.h>
19#define _ASMLANGUAGE
20#include <xtensa/config/core.h>
21
22/*
23 * computes a partial checksum, e.g. for TCP/UDP fragments
24 */
25
26/*
27 * unsigned int csum_partial(const unsigned char *buf, int len,
28 * unsigned int sum);
29 * a2 = buf
30 * a3 = len
31 * a4 = sum
32 *
33 * This function assumes 2- or 4-byte alignment. Other alignments will fail!
34 */
35
36/* ONES_ADD converts twos-complement math to ones-complement. */
37#define ONES_ADD(sum, val) \
38 add sum, sum, val ; \
39 bgeu sum, val, 99f ; \
40 addi sum, sum, 1 ; \
4199: ;
42
43.text
44ENTRY(csum_partial)
45 /*
46 * Experiments with Ethernet and SLIP connections show that buf
47 * is aligned on either a 2-byte or 4-byte boundary.
48 */
49 entry sp, 32
50 extui a5, a2, 0, 2
51 bnez a5, 8f /* branch if 2-byte aligned */
52 /* Fall-through on common case, 4-byte alignment */
531:
54 srli a5, a3, 5 /* 32-byte chunks */
55#if XCHAL_HAVE_LOOPS
56 loopgtz a5, 2f
57#else
58 beqz a5, 2f
59 slli a5, a5, 5
60 add a5, a5, a2 /* a5 = end of last 32-byte chunk */
61.Loop1:
62#endif
63 l32i a6, a2, 0
64 l32i a7, a2, 4
65 ONES_ADD(a4, a6)
66 ONES_ADD(a4, a7)
67 l32i a6, a2, 8
68 l32i a7, a2, 12
69 ONES_ADD(a4, a6)
70 ONES_ADD(a4, a7)
71 l32i a6, a2, 16
72 l32i a7, a2, 20
73 ONES_ADD(a4, a6)
74 ONES_ADD(a4, a7)
75 l32i a6, a2, 24
76 l32i a7, a2, 28
77 ONES_ADD(a4, a6)
78 ONES_ADD(a4, a7)
79 addi a2, a2, 4*8
80#if !XCHAL_HAVE_LOOPS
81 blt a2, a5, .Loop1
82#endif
832:
84 extui a5, a3, 2, 3 /* remaining 4-byte chunks */
85#if XCHAL_HAVE_LOOPS
86 loopgtz a5, 3f
87#else
88 beqz a5, 3f
89 slli a5, a5, 2
90 add a5, a5, a2 /* a5 = end of last 4-byte chunk */
91.Loop2:
92#endif
93 l32i a6, a2, 0
94 ONES_ADD(a4, a6)
95 addi a2, a2, 4
96#if !XCHAL_HAVE_LOOPS
97 blt a2, a5, .Loop2
98#endif
993:
100 _bbci.l a3, 1, 5f /* remaining 2-byte chunk */
101 l16ui a6, a2, 0
102 ONES_ADD(a4, a6)
103 addi a2, a2, 2
1045:
105 _bbci.l a3, 0, 7f /* remaining 1-byte chunk */
1066: l8ui a6, a2, 0
107#ifdef __XTENSA_EB__
108 slli a6, a6, 8 /* load byte into bits 8..15 */
109#endif
110 ONES_ADD(a4, a6)
1117:
112 mov a2, a4
113 retw
114
115 /* uncommon case, buf is 2-byte aligned */
1168:
117 beqz a3, 7b /* branch if len == 0 */
118 beqi a3, 1, 6b /* branch if len == 1 */
119
120 extui a5, a2, 0, 1
121 bnez a5, 8f /* branch if 1-byte aligned */
122
123 l16ui a6, a2, 0 /* common case, len >= 2 */
124 ONES_ADD(a4, a6)
125 addi a2, a2, 2 /* adjust buf */
126 addi a3, a3, -2 /* adjust len */
127 j 1b /* now buf is 4-byte aligned */
128
129 /* case: odd-byte aligned, len > 1
130 * This case is dog slow, so don't give us an odd address.
131 * (I don't think this ever happens, but just in case.)
132 */
1338:
134 srli a5, a3, 2 /* 4-byte chunks */
135#if XCHAL_HAVE_LOOPS
136 loopgtz a5, 2f
137#else
138 beqz a5, 2f
139 slli a5, a5, 2
140 add a5, a5, a2 /* a5 = end of last 4-byte chunk */
141.Loop3:
142#endif
143 l8ui a6, a2, 0 /* bits 24..31 */
144 l16ui a7, a2, 1 /* bits 8..23 */
145 l8ui a8, a2, 3 /* bits 0.. 8 */
146#ifdef __XTENSA_EB__
147 slli a6, a6, 24
148#else
149 slli a8, a8, 24
150#endif
151 slli a7, a7, 8
152 or a7, a7, a6
153 or a7, a7, a8
154 ONES_ADD(a4, a7)
155 addi a2, a2, 4
156#if !XCHAL_HAVE_LOOPS
157 blt a2, a5, .Loop3
158#endif
1592:
160 _bbci.l a3, 1, 3f /* remaining 2-byte chunk, still odd addr */
161 l8ui a6, a2, 0
162 l8ui a7, a2, 1
163#ifdef __XTENSA_EB__
164 slli a6, a6, 8
165#else
166 slli a7, a7, 8
167#endif
168 or a7, a7, a6
169 ONES_ADD(a4, a7)
170 addi a2, a2, 2
1713:
172 j 5b /* branch to handle the remaining byte */
173
174
175
176/*
177 * Copy from ds while checksumming, otherwise like csum_partial
178 *
179 * The macros SRC and DST specify the type of access for the instruction.
180 * thus we can call a custom exception handler for each access type.
181 */
182
183#define SRC(y...) \
184 9999: y; \
185 .section __ex_table, "a"; \
186 .long 9999b, 6001f ; \
187 .previous
188
189#define DST(y...) \
190 9999: y; \
191 .section __ex_table, "a"; \
192 .long 9999b, 6002f ; \
193 .previous
194
195/*
196unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
197 int sum, int *src_err_ptr, int *dst_err_ptr)
198 a2 = src
199 a3 = dst
200 a4 = len
201 a5 = sum
202 a6 = src_err_ptr
203 a7 = dst_err_ptr
204 a8 = temp
205 a9 = temp
206 a10 = temp
207 a11 = original len for exception handling
208 a12 = original dst for exception handling
209
210 This function is optimized for 4-byte aligned addresses. Other
211 alignments work, but not nearly as efficiently.
212 */
213
214ENTRY(csum_partial_copy_generic)
215 entry sp, 32
216 mov a12, a3
217 mov a11, a4
218 or a10, a2, a3
219
220 /* We optimize the following alignment tests for the 4-byte
221 aligned case. Two bbsi.l instructions might seem more optimal
222 (commented out below). However, both labels 5: and 3: are out
223 of the imm8 range, so the assembler relaxes them into
224 equivalent bbci.l, j combinations, which is actually
225 slower. */
226
227 extui a9, a10, 0, 2
228 beqz a9, 1f /* branch if both are 4-byte aligned */
229 bbsi.l a10, 0, 5f /* branch if one address is odd */
230 j 3f /* one address is 2-byte aligned */
231
232/* _bbsi.l a10, 0, 5f */ /* branch if odd address */
233/* _bbsi.l a10, 1, 3f */ /* branch if 2-byte-aligned address */
234
2351:
236 /* src and dst are both 4-byte aligned */
237 srli a10, a4, 5 /* 32-byte chunks */
238#if XCHAL_HAVE_LOOPS
239 loopgtz a10, 2f
240#else
241 beqz a10, 2f
242 slli a10, a10, 5
243 add a10, a10, a2 /* a10 = end of last 32-byte src chunk */
244.Loop5:
245#endif
246SRC( l32i a9, a2, 0 )
247SRC( l32i a8, a2, 4 )
248DST( s32i a9, a3, 0 )
249DST( s32i a8, a3, 4 )
250 ONES_ADD(a5, a9)
251 ONES_ADD(a5, a8)
252SRC( l32i a9, a2, 8 )
253SRC( l32i a8, a2, 12 )
254DST( s32i a9, a3, 8 )
255DST( s32i a8, a3, 12 )
256 ONES_ADD(a5, a9)
257 ONES_ADD(a5, a8)
258SRC( l32i a9, a2, 16 )
259SRC( l32i a8, a2, 20 )
260DST( s32i a9, a3, 16 )
261DST( s32i a8, a3, 20 )
262 ONES_ADD(a5, a9)
263 ONES_ADD(a5, a8)
264SRC( l32i a9, a2, 24 )
265SRC( l32i a8, a2, 28 )
266DST( s32i a9, a3, 24 )
267DST( s32i a8, a3, 28 )
268 ONES_ADD(a5, a9)
269 ONES_ADD(a5, a8)
270 addi a2, a2, 32
271 addi a3, a3, 32
272#if !XCHAL_HAVE_LOOPS
273 blt a2, a10, .Loop5
274#endif
2752:
276 extui a10, a4, 2, 3 /* remaining 4-byte chunks */
277 extui a4, a4, 0, 2 /* reset len for general-case, 2-byte chunks */
278#if XCHAL_HAVE_LOOPS
279 loopgtz a10, 3f
280#else
281 beqz a10, 3f
282 slli a10, a10, 2
283 add a10, a10, a2 /* a10 = end of last 4-byte src chunk */
284.Loop6:
285#endif
286SRC( l32i a9, a2, 0 )
287DST( s32i a9, a3, 0 )
288 ONES_ADD(a5, a9)
289 addi a2, a2, 4
290 addi a3, a3, 4
291#if !XCHAL_HAVE_LOOPS
292 blt a2, a10, .Loop6
293#endif
2943:
295 /*
296 Control comes to here in two cases: (1) It may fall through
297 to here from the 4-byte alignment case to process, at most,
298 one 2-byte chunk. (2) It branches to here from above if
299 either src or dst is 2-byte aligned, and we process all bytes
300 here, except for perhaps a trailing odd byte. It's
301 inefficient, so align your addresses to 4-byte boundaries.
302
303 a2 = src
304 a3 = dst
305 a4 = len
306 a5 = sum
307 */
308 srli a10, a4, 1 /* 2-byte chunks */
309#if XCHAL_HAVE_LOOPS
310 loopgtz a10, 4f
311#else
312 beqz a10, 4f
313 slli a10, a10, 1
314 add a10, a10, a2 /* a10 = end of last 2-byte src chunk */
315.Loop7:
316#endif
317SRC( l16ui a9, a2, 0 )
318DST( s16i a9, a3, 0 )
319 ONES_ADD(a5, a9)
320 addi a2, a2, 2
321 addi a3, a3, 2
322#if !XCHAL_HAVE_LOOPS
323 blt a2, a10, .Loop7
324#endif
3254:
326 /* This section processes a possible trailing odd byte. */
327 _bbci.l a4, 0, 8f /* 1-byte chunk */
328SRC( l8ui a9, a2, 0 )
329DST( s8i a9, a3, 0 )
330#ifdef __XTENSA_EB__
331 slli a9, a9, 8 /* shift byte to bits 8..15 */
332#endif
333 ONES_ADD(a5, a9)
3348:
335 mov a2, a5
336 retw
337
3385:
339 /* Control branch to here when either src or dst is odd. We
340 process all bytes using 8-bit accesses. Grossly inefficient,
341 so don't feed us an odd address. */
342
343 srli a10, a4, 1 /* handle in pairs for 16-bit csum */
344#if XCHAL_HAVE_LOOPS
345 loopgtz a10, 6f
346#else
347 beqz a10, 6f
348 slli a10, a10, 1
349 add a10, a10, a2 /* a10 = end of last odd-aligned, 2-byte src chunk */
350.Loop8:
351#endif
352SRC( l8ui a9, a2, 0 )
353SRC( l8ui a8, a2, 1 )
354DST( s8i a9, a3, 0 )
355DST( s8i a8, a3, 1 )
356#ifdef __XTENSA_EB__
357 slli a9, a9, 8 /* combine into a single 16-bit value */
358#else /* for checksum computation */
359 slli a8, a8, 8
360#endif
361 or a9, a9, a8
362 ONES_ADD(a5, a9)
363 addi a2, a2, 2
364 addi a3, a3, 2
365#if !XCHAL_HAVE_LOOPS
366 blt a2, a10, .Loop8
367#endif
3686:
369 j 4b /* process the possible trailing odd byte */
370
371
372# Exception handler:
373.section .fixup, "ax"
374/*
375 a6 = src_err_ptr
376 a7 = dst_err_ptr
377 a11 = original len for exception handling
378 a12 = original dst for exception handling
379*/
380
3816001:
382 _movi a2, -EFAULT
383 s32i a2, a6, 0 /* src_err_ptr */
384
385 # clear the complete destination - computing the rest
386 # is too much work
387 movi a2, 0
388#if XCHAL_HAVE_LOOPS
389 loopgtz a11, 2f
390#else
391 beqz a11, 2f
392 add a11, a11, a12 /* a11 = ending address */
393.Leloop:
394#endif
395 s8i a2, a12, 0
396 addi a12, a12, 1
397#if !XCHAL_HAVE_LOOPS
398 blt a12, a11, .Leloop
399#endif
4002:
401 retw
402
4036002:
404 movi a2, -EFAULT
405 s32i a2, a7, 0 /* dst_err_ptr */
406 movi a2, 0
407 retw
408
409.previous
410
diff --git a/arch/xtensa/lib/memcopy.S b/arch/xtensa/lib/memcopy.S
new file mode 100644
index 0000000000..e8f6d7eb72
--- /dev/null
+++ b/arch/xtensa/lib/memcopy.S
@@ -0,0 +1,315 @@
1/*
2 * arch/xtensa/lib/hal/memcopy.S -- Core HAL library functions
3 * xthal_memcpy and xthal_bcopy
4 *
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file "COPYING" in the main directory of this archive
7 * for more details.
8 *
9 * Copyright (C) 2002 - 2005 Tensilica Inc.
10 */
11
12#include <xtensa/coreasm.h>
13
14 .macro src_b r, w0, w1
15#ifdef __XTENSA_EB__
16 src \r, \w0, \w1
17#else
18 src \r, \w1, \w0
19#endif
20 .endm
21
22 .macro ssa8 r
23#ifdef __XTENSA_EB__
24 ssa8b \r
25#else
26 ssa8l \r
27#endif
28 .endm
29
30
31/*
32 * void *memcpy(void *dst, const void *src, size_t len);
33 * void *memmove(void *dst, const void *src, size_t len);
34 * void *bcopy(const void *src, void *dst, size_t len);
35 *
36 * This function is intended to do the same thing as the standard
37 * library function memcpy() (or bcopy()) for most cases.
38 * However, where the source and/or destination references
39 * an instruction RAM or ROM or a data RAM or ROM, that
40 * source and/or destination will always be accessed with
41 * 32-bit load and store instructions (as required for these
42 * types of devices).
43 *
44 * !!!!!!! XTFIXME:
45 * !!!!!!! Handling of IRAM/IROM has not yet
46 * !!!!!!! been implemented.
47 *
48 * The bcopy version is provided here to avoid the overhead
49 * of an extra call, for callers that require this convention.
50 *
51 * The (general case) algorithm is as follows:
52 * If destination is unaligned, align it by conditionally
53 * copying 1 and 2 bytes.
54 * If source is aligned,
55 * do 16 bytes with a loop, and then finish up with
56 * 8, 4, 2, and 1 byte copies conditional on the length;
57 * else (if source is unaligned),
58 * do the same, but use SRC to align the source data.
59 * This code tries to use fall-through branches for the common
60 * case of aligned source and destination and multiple
61 * of 4 (or 8) length.
62 *
63 * Register use:
64 * a0/ return address
65 * a1/ stack pointer
66 * a2/ return value
67 * a3/ src
68 * a4/ length
69 * a5/ dst
70 * a6/ tmp
71 * a7/ tmp
72 * a8/ tmp
73 * a9/ tmp
74 * a10/ tmp
75 * a11/ tmp
76 */
77
78 .text
79 .align 4
80 .global bcopy
81 .type bcopy,@function
82bcopy:
83 entry sp, 16 # minimal stack frame
84 # a2=src, a3=dst, a4=len
85 mov a5, a3 # copy dst so that a2 is return value
86 mov a3, a2
87 mov a2, a5
88 j .Lcommon # go to common code for memcpy+bcopy
89
90
91/*
92 * Byte by byte copy
93 */
94 .align 4
95 .byte 0 # 1 mod 4 alignment for LOOPNEZ
96 # (0 mod 4 alignment for LBEG)
97.Lbytecopy:
98#if XCHAL_HAVE_LOOPS
99 loopnez a4, .Lbytecopydone
100#else /* !XCHAL_HAVE_LOOPS */
101 beqz a4, .Lbytecopydone
102 add a7, a3, a4 # a7 = end address for source
103#endif /* !XCHAL_HAVE_LOOPS */
104.Lnextbyte:
105 l8ui a6, a3, 0
106 addi a3, a3, 1
107 s8i a6, a5, 0
108 addi a5, a5, 1
109#if !XCHAL_HAVE_LOOPS
110 blt a3, a7, .Lnextbyte
111#endif /* !XCHAL_HAVE_LOOPS */
112.Lbytecopydone:
113 retw
114
115/*
116 * Destination is unaligned
117 */
118
119 .align 4
120.Ldst1mod2: # dst is only byte aligned
121 _bltui a4, 7, .Lbytecopy # do short copies byte by byte
122
123 # copy 1 byte
124 l8ui a6, a3, 0
125 addi a3, a3, 1
126 addi a4, a4, -1
127 s8i a6, a5, 0
128 addi a5, a5, 1
129 _bbci.l a5, 1, .Ldstaligned # if dst is now aligned, then
130 # return to main algorithm
131.Ldst2mod4: # dst 16-bit aligned
132 # copy 2 bytes
133 _bltui a4, 6, .Lbytecopy # do short copies byte by byte
134 l8ui a6, a3, 0
135 l8ui a7, a3, 1
136 addi a3, a3, 2
137 addi a4, a4, -2
138 s8i a6, a5, 0
139 s8i a7, a5, 1
140 addi a5, a5, 2
141 j .Ldstaligned # dst is now aligned, return to main algorithm
142
143 .align 4
144 .global memcpy
145 .type memcpy,@function
146memcpy:
147 .global memmove
148 .type memmove,@function
149memmove:
150
151 entry sp, 16 # minimal stack frame
152 # a2/ dst, a3/ src, a4/ len
153 mov a5, a2 # copy dst so that a2 is return value
154.Lcommon:
155 _bbsi.l a2, 0, .Ldst1mod2 # if dst is 1 mod 2
156 _bbsi.l a2, 1, .Ldst2mod4 # if dst is 2 mod 4
157.Ldstaligned: # return here from .Ldst?mod? once dst is aligned
158 srli a7, a4, 4 # number of loop iterations with 16B
159 # per iteration
160 movi a8, 3 # if source is not aligned,
161 _bany a3, a8, .Lsrcunaligned # then use shifting copy
162 /*
163 * Destination and source are word-aligned, use word copy.
164 */
165 # copy 16 bytes per iteration for word-aligned dst and word-aligned src
166#if XCHAL_HAVE_LOOPS
167 loopnez a7, .Loop1done
168#else /* !XCHAL_HAVE_LOOPS */
169 beqz a7, .Loop1done
170 slli a8, a7, 4
171 add a8, a8, a3 # a8 = end of last 16B source chunk
172#endif /* !XCHAL_HAVE_LOOPS */
173.Loop1:
174 l32i a6, a3, 0
175 l32i a7, a3, 4
176 s32i a6, a5, 0
177 l32i a6, a3, 8
178 s32i a7, a5, 4
179 l32i a7, a3, 12
180 s32i a6, a5, 8
181 addi a3, a3, 16
182 s32i a7, a5, 12
183 addi a5, a5, 16
184#if !XCHAL_HAVE_LOOPS
185 blt a3, a8, .Loop1
186#endif /* !XCHAL_HAVE_LOOPS */
187.Loop1done:
188 bbci.l a4, 3, .L2
189 # copy 8 bytes
190 l32i a6, a3, 0
191 l32i a7, a3, 4
192 addi a3, a3, 8
193 s32i a6, a5, 0
194 s32i a7, a5, 4
195 addi a5, a5, 8
196.L2:
197 bbsi.l a4, 2, .L3
198 bbsi.l a4, 1, .L4
199 bbsi.l a4, 0, .L5
200 retw
201.L3:
202 # copy 4 bytes
203 l32i a6, a3, 0
204 addi a3, a3, 4
205 s32i a6, a5, 0
206 addi a5, a5, 4
207 bbsi.l a4, 1, .L4
208 bbsi.l a4, 0, .L5
209 retw
210.L4:
211 # copy 2 bytes
212 l16ui a6, a3, 0
213 addi a3, a3, 2
214 s16i a6, a5, 0
215 addi a5, a5, 2
216 bbsi.l a4, 0, .L5
217 retw
218.L5:
219 # copy 1 byte
220 l8ui a6, a3, 0
221 s8i a6, a5, 0
222 retw
223
224/*
225 * Destination is aligned, Source is unaligned
226 */
227
228 .align 4
229.Lsrcunaligned:
230 _beqz a4, .Ldone # avoid loading anything for zero-length copies
231 # copy 16 bytes per iteration for word-aligned dst and unaligned src
232 ssa8 a3 # set shift amount from byte offset
233#define SIM_CHECKS_ALIGNMENT 1 /* set to 1 when running on ISS (simulator) with the
234 lint or ferret client, or 0 to save a few cycles */
235#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
236 and a11, a3, a8 # save unalignment offset for below
237 sub a3, a3, a11 # align a3
238#endif
239 l32i a6, a3, 0 # load first word
240#if XCHAL_HAVE_LOOPS
241 loopnez a7, .Loop2done
242#else /* !XCHAL_HAVE_LOOPS */
243 beqz a7, .Loop2done
244 slli a10, a7, 4
245 add a10, a10, a3 # a10 = end of last 16B source chunk
246#endif /* !XCHAL_HAVE_LOOPS */
247.Loop2:
248 l32i a7, a3, 4
249 l32i a8, a3, 8
250 src_b a6, a6, a7
251 s32i a6, a5, 0
252 l32i a9, a3, 12
253 src_b a7, a7, a8
254 s32i a7, a5, 4
255 l32i a6, a3, 16
256 src_b a8, a8, a9
257 s32i a8, a5, 8
258 addi a3, a3, 16
259 src_b a9, a9, a6
260 s32i a9, a5, 12
261 addi a5, a5, 16
262#if !XCHAL_HAVE_LOOPS
263 blt a3, a10, .Loop2
264#endif /* !XCHAL_HAVE_LOOPS */
265.Loop2done:
266 bbci.l a4, 3, .L12
267 # copy 8 bytes
268 l32i a7, a3, 4
269 l32i a8, a3, 8
270 src_b a6, a6, a7
271 s32i a6, a5, 0
272 addi a3, a3, 8
273 src_b a7, a7, a8
274 s32i a7, a5, 4
275 addi a5, a5, 8
276 mov a6, a8
277.L12:
278 bbci.l a4, 2, .L13
279 # copy 4 bytes
280 l32i a7, a3, 4
281 addi a3, a3, 4
282 src_b a6, a6, a7
283 s32i a6, a5, 0
284 addi a5, a5, 4
285 mov a6, a7
286.L13:
287#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
288 add a3, a3, a11 # readjust a3 with correct misalignment
289#endif
290 bbsi.l a4, 1, .L14
291 bbsi.l a4, 0, .L15
292.Ldone: retw
293.L14:
294 # copy 2 bytes
295 l8ui a6, a3, 0
296 l8ui a7, a3, 1
297 addi a3, a3, 2
298 s8i a6, a5, 0
299 s8i a7, a5, 1
300 addi a5, a5, 2
301 bbsi.l a4, 0, .L15
302 retw
303.L15:
304 # copy 1 byte
305 l8ui a6, a3, 0
306 s8i a6, a5, 0
307 retw
308
309/*
310 * Local Variables:
311 * mode:fundamental
312 * comment-start: "# "
313 * comment-start-skip: "# *"
314 * End:
315 */
diff --git a/arch/xtensa/lib/memset.S b/arch/xtensa/lib/memset.S
new file mode 100644
index 0000000000..4de25134bc
--- /dev/null
+++ b/arch/xtensa/lib/memset.S
@@ -0,0 +1,160 @@
1/*
2 * arch/xtensa/lib/memset.S
3 *
4 * ANSI C standard library function memset
5 * (Well, almost. .fixup code might return zero.)
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file "COPYING" in the main directory of
9 * this archive for more details.
10 *
11 * Copyright (C) 2002 Tensilica Inc.
12 */
13
14#include <xtensa/coreasm.h>
15
16/*
17 * void *memset(void *dst, int c, size_t length)
18 *
19 * The algorithm is as follows:
20 * Create a word with c in all byte positions
21 * If the destination is aligned,
22 * do 16B chucks with a loop, and then finish up with
23 * 8B, 4B, 2B, and 1B stores conditional on the length.
24 * If destination is unaligned, align it by conditionally
25 * setting 1B and 2B and then go to aligned case.
26 * This code tries to use fall-through branches for the common
27 * case of an aligned destination (except for the branches to
28 * the alignment labels).
29 */
30
31/* Load or store instructions that may cause exceptions use the EX macro. */
32
33#define EX(insn,reg1,reg2,offset,handler) \
349: insn reg1, reg2, offset; \
35 .section __ex_table, "a"; \
36 .word 9b, handler; \
37 .previous
38
39
40.text
41.align 4
42.global memset
43.type memset,@function
44memset:
45 entry sp, 16 # minimal stack frame
46 # a2/ dst, a3/ c, a4/ length
47 extui a3, a3, 0, 8 # mask to just 8 bits
48 slli a7, a3, 8 # duplicate character in all bytes of word
49 or a3, a3, a7 # ...
50 slli a7, a3, 16 # ...
51 or a3, a3, a7 # ...
52 mov a5, a2 # copy dst so that a2 is return value
53 movi a6, 3 # for alignment tests
54 bany a2, a6, .Ldstunaligned # if dst is unaligned
55.L0: # return here from .Ldstunaligned when dst is aligned
56 srli a7, a4, 4 # number of loop iterations with 16B
57 # per iteration
58 bnez a4, .Laligned
59 retw
60
61/*
62 * Destination is word-aligned.
63 */
64 # set 16 bytes per iteration for word-aligned dst
65 .align 4 # 1 mod 4 alignment for LOOPNEZ
66 .byte 0 # (0 mod 4 alignment for LBEG)
67.Laligned:
68#if XCHAL_HAVE_LOOPS
69 loopnez a7, .Loop1done
70#else /* !XCHAL_HAVE_LOOPS */
71 beqz a7, .Loop1done
72 slli a6, a7, 4
73 add a6, a6, a5 # a6 = end of last 16B chunk
74#endif /* !XCHAL_HAVE_LOOPS */
75.Loop1:
76 EX(s32i, a3, a5, 0, memset_fixup)
77 EX(s32i, a3, a5, 4, memset_fixup)
78 EX(s32i, a3, a5, 8, memset_fixup)
79 EX(s32i, a3, a5, 12, memset_fixup)
80 addi a5, a5, 16
81#if !XCHAL_HAVE_LOOPS
82 blt a5, a6, .Loop1
83#endif /* !XCHAL_HAVE_LOOPS */
84.Loop1done:
85 bbci.l a4, 3, .L2
86 # set 8 bytes
87 EX(s32i, a3, a5, 0, memset_fixup)
88 EX(s32i, a3, a5, 4, memset_fixup)
89 addi a5, a5, 8
90.L2:
91 bbci.l a4, 2, .L3
92 # set 4 bytes
93 EX(s32i, a3, a5, 0, memset_fixup)
94 addi a5, a5, 4
95.L3:
96 bbci.l a4, 1, .L4
97 # set 2 bytes
98 EX(s16i, a3, a5, 0, memset_fixup)
99 addi a5, a5, 2
100.L4:
101 bbci.l a4, 0, .L5
102 # set 1 byte
103 EX(s8i, a3, a5, 0, memset_fixup)
104.L5:
105.Lret1:
106 retw
107
108/*
109 * Destination is unaligned
110 */
111
112.Ldstunaligned:
113 bltui a4, 8, .Lbyteset # do short copies byte by byte
114 bbci.l a5, 0, .L20 # branch if dst alignment half-aligned
115 # dst is only byte aligned
116 # set 1 byte
117 EX(s8i, a3, a5, 0, memset_fixup)
118 addi a5, a5, 1
119 addi a4, a4, -1
120 # now retest if dst aligned
121 bbci.l a5, 1, .L0 # if now aligned, return to main algorithm
122.L20:
123 # dst half-aligned
124 # set 2 bytes
125 EX(s16i, a3, a5, 0, memset_fixup)
126 addi a5, a5, 2
127 addi a4, a4, -2
128 j .L0 # dst is now aligned, return to main algorithm
129
130/*
131 * Byte by byte set
132 */
133 .align 4
134 .byte 0 # 1 mod 4 alignment for LOOPNEZ
135 # (0 mod 4 alignment for LBEG)
136.Lbyteset:
137#if XCHAL_HAVE_LOOPS
138 loopnez a4, .Lbytesetdone
139#else /* !XCHAL_HAVE_LOOPS */
140 beqz a4, .Lbytesetdone
141 add a6, a5, a4 # a6 = ending address
142#endif /* !XCHAL_HAVE_LOOPS */
143.Lbyteloop:
144 EX(s8i, a3, a5, 0, memset_fixup)
145 addi a5, a5, 1
146#if !XCHAL_HAVE_LOOPS
147 blt a5, a6, .Lbyteloop
148#endif /* !XCHAL_HAVE_LOOPS */
149.Lbytesetdone:
150 retw
151
152
153 .section .fixup, "ax"
154 .align 4
155
156/* We return zero if a failure occurred. */
157
158memset_fixup:
159 movi a2, 0
160 retw
diff --git a/arch/xtensa/lib/pci-auto.c b/arch/xtensa/lib/pci-auto.c
new file mode 100644
index 0000000000..90c790f612
--- /dev/null
+++ b/arch/xtensa/lib/pci-auto.c
@@ -0,0 +1,352 @@
1/*
2 * arch/xtensa/kernel/pci-auto.c
3 *
4 * PCI autoconfiguration library
5 *
6 * Copyright (C) 2001 - 2005 Tensilica Inc.
7 *
8 * Chris Zankel <zankel@tensilica.com, cez@zankel.net>
9 *
10 * Based on work from Matt Porter <mporter@mvista.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/pci.h>
21
22#include <asm/pci-bridge.h>
23
24
25/*
26 *
27 * Setting up a PCI
28 *
29 * pci_ctrl->first_busno = <first bus number (0)>
30 * pci_ctrl->last_busno = <last bus number (0xff)>
31 * pci_ctrl->ops = <PCI config operations>
32 * pci_ctrl->map_irq = <function to return the interrupt number for a device>
33 *
34 * pci_ctrl->io_space.start = <IO space start address (PCI view)>
35 * pci_ctrl->io_space.end = <IO space end address (PCI view)>
36 * pci_ctrl->io_space.base = <IO space offset: address 0 from CPU space>
37 * pci_ctrl->mem_space.start = <MEM space start address (PCI view)>
38 * pci_ctrl->mem_space.end = <MEM space end address (PCI view)>
39 * pci_ctrl->mem_space.base = <MEM space offset: address 0 from CPU space>
40 *
41 * pcibios_init_resource(&pci_ctrl->io_resource, <IO space start>,
42 * <IO space end>, IORESOURCE_IO, "PCI host bridge");
43 * pcibios_init_resource(&pci_ctrl->mem_resources[0], <MEM space start>,
44 * <MEM space end>, IORESOURCE_MEM, "PCI host bridge");
45 *
46 * pci_ctrl->last_busno = pciauto_bus_scan(pci_ctrl,pci_ctrl->first_busno);
47 *
48 * int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
49 *
50 */
51
52
53/* define DEBUG to print some debugging messages. */
54
55#undef DEBUG
56
57#ifdef DEBUG
58# define DBG(x...) printk(x)
59#else
60# define DBG(x...)
61#endif
62
63static int pciauto_upper_iospc;
64static int pciauto_upper_memspc;
65
66static struct pci_dev pciauto_dev;
67static struct pci_bus pciauto_bus;
68
69/*
70 * Helper functions
71 */
72
73/* Initialize the bars of a PCI device. */
74
75static void __init
76pciauto_setup_bars(struct pci_dev *dev, int bar_limit)
77{
78 int bar_size;
79 int bar, bar_nr;
80 int *upper_limit;
81 int found_mem64 = 0;
82
83 for (bar = PCI_BASE_ADDRESS_0, bar_nr = 0;
84 bar <= bar_limit;
85 bar+=4, bar_nr++)
86 {
87 /* Tickle the BAR and get the size */
88 pci_write_config_dword(dev, bar, 0xffffffff);
89 pci_read_config_dword(dev, bar, &bar_size);
90
91 /* If BAR is not implemented go to the next BAR */
92 if (!bar_size)
93 continue;
94
95 /* Check the BAR type and set our address mask */
96 if (bar_size & PCI_BASE_ADDRESS_SPACE_IO)
97 {
98 bar_size &= PCI_BASE_ADDRESS_IO_MASK;
99 upper_limit = &pciauto_upper_iospc;
100 DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr);
101 }
102 else
103 {
104 if ((bar_size & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
105 PCI_BASE_ADDRESS_MEM_TYPE_64)
106 found_mem64 = 1;
107
108 bar_size &= PCI_BASE_ADDRESS_MEM_MASK;
109 upper_limit = &pciauto_upper_memspc;
110 DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr);
111 }
112
113 /* Allocate a base address (bar_size is negative!) */
114 *upper_limit = (*upper_limit + bar_size) & bar_size;
115
116 /* Write it out and update our limit */
117 pci_write_config_dword(dev, bar, *upper_limit);
118
119 /*
120 * If we are a 64-bit decoder then increment to the
121 * upper 32 bits of the bar and force it to locate
122 * in the lower 4GB of memory.
123 */
124
125 if (found_mem64)
126 pci_write_config_dword(dev, (bar+=4), 0x00000000);
127
128 DBG("size=0x%x, address=0x%x\n", ~bar_size + 1, *upper_limit);
129 }
130}
131
132/* Initialize the interrupt number. */
133
134static void __init
135pciauto_setup_irq(struct pci_controller* pci_ctrl,struct pci_dev *dev,int devfn)
136{
137 u8 pin;
138 int irq = 0;
139
140 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
141
142 /* Fix illegal pin numbers. */
143
144 if (pin == 0 || pin > 4)
145 pin = 1;
146
147 if (pci_ctrl->map_irq)
148 irq = pci_ctrl->map_irq(dev, PCI_SLOT(devfn), pin);
149
150 if (irq == -1)
151 irq = 0;
152
153 DBG("PCI Autoconfig: Interrupt %d, pin %d\n", irq, pin);
154
155 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
156}
157
158
159static void __init
160pciauto_prescan_setup_bridge(struct pci_dev *dev, int current_bus,
161 int sub_bus, int *iosave, int *memsave)
162{
163 /* Configure bus number registers */
164 pci_write_config_byte(dev, PCI_PRIMARY_BUS, current_bus);
165 pci_write_config_byte(dev, PCI_SECONDARY_BUS, sub_bus + 1);
166 pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, 0xff);
167
168 /* Round memory allocator to 1MB boundary */
169 pciauto_upper_memspc &= ~(0x100000 - 1);
170 *memsave = pciauto_upper_memspc;
171
172 /* Round I/O allocator to 4KB boundary */
173 pciauto_upper_iospc &= ~(0x1000 - 1);
174 *iosave = pciauto_upper_iospc;
175
176 /* Set up memory and I/O filter limits, assume 32-bit I/O space */
177 pci_write_config_word(dev, PCI_MEMORY_LIMIT,
178 ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
179 pci_write_config_byte(dev, PCI_IO_LIMIT,
180 ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8);
181 pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
182 ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16);
183}
184
185static void __init
186pciauto_postscan_setup_bridge(struct pci_dev *dev, int current_bus, int sub_bus,
187 int *iosave, int *memsave)
188{
189 int cmdstat;
190
191 /* Configure bus number registers */
192 pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, sub_bus);
193
194 /*
195 * Round memory allocator to 1MB boundary.
196 * If no space used, allocate minimum.
197 */
198 pciauto_upper_memspc &= ~(0x100000 - 1);
199 if (*memsave == pciauto_upper_memspc)
200 pciauto_upper_memspc -= 0x00100000;
201
202 pci_write_config_word(dev, PCI_MEMORY_BASE, pciauto_upper_memspc >> 16);
203
204 /* Allocate 1MB for pre-fretch */
205 pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
206 ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
207
208 pciauto_upper_memspc -= 0x100000;
209
210 pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,
211 pciauto_upper_memspc >> 16);
212
213 /* Round I/O allocator to 4KB boundary */
214 pciauto_upper_iospc &= ~(0x1000 - 1);
215 if (*iosave == pciauto_upper_iospc)
216 pciauto_upper_iospc -= 0x1000;
217
218 pci_write_config_byte(dev, PCI_IO_BASE,
219 (pciauto_upper_iospc & 0x0000f000) >> 8);
220 pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
221 pciauto_upper_iospc >> 16);
222
223 /* Enable memory and I/O accesses, enable bus master */
224 pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
225 pci_write_config_dword(dev, PCI_COMMAND,
226 cmdstat |
227 PCI_COMMAND_IO |
228 PCI_COMMAND_MEMORY |
229 PCI_COMMAND_MASTER);
230}
231
232/*
233 * Scan the current PCI bus.
234 */
235
236
237int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
238{
239 int sub_bus, pci_devfn, pci_class, cmdstat, found_multi=0;
240 unsigned short vid;
241 unsigned char header_type;
242 struct pci_dev *dev = &pciauto_dev;
243
244 pciauto_dev.bus = &pciauto_bus;
245 pciauto_dev.sysdata = pci_ctrl;
246 pciauto_bus.ops = pci_ctrl->ops;
247
248 /*
249 * Fetch our I/O and memory space upper boundaries used
250 * to allocated base addresses on this pci_controller.
251 */
252
253 if (current_bus == pci_ctrl->first_busno)
254 {
255 pciauto_upper_iospc = pci_ctrl->io_resource.end + 1;
256 pciauto_upper_memspc = pci_ctrl->mem_resources[0].end + 1;
257 }
258
259 sub_bus = current_bus;
260
261 for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++)
262 {
263 /* Skip our host bridge */
264 if ((current_bus == pci_ctrl->first_busno) && (pci_devfn == 0))
265 continue;
266
267 if (PCI_FUNC(pci_devfn) && !found_multi)
268 continue;
269
270 pciauto_bus.number = current_bus;
271 pciauto_dev.devfn = pci_devfn;
272
273 /* If config space read fails from this device, move on */
274 if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type))
275 continue;
276
277 if (!PCI_FUNC(pci_devfn))
278 found_multi = header_type & 0x80;
279 pci_read_config_word(dev, PCI_VENDOR_ID, &vid);
280
281 if (vid == 0xffff || vid == 0x0000) {
282 found_multi = 0;
283 continue;
284 }
285
286 pci_read_config_dword(dev, PCI_CLASS_REVISION, &pci_class);
287
288 if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
289
290 int iosave, memsave;
291
292 DBG("PCI Autoconfig: Found P2P bridge, device %d\n",
293 PCI_SLOT(pci_devfn));
294
295 /* Allocate PCI I/O and/or memory space */
296 pciauto_setup_bars(dev, PCI_BASE_ADDRESS_1);
297
298 pciauto_prescan_setup_bridge(dev, current_bus, sub_bus,
299 &iosave, &memsave);
300 sub_bus = pciauto_bus_scan(pci_ctrl, sub_bus+1);
301 pciauto_postscan_setup_bridge(dev, current_bus, sub_bus,
302 &iosave, &memsave);
303 pciauto_bus.number = current_bus;
304
305 continue;
306
307 }
308
309
310#if 0
311 /* Skip legacy mode IDE controller */
312
313 if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
314
315 unsigned char prg_iface;
316 pci_read_config_byte(dev, PCI_CLASS_PROG, &prg_iface);
317
318 if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
319 DBG("PCI Autoconfig: Skipping legacy mode "
320 "IDE controller\n");
321 continue;
322 }
323 }
324#endif
325
326 /*
327 * Found a peripheral, enable some standard
328 * settings
329 */
330
331 pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
332 pci_write_config_dword(dev, PCI_COMMAND,
333 cmdstat |
334 PCI_COMMAND_IO |
335 PCI_COMMAND_MEMORY |
336 PCI_COMMAND_MASTER);
337 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
338
339 /* Allocate PCI I/O and/or memory space */
340 DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
341 current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) );
342
343 pciauto_setup_bars(dev, PCI_BASE_ADDRESS_5);
344 pciauto_setup_irq(pci_ctrl, dev, pci_devfn);
345 }
346 return sub_bus;
347}
348
349
350
351
352
diff --git a/arch/xtensa/lib/strcasecmp.c b/arch/xtensa/lib/strcasecmp.c
new file mode 100644
index 0000000000..165b2d6eff
--- /dev/null
+++ b/arch/xtensa/lib/strcasecmp.c
@@ -0,0 +1,32 @@
1/*
2 * linux/arch/xtensa/lib/strcasecmp.c
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2002 Tensilica Inc.
9 */
10
11#include <linux/string.h>
12
13
14/* We handle nothing here except the C locale. Since this is used in
15 only one place, on strings known to contain only 7 bit ASCII, this
16 is ok. */
17
18int strcasecmp(const char *a, const char *b)
19{
20 int ca, cb;
21
22 do {
23 ca = *a++ & 0xff;
24 cb = *b++ & 0xff;
25 if (ca >= 'A' && ca <= 'Z')
26 ca += 'a' - 'A';
27 if (cb >= 'A' && cb <= 'Z')
28 cb += 'a' - 'A';
29 } while (ca == cb && ca != '\0');
30
31 return ca - cb;
32}
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S
new file mode 100644
index 0000000000..71d55df438
--- /dev/null
+++ b/arch/xtensa/lib/strncpy_user.S
@@ -0,0 +1,224 @@
1/*
2 * arch/xtensa/lib/strncpy_user.S
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Returns: -EFAULT if exception before terminator, N if the entire
9 * buffer filled, else strlen.
10 *
11 * Copyright (C) 2002 Tensilica Inc.
12 */
13
14#include <xtensa/coreasm.h>
15#include <linux/errno.h>
16
17/* Load or store instructions that may cause exceptions use the EX macro. */
18
19#define EX(insn,reg1,reg2,offset,handler) \
209: insn reg1, reg2, offset; \
21 .section __ex_table, "a"; \
22 .word 9b, handler; \
23 .previous
24
25/*
26 * char *__strncpy_user(char *dst, const char *src, size_t len)
27 */
28.text
29.begin literal
30.align 4
31.Lmask0:
32 .byte 0xff, 0x00, 0x00, 0x00
33.Lmask1:
34 .byte 0x00, 0xff, 0x00, 0x00
35.Lmask2:
36 .byte 0x00, 0x00, 0xff, 0x00
37.Lmask3:
38 .byte 0x00, 0x00, 0x00, 0xff
39.end literal
40
41# Register use
42# a0/ return address
43# a1/ stack pointer
44# a2/ return value
45# a3/ src
46# a4/ len
47# a5/ mask0
48# a6/ mask1
49# a7/ mask2
50# a8/ mask3
51# a9/ tmp
52# a10/ tmp
53# a11/ dst
54# a12/ tmp
55
56.align 4
57.global __strncpy_user
58.type __strncpy_user,@function
59__strncpy_user:
60 entry sp, 16 # minimal stack frame
61 # a2/ dst, a3/ src, a4/ len
62 mov a11, a2 # leave dst in return value register
63 beqz a4, .Lret # if len is zero
64 l32r a5, .Lmask0 # mask for byte 0
65 l32r a6, .Lmask1 # mask for byte 1
66 l32r a7, .Lmask2 # mask for byte 2
67 l32r a8, .Lmask3 # mask for byte 3
68 bbsi.l a3, 0, .Lsrc1mod2 # if only 8-bit aligned
69 bbsi.l a3, 1, .Lsrc2mod4 # if only 16-bit aligned
70.Lsrcaligned: # return here when src is word-aligned
71 srli a12, a4, 2 # number of loop iterations with 4B per loop
72 movi a9, 3
73 bnone a11, a9, .Laligned
74 j .Ldstunaligned
75
76.Lsrc1mod2: # src address is odd
77 EX(l8ui, a9, a3, 0, fixup_l) # get byte 0
78 addi a3, a3, 1 # advance src pointer
79 EX(s8i, a9, a11, 0, fixup_s) # store byte 0
80 beqz a9, .Lret # if byte 0 is zero
81 addi a11, a11, 1 # advance dst pointer
82 addi a4, a4, -1 # decrement len
83 beqz a4, .Lret # if len is zero
84 bbci.l a3, 1, .Lsrcaligned # if src is now word-aligned
85
86.Lsrc2mod4: # src address is 2 mod 4
87 EX(l8ui, a9, a3, 0, fixup_l) # get byte 0
88 /* 1-cycle interlock */
89 EX(s8i, a9, a11, 0, fixup_s) # store byte 0
90 beqz a9, .Lret # if byte 0 is zero
91 addi a11, a11, 1 # advance dst pointer
92 addi a4, a4, -1 # decrement len
93 beqz a4, .Lret # if len is zero
94 EX(l8ui, a9, a3, 1, fixup_l) # get byte 0
95 addi a3, a3, 2 # advance src pointer
96 EX(s8i, a9, a11, 0, fixup_s) # store byte 0
97 beqz a9, .Lret # if byte 0 is zero
98 addi a11, a11, 1 # advance dst pointer
99 addi a4, a4, -1 # decrement len
100 bnez a4, .Lsrcaligned # if len is nonzero
101.Lret:
102 sub a2, a11, a2 # compute strlen
103 retw
104
105/*
106 * dst is word-aligned, src is word-aligned
107 */
108 .align 4 # 1 mod 4 alignment for LOOPNEZ
109 .byte 0 # (0 mod 4 alignment for LBEG)
110.Laligned:
111#if XCHAL_HAVE_LOOPS
112 loopnez a12, .Loop1done
113#else
114 beqz a12, .Loop1done
115 slli a12, a12, 2
116 add a12, a12, a11 # a12 = end of last 4B chunck
117#endif
118.Loop1:
119 EX(l32i, a9, a3, 0, fixup_l) # get word from src
120 addi a3, a3, 4 # advance src pointer
121 bnone a9, a5, .Lz0 # if byte 0 is zero
122 bnone a9, a6, .Lz1 # if byte 1 is zero
123 bnone a9, a7, .Lz2 # if byte 2 is zero
124 EX(s32i, a9, a11, 0, fixup_s) # store word to dst
125 bnone a9, a8, .Lz3 # if byte 3 is zero
126 addi a11, a11, 4 # advance dst pointer
127#if !XCHAL_HAVE_LOOPS
128 blt a11, a12, .Loop1
129#endif
130
131.Loop1done:
132 bbci.l a4, 1, .L100
133 # copy 2 bytes
134 EX(l16ui, a9, a3, 0, fixup_l)
135 addi a3, a3, 2 # advance src pointer
136#ifdef __XTENSA_EB__
137 bnone a9, a7, .Lz0 # if byte 2 is zero
138 bnone a9, a8, .Lz1 # if byte 3 is zero
139#else
140 bnone a9, a5, .Lz0 # if byte 0 is zero
141 bnone a9, a6, .Lz1 # if byte 1 is zero
142#endif
143 EX(s16i, a9, a11, 0, fixup_s)
144 addi a11, a11, 2 # advance dst pointer
145.L100:
146 bbci.l a4, 0, .Lret
147 EX(l8ui, a9, a3, 0, fixup_l)
148 /* slot */
149 EX(s8i, a9, a11, 0, fixup_s)
150 beqz a9, .Lret # if byte is zero
151 addi a11, a11, 1-3 # advance dst ptr 1, but also cancel
152 # the effect of adding 3 in .Lz3 code
153 /* fall thru to .Lz3 and "retw" */
154
155.Lz3: # byte 3 is zero
156 addi a11, a11, 3 # advance dst pointer
157 sub a2, a11, a2 # compute strlen
158 retw
159.Lz0: # byte 0 is zero
160#ifdef __XTENSA_EB__
161 movi a9, 0
162#endif /* __XTENSA_EB__ */
163 EX(s8i, a9, a11, 0, fixup_s)
164 sub a2, a11, a2 # compute strlen
165 retw
166.Lz1: # byte 1 is zero
167#ifdef __XTENSA_EB__
168 extui a9, a9, 16, 16
169#endif /* __XTENSA_EB__ */
170 EX(s16i, a9, a11, 0, fixup_s)
171 addi a11, a11, 1 # advance dst pointer
172 sub a2, a11, a2 # compute strlen
173 retw
174.Lz2: # byte 2 is zero
175#ifdef __XTENSA_EB__
176 extui a9, a9, 16, 16
177#endif /* __XTENSA_EB__ */
178 EX(s16i, a9, a11, 0, fixup_s)
179 movi a9, 0
180 EX(s8i, a9, a11, 2, fixup_s)
181 addi a11, a11, 2 # advance dst pointer
182 sub a2, a11, a2 # compute strlen
183 retw
184
185 .align 4 # 1 mod 4 alignment for LOOPNEZ
186 .byte 0 # (0 mod 4 alignment for LBEG)
187.Ldstunaligned:
188/*
189 * for now just use byte copy loop
190 */
191#if XCHAL_HAVE_LOOPS
192 loopnez a4, .Lunalignedend
193#else
194 beqz a4, .Lunalignedend
195 add a12, a11, a4 # a12 = ending address
196#endif /* XCHAL_HAVE_LOOPS */
197.Lnextbyte:
198 EX(l8ui, a9, a3, 0, fixup_l)
199 addi a3, a3, 1
200 EX(s8i, a9, a11, 0, fixup_s)
201 beqz a9, .Lunalignedend
202 addi a11, a11, 1
203#if !XCHAL_HAVE_LOOPS
204 blt a11, a12, .Lnextbyte
205#endif
206
207.Lunalignedend:
208 sub a2, a11, a2 # compute strlen
209 retw
210
211
212 .section .fixup, "ax"
213 .align 4
214
215 /* For now, just return -EFAULT. Future implementations might
216 * like to clear remaining kernel space, like the fixup
217 * implementation in memset(). Thus, we differentiate between
218 * load/store fixups. */
219
220fixup_s:
221fixup_l:
222 movi a2, -EFAULT
223 retw
224
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S
new file mode 100644
index 0000000000..cdff4d670f
--- /dev/null
+++ b/arch/xtensa/lib/strnlen_user.S
@@ -0,0 +1,147 @@
1/*
2 * arch/xtensa/lib/strnlen_user.S
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Returns strnlen, including trailing zero terminator.
9 * Zero indicates error.
10 *
11 * Copyright (C) 2002 Tensilica Inc.
12 */
13
14#include <xtensa/coreasm.h>
15
16/* Load or store instructions that may cause exceptions use the EX macro. */
17
18#define EX(insn,reg1,reg2,offset,handler) \
199: insn reg1, reg2, offset; \
20 .section __ex_table, "a"; \
21 .word 9b, handler; \
22 .previous
23
24/*
25 * size_t __strnlen_user(const char *s, size_t len)
26 */
27.text
28.begin literal
29.align 4
30.Lmask0:
31 .byte 0xff, 0x00, 0x00, 0x00
32.Lmask1:
33 .byte 0x00, 0xff, 0x00, 0x00
34.Lmask2:
35 .byte 0x00, 0x00, 0xff, 0x00
36.Lmask3:
37 .byte 0x00, 0x00, 0x00, 0xff
38.end literal
39
40# Register use:
41# a2/ src
42# a3/ len
43# a4/ tmp
44# a5/ mask0
45# a6/ mask1
46# a7/ mask2
47# a8/ mask3
48# a9/ tmp
49# a10/ tmp
50
51.align 4
52.global __strnlen_user
53.type __strnlen_user,@function
54__strnlen_user:
55 entry sp, 16 # minimal stack frame
56 # a2/ s, a3/ len
57 addi a4, a2, -4 # because we overincrement at the end;
58 # we compensate with load offsets of 4
59 l32r a5, .Lmask0 # mask for byte 0
60 l32r a6, .Lmask1 # mask for byte 1
61 l32r a7, .Lmask2 # mask for byte 2
62 l32r a8, .Lmask3 # mask for byte 3
63 bbsi.l a2, 0, .L1mod2 # if only 8-bit aligned
64 bbsi.l a2, 1, .L2mod4 # if only 16-bit aligned
65
66/*
67 * String is word-aligned.
68 */
69.Laligned:
70 srli a10, a3, 2 # number of loop iterations with 4B per loop
71#if XCHAL_HAVE_LOOPS
72 loopnez a10, .Ldone
73#else
74 beqz a10, .Ldone
75 slli a10, a10, 2
76 add a10, a10, a4 # a10 = end of last 4B chunk
77#endif /* XCHAL_HAVE_LOOPS */
78.Loop:
79 EX(l32i, a9, a4, 4, lenfixup) # get next word of string
80 addi a4, a4, 4 # advance string pointer
81 bnone a9, a5, .Lz0 # if byte 0 is zero
82 bnone a9, a6, .Lz1 # if byte 1 is zero
83 bnone a9, a7, .Lz2 # if byte 2 is zero
84 bnone a9, a8, .Lz3 # if byte 3 is zero
85#if !XCHAL_HAVE_LOOPS
86 blt a4, a10, .Loop
87#endif
88
89.Ldone:
90 EX(l32i, a9, a4, 4, lenfixup) # load 4 bytes for remaining checks
91
92 bbci.l a3, 1, .L100
93 # check two more bytes (bytes 0, 1 of word)
94 addi a4, a4, 2 # advance string pointer
95 bnone a9, a5, .Lz0 # if byte 0 is zero
96 bnone a9, a6, .Lz1 # if byte 1 is zero
97.L100:
98 bbci.l a3, 0, .L101
99 # check one more byte (byte 2 of word)
100 # Actually, we don't need to check. Zero or nonzero, we'll add one.
101 # Do not add an extra one for the NULL terminator since we have
102 # exhausted the original len parameter.
103 addi a4, a4, 1 # advance string pointer
104.L101:
105 sub a2, a4, a2 # compute length
106 retw
107
108# NOTE that in several places below, we point to the byte just after
109# the zero byte in order to include the NULL terminator in the count.
110
111.Lz3: # byte 3 is zero
112 addi a4, a4, 3 # point to zero byte
113.Lz0: # byte 0 is zero
114 addi a4, a4, 1 # point just beyond zero byte
115 sub a2, a4, a2 # subtract to get length
116 retw
117.Lz1: # byte 1 is zero
118 addi a4, a4, 1+1 # point just beyond zero byte
119 sub a2, a4, a2 # subtract to get length
120 retw
121.Lz2: # byte 2 is zero
122 addi a4, a4, 2+1 # point just beyond zero byte
123 sub a2, a4, a2 # subtract to get length
124 retw
125
126.L1mod2: # address is odd
127 EX(l8ui, a9, a4, 4, lenfixup) # get byte 0
128 addi a4, a4, 1 # advance string pointer
129 beqz a9, .Lz3 # if byte 0 is zero
130 bbci.l a4, 1, .Laligned # if string pointer is now word-aligned
131
132.L2mod4: # address is 2 mod 4
133 addi a4, a4, 2 # advance ptr for aligned access
134 EX(l32i, a9, a4, 0, lenfixup) # get word with first two bytes of string
135 bnone a9, a7, .Lz2 # if byte 2 (of word, not string) is zero
136 bany a9, a8, .Laligned # if byte 3 (of word, not string) is nonzero
137 # byte 3 is zero
138 addi a4, a4, 3+1 # point just beyond zero byte
139 sub a2, a4, a2 # subtract to get length
140 retw
141
142 .section .fixup, "ax"
143 .align 4
144lenfixup:
145 movi a2, 0
146 retw
147
diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S
new file mode 100644
index 0000000000..265db2693c
--- /dev/null
+++ b/arch/xtensa/lib/usercopy.S
@@ -0,0 +1,321 @@
1/*
2 * arch/xtensa/lib/usercopy.S
3 *
4 * Copy to/from user space (derived from arch/xtensa/lib/hal/memcopy.S)
5 *
6 * DO NOT COMBINE this function with <arch/xtensa/lib/hal/memcopy.S>.
7 * It needs to remain separate and distinct. The hal files are part
8 * of the the Xtensa link-time HAL, and those files may differ per
9 * processor configuration. Patching the kernel for another
10 * processor configuration includes replacing the hal files, and we
11 * could loose the special functionality for accessing user-space
12 * memory during such a patch. We sacrifice a little code space here
13 * in favor to simplify code maintenance.
14 *
15 * This file is subject to the terms and conditions of the GNU General
16 * Public License. See the file "COPYING" in the main directory of
17 * this archive for more details.
18 *
19 * Copyright (C) 2002 Tensilica Inc.
20 */
21
22
23/*
24 * size_t __xtensa_copy_user (void *dst, const void *src, size_t len);
25 *
26 * The returned value is the number of bytes not copied. Implies zero
27 * is success.
28 *
29 * The general case algorithm is as follows:
30 * If the destination and source are both aligned,
31 * do 16B chunks with a loop, and then finish up with
32 * 8B, 4B, 2B, and 1B copies conditional on the length.
33 * If destination is aligned and source unaligned,
34 * do the same, but use SRC to align the source data.
35 * If destination is unaligned, align it by conditionally
36 * copying 1B and 2B and then retest.
37 * This code tries to use fall-through braches for the common
38 * case of aligned destinations (except for the branches to
39 * the alignment label).
40 *
41 * Register use:
42 * a0/ return address
43 * a1/ stack pointer
44 * a2/ return value
45 * a3/ src
46 * a4/ length
47 * a5/ dst
48 * a6/ tmp
49 * a7/ tmp
50 * a8/ tmp
51 * a9/ tmp
52 * a10/ tmp
53 * a11/ original length
54 */
55
56#include <xtensa/coreasm.h>
57
58#ifdef __XTENSA_EB__
59#define ALIGN(R, W0, W1) src R, W0, W1
60#define SSA8(R) ssa8b R
61#else
62#define ALIGN(R, W0, W1) src R, W1, W0
63#define SSA8(R) ssa8l R
64#endif
65
66/* Load or store instructions that may cause exceptions use the EX macro. */
67
68#define EX(insn,reg1,reg2,offset,handler) \
699: insn reg1, reg2, offset; \
70 .section __ex_table, "a"; \
71 .word 9b, handler; \
72 .previous
73
74
75 .text
76 .align 4
77 .global __xtensa_copy_user
78 .type __xtensa_copy_user,@function
79__xtensa_copy_user:
80 entry sp, 16 # minimal stack frame
81 # a2/ dst, a3/ src, a4/ len
82 mov a5, a2 # copy dst so that a2 is return value
83 mov a11, a4 # preserve original len for error case
84.Lcommon:
85 bbsi.l a2, 0, .Ldst1mod2 # if dst is 1 mod 2
86 bbsi.l a2, 1, .Ldst2mod4 # if dst is 2 mod 4
87.Ldstaligned: # return here from .Ldstunaligned when dst is aligned
88 srli a7, a4, 4 # number of loop iterations with 16B
89 # per iteration
90 movi a8, 3 # if source is also aligned,
91 bnone a3, a8, .Laligned # then use word copy
92 SSA8( a3) # set shift amount from byte offset
93 bnez a4, .Lsrcunaligned
94 movi a2, 0 # return success for len==0
95 retw
96
97/*
98 * Destination is unaligned
99 */
100
101.Ldst1mod2: # dst is only byte aligned
102 bltui a4, 7, .Lbytecopy # do short copies byte by byte
103
104 # copy 1 byte
105 EX(l8ui, a6, a3, 0, l_fixup)
106 addi a3, a3, 1
107 EX(s8i, a6, a5, 0, s_fixup)
108 addi a5, a5, 1
109 addi a4, a4, -1
110 bbci.l a5, 1, .Ldstaligned # if dst is now aligned, then
111 # return to main algorithm
112.Ldst2mod4: # dst 16-bit aligned
113 # copy 2 bytes
114 bltui a4, 6, .Lbytecopy # do short copies byte by byte
115 EX(l8ui, a6, a3, 0, l_fixup)
116 EX(l8ui, a7, a3, 1, l_fixup)
117 addi a3, a3, 2
118 EX(s8i, a6, a5, 0, s_fixup)
119 EX(s8i, a7, a5, 1, s_fixup)
120 addi a5, a5, 2
121 addi a4, a4, -2
122 j .Ldstaligned # dst is now aligned, return to main algorithm
123
124/*
125 * Byte by byte copy
126 */
127 .align 4
128 .byte 0 # 1 mod 4 alignment for LOOPNEZ
129 # (0 mod 4 alignment for LBEG)
130.Lbytecopy:
131#if XCHAL_HAVE_LOOPS
132 loopnez a4, .Lbytecopydone
133#else /* !XCHAL_HAVE_LOOPS */
134 beqz a4, .Lbytecopydone
135 add a7, a3, a4 # a7 = end address for source
136#endif /* !XCHAL_HAVE_LOOPS */
137.Lnextbyte:
138 EX(l8ui, a6, a3, 0, l_fixup)
139 addi a3, a3, 1
140 EX(s8i, a6, a5, 0, s_fixup)
141 addi a5, a5, 1
142#if !XCHAL_HAVE_LOOPS
143 blt a3, a7, .Lnextbyte
144#endif /* !XCHAL_HAVE_LOOPS */
145.Lbytecopydone:
146 movi a2, 0 # return success for len bytes copied
147 retw
148
149/*
150 * Destination and source are word-aligned.
151 */
152 # copy 16 bytes per iteration for word-aligned dst and word-aligned src
153 .align 4 # 1 mod 4 alignment for LOOPNEZ
154 .byte 0 # (0 mod 4 alignment for LBEG)
155.Laligned:
156#if XCHAL_HAVE_LOOPS
157 loopnez a7, .Loop1done
158#else /* !XCHAL_HAVE_LOOPS */
159 beqz a7, .Loop1done
160 slli a8, a7, 4
161 add a8, a8, a3 # a8 = end of last 16B source chunk
162#endif /* !XCHAL_HAVE_LOOPS */
163.Loop1:
164 EX(l32i, a6, a3, 0, l_fixup)
165 EX(l32i, a7, a3, 4, l_fixup)
166 EX(s32i, a6, a5, 0, s_fixup)
167 EX(l32i, a6, a3, 8, l_fixup)
168 EX(s32i, a7, a5, 4, s_fixup)
169 EX(l32i, a7, a3, 12, l_fixup)
170 EX(s32i, a6, a5, 8, s_fixup)
171 addi a3, a3, 16
172 EX(s32i, a7, a5, 12, s_fixup)
173 addi a5, a5, 16
174#if !XCHAL_HAVE_LOOPS
175 blt a3, a8, .Loop1
176#endif /* !XCHAL_HAVE_LOOPS */
177.Loop1done:
178 bbci.l a4, 3, .L2
179 # copy 8 bytes
180 EX(l32i, a6, a3, 0, l_fixup)
181 EX(l32i, a7, a3, 4, l_fixup)
182 addi a3, a3, 8
183 EX(s32i, a6, a5, 0, s_fixup)
184 EX(s32i, a7, a5, 4, s_fixup)
185 addi a5, a5, 8
186.L2:
187 bbci.l a4, 2, .L3
188 # copy 4 bytes
189 EX(l32i, a6, a3, 0, l_fixup)
190 addi a3, a3, 4
191 EX(s32i, a6, a5, 0, s_fixup)
192 addi a5, a5, 4
193.L3:
194 bbci.l a4, 1, .L4
195 # copy 2 bytes
196 EX(l16ui, a6, a3, 0, l_fixup)
197 addi a3, a3, 2
198 EX(s16i, a6, a5, 0, s_fixup)
199 addi a5, a5, 2
200.L4:
201 bbci.l a4, 0, .L5
202 # copy 1 byte
203 EX(l8ui, a6, a3, 0, l_fixup)
204 EX(s8i, a6, a5, 0, s_fixup)
205.L5:
206 movi a2, 0 # return success for len bytes copied
207 retw
208
209/*
210 * Destination is aligned, Source is unaligned
211 */
212
213 .align 4
214 .byte 0 # 1 mod 4 alignement for LOOPNEZ
215 # (0 mod 4 alignment for LBEG)
216.Lsrcunaligned:
217 # copy 16 bytes per iteration for word-aligned dst and unaligned src
218 and a10, a3, a8 # save unalignment offset for below
219 sub a3, a3, a10 # align a3 (to avoid sim warnings only; not needed for hardware)
220 EX(l32i, a6, a3, 0, l_fixup) # load first word
221#if XCHAL_HAVE_LOOPS
222 loopnez a7, .Loop2done
223#else /* !XCHAL_HAVE_LOOPS */
224 beqz a7, .Loop2done
225 slli a10, a7, 4
226 add a10, a10, a3 # a10 = end of last 16B source chunk
227#endif /* !XCHAL_HAVE_LOOPS */
228.Loop2:
229 EX(l32i, a7, a3, 4, l_fixup)
230 EX(l32i, a8, a3, 8, l_fixup)
231 ALIGN( a6, a6, a7)
232 EX(s32i, a6, a5, 0, s_fixup)
233 EX(l32i, a9, a3, 12, l_fixup)
234 ALIGN( a7, a7, a8)
235 EX(s32i, a7, a5, 4, s_fixup)
236 EX(l32i, a6, a3, 16, l_fixup)
237 ALIGN( a8, a8, a9)
238 EX(s32i, a8, a5, 8, s_fixup)
239 addi a3, a3, 16
240 ALIGN( a9, a9, a6)
241 EX(s32i, a9, a5, 12, s_fixup)
242 addi a5, a5, 16
243#if !XCHAL_HAVE_LOOPS
244 blt a3, a10, .Loop2
245#endif /* !XCHAL_HAVE_LOOPS */
246.Loop2done:
247 bbci.l a4, 3, .L12
248 # copy 8 bytes
249 EX(l32i, a7, a3, 4, l_fixup)
250 EX(l32i, a8, a3, 8, l_fixup)
251 ALIGN( a6, a6, a7)
252 EX(s32i, a6, a5, 0, s_fixup)
253 addi a3, a3, 8
254 ALIGN( a7, a7, a8)
255 EX(s32i, a7, a5, 4, s_fixup)
256 addi a5, a5, 8
257 mov a6, a8
258.L12:
259 bbci.l a4, 2, .L13
260 # copy 4 bytes
261 EX(l32i, a7, a3, 4, l_fixup)
262 addi a3, a3, 4
263 ALIGN( a6, a6, a7)
264 EX(s32i, a6, a5, 0, s_fixup)
265 addi a5, a5, 4
266 mov a6, a7
267.L13:
268 add a3, a3, a10 # readjust a3 with correct misalignment
269 bbci.l a4, 1, .L14
270 # copy 2 bytes
271 EX(l8ui, a6, a3, 0, l_fixup)
272 EX(l8ui, a7, a3, 1, l_fixup)
273 addi a3, a3, 2
274 EX(s8i, a6, a5, 0, s_fixup)
275 EX(s8i, a7, a5, 1, s_fixup)
276 addi a5, a5, 2
277.L14:
278 bbci.l a4, 0, .L15
279 # copy 1 byte
280 EX(l8ui, a6, a3, 0, l_fixup)
281 EX(s8i, a6, a5, 0, s_fixup)
282.L15:
283 movi a2, 0 # return success for len bytes copied
284 retw
285
286
287 .section .fixup, "ax"
288 .align 4
289
290/* a2 = original dst; a5 = current dst; a11= original len
291 * bytes_copied = a5 - a2
292 * retval = bytes_not_copied = original len - bytes_copied
293 * retval = a11 - (a5 - a2)
294 *
295 * Clearing the remaining pieces of kernel memory plugs security
296 * holes. This functionality is the equivalent of the *_zeroing
297 * functions that some architectures provide.
298 */
299
300.Lmemset:
301 .word memset
302
303s_fixup:
304 sub a2, a5, a2 /* a2 <-- bytes copied */
305 sub a2, a11, a2 /* a2 <-- bytes not copied */
306 retw
307
308l_fixup:
309 sub a2, a5, a2 /* a2 <-- bytes copied */
310 sub a2, a11, a2 /* a2 <-- bytes not copied == return value */
311
312 /* void *memset(void *s, int c, size_t n); */
313 mov a6, a5 /* s */
314 movi a7, 0 /* c */
315 mov a8, a2 /* n */
316 l32r a4, .Lmemset
317 callx4 a4
318 /* Ignore memset return value in a6. */
319 /* a2 still contains bytes not copied. */
320 retw
321
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile
new file mode 100644
index 0000000000..a5aed5932d
--- /dev/null
+++ b/arch/xtensa/mm/Makefile
@@ -0,0 +1,13 @@
1#
2# Makefile for the Linux/Xtensa-specific parts of the memory manager.
3#
4# Note! Dependencies are done automagically by 'make dep', which also
5# removes any old dependencies. DON'T put your own dependencies here
6# unless it's something special (ie not a .c file).
7#
8# Note 2! The CFLAGS definition is now in the main makefile...
9
10obj-y := init.o fault.o tlb.o misc.o
11obj-m :=
12obj-n :=
13obj- :=
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
new file mode 100644
index 0000000000..a945a33e85
--- /dev/null
+++ b/arch/xtensa/mm/fault.c
@@ -0,0 +1,241 @@
1// TODO VM_EXEC flag work-around, cache aliasing
2/*
3 * arch/xtensa/mm/fault.c
4 *
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file "COPYING" in the main directory of this archive
7 * for more details.
8 *
9 * Copyright (C) 2001 - 2005 Tensilica Inc.
10 *
11 * Chris Zankel <chris@zankel.net>
12 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
13 */
14
15#include <linux/mm.h>
16#include <linux/module.h>
17#include <asm/mmu_context.h>
18#include <asm/cacheflush.h>
19#include <asm/hardirq.h>
20#include <asm/uaccess.h>
21#include <asm/system.h>
22#include <asm/pgalloc.h>
23
24unsigned long asid_cache = ASID_FIRST_VERSION;
25void bad_page_fault(struct pt_regs*, unsigned long, int);
26
27/*
28 * This routine handles page faults. It determines the address,
29 * and the problem, and then passes it off to one of the appropriate
30 * routines.
31 *
32 * Note: does not handle Miss and MultiHit.
33 */
34
35void do_page_fault(struct pt_regs *regs)
36{
37 struct vm_area_struct * vma;
38 struct mm_struct *mm = current->mm;
39 unsigned int exccause = regs->exccause;
40 unsigned int address = regs->excvaddr;
41 siginfo_t info;
42
43 int is_write, is_exec;
44
45 info.si_code = SEGV_MAPERR;
46
47 /* We fault-in kernel-space virtual memory on-demand. The
48 * 'reference' page table is init_mm.pgd.
49 */
50 if (address >= TASK_SIZE && !user_mode(regs))
51 goto vmalloc_fault;
52
53 /* If we're in an interrupt or have no user
54 * context, we must not take the fault..
55 */
56 if (in_atomic() || !mm) {
57 bad_page_fault(regs, address, SIGSEGV);
58 return;
59 }
60
61 is_write = (exccause == XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0;
62 is_exec = (exccause == XCHAL_EXCCAUSE_ITLB_PRIVILEGE ||
63 exccause == XCHAL_EXCCAUSE_ITLB_MISS ||
64 exccause == XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
65
66#if 0
67 printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid,
68 address, exccause, regs->pc, is_write? "w":"", is_exec? "x":"");
69#endif
70
71 down_read(&mm->mmap_sem);
72 vma = find_vma(mm, address);
73
74 if (!vma)
75 goto bad_area;
76 if (vma->vm_start <= address)
77 goto good_area;
78 if (!(vma->vm_flags & VM_GROWSDOWN))
79 goto bad_area;
80 if (expand_stack(vma, address))
81 goto bad_area;
82
83 /* Ok, we have a good vm_area for this memory access, so
84 * we can handle it..
85 */
86
87good_area:
88 info.si_code = SEGV_ACCERR;
89
90 if (is_write) {
91 if (!(vma->vm_flags & VM_WRITE))
92 goto bad_area;
93 } else if (is_exec) {
94 if (!(vma->vm_flags & VM_EXEC))
95 goto bad_area;
96 } else /* Allow read even from write-only pages. */
97 if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
98 goto bad_area;
99
100 /* If for any reason at all we couldn't handle the fault,
101 * make sure we exit gracefully rather than endlessly redo
102 * the fault.
103 */
104survive:
105 switch (handle_mm_fault(mm, vma, address, is_write)) {
106 case VM_FAULT_MINOR:
107 current->min_flt++;
108 break;
109 case VM_FAULT_MAJOR:
110 current->maj_flt++;
111 break;
112 case VM_FAULT_SIGBUS:
113 goto do_sigbus;
114 case VM_FAULT_OOM:
115 goto out_of_memory;
116 default:
117 BUG();
118 }
119
120 up_read(&mm->mmap_sem);
121 return;
122
123 /* Something tried to access memory that isn't in our memory map..
124 * Fix it, but check if it's kernel or user first..
125 */
126bad_area:
127 up_read(&mm->mmap_sem);
128 if (user_mode(regs)) {
129 current->thread.bad_vaddr = address;
130 current->thread.error_code = is_write;
131 info.si_signo = SIGSEGV;
132 info.si_errno = 0;
133 /* info.si_code has been set above */
134 info.si_addr = (void *) address;
135 force_sig_info(SIGSEGV, &info, current);
136 return;
137 }
138 bad_page_fault(regs, address, SIGSEGV);
139 return;
140
141
142 /* We ran out of memory, or some other thing happened to us that made
143 * us unable to handle the page fault gracefully.
144 */
145out_of_memory:
146 up_read(&mm->mmap_sem);
147 if (current->pid == 1) {
148 yield();
149 down_read(&mm->mmap_sem);
150 goto survive;
151 }
152 printk("VM: killing process %s\n", current->comm);
153 if (user_mode(regs))
154 do_exit(SIGKILL);
155 bad_page_fault(regs, address, SIGKILL);
156 return;
157
158do_sigbus:
159 up_read(&mm->mmap_sem);
160
161 /* Send a sigbus, regardless of whether we were in kernel
162 * or user mode.
163 */
164 current->thread.bad_vaddr = address;
165 info.si_code = SIGBUS;
166 info.si_errno = 0;
167 info.si_code = BUS_ADRERR;
168 info.si_addr = (void *) address;
169 force_sig_info(SIGBUS, &info, current);
170
171 /* Kernel mode? Handle exceptions or die */
172 if (!user_mode(regs))
173 bad_page_fault(regs, address, SIGBUS);
174
175vmalloc_fault:
176 {
177 /* Synchronize this task's top level page-table
178 * with the 'reference' page table.
179 */
180 struct mm_struct *act_mm = current->active_mm;
181 int index = pgd_index(address);
182 pgd_t *pgd, *pgd_k;
183 pmd_t *pmd, *pmd_k;
184 pte_t *pte_k;
185
186 if (act_mm == NULL)
187 goto bad_page_fault;
188
189 pgd = act_mm->pgd + index;
190 pgd_k = init_mm.pgd + index;
191
192 if (!pgd_present(*pgd_k))
193 goto bad_page_fault;
194
195 pgd_val(*pgd) = pgd_val(*pgd_k);
196
197 pmd = pmd_offset(pgd, address);
198 pmd_k = pmd_offset(pgd_k, address);
199 if (!pmd_present(*pmd) || !pmd_present(*pmd_k))
200 goto bad_page_fault;
201
202 pmd_val(*pmd) = pmd_val(*pmd_k);
203 pte_k = pte_offset_kernel(pmd_k, address);
204
205 if (!pte_present(*pte_k))
206 goto bad_page_fault;
207 return;
208 }
209bad_page_fault:
210 bad_page_fault(regs, address, SIGKILL);
211 return;
212}
213
214
215void
216bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
217{
218 extern void die(const char*, struct pt_regs*, long);
219 const struct exception_table_entry *entry;
220
221 /* Are we prepared to handle this kernel fault? */
222 if ((entry = search_exception_tables(regs->pc)) != NULL) {
223#if 1
224 printk(KERN_DEBUG "%s: Exception at pc=%#010lx (%lx)\n",
225 current->comm, regs->pc, entry->fixup);
226#endif
227 current->thread.bad_uaddr = address;
228 regs->pc = entry->fixup;
229 return;
230 }
231
232 /* Oops. The kernel tried to access some bad page. We'll have to
233 * terminate things with extreme prejudice.
234 */
235 printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
236 "address %08lx\n pc = %08lx, ra = %08lx\n",
237 address, regs->pc, regs->areg[0]);
238 die("Oops", regs, sig);
239 do_exit(sig);
240}
241
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
new file mode 100644
index 0000000000..56aace84aa
--- /dev/null
+++ b/arch/xtensa/mm/init.c
@@ -0,0 +1,551 @@
1/*
2 * arch/xtensa/mm/init.c
3 *
4 * Derived from MIPS, PPC.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
14 * Marc Gauthier
15 * Kevin Chea
16 */
17
18#include <linux/config.h>
19#include <linux/init.h>
20#include <linux/signal.h>
21#include <linux/sched.h>
22#include <linux/kernel.h>
23#include <linux/errno.h>
24#include <linux/string.h>
25#include <linux/types.h>
26#include <linux/ptrace.h>
27#include <linux/bootmem.h>
28#include <linux/swap.h>
29
30#include <asm/pgtable.h>
31#include <asm/bootparam.h>
32#include <asm/mmu_context.h>
33#include <asm/tlb.h>
34#include <asm/tlbflush.h>
35#include <asm/page.h>
36#include <asm/pgalloc.h>
37#include <asm/pgtable.h>
38
39
40#define DEBUG 0
41
42DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
43//static DEFINE_SPINLOCK(tlb_lock);
44
45/*
46 * This flag is used to indicate that the page was mapped and modified in
47 * kernel space, so the cache is probably dirty at that address.
48 * If cache aliasing is enabled and the page color mismatches, update_mmu_cache
49 * synchronizes the caches if this bit is set.
50 */
51
52#define PG_cache_clean PG_arch_1
53
54/* References to section boundaries */
55
56extern char _ftext, _etext, _fdata, _edata, _rodata_end;
57extern char __init_begin, __init_end;
58
59/*
60 * mem_reserve(start, end, must_exist)
61 *
62 * Reserve some memory from the memory pool.
63 *
64 * Parameters:
65 * start Start of region,
66 * end End of region,
67 * must_exist Must exist in memory pool.
68 *
69 * Returns:
70 * 0 (memory area couldn't be mapped)
71 * -1 (success)
72 */
73
74int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
75{
76 int i;
77
78 if (start == end)
79 return 0;
80
81 start = start & PAGE_MASK;
82 end = PAGE_ALIGN(end);
83
84 for (i = 0; i < sysmem.nr_banks; i++)
85 if (start < sysmem.bank[i].end
86 && end >= sysmem.bank[i].start)
87 break;
88
89 if (i == sysmem.nr_banks) {
90 if (must_exist)
91 printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) "
92 "not in any region!\n", start, end);
93 return 0;
94 }
95
96 if (start > sysmem.bank[i].start) {
97 if (end < sysmem.bank[i].end) {
98 /* split entry */
99 if (sysmem.nr_banks >= SYSMEM_BANKS_MAX)
100 panic("meminfo overflow\n");
101 sysmem.bank[sysmem.nr_banks].start = end;
102 sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end;
103 sysmem.nr_banks++;
104 }
105 sysmem.bank[i].end = start;
106 } else {
107 if (end < sysmem.bank[i].end)
108 sysmem.bank[i].start = end;
109 else {
110 /* remove entry */
111 sysmem.nr_banks--;
112 sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
113 sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end;
114 }
115 }
116 return -1;
117}
118
119
120/*
121 * Initialize the bootmem system and give it all the memory we have available.
122 */
123
124void __init bootmem_init(void)
125{
126 unsigned long pfn;
127 unsigned long bootmap_start, bootmap_size;
128 int i;
129
130 max_low_pfn = max_pfn = 0;
131 min_low_pfn = ~0;
132
133 for (i=0; i < sysmem.nr_banks; i++) {
134 pfn = PAGE_ALIGN(sysmem.bank[i].start) >> PAGE_SHIFT;
135 if (pfn < min_low_pfn)
136 min_low_pfn = pfn;
137 pfn = PAGE_ALIGN(sysmem.bank[i].end - 1) >> PAGE_SHIFT;
138 if (pfn > max_pfn)
139 max_pfn = pfn;
140 }
141
142 if (min_low_pfn > max_pfn)
143 panic("No memory found!\n");
144
145 max_low_pfn = max_pfn < MAX_LOW_MEMORY >> PAGE_SHIFT ?
146 max_pfn : MAX_LOW_MEMORY >> PAGE_SHIFT;
147
148 /* Find an area to use for the bootmem bitmap. */
149
150 bootmap_size = bootmem_bootmap_pages(max_low_pfn) << PAGE_SHIFT;
151 bootmap_start = ~0;
152
153 for (i=0; i<sysmem.nr_banks; i++)
154 if (sysmem.bank[i].end - sysmem.bank[i].start >= bootmap_size) {
155 bootmap_start = sysmem.bank[i].start;
156 break;
157 }
158
159 if (bootmap_start == ~0UL)
160 panic("Cannot find %ld bytes for bootmap\n", bootmap_size);
161
162 /* Reserve the bootmem bitmap area */
163
164 mem_reserve(bootmap_start, bootmap_start + bootmap_size, 1);
165 bootmap_size = init_bootmem_node(NODE_DATA(0), min_low_pfn,
166 bootmap_start >> PAGE_SHIFT,
167 max_low_pfn);
168
169 /* Add all remaining memory pieces into the bootmem map */
170
171 for (i=0; i<sysmem.nr_banks; i++)
172 free_bootmem(sysmem.bank[i].start,
173 sysmem.bank[i].end - sysmem.bank[i].start);
174
175}
176
177
178void __init paging_init(void)
179{
180 unsigned long zones_size[MAX_NR_ZONES];
181 int i;
182
183 /* All pages are DMA-able, so we put them all in the DMA zone. */
184
185 zones_size[ZONE_DMA] = max_low_pfn;
186 for (i = 1; i < MAX_NR_ZONES; i++)
187 zones_size[i] = 0;
188
189#ifdef CONFIG_HIGHMEM
190 zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
191#endif
192
193 /* Initialize the kernel's page tables. */
194
195 memset(swapper_pg_dir, 0, PAGE_SIZE);
196
197 free_area_init(zones_size);
198}
199
200/*
201 * Flush the mmu and reset associated register to default values.
202 */
203
204void __init init_mmu (void)
205{
206 /* Writing zeros to the <t>TLBCFG special registers ensure
207 * that valid values exist in the register. For existing
208 * PGSZID<w> fields, zero selects the first element of the
209 * page-size array. For nonexistant PGSZID<w> fields, zero is
210 * the best value to write. Also, when changing PGSZID<w>
211 * fields, the corresponding TLB must be flushed.
212 */
213 set_itlbcfg_register (0);
214 set_dtlbcfg_register (0);
215 flush_tlb_all ();
216
217 /* Set rasid register to a known value. */
218
219 set_rasid_register (ASID_ALL_RESERVED);
220
221 /* Set PTEVADDR special register to the start of the page
222 * table, which is in kernel mappable space (ie. not
223 * statically mapped). This register's value is undefined on
224 * reset.
225 */
226 set_ptevaddr_register (PGTABLE_START);
227}
228
229/*
230 * Initialize memory pages.
231 */
232
233void __init mem_init(void)
234{
235 unsigned long codesize, reservedpages, datasize, initsize;
236 unsigned long highmemsize, tmp, ram;
237
238 max_mapnr = num_physpages = max_low_pfn;
239 high_memory = (void *) __va(max_mapnr << PAGE_SHIFT);
240 highmemsize = 0;
241
242#if CONFIG_HIGHMEM
243#error HIGHGMEM not implemented in init.c
244#endif
245
246 totalram_pages += free_all_bootmem();
247
248 reservedpages = ram = 0;
249 for (tmp = 0; tmp < max_low_pfn; tmp++) {
250 ram++;
251 if (PageReserved(mem_map+tmp))
252 reservedpages++;
253 }
254
255 codesize = (unsigned long) &_etext - (unsigned long) &_ftext;
256 datasize = (unsigned long) &_edata - (unsigned long) &_fdata;
257 initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
258
259 printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
260 "%ldk data, %ldk init %ldk highmem)\n",
261 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
262 ram << (PAGE_SHIFT-10),
263 codesize >> 10,
264 reservedpages << (PAGE_SHIFT-10),
265 datasize >> 10,
266 initsize >> 10,
267 highmemsize >> 10);
268}
269
270void
271free_reserved_mem(void *start, void *end)
272{
273 for (; start < end; start += PAGE_SIZE) {
274 ClearPageReserved(virt_to_page(start));
275 set_page_count(virt_to_page(start), 1);
276 free_page((unsigned long)start);
277 totalram_pages++;
278 }
279}
280
281#ifdef CONFIG_BLK_DEV_INITRD
282extern int initrd_is_mapped;
283
284void free_initrd_mem(unsigned long start, unsigned long end)
285{
286 if (initrd_is_mapped) {
287 free_reserved_mem((void*)start, (void*)end);
288 printk ("Freeing initrd memory: %ldk freed\n",(end-start)>>10);
289 }
290}
291#endif
292
293void free_initmem(void)
294{
295 free_reserved_mem(&__init_begin, &__init_end);
296 printk("Freeing unused kernel memory: %dk freed\n",
297 (&__init_end - &__init_begin) >> 10);
298}
299
300void show_mem(void)
301{
302 int i, free = 0, total = 0, reserved = 0;
303 int shared = 0, cached = 0;
304
305 printk("Mem-info:\n");
306 show_free_areas();
307 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
308 i = max_mapnr;
309 while (i-- > 0) {
310 total++;
311 if (PageReserved(mem_map+i))
312 reserved++;
313 else if (PageSwapCache(mem_map+i))
314 cached++;
315 else if (!page_count(mem_map + i))
316 free++;
317 else
318 shared += page_count(mem_map + i) - 1;
319 }
320 printk("%d pages of RAM\n", total);
321 printk("%d reserved pages\n", reserved);
322 printk("%d pages shared\n", shared);
323 printk("%d pages swap cached\n",cached);
324 printk("%d free pages\n", free);
325}
326
327/* ------------------------------------------------------------------------- */
328
329#if (DCACHE_WAY_SIZE > PAGE_SIZE)
330
331/*
332 * With cache aliasing, the page color of the page in kernel space and user
333 * space might mismatch. We temporarily map the page to a different virtual
334 * address with the same color and clear the page there.
335 */
336
337void clear_user_page(void *kaddr, unsigned long vaddr, struct page* page)
338{
339
340 /* There shouldn't be any entries for this page. */
341
342 __flush_invalidate_dcache_page_phys(__pa(page_address(page)));
343
344 if (!PAGE_COLOR_EQ(vaddr, kaddr)) {
345 unsigned long v, p;
346
347 /* Temporarily map page to DTLB_WAY_DCACHE_ALIAS0. */
348
349 spin_lock(&tlb_lock);
350
351 p = (unsigned long)pte_val((mk_pte(page,PAGE_KERNEL)));
352 kaddr = (void*)PAGE_COLOR_MAP0(vaddr);
353 v = (unsigned long)kaddr | DTLB_WAY_DCACHE_ALIAS0;
354 __asm__ __volatile__("wdtlb %0,%1; dsync" : :"a" (p), "a" (v));
355
356 clear_page(kaddr);
357
358 spin_unlock(&tlb_lock);
359 } else {
360 clear_page(kaddr);
361 }
362
363 /* We need to make sure that i$ and d$ are coherent. */
364
365 clear_bit(PG_cache_clean, &page->flags);
366}
367
368/*
369 * With cache aliasing, we have to make sure that the page color of the page
370 * in kernel space matches that of the virtual user address before we read
371 * the page. If the page color differ, we create a temporary DTLB entry with
372 * the corrent page color and use this 'temporary' address as the source.
373 * We then use the same approach as in clear_user_page and copy the data
374 * to the kernel space and clear the PG_cache_clean bit to synchronize caches
375 * later.
376 *
377 * Note:
378 * Instead of using another 'way' for the temporary DTLB entry, we could
379 * probably use the same entry that points to the kernel address (after
380 * saving the original value and restoring it when we are done).
381 */
382
383void copy_user_page(void* to, void* from, unsigned long vaddr,
384 struct page* to_page)
385{
386 /* There shouldn't be any entries for the new page. */
387
388 __flush_invalidate_dcache_page_phys(__pa(page_address(to_page)));
389
390 spin_lock(&tlb_lock);
391
392 if (!PAGE_COLOR_EQ(vaddr, from)) {
393 unsigned long v, p, t;
394
395 __asm__ __volatile__ ("pdtlb %1,%2; rdtlb1 %0,%1"
396 : "=a"(p), "=a"(t) : "a"(from));
397 from = (void*)PAGE_COLOR_MAP0(vaddr);
398 v = (unsigned long)from | DTLB_WAY_DCACHE_ALIAS0;
399 __asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
400 }
401
402 if (!PAGE_COLOR_EQ(vaddr, to)) {
403 unsigned long v, p;
404
405 p = (unsigned long)pte_val((mk_pte(to_page,PAGE_KERNEL)));
406 to = (void*)PAGE_COLOR_MAP1(vaddr);
407 v = (unsigned long)to | DTLB_WAY_DCACHE_ALIAS1;
408 __asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
409 }
410 copy_page(to, from);
411
412 spin_unlock(&tlb_lock);
413
414 /* We need to make sure that i$ and d$ are coherent. */
415
416 clear_bit(PG_cache_clean, &to_page->flags);
417}
418
419
420
421/*
422 * Any time the kernel writes to a user page cache page, or it is about to
423 * read from a page cache page this routine is called.
424 *
425 * Note:
426 * The kernel currently only provides one architecture bit in the page
427 * flags that we use for I$/D$ coherency. Maybe, in future, we can
428 * use a sepearte bit for deferred dcache aliasing:
429 * If the page is not mapped yet, we only need to set a flag,
430 * if mapped, we need to invalidate the page.
431 */
432// FIXME: we probably need this for WB caches not only for Page Coloring..
433
434void flush_dcache_page(struct page *page)
435{
436 unsigned long addr = __pa(page_address(page));
437 struct address_space *mapping = page_mapping(page);
438
439 __flush_invalidate_dcache_page_phys(addr);
440
441 if (!test_bit(PG_cache_clean, &page->flags))
442 return;
443
444 /* If this page hasn't been mapped, yet, handle I$/D$ coherency later.*/
445#if 0
446 if (mapping && !mapping_mapped(mapping))
447 clear_bit(PG_cache_clean, &page->flags);
448 else
449#endif
450 __invalidate_icache_page_phys(addr);
451}
452
453void flush_cache_range(struct vm_area_struct* vma, unsigned long s,
454 unsigned long e)
455{
456 __flush_invalidate_cache_all();
457}
458
459void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
460 unsigned long pfn)
461{
462 struct page *page = pfn_to_page(pfn);
463
464 /* Remove any entry for the old mapping. */
465
466 if (current->active_mm == vma->vm_mm) {
467 unsigned long addr = __pa(page_address(page));
468 __flush_invalidate_dcache_page_phys(addr);
469 if ((vma->vm_flags & VM_EXEC) != 0)
470 __invalidate_icache_page_phys(addr);
471 } else {
472 BUG();
473 }
474}
475
476#endif /* (DCACHE_WAY_SIZE > PAGE_SIZE) */
477
478
479pte_t* pte_alloc_one_kernel (struct mm_struct* mm, unsigned long addr)
480{
481 pte_t* pte = (pte_t*)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 0);
482 if (likely(pte)) {
483 pte_t* ptep = (pte_t*)(pte_val(*pte) + PAGE_OFFSET);
484 int i;
485 for (i = 0; i < 1024; i++, ptep++)
486 pte_clear(mm, addr, ptep);
487 }
488 return pte;
489}
490
491struct page* pte_alloc_one(struct mm_struct *mm, unsigned long addr)
492{
493 struct page *page;
494
495 page = alloc_pages(GFP_KERNEL | __GFP_REPEAT, 0);
496
497 if (likely(page)) {
498 pte_t* ptep = kmap_atomic(page, KM_USER0);
499 int i;
500
501 for (i = 0; i < 1024; i++, ptep++)
502 pte_clear(mm, addr, ptep);
503
504 kunmap_atomic(ptep, KM_USER0);
505 }
506 return page;
507}
508
509
510/*
511 * Handle D$/I$ coherency.
512 *
513 * Note:
514 * We only have one architecture bit for the page flags, so we cannot handle
515 * cache aliasing, yet.
516 */
517
518void
519update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte)
520{
521 unsigned long pfn = pte_pfn(pte);
522 struct page *page;
523 unsigned long vaddr = addr & PAGE_MASK;
524
525 if (!pfn_valid(pfn))
526 return;
527
528 page = pfn_to_page(pfn);
529
530 invalidate_itlb_mapping(addr);
531 invalidate_dtlb_mapping(addr);
532
533 /* We have a new mapping. Use it. */
534
535 write_dtlb_entry(pte, dtlb_probe(addr));
536
537 /* If the processor can execute from this page, synchronize D$/I$. */
538
539 if ((vma->vm_flags & VM_EXEC) != 0) {
540
541 write_itlb_entry(pte, itlb_probe(addr));
542
543 /* Synchronize caches, if not clean. */
544
545 if (!test_and_set_bit(PG_cache_clean, &page->flags)) {
546 __flush_dcache_page(vaddr);
547 __invalidate_icache_page(vaddr);
548 }
549 }
550}
551
diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S
new file mode 100644
index 0000000000..327c0f1718
--- /dev/null
+++ b/arch/xtensa/mm/misc.S
@@ -0,0 +1,374 @@
1/*
2 * arch/xtensa/mm/misc.S
3 *
4 * Miscellaneous assembly functions.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 */
14
15/* Note: we might want to implement some of the loops as zero-overhead-loops,
16 * where applicable and if supported by the processor.
17 */
18
19#include <linux/linkage.h>
20#include <asm/page.h>
21#include <asm/pgtable.h>
22
23#include <xtensa/cacheasm.h>
24#include <xtensa/cacheattrasm.h>
25
26/* clear_page (page) */
27
28ENTRY(clear_page)
29 entry a1, 16
30 addi a4, a2, PAGE_SIZE
31 movi a3, 0
32
331: s32i a3, a2, 0
34 s32i a3, a2, 4
35 s32i a3, a2, 8
36 s32i a3, a2, 12
37 s32i a3, a2, 16
38 s32i a3, a2, 20
39 s32i a3, a2, 24
40 s32i a3, a2, 28
41 addi a2, a2, 32
42 blt a2, a4, 1b
43
44 retw
45
46/*
47 * copy_page (void *to, void *from)
48 * a2 a3
49 */
50
51ENTRY(copy_page)
52 entry a1, 16
53 addi a4, a2, PAGE_SIZE
54
551: l32i a5, a3, 0
56 l32i a6, a3, 4
57 l32i a7, a3, 8
58 s32i a5, a2, 0
59 s32i a6, a2, 4
60 s32i a7, a2, 8
61 l32i a5, a3, 12
62 l32i a6, a3, 16
63 l32i a7, a3, 20
64 s32i a5, a2, 12
65 s32i a6, a2, 16
66 s32i a7, a2, 20
67 l32i a5, a3, 24
68 l32i a6, a3, 28
69 s32i a5, a2, 24
70 s32i a6, a2, 28
71 addi a2, a2, 32
72 addi a3, a3, 32
73 blt a2, a4, 1b
74
75 retw
76
77
78/*
79 * void __flush_invalidate_cache_all(void)
80 */
81
82ENTRY(__flush_invalidate_cache_all)
83 entry sp, 16
84 dcache_writeback_inv_all a2, a3
85 icache_invalidate_all a2, a3
86 retw
87
88/*
89 * void __invalidate_icache_all(void)
90 */
91
92ENTRY(__invalidate_icache_all)
93 entry sp, 16
94 icache_invalidate_all a2, a3
95 retw
96
97/*
98 * void __flush_invalidate_dcache_all(void)
99 */
100
101ENTRY(__flush_invalidate_dcache_all)
102 entry sp, 16
103 dcache_writeback_inv_all a2, a3
104 retw
105
106
107/*
108 * void __flush_invalidate_cache_range(ulong start, ulong size)
109 */
110
111ENTRY(__flush_invalidate_cache_range)
112 entry sp, 16
113 mov a4, a2
114 mov a5, a3
115 dcache_writeback_inv_region a4, a5, a6
116 icache_invalidate_region a2, a3, a4
117 retw
118
119/*
120 * void __invalidate_icache_page(ulong start)
121 */
122
123ENTRY(__invalidate_icache_page)
124 entry sp, 16
125 movi a3, PAGE_SIZE
126 icache_invalidate_region a2, a3, a4
127 retw
128
129/*
130 * void __invalidate_dcache_page(ulong start)
131 */
132
133ENTRY(__invalidate_dcache_page)
134 entry sp, 16
135 movi a3, PAGE_SIZE
136 dcache_invalidate_region a2, a3, a4
137 retw
138
139/*
140 * void __invalidate_icache_range(ulong start, ulong size)
141 */
142
143ENTRY(__invalidate_icache_range)
144 entry sp, 16
145 icache_invalidate_region a2, a3, a4
146 retw
147
148/*
149 * void __invalidate_dcache_range(ulong start, ulong size)
150 */
151
152ENTRY(__invalidate_dcache_range)
153 entry sp, 16
154 dcache_invalidate_region a2, a3, a4
155 retw
156
157/*
158 * void __flush_dcache_page(ulong start)
159 */
160
161ENTRY(__flush_dcache_page)
162 entry sp, 16
163 movi a3, PAGE_SIZE
164 dcache_writeback_region a2, a3, a4
165 retw
166
167/*
168 * void __flush_invalidate_dcache_page(ulong start)
169 */
170
171ENTRY(__flush_invalidate_dcache_page)
172 entry sp, 16
173 movi a3, PAGE_SIZE
174 dcache_writeback_inv_region a2, a3, a4
175 retw
176
177/*
178 * void __flush_invalidate_dcache_range(ulong start, ulong size)
179 */
180
181ENTRY(__flush_invalidate_dcache_range)
182 entry sp, 16
183 dcache_writeback_inv_region a2, a3, a4
184 retw
185
186/*
187 * void __invalidate_dcache_all(void)
188 */
189
190ENTRY(__invalidate_dcache_all)
191 entry sp, 16
192 dcache_invalidate_all a2, a3
193 retw
194
195/*
196 * void __flush_invalidate_dcache_page_phys(ulong start)
197 */
198
199ENTRY(__flush_invalidate_dcache_page_phys)
200 entry sp, 16
201
202 movi a3, XCHAL_DCACHE_SIZE
203 movi a4, PAGE_MASK | 1
204 addi a2, a2, 1
205
2061: addi a3, a3, -XCHAL_DCACHE_LINESIZE
207
208 ldct a6, a3
209 dsync
210 and a6, a6, a4
211 beq a6, a2, 2f
212 bgeui a3, 2, 1b
213 retw
214
2152: diwbi a3, 0
216 bgeui a3, 2, 1b
217 retw
218
219ENTRY(check_dcache_low0)
220 entry sp, 16
221
222 movi a3, XCHAL_DCACHE_SIZE / 4
223 movi a4, PAGE_MASK | 1
224 addi a2, a2, 1
225
2261: addi a3, a3, -XCHAL_DCACHE_LINESIZE
227
228 ldct a6, a3
229 dsync
230 and a6, a6, a4
231 beq a6, a2, 2f
232 bgeui a3, 2, 1b
233 retw
234
2352: j 2b
236
237ENTRY(check_dcache_high0)
238 entry sp, 16
239
240 movi a5, XCHAL_DCACHE_SIZE / 4
241 movi a3, XCHAL_DCACHE_SIZE / 2
242 movi a4, PAGE_MASK | 1
243 addi a2, a2, 1
244
2451: addi a3, a3, -XCHAL_DCACHE_LINESIZE
246 addi a5, a5, -XCHAL_DCACHE_LINESIZE
247
248 ldct a6, a3
249 dsync
250 and a6, a6, a4
251 beq a6, a2, 2f
252 bgeui a5, 2, 1b
253 retw
254
2552: j 2b
256
257ENTRY(check_dcache_low1)
258 entry sp, 16
259
260 movi a5, XCHAL_DCACHE_SIZE / 4
261 movi a3, XCHAL_DCACHE_SIZE * 3 / 4
262 movi a4, PAGE_MASK | 1
263 addi a2, a2, 1
264
2651: addi a3, a3, -XCHAL_DCACHE_LINESIZE
266 addi a5, a5, -XCHAL_DCACHE_LINESIZE
267
268 ldct a6, a3
269 dsync
270 and a6, a6, a4
271 beq a6, a2, 2f
272 bgeui a5, 2, 1b
273 retw
274
2752: j 2b
276
277ENTRY(check_dcache_high1)
278 entry sp, 16
279
280 movi a5, XCHAL_DCACHE_SIZE / 4
281 movi a3, XCHAL_DCACHE_SIZE
282 movi a4, PAGE_MASK | 1
283 addi a2, a2, 1
284
2851: addi a3, a3, -XCHAL_DCACHE_LINESIZE
286 addi a5, a5, -XCHAL_DCACHE_LINESIZE
287
288 ldct a6, a3
289 dsync
290 and a6, a6, a4
291 beq a6, a2, 2f
292 bgeui a5, 2, 1b
293 retw
294
2952: j 2b
296
297
298/*
299 * void __invalidate_icache_page_phys(ulong start)
300 */
301
302ENTRY(__invalidate_icache_page_phys)
303 entry sp, 16
304
305 movi a3, XCHAL_ICACHE_SIZE
306 movi a4, PAGE_MASK | 1
307 addi a2, a2, 1
308
3091: addi a3, a3, -XCHAL_ICACHE_LINESIZE
310
311 lict a6, a3
312 isync
313 and a6, a6, a4
314 beq a6, a2, 2f
315 bgeui a3, 2, 1b
316 retw
317
3182: iii a3, 0
319 bgeui a3, 2, 1b
320 retw
321
322
323#if 0
324
325 movi a3, XCHAL_DCACHE_WAYS - 1
326 movi a4, PAGE_SIZE
327
3281: mov a5, a2
329 add a6, a2, a4
330
3312: diwbi a5, 0
332 diwbi a5, XCHAL_DCACHE_LINESIZE
333 diwbi a5, XCHAL_DCACHE_LINESIZE * 2
334 diwbi a5, XCHAL_DCACHE_LINESIZE * 3
335
336 addi a5, a5, XCHAL_DCACHE_LINESIZE * 4
337 blt a5, a6, 2b
338
339 addi a3, a3, -1
340 addi a2, a2, XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS
341 bgez a3, 1b
342
343 retw
344
345ENTRY(__invalidate_icache_page_index)
346 entry sp, 16
347
348 movi a3, XCHAL_ICACHE_WAYS - 1
349 movi a4, PAGE_SIZE
350
3511: mov a5, a2
352 add a6, a2, a4
353
3542: iii a5, 0
355 iii a5, XCHAL_ICACHE_LINESIZE
356 iii a5, XCHAL_ICACHE_LINESIZE * 2
357 iii a5, XCHAL_ICACHE_LINESIZE * 3
358
359 addi a5, a5, XCHAL_ICACHE_LINESIZE * 4
360 blt a5, a6, 2b
361
362 addi a3, a3, -1
363 addi a2, a2, XCHAL_ICACHE_SIZE / XCHAL_ICACHE_WAYS
364 bgez a3, 2b
365
366 retw
367
368#endif
369
370
371
372
373
374
diff --git a/arch/xtensa/mm/pgtable.c b/arch/xtensa/mm/pgtable.c
new file mode 100644
index 0000000000..e5e119c820
--- /dev/null
+++ b/arch/xtensa/mm/pgtable.c
@@ -0,0 +1,76 @@
1/*
2 * arch/xtensa/mm/fault.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 *
10 * Chris Zankel <chris@zankel.net>
11 */
12
13#if (DCACHE_SIZE > PAGE_SIZE)
14
15pte_t* pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
16{
17 pte_t *pte, p;
18 int color = ADDR_COLOR(address);
19 int i;
20
21 p = (pte_t*) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, COLOR_ORDER);
22
23 if (likely(p)) {
24 struct page *page;
25
26 for (i = 0; i < COLOR_SIZE; i++, p++) {
27 page = virt_to_page(pte);
28
29 set_page_count(page, 1);
30 ClearPageCompound(page);
31
32 if (ADDR_COLOR(p) == color)
33 pte = p;
34 else
35 free_page(p);
36 }
37 clear_page(pte);
38 }
39 return pte;
40}
41
42#ifdef PROFILING
43
44int mask;
45int hit;
46int flush;
47
48#endif
49
50struct page* pte_alloc_one(struct mm_struct *mm, unsigned long address)
51{
52 struct page *page, p;
53 int color = ADDR_COLOR(address);
54
55 p = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
56
57 if (likely(p)) {
58 for (i = 0; i < PAGE_ORDER; i++) {
59 set_page_count(p, 1);
60 ClearPageCompound(p);
61
62 if (PADDR_COLOR(page_address(pg)) == color)
63 page = p;
64 else
65 free_page(p);
66 }
67 clear_highpage(page);
68 }
69
70 return page;
71}
72
73#endif
74
75
76
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c
new file mode 100644
index 0000000000..d3bd3bfc3b
--- /dev/null
+++ b/arch/xtensa/mm/tlb.c
@@ -0,0 +1,545 @@
1/*
2 * arch/xtensa/mm/mmu.c
3 *
4 * Logic that manipulates the Xtensa MMU. Derived from MIPS.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2003 Tensilica Inc.
11 *
12 * Joe Taylor
13 * Chris Zankel <chris@zankel.net>
14 * Marc Gauthier
15 */
16
17#include <linux/mm.h>
18#include <asm/processor.h>
19#include <asm/mmu_context.h>
20#include <asm/tlbflush.h>
21#include <asm/system.h>
22#include <asm/cacheflush.h>
23
24
25static inline void __flush_itlb_all (void)
26{
27 int way, index;
28
29 for (way = 0; way < XCHAL_ITLB_ARF_WAYS; way++) {
30 for (index = 0; index < ITLB_ENTRIES_PER_ARF_WAY; index++) {
31 int entry = way + (index << PAGE_SHIFT);
32 invalidate_itlb_entry_no_isync (entry);
33 }
34 }
35 asm volatile ("isync\n");
36}
37
38static inline void __flush_dtlb_all (void)
39{
40 int way, index;
41
42 for (way = 0; way < XCHAL_DTLB_ARF_WAYS; way++) {
43 for (index = 0; index < DTLB_ENTRIES_PER_ARF_WAY; index++) {
44 int entry = way + (index << PAGE_SHIFT);
45 invalidate_dtlb_entry_no_isync (entry);
46 }
47 }
48 asm volatile ("isync\n");
49}
50
51
52void flush_tlb_all (void)
53{
54 __flush_itlb_all();
55 __flush_dtlb_all();
56}
57
58/* If mm is current, we simply assign the current task a new ASID, thus,
59 * invalidating all previous tlb entries. If mm is someone else's user mapping,
60 * wie invalidate the context, thus, when that user mapping is swapped in,
61 * a new context will be assigned to it.
62 */
63
64void flush_tlb_mm(struct mm_struct *mm)
65{
66#if 0
67 printk("[tlbmm<%lx>]\n", (unsigned long)mm->context);
68#endif
69
70 if (mm == current->active_mm) {
71 int flags;
72 local_save_flags(flags);
73 get_new_mmu_context(mm, asid_cache);
74 set_rasid_register(ASID_INSERT(mm->context));
75 local_irq_restore(flags);
76 }
77 else
78 mm->context = 0;
79}
80
81void flush_tlb_range (struct vm_area_struct *vma,
82 unsigned long start, unsigned long end)
83{
84 struct mm_struct *mm = vma->vm_mm;
85 unsigned long flags;
86
87 if (mm->context == NO_CONTEXT)
88 return;
89
90#if 0
91 printk("[tlbrange<%02lx,%08lx,%08lx>]\n",
92 (unsigned long)mm->context, start, end);
93#endif
94 local_save_flags(flags);
95
96 if (end-start + (PAGE_SIZE-1) <= SMALLEST_NTLB_ENTRIES << PAGE_SHIFT) {
97 int oldpid = get_rasid_register();
98 set_rasid_register (ASID_INSERT(mm->context));
99 start &= PAGE_MASK;
100 if (vma->vm_flags & VM_EXEC)
101 while(start < end) {
102 invalidate_itlb_mapping(start);
103 invalidate_dtlb_mapping(start);
104 start += PAGE_SIZE;
105 }
106 else
107 while(start < end) {
108 invalidate_dtlb_mapping(start);
109 start += PAGE_SIZE;
110 }
111
112 set_rasid_register(oldpid);
113 } else {
114 get_new_mmu_context(mm, asid_cache);
115 if (mm == current->active_mm)
116 set_rasid_register(ASID_INSERT(mm->context));
117 }
118 local_irq_restore(flags);
119}
120
121void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
122{
123 struct mm_struct* mm = vma->vm_mm;
124 unsigned long flags;
125 int oldpid;
126#if 0
127 printk("[tlbpage<%02lx,%08lx>]\n",
128 (unsigned long)mm->context, page);
129#endif
130
131 if(mm->context == NO_CONTEXT)
132 return;
133
134 local_save_flags(flags);
135
136 oldpid = get_rasid_register();
137
138 if (vma->vm_flags & VM_EXEC)
139 invalidate_itlb_mapping(page);
140 invalidate_dtlb_mapping(page);
141
142 set_rasid_register(oldpid);
143
144 local_irq_restore(flags);
145
146#if 0
147 flush_tlb_all();
148 return;
149#endif
150}
151
152
153#ifdef DEBUG_TLB
154
155#define USE_ITLB 0
156#define USE_DTLB 1
157
158struct way_config_t {
159 int indicies;
160 int indicies_log2;
161 int pgsz_log2;
162 int arf;
163};
164
165static struct way_config_t itlb[XCHAL_ITLB_WAYS] =
166{
167 { XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES),
168 XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES_LOG2),
169 XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, PAGESZ_LOG2_MIN),
170 XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ARF)
171 },
172 { XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES),
173 XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES_LOG2),
174 XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, PAGESZ_LOG2_MIN),
175 XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ARF)
176 },
177 { XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES),
178 XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES_LOG2),
179 XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, PAGESZ_LOG2_MIN),
180 XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ARF)
181 },
182 { XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES),
183 XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES_LOG2),
184 XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, PAGESZ_LOG2_MIN),
185 XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ARF)
186 },
187 { XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES),
188 XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES_LOG2),
189 XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, PAGESZ_LOG2_MIN),
190 XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ARF)
191 },
192 { XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES),
193 XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES_LOG2),
194 XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, PAGESZ_LOG2_MIN),
195 XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ARF)
196 },
197 { XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES),
198 XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES_LOG2),
199 XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, PAGESZ_LOG2_MIN),
200 XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ARF)
201 }
202};
203
204static struct way_config_t dtlb[XCHAL_DTLB_WAYS] =
205{
206 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES),
207 XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES_LOG2),
208 XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, PAGESZ_LOG2_MIN),
209 XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ARF)
210 },
211 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES),
212 XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES_LOG2),
213 XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, PAGESZ_LOG2_MIN),
214 XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ARF)
215 },
216 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES),
217 XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES_LOG2),
218 XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, PAGESZ_LOG2_MIN),
219 XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ARF)
220 },
221 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES),
222 XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES_LOG2),
223 XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, PAGESZ_LOG2_MIN),
224 XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ARF)
225 },
226 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES),
227 XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES_LOG2),
228 XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, PAGESZ_LOG2_MIN),
229 XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ARF)
230 },
231 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES),
232 XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES_LOG2),
233 XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, PAGESZ_LOG2_MIN),
234 XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ARF)
235 },
236 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES),
237 XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES_LOG2),
238 XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, PAGESZ_LOG2_MIN),
239 XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ARF)
240 },
241 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES),
242 XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES_LOG2),
243 XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, PAGESZ_LOG2_MIN),
244 XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ARF)
245 },
246 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES),
247 XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES_LOG2),
248 XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, PAGESZ_LOG2_MIN),
249 XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ARF)
250 },
251 { XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES),
252 XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES_LOG2),
253 XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, PAGESZ_LOG2_MIN),
254 XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ARF)
255 }
256};
257
258/* Total number of entries: */
259#define ITLB_TOTAL_ENTRIES \
260 XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES) + \
261 XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES) + \
262 XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES) + \
263 XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES) + \
264 XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES) + \
265 XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES) + \
266 XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES)
267#define DTLB_TOTAL_ENTRIES \
268 XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES) + \
269 XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES) + \
270 XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES) + \
271 XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES) + \
272 XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES) + \
273 XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES) + \
274 XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES) + \
275 XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES) + \
276 XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES) + \
277 XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES)
278
279
280typedef struct {
281 unsigned va;
282 unsigned pa;
283 unsigned char asid;
284 unsigned char ca;
285 unsigned char way;
286 unsigned char index;
287 unsigned char pgsz_log2; /* 0 .. 32 */
288 unsigned char type; /* 0=ITLB 1=DTLB */
289} tlb_dump_entry_t;
290
291/* Return -1 if a precedes b, +1 if a follows b, 0 if same: */
292int cmp_tlb_dump_info( tlb_dump_entry_t *a, tlb_dump_entry_t *b )
293{
294 if (a->asid < b->asid) return -1;
295 if (a->asid > b->asid) return 1;
296 if (a->va < b->va) return -1;
297 if (a->va > b->va) return 1;
298 if (a->pa < b->pa) return -1;
299 if (a->pa > b->pa) return 1;
300 if (a->ca < b->ca) return -1;
301 if (a->ca > b->ca) return 1;
302 if (a->way < b->way) return -1;
303 if (a->way > b->way) return 1;
304 if (a->index < b->index) return -1;
305 if (a->index > b->index) return 1;
306 return 0;
307}
308
309void sort_tlb_dump_info( tlb_dump_entry_t *t, int n )
310{
311 int i, j;
312 /* Simple O(n*n) sort: */
313 for (i = 0; i < n-1; i++)
314 for (j = i+1; j < n; j++)
315 if (cmp_tlb_dump_info(t+i, t+j) > 0) {
316 tlb_dump_entry_t tmp = t[i];
317 t[i] = t[j];
318 t[j] = tmp;
319 }
320}
321
322
323static tlb_dump_entry_t itlb_dump_info[ITLB_TOTAL_ENTRIES];
324static tlb_dump_entry_t dtlb_dump_info[DTLB_TOTAL_ENTRIES];
325
326
327static inline char *way_type (int type)
328{
329 return type ? "autorefill" : "non-autorefill";
330}
331
332void print_entry (struct way_config_t *way_info,
333 unsigned int way,
334 unsigned int index,
335 unsigned int virtual,
336 unsigned int translation)
337{
338 char valid_chr;
339 unsigned int va, pa, asid, ca;
340
341 va = virtual &
342 ~((1 << (way_info->pgsz_log2 + way_info->indicies_log2)) - 1);
343 asid = virtual & ((1 << XCHAL_MMU_ASID_BITS) - 1);
344 pa = translation & ~((1 << way_info->pgsz_log2) - 1);
345 ca = translation & ((1 << XCHAL_MMU_CA_BITS) - 1);
346 valid_chr = asid ? 'V' : 'I';
347
348 /* Compute and incorporate the effect of the index bits on the
349 * va. It's more useful for kernel debugging, since we always
350 * want to know the effective va anyway. */
351
352 va += index << way_info->pgsz_log2;
353
354 printk ("\t[%d,%d] (%c) vpn 0x%.8x ppn 0x%.8x asid 0x%.2x am 0x%x\n",
355 way, index, valid_chr, va, pa, asid, ca);
356}
357
358void print_itlb_entry (struct way_config_t *way_info, int way, int index)
359{
360 print_entry (way_info, way, index,
361 read_itlb_virtual (way + (index << way_info->pgsz_log2)),
362 read_itlb_translation (way + (index << way_info->pgsz_log2)));
363}
364
365void print_dtlb_entry (struct way_config_t *way_info, int way, int index)
366{
367 print_entry (way_info, way, index,
368 read_dtlb_virtual (way + (index << way_info->pgsz_log2)),
369 read_dtlb_translation (way + (index << way_info->pgsz_log2)));
370}
371
372void dump_itlb (void)
373{
374 int way, index;
375
376 printk ("\nITLB: ways = %d\n", XCHAL_ITLB_WAYS);
377
378 for (way = 0; way < XCHAL_ITLB_WAYS; way++) {
379 printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
380 way, itlb[way].indicies,
381 itlb[way].pgsz_log2, way_type(itlb[way].arf));
382 for (index = 0; index < itlb[way].indicies; index++) {
383 print_itlb_entry(&itlb[way], way, index);
384 }
385 }
386}
387
388void dump_dtlb (void)
389{
390 int way, index;
391
392 printk ("\nDTLB: ways = %d\n", XCHAL_DTLB_WAYS);
393
394 for (way = 0; way < XCHAL_DTLB_WAYS; way++) {
395 printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
396 way, dtlb[way].indicies,
397 dtlb[way].pgsz_log2, way_type(dtlb[way].arf));
398 for (index = 0; index < dtlb[way].indicies; index++) {
399 print_dtlb_entry(&dtlb[way], way, index);
400 }
401 }
402}
403
404void dump_tlb (tlb_dump_entry_t *tinfo, struct way_config_t *config,
405 int entries, int ways, int type, int show_invalid)
406{
407 tlb_dump_entry_t *e = tinfo;
408 int way, i;
409
410 /* Gather all info: */
411 for (way = 0; way < ways; way++) {
412 struct way_config_t *cfg = config + way;
413 for (i = 0; i < cfg->indicies; i++) {
414 unsigned wayindex = way + (i << cfg->pgsz_log2);
415 unsigned vv = (type ? read_dtlb_virtual (wayindex)
416 : read_itlb_virtual (wayindex));
417 unsigned pp = (type ? read_dtlb_translation (wayindex)
418 : read_itlb_translation (wayindex));
419
420 /* Compute and incorporate the effect of the index bits on the
421 * va. It's more useful for kernel debugging, since we always
422 * want to know the effective va anyway. */
423
424 e->va = (vv & ~((1 << (cfg->pgsz_log2 + cfg->indicies_log2)) - 1));
425 e->va += (i << cfg->pgsz_log2);
426 e->pa = (pp & ~((1 << cfg->pgsz_log2) - 1));
427 e->asid = (vv & ((1 << XCHAL_MMU_ASID_BITS) - 1));
428 e->ca = (pp & ((1 << XCHAL_MMU_CA_BITS) - 1));
429 e->way = way;
430 e->index = i;
431 e->pgsz_log2 = cfg->pgsz_log2;
432 e->type = type;
433 e++;
434 }
435 }
436#if 1
437 /* Sort by ASID and VADDR: */
438 sort_tlb_dump_info (tinfo, entries);
439#endif
440
441 /* Display all sorted info: */
442 printk ("\n%cTLB dump:\n", (type ? 'D' : 'I'));
443 for (e = tinfo, i = 0; i < entries; i++, e++) {
444#if 0
445 if (e->asid == 0 && !show_invalid)
446 continue;
447#endif
448 printk ("%c way=%d i=%d ASID=%02X V=%08X -> P=%08X CA=%X (%d %cB)\n",
449 (e->type ? 'D' : 'I'), e->way, e->index,
450 e->asid, e->va, e->pa, e->ca,
451 (1 << (e->pgsz_log2 % 10)),
452 " kMG"[e->pgsz_log2 / 10]
453 );
454 }
455}
456
457void dump_tlbs2 (int showinv)
458{
459 dump_tlb (itlb_dump_info, itlb, ITLB_TOTAL_ENTRIES, XCHAL_ITLB_WAYS, 0, showinv);
460 dump_tlb (dtlb_dump_info, dtlb, DTLB_TOTAL_ENTRIES, XCHAL_DTLB_WAYS, 1, showinv);
461}
462
463void dump_all_tlbs (void)
464{
465 dump_tlbs2 (1);
466}
467
468void dump_valid_tlbs (void)
469{
470 dump_tlbs2 (0);
471}
472
473
474void dump_tlbs (void)
475{
476 dump_itlb();
477 dump_dtlb();
478}
479
480void dump_cache_tag(int dcache, int idx)
481{
482 int w, i, s, e;
483 unsigned long tag, index;
484 unsigned long num_lines, num_ways, cache_size, line_size;
485
486 num_ways = dcache ? XCHAL_DCACHE_WAYS : XCHAL_ICACHE_WAYS;
487 cache_size = dcache ? XCHAL_DCACHE_SIZE : XCHAL_ICACHE_SIZE;
488 line_size = dcache ? XCHAL_DCACHE_LINESIZE : XCHAL_ICACHE_LINESIZE;
489
490 num_lines = cache_size / num_ways;
491
492 s = 0; e = num_lines;
493
494 if (idx >= 0)
495 e = (s = idx * line_size) + 1;
496
497 for (i = s; i < e; i+= line_size) {
498 printk("\nline %#08x:", i);
499 for (w = 0; w < num_ways; w++) {
500 index = w * num_lines + i;
501 if (dcache)
502 __asm__ __volatile__("ldct %0, %1\n\t"
503 : "=a"(tag) : "a"(index));
504 else
505 __asm__ __volatile__("lict %0, %1\n\t"
506 : "=a"(tag) : "a"(index));
507
508 printk(" %#010lx", tag);
509 }
510 }
511 printk ("\n");
512}
513
514void dump_icache(int index)
515{
516 unsigned long data, addr;
517 int w, i;
518
519 const unsigned long num_ways = XCHAL_ICACHE_WAYS;
520 const unsigned long cache_size = XCHAL_ICACHE_SIZE;
521 const unsigned long line_size = XCHAL_ICACHE_LINESIZE;
522 const unsigned long num_lines = cache_size / num_ways / line_size;
523
524 for (w = 0; w < num_ways; w++) {
525 printk ("\nWay %d", w);
526
527 for (i = 0; i < line_size; i+= 4) {
528 addr = w * num_lines + index * line_size + i;
529 __asm__ __volatile__("licw %0, %1\n\t"
530 : "=a"(data) : "a"(addr));
531 printk(" %#010lx", data);
532 }
533 }
534 printk ("\n");
535}
536
537void dump_cache_tags(void)
538{
539 printk("Instruction cache\n");
540 dump_cache_tag(0, -1);
541 printk("Data cache\n");
542 dump_cache_tag(1, -1);
543}
544
545#endif
diff --git a/arch/xtensa/platform-iss/Makefile b/arch/xtensa/platform-iss/Makefile
new file mode 100644
index 0000000000..5b394e9620
--- /dev/null
+++ b/arch/xtensa/platform-iss/Makefile
@@ -0,0 +1,13 @@
1# $Id: Makefile,v 1.1.1.1 2002/08/28 16:10:14 aroll Exp $
2#
3# Makefile for the Xtensa Instruction Set Simulator (ISS)
4# "prom monitor" library routines under Linux.
5#
6# Note! Dependencies are done automagically by 'make dep', which also
7# removes any old dependencies. DON'T put your own dependencies here
8# unless it's something special (ie not a .c file).
9#
10# Note 2! The CFLAGS definitions are in the main makefile...
11
12obj-y = io.o console.o setup.o network.o
13
diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c
new file mode 100644
index 0000000000..9e2b53f6a9
--- /dev/null
+++ b/arch/xtensa/platform-iss/console.c
@@ -0,0 +1,303 @@
1/*
2 * arch/xtensa/platform-iss/console.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001-2005 Tensilica Inc.
9 * Authors Christian Zankel, Joe Taylor
10 */
11
12#include <linux/module.h>
13#include <linux/config.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/console.h>
17#include <linux/init.h>
18#include <linux/slab.h>
19#include <linux/mm.h>
20#include <linux/major.h>
21#include <linux/param.h>
22#include <linux/serial.h>
23#include <linux/serialP.h>
24#include <linux/console.h>
25
26#include <asm/uaccess.h>
27#include <asm/irq.h>
28
29#include <xtensa/simcall.h>
30
31#include <linux/tty.h>
32#include <linux/tty_flip.h>
33
34#ifdef SERIAL_INLINE
35#define _INLINE_ inline
36#endif
37
38#define SERIAL_MAX_NUM_LINES 1
39#define SERIAL_TIMER_VALUE (20 * HZ)
40
41static struct tty_driver *serial_driver;
42static struct timer_list serial_timer;
43
44static DEFINE_SPINLOCK(timer_lock);
45
46int errno;
47
48static int __simc (int a, int b, int c, int d, int e, int f)
49{
50 int ret;
51 __asm__ __volatile__ ("simcall\n"
52 "mov %0, a2\n"
53 "mov %1, a3\n" : "=a" (ret), "=a" (errno)
54 : : "a2", "a3");
55 return ret;
56}
57
58static char *serial_version = "0.1";
59static char *serial_name = "ISS serial driver";
60
61/*
62 * This routine is called whenever a serial port is opened. It
63 * enables interrupts for a serial port, linking in its async structure into
64 * the IRQ chain. It also performs the serial-specific
65 * initialization for the tty structure.
66 */
67
68static void rs_poll(unsigned long);
69
70static int rs_open(struct tty_struct *tty, struct file * filp)
71{
72 int line = tty->index;
73
74 if ((line < 0) || (line >= SERIAL_MAX_NUM_LINES))
75 return -ENODEV;
76
77 spin_lock(&timer_lock);
78
79 if (tty->count == 1) {
80 init_timer(&serial_timer);
81 serial_timer.data = (unsigned long) tty;
82 serial_timer.function = rs_poll;
83 mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
84 }
85 spin_unlock(&timer_lock);
86
87 return 0;
88}
89
90
91/*
92 * ------------------------------------------------------------
93 * iss_serial_close()
94 *
95 * This routine is called when the serial port gets closed. First, we
96 * wait for the last remaining data to be sent. Then, we unlink its
97 * async structure from the interrupt chain if necessary, and we free
98 * that IRQ if nothing is left in the chain.
99 * ------------------------------------------------------------
100 */
101static void rs_close(struct tty_struct *tty, struct file * filp)
102{
103 spin_lock(&timer_lock);
104 if (tty->count == 1)
105 del_timer_sync(&serial_timer);
106 spin_unlock(&timer_lock);
107}
108
109
110static int rs_write(struct tty_struct * tty,
111 const unsigned char *buf, int count)
112{
113 /* see drivers/char/serialX.c to reference original version */
114
115 __simc (SYS_write, 1, (unsigned long)buf, count, 0, 0);
116 return count;
117}
118
119static void rs_poll(unsigned long priv)
120{
121 struct tty_struct* tty = (struct tty_struct*) priv;
122
123 struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
124 int i = 0;
125 unsigned char c;
126
127 spin_lock(&timer_lock);
128
129 while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){
130 __simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0);
131 tty->flip.count++;
132 *tty->flip.char_buf_ptr++ = c;
133 *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
134 i++;
135 }
136
137 if (i)
138 tty_flip_buffer_push(tty);
139
140
141 mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
142 spin_unlock(&timer_lock);
143}
144
145
146static void rs_put_char(struct tty_struct *tty, unsigned char ch)
147{
148 char buf[2];
149
150 if (!tty)
151 return;
152
153 buf[0] = ch;
154 buf[1] = '\0'; /* Is this NULL necessary? */
155 __simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);
156}
157
158static void rs_flush_chars(struct tty_struct *tty)
159{
160}
161
162static int rs_write_room(struct tty_struct *tty)
163{
164 /* Let's say iss can always accept 2K characters.. */
165 return 2 * 1024;
166}
167
168static int rs_chars_in_buffer(struct tty_struct *tty)
169{
170 /* the iss doesn't buffer characters */
171 return 0;
172}
173
174static void rs_hangup(struct tty_struct *tty)
175{
176 /* Stub, once again.. */
177}
178
179static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
180{
181 /* Stub, once again.. */
182}
183
184static int rs_read_proc(char *page, char **start, off_t off, int count,
185 int *eof, void *data)
186{
187 int len = 0;
188 off_t begin = 0;
189
190 len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
191 *eof = 1;
192
193 if (off >= len + begin)
194 return 0;
195
196 *start = page + (off - begin);
197 return ((count < begin + len - off) ? count : begin + len - off);
198}
199
200
201int register_serial(struct serial_struct*);
202void unregister_serial(int);
203
204static struct tty_operations serial_ops = {
205 .open = rs_open,
206 .close = rs_close,
207 .write = rs_write,
208 .put_char = rs_put_char,
209 .flush_chars = rs_flush_chars,
210 .write_room = rs_write_room,
211 .chars_in_buffer = rs_chars_in_buffer,
212 .hangup = rs_hangup,
213 .wait_until_sent = rs_wait_until_sent,
214 .read_proc = rs_read_proc
215};
216
217int __init rs_init(void)
218{
219 serial_driver = alloc_tty_driver(1);
220
221 printk ("%s %s\n", serial_name, serial_version);
222
223 /* Initialize the tty_driver structure */
224
225 serial_driver->owner = THIS_MODULE;
226 serial_driver->driver_name = "iss_serial";
227 serial_driver->name = "ttyS";
228 serial_driver->major = TTY_MAJOR;
229 serial_driver->minor_start = 64;
230 serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
231 serial_driver->subtype = SERIAL_TYPE_NORMAL;
232 serial_driver->init_termios = tty_std_termios;
233 serial_driver->init_termios.c_cflag =
234 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
235 serial_driver->flags = TTY_DRIVER_REAL_RAW;
236
237 tty_set_operations(serial_driver, &serial_ops);
238
239 if (tty_register_driver(serial_driver))
240 panic("Couldn't register serial driver\n");
241 return 0;
242}
243
244
245static __exit void rs_exit(void)
246{
247 int error;
248
249 if ((error = tty_unregister_driver(serial_driver)))
250 printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
251 error);
252 put_tty_driver(serial_driver);
253}
254
255
256/* We use `late_initcall' instead of just `__initcall' as a workaround for
257 * the fact that (1) simcons_tty_init can't be called before tty_init,
258 * (2) tty_init is called via `module_init', (3) if statically linked,
259 * module_init == device_init, and (4) there's no ordering of init lists.
260 * We can do this easily because simcons is always statically linked, but
261 * other tty drivers that depend on tty_init and which must use
262 * `module_init' to declare their init routines are likely to be broken.
263 */
264
265late_initcall(rs_init);
266
267
268#ifdef CONFIG_SERIAL_CONSOLE
269
270static void iss_console_write(struct console *co, const char *s, unsigned count)
271{
272 int len = strlen(s);
273
274 if (s != 0 && *s != 0)
275 __simc (SYS_write, 1, (unsigned long)s,
276 count < len ? count : len,0,0);
277}
278
279static struct tty_driver* iss_console_device(struct console *c, int *index)
280{
281 *index = c->index;
282 return serial_driver;
283}
284
285
286static struct console sercons = {
287 .name = "ttyS",
288 .write = iss_console_write,
289 .device = iss_console_device,
290 .flags = CON_PRINTBUFFER,
291 .index = -1
292};
293
294static int __init iss_console_init(void)
295{
296 register_console(&sercons);
297 return 0;
298}
299
300console_initcall(iss_console_init);
301
302#endif /* CONFIG_SERIAL_CONSOLE */
303
diff --git a/arch/xtensa/platform-iss/io.c b/arch/xtensa/platform-iss/io.c
new file mode 100644
index 0000000000..5b161a5cb6
--- /dev/null
+++ b/arch/xtensa/platform-iss/io.c
@@ -0,0 +1,32 @@
1/* This file isn't really needed right now. */
2
3#if 0
4
5#include <asm/io.h>
6#include <xtensa/simcall.h>
7
8extern int __simc ();
9
10
11char iss_serial_getc()
12{
13 char c;
14 __simc( SYS_read, 0, &c, 1 );
15 return c;
16}
17
18void iss_serial_putc( char c )
19{
20 __simc( SYS_write, 1, &c, 1 );
21}
22
23void iss_serial_puts( char *s )
24{
25 if( s != 0 && *s != 0 )
26 __simc( SYS_write, 1, s, strlen(s) );
27}
28
29/*#error Need I/O ports to specific hardware!*/
30
31#endif
32
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
new file mode 100644
index 0000000000..498d7dced1
--- /dev/null
+++ b/arch/xtensa/platform-iss/network.c
@@ -0,0 +1,855 @@
1/*
2 *
3 * arch/xtensa/platform-iss/network.c
4 *
5 * Platform specific initialization.
6 *
7 * Authors: Chris Zankel <chris@zankel.net>
8 * Based on work form the UML team.
9 *
10 * Copyright 2005 Tensilica Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 */
18
19#include <linux/config.h>
20#include <linux/list.h>
21#include <linux/irq.h>
22#include <linux/spinlock.h>
23#include <linux/slab.h>
24#include <linux/timer.h>
25#include <linux/if_ether.h>
26#include <linux/inetdevice.h>
27#include <linux/init.h>
28#include <linux/if_tun.h>
29#include <linux/etherdevice.h>
30#include <linux/interrupt.h>
31#include <linux/ioctl.h>
32#include <linux/bootmem.h>
33#include <linux/ethtool.h>
34#include <linux/rtnetlink.h>
35#include <linux/timer.h>
36
37#include <xtensa/simcall.h>
38
39#define DRIVER_NAME "iss-netdev"
40#define ETH_MAX_PACKET 1500
41#define ETH_HEADER_OTHER 14
42#define ISS_NET_TIMER_VALUE (2 * HZ)
43
44
45static DEFINE_SPINLOCK(opened_lock);
46static LIST_HEAD(opened);
47
48static DEFINE_SPINLOCK(devices_lock);
49static LIST_HEAD(devices);
50
51/* ------------------------------------------------------------------------- */
52
53/* We currently only support the TUNTAP transport protocol. */
54
55#define TRANSPORT_TUNTAP_NAME "tuntap"
56#define TRANSPORT_TUNTAP_MTU ETH_MAX_PACKET
57
58struct tuntap_info {
59 char dev_name[IFNAMSIZ];
60 int fixed_config;
61 unsigned char gw[ETH_ALEN];
62 int fd;
63};
64
65/* ------------------------------------------------------------------------- */
66
67
68/* This structure contains out private information for the driver. */
69
70struct iss_net_private {
71
72 struct list_head device_list;
73 struct list_head opened_list;
74
75 spinlock_t lock;
76 struct net_device *dev;
77 struct platform_device pdev;
78 struct timer_list tl;
79 struct net_device_stats stats;
80
81 struct timer_list timer;
82 unsigned int timer_val;
83
84 int index;
85 int mtu;
86
87 unsigned char mac[ETH_ALEN];
88 int have_mac;
89
90 struct {
91 union {
92 struct tuntap_info tuntap;
93 } info;
94
95 int (*open)(struct iss_net_private *lp);
96 void (*close)(struct iss_net_private *lp);
97 int (*read)(struct iss_net_private *lp, struct sk_buff **skb);
98 int (*write)(struct iss_net_private *lp, struct sk_buff **skb);
99 unsigned short (*protocol)(struct sk_buff *skb);
100 int (*poll)(struct iss_net_private *lp);
101 } tp;
102
103};
104
105/* ======================= ISS SIMCALL INTERFACE =========================== */
106
107/* Note: __simc must _not_ be declared inline! */
108
109static int errno;
110
111static int __simc (int a, int b, int c, int d, int e, int f)
112{
113 int ret;
114 __asm__ __volatile__ ("simcall\n"
115 "mov %0, a2\n"
116 "mov %1, a3\n" : "=a" (ret), "=a" (errno)
117 : : "a2", "a3");
118 return ret;
119}
120
121static int inline simc_open(char *file, int flags, int mode)
122{
123 return __simc(SYS_open, (int) file, flags, mode, 0, 0);
124}
125
126static int inline simc_close(int fd)
127{
128 return __simc(SYS_close, fd, 0, 0, 0, 0);
129}
130
131static int inline simc_ioctl(int fd, int request, void *arg)
132{
133 return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
134}
135
136static int inline simc_read(int fd, void *buf, size_t count)
137{
138 return __simc(SYS_read, fd, (int) buf, count, 0, 0);
139}
140
141static int inline simc_write(int fd, void *buf, size_t count)
142{
143 return __simc(SYS_write, fd, (int) buf, count, 0, 0);
144}
145
146static int inline simc_poll(int fd)
147{
148 struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
149
150 return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,0,0);
151}
152
153/* ================================ HELPERS ================================ */
154
155
156static char *split_if_spec(char *str, ...)
157{
158 char **arg, *end;
159 va_list ap;
160
161 va_start(ap, str);
162 while ((arg = va_arg(ap, char**)) != NULL) {
163 if (*str == '\0')
164 return NULL;
165 end = strchr(str, ',');
166 if (end != str)
167 *arg = str;
168 if (end == NULL)
169 return NULL;
170 *end ++ = '\0';
171 str = end;
172 }
173 va_end(ap);
174 return str;
175}
176
177
178#if 0
179/* Adjust SKB. */
180
181struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
182{
183 if ((skb != NULL) && (skb_tailroom(skb) < extra)) {
184 struct sk_buff *skb2;
185
186 skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);
187 dev_kfree_skb(skb);
188 skb = skb2;
189 }
190 if (skb != NULL)
191 skb_put(skb, extra);
192
193 return skb;
194}
195#endif
196
197/* Return the IP address as a string for a given device. */
198
199static void dev_ip_addr(void *d, char *buf, char *bin_buf)
200{
201 struct net_device *dev = d;
202 struct in_device *ip = dev->ip_ptr;
203 struct in_ifaddr *in;
204 u32 addr;
205
206 if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) {
207 printk(KERN_WARNING "Device not assigned an IP address!\n");
208 return;
209 }
210
211 addr = in->ifa_address;
212 sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff,
213 (addr >> 16) & 0xff, addr >> 24);
214
215 if (bin_buf) {
216 bin_buf[0] = addr & 0xff;
217 bin_buf[1] = (addr >> 8) & 0xff;
218 bin_buf[2] = (addr >> 16) & 0xff;
219 bin_buf[3] = addr >> 24;
220 }
221}
222
223/* Set Ethernet address of the specified device. */
224
225static void inline set_ether_mac(void *d, unsigned char *addr)
226{
227 struct net_device *dev = d;
228 memcpy(dev->dev_addr, addr, ETH_ALEN);
229}
230
231
232/* ======================= TUNTAP TRANSPORT INTERFACE ====================== */
233
234static int tuntap_open(struct iss_net_private *lp)
235{
236 struct ifreq ifr;
237 char *dev_name = lp->tp.info.tuntap.dev_name;
238 int err = -EINVAL;
239 int fd;
240
241 /* We currently only support a fixed configuration. */
242
243 if (!lp->tp.info.tuntap.fixed_config)
244 return -EINVAL;
245
246 if ((fd = simc_open("/dev/net/tun", 02, 0)) < 0) { /* O_RDWR */
247 printk("Failed to open /dev/net/tun, returned %d "
248 "(errno = %d)\n", fd, errno);
249 return fd;
250 }
251
252 memset(&ifr, 0, sizeof ifr);
253 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
254 strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name - 1);
255
256 if ((err = simc_ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0) {
257 printk("Failed to set interface, returned %d "
258 "(errno = %d)\n", err, errno);
259 simc_close(fd);
260 return err;
261 }
262
263 lp->tp.info.tuntap.fd = fd;
264 return err;
265}
266
267static void tuntap_close(struct iss_net_private *lp)
268{
269#if 0
270 if (lp->tp.info.tuntap.fixed_config)
271 iter_addresses(lp->tp.info.tuntap.dev, close_addr, lp->host.dev_name);
272#endif
273 simc_close(lp->tp.info.tuntap.fd);
274 lp->tp.info.tuntap.fd = -1;
275}
276
277static int tuntap_read (struct iss_net_private *lp, struct sk_buff **skb)
278{
279#if 0
280 *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
281 if (*skb == NULL)
282 return -ENOMEM;
283#endif
284
285 return simc_read(lp->tp.info.tuntap.fd,
286 (*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER);
287}
288
289static int tuntap_write (struct iss_net_private *lp, struct sk_buff **skb)
290{
291 return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
292}
293
294unsigned short tuntap_protocol(struct sk_buff *skb)
295{
296 return eth_type_trans(skb, skb->dev);
297}
298
299static int tuntap_poll(struct iss_net_private *lp)
300{
301 return simc_poll(lp->tp.info.tuntap.fd);
302}
303
304/*
305 * Currently only a device name is supported.
306 * ethX=tuntap[,[mac address][,[device name]]]
307 */
308
309static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
310{
311 const int len = strlen(TRANSPORT_TUNTAP_NAME);
312 char *dev_name = NULL, *mac_str = NULL, *rem = NULL;
313
314 /* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */
315
316 if (strncmp(init, TRANSPORT_TUNTAP_NAME, len))
317 return 0;
318
319 if (*(init += strlen(TRANSPORT_TUNTAP_NAME)) == ',') {
320 if ((rem=split_if_spec(init+1, &mac_str, &dev_name)) != NULL) {
321 printk("Extra garbage on specification : '%s'\n", rem);
322 return 0;
323 }
324 } else if (*init != '\0') {
325 printk("Invalid argument: %s. Skipping device!\n", init);
326 return 0;
327 }
328
329 if (dev_name) {
330 strncpy(lp->tp.info.tuntap.dev_name, dev_name,
331 sizeof lp->tp.info.tuntap.dev_name);
332 lp->tp.info.tuntap.fixed_config = 1;
333 } else
334 strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME);
335
336
337#if 0
338 if (setup_etheraddr(mac_str, lp->mac))
339 lp->have_mac = 1;
340#endif
341 lp->mtu = TRANSPORT_TUNTAP_MTU;
342
343 //lp->info.tuntap.gate_addr = gate_addr;
344
345 lp->tp.info.tuntap.fd = -1;
346
347 lp->tp.open = tuntap_open;
348 lp->tp.close = tuntap_close;
349 lp->tp.read = tuntap_read;
350 lp->tp.write = tuntap_write;
351 lp->tp.protocol = tuntap_protocol;
352 lp->tp.poll = tuntap_poll;
353
354 printk("TUN/TAP backend - ");
355#if 0
356 if (lp->host.gate_addr != NULL)
357 printk("IP = %s", lp->host.gate_addr);
358#endif
359 printk("\n");
360
361 return 1;
362}
363
364/* ================================ ISS NET ================================ */
365
366static int iss_net_rx(struct net_device *dev)
367{
368 struct iss_net_private *lp = dev->priv;
369 int pkt_len;
370 struct sk_buff *skb;
371
372 /* Check if there is any new data. */
373
374 if (lp->tp.poll(lp) == 0)
375 return 0;
376
377 /* Try to allocate memory, if it fails, try again next round. */
378
379 if ((skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER)) == NULL) {
380 lp->stats.rx_dropped++;
381 return 0;
382 }
383
384 skb_reserve(skb, 2);
385
386 /* Setup skb */
387
388 skb->dev = dev;
389 skb->mac.raw = skb->data;
390 pkt_len = lp->tp.read(lp, &skb);
391 skb_put(skb, pkt_len);
392
393 if (pkt_len > 0) {
394 skb_trim(skb, pkt_len);
395 skb->protocol = lp->tp.protocol(skb);
396 // netif_rx(skb);
397 netif_rx_ni(skb);
398
399 lp->stats.rx_bytes += skb->len;
400 lp->stats.rx_packets++;
401 return pkt_len;
402 }
403 kfree_skb(skb);
404 return pkt_len;
405}
406
407static int iss_net_poll(void)
408{
409 struct list_head *ele;
410 int err, ret = 0;
411
412 spin_lock(&opened_lock);
413
414 list_for_each(ele, &opened) {
415 struct iss_net_private *lp;
416
417 lp = list_entry(ele, struct iss_net_private, opened_list);
418
419 if (!netif_running(lp->dev))
420 break;
421
422 spin_lock(&lp->lock);
423
424 while ((err = iss_net_rx(lp->dev)) > 0)
425 ret++;
426
427 spin_unlock(&lp->lock);
428
429 if (err < 0) {
430 printk(KERN_ERR "Device '%s' read returned %d, "
431 "shutting it down\n", lp->dev->name, err);
432 dev_close(lp->dev);
433 } else {
434 // FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ);
435 }
436 }
437
438 spin_unlock(&opened_lock);
439 return ret;
440}
441
442
443static void iss_net_timer(unsigned long priv)
444{
445 struct iss_net_private* lp = (struct iss_net_private*) priv;
446
447 spin_lock(&lp->lock);
448
449 iss_net_poll();
450
451 mod_timer(&lp->timer, jiffies + lp->timer_val);
452
453 spin_unlock(&lp->lock);
454}
455
456
457static int iss_net_open(struct net_device *dev)
458{
459 struct iss_net_private *lp = dev->priv;
460 char addr[sizeof "255.255.255.255\0"];
461 int err;
462
463 spin_lock(&lp->lock);
464
465 if ((err = lp->tp.open(lp)) < 0)
466 goto out;
467
468 if (!lp->have_mac) {
469 dev_ip_addr(dev, addr, &lp->mac[2]);
470 set_ether_mac(dev, lp->mac);
471 }
472
473 netif_start_queue(dev);
474
475 /* clear buffer - it can happen that the host side of the interface
476 * is full when we gethere. In this case, new data is never queued,
477 * SIGIOs never arrive, and the net never works.
478 */
479 while ((err = iss_net_rx(dev)) > 0)
480 ;
481
482 spin_lock(&opened_lock);
483 list_add(&lp->opened_list, &opened);
484 spin_unlock(&opened_lock);
485
486 init_timer(&lp->timer);
487 lp->timer_val = ISS_NET_TIMER_VALUE;
488 lp->timer.data = (unsigned long) lp;
489 lp->timer.function = iss_net_timer;
490 mod_timer(&lp->timer, jiffies + lp->timer_val);
491
492out:
493 spin_unlock(&lp->lock);
494 return err;
495}
496
497static int iss_net_close(struct net_device *dev)
498{
499 struct iss_net_private *lp = dev->priv;
500printk("iss_net_close!\n");
501 netif_stop_queue(dev);
502 spin_lock(&lp->lock);
503
504 spin_lock(&opened_lock);
505 list_del(&opened);
506 spin_unlock(&opened_lock);
507
508 del_timer_sync(&lp->timer);
509
510 lp->tp.close(lp);
511
512 spin_unlock(&lp->lock);
513 return 0;
514}
515
516static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
517{
518 struct iss_net_private *lp = dev->priv;
519 unsigned long flags;
520 int len;
521
522 netif_stop_queue(dev);
523 spin_lock_irqsave(&lp->lock, flags);
524
525 len = lp->tp.write(lp, &skb);
526
527 if (len == skb->len) {
528 lp->stats.tx_packets++;
529 lp->stats.tx_bytes += skb->len;
530 dev->trans_start = jiffies;
531 netif_start_queue(dev);
532
533 /* this is normally done in the interrupt when tx finishes */
534 netif_wake_queue(dev);
535
536 } else if (len == 0) {
537 netif_start_queue(dev);
538 lp->stats.tx_dropped++;
539
540 } else {
541 netif_start_queue(dev);
542 printk(KERN_ERR "iss_net_start_xmit: failed(%d)\n", len);
543 }
544
545 spin_unlock_irqrestore(&lp->lock, flags);
546
547 dev_kfree_skb(skb);
548 return 0;
549}
550
551
552static struct net_device_stats *iss_net_get_stats(struct net_device *dev)
553{
554 struct iss_net_private *lp = dev->priv;
555 return &lp->stats;
556}
557
558static void iss_net_set_multicast_list(struct net_device *dev)
559{
560#if 0
561 if (dev->flags & IFF_PROMISC)
562 return;
563 else if (dev->mc_count)
564 dev->flags |= IFF_ALLMULTI;
565 else
566 dev->flags &= ~IFF_ALLMULTI;
567#endif
568}
569
570static void iss_net_tx_timeout(struct net_device *dev)
571{
572#if 0
573 dev->trans_start = jiffies;
574 netif_wake_queue(dev);
575#endif
576}
577
578static int iss_net_set_mac(struct net_device *dev, void *addr)
579{
580#if 0
581 struct iss_net_private *lp = dev->priv;
582 struct sockaddr *hwaddr = addr;
583
584 spin_lock(&lp->lock);
585 memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
586 spin_unlock(&lp->lock);
587#endif
588
589 return 0;
590}
591
592static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
593{
594#if 0
595 struct iss_net_private *lp = dev->priv;
596 int err = 0;
597
598 spin_lock(&lp->lock);
599
600 // FIXME not needed new_mtu = transport_set_mtu(new_mtu, &lp->user);
601
602 if (new_mtu < 0)
603 err = new_mtu;
604 else
605 dev->mtu = new_mtu;
606
607 spin_unlock(&lp->lock);
608 return err;
609#endif
610 return -EINVAL;
611}
612
613static int iss_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
614{
615#if 0
616 static const struct ethtool_drvinfo info = {
617 .cmd = ETHTOOL_GDRVINFO,
618 .driver = DRIVER_NAME,
619 .version = "42",
620 };
621 void *useraddr;
622 u32 ethcmd;
623
624 switch (cmd) {
625 case SIOCETHTOOL:
626 useraddr = ifr->ifr_data;
627 if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
628 return -EFAULT;
629
630 switch (ethcmd) {
631 case ETHTOOL_GDRVINFO:
632 if (copy_to_user(useraddr, &info, sizeof(info)))
633 return -EFAULT;
634 return 0;
635 default:
636 return -EOPNOTSUPP;
637 }
638 default:
639 return -EINVAL;
640 }
641#endif
642 return -EINVAL;
643}
644
645void iss_net_user_timer_expire(unsigned long _conn)
646{
647}
648
649
650static struct device_driver iss_net_driver = {
651 .name = DRIVER_NAME,
652 .bus = &platform_bus_type,
653};
654
655static int driver_registered;
656
657static int iss_net_configure(int index, char *init)
658{
659 struct net_device *dev;
660 struct iss_net_private *lp;
661 int err;
662
663 if ((dev = alloc_etherdev(sizeof *lp)) == NULL) {
664 printk(KERN_ERR "eth_configure: failed to allocate device\n");
665 return 1;
666 }
667
668 /* Initialize private element. */
669
670 lp = dev->priv;
671 *lp = ((struct iss_net_private) {
672 .device_list = LIST_HEAD_INIT(lp->device_list),
673 .opened_list = LIST_HEAD_INIT(lp->opened_list),
674 .lock = SPIN_LOCK_UNLOCKED,
675 .dev = dev,
676 .index = index,
677 //.fd = -1,
678 .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 },
679 .have_mac = 0,
680 });
681
682 /*
683 * Try all transport protocols.
684 * Note: more protocols can be added by adding '&& !X_init(lp, eth)'.
685 */
686
687 if (!tuntap_probe(lp, index, init)) {
688 printk("Invalid arguments. Skipping device!\n");
689 goto errout;
690 }
691
692 printk(KERN_INFO "Netdevice %d ", index);
693 if (lp->have_mac)
694 printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
695 lp->mac[0], lp->mac[1],
696 lp->mac[2], lp->mac[3],
697 lp->mac[4], lp->mac[5]);
698 printk(": ");
699
700 /* sysfs register */
701
702 if (!driver_registered) {
703 driver_register(&iss_net_driver);
704 driver_registered = 1;
705 }
706
707 spin_lock(&devices_lock);
708 list_add(&lp->device_list, &devices);
709 spin_unlock(&devices_lock);
710
711 lp->pdev.id = index;
712 lp->pdev.name = DRIVER_NAME;
713 platform_device_register(&lp->pdev);
714 SET_NETDEV_DEV(dev,&lp->pdev.dev);
715
716 /*
717 * If this name ends up conflicting with an existing registered
718 * netdevice, that is OK, register_netdev{,ice}() will notice this
719 * and fail.
720 */
721 snprintf(dev->name, sizeof dev->name, "eth%d", index);
722
723 dev->mtu = lp->mtu;
724 dev->open = iss_net_open;
725 dev->hard_start_xmit = iss_net_start_xmit;
726 dev->stop = iss_net_close;
727 dev->get_stats = iss_net_get_stats;
728 dev->set_multicast_list = iss_net_set_multicast_list;
729 dev->tx_timeout = iss_net_tx_timeout;
730 dev->set_mac_address = iss_net_set_mac;
731 dev->change_mtu = iss_net_change_mtu;
732 dev->do_ioctl = iss_net_ioctl;
733 dev->watchdog_timeo = (HZ >> 1);
734 dev->irq = -1;
735
736 rtnl_lock();
737 err = register_netdevice(dev);
738 rtnl_unlock();
739
740 if (err) {
741 printk("Error registering net device!\n");
742 /* XXX: should we call ->remove() here? */
743 free_netdev(dev);
744 return 1;
745 }
746
747 init_timer(&lp->tl);
748 lp->tl.function = iss_net_user_timer_expire;
749
750#if 0
751 if (lp->have_mac)
752 set_ether_mac(dev, lp->mac);
753#endif
754 return 0;
755
756errout:
757 // FIXME: unregister; free, etc..
758 return -EIO;
759
760}
761
762/* ------------------------------------------------------------------------- */
763
764/* Filled in during early boot */
765
766struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
767
768struct iss_net_init {
769 struct list_head list;
770 char *init; /* init string */
771 int index;
772};
773
774/*
775 * Parse the command line and look for 'ethX=...' fields, and register all
776 * those fields. They will be later initialized in iss_net_init.
777 */
778
779#define ERR KERN_ERR "iss_net_setup: "
780
781static int iss_net_setup(char *str)
782{
783 struct iss_net_private *device = NULL;
784 struct iss_net_init *new;
785 struct list_head *ele;
786 char *end;
787 int n;
788
789 n = simple_strtoul(str, &end, 0);
790 if (end == str) {
791 printk(ERR "Failed to parse '%s'\n", str);
792 return 1;
793 }
794 if (n < 0) {
795 printk(ERR "Device %d is negative\n", n);
796 return 1;
797 }
798 if (*(str = end) != '=') {
799 printk(ERR "Expected '=' after device number\n");
800 return 1;
801 }
802
803 spin_lock(&devices_lock);
804
805 list_for_each(ele, &devices) {
806 device = list_entry(ele, struct iss_net_private, device_list);
807 if (device->index == n)
808 break;
809 }
810
811 spin_unlock(&devices_lock);
812
813 if (device && device->index == n) {
814 printk(ERR "Device %d already configured\n", n);
815 return 1;
816 }
817
818 if ((new = alloc_bootmem(sizeof new)) == NULL) {
819 printk("Alloc_bootmem failed\n");
820 return 1;
821 }
822
823 INIT_LIST_HEAD(&new->list);
824 new->index = n;
825 new->init = str + 1;
826
827 list_add_tail(&new->list, &eth_cmd_line);
828 return 1;
829}
830
831#undef ERR
832
833__setup("eth", iss_net_setup);
834
835/*
836 * Initialize all ISS Ethernet devices previously registered in iss_net_setup.
837 */
838
839static int iss_net_init(void)
840{
841 struct list_head *ele, *next;
842
843 /* Walk through all Ethernet devices specified in the command line. */
844
845 list_for_each_safe(ele, next, &eth_cmd_line) {
846 struct iss_net_init *eth;
847 eth = list_entry(ele, struct iss_net_init, list);
848 iss_net_configure(eth->index, eth->init);
849 }
850
851 return 1;
852}
853
854module_init(iss_net_init);
855
diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c
new file mode 100644
index 0000000000..2e6dcbf0cc
--- /dev/null
+++ b/arch/xtensa/platform-iss/setup.c
@@ -0,0 +1,112 @@
1/*
2 *
3 * arch/xtensa/platform-iss/setup.c
4 *
5 * Platform specific initialization.
6 *
7 * Authors: Chris Zankel <chris@zankel.net>
8 * Joe Taylor <joe@tensilica.com>
9 *
10 * Copyright 2001 - 2005 Tensilica Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 */
18#include <linux/config.h>
19#include <linux/stddef.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/errno.h>
23#include <linux/reboot.h>
24#include <linux/pci.h>
25#include <linux/kdev_t.h>
26#include <linux/types.h>
27#include <linux/major.h>
28#include <linux/blkdev.h>
29#include <linux/console.h>
30#include <linux/delay.h>
31#include <linux/stringify.h>
32#include <linux/notifier.h>
33
34#include <asm/platform.h>
35#include <asm/bootparam.h>
36
37
38void __init platform_init(bp_tag_t* bootparam)
39{
40
41}
42
43void platform_halt(void)
44{
45 printk (" ** Called platform_halt(), looping forever! **\n");
46 while (1);
47}
48
49void platform_power_off(void)
50{
51 printk (" ** Called platform_power_off(), looping forever! **\n");
52 while (1);
53}
54void platform_restart(void)
55{
56 /* Flush and reset the mmu, simulate a processor reset, and
57 * jump to the reset vector. */
58
59 __asm__ __volatile__("movi a2, 15\n\t"
60 "wsr a2, " __stringify(ICOUNTLEVEL) "\n\t"
61 "movi a2, 0\n\t"
62 "wsr a2, " __stringify(ICOUNT) "\n\t"
63 "wsr a2, " __stringify(IBREAKENABLE) "\n\t"
64 "wsr a2, " __stringify(LCOUNT) "\n\t"
65 "movi a2, 0x1f\n\t"
66 "wsr a2, " __stringify(PS) "\n\t"
67 "isync\n\t"
68 "jx %0\n\t"
69 :
70 : "a" (XCHAL_RESET_VECTOR_VADDR)
71 : "a2");
72
73 /* control never gets here */
74}
75
76extern void iss_net_poll(void);
77
78const char twirl[]="|/-\\|/-\\";
79
80void platform_heartbeat(void)
81{
82#if 0
83 static int i = 0, j = 0;
84
85 if (--i < 0) {
86 i = 99;
87 printk("\r%c\r", twirl[j++]);
88 if (j == 8)
89 j = 0;
90 }
91#endif
92}
93
94
95
96static int
97iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
98{
99 __asm__ __volatile__("movi a2, -1; simcall\n");
100 return NOTIFY_DONE;
101}
102
103static struct notifier_block iss_panic_block = {
104 iss_panic_event,
105 NULL,
106 0
107};
108
109void __init platform_setup(char **p_cmdline)
110{
111 notifier_chain_register(&panic_notifier_list, &iss_panic_block);
112}
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 88d1ad656e..e0a53570fe 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -45,6 +45,7 @@
45#include <asm/semaphore.h> 45#include <asm/semaphore.h>
46#include <linux/init.h> 46#include <linux/init.h>
47#include <linux/device.h> 47#include <linux/device.h>
48#include <linux/compat.h>
48 49
49#define IPMI_DEVINTF_VERSION "v33" 50#define IPMI_DEVINTF_VERSION "v33"
50 51
@@ -500,10 +501,205 @@ static int ipmi_ioctl(struct inode *inode,
500 return rv; 501 return rv;
501} 502}
502 503
504#ifdef CONFIG_COMPAT
505
506/*
507 * The following code contains code for supporting 32-bit compatible
508 * ioctls on 64-bit kernels. This allows running 32-bit apps on the
509 * 64-bit kernel
510 */
511#define COMPAT_IPMICTL_SEND_COMMAND \
512 _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
513#define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \
514 _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
515#define COMPAT_IPMICTL_RECEIVE_MSG \
516 _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
517#define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC \
518 _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
519
520struct compat_ipmi_msg {
521 u8 netfn;
522 u8 cmd;
523 u16 data_len;
524 compat_uptr_t data;
525};
526
527struct compat_ipmi_req {
528 compat_uptr_t addr;
529 compat_uint_t addr_len;
530 compat_long_t msgid;
531 struct compat_ipmi_msg msg;
532};
533
534struct compat_ipmi_recv {
535 compat_int_t recv_type;
536 compat_uptr_t addr;
537 compat_uint_t addr_len;
538 compat_long_t msgid;
539 struct compat_ipmi_msg msg;
540};
541
542struct compat_ipmi_req_settime {
543 struct compat_ipmi_req req;
544 compat_int_t retries;
545 compat_uint_t retry_time_ms;
546};
547
548/*
549 * Define some helper functions for copying IPMI data
550 */
551static long get_compat_ipmi_msg(struct ipmi_msg *p64,
552 struct compat_ipmi_msg __user *p32)
553{
554 compat_uptr_t tmp;
555
556 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
557 __get_user(p64->netfn, &p32->netfn) ||
558 __get_user(p64->cmd, &p32->cmd) ||
559 __get_user(p64->data_len, &p32->data_len) ||
560 __get_user(tmp, &p32->data))
561 return -EFAULT;
562 p64->data = compat_ptr(tmp);
563 return 0;
564}
565
566static long put_compat_ipmi_msg(struct ipmi_msg *p64,
567 struct compat_ipmi_msg __user *p32)
568{
569 if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
570 __put_user(p64->netfn, &p32->netfn) ||
571 __put_user(p64->cmd, &p32->cmd) ||
572 __put_user(p64->data_len, &p32->data_len))
573 return -EFAULT;
574 return 0;
575}
576
577static long get_compat_ipmi_req(struct ipmi_req *p64,
578 struct compat_ipmi_req __user *p32)
579{
580
581 compat_uptr_t tmp;
582
583 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
584 __get_user(tmp, &p32->addr) ||
585 __get_user(p64->addr_len, &p32->addr_len) ||
586 __get_user(p64->msgid, &p32->msgid) ||
587 get_compat_ipmi_msg(&p64->msg, &p32->msg))
588 return -EFAULT;
589 p64->addr = compat_ptr(tmp);
590 return 0;
591}
592
593static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
594 struct compat_ipmi_req_settime __user *p32)
595{
596 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
597 get_compat_ipmi_req(&p64->req, &p32->req) ||
598 __get_user(p64->retries, &p32->retries) ||
599 __get_user(p64->retry_time_ms, &p32->retry_time_ms))
600 return -EFAULT;
601 return 0;
602}
603
604static long get_compat_ipmi_recv(struct ipmi_recv *p64,
605 struct compat_ipmi_recv __user *p32)
606{
607 compat_uptr_t tmp;
608
609 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
610 __get_user(p64->recv_type, &p32->recv_type) ||
611 __get_user(tmp, &p32->addr) ||
612 __get_user(p64->addr_len, &p32->addr_len) ||
613 __get_user(p64->msgid, &p32->msgid) ||
614 get_compat_ipmi_msg(&p64->msg, &p32->msg))
615 return -EFAULT;
616 p64->addr = compat_ptr(tmp);
617 return 0;
618}
619
620static long put_compat_ipmi_recv(struct ipmi_recv *p64,
621 struct compat_ipmi_recv __user *p32)
622{
623 if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
624 __put_user(p64->recv_type, &p32->recv_type) ||
625 __put_user(p64->addr_len, &p32->addr_len) ||
626 __put_user(p64->msgid, &p32->msgid) ||
627 put_compat_ipmi_msg(&p64->msg, &p32->msg))
628 return -EFAULT;
629 return 0;
630}
631
632/*
633 * Handle compatibility ioctls
634 */
635static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
636 unsigned long arg)
637{
638 int rc;
639 struct ipmi_file_private *priv = filep->private_data;
640
641 switch(cmd) {
642 case COMPAT_IPMICTL_SEND_COMMAND:
643 {
644 struct ipmi_req rp;
645
646 if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
647 return -EFAULT;
648
649 return handle_send_req(priv->user, &rp,
650 priv->default_retries,
651 priv->default_retry_time_ms);
652 }
653 case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
654 {
655 struct ipmi_req_settime sp;
656
657 if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
658 return -EFAULT;
659
660 return handle_send_req(priv->user, &sp.req,
661 sp.retries, sp.retry_time_ms);
662 }
663 case COMPAT_IPMICTL_RECEIVE_MSG:
664 case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
665 {
666 struct ipmi_recv *precv64, recv64;
667
668 if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
669 return -EFAULT;
670
671 precv64 = compat_alloc_user_space(sizeof(recv64));
672 if (copy_to_user(precv64, &recv64, sizeof(recv64)))
673 return -EFAULT;
674
675 rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
676 ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
677 ? IPMICTL_RECEIVE_MSG
678 : IPMICTL_RECEIVE_MSG_TRUNC),
679 (long) precv64);
680 if (rc != 0)
681 return rc;
682
683 if (copy_from_user(&recv64, precv64, sizeof(recv64)))
684 return -EFAULT;
685
686 if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
687 return -EFAULT;
688
689 return rc;
690 }
691 default:
692 return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
693 }
694}
695#endif
503 696
504static struct file_operations ipmi_fops = { 697static struct file_operations ipmi_fops = {
505 .owner = THIS_MODULE, 698 .owner = THIS_MODULE,
506 .ioctl = ipmi_ioctl, 699 .ioctl = ipmi_ioctl,
700#ifdef CONFIG_COMPAT
701 .compat_ioctl = compat_ipmi_ioctl,
702#endif
507 .open = ipmi_open, 703 .open = ipmi_open,
508 .release = ipmi_release, 704 .release = ipmi_release,
509 .fasync = ipmi_fasync, 705 .fasync = ipmi_fasync,
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 0c81652eab..1813d0d198 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -54,7 +54,9 @@ static int ipmi_init_msghandler(void);
54 54
55static int initialized = 0; 55static int initialized = 0;
56 56
57static struct proc_dir_entry *proc_ipmi_root = NULL; 57#ifdef CONFIG_PROC_FS
58struct proc_dir_entry *proc_ipmi_root = NULL;
59#endif /* CONFIG_PROC_FS */
58 60
59#define MAX_EVENTS_IN_QUEUE 25 61#define MAX_EVENTS_IN_QUEUE 25
60 62
@@ -124,11 +126,13 @@ struct ipmi_channel
124 unsigned char protocol; 126 unsigned char protocol;
125}; 127};
126 128
129#ifdef CONFIG_PROC_FS
127struct ipmi_proc_entry 130struct ipmi_proc_entry
128{ 131{
129 char *name; 132 char *name;
130 struct ipmi_proc_entry *next; 133 struct ipmi_proc_entry *next;
131}; 134};
135#endif
132 136
133#define IPMI_IPMB_NUM_SEQ 64 137#define IPMI_IPMB_NUM_SEQ 64
134#define IPMI_MAX_CHANNELS 8 138#define IPMI_MAX_CHANNELS 8
@@ -156,10 +160,13 @@ struct ipmi_smi
156 struct ipmi_smi_handlers *handlers; 160 struct ipmi_smi_handlers *handlers;
157 void *send_info; 161 void *send_info;
158 162
163#ifdef CONFIG_PROC_FS
159 /* A list of proc entries for this interface. This does not 164 /* A list of proc entries for this interface. This does not
160 need a lock, only one thread creates it and only one thread 165 need a lock, only one thread creates it and only one thread
161 destroys it. */ 166 destroys it. */
167 spinlock_t proc_entry_lock;
162 struct ipmi_proc_entry *proc_entries; 168 struct ipmi_proc_entry *proc_entries;
169#endif
163 170
164 /* A table of sequence numbers for this interface. We use the 171 /* A table of sequence numbers for this interface. We use the
165 sequence numbers for IPMB messages that go out of the 172 sequence numbers for IPMB messages that go out of the
@@ -1470,8 +1477,9 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
1470 read_proc_t *read_proc, write_proc_t *write_proc, 1477 read_proc_t *read_proc, write_proc_t *write_proc,
1471 void *data, struct module *owner) 1478 void *data, struct module *owner)
1472{ 1479{
1473 struct proc_dir_entry *file;
1474 int rv = 0; 1480 int rv = 0;
1481#ifdef CONFIG_PROC_FS
1482 struct proc_dir_entry *file;
1475 struct ipmi_proc_entry *entry; 1483 struct ipmi_proc_entry *entry;
1476 1484
1477 /* Create a list element. */ 1485 /* Create a list element. */
@@ -1497,10 +1505,13 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
1497 file->write_proc = write_proc; 1505 file->write_proc = write_proc;
1498 file->owner = owner; 1506 file->owner = owner;
1499 1507
1508 spin_lock(&smi->proc_entry_lock);
1500 /* Stick it on the list. */ 1509 /* Stick it on the list. */
1501 entry->next = smi->proc_entries; 1510 entry->next = smi->proc_entries;
1502 smi->proc_entries = entry; 1511 smi->proc_entries = entry;
1512 spin_unlock(&smi->proc_entry_lock);
1503 } 1513 }
1514#endif /* CONFIG_PROC_FS */
1504 1515
1505 return rv; 1516 return rv;
1506} 1517}
@@ -1509,6 +1520,7 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
1509{ 1520{
1510 int rv = 0; 1521 int rv = 0;
1511 1522
1523#ifdef CONFIG_PROC_FS
1512 sprintf(smi->proc_dir_name, "%d", num); 1524 sprintf(smi->proc_dir_name, "%d", num);
1513 smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); 1525 smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
1514 if (!smi->proc_dir) 1526 if (!smi->proc_dir)
@@ -1531,14 +1543,17 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
1531 rv = ipmi_smi_add_proc_entry(smi, "version", 1543 rv = ipmi_smi_add_proc_entry(smi, "version",
1532 version_file_read_proc, NULL, 1544 version_file_read_proc, NULL,
1533 smi, THIS_MODULE); 1545 smi, THIS_MODULE);
1546#endif /* CONFIG_PROC_FS */
1534 1547
1535 return rv; 1548 return rv;
1536} 1549}
1537 1550
1538static void remove_proc_entries(ipmi_smi_t smi) 1551static void remove_proc_entries(ipmi_smi_t smi)
1539{ 1552{
1553#ifdef CONFIG_PROC_FS
1540 struct ipmi_proc_entry *entry; 1554 struct ipmi_proc_entry *entry;
1541 1555
1556 spin_lock(&smi->proc_entry_lock);
1542 while (smi->proc_entries) { 1557 while (smi->proc_entries) {
1543 entry = smi->proc_entries; 1558 entry = smi->proc_entries;
1544 smi->proc_entries = entry->next; 1559 smi->proc_entries = entry->next;
@@ -1547,7 +1562,9 @@ static void remove_proc_entries(ipmi_smi_t smi)
1547 kfree(entry->name); 1562 kfree(entry->name);
1548 kfree(entry); 1563 kfree(entry);
1549 } 1564 }
1565 spin_unlock(&smi->proc_entry_lock);
1550 remove_proc_entry(smi->proc_dir_name, proc_ipmi_root); 1566 remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);
1567#endif /* CONFIG_PROC_FS */
1551} 1568}
1552 1569
1553static int 1570static int
@@ -1694,6 +1711,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
1694 new_intf->seq_table[j].seqid = 0; 1711 new_intf->seq_table[j].seqid = 0;
1695 } 1712 }
1696 new_intf->curr_seq = 0; 1713 new_intf->curr_seq = 0;
1714#ifdef CONFIG_PROC_FS
1715 spin_lock_init(&(new_intf->proc_entry_lock));
1716#endif
1697 spin_lock_init(&(new_intf->waiting_msgs_lock)); 1717 spin_lock_init(&(new_intf->waiting_msgs_lock));
1698 INIT_LIST_HEAD(&(new_intf->waiting_msgs)); 1718 INIT_LIST_HEAD(&(new_intf->waiting_msgs));
1699 spin_lock_init(&(new_intf->events_lock)); 1719 spin_lock_init(&(new_intf->events_lock));
@@ -2747,16 +2767,13 @@ static struct timer_list ipmi_timer;
2747 the queue and this silliness can go away. */ 2767 the queue and this silliness can go away. */
2748#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME)) 2768#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
2749 2769
2750static volatile int stop_operation = 0; 2770static atomic_t stop_operation;
2751static volatile int timer_stopped = 0;
2752static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME; 2771static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
2753 2772
2754static void ipmi_timeout(unsigned long data) 2773static void ipmi_timeout(unsigned long data)
2755{ 2774{
2756 if (stop_operation) { 2775 if (atomic_read(&stop_operation))
2757 timer_stopped = 1;
2758 return; 2776 return;
2759 }
2760 2777
2761 ticks_to_req_ev--; 2778 ticks_to_req_ev--;
2762 if (ticks_to_req_ev == 0) { 2779 if (ticks_to_req_ev == 0) {
@@ -2766,8 +2783,7 @@ static void ipmi_timeout(unsigned long data)
2766 2783
2767 ipmi_timeout_handler(IPMI_TIMEOUT_TIME); 2784 ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
2768 2785
2769 ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES; 2786 mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
2770 add_timer(&ipmi_timer);
2771} 2787}
2772 2788
2773 2789
@@ -3089,6 +3105,7 @@ static int ipmi_init_msghandler(void)
3089 ipmi_interfaces[i] = NULL; 3105 ipmi_interfaces[i] = NULL;
3090 } 3106 }
3091 3107
3108#ifdef CONFIG_PROC_FS
3092 proc_ipmi_root = proc_mkdir("ipmi", NULL); 3109 proc_ipmi_root = proc_mkdir("ipmi", NULL);
3093 if (!proc_ipmi_root) { 3110 if (!proc_ipmi_root) {
3094 printk(KERN_ERR PFX "Unable to create IPMI proc dir"); 3111 printk(KERN_ERR PFX "Unable to create IPMI proc dir");
@@ -3096,6 +3113,7 @@ static int ipmi_init_msghandler(void)
3096 } 3113 }
3097 3114
3098 proc_ipmi_root->owner = THIS_MODULE; 3115 proc_ipmi_root->owner = THIS_MODULE;
3116#endif /* CONFIG_PROC_FS */
3099 3117
3100 init_timer(&ipmi_timer); 3118 init_timer(&ipmi_timer);
3101 ipmi_timer.data = 0; 3119 ipmi_timer.data = 0;
@@ -3130,13 +3148,12 @@ static __exit void cleanup_ipmi(void)
3130 3148
3131 /* Tell the timer to stop, then wait for it to stop. This avoids 3149 /* Tell the timer to stop, then wait for it to stop. This avoids
3132 problems with race conditions removing the timer here. */ 3150 problems with race conditions removing the timer here. */
3133 stop_operation = 1; 3151 atomic_inc(&stop_operation);
3134 while (!timer_stopped) { 3152 del_timer_sync(&ipmi_timer);
3135 set_current_state(TASK_UNINTERRUPTIBLE);
3136 schedule_timeout(1);
3137 }
3138 3153
3154#ifdef CONFIG_PROC_FS
3139 remove_proc_entry(proc_ipmi_root->name, &proc_root); 3155 remove_proc_entry(proc_ipmi_root->name, &proc_root);
3156#endif /* CONFIG_PROC_FS */
3140 3157
3141 initialized = 0; 3158 initialized = 0;
3142 3159
@@ -3177,4 +3194,5 @@ EXPORT_SYMBOL(ipmi_get_my_address);
3177EXPORT_SYMBOL(ipmi_set_my_LUN); 3194EXPORT_SYMBOL(ipmi_set_my_LUN);
3178EXPORT_SYMBOL(ipmi_get_my_LUN); 3195EXPORT_SYMBOL(ipmi_get_my_LUN);
3179EXPORT_SYMBOL(ipmi_smi_add_proc_entry); 3196EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
3197EXPORT_SYMBOL(proc_ipmi_root);
3180EXPORT_SYMBOL(ipmi_user_set_run_to_completion); 3198EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index cb5cdc6f14..f951c30236 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -31,10 +31,13 @@
31 * with this program; if not, write to the Free Software Foundation, Inc., 31 * with this program; if not, write to the Free Software Foundation, Inc.,
32 * 675 Mass Ave, Cambridge, MA 02139, USA. 32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 */ 33 */
34#include <asm/semaphore.h> 34#include <linux/config.h>
35#include <linux/kdev_t.h>
36#include <linux/module.h> 35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/proc_fs.h>
37#include <linux/string.h> 38#include <linux/string.h>
39#include <linux/completion.h>
40#include <linux/kdev_t.h>
38#include <linux/ipmi.h> 41#include <linux/ipmi.h>
39#include <linux/ipmi_smi.h> 42#include <linux/ipmi_smi.h>
40 43
@@ -44,6 +47,18 @@
44/* Where to we insert our poweroff function? */ 47/* Where to we insert our poweroff function? */
45extern void (*pm_power_off)(void); 48extern void (*pm_power_off)(void);
46 49
50/* Definitions for controlling power off (if the system supports it). It
51 * conveniently matches the IPMI chassis control values. */
52#define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */
53#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */
54
55/* the IPMI data command */
56static int poweroff_control = IPMI_CHASSIS_POWER_DOWN;
57
58/* parameter definition to allow user to flag power cycle */
59module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN);
60MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
61
47/* Stuff from the get device id command. */ 62/* Stuff from the get device id command. */
48static unsigned int mfg_id; 63static unsigned int mfg_id;
49static unsigned int prod_id; 64static unsigned int prod_id;
@@ -75,10 +90,10 @@ static struct ipmi_recv_msg halt_recv_msg =
75 90
76static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data) 91static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
77{ 92{
78 struct semaphore *sem = recv_msg->user_msg_data; 93 struct completion *comp = recv_msg->user_msg_data;
79 94
80 if (sem) 95 if (comp)
81 up(sem); 96 complete(comp);
82} 97}
83 98
84static struct ipmi_user_hndl ipmi_poweroff_handler = 99static struct ipmi_user_hndl ipmi_poweroff_handler =
@@ -91,27 +106,27 @@ static int ipmi_request_wait_for_response(ipmi_user_t user,
91 struct ipmi_addr *addr, 106 struct ipmi_addr *addr,
92 struct kernel_ipmi_msg *send_msg) 107 struct kernel_ipmi_msg *send_msg)
93{ 108{
94 int rv; 109 int rv;
95 struct semaphore sem; 110 struct completion comp;
96 111
97 sema_init (&sem, 0); 112 init_completion(&comp);
98 113
99 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &sem, 114 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp,
100 &halt_smi_msg, &halt_recv_msg, 0); 115 &halt_smi_msg, &halt_recv_msg, 0);
101 if (rv) 116 if (rv)
102 return rv; 117 return rv;
103 118
104 down (&sem); 119 wait_for_completion(&comp);
105 120
106 return halt_recv_msg.msg.data[0]; 121 return halt_recv_msg.msg.data[0];
107} 122}
108 123
109/* We are in run-to-completion mode, no semaphore is desired. */ 124/* We are in run-to-completion mode, no completion is desired. */
110static int ipmi_request_in_rc_mode(ipmi_user_t user, 125static int ipmi_request_in_rc_mode(ipmi_user_t user,
111 struct ipmi_addr *addr, 126 struct ipmi_addr *addr,
112 struct kernel_ipmi_msg *send_msg) 127 struct kernel_ipmi_msg *send_msg)
113{ 128{
114 int rv; 129 int rv;
115 130
116 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL, 131 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
117 &halt_smi_msg, &halt_recv_msg, 0); 132 &halt_smi_msg, &halt_recv_msg, 0);
@@ -349,26 +364,38 @@ static void ipmi_poweroff_chassis (ipmi_user_t user)
349 smi_addr.channel = IPMI_BMC_CHANNEL; 364 smi_addr.channel = IPMI_BMC_CHANNEL;
350 smi_addr.lun = 0; 365 smi_addr.lun = 0;
351 366
352 printk(KERN_INFO PFX "Powering down via IPMI chassis control command\n"); 367 powercyclefailed:
368 printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
369 ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle"));
353 370
354 /* 371 /*
355 * Power down 372 * Power down
356 */ 373 */
357 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; 374 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
358 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; 375 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
359 data[0] = 0; /* Power down */ 376 data[0] = poweroff_control;
360 send_msg.data = data; 377 send_msg.data = data;
361 send_msg.data_len = sizeof(data); 378 send_msg.data_len = sizeof(data);
362 rv = ipmi_request_in_rc_mode(user, 379 rv = ipmi_request_in_rc_mode(user,
363 (struct ipmi_addr *) &smi_addr, 380 (struct ipmi_addr *) &smi_addr,
364 &send_msg); 381 &send_msg);
365 if (rv) { 382 if (rv) {
366 printk(KERN_ERR PFX "Unable to send chassis powerdown message," 383 switch (poweroff_control) {
367 " IPMI error 0x%x\n", rv); 384 case IPMI_CHASSIS_POWER_CYCLE:
368 goto out; 385 /* power cycle failed, default to power down */
386 printk(KERN_ERR PFX "Unable to send chassis power " \
387 "cycle message, IPMI error 0x%x\n", rv);
388 poweroff_control = IPMI_CHASSIS_POWER_DOWN;
389 goto powercyclefailed;
390
391 case IPMI_CHASSIS_POWER_DOWN:
392 default:
393 printk(KERN_ERR PFX "Unable to send chassis power " \
394 "down message, IPMI error 0x%x\n", rv);
395 break;
396 }
369 } 397 }
370 398
371 out:
372 return; 399 return;
373} 400}
374 401
@@ -430,7 +457,8 @@ static void ipmi_po_new_smi(int if_num)
430 if (ready) 457 if (ready)
431 return; 458 return;
432 459
433 rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user); 460 rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,
461 &ipmi_user);
434 if (rv) { 462 if (rv) {
435 printk(KERN_ERR PFX "could not create IPMI user, error %d\n", 463 printk(KERN_ERR PFX "could not create IPMI user, error %d\n",
436 rv); 464 rv);
@@ -509,21 +537,84 @@ static struct ipmi_smi_watcher smi_watcher =
509}; 537};
510 538
511 539
540#ifdef CONFIG_PROC_FS
541/* displays properties to proc */
542static int proc_read_chassctrl(char *page, char **start, off_t off, int count,
543 int *eof, void *data)
544{
545 return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n",
546 poweroff_control);
547}
548
549/* process property writes from proc */
550static int proc_write_chassctrl(struct file *file, const char *buffer,
551 unsigned long count, void *data)
552{
553 int rv = count;
554 unsigned int newval = 0;
555
556 sscanf(buffer, "%d", &newval);
557 switch (newval) {
558 case IPMI_CHASSIS_POWER_CYCLE:
559 printk(KERN_INFO PFX "power cycle is now enabled\n");
560 poweroff_control = newval;
561 break;
562
563 case IPMI_CHASSIS_POWER_DOWN:
564 poweroff_control = IPMI_CHASSIS_POWER_DOWN;
565 break;
566
567 default:
568 rv = -EINVAL;
569 break;
570 }
571
572 return rv;
573}
574#endif /* CONFIG_PROC_FS */
575
512/* 576/*
513 * Startup and shutdown functions. 577 * Startup and shutdown functions.
514 */ 578 */
515static int ipmi_poweroff_init (void) 579static int ipmi_poweroff_init (void)
516{ 580{
517 int rv; 581 int rv;
582 struct proc_dir_entry *file;
518 583
519 printk ("Copyright (C) 2004 MontaVista Software -" 584 printk ("Copyright (C) 2004 MontaVista Software -"
520 " IPMI Powerdown via sys_reboot version " 585 " IPMI Powerdown via sys_reboot version "
521 IPMI_POWEROFF_VERSION ".\n"); 586 IPMI_POWEROFF_VERSION ".\n");
522 587
588 switch (poweroff_control) {
589 case IPMI_CHASSIS_POWER_CYCLE:
590 printk(KERN_INFO PFX "Power cycle is enabled.\n");
591 break;
592
593 case IPMI_CHASSIS_POWER_DOWN:
594 default:
595 poweroff_control = IPMI_CHASSIS_POWER_DOWN;
596 break;
597 }
598
523 rv = ipmi_smi_watcher_register(&smi_watcher); 599 rv = ipmi_smi_watcher_register(&smi_watcher);
524 if (rv) 600 if (rv) {
525 printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); 601 printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
602 goto out_err;
603 }
604
605#ifdef CONFIG_PROC_FS
606 file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
607 if (!file) {
608 printk(KERN_ERR PFX "Unable to create proc power control\n");
609 } else {
610 file->nlink = 1;
611 file->read_proc = proc_read_chassctrl;
612 file->write_proc = proc_write_chassctrl;
613 file->owner = THIS_MODULE;
614 }
615#endif
526 616
617 out_err:
527 return rv; 618 return rv;
528} 619}
529 620
@@ -532,6 +623,10 @@ static __exit void ipmi_poweroff_cleanup(void)
532{ 623{
533 int rv; 624 int rv;
534 625
626#ifdef CONFIG_PROC_FS
627 remove_proc_entry("poweroff_control", proc_ipmi_root);
628#endif
629
535 ipmi_smi_watcher_unregister(&smi_watcher); 630 ipmi_smi_watcher_unregister(&smi_watcher);
536 631
537 if (ready) { 632 if (ready) {
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 8ce508b298..5c843c9bf8 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -19,7 +19,7 @@
19 * 19 *
20 * Note, the TPM chip is not interrupt driven (only polling) 20 * Note, the TPM chip is not interrupt driven (only polling)
21 * and can have very long timeouts (minutes!). Hence the unusual 21 * and can have very long timeouts (minutes!). Hence the unusual
22 * calls to schedule_timeout. 22 * calls to msleep.
23 * 23 *
24 */ 24 */
25 25
@@ -28,19 +28,16 @@
28#include <linux/spinlock.h> 28#include <linux/spinlock.h>
29#include "tpm.h" 29#include "tpm.h"
30 30
31#define TPM_MINOR 224 /* officially assigned */ 31enum tpm_const {
32 32 TPM_MINOR = 224, /* officially assigned */
33#define TPM_BUFSIZE 2048 33 TPM_BUFSIZE = 2048,
34 34 TPM_NUM_DEVICES = 256,
35/* PCI configuration addresses */ 35 TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
36#define PCI_GEN_PMCON_1 0xA0 36};
37#define PCI_GEN1_DEC 0xE4
38#define PCI_LPC_EN 0xE6
39#define PCI_GEN2_DEC 0xEC
40 37
41static LIST_HEAD(tpm_chip_list); 38static LIST_HEAD(tpm_chip_list);
42static DEFINE_SPINLOCK(driver_lock); 39static DEFINE_SPINLOCK(driver_lock);
43static int dev_mask[32]; 40static int dev_mask[TPM_NUM_MASK_ENTRIES];
44 41
45static void user_reader_timeout(unsigned long ptr) 42static void user_reader_timeout(unsigned long ptr)
46{ 43{
@@ -52,92 +49,17 @@ static void user_reader_timeout(unsigned long ptr)
52 up(&chip->buffer_mutex); 49 up(&chip->buffer_mutex);
53} 50}
54 51
55void tpm_time_expired(unsigned long ptr)
56{
57 int *exp = (int *) ptr;
58 *exp = 1;
59}
60
61EXPORT_SYMBOL_GPL(tpm_time_expired);
62
63/*
64 * Initialize the LPC bus and enable the TPM ports
65 */
66int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base)
67{
68 u32 lpcenable, tmp;
69 int is_lpcm = 0;
70
71 switch (pci_dev->vendor) {
72 case PCI_VENDOR_ID_INTEL:
73 switch (pci_dev->device) {
74 case PCI_DEVICE_ID_INTEL_82801CA_12:
75 case PCI_DEVICE_ID_INTEL_82801DB_12:
76 is_lpcm = 1;
77 break;
78 }
79 /* init ICH (enable LPC) */
80 pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable);
81 lpcenable |= 0x20000000;
82 pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable);
83
84 if (is_lpcm) {
85 pci_read_config_dword(pci_dev, PCI_GEN1_DEC,
86 &lpcenable);
87 if ((lpcenable & 0x20000000) == 0) {
88 dev_err(&pci_dev->dev,
89 "cannot enable LPC\n");
90 return -ENODEV;
91 }
92 }
93
94 /* initialize TPM registers */
95 pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp);
96
97 if (!is_lpcm)
98 tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0);
99 else
100 tmp =
101 (tmp & 0xFFFF0000) | (base & 0xFFF0) |
102 0x00000001;
103
104 pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp);
105
106 if (is_lpcm) {
107 pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1,
108 &tmp);
109 tmp |= 0x00000004; /* enable CLKRUN */
110 pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1,
111 tmp);
112 }
113 tpm_write_index(0x0D, 0x55); /* unlock 4F */
114 tpm_write_index(0x0A, 0x00); /* int disable */
115 tpm_write_index(0x08, base); /* base addr lo */
116 tpm_write_index(0x09, (base & 0xFF00) >> 8); /* base addr hi */
117 tpm_write_index(0x0D, 0xAA); /* lock 4F */
118 break;
119 case PCI_VENDOR_ID_AMD:
120 /* nothing yet */
121 break;
122 }
123
124 return 0;
125}
126
127EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
128
129/* 52/*
130 * Internal kernel interface to transmit TPM commands 53 * Internal kernel interface to transmit TPM commands
131 */ 54 */
132static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, 55static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
133 size_t bufsiz) 56 size_t bufsiz)
134{ 57{
135 ssize_t len; 58 ssize_t rc;
136 u32 count; 59 u32 count;
137 __be32 *native_size; 60 unsigned long stop;
138 61
139 native_size = (__force __be32 *) (buf + 2); 62 count = be32_to_cpu(*((__be32 *) (buf + 2)));
140 count = be32_to_cpu(*native_size);
141 63
142 if (count == 0) 64 if (count == 0)
143 return -ENODATA; 65 return -ENODATA;
@@ -149,53 +71,49 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
149 71
150 down(&chip->tpm_mutex); 72 down(&chip->tpm_mutex);
151 73
152 if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { 74 if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
153 dev_err(&chip->pci_dev->dev, 75 dev_err(&chip->pci_dev->dev,
154 "tpm_transmit: tpm_send: error %zd\n", len); 76 "tpm_transmit: tpm_send: error %zd\n", rc);
155 return len; 77 goto out;
156 } 78 }
157 79
158 down(&chip->timer_manipulation_mutex); 80 stop = jiffies + 2 * 60 * HZ;
159 chip->time_expired = 0;
160 init_timer(&chip->device_timer);
161 chip->device_timer.function = tpm_time_expired;
162 chip->device_timer.expires = jiffies + 2 * 60 * HZ;
163 chip->device_timer.data = (unsigned long) &chip->time_expired;
164 add_timer(&chip->device_timer);
165 up(&chip->timer_manipulation_mutex);
166
167 do { 81 do {
168 u8 status = inb(chip->vendor->base + 1); 82 u8 status = inb(chip->vendor->base + 1);
169 if ((status & chip->vendor->req_complete_mask) == 83 if ((status & chip->vendor->req_complete_mask) ==
170 chip->vendor->req_complete_val) { 84 chip->vendor->req_complete_val) {
171 down(&chip->timer_manipulation_mutex);
172 del_singleshot_timer_sync(&chip->device_timer);
173 up(&chip->timer_manipulation_mutex);
174 goto out_recv; 85 goto out_recv;
175 } 86 }
176 set_current_state(TASK_UNINTERRUPTIBLE); 87
177 schedule_timeout(TPM_TIMEOUT); 88 if ((status == chip->vendor->req_canceled)) {
89 dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
90 rc = -ECANCELED;
91 goto out;
92 }
93
94 msleep(TPM_TIMEOUT); /* CHECK */
178 rmb(); 95 rmb();
179 } while (!chip->time_expired); 96 } while (time_before(jiffies, stop));
180 97
181 98
182 chip->vendor->cancel(chip); 99 chip->vendor->cancel(chip);
183 dev_err(&chip->pci_dev->dev, "Time expired\n"); 100 dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
184 up(&chip->tpm_mutex); 101 rc = -ETIME;
185 return -EIO; 102 goto out;
186 103
187out_recv: 104out_recv:
188 len = chip->vendor->recv(chip, (u8 *) buf, bufsiz); 105 rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
189 if (len < 0) 106 if (rc < 0)
190 dev_err(&chip->pci_dev->dev, 107 dev_err(&chip->pci_dev->dev,
191 "tpm_transmit: tpm_recv: error %zd\n", len); 108 "tpm_transmit: tpm_recv: error %zd\n", rc);
109out:
192 up(&chip->tpm_mutex); 110 up(&chip->tpm_mutex);
193 return len; 111 return rc;
194} 112}
195 113
196#define TPM_DIGEST_SIZE 20 114#define TPM_DIGEST_SIZE 20
197#define CAP_PCR_RESULT_SIZE 18 115#define CAP_PCR_RESULT_SIZE 18
198static u8 cap_pcr[] = { 116static const u8 cap_pcr[] = {
199 0, 193, /* TPM_TAG_RQU_COMMAND */ 117 0, 193, /* TPM_TAG_RQU_COMMAND */
200 0, 0, 0, 22, /* length */ 118 0, 0, 0, 22, /* length */
201 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 119 0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -205,75 +123,94 @@ static u8 cap_pcr[] = {
205}; 123};
206 124
207#define READ_PCR_RESULT_SIZE 30 125#define READ_PCR_RESULT_SIZE 30
208static u8 pcrread[] = { 126static const u8 pcrread[] = {
209 0, 193, /* TPM_TAG_RQU_COMMAND */ 127 0, 193, /* TPM_TAG_RQU_COMMAND */
210 0, 0, 0, 14, /* length */ 128 0, 0, 0, 14, /* length */
211 0, 0, 0, 21, /* TPM_ORD_PcrRead */ 129 0, 0, 0, 21, /* TPM_ORD_PcrRead */
212 0, 0, 0, 0 /* PCR index */ 130 0, 0, 0, 0 /* PCR index */
213}; 131};
214 132
215static ssize_t show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) 133ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
134 char *buf)
216{ 135{
217 u8 data[READ_PCR_RESULT_SIZE]; 136 u8 data[READ_PCR_RESULT_SIZE];
218 ssize_t len; 137 ssize_t len;
219 int i, j, index, num_pcrs; 138 int i, j, num_pcrs;
139 __be32 index;
220 char *str = buf; 140 char *str = buf;
221 141
222 struct tpm_chip *chip = 142 struct tpm_chip *chip =
223 pci_get_drvdata(container_of(dev, struct pci_dev, dev)); 143 pci_get_drvdata(to_pci_dev(dev));
224 if (chip == NULL) 144 if (chip == NULL)
225 return -ENODEV; 145 return -ENODEV;
226 146
227 memcpy(data, cap_pcr, sizeof(cap_pcr)); 147 memcpy(data, cap_pcr, sizeof(cap_pcr));
228 if ((len = tpm_transmit(chip, data, sizeof(data))) 148 if ((len = tpm_transmit(chip, data, sizeof(data)))
229 < CAP_PCR_RESULT_SIZE) 149 < CAP_PCR_RESULT_SIZE) {
230 return len; 150 dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
151 "attempting to determine the number of PCRS\n",
152 be32_to_cpu(*((__be32 *) (data + 6))));
153 return 0;
154 }
231 155
232 num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14))); 156 num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
233 157
234 for (i = 0; i < num_pcrs; i++) { 158 for (i = 0; i < num_pcrs; i++) {
235 memcpy(data, pcrread, sizeof(pcrread)); 159 memcpy(data, pcrread, sizeof(pcrread));
236 index = cpu_to_be32(i); 160 index = cpu_to_be32(i);
237 memcpy(data + 10, &index, 4); 161 memcpy(data + 10, &index, 4);
238 if ((len = tpm_transmit(chip, data, sizeof(data))) 162 if ((len = tpm_transmit(chip, data, sizeof(data)))
239 < READ_PCR_RESULT_SIZE) 163 < READ_PCR_RESULT_SIZE){
240 return len; 164 dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred"
165 " attempting to read PCR %d of %d\n",
166 be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
167 goto out;
168 }
241 str += sprintf(str, "PCR-%02d: ", i); 169 str += sprintf(str, "PCR-%02d: ", i);
242 for (j = 0; j < TPM_DIGEST_SIZE; j++) 170 for (j = 0; j < TPM_DIGEST_SIZE; j++)
243 str += sprintf(str, "%02X ", *(data + 10 + j)); 171 str += sprintf(str, "%02X ", *(data + 10 + j));
244 str += sprintf(str, "\n"); 172 str += sprintf(str, "\n");
245 } 173 }
174out:
246 return str - buf; 175 return str - buf;
247} 176}
248 177EXPORT_SYMBOL_GPL(tpm_show_pcrs);
249static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
250 178
251#define READ_PUBEK_RESULT_SIZE 314 179#define READ_PUBEK_RESULT_SIZE 314
252static u8 readpubek[] = { 180static const u8 readpubek[] = {
253 0, 193, /* TPM_TAG_RQU_COMMAND */ 181 0, 193, /* TPM_TAG_RQU_COMMAND */
254 0, 0, 0, 30, /* length */ 182 0, 0, 0, 30, /* length */
255 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ 183 0, 0, 0, 124, /* TPM_ORD_ReadPubek */
256}; 184};
257 185
258static ssize_t show_pubek(struct device *dev, struct device_attribute *attr, char *buf) 186ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
187 char *buf)
259{ 188{
260 u8 data[READ_PUBEK_RESULT_SIZE]; 189 u8 *data;
261 ssize_t len; 190 ssize_t len;
262 __be32 *native_val; 191 int i, rc;
263 int i;
264 char *str = buf; 192 char *str = buf;
265 193
266 struct tpm_chip *chip = 194 struct tpm_chip *chip =
267 pci_get_drvdata(container_of(dev, struct pci_dev, dev)); 195 pci_get_drvdata(to_pci_dev(dev));
268 if (chip == NULL) 196 if (chip == NULL)
269 return -ENODEV; 197 return -ENODEV;
270 198
199 data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
200 if (!data)
201 return -ENOMEM;
202
271 memcpy(data, readpubek, sizeof(readpubek)); 203 memcpy(data, readpubek, sizeof(readpubek));
272 memset(data + sizeof(readpubek), 0, 20); /* zero nonce */ 204 memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
273 205
274 if ((len = tpm_transmit(chip, data, sizeof(data))) < 206 if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
275 READ_PUBEK_RESULT_SIZE) 207 READ_PUBEK_RESULT_SIZE) {
276 return len; 208 dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
209 "attempting to read the PUBEK\n",
210 be32_to_cpu(*((__be32 *) (data + 6))));
211 rc = 0;
212 goto out;
213 }
277 214
278 /* 215 /*
279 ignore header 10 bytes 216 ignore header 10 bytes
@@ -286,8 +223,6 @@ static ssize_t show_pubek(struct device *dev, struct device_attribute *attr, cha
286 ignore checksum 20 bytes 223 ignore checksum 20 bytes
287 */ 224 */
288 225
289 native_val = (__force __be32 *) (data + 34);
290
291 str += 226 str +=
292 sprintf(str, 227 sprintf(str,
293 "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" 228 "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
@@ -298,21 +233,23 @@ static ssize_t show_pubek(struct device *dev, struct device_attribute *attr, cha
298 data[15], data[16], data[17], data[22], data[23], 233 data[15], data[16], data[17], data[22], data[23],
299 data[24], data[25], data[26], data[27], data[28], 234 data[24], data[25], data[26], data[27], data[28],
300 data[29], data[30], data[31], data[32], data[33], 235 data[29], data[30], data[31], data[32], data[33],
301 be32_to_cpu(*native_val) 236 be32_to_cpu(*((__be32 *) (data + 32))));
302 );
303 237
304 for (i = 0; i < 256; i++) { 238 for (i = 0; i < 256; i++) {
305 str += sprintf(str, "%02X ", data[i + 39]); 239 str += sprintf(str, "%02X ", data[i + 39]);
306 if ((i + 1) % 16 == 0) 240 if ((i + 1) % 16 == 0)
307 str += sprintf(str, "\n"); 241 str += sprintf(str, "\n");
308 } 242 }
309 return str - buf; 243 rc = str - buf;
244out:
245 kfree(data);
246 return rc;
310} 247}
311 248
312static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL); 249EXPORT_SYMBOL_GPL(tpm_show_pubek);
313 250
314#define CAP_VER_RESULT_SIZE 18 251#define CAP_VER_RESULT_SIZE 18
315static u8 cap_version[] = { 252static const u8 cap_version[] = {
316 0, 193, /* TPM_TAG_RQU_COMMAND */ 253 0, 193, /* TPM_TAG_RQU_COMMAND */
317 0, 0, 0, 18, /* length */ 254 0, 0, 0, 18, /* length */
318 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 255 0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -321,7 +258,7 @@ static u8 cap_version[] = {
321}; 258};
322 259
323#define CAP_MANUFACTURER_RESULT_SIZE 18 260#define CAP_MANUFACTURER_RESULT_SIZE 18
324static u8 cap_manufacturer[] = { 261static const u8 cap_manufacturer[] = {
325 0, 193, /* TPM_TAG_RQU_COMMAND */ 262 0, 193, /* TPM_TAG_RQU_COMMAND */
326 0, 0, 0, 22, /* length */ 263 0, 0, 0, 22, /* length */
327 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 264 0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -330,14 +267,15 @@ static u8 cap_manufacturer[] = {
330 0, 0, 1, 3 267 0, 0, 1, 3
331}; 268};
332 269
333static ssize_t show_caps(struct device *dev, struct device_attribute *attr, char *buf) 270ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
271 char *buf)
334{ 272{
335 u8 data[READ_PUBEK_RESULT_SIZE]; 273 u8 data[sizeof(cap_manufacturer)];
336 ssize_t len; 274 ssize_t len;
337 char *str = buf; 275 char *str = buf;
338 276
339 struct tpm_chip *chip = 277 struct tpm_chip *chip =
340 pci_get_drvdata(container_of(dev, struct pci_dev, dev)); 278 pci_get_drvdata(to_pci_dev(dev));
341 if (chip == NULL) 279 if (chip == NULL)
342 return -ENODEV; 280 return -ENODEV;
343 281
@@ -348,7 +286,7 @@ static ssize_t show_caps(struct device *dev, struct device_attribute *attr, char
348 return len; 286 return len;
349 287
350 str += sprintf(str, "Manufacturer: 0x%x\n", 288 str += sprintf(str, "Manufacturer: 0x%x\n",
351 be32_to_cpu(*(data + 14))); 289 be32_to_cpu(*((__be32 *) (data + 14))));
352 290
353 memcpy(data, cap_version, sizeof(cap_version)); 291 memcpy(data, cap_version, sizeof(cap_version));
354 292
@@ -363,8 +301,20 @@ static ssize_t show_caps(struct device *dev, struct device_attribute *attr, char
363 301
364 return str - buf; 302 return str - buf;
365} 303}
304EXPORT_SYMBOL_GPL(tpm_show_caps);
305
306ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
307 const char *buf, size_t count)
308{
309 struct tpm_chip *chip = dev_get_drvdata(dev);
310 if (chip == NULL)
311 return 0;
312
313 chip->vendor->cancel(chip);
314 return count;
315}
316EXPORT_SYMBOL_GPL(tpm_store_cancel);
366 317
367static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
368 318
369/* 319/*
370 * Device file system interface to the TPM 320 * Device file system interface to the TPM
@@ -422,24 +372,15 @@ EXPORT_SYMBOL_GPL(tpm_open);
422int tpm_release(struct inode *inode, struct file *file) 372int tpm_release(struct inode *inode, struct file *file)
423{ 373{
424 struct tpm_chip *chip = file->private_data; 374 struct tpm_chip *chip = file->private_data;
425
426 file->private_data = NULL;
427 375
428 spin_lock(&driver_lock); 376 spin_lock(&driver_lock);
377 file->private_data = NULL;
429 chip->num_opens--; 378 chip->num_opens--;
430 spin_unlock(&driver_lock); 379 del_singleshot_timer_sync(&chip->user_read_timer);
431
432 down(&chip->timer_manipulation_mutex);
433 if (timer_pending(&chip->user_read_timer))
434 del_singleshot_timer_sync(&chip->user_read_timer);
435 else if (timer_pending(&chip->device_timer))
436 del_singleshot_timer_sync(&chip->device_timer);
437 up(&chip->timer_manipulation_mutex);
438
439 kfree(chip->data_buffer);
440 atomic_set(&chip->data_pending, 0); 380 atomic_set(&chip->data_pending, 0);
441
442 pci_dev_put(chip->pci_dev); 381 pci_dev_put(chip->pci_dev);
382 kfree(chip->data_buffer);
383 spin_unlock(&driver_lock);
443 return 0; 384 return 0;
444} 385}
445 386
@@ -453,10 +394,8 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
453 394
454 /* cannot perform a write until the read has cleared 395 /* cannot perform a write until the read has cleared
455 either via tpm_read or a user_read_timer timeout */ 396 either via tpm_read or a user_read_timer timeout */
456 while (atomic_read(&chip->data_pending) != 0) { 397 while (atomic_read(&chip->data_pending) != 0)
457 set_current_state(TASK_UNINTERRUPTIBLE); 398 msleep(TPM_TIMEOUT);
458 schedule_timeout(TPM_TIMEOUT);
459 }
460 399
461 down(&chip->buffer_mutex); 400 down(&chip->buffer_mutex);
462 401
@@ -476,13 +415,7 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
476 up(&chip->buffer_mutex); 415 up(&chip->buffer_mutex);
477 416
478 /* Set a timeout by which the reader must come claim the result */ 417 /* Set a timeout by which the reader must come claim the result */
479 down(&chip->timer_manipulation_mutex); 418 mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
480 init_timer(&chip->user_read_timer);
481 chip->user_read_timer.function = user_reader_timeout;
482 chip->user_read_timer.data = (unsigned long) chip;
483 chip->user_read_timer.expires = jiffies + (60 * HZ);
484 add_timer(&chip->user_read_timer);
485 up(&chip->timer_manipulation_mutex);
486 419
487 return in_size; 420 return in_size;
488} 421}
@@ -493,29 +426,19 @@ ssize_t tpm_read(struct file * file, char __user * buf,
493 size_t size, loff_t * off) 426 size_t size, loff_t * off)
494{ 427{
495 struct tpm_chip *chip = file->private_data; 428 struct tpm_chip *chip = file->private_data;
496 int ret_size = -ENODATA; 429 int ret_size;
497 430
498 if (atomic_read(&chip->data_pending) != 0) { /* Result available */ 431 del_singleshot_timer_sync(&chip->user_read_timer);
499 down(&chip->timer_manipulation_mutex); 432 ret_size = atomic_read(&chip->data_pending);
500 del_singleshot_timer_sync(&chip->user_read_timer); 433 atomic_set(&chip->data_pending, 0);
501 up(&chip->timer_manipulation_mutex); 434 if (ret_size > 0) { /* relay data */
435 if (size < ret_size)
436 ret_size = size;
502 437
503 down(&chip->buffer_mutex); 438 down(&chip->buffer_mutex);
504 439 if (copy_to_user
505 ret_size = atomic_read(&chip->data_pending); 440 ((void __user *) buf, chip->data_buffer, ret_size))
506 atomic_set(&chip->data_pending, 0); 441 ret_size = -EFAULT;
507
508 if (ret_size == 0) /* timeout just occurred */
509 ret_size = -ETIME;
510 else if (ret_size > 0) { /* relay data */
511 if (size < ret_size)
512 ret_size = size;
513
514 if (copy_to_user((void __user *) buf,
515 chip->data_buffer, ret_size)) {
516 ret_size = -EFAULT;
517 }
518 }
519 up(&chip->buffer_mutex); 442 up(&chip->buffer_mutex);
520 } 443 }
521 444
@@ -542,13 +465,11 @@ void __devexit tpm_remove(struct pci_dev *pci_dev)
542 pci_set_drvdata(pci_dev, NULL); 465 pci_set_drvdata(pci_dev, NULL);
543 misc_deregister(&chip->vendor->miscdev); 466 misc_deregister(&chip->vendor->miscdev);
544 467
545 device_remove_file(&pci_dev->dev, &dev_attr_pubek); 468 sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
546 device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
547 device_remove_file(&pci_dev->dev, &dev_attr_caps);
548 469
549 pci_disable_device(pci_dev); 470 pci_disable_device(pci_dev);
550 471
551 dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32)); 472 dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
552 473
553 kfree(chip); 474 kfree(chip);
554 475
@@ -590,10 +511,6 @@ int tpm_pm_resume(struct pci_dev *pci_dev)
590 if (chip == NULL) 511 if (chip == NULL)
591 return -ENODEV; 512 return -ENODEV;
592 513
593 spin_lock(&driver_lock);
594 tpm_lpc_bus_init(pci_dev, chip->vendor->base);
595 spin_unlock(&driver_lock);
596
597 return 0; 514 return 0;
598} 515}
599 516
@@ -622,17 +539,21 @@ int tpm_register_hardware(struct pci_dev *pci_dev,
622 539
623 init_MUTEX(&chip->buffer_mutex); 540 init_MUTEX(&chip->buffer_mutex);
624 init_MUTEX(&chip->tpm_mutex); 541 init_MUTEX(&chip->tpm_mutex);
625 init_MUTEX(&chip->timer_manipulation_mutex);
626 INIT_LIST_HEAD(&chip->list); 542 INIT_LIST_HEAD(&chip->list);
627 543
544 init_timer(&chip->user_read_timer);
545 chip->user_read_timer.function = user_reader_timeout;
546 chip->user_read_timer.data = (unsigned long) chip;
547
628 chip->vendor = entry; 548 chip->vendor = entry;
629 549
630 chip->dev_num = -1; 550 chip->dev_num = -1;
631 551
632 for (i = 0; i < 32; i++) 552 for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
633 for (j = 0; j < 8; j++) 553 for (j = 0; j < 8 * sizeof(int); j++)
634 if ((dev_mask[i] & (1 << j)) == 0) { 554 if ((dev_mask[i] & (1 << j)) == 0) {
635 chip->dev_num = i * 32 + j; 555 chip->dev_num =
556 i * TPM_NUM_MASK_ENTRIES + j;
636 dev_mask[i] |= 1 << j; 557 dev_mask[i] |= 1 << j;
637 goto dev_num_search_complete; 558 goto dev_num_search_complete;
638 } 559 }
@@ -665,31 +586,20 @@ dev_num_search_complete:
665 return -ENODEV; 586 return -ENODEV;
666 } 587 }
667 588
589 spin_lock(&driver_lock);
590
668 pci_set_drvdata(pci_dev, chip); 591 pci_set_drvdata(pci_dev, chip);
669 592
670 list_add(&chip->list, &tpm_chip_list); 593 list_add(&chip->list, &tpm_chip_list);
671 594
672 device_create_file(&pci_dev->dev, &dev_attr_pubek); 595 spin_unlock(&driver_lock);
673 device_create_file(&pci_dev->dev, &dev_attr_pcrs);
674 device_create_file(&pci_dev->dev, &dev_attr_caps);
675
676 return 0;
677}
678 596
679EXPORT_SYMBOL_GPL(tpm_register_hardware); 597 sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
680 598
681static int __init init_tpm(void)
682{
683 return 0; 599 return 0;
684} 600}
685 601
686static void __exit cleanup_tpm(void) 602EXPORT_SYMBOL_GPL(tpm_register_hardware);
687{
688
689}
690
691module_init(init_tpm);
692module_exit(cleanup_tpm);
693 603
694MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); 604MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
695MODULE_DESCRIPTION("TPM Driver"); 605MODULE_DESCRIPTION("TPM Driver");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index de0c796fce..10cb450191 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -25,23 +25,38 @@
25#include <linux/fs.h> 25#include <linux/fs.h>
26#include <linux/miscdevice.h> 26#include <linux/miscdevice.h>
27 27
28#define TPM_TIMEOUT msecs_to_jiffies(5) 28enum tpm_timeout {
29 TPM_TIMEOUT = 5, /* msecs */
30};
29 31
30/* TPM addresses */ 32/* TPM addresses */
31#define TPM_ADDR 0x4E 33enum tpm_addr {
32#define TPM_DATA 0x4F 34 TPM_ADDR = 0x4E,
35 TPM_DATA = 0x4F
36};
37
38extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
39 char *);
40extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
41 char *);
42extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
43 char *);
44extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
45 const char *, size_t);
33 46
34struct tpm_chip; 47struct tpm_chip;
35 48
36struct tpm_vendor_specific { 49struct tpm_vendor_specific {
37 u8 req_complete_mask; 50 u8 req_complete_mask;
38 u8 req_complete_val; 51 u8 req_complete_val;
52 u8 req_canceled;
39 u16 base; /* TPM base address */ 53 u16 base; /* TPM base address */
40 54
41 int (*recv) (struct tpm_chip *, u8 *, size_t); 55 int (*recv) (struct tpm_chip *, u8 *, size_t);
42 int (*send) (struct tpm_chip *, u8 *, size_t); 56 int (*send) (struct tpm_chip *, u8 *, size_t);
43 void (*cancel) (struct tpm_chip *); 57 void (*cancel) (struct tpm_chip *);
44 struct miscdevice miscdev; 58 struct miscdevice miscdev;
59 struct attribute_group *attr_group;
45}; 60};
46 61
47struct tpm_chip { 62struct tpm_chip {
@@ -58,8 +73,6 @@ struct tpm_chip {
58 73
59 struct timer_list user_read_timer; /* user needs to claim result */ 74 struct timer_list user_read_timer; /* user needs to claim result */
60 struct semaphore tpm_mutex; /* tpm is processing */ 75 struct semaphore tpm_mutex; /* tpm is processing */
61 struct timer_list device_timer; /* tpm is processing */
62 struct semaphore timer_manipulation_mutex;
63 76
64 struct tpm_vendor_specific *vendor; 77 struct tpm_vendor_specific *vendor;
65 78
@@ -78,9 +91,6 @@ static inline void tpm_write_index(int index, int value)
78 outb(value & 0xFF, TPM_DATA); 91 outb(value & 0xFF, TPM_DATA);
79} 92}
80 93
81extern void tpm_time_expired(unsigned long);
82extern int tpm_lpc_bus_init(struct pci_dev *, u16);
83
84extern int tpm_register_hardware(struct pci_dev *, 94extern int tpm_register_hardware(struct pci_dev *,
85 struct tpm_vendor_specific *); 95 struct tpm_vendor_specific *);
86extern int tpm_open(struct inode *, struct file *); 96extern int tpm_open(struct inode *, struct file *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index f9333e729b..61fe14a771 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -22,17 +22,23 @@
22#include "tpm.h" 22#include "tpm.h"
23 23
24/* Atmel definitions */ 24/* Atmel definitions */
25#define TPM_ATML_BASE 0x400 25enum tpm_atmel_addr {
26 TPM_ATMEL_BASE_ADDR_LO = 0x08,
27 TPM_ATMEL_BASE_ADDR_HI = 0x09
28};
26 29
27/* write status bits */ 30/* write status bits */
28#define ATML_STATUS_ABORT 0x01 31enum tpm_atmel_write_status {
29#define ATML_STATUS_LASTBYTE 0x04 32 ATML_STATUS_ABORT = 0x01,
30 33 ATML_STATUS_LASTBYTE = 0x04
34};
31/* read status bits */ 35/* read status bits */
32#define ATML_STATUS_BUSY 0x01 36enum tpm_atmel_read_status {
33#define ATML_STATUS_DATA_AVAIL 0x02 37 ATML_STATUS_BUSY = 0x01,
34#define ATML_STATUS_REWRITE 0x04 38 ATML_STATUS_DATA_AVAIL = 0x02,
35 39 ATML_STATUS_REWRITE = 0x04,
40 ATML_STATUS_READY = 0x08
41};
36 42
37static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) 43static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
38{ 44{
@@ -121,13 +127,29 @@ static struct file_operations atmel_ops = {
121 .release = tpm_release, 127 .release = tpm_release,
122}; 128};
123 129
130static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
131static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
132static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
133static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
134
135static struct attribute* atmel_attrs[] = {
136 &dev_attr_pubek.attr,
137 &dev_attr_pcrs.attr,
138 &dev_attr_caps.attr,
139 &dev_attr_cancel.attr,
140 0,
141};
142
143static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
144
124static struct tpm_vendor_specific tpm_atmel = { 145static struct tpm_vendor_specific tpm_atmel = {
125 .recv = tpm_atml_recv, 146 .recv = tpm_atml_recv,
126 .send = tpm_atml_send, 147 .send = tpm_atml_send,
127 .cancel = tpm_atml_cancel, 148 .cancel = tpm_atml_cancel,
128 .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, 149 .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
129 .req_complete_val = ATML_STATUS_DATA_AVAIL, 150 .req_complete_val = ATML_STATUS_DATA_AVAIL,
130 .base = TPM_ATML_BASE, 151 .req_canceled = ATML_STATUS_READY,
152 .attr_group = &atmel_attr_grp,
131 .miscdev = { .fops = &atmel_ops, }, 153 .miscdev = { .fops = &atmel_ops, },
132}; 154};
133 155
@@ -136,14 +158,16 @@ static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
136{ 158{
137 u8 version[4]; 159 u8 version[4];
138 int rc = 0; 160 int rc = 0;
161 int lo, hi;
139 162
140 if (pci_enable_device(pci_dev)) 163 if (pci_enable_device(pci_dev))
141 return -EIO; 164 return -EIO;
142 165
143 if (tpm_lpc_bus_init(pci_dev, TPM_ATML_BASE)) { 166 lo = tpm_read_index( TPM_ATMEL_BASE_ADDR_LO );
144 rc = -ENODEV; 167 hi = tpm_read_index( TPM_ATMEL_BASE_ADDR_HI );
145 goto out_err; 168
146 } 169 tpm_atmel.base = (hi<<8)|lo;
170 dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
147 171
148 /* verify that it is an Atmel part */ 172 /* verify that it is an Atmel part */
149 if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T' 173 if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
@@ -183,6 +207,7 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
183 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, 207 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
184 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, 208 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
185 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, 209 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
210 {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
186 {0,} 211 {0,}
187}; 212};
188 213
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 9cce833a09..1a45e7dfc1 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -22,43 +22,52 @@
22#include "tpm.h" 22#include "tpm.h"
23 23
24/* National definitions */ 24/* National definitions */
25#define TPM_NSC_BASE 0x360 25enum tpm_nsc_addr{
26#define TPM_NSC_IRQ 0x07 26 TPM_NSC_BASE = 0x360,
27 TPM_NSC_IRQ = 0x07,
28 TPM_NSC_BASE0_HI = 0x60,
29 TPM_NSC_BASE0_LO = 0x61,
30 TPM_NSC_BASE1_HI = 0x62,
31 TPM_NSC_BASE1_LO = 0x63
32};
27 33
28#define NSC_LDN_INDEX 0x07 34enum tpm_nsc_index {
29#define NSC_SID_INDEX 0x20 35 NSC_LDN_INDEX = 0x07,
30#define NSC_LDC_INDEX 0x30 36 NSC_SID_INDEX = 0x20,
31#define NSC_DIO_INDEX 0x60 37 NSC_LDC_INDEX = 0x30,
32#define NSC_CIO_INDEX 0x62 38 NSC_DIO_INDEX = 0x60,
33#define NSC_IRQ_INDEX 0x70 39 NSC_CIO_INDEX = 0x62,
34#define NSC_ITS_INDEX 0x71 40 NSC_IRQ_INDEX = 0x70,
41 NSC_ITS_INDEX = 0x71
42};
35 43
36#define NSC_STATUS 0x01 44enum tpm_nsc_status_loc {
37#define NSC_COMMAND 0x01 45 NSC_STATUS = 0x01,
38#define NSC_DATA 0x00 46 NSC_COMMAND = 0x01,
47 NSC_DATA = 0x00
48};
39 49
40/* status bits */ 50/* status bits */
41#define NSC_STATUS_OBF 0x01 /* output buffer full */ 51enum tpm_nsc_status {
42#define NSC_STATUS_IBF 0x02 /* input buffer full */ 52 NSC_STATUS_OBF = 0x01, /* output buffer full */
43#define NSC_STATUS_F0 0x04 /* F0 */ 53 NSC_STATUS_IBF = 0x02, /* input buffer full */
44#define NSC_STATUS_A2 0x08 /* A2 */ 54 NSC_STATUS_F0 = 0x04, /* F0 */
45#define NSC_STATUS_RDY 0x10 /* ready to receive command */ 55 NSC_STATUS_A2 = 0x08, /* A2 */
46#define NSC_STATUS_IBR 0x20 /* ready to receive data */ 56 NSC_STATUS_RDY = 0x10, /* ready to receive command */
47 57 NSC_STATUS_IBR = 0x20 /* ready to receive data */
58};
48/* command bits */ 59/* command bits */
49#define NSC_COMMAND_NORMAL 0x01 /* normal mode */ 60enum tpm_nsc_cmd_mode {
50#define NSC_COMMAND_EOC 0x03 61 NSC_COMMAND_NORMAL = 0x01, /* normal mode */
51#define NSC_COMMAND_CANCEL 0x22 62 NSC_COMMAND_EOC = 0x03,
52 63 NSC_COMMAND_CANCEL = 0x22
64};
53/* 65/*
54 * Wait for a certain status to appear 66 * Wait for a certain status to appear
55 */ 67 */
56static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) 68static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
57{ 69{
58 int expired = 0; 70 unsigned long stop;
59 struct timer_list status_timer =
60 TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
61 (unsigned long) &expired);
62 71
63 /* status immediately available check */ 72 /* status immediately available check */
64 *data = inb(chip->vendor->base + NSC_STATUS); 73 *data = inb(chip->vendor->base + NSC_STATUS);
@@ -66,17 +75,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
66 return 0; 75 return 0;
67 76
68 /* wait for status */ 77 /* wait for status */
69 add_timer(&status_timer); 78 stop = jiffies + 10 * HZ;
70 do { 79 do {
71 set_current_state(TASK_UNINTERRUPTIBLE); 80 msleep(TPM_TIMEOUT);
72 schedule_timeout(TPM_TIMEOUT);
73 *data = inb(chip->vendor->base + 1); 81 *data = inb(chip->vendor->base + 1);
74 if ((*data & mask) == val) { 82 if ((*data & mask) == val)
75 del_singleshot_timer_sync(&status_timer);
76 return 0; 83 return 0;
77 }
78 } 84 }
79 while (!expired); 85 while (time_before(jiffies, stop));
80 86
81 return -EBUSY; 87 return -EBUSY;
82} 88}
@@ -84,10 +90,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
84static int nsc_wait_for_ready(struct tpm_chip *chip) 90static int nsc_wait_for_ready(struct tpm_chip *chip)
85{ 91{
86 int status; 92 int status;
87 int expired = 0; 93 unsigned long stop;
88 struct timer_list status_timer =
89 TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
90 (unsigned long) &expired);
91 94
92 /* status immediately available check */ 95 /* status immediately available check */
93 status = inb(chip->vendor->base + NSC_STATUS); 96 status = inb(chip->vendor->base + NSC_STATUS);
@@ -97,19 +100,16 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
97 return 0; 100 return 0;
98 101
99 /* wait for status */ 102 /* wait for status */
100 add_timer(&status_timer); 103 stop = jiffies + 100;
101 do { 104 do {
102 set_current_state(TASK_UNINTERRUPTIBLE); 105 msleep(TPM_TIMEOUT);
103 schedule_timeout(TPM_TIMEOUT);
104 status = inb(chip->vendor->base + NSC_STATUS); 106 status = inb(chip->vendor->base + NSC_STATUS);
105 if (status & NSC_STATUS_OBF) 107 if (status & NSC_STATUS_OBF)
106 status = inb(chip->vendor->base + NSC_DATA); 108 status = inb(chip->vendor->base + NSC_DATA);
107 if (status & NSC_STATUS_RDY) { 109 if (status & NSC_STATUS_RDY)
108 del_singleshot_timer_sync(&status_timer);
109 return 0; 110 return 0;
110 }
111 } 111 }
112 while (!expired); 112 while (time_before(jiffies, stop));
113 113
114 dev_info(&chip->pci_dev->dev, "wait for ready failed\n"); 114 dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
115 return -EBUSY; 115 return -EBUSY;
@@ -228,30 +228,46 @@ static struct file_operations nsc_ops = {
228 .release = tpm_release, 228 .release = tpm_release,
229}; 229};
230 230
231static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
232static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
233static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
234static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel);
235
236static struct attribute * nsc_attrs[] = {
237 &dev_attr_pubek.attr,
238 &dev_attr_pcrs.attr,
239 &dev_attr_caps.attr,
240 &dev_attr_cancel.attr,
241 0,
242};
243
244static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
245
231static struct tpm_vendor_specific tpm_nsc = { 246static struct tpm_vendor_specific tpm_nsc = {
232 .recv = tpm_nsc_recv, 247 .recv = tpm_nsc_recv,
233 .send = tpm_nsc_send, 248 .send = tpm_nsc_send,
234 .cancel = tpm_nsc_cancel, 249 .cancel = tpm_nsc_cancel,
235 .req_complete_mask = NSC_STATUS_OBF, 250 .req_complete_mask = NSC_STATUS_OBF,
236 .req_complete_val = NSC_STATUS_OBF, 251 .req_complete_val = NSC_STATUS_OBF,
237 .base = TPM_NSC_BASE, 252 .req_canceled = NSC_STATUS_RDY,
253 .attr_group = &nsc_attr_grp,
238 .miscdev = { .fops = &nsc_ops, }, 254 .miscdev = { .fops = &nsc_ops, },
239
240}; 255};
241 256
242static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, 257static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
243 const struct pci_device_id *pci_id) 258 const struct pci_device_id *pci_id)
244{ 259{
245 int rc = 0; 260 int rc = 0;
261 int lo, hi;
262
263 hi = tpm_read_index(TPM_NSC_BASE0_HI);
264 lo = tpm_read_index(TPM_NSC_BASE0_LO);
265
266 tpm_nsc.base = (hi<<8) | lo;
246 267
247 if (pci_enable_device(pci_dev)) 268 if (pci_enable_device(pci_dev))
248 return -EIO; 269 return -EIO;
249 270
250 if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) {
251 rc = -ENODEV;
252 goto out_err;
253 }
254
255 /* verify that it is a National part (SID) */ 271 /* verify that it is a National part (SID) */
256 if (tpm_read_index(NSC_SID_INDEX) != 0xEF) { 272 if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
257 rc = -ENODEV; 273 rc = -ENODEV;
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index 84a49d2ec9..4adb2843f8 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $ 2 * $Id: ir-common.c,v 1.10 2005/05/22 19:23:39 nsh Exp $
3 * 3 *
4 * some common structs and functions to handle infrared remotes via 4 * some common structs and functions to handle infrared remotes via
5 * input layer ... 5 * input layer ...
@@ -131,10 +131,10 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
131 [ 18 ] = KEY_KP0, 131 [ 18 ] = KEY_KP0,
132 132
133 [ 0 ] = KEY_POWER, 133 [ 0 ] = KEY_POWER,
134 [ 27 ] = KEY_LANGUAGE, //MTS button 134// [ 27 ] = MTS button
135 [ 2 ] = KEY_TUNER, // TV/FM 135 [ 2 ] = KEY_TUNER, // TV/FM
136 [ 30 ] = KEY_VIDEO, 136 [ 30 ] = KEY_VIDEO,
137 [ 22 ] = KEY_INFO, //display button 137// [ 22 ] = display button
138 [ 4 ] = KEY_VOLUMEUP, 138 [ 4 ] = KEY_VOLUMEUP,
139 [ 8 ] = KEY_VOLUMEDOWN, 139 [ 8 ] = KEY_VOLUMEDOWN,
140 [ 12 ] = KEY_CHANNELUP, 140 [ 12 ] = KEY_CHANNELUP,
@@ -142,7 +142,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
142 [ 3 ] = KEY_ZOOM, // fullscreen 142 [ 3 ] = KEY_ZOOM, // fullscreen
143 [ 31 ] = KEY_SUBTITLE, // closed caption/teletext 143 [ 31 ] = KEY_SUBTITLE, // closed caption/teletext
144 [ 32 ] = KEY_SLEEP, 144 [ 32 ] = KEY_SLEEP,
145 [ 41 ] = KEY_SEARCH, //boss key 145// [ 41 ] = boss key
146 [ 20 ] = KEY_MUTE, 146 [ 20 ] = KEY_MUTE,
147 [ 43 ] = KEY_RED, 147 [ 43 ] = KEY_RED,
148 [ 44 ] = KEY_GREEN, 148 [ 44 ] = KEY_GREEN,
@@ -150,17 +150,17 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
150 [ 46 ] = KEY_BLUE, 150 [ 46 ] = KEY_BLUE,
151 [ 24 ] = KEY_KPPLUS, //fine tune + 151 [ 24 ] = KEY_KPPLUS, //fine tune +
152 [ 25 ] = KEY_KPMINUS, //fine tune - 152 [ 25 ] = KEY_KPMINUS, //fine tune -
153 [ 42 ] = KEY_ANGLE, //picture in picture 153// [ 42 ] = picture in picture
154 [ 33 ] = KEY_KPDOT, 154 [ 33 ] = KEY_KPDOT,
155 [ 19 ] = KEY_KPENTER, 155 [ 19 ] = KEY_KPENTER,
156 [ 17 ] = KEY_AGAIN, //recall 156// [ 17 ] = recall
157 [ 34 ] = KEY_BACK, 157 [ 34 ] = KEY_BACK,
158 [ 35 ] = KEY_PLAYPAUSE, 158 [ 35 ] = KEY_PLAYPAUSE,
159 [ 36 ] = KEY_NEXT, 159 [ 36 ] = KEY_NEXT,
160 [ 37 ] = KEY_T, //time shifting 160// [ 37 ] = time shifting
161 [ 38 ] = KEY_STOP, 161 [ 38 ] = KEY_STOP,
162 [ 39 ] = KEY_RECORD, 162 [ 39 ] = KEY_RECORD
163 [ 40 ] = KEY_SHUFFLE //snapshot 163// [ 40 ] = snapshot
164}; 164};
165EXPORT_SYMBOL_GPL(ir_codes_winfast); 165EXPORT_SYMBOL_GPL(ir_codes_winfast);
166 166
@@ -184,18 +184,30 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
184 [ 0x07 ] = KEY_KP7, // 7 184 [ 0x07 ] = KEY_KP7, // 7
185 [ 0x08 ] = KEY_KP8, // 8 185 [ 0x08 ] = KEY_KP8, // 8
186 [ 0x09 ] = KEY_KP9, // 9 186 [ 0x09 ] = KEY_KP9, // 9
187 [ 0x0a ] = KEY_TEXT, // keypad asterisk as well
187 [ 0x0b ] = KEY_RED, // red button 188 [ 0x0b ] = KEY_RED, // red button
188 [ 0x0c ] = KEY_OPTION, // black key without text 189 [ 0x0c ] = KEY_RADIO, // radio
189 [ 0x0d ] = KEY_MENU, // menu 190 [ 0x0d ] = KEY_MENU, // menu
191 [ 0x0e ] = KEY_SUBTITLE, // also the # key
190 [ 0x0f ] = KEY_MUTE, // mute 192 [ 0x0f ] = KEY_MUTE, // mute
191 [ 0x10 ] = KEY_VOLUMEUP, // volume + 193 [ 0x10 ] = KEY_VOLUMEUP, // volume +
192 [ 0x11 ] = KEY_VOLUMEDOWN, // volume - 194 [ 0x11 ] = KEY_VOLUMEDOWN, // volume -
193 [ 0x1e ] = KEY_NEXT, // skip >| 195 [ 0x12 ] = KEY_PREVIOUS, // previous channel
196 [ 0x14 ] = KEY_UP, // up
197 [ 0x15 ] = KEY_DOWN, // down
198 [ 0x16 ] = KEY_LEFT, // left
199 [ 0x17 ] = KEY_RIGHT, // right
200 [ 0x18 ] = KEY_VIDEO, // Videos
201 [ 0x19 ] = KEY_AUDIO, // Music
202 [ 0x1a ] = KEY_MHP, // Pictures - presume this means "Multimedia Home Platform"- no "PICTURES" key in input.h
203 [ 0x1b ] = KEY_EPG, // Guide
204 [ 0x1c ] = KEY_TV, // TV
205 [ 0x1e ] = KEY_NEXTSONG, // skip >|
194 [ 0x1f ] = KEY_EXIT, // back/exit 206 [ 0x1f ] = KEY_EXIT, // back/exit
195 [ 0x20 ] = KEY_CHANNELUP, // channel / program + 207 [ 0x20 ] = KEY_CHANNELUP, // channel / program +
196 [ 0x21 ] = KEY_CHANNELDOWN, // channel / program - 208 [ 0x21 ] = KEY_CHANNELDOWN, // channel / program -
197 [ 0x22 ] = KEY_CHANNEL, // source (old black remote) 209 [ 0x22 ] = KEY_CHANNEL, // source (old black remote)
198 [ 0x24 ] = KEY_PREVIOUS, // replay |< 210 [ 0x24 ] = KEY_PREVIOUSSONG, // replay |<
199 [ 0x25 ] = KEY_ENTER, // OK 211 [ 0x25 ] = KEY_ENTER, // OK
200 [ 0x26 ] = KEY_SLEEP, // minimize (old black remote) 212 [ 0x26 ] = KEY_SLEEP, // minimize (old black remote)
201 [ 0x29 ] = KEY_BLUE, // blue key 213 [ 0x29 ] = KEY_BLUE, // blue key
@@ -213,6 +225,39 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
213}; 225};
214EXPORT_SYMBOL(ir_codes_hauppauge_new); 226EXPORT_SYMBOL(ir_codes_hauppauge_new);
215 227
228IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
229 [ 2 ] = KEY_KP0,
230 [ 1 ] = KEY_KP1,
231 [ 11 ] = KEY_KP2,
232 [ 27 ] = KEY_KP3,
233 [ 5 ] = KEY_KP4,
234 [ 9 ] = KEY_KP5,
235 [ 21 ] = KEY_KP6,
236 [ 6 ] = KEY_KP7,
237 [ 10 ] = KEY_KP8,
238 [ 18 ] = KEY_KP9,
239
240 [ 3 ] = KEY_TUNER, // TV/FM
241 [ 7 ] = KEY_SEARCH, // scan
242 [ 28 ] = KEY_ZOOM, // full screen
243 [ 30 ] = KEY_POWER,
244 [ 23 ] = KEY_VOLUMEDOWN,
245 [ 31 ] = KEY_VOLUMEUP,
246 [ 20 ] = KEY_CHANNELDOWN,
247 [ 22 ] = KEY_CHANNELUP,
248 [ 24 ] = KEY_MUTE,
249
250 [ 0 ] = KEY_LIST, // source
251 [ 19 ] = KEY_INFO, // loop
252 [ 16 ] = KEY_LAST, // +100
253 [ 13 ] = KEY_CLEAR, // reset
254 [ 12 ] = BTN_RIGHT, // fun++
255 [ 4 ] = BTN_LEFT, // fun--
256 [ 14 ] = KEY_GOTO, // function
257 [ 15 ] = KEY_STOP, // freeze
258};
259EXPORT_SYMBOL(ir_codes_pixelview);
260
216/* -------------------------------------------------------------------------- */ 261/* -------------------------------------------------------------------------- */
217 262
218static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) 263static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
@@ -379,3 +424,4 @@ EXPORT_SYMBOL_GPL(ir_decode_biphase);
379 * c-basic-offset: 8 424 * c-basic-offset: 8
380 * End: 425 * End:
381 */ 426 */
427
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index cb826c9adf..c04fd11526 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -403,7 +403,7 @@ static struct file_operations video_fops =
403 .llseek = no_llseek, 403 .llseek = no_llseek,
404}; 404};
405 405
406void vv_callback(struct saa7146_dev *dev, unsigned long status) 406static void vv_callback(struct saa7146_dev *dev, unsigned long status)
407{ 407{
408 u32 isr = status; 408 u32 isr = status;
409 409
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 4983e1b1bb..01387f883c 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -27,9 +27,9 @@ source "drivers/media/dvb/ttpci/Kconfig"
27 27
28comment "Supported USB Adapters" 28comment "Supported USB Adapters"
29 depends on DVB_CORE && USB 29 depends on DVB_CORE && USB
30source "drivers/media/dvb/dvb-usb/Kconfig"
30source "drivers/media/dvb/ttusb-budget/Kconfig" 31source "drivers/media/dvb/ttusb-budget/Kconfig"
31source "drivers/media/dvb/ttusb-dec/Kconfig" 32source "drivers/media/dvb/ttusb-dec/Kconfig"
32source "drivers/media/dvb/dibusb/Kconfig"
33source "drivers/media/dvb/cinergyT2/Kconfig" 33source "drivers/media/dvb/cinergyT2/Kconfig"
34 34
35comment "Supported FlexCopII (B2C2) Adapters" 35comment "Supported FlexCopII (B2C2) Adapters"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index 520fc39028..3c6ff16191 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
2# Makefile for the kernel multimedia device drivers. 2# Makefile for the kernel multimedia device drivers.
3# 3#
4 4
5obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dibusb/ cinergyT2/ 5obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 99bd675df9..fafd0ab3a2 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -6,6 +6,7 @@ config DVB_B2C2_FLEXCOP
6 select DVB_MT312 6 select DVB_MT312
7 select DVB_NXT2002 7 select DVB_NXT2002
8 select DVB_STV0297 8 select DVB_STV0297
9 select DVB_BCM3510
9 help 10 help
10 Support for the digital TV receiver chip made by B2C2 Inc. included in 11 Support for the digital TV receiver chip made by B2C2 Inc. included in
11 Technisats PCI cards and USB boxes. 12 Technisats PCI cards and USB boxes.
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 71be400e9a..0410cc96a4 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -10,6 +10,7 @@
10#include "stv0299.h" 10#include "stv0299.h"
11#include "mt352.h" 11#include "mt352.h"
12#include "nxt2002.h" 12#include "nxt2002.h"
13#include "bcm3510.h"
13#include "stv0297.h" 14#include "stv0297.h"
14#include "mt312.h" 15#include "mt312.h"
15 16
@@ -285,21 +286,25 @@ static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_front
285} 286}
286 287
287static struct mt352_config samsung_tdtc9251dh0_config = { 288static struct mt352_config samsung_tdtc9251dh0_config = {
288
289 .demod_address = 0x0f, 289 .demod_address = 0x0f,
290 .demod_init = samsung_tdtc9251dh0_demod_init, 290 .demod_init = samsung_tdtc9251dh0_demod_init,
291 .pll_set = samsung_tdtc9251dh0_pll_set, 291 .pll_set = samsung_tdtc9251dh0_pll_set,
292}; 292};
293 293
294static int nxt2002_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) 294static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
295{ 295{
296 struct flexcop_device *fc = fe->dvb->priv; 296 struct flexcop_device *fc = fe->dvb->priv;
297 return request_firmware(fw, name, fc->dev); 297 return request_firmware(fw, name, fc->dev);
298} 298}
299 299
300static struct nxt2002_config samsung_tbmv_config = { 300static struct nxt2002_config samsung_tbmv_config = {
301 .demod_address = 0x0a, 301 .demod_address = 0x0a,
302 .request_firmware = nxt2002_request_firmware, 302 .request_firmware = flexcop_fe_request_firmware,
303};
304
305static struct bcm3510_config air2pc_atsc_first_gen_config = {
306 .demod_address = 0x0f,
307 .request_firmware = flexcop_fe_request_firmware,
303}; 308};
304 309
305static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 310static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
@@ -354,11 +359,16 @@ int flexcop_frontend_init(struct flexcop_device *fc)
354 fc->dev_type = FC_AIR_DVB; 359 fc->dev_type = FC_AIR_DVB;
355 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); 360 info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
356 } else 361 } else
357 /* try the air atsc (nxt2002) */ 362 /* try the air atsc 2nd generation (nxt2002) */
358 if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { 363 if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
359 fc->dev_type = FC_AIR_ATSC; 364 fc->dev_type = FC_AIR_ATSC2;
360 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); 365 info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
361 } else 366 } else
367 /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
368 if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
369 fc->dev_type = FC_AIR_ATSC1;
370 info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
371 } else
362 /* try the cable dvb (stv0297) */ 372 /* try the cable dvb (stv0297) */
363 if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) { 373 if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) {
364 fc->dev_type = FC_CABLE; 374 fc->dev_type = FC_CABLE;
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index 19e06da467..2308254565 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -45,11 +45,12 @@ const char *flexcop_revision_names[] = {
45 45
46const char *flexcop_device_names[] = { 46const char *flexcop_device_names[] = {
47 "Unkown device", 47 "Unkown device",
48 "AirStar 2 DVB-T", 48 "Air2PC/AirStar 2 DVB-T",
49 "AirStar 2 ATSC", 49 "Air2PC/AirStar 2 ATSC 1st generation",
50 "SkyStar 2 DVB-S", 50 "Air2PC/AirStar 2 ATSC 2nd generation",
51 "SkyStar 2 DVB-S (old version)", 51 "Sky2PC/SkyStar 2 DVB-S",
52 "CableStar 2 DVB-C", 52 "Sky2PC/SkyStar 2 DVB-S (old version)",
53 "Cable2PC/CableStar 2 DVB-C",
53}; 54};
54 55
55const char *flexcop_bus_names[] = { 56const char *flexcop_bus_names[] = {
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 5e131be55c..75b50f21af 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -21,7 +21,8 @@ extern const char *flexcop_revision_names[];
21typedef enum { 21typedef enum {
22 FC_UNK = 0, 22 FC_UNK = 0,
23 FC_AIR_DVB, 23 FC_AIR_DVB,
24 FC_AIR_ATSC, 24 FC_AIR_ATSC1,
25 FC_AIR_ATSC2,
25 FC_SKY, 26 FC_SKY,
26 FC_SKY_OLD, 27 FC_SKY_OLD,
27 FC_CABLE, 28 FC_CABLE,
diff --git a/drivers/media/dvb/dibusb/Kconfig b/drivers/media/dvb/dibusb/Kconfig
deleted file mode 100644
index 74dfc73ae5..0000000000
--- a/drivers/media/dvb/dibusb/Kconfig
+++ /dev/null
@@ -1,62 +0,0 @@
1config DVB_DIBUSB
2 tristate "DiBcom USB DVB-T devices (see help for a complete device list)"
3 depends on DVB_CORE && USB
4 select FW_LOADER
5 select DVB_DIB3000MB
6 select DVB_DIB3000MC
7 select DVB_MT352
8 help
9 Support for USB 1.1 and 2.0 DVB-T devices based on reference designs made by
10 DiBcom (http://www.dibcom.fr) and C&E.
11
12 Devices supported by this driver:
13
14 TwinhanDTV USB-Ter (VP7041)
15 TwinhanDTV Magic Box (VP7041e)
16 KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
17 Hama DVB-T USB-Box
18 DiBcom reference devices (non-public)
19 Ultima Electronic/Artec T1 USB TVBOX
20 Compro Videomate DVB-U2000 - DVB-T USB
21 Grandtec DVB-T USB
22 Avermedia AverTV DVBT USB
23 Artec T1 USB1.1 and USB2.0 boxes
24 Yakumo/Typhoon DVB-T USB2.0
25 Hanftek UMT-010 USB2.0
26 Hauppauge WinTV NOVA-T USB2
27
28 The VP7041 seems to be identical to "CTS Portable" (Chinese
29 Television System).
30
31 These devices can be understood as budget ones, they "only" deliver
32 (a part of) the MPEG2 transport stream.
33
34 A firmware is needed to get the device working. See Documentation/dvb/README.dibusb
35 details.
36
37 Say Y if you own such a device and want to use it. You should build it as
38 a module.
39
40config DVB_DIBUSB_MISDESIGNED_DEVICES
41 bool "Enable support for some misdesigned (see help) devices, which identify with wrong IDs"
42 depends on DVB_DIBUSB
43 help
44 Somehow Artec/Ultima Electronic forgot to program the eeprom of some of their
45 USB1.1/USB2.0 devices.
46 So comes that they identify with the default Vendor and Product ID of the Cypress
47 CY7C64613 (AN2235) or Cypress FX2.
48
49 Affected device IDs:
50 0x0574:0x2235 (Artec T1 USB1.1, cold)
51 0x04b4:0x8613 (Artec T1 USB2.0, cold)
52 0x0574:0x1002 (Artec T1 USB2.0, warm)
53 0x0574:0x2131 (aged DiBcom USB1.1 test device)
54
55 Say Y if your device has one of the mentioned IDs.
56
57config DVB_DIBCOM_DEBUG
58 bool "Enable extended debug support for DiBcom USB device"
59 depends on DVB_DIBUSB
60 help
61 Say Y if you want to enable debuging. See modinfo dvb-dibusb for
62 debug levels.
diff --git a/drivers/media/dvb/dibusb/Makefile b/drivers/media/dvb/dibusb/Makefile
deleted file mode 100644
index e941c50862..0000000000
--- a/drivers/media/dvb/dibusb/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
1dvb-dibusb-objs = dvb-dibusb-core.o \
2 dvb-dibusb-dvb.o \
3 dvb-dibusb-fe-i2c.o \
4 dvb-dibusb-firmware.o \
5 dvb-dibusb-remote.o \
6 dvb-dibusb-usb.o \
7 dvb-fe-dtt200u.o
8
9obj-$(CONFIG_DVB_DIBUSB) += dvb-dibusb.o
10
11EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-core.c b/drivers/media/dvb/dibusb/dvb-dibusb-core.c
deleted file mode 100644
index 26235f9247..0000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-core.c
+++ /dev/null
@@ -1,558 +0,0 @@
1/*
2 * Driver for mobile USB Budget DVB-T devices based on reference
3 * design made by DiBcom (http://www.dibcom.fr/)
4 *
5 * dvb-dibusb-core.c
6 *
7 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
8 *
9 * based on GPL code from DiBcom, which has
10 * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
11 *
12 * Remote control code added by David Matthews (dm@prolingua.co.uk)
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation, version 2.
17 *
18 * Acknowledgements
19 *
20 * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
21 * sources, on which this driver (and the dib3000mb/mc/p frontends) are based.
22 *
23 * see Documentation/dvb/README.dibusb for more information
24 */
25#include "dvb-dibusb.h"
26
27#include <linux/moduleparam.h>
28
29/* debug */
30int dvb_dibusb_debug;
31module_param_named(debug, dvb_dibusb_debug, int, 0644);
32
33#ifdef CONFIG_DVB_DIBCOM_DEBUG
34#define DBSTATUS ""
35#else
36#define DBSTATUS " (debugging is not enabled)"
37#endif
38MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able))." DBSTATUS);
39#undef DBSTATUS
40
41static int pid_parse;
42module_param(pid_parse, int, 0644);
43MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0");
44
45static int rc_query_interval = 100;
46module_param(rc_query_interval, int, 0644);
47MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query (default: 100; min: 40)");
48
49static int rc_key_repeat_count = 2;
50module_param(rc_key_repeat_count, int, 0644);
51MODULE_PARM_DESC(rc_key_repeat_count, "how many key repeats will be dropped before passing the key event again (default: 2)");
52
53/* Vendor IDs */
54#define USB_VID_ADSTECH 0x06e1
55#define USB_VID_ANCHOR 0x0547
56#define USB_VID_AVERMEDIA 0x14aa
57#define USB_VID_COMPRO 0x185b
58#define USB_VID_COMPRO_UNK 0x145f
59#define USB_VID_CYPRESS 0x04b4
60#define USB_VID_DIBCOM 0x10b8
61#define USB_VID_EMPIA 0xeb1a
62#define USB_VID_GRANDTEC 0x5032
63#define USB_VID_HANFTEK 0x15f4
64#define USB_VID_HAUPPAUGE 0x2040
65#define USB_VID_HYPER_PALTEK 0x1025
66#define USB_VID_IMC_NETWORKS 0x13d3
67#define USB_VID_TWINHAN 0x1822
68#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
69
70/* Product IDs */
71#define USB_PID_ADSTECH_USB2_COLD 0xa333
72#define USB_PID_ADSTECH_USB2_WARM 0xa334
73#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
74#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
75#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
76#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
77#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
78#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
79#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
80#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9
81#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
82#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
83#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
84#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
85#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
86#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
87#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
88#define USB_PID_TWINHAN_VP7041_COLD 0x3201
89#define USB_PID_TWINHAN_VP7041_WARM 0x3202
90#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
91#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
92#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
93#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
94#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
95#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
96#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
97#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
98#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
99#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
100#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
101#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
102#define USB_PID_YAKUMO_DTT200U_COLD 0x0201
103#define USB_PID_YAKUMO_DTT200U_WARM 0x0301
104#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
105#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
106
107/* USB Driver stuff
108 * table of devices that this driver is working with
109 *
110 * ATTENTION: Never ever change the order of this table, the particular
111 * devices depend on this order
112 *
113 * Each entry is used as a reference in the device_struct. Currently this is
114 * the only non-redundant way of assigning USB ids to actual devices I'm aware
115 * of, because there is only one place in the code where the assignment of
116 * vendor and product id is done, here.
117 */
118static struct usb_device_id dib_table [] = {
119/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
120/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
121/* 02 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_COLD) },
122/* 03 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_WARM) },
123
124/* 04 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
125/* 05 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
126/* 06 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
127/* 07 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
128/* 08 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
129/* 09 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) },
130/* 10 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) },
131/* 11 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
132/* 12 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
133/* 13 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
134/* 14 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
135/* 15 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
136/* 16 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) },
137/* 17 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) },
138/* 18 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) },
139/* 19 */ { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_COLD) },
140/* 20 */ { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_WARM) },
141/* 21 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
142/* 22 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
143/* 23 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
144/* 24 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
145/* 25 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
146/* 26 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
147/* 27 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
148
149/* 28 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
150/* 29 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
151
152/* 30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) },
153/* 31 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
154/* 32 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
155/* 33 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
156/*
157 * activate the following define when you have one of the devices and want to
158 * build it from build-2.6 in dvb-kernel
159 */
160// #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
161#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
162/* 34 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
163/* 35 */ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) },
164/* 36 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) },
165/* 37 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) },
166#endif
167 { } /* Terminating entry */
168};
169
170MODULE_DEVICE_TABLE (usb, dib_table);
171
172static struct dibusb_usb_controller dibusb_usb_ctrl[] = {
173 { .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
174 { .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
175 { .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
176};
177
178struct dibusb_tuner dibusb_tuner[] = {
179 { DIBUSB_TUNER_CABLE_THOMSON,
180 0x61
181 },
182 { DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5,
183 0x60
184 },
185 { DIBUSB_TUNER_CABLE_LG_TDTP_E102P,
186 0x61
187 },
188 { DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5,
189 0x60
190 },
191};
192
193static struct dibusb_demod dibusb_demod[] = {
194 { DIBUSB_DIB3000MB,
195 16,
196 { 0x8, 0 },
197 },
198 { DIBUSB_DIB3000MC,
199 32,
200 { 0x9, 0xa, 0xb, 0xc },
201 },
202 { DIBUSB_MT352,
203 254,
204 { 0xf, 0 },
205 },
206 { DTT200U_FE,
207 8,
208 { 0xff,0 }, /* there is no i2c bus in this device */
209 }
210};
211
212static struct dibusb_device_class dibusb_device_classes[] = {
213 { .id = DIBUSB1_1, .usb_ctrl = &dibusb_usb_ctrl[0],
214 .firmware = "dvb-dibusb-5.0.0.11.fw",
215 .pipe_cmd = 0x01, .pipe_data = 0x02,
216 .urb_count = 7, .urb_buffer_size = 4096,
217 DIBUSB_RC_NEC_PROTOCOL,
218 &dibusb_demod[DIBUSB_DIB3000MB],
219 &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
220 },
221 { DIBUSB1_1_AN2235, &dibusb_usb_ctrl[1],
222 "dvb-dibusb-an2235-1.fw",
223 0x01, 0x02,
224 7, 4096,
225 DIBUSB_RC_NEC_PROTOCOL,
226 &dibusb_demod[DIBUSB_DIB3000MB],
227 &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
228 },
229 { DIBUSB2_0,&dibusb_usb_ctrl[2],
230 "dvb-dibusb-6.0.0.5.fw",
231 0x01, 0x06,
232 7, 4096,
233 DIBUSB_RC_NEC_PROTOCOL,
234 &dibusb_demod[DIBUSB_DIB3000MC],
235 &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5],
236 },
237 { UMT2_0, &dibusb_usb_ctrl[2],
238 "dvb-dibusb-umt-2.fw",
239 0x01, 0x06,
240 20, 512,
241 DIBUSB_RC_NO,
242 &dibusb_demod[DIBUSB_MT352],
243 &dibusb_tuner[DIBUSB_TUNER_CABLE_LG_TDTP_E102P],
244 },
245 { DIBUSB2_0B,&dibusb_usb_ctrl[2],
246 "dvb-dibusb-adstech-usb2-1.fw",
247 0x01, 0x06,
248 7, 4096,
249 DIBUSB_RC_NEC_PROTOCOL,
250 &dibusb_demod[DIBUSB_DIB3000MB],
251 &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
252 },
253 { NOVAT_USB2,&dibusb_usb_ctrl[2],
254 "dvb-dibusb-nova-t-1.fw",
255 0x01, 0x06,
256 7, 4096,
257 DIBUSB_RC_HAUPPAUGE_PROTO,
258 &dibusb_demod[DIBUSB_DIB3000MC],
259 &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5],
260 },
261 { DTT200U,&dibusb_usb_ctrl[2],
262 "dvb-dtt200u-1.fw",
263 0x01, 0x02,
264 7, 4096,
265 DIBUSB_RC_NO,
266 &dibusb_demod[DTT200U_FE],
267 NULL, /* no explicit tuner/pll-programming necessary (it has the ENV57H1XD5) */
268 },
269};
270
271static struct dibusb_usb_device dibusb_devices[] = {
272 { "TwinhanDTV USB1.1 / Magic Box / HAMA USB1.1 DVB-T device",
273 &dibusb_device_classes[DIBUSB1_1],
274 { &dib_table[19], &dib_table[21], NULL},
275 { &dib_table[20], &dib_table[22], NULL},
276 },
277 { "KWorld V-Stream XPERT DTV - DVB-T USB1.1",
278 &dibusb_device_classes[DIBUSB1_1],
279 { &dib_table[11], NULL },
280 { &dib_table[12], NULL },
281 },
282 { "Grandtec USB1.1 DVB-T",
283 &dibusb_device_classes[DIBUSB1_1],
284 { &dib_table[13], &dib_table[15], NULL },
285 { &dib_table[14], &dib_table[16], NULL },
286 },
287 { "DiBcom USB1.1 DVB-T reference design (MOD3000)",
288 &dibusb_device_classes[DIBUSB1_1],
289 { &dib_table[7], NULL },
290 { &dib_table[8], NULL },
291 },
292 { "Artec T1 USB1.1 TVBOX with AN2135",
293 &dibusb_device_classes[DIBUSB1_1],
294 { &dib_table[23], NULL },
295 { &dib_table[24], NULL },
296 },
297 { "Artec T1 USB1.1 TVBOX with AN2235",
298 &dibusb_device_classes[DIBUSB1_1_AN2235],
299 { &dib_table[25], NULL },
300 { &dib_table[26], NULL },
301 },
302 { "Avermedia AverTV DVBT USB1.1",
303 &dibusb_device_classes[DIBUSB1_1],
304 { &dib_table[0], NULL },
305 { &dib_table[1], NULL },
306 },
307 { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
308 &dibusb_device_classes[DIBUSB1_1],
309 { &dib_table[4], &dib_table[6], NULL},
310 { &dib_table[5], NULL },
311 },
312 { "Unkown USB1.1 DVB-T device ???? please report the name to the author",
313 &dibusb_device_classes[DIBUSB1_1],
314 { &dib_table[17], NULL },
315 { &dib_table[18], NULL },
316 },
317 { "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
318 &dibusb_device_classes[DIBUSB2_0],
319 { &dib_table[9], NULL },
320 { &dib_table[10], NULL },
321 },
322 { "Artec T1 USB2.0 TVBOX (please report the warm ID)",
323 &dibusb_device_classes[DIBUSB2_0],
324 { &dib_table[27], NULL },
325 { NULL },
326 },
327 { "Hauppauge WinTV NOVA-T USB2",
328 &dibusb_device_classes[NOVAT_USB2],
329 { &dib_table[30], NULL },
330 { &dib_table[31], NULL },
331 },
332 { "DTT200U (Yakumo/Hama/Typhoon) DVB-T USB2.0",
333 &dibusb_device_classes[DTT200U],
334 { &dib_table[2], NULL },
335 { &dib_table[3], NULL },
336 },
337 { "Hanftek UMT-010 DVB-T USB2.0",
338 &dibusb_device_classes[UMT2_0],
339 { &dib_table[28], NULL },
340 { &dib_table[29], NULL },
341 },
342 { "KWorld/ADSTech Instant DVB-T USB 2.0",
343 &dibusb_device_classes[DIBUSB2_0B],
344 { &dib_table[32], NULL },
345 { &dib_table[33], NULL }, /* device ID with default DIBUSB2_0-firmware */
346 },
347#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
348 { "Artec T1 USB1.1 TVBOX with AN2235 (misdesigned)",
349 &dibusb_device_classes[DIBUSB1_1_AN2235],
350 { &dib_table[34], NULL },
351 { NULL },
352 },
353 { "Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)",
354 &dibusb_device_classes[DTT200U],
355 { &dib_table[35], NULL },
356 { &dib_table[36], NULL }, /* undefined, it could be that the device will get another USB ID in warm state */
357 },
358 { "DiBcom USB1.1 DVB-T reference design (MOD3000) with AN2135 default IDs",
359 &dibusb_device_classes[DIBUSB1_1],
360 { &dib_table[37], NULL },
361 { NULL },
362 },
363#endif
364};
365
366static int dibusb_exit(struct usb_dibusb *dib)
367{
368 deb_info("init_state before exiting everything: %x\n",dib->init_state);
369 dibusb_remote_exit(dib);
370 dibusb_fe_exit(dib);
371 dibusb_i2c_exit(dib);
372 dibusb_dvb_exit(dib);
373 dibusb_urb_exit(dib);
374 deb_info("init_state should be zero now: %x\n",dib->init_state);
375 dib->init_state = DIBUSB_STATE_INIT;
376 kfree(dib);
377 return 0;
378}
379
380static int dibusb_init(struct usb_dibusb *dib)
381{
382 int ret = 0;
383 sema_init(&dib->usb_sem, 1);
384 sema_init(&dib->i2c_sem, 1);
385
386 dib->init_state = DIBUSB_STATE_INIT;
387
388 if ((ret = dibusb_urb_init(dib)) ||
389 (ret = dibusb_dvb_init(dib)) ||
390 (ret = dibusb_i2c_init(dib))) {
391 dibusb_exit(dib);
392 return ret;
393 }
394
395 if ((ret = dibusb_fe_init(dib)))
396 err("could not initialize a frontend.");
397
398 if ((ret = dibusb_remote_init(dib)))
399 err("could not initialize remote control.");
400
401 return 0;
402}
403
404static struct dibusb_usb_device * dibusb_device_class_quirk(struct usb_device *udev, struct dibusb_usb_device *dev)
405{
406 int i;
407
408 /* Quirk for the Kworld/ADSTech Instant USB2.0 device. It has the same USB
409 * IDs like the USB1.1 KWorld after loading the firmware. Which is a bad
410 * idea and make this quirk necessary.
411 */
412 if (dev->dev_cl->id == DIBUSB1_1 && udev->speed == USB_SPEED_HIGH) {
413 info("this seems to be the Kworld/ADSTech Instant USB2.0 device or equal.");
414 for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) {
415 if (dibusb_devices[i].dev_cl->id == DIBUSB2_0B) {
416 dev = &dibusb_devices[i];
417 break;
418 }
419 }
420 }
421
422 return dev;
423}
424
425static struct dibusb_usb_device * dibusb_find_device (struct usb_device *udev,int *cold)
426{
427 int i,j;
428 struct dibusb_usb_device *dev = NULL;
429 *cold = -1;
430
431 for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) {
432 for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].cold_ids[j] != NULL; j++) {
433 deb_info("check for cold %x %x\n",dibusb_devices[i].cold_ids[j]->idVendor, dibusb_devices[i].cold_ids[j]->idProduct);
434 if (dibusb_devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
435 dibusb_devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
436 *cold = 1;
437 dev = &dibusb_devices[i];
438 break;
439 }
440 }
441
442 if (dev != NULL)
443 break;
444
445 for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].warm_ids[j] != NULL; j++) {
446 deb_info("check for warm %x %x\n",dibusb_devices[i].warm_ids[j]->idVendor, dibusb_devices[i].warm_ids[j]->idProduct);
447 if (dibusb_devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
448 dibusb_devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
449 *cold = 0;
450 dev = &dibusb_devices[i];
451 break;
452 }
453 }
454 }
455
456 if (dev != NULL)
457 dev = dibusb_device_class_quirk(udev,dev);
458
459 return dev;
460}
461
462/*
463 * USB
464 */
465static int dibusb_probe(struct usb_interface *intf,
466 const struct usb_device_id *id)
467{
468 struct usb_device *udev = interface_to_usbdev(intf);
469 struct usb_dibusb *dib = NULL;
470 struct dibusb_usb_device *dibdev = NULL;
471
472 int ret = -ENOMEM,cold=0;
473
474 if ((dibdev = dibusb_find_device(udev,&cold)) == NULL) {
475 err("something went very wrong, "
476 "unknown product ID: %.4x",le16_to_cpu(udev->descriptor.idProduct));
477 return -ENODEV;
478 }
479
480 if (cold == 1) {
481 info("found a '%s' in cold state, will try to load a firmware",dibdev->name);
482 ret = dibusb_loadfirmware(udev,dibdev);
483 } else {
484 info("found a '%s' in warm state.",dibdev->name);
485 dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL);
486 if (dib == NULL) {
487 err("no memory");
488 return ret;
489 }
490 memset(dib,0,sizeof(struct usb_dibusb));
491
492 dib->udev = udev;
493 dib->dibdev = dibdev;
494
495 /* store parameters to structures */
496 dib->rc_query_interval = rc_query_interval;
497 dib->pid_parse = pid_parse;
498 dib->rc_key_repeat_count = rc_key_repeat_count;
499
500 usb_set_intfdata(intf, dib);
501
502 ret = dibusb_init(dib);
503 }
504
505 if (ret == 0)
506 info("%s successfully initialized and connected.",dibdev->name);
507 else
508 info("%s error while loading driver (%d)",dibdev->name,ret);
509 return ret;
510}
511
512static void dibusb_disconnect(struct usb_interface *intf)
513{
514 struct usb_dibusb *dib = usb_get_intfdata(intf);
515 const char *name = DRIVER_DESC;
516
517 usb_set_intfdata(intf,NULL);
518 if (dib != NULL && dib->dibdev != NULL) {
519 name = dib->dibdev->name;
520 dibusb_exit(dib);
521 }
522 info("%s successfully deinitialized and disconnected.",name);
523
524}
525
526/* usb specific object needed to register this driver with the usb subsystem */
527static struct usb_driver dibusb_driver = {
528 .owner = THIS_MODULE,
529 .name = DRIVER_DESC,
530 .probe = dibusb_probe,
531 .disconnect = dibusb_disconnect,
532 .id_table = dib_table,
533};
534
535/* module stuff */
536static int __init usb_dibusb_init(void)
537{
538 int result;
539 if ((result = usb_register(&dibusb_driver))) {
540 err("usb_register failed. Error number %d",result);
541 return result;
542 }
543
544 return 0;
545}
546
547static void __exit usb_dibusb_exit(void)
548{
549 /* deregister this driver from the USB subsystem */
550 usb_deregister(&dibusb_driver);
551}
552
553module_init (usb_dibusb_init);
554module_exit (usb_dibusb_exit);
555
556MODULE_AUTHOR(DRIVER_AUTHOR);
557MODULE_DESCRIPTION(DRIVER_DESC);
558MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c b/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
deleted file mode 100644
index 400b439e80..0000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
+++ /dev/null
@@ -1,185 +0,0 @@
1/*
2 * dvb-dibusb-dvb.c is part of the driver for mobile USB Budget DVB-T devices
3 * based on reference design made by DiBcom (http://www.dibcom.fr/)
4 *
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
7 * see dvb-dibusb-core.c for more copyright details.
8 *
9 * This file contains functions for initializing and handling the
10 * linux-dvb API.
11 */
12#include "dvb-dibusb.h"
13
14#include <linux/usb.h>
15#include <linux/version.h>
16
17static u32 urb_compl_count;
18
19/*
20 * MPEG2 TS DVB stuff
21 */
22void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
23{
24 struct usb_dibusb *dib = urb->context;
25
26 deb_ts("urb complete feedcount: %d, status: %d, length: %d\n",dib->feedcount,urb->status,
27 urb->actual_length);
28
29 urb_compl_count++;
30 if (urb_compl_count % 1000 == 0)
31 deb_info("%d urbs completed so far.\n",urb_compl_count);
32
33 switch (urb->status) {
34 case 0: /* success */
35 case -ETIMEDOUT: /* NAK */
36 break;
37 case -ECONNRESET: /* kill */
38 case -ENOENT:
39 case -ESHUTDOWN:
40 return;
41 default: /* error */
42 deb_ts("urb completition error %d.", urb->status);
43 break;
44 }
45
46 if (dib->feedcount > 0 && urb->actual_length > 0) {
47 if (dib->init_state & DIBUSB_STATE_DVB)
48 dvb_dmx_swfilter(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length);
49 } else
50 deb_ts("URB dropped because of feedcount.\n");
51
52 usb_submit_urb(urb,GFP_ATOMIC);
53}
54
55static int dibusb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
56{
57 struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
58 int newfeedcount;
59
60 if (dib == NULL)
61 return -ENODEV;
62
63 newfeedcount = dib->feedcount + (onoff ? 1 : -1);
64
65 /*
66 * stop feed before setting a new pid if there will be no pid anymore
67 */
68 if (newfeedcount == 0) {
69 deb_ts("stop feeding\n");
70 if (dib->xfer_ops.fifo_ctrl != NULL) {
71 if (dib->xfer_ops.fifo_ctrl(dib->fe,0)) {
72 err("error while inhibiting fifo.");
73 return -ENODEV;
74 }
75 }
76 dibusb_streaming(dib,0);
77 }
78
79 dib->feedcount = newfeedcount;
80
81 /* activate the pid on the device specific pid_filter */
82 deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
83 if (dib->pid_parse && dib->xfer_ops.pid_ctrl != NULL)
84 dib->xfer_ops.pid_ctrl(dib->fe,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
85
86 /*
87 * start the feed if this was the first pid to set and there is still a pid
88 * for reception.
89 */
90 if (dib->feedcount == onoff && dib->feedcount > 0) {
91
92 deb_ts("controlling pid parser\n");
93 if (dib->xfer_ops.pid_parse != NULL) {
94 if (dib->xfer_ops.pid_parse(dib->fe,dib->pid_parse) < 0) {
95 err("could not handle pid_parser");
96 }
97 }
98
99 deb_ts("start feeding\n");
100 if (dib->xfer_ops.fifo_ctrl != NULL) {
101 if (dib->xfer_ops.fifo_ctrl(dib->fe,1)) {
102 err("error while enabling fifo.");
103 return -ENODEV;
104 }
105 }
106 dibusb_streaming(dib,1);
107 }
108 return 0;
109}
110
111static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
112{
113 deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
114 return dibusb_ctrl_feed(dvbdmxfeed,1);
115}
116
117static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
118{
119 deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
120 return dibusb_ctrl_feed(dvbdmxfeed,0);
121}
122
123int dibusb_dvb_init(struct usb_dibusb *dib)
124{
125 int ret;
126
127 urb_compl_count = 0;
128
129 if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC,
130 THIS_MODULE)) < 0) {
131 deb_info("dvb_register_adapter failed: error %d", ret);
132 goto err;
133 }
134 dib->adapter.priv = dib;
135
136/* i2c is done in dibusb_i2c_init */
137
138 dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
139
140 dib->demux.priv = (void *)dib;
141 /* get pidcount from demod */
142 dib->demux.feednum = dib->demux.filternum = 255;
143 dib->demux.start_feed = dibusb_start_feed;
144 dib->demux.stop_feed = dibusb_stop_feed;
145 dib->demux.write_to_decoder = NULL;
146 if ((ret = dvb_dmx_init(&dib->demux)) < 0) {
147 err("dvb_dmx_init failed: error %d",ret);
148 goto err_dmx;
149 }
150
151 dib->dmxdev.filternum = dib->demux.filternum;
152 dib->dmxdev.demux = &dib->demux.dmx;
153 dib->dmxdev.capabilities = 0;
154 if ((ret = dvb_dmxdev_init(&dib->dmxdev, &dib->adapter)) < 0) {
155 err("dvb_dmxdev_init failed: error %d",ret);
156 goto err_dmx_dev;
157 }
158
159 dvb_net_init(&dib->adapter, &dib->dvb_net, &dib->demux.dmx);
160
161 goto success;
162err_dmx_dev:
163 dvb_dmx_release(&dib->demux);
164err_dmx:
165 dvb_unregister_adapter(&dib->adapter);
166err:
167 return ret;
168success:
169 dib->init_state |= DIBUSB_STATE_DVB;
170 return 0;
171}
172
173int dibusb_dvb_exit(struct usb_dibusb *dib)
174{
175 if (dib->init_state & DIBUSB_STATE_DVB) {
176 dib->init_state &= ~DIBUSB_STATE_DVB;
177 deb_info("unregistering DVB part\n");
178 dvb_net_release(&dib->dvb_net);
179 dib->demux.dmx.close(&dib->demux.dmx);
180 dvb_dmxdev_release(&dib->dmxdev);
181 dvb_dmx_release(&dib->demux);
182 dvb_unregister_adapter(&dib->adapter);
183 }
184 return 0;
185}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
deleted file mode 100644
index 5a71b88797..0000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
+++ /dev/null
@@ -1,582 +0,0 @@
1/*
2 * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices
3 * based on reference design made by DiBcom (http://www.dibcom.fr/)
4 *
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
7 * see dvb-dibusb-core.c for more copyright details.
8 *
9 * This file contains functions for attaching, initializing of an appropriate
10 * demodulator/frontend. I2C-stuff is also located here.
11 *
12 */
13#include "dvb-dibusb.h"
14
15#include <linux/usb.h>
16
17static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr,
18 u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
19{
20 u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
21 /* write only ? */
22 int wo = (rbuf == NULL || rlen == 0),
23 len = 2 + wlen + (wo ? 0 : 2);
24
25 sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
26 sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
27
28 memcpy(&sndbuf[2],wbuf,wlen);
29
30 if (!wo) {
31 sndbuf[wlen+2] = (rlen >> 8) & 0xff;
32 sndbuf[wlen+3] = rlen & 0xff;
33 }
34
35 return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen);
36}
37
38/*
39 * I2C master xfer function
40 */
41static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
42{
43 struct usb_dibusb *dib = i2c_get_adapdata(adap);
44 int i;
45
46 if (down_interruptible(&dib->i2c_sem) < 0)
47 return -EAGAIN;
48
49 if (num > 2)
50 warn("more than 2 i2c messages at a time is not handled yet. TODO.");
51
52 for (i = 0; i < num; i++) {
53 /* write/read request */
54 if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
55 if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,
56 msg[i+1].buf,msg[i+1].len) < 0)
57 break;
58 i++;
59 } else
60 if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
61 break;
62 }
63
64 up(&dib->i2c_sem);
65 return i;
66}
67
68static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
69{
70 return I2C_FUNC_I2C;
71}
72
73static struct i2c_algorithm dibusb_algo = {
74 .name = "DiBcom USB i2c algorithm",
75 .id = I2C_ALGO_BIT,
76 .master_xfer = dibusb_i2c_xfer,
77 .functionality = dibusb_i2c_func,
78};
79
80static int dibusb_general_demod_init(struct dvb_frontend *fe);
81static u8 dibusb_general_pll_addr(struct dvb_frontend *fe);
82static int dibusb_general_pll_init(struct dvb_frontend *fe, u8 pll_buf[5]);
83static int dibusb_general_pll_set(struct dvb_frontend *fe,
84 struct dvb_frontend_parameters* params, u8 pll_buf[5]);
85
86static struct mt352_config mt352_hanftek_umt_010_config = {
87 .demod_address = 0x1e,
88 .demod_init = dibusb_general_demod_init,
89 .pll_set = dibusb_general_pll_set,
90};
91
92static int dibusb_tuner_quirk(struct usb_dibusb *dib)
93{
94 switch (dib->dibdev->dev_cl->id) {
95 case DIBUSB1_1: /* some these device have the ENV77H11D5 and some the THOMSON CABLE */
96 case DIBUSB1_1_AN2235: { /* actually its this device, but in warm state they are indistinguishable */
97 struct dibusb_tuner *t;
98 u8 b[2] = { 0,0 } ,b2[1];
99 struct i2c_msg msg[2] = {
100 { .flags = 0, .buf = b, .len = 2 },
101 { .flags = I2C_M_RD, .buf = b2, .len = 1},
102 };
103
104 t = &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5];
105
106 msg[0].addr = msg[1].addr = t->pll_addr;
107
108 if (dib->xfer_ops.tuner_pass_ctrl != NULL)
109 dib->xfer_ops.tuner_pass_ctrl(dib->fe,1,t->pll_addr);
110 dibusb_i2c_xfer(&dib->i2c_adap,msg,2);
111 if (dib->xfer_ops.tuner_pass_ctrl != NULL)
112 dib->xfer_ops.tuner_pass_ctrl(dib->fe,0,t->pll_addr);
113
114 if (b2[0] == 0xfe)
115 info("this device has the Thomson Cable onboard. Which is default.");
116 else {
117 dib->tuner = t;
118 info("this device has the Panasonic ENV77H11D5 onboard.");
119 }
120 break;
121 }
122 default:
123 break;
124 }
125 return 0;
126}
127
128int dibusb_fe_init(struct usb_dibusb* dib)
129{
130 struct dib3000_config demod_cfg;
131 int i;
132
133 if (dib->init_state & DIBUSB_STATE_I2C) {
134 for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) &&
135 dib->dibdev->dev_cl->demod->i2c_addrs[i] != 0; i++) {
136
137 demod_cfg.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
138 demod_cfg.pll_addr = dibusb_general_pll_addr;
139 demod_cfg.pll_set = dibusb_general_pll_set;
140 demod_cfg.pll_init = dibusb_general_pll_init;
141
142 deb_info("demod id: %d %d\n",dib->dibdev->dev_cl->demod->id,DTT200U_FE);
143
144 switch (dib->dibdev->dev_cl->demod->id) {
145 case DIBUSB_DIB3000MB:
146 dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
147 break;
148 case DIBUSB_DIB3000MC:
149 dib->fe = dib3000mc_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
150 break;
151 case DIBUSB_MT352:
152 mt352_hanftek_umt_010_config.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
153 dib->fe = mt352_attach(&mt352_hanftek_umt_010_config, &dib->i2c_adap);
154 break;
155 case DTT200U_FE:
156 dib->fe = dtt200u_fe_attach(dib,&dib->xfer_ops);
157 break;
158 }
159 if (dib->fe != NULL) {
160 info("found demodulator at i2c address 0x%x",dib->dibdev->dev_cl->demod->i2c_addrs[i]);
161 break;
162 }
163 }
164 /* if a frontend was found */
165 if (dib->fe != NULL) {
166 if (dib->fe->ops->sleep != NULL)
167 dib->fe_sleep = dib->fe->ops->sleep;
168 dib->fe->ops->sleep = dibusb_hw_sleep;
169
170 if (dib->fe->ops->init != NULL )
171 dib->fe_init = dib->fe->ops->init;
172 dib->fe->ops->init = dibusb_hw_wakeup;
173
174 /* setting the default tuner */
175 dib->tuner = dib->dibdev->dev_cl->tuner;
176
177 /* check which tuner is mounted on this device, in case this is unsure */
178 dibusb_tuner_quirk(dib);
179 }
180 }
181 if (dib->fe == NULL) {
182 err("A frontend driver was not found for device '%s'.",
183 dib->dibdev->name);
184 return -ENODEV;
185 } else {
186 if (dvb_register_frontend(&dib->adapter, dib->fe)) {
187 err("Frontend registration failed.");
188 if (dib->fe->ops->release)
189 dib->fe->ops->release(dib->fe);
190 dib->fe = NULL;
191 return -ENODEV;
192 }
193 }
194
195 return 0;
196}
197
198int dibusb_fe_exit(struct usb_dibusb *dib)
199{
200 if (dib->fe != NULL)
201 dvb_unregister_frontend(dib->fe);
202 return 0;
203}
204
205int dibusb_i2c_init(struct usb_dibusb *dib)
206{
207 int ret = 0;
208
209 dib->adapter.priv = dib;
210
211 strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE);
212#ifdef I2C_ADAP_CLASS_TV_DIGITAL
213 dib->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
214#else
215 dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
216#endif
217 dib->i2c_adap.algo = &dibusb_algo;
218 dib->i2c_adap.algo_data = NULL;
219 dib->i2c_adap.id = I2C_ALGO_BIT;
220
221 i2c_set_adapdata(&dib->i2c_adap, dib);
222
223 if ((ret = i2c_add_adapter(&dib->i2c_adap)) < 0)
224 err("could not add i2c adapter");
225
226 dib->init_state |= DIBUSB_STATE_I2C;
227
228 return ret;
229}
230
231int dibusb_i2c_exit(struct usb_dibusb *dib)
232{
233 if (dib->init_state & DIBUSB_STATE_I2C)
234 i2c_del_adapter(&dib->i2c_adap);
235 dib->init_state &= ~DIBUSB_STATE_I2C;
236 return 0;
237}
238
239
240/* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */
241static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
242{
243 u32 tfreq = (fep->frequency + 36125000) / 62500;
244 int vu,p0,p1,p2;
245
246 if (fep->frequency > 403250000)
247 vu = 1, p2 = 1, p1 = 0, p0 = 1;
248 else if (fep->frequency > 115750000)
249 vu = 0, p2 = 1, p1 = 1, p0 = 0;
250 else if (fep->frequency > 44250000)
251 vu = 0, p2 = 0, p1 = 1, p0 = 1;
252 else
253 return -EINVAL;
254
255 pllbuf[0] = (tfreq >> 8) & 0x7f;
256 pllbuf[1] = tfreq & 0xff;
257 pllbuf[2] = 0x8e;
258 pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;
259 return 0;
260}
261
262static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
263{
264 u32 freq_khz = fep->frequency / 1000;
265 u32 tfreq = ((freq_khz + 36125)*6 + 500) / 1000;
266 u8 TA, T210, R210, ctrl1, cp210, p4321;
267 if (freq_khz > 858000) {
268 err("frequency cannot be larger than 858 MHz.");
269 return -EINVAL;
270 }
271
272 // contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0
273 TA = 1;
274 T210 = 0;
275 R210 = 0x2;
276 ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210;
277
278// ******** CHARGE PUMP CONFIG vs RF FREQUENCIES *****************
279 if (freq_khz < 470000)
280 cp210 = 2; // VHF Low and High band ch E12 to E4 to E12
281 else if (freq_khz < 526000)
282 cp210 = 4; // UHF band Ch E21 to E27
283 else // if (freq < 862000000)
284 cp210 = 5; // UHF band ch E28 to E69
285
286//********************* BW select *******************************
287 if (freq_khz < 153000)
288 p4321 = 1; // BW selected for VHF low
289 else if (freq_khz < 470000)
290 p4321 = 2; // BW selected for VHF high E5 to E12
291 else // if (freq < 862000000)
292 p4321 = 4; // BW selection for UHF E21 to E69
293
294 pllbuf[0] = (tfreq >> 8) & 0xff;
295 pllbuf[1] = (tfreq >> 0) & 0xff;
296 pllbuf[2] = 0xff & ctrl1;
297 pllbuf[3] = (cp210 << 5) | (p4321);
298
299 return 0;
300}
301
302/*
303 * 7 6 5 4 3 2 1 0
304 * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
305 *
306 * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
307 * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
308 *
309 * Control byte 1 1 T/A=1 T2 T1 T0 R2 R1 R0
310 * 1 T/A=0 0 0 ATC AL2 AL1 AL0
311 *
312 * Control byte 2 CP2 CP1 CP0 BS5 BS4 BS3 BS2 BS1
313 *
314 * MA0/1 = programmable address bits
315 * R/~W = read/write bit (0 for writing)
316 * N14-0 = programmable LO frequency
317 *
318 * T/A = test AGC bit (0 = next 6 bits AGC setting,
319 * 1 = next 6 bits test and reference divider ratio settings)
320 * T2-0 = test bits
321 * R2-0 = reference divider ratio and programmable frequency step
322 * ATC = AGC current setting and time constant
323 * ATC = 0: AGC current = 220nA, AGC time constant = 2s
324 * ATC = 1: AGC current = 9uA, AGC time constant = 50ms
325 * AL2-0 = AGC take-over point bits
326 * CP2-0 = charge pump current
327 * BS5-1 = PMOS ports control bits;
328 * BSn = 0 corresponding port is off, high-impedance state (at power-on)
329 * BSn = 1 corresponding port is on
330 */
331static int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend *fe, u8 pllbuf[4])
332{
333 pllbuf[0] = 0x0b;
334 pllbuf[1] = 0xf5;
335 pllbuf[2] = 0x85;
336 pllbuf[3] = 0xab;
337 return 0;
338}
339
340static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameters *fep,u8 pllbuf[4])
341{
342 int tuner_frequency = 0;
343 u8 band, cp, filter;
344
345 // determine charge pump
346 tuner_frequency = fep->frequency + 36166000;
347 if (tuner_frequency < 87000000)
348 return -EINVAL;
349 else if (tuner_frequency < 130000000)
350 cp = 3;
351 else if (tuner_frequency < 160000000)
352 cp = 5;
353 else if (tuner_frequency < 200000000)
354 cp = 6;
355 else if (tuner_frequency < 290000000)
356 cp = 3;
357 else if (tuner_frequency < 420000000)
358 cp = 5;
359 else if (tuner_frequency < 480000000)
360 cp = 6;
361 else if (tuner_frequency < 620000000)
362 cp = 3;
363 else if (tuner_frequency < 830000000)
364 cp = 5;
365 else if (tuner_frequency < 895000000)
366 cp = 7;
367 else
368 return -EINVAL;
369
370 // determine band
371 if (fep->frequency < 49000000)
372 return -EINVAL;
373 else if (fep->frequency < 161000000)
374 band = 1;
375 else if (fep->frequency < 444000000)
376 band = 2;
377 else if (fep->frequency < 861000000)
378 band = 4;
379 else
380 return -EINVAL;
381
382 // setup PLL filter
383 switch (fep->u.ofdm.bandwidth) {
384 case BANDWIDTH_6_MHZ:
385 case BANDWIDTH_7_MHZ:
386 filter = 0;
387 break;
388 case BANDWIDTH_8_MHZ:
389 filter = 1;
390 break;
391 default:
392 return -EINVAL;
393 }
394
395 // calculate divisor
396 // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
397 tuner_frequency = (((fep->frequency / 1000) * 6) + 217496) / 1000;
398
399 // setup tuner buffer
400 pllbuf[0] = (tuner_frequency >> 8) & 0x7f;
401 pllbuf[1] = tuner_frequency & 0xff;
402 pllbuf[2] = 0xca;
403 pllbuf[3] = (cp << 5) | (filter << 3) | band;
404 return 0;
405}
406
407/*
408 * 7 6 5 4 3 2 1 0
409 * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
410 *
411 * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
412 * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
413 *
414 * Control byte 1 CP T2 T1 T0 RSA RSB OS
415 *
416 * Band Switch byte X X X P4 P3 P2 P1 P0
417 *
418 * Auxiliary byte ATC AL2 AL1 AL0 0 0 0 0
419 *
420 * Address: MA1 MA0 Address
421 * 0 0 c0
422 * 0 1 c2 (always valid)
423 * 1 0 c4
424 * 1 1 c6
425 */
426static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters* fep, u8 pllbuf[4])
427{
428 u32 div;
429 u8 p210, p3;
430
431#define TUNER_MUL 62500
432
433 div = (fep->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
434// div = ((fep->frequency/1000 + 36166) * 6) / 1000;
435
436 if (fep->frequency < 174500000)
437 p210 = 1; // not supported by the tdtp_e102p
438 else if (fep->frequency < 230000000) // VHF
439 p210 = 2;
440 else
441 p210 = 4;
442
443 if (fep->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
444 p3 = 0;
445 else
446 p3 = 1;
447
448 pllbuf[0] = (div >> 8) & 0x7f;
449 pllbuf[1] = div & 0xff;
450 pllbuf[2] = 0xce;
451// pllbuf[2] = 0xcc;
452 pllbuf[3] = (p3 << 3) | p210;
453
454 return 0;
455}
456
457static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend *fe)
458{
459 static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
460 static u8 mt352_reset[] = { 0x50, 0x80 };
461 static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
462 static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
463 static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
464
465 static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
466 static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
467 static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
468 static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
469 static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
470
471 static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
472 static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
473
474 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
475 udelay(2000);
476 mt352_write(fe, mt352_reset, sizeof(mt352_reset));
477 mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
478
479 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
480 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
481
482 mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
483 mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
484 mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
485 mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
486 mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
487
488 mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
489 mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
490
491 return 0;
492}
493
494static int dibusb_general_demod_init(struct dvb_frontend *fe)
495{
496 struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
497 switch (dib->dibdev->dev_cl->id) {
498 case UMT2_0:
499 return lg_tdtp_e102p_mt352_demod_init(fe);
500 default: /* other device classes do not have device specific demod inits */
501 break;
502 }
503 return 0;
504}
505
506static u8 dibusb_general_pll_addr(struct dvb_frontend *fe)
507{
508 struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
509 return dib->tuner->pll_addr;
510}
511
512static int dibusb_pll_i2c_helper(struct usb_dibusb *dib, u8 pll_buf[5], u8 buf[4])
513{
514 if (pll_buf == NULL) {
515 struct i2c_msg msg = {
516 .addr = dib->tuner->pll_addr,
517 .flags = 0,
518 .buf = buf,
519 .len = sizeof(buf)
520 };
521 if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1)
522 return -EIO;
523 msleep(1);
524 } else {
525 pll_buf[0] = dib->tuner->pll_addr << 1;
526 memcpy(&pll_buf[1],buf,4);
527 }
528
529 return 0;
530}
531
532static int dibusb_general_pll_init(struct dvb_frontend *fe,
533 u8 pll_buf[5])
534{
535 struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
536 u8 buf[4];
537 int ret=0;
538 switch (dib->tuner->id) {
539 case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
540 ret = panasonic_cofdm_env77h11d5_tda6650_init(fe,buf);
541 break;
542 default:
543 break;
544 }
545
546 if (ret)
547 return ret;
548
549 return dibusb_pll_i2c_helper(dib,pll_buf,buf);
550}
551
552static int dibusb_general_pll_set(struct dvb_frontend *fe,
553 struct dvb_frontend_parameters *fep, u8 pll_buf[5])
554{
555 struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
556 u8 buf[4];
557 int ret=0;
558
559 switch (dib->tuner->id) {
560 case DIBUSB_TUNER_CABLE_THOMSON:
561 ret = thomson_cable_eu_pll_set(fep, buf);
562 break;
563 case DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5:
564 ret = panasonic_cofdm_env57h1xd5_pll_set(fep, buf);
565 break;
566 case DIBUSB_TUNER_CABLE_LG_TDTP_E102P:
567 ret = lg_tdtp_e102p_tua6034(fep, buf);
568 break;
569 case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
570 ret = panasonic_cofdm_env77h11d5_tda6650_set(fep,buf);
571 break;
572 default:
573 warn("no pll programming routine found for tuner %d.\n",dib->tuner->id);
574 ret = -ENODEV;
575 break;
576 }
577
578 if (ret)
579 return ret;
580
581 return dibusb_pll_i2c_helper(dib,pll_buf,buf);
582}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c b/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
deleted file mode 100644
index 504ba47afd..0000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
+++ /dev/null
@@ -1,87 +0,0 @@
1/*
2 * dvb-dibusb-firmware.c is part of the driver for mobile USB Budget DVB-T devices
3 * based on reference design made by DiBcom (http://www.dibcom.fr/)
4 *
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
7 * see dvb-dibusb-core.c for more copyright details.
8 *
9 * This file contains functions for downloading the firmware to the device.
10 */
11#include "dvb-dibusb.h"
12
13#include <linux/firmware.h>
14#include <linux/usb.h>
15
16/*
17 * load a firmware packet to the device
18 */
19static int dibusb_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
20{
21 return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
22 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
23}
24
25int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev)
26{
27 const struct firmware *fw = NULL;
28 u16 addr;
29 u8 *b,*p;
30 int ret = 0,i;
31
32 if ((ret = request_firmware(&fw, dibdev->dev_cl->firmware, &udev->dev)) != 0) {
33 err("did not find the firmware file. (%s) "
34 "Please see linux/Documentation/dvb/ for more details on firmware-problems.",
35 dibdev->dev_cl->firmware);
36 return ret;
37 }
38
39 info("downloading firmware from file '%s'.",dibdev->dev_cl->firmware);
40
41 p = kmalloc(fw->size,GFP_KERNEL);
42 if (p != NULL) {
43 u8 reset;
44 /*
45 * you cannot use the fw->data as buffer for
46 * usb_control_msg, a new buffer has to be
47 * created
48 */
49 memcpy(p,fw->data,fw->size);
50
51 /* stop the CPU */
52 reset = 1;
53 if ((ret = dibusb_writemem(udev,dibdev->dev_cl->usb_ctrl->cpu_cs_register,&reset,1)) != 1)
54 err("could not stop the USB controller CPU.");
55 for(i = 0; p[i+3] == 0 && i < fw->size; ) {
56 b = (u8 *) &p[i];
57 addr = *((u16 *) &b[1]);
58
59 ret = dibusb_writemem(udev,addr,&b[4],b[0]);
60
61 if (ret != b[0]) {
62 err("error while transferring firmware "
63 "(transferred size: %d, block size: %d)",
64 ret,b[0]);
65 ret = -EINVAL;
66 break;
67 }
68 i += 5 + b[0];
69 }
70 /* length in ret */
71 if (ret > 0)
72 ret = 0;
73 /* restart the CPU */
74 reset = 0;
75 if (ret || dibusb_writemem(udev,dibdev->dev_cl->usb_ctrl->cpu_cs_register,&reset,1) != 1) {
76 err("could not restart the USB controller CPU.");
77 ret = -EINVAL;
78 }
79
80 kfree(p);
81 } else {
82 ret = -ENOMEM;
83 }
84 release_firmware(fw);
85
86 return ret;
87}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c b/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
deleted file mode 100644
index 9dc8b15517..0000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
+++ /dev/null
@@ -1,316 +0,0 @@
1/*
2 * dvb-dibusb-remote.c is part of the driver for mobile USB Budget DVB-T devices
3 * based on reference design made by DiBcom (http://www.dibcom.fr/)
4 *
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
7 * see dvb-dibusb-core.c for more copyright details.
8 *
9 * This file contains functions for handling the event device on the software
10 * side and the remote control on the hardware side.
11 */
12#include "dvb-dibusb.h"
13
14/* Table to map raw key codes to key events. This should not be hard-wired
15 into the kernel. */
16static const struct { u8 c0, c1, c2; uint32_t key; } nec_rc_keys [] =
17{
18 /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
19 { 0x00, 0xff, 0x16, KEY_POWER },
20 { 0x00, 0xff, 0x10, KEY_MUTE },
21 { 0x00, 0xff, 0x03, KEY_1 },
22 { 0x00, 0xff, 0x01, KEY_2 },
23 { 0x00, 0xff, 0x06, KEY_3 },
24 { 0x00, 0xff, 0x09, KEY_4 },
25 { 0x00, 0xff, 0x1d, KEY_5 },
26 { 0x00, 0xff, 0x1f, KEY_6 },
27 { 0x00, 0xff, 0x0d, KEY_7 },
28 { 0x00, 0xff, 0x19, KEY_8 },
29 { 0x00, 0xff, 0x1b, KEY_9 },
30 { 0x00, 0xff, 0x15, KEY_0 },
31 { 0x00, 0xff, 0x05, KEY_CHANNELUP },
32 { 0x00, 0xff, 0x02, KEY_CHANNELDOWN },
33 { 0x00, 0xff, 0x1e, KEY_VOLUMEUP },
34 { 0x00, 0xff, 0x0a, KEY_VOLUMEDOWN },
35 { 0x00, 0xff, 0x11, KEY_RECORD },
36 { 0x00, 0xff, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
37 { 0x00, 0xff, 0x14, KEY_PLAY },
38 { 0x00, 0xff, 0x1a, KEY_STOP },
39 { 0x00, 0xff, 0x40, KEY_REWIND },
40 { 0x00, 0xff, 0x12, KEY_FASTFORWARD },
41 { 0x00, 0xff, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
42 { 0x00, 0xff, 0x4c, KEY_PAUSE },
43 { 0x00, 0xff, 0x4d, KEY_SCREEN }, /* Full screen mode. */
44 { 0x00, 0xff, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
45 /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
46 { 0x00, 0xff, 0x0c, KEY_CANCEL }, /* Cancel */
47 { 0x00, 0xff, 0x1c, KEY_EPG }, /* EPG */
48 { 0x00, 0xff, 0x00, KEY_TAB }, /* Tab */
49 { 0x00, 0xff, 0x48, KEY_INFO }, /* Preview */
50 { 0x00, 0xff, 0x04, KEY_LIST }, /* RecordList */
51 { 0x00, 0xff, 0x0f, KEY_TEXT }, /* Teletext */
52 /* Key codes for the KWorld/ADSTech/JetWay remote. */
53 { 0x86, 0x6b, 0x12, KEY_POWER },
54 { 0x86, 0x6b, 0x0f, KEY_SELECT }, /* source */
55 { 0x86, 0x6b, 0x0c, KEY_UNKNOWN }, /* scan */
56 { 0x86, 0x6b, 0x0b, KEY_EPG },
57 { 0x86, 0x6b, 0x10, KEY_MUTE },
58 { 0x86, 0x6b, 0x01, KEY_1 },
59 { 0x86, 0x6b, 0x02, KEY_2 },
60 { 0x86, 0x6b, 0x03, KEY_3 },
61 { 0x86, 0x6b, 0x04, KEY_4 },
62 { 0x86, 0x6b, 0x05, KEY_5 },
63 { 0x86, 0x6b, 0x06, KEY_6 },
64 { 0x86, 0x6b, 0x07, KEY_7 },
65 { 0x86, 0x6b, 0x08, KEY_8 },
66 { 0x86, 0x6b, 0x09, KEY_9 },
67 { 0x86, 0x6b, 0x0a, KEY_0 },
68 { 0x86, 0x6b, 0x18, KEY_ZOOM },
69 { 0x86, 0x6b, 0x1c, KEY_UNKNOWN }, /* preview */
70 { 0x86, 0x6b, 0x13, KEY_UNKNOWN }, /* snap */
71 { 0x86, 0x6b, 0x00, KEY_UNDO },
72 { 0x86, 0x6b, 0x1d, KEY_RECORD },
73 { 0x86, 0x6b, 0x0d, KEY_STOP },
74 { 0x86, 0x6b, 0x0e, KEY_PAUSE },
75 { 0x86, 0x6b, 0x16, KEY_PLAY },
76 { 0x86, 0x6b, 0x11, KEY_BACK },
77 { 0x86, 0x6b, 0x19, KEY_FORWARD },
78 { 0x86, 0x6b, 0x14, KEY_UNKNOWN }, /* pip */
79 { 0x86, 0x6b, 0x15, KEY_ESC },
80 { 0x86, 0x6b, 0x1a, KEY_UP },
81 { 0x86, 0x6b, 0x1e, KEY_DOWN },
82 { 0x86, 0x6b, 0x1f, KEY_LEFT },
83 { 0x86, 0x6b, 0x1b, KEY_RIGHT },
84};
85
86/* Hauppauge NOVA-T USB2 keys */
87static const struct { u16 raw; uint32_t key; } haupp_rc_keys [] = {
88 { 0xddf, KEY_GOTO },
89 { 0xdef, KEY_POWER },
90 { 0xce7, KEY_TV },
91 { 0xcc7, KEY_VIDEO },
92 { 0xccf, KEY_AUDIO },
93 { 0xcd7, KEY_MEDIA },
94 { 0xcdf, KEY_EPG },
95 { 0xca7, KEY_UP },
96 { 0xc67, KEY_RADIO },
97 { 0xcb7, KEY_LEFT },
98 { 0xd2f, KEY_OK },
99 { 0xcbf, KEY_RIGHT },
100 { 0xcff, KEY_BACK },
101 { 0xcaf, KEY_DOWN },
102 { 0xc6f, KEY_MENU },
103 { 0xc87, KEY_VOLUMEUP },
104 { 0xc8f, KEY_VOLUMEDOWN },
105 { 0xc97, KEY_CHANNEL },
106 { 0xc7f, KEY_MUTE },
107 { 0xd07, KEY_CHANNELUP },
108 { 0xd0f, KEY_CHANNELDOWN },
109 { 0xdbf, KEY_RECORD },
110 { 0xdb7, KEY_STOP },
111 { 0xd97, KEY_REWIND },
112 { 0xdaf, KEY_PLAY },
113 { 0xda7, KEY_FASTFORWARD },
114 { 0xd27, KEY_LAST }, /* Skip backwards */
115 { 0xd87, KEY_PAUSE },
116 { 0xcf7, KEY_NEXT },
117 { 0xc07, KEY_0 },
118 { 0xc0f, KEY_1 },
119 { 0xc17, KEY_2 },
120 { 0xc1f, KEY_3 },
121 { 0xc27, KEY_4 },
122 { 0xc2f, KEY_5 },
123 { 0xc37, KEY_6 },
124 { 0xc3f, KEY_7 },
125 { 0xc47, KEY_8 },
126 { 0xc4f, KEY_9 },
127 { 0xc57, KEY_KPASTERISK },
128 { 0xc77, KEY_GRAVE }, /* # */
129 { 0xc5f, KEY_RED },
130 { 0xd77, KEY_GREEN },
131 { 0xdc7, KEY_YELLOW },
132 { 0xd4f, KEY_BLUE},
133};
134
135static int dibusb_key2event_nec(struct usb_dibusb *dib,u8 rb[5])
136{
137 int i;
138 switch (rb[0]) {
139 case DIBUSB_RC_NEC_KEY_PRESSED:
140 /* rb[1-3] is the actual key, rb[4] is a checksum */
141 deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
142 rb[1], rb[2], rb[3], rb[4]);
143
144 if ((0xff - rb[3]) != rb[4]) {
145 deb_rc("remote control checksum failed.\n");
146 break;
147 }
148
149 /* See if we can match the raw key code. */
150 for (i = 0; i < sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++) {
151 if (nec_rc_keys[i].c0 == rb[1] &&
152 nec_rc_keys[i].c1 == rb[2] &&
153 nec_rc_keys[i].c2 == rb[3]) {
154
155 dib->last_event = nec_rc_keys[i].key;
156 return 1;
157 }
158 }
159 break;
160 case DIBUSB_RC_NEC_KEY_REPEATED:
161 /* rb[1]..rb[4] are always zero.*/
162 /* Repeats often seem to occur so for the moment just ignore this. */
163 return 0;
164 case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */
165 default:
166 break;
167 }
168 return -1;
169}
170
171static int dibusb_key2event_hauppauge(struct usb_dibusb *dib,u8 rb[4])
172{
173 u16 raw;
174 int i,state;
175 switch (rb[0]) {
176 case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
177 raw = ((rb[1] & 0x0f) << 8) | rb[2];
178
179 state = !!(rb[1] & 0x40);
180
181 deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to %04x state: %d\n",rb[1],rb[2],rb[3],raw,state);
182 for (i = 0; i < sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++) {
183 if (haupp_rc_keys[i].raw == raw) {
184 if (dib->last_event == haupp_rc_keys[i].key &&
185 dib->last_state == state) {
186 deb_rc("key repeat\n");
187 return 0;
188 } else {
189 dib->last_event = haupp_rc_keys[i].key;
190 dib->last_state = state;
191 return 1;
192 }
193 }
194 }
195
196 break;
197 case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
198 default:
199 break;
200 }
201 return -1;
202}
203
204/*
205 * Read the remote control and feed the appropriate event.
206 * NEC protocol is used for remote controls
207 */
208static int dibusb_read_remote_control(struct usb_dibusb *dib)
209{
210 u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5];
211 int ret,event = 0;
212
213 if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5)))
214 return ret;
215
216 switch (dib->dibdev->dev_cl->remote_type) {
217 case DIBUSB_RC_NEC_PROTOCOL:
218 event = dibusb_key2event_nec(dib,rb);
219 break;
220 case DIBUSB_RC_HAUPPAUGE_PROTO:
221 event = dibusb_key2event_hauppauge(dib,rb);
222 default:
223 break;
224 }
225
226 /* key repeat */
227 if (event == 0)
228 if (++dib->repeat_key_count < dib->rc_key_repeat_count) {
229 deb_rc("key repeat dropped. (%d)\n",dib->repeat_key_count);
230 event = -1; /* skip this key repeat */
231 }
232
233 if (event == 1 || event == 0) {
234 deb_rc("Translated key 0x%04x\n",event);
235
236 /* Signal down and up events for this key. */
237 input_report_key(&dib->rc_input_dev, dib->last_event, 1);
238 input_report_key(&dib->rc_input_dev, dib->last_event, 0);
239 input_sync(&dib->rc_input_dev);
240
241 if (event == 1)
242 dib->repeat_key_count = 0;
243 }
244 return 0;
245}
246
247/* Remote-control poll function - called every dib->rc_query_interval ms to see
248 whether the remote control has received anything. */
249static void dibusb_remote_query(void *data)
250{
251 struct usb_dibusb *dib = (struct usb_dibusb *) data;
252 /* TODO: need a lock here. We can simply skip checking for the remote control
253 if we're busy. */
254 dibusb_read_remote_control(dib);
255 schedule_delayed_work(&dib->rc_query_work,
256 msecs_to_jiffies(dib->rc_query_interval));
257}
258
259int dibusb_remote_init(struct usb_dibusb *dib)
260{
261 int i;
262
263 if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO)
264 return 0;
265
266 /* Initialise the remote-control structures.*/
267 init_input_dev(&dib->rc_input_dev);
268
269 dib->rc_input_dev.evbit[0] = BIT(EV_KEY);
270 dib->rc_input_dev.keycodesize = sizeof(unsigned char);
271 dib->rc_input_dev.keycodemax = KEY_MAX;
272 dib->rc_input_dev.name = DRIVER_DESC " remote control";
273
274 switch (dib->dibdev->dev_cl->remote_type) {
275 case DIBUSB_RC_NEC_PROTOCOL:
276 for (i=0; i<sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++)
277 set_bit(nec_rc_keys[i].key, dib->rc_input_dev.keybit);
278 break;
279 case DIBUSB_RC_HAUPPAUGE_PROTO:
280 for (i=0; i<sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++)
281 set_bit(haupp_rc_keys[i].key, dib->rc_input_dev.keybit);
282 break;
283 default:
284 break;
285 }
286
287
288 input_register_device(&dib->rc_input_dev);
289
290 INIT_WORK(&dib->rc_query_work, dibusb_remote_query, dib);
291
292 /* Start the remote-control polling. */
293 if (dib->rc_query_interval < 40)
294 dib->rc_query_interval = 100; /* default */
295
296 info("schedule remote query interval to %d msecs.",dib->rc_query_interval);
297 schedule_delayed_work(&dib->rc_query_work,msecs_to_jiffies(dib->rc_query_interval));
298
299 dib->init_state |= DIBUSB_STATE_REMOTE;
300
301 return 0;
302}
303
304int dibusb_remote_exit(struct usb_dibusb *dib)
305{
306 if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO)
307 return 0;
308
309 if (dib->init_state & DIBUSB_STATE_REMOTE) {
310 cancel_delayed_work(&dib->rc_query_work);
311 flush_scheduled_work();
312 input_unregister_device(&dib->rc_input_dev);
313 }
314 dib->init_state &= ~DIBUSB_STATE_REMOTE;
315 return 0;
316}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c b/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
deleted file mode 100644
index 642f0596a5..0000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
+++ /dev/null
@@ -1,303 +0,0 @@
1/*
2 * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices
3 * based on reference design made by DiBcom (http://www.dibcom.fr/)
4 *
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
7 * see dvb-dibusb-core.c for more copyright details.
8 *
9 * This file contains functions for initializing and handling the
10 * usb specific stuff.
11 */
12#include "dvb-dibusb.h"
13
14#include <linux/version.h>
15#include <linux/pci.h>
16
17int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
18 u16 rlen)
19{
20 int actlen,ret = -ENOMEM;
21
22 if (wbuf == NULL || wlen == 0)
23 return -EINVAL;
24
25 if ((ret = down_interruptible(&dib->usb_sem)))
26 return ret;
27
28 debug_dump(wbuf,wlen);
29
30 ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,
31 dib->dibdev->dev_cl->pipe_cmd), wbuf,wlen,&actlen,
32 DIBUSB_I2C_TIMEOUT);
33
34 if (ret)
35 err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
36 else
37 ret = actlen != wlen ? -1 : 0;
38
39 /* an answer is expected, and no error before */
40 if (!ret && rbuf && rlen) {
41 ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev,
42 dib->dibdev->dev_cl->pipe_cmd),rbuf,rlen,&actlen,
43 DIBUSB_I2C_TIMEOUT);
44
45 if (ret)
46 err("recv bulk message failed: %d",ret);
47 else {
48 deb_alot("rlen: %d\n",rlen);
49 debug_dump(rbuf,actlen);
50 }
51 }
52
53 up(&dib->usb_sem);
54 return ret;
55}
56
57/*
58 * Cypress controls
59 */
60int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
61{
62 return dibusb_readwrite_usb(dib,buf,len,NULL,0);
63}
64
65#if 0
66/*
67 * #if 0'ing the following functions as they are not in use _now_,
68 * but probably will be sometime.
69 */
70/*
71 * do not use this, just a workaround for a bug,
72 * which will hopefully never occur :).
73 */
74int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
75{
76 u8 b[1] = { DIBUSB_REQ_INTR_READ };
77 return dibusb_write_usb(dib,b,1);
78}
79#endif
80
81/*
82 * ioctl for the firmware
83 */
84static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
85{
86 u8 b[34];
87 int size = plen > 32 ? 32 : plen;
88 memset(b,0,34);
89 b[0] = DIBUSB_REQ_SET_IOCTL;
90 b[1] = cmd;
91
92 if (size > 0)
93 memcpy(&b[2],param,size);
94
95 return dibusb_write_usb(dib,b,34); //2+size);
96}
97
98/*
99 * ioctl for power control
100 */
101int dibusb_hw_wakeup(struct dvb_frontend *fe)
102{
103 struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
104 u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
105 deb_info("dibusb-device is getting up.\n");
106
107 switch (dib->dibdev->dev_cl->id) {
108 case DTT200U:
109 break;
110 default:
111 dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
112 break;
113 }
114
115 if (dib->fe_init)
116 return dib->fe_init(fe);
117
118 return 0;
119}
120
121int dibusb_hw_sleep(struct dvb_frontend *fe)
122{
123 struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
124 u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
125 deb_info("dibusb-device is going to bed.\n");
126 /* workaround, something is wrong, when dibusb 1.1 device are going to bed too late */
127 switch (dib->dibdev->dev_cl->id) {
128 case DIBUSB1_1:
129 case NOVAT_USB2:
130 case DTT200U:
131 break;
132 default:
133 dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
134 break;
135 }
136 if (dib->fe_sleep)
137 return dib->fe_sleep(fe);
138
139 return 0;
140}
141
142int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode)
143{
144 u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode };
145 return dibusb_readwrite_usb(dib,b,2,NULL,0);
146}
147
148static int dibusb_urb_kill(struct usb_dibusb *dib)
149{
150 int i;
151deb_info("trying to kill urbs\n");
152 if (dib->init_state & DIBUSB_STATE_URB_SUBMIT) {
153 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
154 deb_info("killing URB no. %d.\n",i);
155
156 /* stop the URB */
157 usb_kill_urb(dib->urb_list[i]);
158 }
159 } else
160 deb_info(" URBs not killed.\n");
161 dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT;
162 return 0;
163}
164
165static int dibusb_urb_submit(struct usb_dibusb *dib)
166{
167 int i,ret;
168 if (dib->init_state & DIBUSB_STATE_URB_INIT) {
169 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
170 deb_info("submitting URB no. %d\n",i);
171 if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {
172 err("could not submit buffer urb no. %d - get them all back\n",i);
173 dibusb_urb_kill(dib);
174 return ret;
175 }
176 dib->init_state |= DIBUSB_STATE_URB_SUBMIT;
177 }
178 }
179 return 0;
180}
181
182int dibusb_streaming(struct usb_dibusb *dib,int onoff)
183{
184 if (onoff)
185 dibusb_urb_submit(dib);
186 else
187 dibusb_urb_kill(dib);
188
189 switch (dib->dibdev->dev_cl->id) {
190 case DIBUSB2_0:
191 case DIBUSB2_0B:
192 case NOVAT_USB2:
193 case UMT2_0:
194 if (onoff)
195 return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);
196 else
197 return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);
198 break;
199 default:
200 break;
201 }
202 return 0;
203}
204
205int dibusb_urb_init(struct usb_dibusb *dib)
206{
207 int i,bufsize,def_pid_parse = 1;
208
209 /*
210 * when reloading the driver w/o replugging the device
211 * a timeout occures, this helps
212 */
213 usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
214 usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
215 usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data));
216
217 /* allocate the array for the data transfer URBs */
218 dib->urb_list = kmalloc(dib->dibdev->dev_cl->urb_count*sizeof(struct urb *),GFP_KERNEL);
219 if (dib->urb_list == NULL)
220 return -ENOMEM;
221 memset(dib->urb_list,0,dib->dibdev->dev_cl->urb_count*sizeof(struct urb *));
222
223 dib->init_state |= DIBUSB_STATE_URB_LIST;
224
225 bufsize = dib->dibdev->dev_cl->urb_count*dib->dibdev->dev_cl->urb_buffer_size;
226 deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
227 /* allocate the actual buffer for the URBs */
228 if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) {
229 deb_info("not enough memory.\n");
230 return -ENOMEM;
231 }
232 deb_info("allocation complete\n");
233 memset(dib->buffer,0,bufsize);
234
235 dib->init_state |= DIBUSB_STATE_URB_BUF;
236
237 /* allocate and submit the URBs */
238 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
239 if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
240 return -ENOMEM;
241 }
242
243 usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
244 usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data),
245 &dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size],
246 dib->dibdev->dev_cl->urb_buffer_size,
247 dibusb_urb_complete, dib);
248
249 dib->urb_list[i]->transfer_flags = 0;
250
251 dib->init_state |= DIBUSB_STATE_URB_INIT;
252 }
253
254 /* dib->pid_parse here contains the value of the module parameter */
255 /* decide if pid parsing can be deactivated:
256 * is possible (by device type) and wanted (by user)
257 */
258 switch (dib->dibdev->dev_cl->id) {
259 case DIBUSB2_0:
260 case DIBUSB2_0B:
261 if (dib->udev->speed == USB_SPEED_HIGH && !dib->pid_parse) {
262 def_pid_parse = 0;
263 info("running at HIGH speed, will deliver the complete TS.");
264 } else
265 info("will use pid_parsing.");
266 break;
267 default:
268 break;
269 }
270 /* from here on it contains the device and user decision */
271 dib->pid_parse = def_pid_parse;
272
273 return 0;
274}
275
276int dibusb_urb_exit(struct usb_dibusb *dib)
277{
278 int i;
279
280 dibusb_urb_kill(dib);
281
282 if (dib->init_state & DIBUSB_STATE_URB_LIST) {
283 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
284 if (dib->urb_list[i] != NULL) {
285 deb_info("freeing URB no. %d.\n",i);
286 /* free the URBs */
287 usb_free_urb(dib->urb_list[i]);
288 }
289 }
290 /* free the urb array */
291 kfree(dib->urb_list);
292 dib->init_state &= ~DIBUSB_STATE_URB_LIST;
293 }
294
295 if (dib->init_state & DIBUSB_STATE_URB_BUF)
296 pci_free_consistent(NULL,
297 dib->dibdev->dev_cl->urb_buffer_size*dib->dibdev->dev_cl->urb_count,
298 dib->buffer,dib->dma_handle);
299
300 dib->init_state &= ~DIBUSB_STATE_URB_BUF;
301 dib->init_state &= ~DIBUSB_STATE_URB_INIT;
302 return 0;
303}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb.h b/drivers/media/dvb/dibusb/dvb-dibusb.h
deleted file mode 100644
index c965b64fb1..0000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb.h
+++ /dev/null
@@ -1,327 +0,0 @@
1/*
2 * dvb-dibusb.h
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 *
10 * for more information see dvb-dibusb-core.c .
11 */
12#ifndef __DVB_DIBUSB_H__
13#define __DVB_DIBUSB_H__
14
15#include <linux/input.h>
16#include <linux/config.h>
17#include <linux/usb.h>
18
19#include "dvb_frontend.h"
20#include "dvb_demux.h"
21#include "dvb_net.h"
22#include "dmxdev.h"
23
24#include "dib3000.h"
25#include "mt352.h"
26
27/* debug */
28#ifdef CONFIG_DVB_DIBCOM_DEBUG
29#define dprintk(level,args...) \
30 do { if ((dvb_dibusb_debug & level)) { printk(args); } } while (0)
31
32#define debug_dump(b,l) {\
33 int i; \
34 for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
35 deb_xfer("\n");\
36}
37
38#else
39#define dprintk(args...)
40#define debug_dump(b,l)
41#endif
42
43extern int dvb_dibusb_debug;
44
45/* Version information */
46#define DRIVER_VERSION "0.3"
47#define DRIVER_DESC "DiBcom based USB Budget DVB-T device"
48#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
49
50#define deb_info(args...) dprintk(0x01,args)
51#define deb_xfer(args...) dprintk(0x02,args)
52#define deb_alot(args...) dprintk(0x04,args)
53#define deb_ts(args...) dprintk(0x08,args)
54#define deb_err(args...) dprintk(0x10,args)
55#define deb_rc(args...) dprintk(0x20,args)
56
57/* generic log methods - taken from usb.h */
58#undef err
59#define err(format, arg...) printk(KERN_ERR "dvb-dibusb: " format "\n" , ## arg)
60#undef info
61#define info(format, arg...) printk(KERN_INFO "dvb-dibusb: " format "\n" , ## arg)
62#undef warn
63#define warn(format, arg...) printk(KERN_WARNING "dvb-dibusb: " format "\n" , ## arg)
64
65struct dibusb_usb_controller {
66 const char *name; /* name of the usb controller */
67 u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */
68};
69
70typedef enum {
71 DIBUSB1_1 = 0,
72 DIBUSB1_1_AN2235,
73 DIBUSB2_0,
74 UMT2_0,
75 DIBUSB2_0B,
76 NOVAT_USB2,
77 DTT200U,
78} dibusb_class_t;
79
80typedef enum {
81 DIBUSB_TUNER_CABLE_THOMSON = 0,
82 DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5,
83 DIBUSB_TUNER_CABLE_LG_TDTP_E102P,
84 DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5,
85} dibusb_tuner_t;
86
87typedef enum {
88 DIBUSB_DIB3000MB = 0,
89 DIBUSB_DIB3000MC,
90 DIBUSB_MT352,
91 DTT200U_FE,
92} dibusb_demodulator_t;
93
94typedef enum {
95 DIBUSB_RC_NO = 0,
96 DIBUSB_RC_NEC_PROTOCOL,
97 DIBUSB_RC_HAUPPAUGE_PROTO,
98} dibusb_remote_t;
99
100struct dibusb_tuner {
101 dibusb_tuner_t id;
102
103 u8 pll_addr; /* tuner i2c address */
104};
105extern struct dibusb_tuner dibusb_tuner[];
106
107#define DIBUSB_POSSIBLE_I2C_ADDR_NUM 4
108struct dibusb_demod {
109 dibusb_demodulator_t id;
110
111 int pid_filter_count; /* counter of the internal pid_filter */
112 u8 i2c_addrs[DIBUSB_POSSIBLE_I2C_ADDR_NUM]; /* list of possible i2c addresses of the demod */
113};
114
115#define DIBUSB_MAX_TUNER_NUM 2
116struct dibusb_device_class {
117 dibusb_class_t id;
118
119 const struct dibusb_usb_controller *usb_ctrl; /* usb controller */
120 const char *firmware; /* valid firmware filenames */
121
122 int pipe_cmd; /* command pipe (read/write) */
123 int pipe_data; /* data pipe */
124
125 int urb_count; /* number of data URBs to be submitted */
126 int urb_buffer_size; /* the size of the buffer for each URB */
127
128 dibusb_remote_t remote_type; /* does this device have a ir-receiver */
129
130 struct dibusb_demod *demod; /* which demodulator is mount */
131 struct dibusb_tuner *tuner; /* which tuner can be found here */
132};
133
134#define DIBUSB_ID_MAX_NUM 15
135struct dibusb_usb_device {
136 const char *name; /* real name of the box */
137 struct dibusb_device_class *dev_cl; /* which dibusb_device_class is this device part of */
138
139 struct usb_device_id *cold_ids[DIBUSB_ID_MAX_NUM]; /* list of USB ids when this device is at pre firmware state */
140 struct usb_device_id *warm_ids[DIBUSB_ID_MAX_NUM]; /* list of USB ids when this device is at post firmware state */
141};
142
143/* a PID for the pid_filter list, when in use */
144struct dibusb_pid
145{
146 int index;
147 u16 pid;
148 int active;
149};
150
151struct usb_dibusb {
152 /* usb */
153 struct usb_device * udev;
154
155 struct dibusb_usb_device * dibdev;
156
157#define DIBUSB_STATE_INIT 0x000
158#define DIBUSB_STATE_URB_LIST 0x001
159#define DIBUSB_STATE_URB_BUF 0x002
160#define DIBUSB_STATE_URB_INIT 0x004
161#define DIBUSB_STATE_DVB 0x008
162#define DIBUSB_STATE_I2C 0x010
163#define DIBUSB_STATE_REMOTE 0x020
164#define DIBUSB_STATE_URB_SUBMIT 0x040
165 int init_state;
166
167 int feedcount;
168 struct dib_fe_xfer_ops xfer_ops;
169
170 struct dibusb_tuner *tuner;
171
172 struct urb **urb_list;
173 u8 *buffer;
174 dma_addr_t dma_handle;
175
176 /* I2C */
177 struct i2c_adapter i2c_adap;
178
179 /* locking */
180 struct semaphore usb_sem;
181 struct semaphore i2c_sem;
182
183 /* dvb */
184 struct dvb_adapter adapter;
185 struct dmxdev dmxdev;
186 struct dvb_demux demux;
187 struct dvb_net dvb_net;
188 struct dvb_frontend* fe;
189
190 int (*fe_sleep) (struct dvb_frontend *);
191 int (*fe_init) (struct dvb_frontend *);
192
193 /* remote control */
194 struct input_dev rc_input_dev;
195 struct work_struct rc_query_work;
196 int last_event;
197 int last_state; /* for Hauppauge RC protocol */
198 int repeat_key_count;
199 int rc_key_repeat_count; /* module parameter */
200
201 /* module parameters */
202 int pid_parse;
203 int rc_query_interval;
204};
205
206/* commonly used functions in the separated files */
207
208/* dvb-dibusb-firmware.c */
209int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev);
210
211/* dvb-dibusb-remote.c */
212int dibusb_remote_exit(struct usb_dibusb *dib);
213int dibusb_remote_init(struct usb_dibusb *dib);
214
215/* dvb-dibusb-fe-i2c.c */
216int dibusb_fe_init(struct usb_dibusb* dib);
217int dibusb_fe_exit(struct usb_dibusb *dib);
218int dibusb_i2c_init(struct usb_dibusb *dib);
219int dibusb_i2c_exit(struct usb_dibusb *dib);
220
221/* dvb-dibusb-dvb.c */
222void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs);
223int dibusb_dvb_init(struct usb_dibusb *dib);
224int dibusb_dvb_exit(struct usb_dibusb *dib);
225
226/* dvb-dibusb-usb.c */
227int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
228 u16 rlen);
229int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len);
230
231int dibusb_hw_wakeup(struct dvb_frontend *);
232int dibusb_hw_sleep(struct dvb_frontend *);
233int dibusb_set_streaming_mode(struct usb_dibusb *,u8);
234int dibusb_streaming(struct usb_dibusb *,int);
235
236int dibusb_urb_init(struct usb_dibusb *);
237int dibusb_urb_exit(struct usb_dibusb *);
238
239/* dvb-fe-dtt200u.c */
240struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *,struct dib_fe_xfer_ops *);
241
242/* i2c and transfer stuff */
243#define DIBUSB_I2C_TIMEOUT 5000
244
245/*
246 * protocol of all dibusb related devices
247 */
248
249/*
250 * bulk msg to/from endpoint 0x01
251 *
252 * general structure:
253 * request_byte parameter_bytes
254 */
255
256#define DIBUSB_REQ_START_READ 0x00
257#define DIBUSB_REQ_START_DEMOD 0x01
258
259/*
260 * i2c read
261 * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
262 * bulk read: byte_buffer (length_word bytes)
263 */
264#define DIBUSB_REQ_I2C_READ 0x02
265
266/*
267 * i2c write
268 * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
269 */
270#define DIBUSB_REQ_I2C_WRITE 0x03
271
272/*
273 * polling the value of the remote control
274 * bulk write: 0x04
275 * bulk read: byte_buffer (5 bytes)
276 *
277 * first byte of byte_buffer shows the status (0x00, 0x01, 0x02)
278 */
279#define DIBUSB_REQ_POLL_REMOTE 0x04
280
281#define DIBUSB_RC_NEC_EMPTY 0x00
282#define DIBUSB_RC_NEC_KEY_PRESSED 0x01
283#define DIBUSB_RC_NEC_KEY_REPEATED 0x02
284
285/* additional status values for Hauppauge Remote Control Protocol */
286#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01
287#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03
288
289/* streaming mode:
290 * bulk write: 0x05 mode_byte
291 *
292 * mode_byte is mostly 0x00
293 */
294#define DIBUSB_REQ_SET_STREAMING_MODE 0x05
295
296/* interrupt the internal read loop, when blocking */
297#define DIBUSB_REQ_INTR_READ 0x06
298
299/* io control
300 * 0x07 cmd_byte param_bytes
301 *
302 * param_bytes can be up to 32 bytes
303 *
304 * cmd_byte function parameter name
305 * 0x00 power mode
306 * 0x00 sleep
307 * 0x01 wakeup
308 *
309 * 0x01 enable streaming
310 * 0x02 disable streaming
311 *
312 *
313 */
314#define DIBUSB_REQ_SET_IOCTL 0x07
315
316/* IOCTL commands */
317
318/* change the power mode in firmware */
319#define DIBUSB_IOCTL_CMD_POWER_MODE 0x00
320#define DIBUSB_IOCTL_POWER_SLEEP 0x00
321#define DIBUSB_IOCTL_POWER_WAKEUP 0x01
322
323/* modify streaming of the FX2 */
324#define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01
325#define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02
326
327#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index d19301d90a..d6b7a9de47 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -35,6 +35,7 @@
35#include <linux/moduleparam.h> 35#include <linux/moduleparam.h>
36#include <linux/list.h> 36#include <linux/list.h>
37#include <linux/suspend.h> 37#include <linux/suspend.h>
38#include <linux/jiffies.h>
38#include <asm/processor.h> 39#include <asm/processor.h>
39#include <asm/semaphore.h> 40#include <asm/semaphore.h>
40 41
@@ -327,7 +328,8 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
327 return 1; 328 return 1;
328 329
329 if (fepriv->dvbdev->writers == 1) 330 if (fepriv->dvbdev->writers == 1)
330 if (jiffies - fepriv->release_jiffies > dvb_shutdown_timeout * HZ) 331 if (time_after(jiffies, fepriv->release_jiffies +
332 dvb_shutdown_timeout * HZ))
331 return 1; 333 return 1;
332 334
333 return 0; 335 return 0;
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
new file mode 100644
index 0000000000..8aa32f6e44
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -0,0 +1,99 @@
1config DVB_USB
2 tristate "Support for various USB DVB devices"
3 depends on DVB_CORE && USB
4 select FW_LOADER
5 help
6 By enabling this you will be able to choose the various USB 1.1 and
7 USB2.0 DVB devices.
8
9 Almost every USB device needs a firmware, please look into
10 <file:Documentation/dvb/README.dvb-usb>
11
12 Say Y if you own an USB DVB device.
13
14config DVB_USB_DEBUG
15 bool "Enable extended debug support for all DVB-USB devices"
16 depends on DVB_USB
17 help
18 Say Y if you want to enable debuging. See modinfo dvb-usb (and the
19 appropriate drivers) for debug levels.
20
21config DVB_USB_A800
22 tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
23 depends on DVB_USB
24 help
25 Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
26
27config DVB_USB_DIBUSB_MB
28 tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
29 depends on DVB_USB
30 help
31 Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
32 DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
33
34 Devices supported by this driver:
35 TwinhanDTV USB-Ter (VP7041)
36 TwinhanDTV Magic Box (VP7041e)
37 KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
38 Hama DVB-T USB1.1-Box
39 DiBcom USB1.1 reference devices (non-public)
40 Ultima Electronic/Artec T1 USB TVBOX
41 Compro Videomate DVB-U2000 - DVB-T USB
42 Grandtec DVB-T USB
43 Avermedia AverTV DVBT USB1.1
44 Artec T1 USB1.1 boxes
45
46 The VP7041 seems to be identical to "CTS Portable" (Chinese
47 Television System).
48
49 Say Y if you own such a device and want to use it. You should build it as
50 a module.
51
52config DVB_USB_DIBUSB_MC
53 tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
54 depends on DVB_USB
55 help
56 Support for 2.0 DVB-T receivers based on reference designs made by
57 DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
58
59 Devices supported by this driver:
60 DiBcom USB2.0 reference devices (non-public)
61 Artec T1 USB2.0 boxes
62
63 Say Y if you own such a device and want to use it. You should build it as
64 a module.
65
66config DVB_USB_UMT_010
67 tristate "HanfTek UMT-010 DVB-T USB2.0 support"
68 depends on DVB_USB
69 help
70 Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
71
72config DVB_USB_DIGITV
73 tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
74 depends on DVB_USB
75 help
76 Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
77
78config DVB_USB_VP7045
79 tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support"
80 depends on DVB_USB
81 help
82 Say Y here to support the
83 TwinhanDTV Alpha (stick) (VP-7045),
84 TwinhanDTV MagicBox II (VP-7046) and
85 DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers.
86
87config DVB_USB_NOVA_T_USB2
88 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
89 depends on DVB_USB
90 help
91 Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
92
93config DVB_USB_DTT200U
94 tristate "Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support"
95 depends on DVB_USB
96 help
97 Say Y here to support the Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
98
99 The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
new file mode 100644
index 0000000000..d65b50f9ab
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -0,0 +1,30 @@
1dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o
2obj-$(CONFIG_DVB_USB) += dvb-usb.o
3
4dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
5obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
6
7dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
8obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
9
10dvb-usb-dibusb-common-objs = dibusb-common.o
11
12dvb-usb-a800-objs = a800.o
13obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o
14
15dvb-usb-dibusb-mb-objs = dibusb-mb.o
16obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o
17
18dvb-usb-dibusb-mc-objs = dibusb-mc.o
19obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o
20
21dvb-usb-nova-t-usb2-objs = nova-t-usb2.o
22obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o
23
24dvb-usb-umt-010-objs = umt-010.o
25obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
26
27dvb-usb-digitv-objs = digitv.o
28obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
29
30EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
new file mode 100644
index 0000000000..a354293560
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -0,0 +1,176 @@
1/* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T
2 * USB2.0 (A800) DVB-T receiver.
3 *
4 * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * Thanks to
7 * - AVerMedia who kindly provided information and
8 * - Glen Harris who suffered from my mistakes during development.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation, version 2.
13 *
14 * see Documentation/dvb/README.dvb-usb for more information
15 */
16#include "dibusb.h"
17
18static int debug;
19module_param(debug, int, 0644);
20MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
21#define deb_rc(args...) dprintk(debug,0x01,args)
22
23static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
24{
25 /* do nothing for the AVerMedia */
26 return 0;
27}
28
29static struct dvb_usb_rc_key a800_rc_keys[] = {
30 { 0x02, 0x01, KEY_PROG1 }, /* SOURCE */
31 { 0x02, 0x00, KEY_POWER }, /* POWER */
32 { 0x02, 0x05, KEY_1 }, /* 1 */
33 { 0x02, 0x06, KEY_2 }, /* 2 */
34 { 0x02, 0x07, KEY_3 }, /* 3 */
35 { 0x02, 0x09, KEY_4 }, /* 4 */
36 { 0x02, 0x0a, KEY_5 }, /* 5 */
37 { 0x02, 0x0b, KEY_6 }, /* 6 */
38 { 0x02, 0x0d, KEY_7 }, /* 7 */
39 { 0x02, 0x0e, KEY_8 }, /* 8 */
40 { 0x02, 0x0f, KEY_9 }, /* 9 */
41 { 0x02, 0x12, KEY_LEFT }, /* L / DISPLAY */
42 { 0x02, 0x11, KEY_0 }, /* 0 */
43 { 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */
44 { 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */
45 { 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */
46 { 0x02, 0x03, KEY_CHANNELUP }, /* CH UP */
47 { 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */
48 { 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */
49 { 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */
50 { 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */
51 { 0x02, 0x14, KEY_MUTE }, /* MUTE */
52 { 0x02, 0x08, KEY_AUDIO }, /* AUDIO */
53 { 0x02, 0x19, KEY_RECORD }, /* RECORD */
54 { 0x02, 0x18, KEY_PLAY }, /* PLAY */
55 { 0x02, 0x1b, KEY_STOP }, /* STOP */
56 { 0x02, 0x1a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */
57 { 0x02, 0x1d, KEY_BACK }, /* << / RED */
58 { 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */
59 { 0x02, 0x03, KEY_TEXT }, /* TELETEXT */
60 { 0x02, 0x01, KEY_FIRST }, /* |<< / GREEN */
61 { 0x02, 0x00, KEY_LAST }, /* >>| / BLUE */
62 { 0x02, 0x04, KEY_EPG }, /* EPG */
63 { 0x02, 0x15, KEY_MENU }, /* MENU */
64};
65
66int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
67{
68 u8 key[5];
69 if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
70 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
71 2*HZ) != 5)
72 return -ENODEV;
73
74 /* call the universal NEC remote processor, to find out the key's state and event */
75 dvb_usb_nec_rc_key_to_event(d,key,event,state);
76 if (key[0] != 0)
77 deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
78 return 0;
79}
80
81/* USB Driver stuff */
82static struct dvb_usb_properties a800_properties;
83
84static int a800_probe(struct usb_interface *intf,
85 const struct usb_device_id *id)
86{
87 return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE);
88}
89
90/* do not change the order of the ID table */
91static struct usb_device_id a800_table [] = {
92/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_COLD) },
93/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_WARM) },
94 { } /* Terminating entry */
95};
96MODULE_DEVICE_TABLE (usb, a800_table);
97
98static struct dvb_usb_properties a800_properties = {
99 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
100 .pid_filter_count = 32,
101
102 .usb_ctrl = CYPRESS_FX2,
103
104 .firmware = "dvb-usb-avertv-a800-02.fw",
105
106 .size_of_priv = sizeof(struct dibusb_state),
107
108 .streaming_ctrl = dibusb2_0_streaming_ctrl,
109 .pid_filter = dibusb_pid_filter,
110 .pid_filter_ctrl = dibusb_pid_filter_ctrl,
111 .power_ctrl = a800_power_ctrl,
112 .frontend_attach = dibusb_dib3000mc_frontend_attach,
113 .tuner_attach = dibusb_dib3000mc_tuner_attach,
114
115 .rc_interval = DEFAULT_RC_INTERVAL,
116 .rc_key_map = a800_rc_keys,
117 .rc_key_map_size = ARRAY_SIZE(a800_rc_keys),
118 .rc_query = a800_rc_query,
119
120 .i2c_algo = &dibusb_i2c_algo,
121
122 .generic_bulk_ctrl_endpoint = 0x01,
123 /* parameter for the MPEG2-data transfer */
124 .urb = {
125 .type = DVB_USB_BULK,
126 .count = 7,
127 .endpoint = 0x06,
128 .u = {
129 .bulk = {
130 .buffersize = 4096,
131 }
132 }
133 },
134
135 .num_device_descs = 1,
136 .devices = {
137 { "AVerMedia AverTV DVB-T USB 2.0 (A800)",
138 { &a800_table[0], NULL },
139 { &a800_table[1], NULL },
140 },
141 }
142};
143
144static struct usb_driver a800_driver = {
145 .owner = THIS_MODULE,
146 .name = "AVerMedia AverTV DVB-T USB 2.0 (A800)",
147 .probe = a800_probe,
148 .disconnect = dvb_usb_device_exit,
149 .id_table = a800_table,
150};
151
152/* module stuff */
153static int __init a800_module_init(void)
154{
155 int result;
156 if ((result = usb_register(&a800_driver))) {
157 err("usb_register failed. Error number %d",result);
158 return result;
159 }
160
161 return 0;
162}
163
164static void __exit a800_module_exit(void)
165{
166 /* deregister this driver from the USB subsystem */
167 usb_deregister(&a800_driver);
168}
169
170module_init (a800_module_init);
171module_exit (a800_module_exit);
172
173MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
174MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)");
175MODULE_VERSION("1.0");
176MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
new file mode 100644
index 0000000000..63b626f70c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -0,0 +1,272 @@
1/* Common methods for dibusb-based-receivers.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation, version 2.
8 *
9 * see Documentation/dvb/README.dvb-usb for more information
10 */
11#include "dibusb.h"
12
13static int debug;
14module_param(debug, int, 0644);
15MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS);
16MODULE_LICENSE("GPL");
17
18#define deb_info(args...) dprintk(debug,0x01,args)
19
20/* common stuff used by the different dibusb modules */
21int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
22{
23 if (d->priv != NULL) {
24 struct dib_fe_xfer_ops *ops = d->priv;
25 if (ops->fifo_ctrl != NULL)
26 if (ops->fifo_ctrl(d->fe,onoff)) {
27 err("error while controlling the fifo of the demod.");
28 return -ENODEV;
29 }
30 }
31 return 0;
32}
33EXPORT_SYMBOL(dibusb_streaming_ctrl);
34
35int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
36{
37 if (d->priv != NULL) {
38 struct dib_fe_xfer_ops *ops = d->priv;
39 if (d->pid_filtering && ops->pid_ctrl != NULL)
40 ops->pid_ctrl(d->fe,index,pid,onoff);
41 }
42 return 0;
43}
44EXPORT_SYMBOL(dibusb_pid_filter);
45
46int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff)
47{
48 if (d->priv != NULL) {
49 struct dib_fe_xfer_ops *ops = d->priv;
50 if (ops->pid_parse != NULL)
51 if (ops->pid_parse(d->fe,onoff) < 0)
52 err("could not handle pid_parser");
53 }
54 return 0;
55}
56EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
57
58int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
59{
60 u8 b[3];
61 int ret;
62 b[0] = DIBUSB_REQ_SET_IOCTL;
63 b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
64 b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
65 ret = dvb_usb_generic_write(d,b,3);
66 msleep(10);
67 return ret;
68}
69EXPORT_SYMBOL(dibusb_power_ctrl);
70
71int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
72{
73 u8 b[2];
74 b[0] = DIBUSB_REQ_SET_IOCTL;
75 b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
76
77 dvb_usb_generic_write(d,b,3);
78
79 return dibusb_streaming_ctrl(d,onoff);
80}
81EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
82
83int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
84{
85 if (onoff) {
86 u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP };
87 return dvb_usb_generic_write(d,b,3);
88 } else
89 return 0;
90}
91EXPORT_SYMBOL(dibusb2_0_power_ctrl);
92
93static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
94 u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
95{
96 u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
97 /* write only ? */
98 int wo = (rbuf == NULL || rlen == 0),
99 len = 2 + wlen + (wo ? 0 : 2);
100
101 sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
102 sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
103
104 memcpy(&sndbuf[2],wbuf,wlen);
105
106 if (!wo) {
107 sndbuf[wlen+2] = (rlen >> 8) & 0xff;
108 sndbuf[wlen+3] = rlen & 0xff;
109 }
110
111 return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0);
112}
113
114/*
115 * I2C master xfer function
116 */
117static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
118{
119 struct dvb_usb_device *d = i2c_get_adapdata(adap);
120 int i;
121
122 if (down_interruptible(&d->i2c_sem) < 0)
123 return -EAGAIN;
124
125 if (num > 2)
126 warn("more than 2 i2c messages at a time is not handled yet. TODO.");
127
128 for (i = 0; i < num; i++) {
129 /* write/read request */
130 if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
131 if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
132 msg[i+1].buf,msg[i+1].len) < 0)
133 break;
134 i++;
135 } else
136 if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
137 break;
138 }
139
140 up(&d->i2c_sem);
141 return i;
142}
143
144static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
145{
146 return I2C_FUNC_I2C;
147}
148
149struct i2c_algorithm dibusb_i2c_algo = {
150 .name = "DiBcom USB I2C algorithm",
151 .id = I2C_ALGO_BIT,
152 .master_xfer = dibusb_i2c_xfer,
153 .functionality = dibusb_i2c_func,
154};
155EXPORT_SYMBOL(dibusb_i2c_algo);
156
157int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
158{
159 u8 wbuf[1] = { offs };
160 return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1);
161}
162EXPORT_SYMBOL(dibusb_read_eeprom_byte);
163
164int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
165{
166 struct dib3000_config demod_cfg;
167 struct dibusb_state *st = d->priv;
168
169 demod_cfg.pll_set = dvb_usb_pll_set_i2c;
170 demod_cfg.pll_init = dvb_usb_pll_init_i2c;
171
172 for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
173 if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
174 d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
175 return 0;
176 }
177
178 return -ENODEV;
179}
180EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
181
182int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
183{
184 d->pll_addr = 0x60;
185 d->pll_desc = &dvb_pll_env57h1xd5;
186 return 0;
187}
188EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
189
190/*
191 * common remote control stuff
192 */
193struct dvb_usb_rc_key dibusb_rc_keys[] = {
194 /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
195 { 0x00, 0x16, KEY_POWER },
196 { 0x00, 0x10, KEY_MUTE },
197 { 0x00, 0x03, KEY_1 },
198 { 0x00, 0x01, KEY_2 },
199 { 0x00, 0x06, KEY_3 },
200 { 0x00, 0x09, KEY_4 },
201 { 0x00, 0x1d, KEY_5 },
202 { 0x00, 0x1f, KEY_6 },
203 { 0x00, 0x0d, KEY_7 },
204 { 0x00, 0x19, KEY_8 },
205 { 0x00, 0x1b, KEY_9 },
206 { 0x00, 0x15, KEY_0 },
207 { 0x00, 0x05, KEY_CHANNELUP },
208 { 0x00, 0x02, KEY_CHANNELDOWN },
209 { 0x00, 0x1e, KEY_VOLUMEUP },
210 { 0x00, 0x0a, KEY_VOLUMEDOWN },
211 { 0x00, 0x11, KEY_RECORD },
212 { 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
213 { 0x00, 0x14, KEY_PLAY },
214 { 0x00, 0x1a, KEY_STOP },
215 { 0x00, 0x40, KEY_REWIND },
216 { 0x00, 0x12, KEY_FASTFORWARD },
217 { 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
218 { 0x00, 0x4c, KEY_PAUSE },
219 { 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */
220 { 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
221 /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
222 { 0x00, 0x0c, KEY_CANCEL }, /* Cancel */
223 { 0x00, 0x1c, KEY_EPG }, /* EPG */
224 { 0x00, 0x00, KEY_TAB }, /* Tab */
225 { 0x00, 0x48, KEY_INFO }, /* Preview */
226 { 0x00, 0x04, KEY_LIST }, /* RecordList */
227 { 0x00, 0x0f, KEY_TEXT }, /* Teletext */
228 /* Key codes for the KWorld/ADSTech/JetWay remote. */
229 { 0x86, 0x12, KEY_POWER },
230 { 0x86, 0x0f, KEY_SELECT }, /* source */
231 { 0x86, 0x0c, KEY_UNKNOWN }, /* scan */
232 { 0x86, 0x0b, KEY_EPG },
233 { 0x86, 0x10, KEY_MUTE },
234 { 0x86, 0x01, KEY_1 },
235 { 0x86, 0x02, KEY_2 },
236 { 0x86, 0x03, KEY_3 },
237 { 0x86, 0x04, KEY_4 },
238 { 0x86, 0x05, KEY_5 },
239 { 0x86, 0x06, KEY_6 },
240 { 0x86, 0x07, KEY_7 },
241 { 0x86, 0x08, KEY_8 },
242 { 0x86, 0x09, KEY_9 },
243 { 0x86, 0x0a, KEY_0 },
244 { 0x86, 0x18, KEY_ZOOM },
245 { 0x86, 0x1c, KEY_UNKNOWN }, /* preview */
246 { 0x86, 0x13, KEY_UNKNOWN }, /* snap */
247 { 0x86, 0x00, KEY_UNDO },
248 { 0x86, 0x1d, KEY_RECORD },
249 { 0x86, 0x0d, KEY_STOP },
250 { 0x86, 0x0e, KEY_PAUSE },
251 { 0x86, 0x16, KEY_PLAY },
252 { 0x86, 0x11, KEY_BACK },
253 { 0x86, 0x19, KEY_FORWARD },
254 { 0x86, 0x14, KEY_UNKNOWN }, /* pip */
255 { 0x86, 0x15, KEY_ESC },
256 { 0x86, 0x1a, KEY_UP },
257 { 0x86, 0x1e, KEY_DOWN },
258 { 0x86, 0x1f, KEY_LEFT },
259 { 0x86, 0x1b, KEY_RIGHT },
260};
261EXPORT_SYMBOL(dibusb_rc_keys);
262
263int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
264{
265 u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE;
266 dvb_usb_generic_rw(d,&cmd,1,key,5,0);
267 dvb_usb_nec_rc_key_to_event(d,key,event,state);
268 if (key[0] != 0)
269 deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
270 return 0;
271}
272EXPORT_SYMBOL(dibusb_rc_query);
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
new file mode 100644
index 0000000000..a0ffbb59fa
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -0,0 +1,316 @@
1/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
2 * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B)
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * based on GPL code from DiBcom, which has
7 * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation, version 2.
12 *
13 * see Documentation/dvb/README.dvb-usb for more information
14 */
15#include "dibusb.h"
16
17static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
18{
19 struct dib3000_config demod_cfg;
20 struct dibusb_state *st = d->priv;
21
22 demod_cfg.demod_address = 0x8;
23 demod_cfg.pll_set = dvb_usb_pll_set_i2c;
24 demod_cfg.pll_init = dvb_usb_pll_init_i2c;
25
26 if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
27 return -ENODEV;
28
29 d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
30
31 return 0;
32}
33
34/* some of the dibusb 1.1 device aren't equipped with the default tuner
35 * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures
36 * this out. */
37static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d)
38{
39 u8 b[2] = { 0,0 }, b2[1];
40 int ret = 0;
41 struct i2c_msg msg[2] = {
42 { .flags = 0, .buf = b, .len = 2 },
43 { .flags = I2C_M_RD, .buf = b2, .len = 1 },
44 };
45
46 /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
47 msg[0].addr = msg[1].addr = 0x60;
48
49 if (d->tuner_pass_ctrl)
50 d->tuner_pass_ctrl(d->fe,1,msg[0].addr);
51
52 if (i2c_transfer (&d->i2c_adap, msg, 2) != 2) {
53 err("tuner i2c write failed.");
54 ret = -EREMOTEIO;
55 }
56
57 if (d->tuner_pass_ctrl)
58 d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
59
60 if (b2[0] == 0xfe) {
61 info("this device has the Thomson Cable onboard. Which is default.");
62 d->pll_addr = 0x61;
63 d->pll_desc = &dvb_pll_tua6010xs;
64 } else {
65 u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
66 info("this device has the Panasonic ENV77H11D5 onboard.");
67 d->pll_addr = 0x60;
68 memcpy(d->pll_init,bpll,4);
69 d->pll_desc = &dvb_pll_tda665x;
70 }
71
72 return ret;
73}
74
75/* USB Driver stuff */
76static struct dvb_usb_properties dibusb1_1_properties;
77static struct dvb_usb_properties dibusb1_1_an2235_properties;
78static struct dvb_usb_properties dibusb2_0b_properties;
79
80static int dibusb_probe(struct usb_interface *intf,
81 const struct usb_device_id *id)
82{
83 if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 ||
84 dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) == 0 ||
85 dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0)
86 return 0;
87
88 return -EINVAL;
89}
90
91/* do not change the order of the ID table */
92static struct usb_device_id dibusb_dib3000mb_table [] = {
93/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
94/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
95/* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
96/* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
97/* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
98/* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
99/* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
100/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
101/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
102/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
103/* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
104/* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
105/* 12 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) },
106/* 13 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) },
107/* 14 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) },
108/* 15 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_COLD) },
109/* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) },
110/* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
111/* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
112/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
113/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
114/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
115/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
116/* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
117/* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
118 { } /* Terminating entry */
119};
120MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
121
122static struct dvb_usb_properties dibusb1_1_properties = {
123 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
124 .pid_filter_count = 16,
125
126 .usb_ctrl = CYPRESS_AN2135,
127
128 .firmware = "dvb-usb-dibusb-5.0.0.11.fw",
129
130 .size_of_priv = sizeof(struct dibusb_state),
131
132 .streaming_ctrl = dibusb_streaming_ctrl,
133 .pid_filter = dibusb_pid_filter,
134 .pid_filter_ctrl = dibusb_pid_filter_ctrl,
135 .power_ctrl = dibusb_power_ctrl,
136 .frontend_attach = dibusb_dib3000mb_frontend_attach,
137 .tuner_attach = dibusb_dib3000mb_tuner_attach,
138
139 .rc_interval = DEFAULT_RC_INTERVAL,
140 .rc_key_map = dibusb_rc_keys,
141 .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
142 .rc_query = dibusb_rc_query,
143
144 .i2c_algo = &dibusb_i2c_algo,
145
146 .generic_bulk_ctrl_endpoint = 0x01,
147 /* parameter for the MPEG2-data transfer */
148 .urb = {
149 .type = DVB_USB_BULK,
150 .count = 7,
151 .endpoint = 0x02,
152 .u = {
153 .bulk = {
154 .buffersize = 4096,
155 }
156 }
157 },
158
159 .num_device_descs = 8,
160 .devices = {
161 { "AVerMedia AverTV DVBT USB1.1",
162 { &dibusb_dib3000mb_table[0], NULL },
163 { &dibusb_dib3000mb_table[1], NULL },
164 },
165 { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
166 { &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL},
167 { &dibusb_dib3000mb_table[3], NULL },
168 },
169 { "DiBcom USB1.1 DVB-T reference design (MOD3000)",
170 { &dibusb_dib3000mb_table[5], NULL },
171 { &dibusb_dib3000mb_table[6], NULL },
172 },
173 { "KWorld V-Stream XPERT DTV - DVB-T USB1.1",
174 { &dibusb_dib3000mb_table[7], NULL },
175 { &dibusb_dib3000mb_table[8], NULL },
176 },
177 { "Grandtec USB1.1 DVB-T",
178 { &dibusb_dib3000mb_table[9], &dibusb_dib3000mb_table[11], NULL },
179 { &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL },
180 },
181 { "Unkown USB1.1 DVB-T device ???? please report the name to the author",
182 { &dibusb_dib3000mb_table[13], NULL },
183 { &dibusb_dib3000mb_table[14], NULL },
184 },
185 { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device",
186 { &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL},
187 { &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL},
188 },
189 { "Artec T1 USB1.1 TVBOX with AN2135",
190 { &dibusb_dib3000mb_table[19], NULL },
191 { &dibusb_dib3000mb_table[20], NULL },
192 },
193 }
194};
195
196static struct dvb_usb_properties dibusb1_1_an2235_properties = {
197 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
198 .usb_ctrl = CYPRESS_AN2235,
199
200 .firmware = "dvb-usb-dibusb-an2235-01.fw",
201
202 .size_of_priv = sizeof(struct dibusb_state),
203
204 .streaming_ctrl = dibusb_streaming_ctrl,
205 .pid_filter = dibusb_pid_filter,
206 .pid_filter_ctrl = dibusb_pid_filter_ctrl,
207 .power_ctrl = dibusb_power_ctrl,
208 .frontend_attach = dibusb_dib3000mb_frontend_attach,
209 .tuner_attach = dibusb_dib3000mb_tuner_attach,
210
211 .rc_interval = DEFAULT_RC_INTERVAL,
212 .rc_key_map = dibusb_rc_keys,
213 .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
214 .rc_query = dibusb_rc_query,
215
216 .i2c_algo = &dibusb_i2c_algo,
217
218 .generic_bulk_ctrl_endpoint = 0x01,
219 /* parameter for the MPEG2-data transfer */
220 .urb = {
221 .type = DVB_USB_BULK,
222 .count = 7,
223 .endpoint = 0x02,
224 .u = {
225 .bulk = {
226 .buffersize = 4096,
227 }
228 }
229 },
230
231 .num_device_descs = 1,
232 .devices = {
233 { "Artec T1 USB1.1 TVBOX with AN2235",
234 { &dibusb_dib3000mb_table[20], NULL },
235 { &dibusb_dib3000mb_table[21], NULL },
236 },
237 }
238};
239
240static struct dvb_usb_properties dibusb2_0b_properties = {
241 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
242 .usb_ctrl = CYPRESS_FX2,
243
244 .firmware = "dvb-usb-adstech-usb2-01.fw",
245
246 .size_of_priv = sizeof(struct dibusb_state),
247
248 .streaming_ctrl = dibusb2_0_streaming_ctrl,
249 .pid_filter = dibusb_pid_filter,
250 .pid_filter_ctrl = dibusb_pid_filter_ctrl,
251 .power_ctrl = dibusb2_0_power_ctrl,
252 .frontend_attach = dibusb_dib3000mb_frontend_attach,
253 .tuner_attach = dibusb_dib3000mb_tuner_attach,
254
255 .rc_interval = DEFAULT_RC_INTERVAL,
256 .rc_key_map = dibusb_rc_keys,
257 .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
258 .rc_query = dibusb_rc_query,
259
260 .i2c_algo = &dibusb_i2c_algo,
261
262 .generic_bulk_ctrl_endpoint = 0x01,
263 /* parameter for the MPEG2-data transfer */
264 .urb = {
265 .type = DVB_USB_BULK,
266 .count = 7,
267 .endpoint = 0x06,
268 .u = {
269 .bulk = {
270 .buffersize = 4096,
271 }
272 }
273 },
274
275 .num_device_descs = 2,
276 .devices = {
277 { "KWorld/ADSTech Instant DVB-T USB 2.0",
278 { &dibusb_dib3000mb_table[23], NULL },
279 { &dibusb_dib3000mb_table[24], NULL }, /* device ID with default DIBUSB2_0-firmware */
280 },
281 }
282};
283
284static struct usb_driver dibusb_driver = {
285 .owner = THIS_MODULE,
286 .name = "DiBcom based USB DVB-T devices (DiB3000M-B based)",
287 .probe = dibusb_probe,
288 .disconnect = dvb_usb_device_exit,
289 .id_table = dibusb_dib3000mb_table,
290};
291
292/* module stuff */
293static int __init dibusb_module_init(void)
294{
295 int result;
296 if ((result = usb_register(&dibusb_driver))) {
297 err("usb_register failed. Error number %d",result);
298 return result;
299 }
300
301 return 0;
302}
303
304static void __exit dibusb_module_exit(void)
305{
306 /* deregister this driver from the USB subsystem */
307 usb_deregister(&dibusb_driver);
308}
309
310module_init (dibusb_module_init);
311module_exit (dibusb_module_exit);
312
313MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
314MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)");
315MODULE_VERSION("1.0");
316MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
new file mode 100644
index 0000000000..aad8ed3fe0
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -0,0 +1,116 @@
1/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
2 * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P)
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * based on GPL code from DiBcom, which has
7 * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation, version 2.
12 *
13 * see Documentation/dvb/README.dvb-usb for more information
14 */
15#include "dibusb.h"
16
17/* USB Driver stuff */
18static struct dvb_usb_properties dibusb_mc_properties;
19
20static int dibusb_mc_probe(struct usb_interface *intf,
21 const struct usb_device_id *id)
22{
23 return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE);
24}
25
26/* do not change the order of the ID table */
27static struct usb_device_id dibusb_dib3000mc_table [] = {
28/* 00 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) },
29/* 01 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) },
30/* 02 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
31 { } /* Terminating entry */
32};
33MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
34
35static struct dvb_usb_properties dibusb_mc_properties = {
36 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
37 .pid_filter_count = 32,
38
39 .usb_ctrl = CYPRESS_FX2,
40 .firmware = "dvb-usb-dibusb-6.0.0.8.fw",
41
42 .size_of_priv = sizeof(struct dibusb_state),
43
44 .streaming_ctrl = dibusb2_0_streaming_ctrl,
45 .pid_filter = dibusb_pid_filter,
46 .pid_filter_ctrl = dibusb_pid_filter_ctrl,
47 .power_ctrl = dibusb2_0_power_ctrl,
48 .frontend_attach = dibusb_dib3000mc_frontend_attach,
49 .tuner_attach = dibusb_dib3000mc_tuner_attach,
50
51 .rc_interval = DEFAULT_RC_INTERVAL,
52 .rc_key_map = dibusb_rc_keys,
53 .rc_key_map_size = 63, /* FIXME */
54 .rc_query = dibusb_rc_query,
55
56 .i2c_algo = &dibusb_i2c_algo,
57
58 .generic_bulk_ctrl_endpoint = 0x01,
59 /* parameter for the MPEG2-data transfer */
60 .urb = {
61 .type = DVB_USB_BULK,
62 .count = 7,
63 .endpoint = 0x06,
64 .u = {
65 .bulk = {
66 .buffersize = 4096,
67 }
68 }
69 },
70
71 .num_device_descs = 2,
72 .devices = {
73 { "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
74 { &dibusb_dib3000mc_table[0], NULL },
75 { &dibusb_dib3000mc_table[1], NULL },
76 },
77 { "Artec T1 USB2.0 TVBOX (please report the warm ID)",
78 { &dibusb_dib3000mc_table[2], NULL },
79 { NULL },
80 },
81 }
82};
83
84static struct usb_driver dibusb_mc_driver = {
85 .owner = THIS_MODULE,
86 .name = "DiBcom based USB2.0 DVB-T (DiB3000M-C/P based) devices",
87 .probe = dibusb_mc_probe,
88 .disconnect = dvb_usb_device_exit,
89 .id_table = dibusb_dib3000mc_table,
90};
91
92/* module stuff */
93static int __init dibusb_mc_module_init(void)
94{
95 int result;
96 if ((result = usb_register(&dibusb_mc_driver))) {
97 err("usb_register failed. Error number %d",result);
98 return result;
99 }
100
101 return 0;
102}
103
104static void __exit dibusb_mc_module_exit(void)
105{
106 /* deregister this driver from the USB subsystem */
107 usb_deregister(&dibusb_mc_driver);
108}
109
110module_init (dibusb_mc_module_init);
111module_exit (dibusb_mc_module_exit);
112
113MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
114MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices");
115MODULE_VERSION("1.0");
116MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
new file mode 100644
index 0000000000..6611f62977
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -0,0 +1,122 @@
1/* Header file for all dibusb-based-receivers.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation, version 2.
8 *
9 * see Documentation/dvb/README.dvb-usb for more information
10 */
11#ifndef _DVB_USB_DIBUSB_H_
12#define _DVB_USB_DIBUSB_H_
13
14#define DVB_USB_LOG_PREFIX "dibusb"
15#include "dvb-usb.h"
16
17#include "dib3000.h"
18
19/*
20 * protocol of all dibusb related devices
21 */
22
23/*
24 * bulk msg to/from endpoint 0x01
25 *
26 * general structure:
27 * request_byte parameter_bytes
28 */
29
30#define DIBUSB_REQ_START_READ 0x00
31#define DIBUSB_REQ_START_DEMOD 0x01
32
33/*
34 * i2c read
35 * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
36 * bulk read: byte_buffer (length_word bytes)
37 */
38#define DIBUSB_REQ_I2C_READ 0x02
39
40/*
41 * i2c write
42 * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
43 */
44#define DIBUSB_REQ_I2C_WRITE 0x03
45
46/*
47 * polling the value of the remote control
48 * bulk write: 0x04
49 * bulk read: byte_buffer (5 bytes)
50 */
51#define DIBUSB_REQ_POLL_REMOTE 0x04
52
53/* additional status values for Hauppauge Remote Control Protocol */
54#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01
55#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03
56
57/* streaming mode:
58 * bulk write: 0x05 mode_byte
59 *
60 * mode_byte is mostly 0x00
61 */
62#define DIBUSB_REQ_SET_STREAMING_MODE 0x05
63
64/* interrupt the internal read loop, when blocking */
65#define DIBUSB_REQ_INTR_READ 0x06
66
67/* io control
68 * 0x07 cmd_byte param_bytes
69 *
70 * param_bytes can be up to 32 bytes
71 *
72 * cmd_byte function parameter name
73 * 0x00 power mode
74 * 0x00 sleep
75 * 0x01 wakeup
76 *
77 * 0x01 enable streaming
78 * 0x02 disable streaming
79 *
80 *
81 */
82#define DIBUSB_REQ_SET_IOCTL 0x07
83
84/* IOCTL commands */
85
86/* change the power mode in firmware */
87#define DIBUSB_IOCTL_CMD_POWER_MODE 0x00
88#define DIBUSB_IOCTL_POWER_SLEEP 0x00
89#define DIBUSB_IOCTL_POWER_WAKEUP 0x01
90
91/* modify streaming of the FX2 */
92#define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01
93#define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02
94
95struct dibusb_state {
96 struct dib_fe_xfer_ops ops;
97
98 /* for RC5 remote control */
99 int old_toggle;
100 int last_repeat_count;
101};
102
103extern struct i2c_algorithm dibusb_i2c_algo;
104
105extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *);
106extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *);
107
108extern int dibusb_streaming_ctrl(struct dvb_usb_device *, int);
109extern int dibusb_pid_filter(struct dvb_usb_device *, int, u16, int);
110extern int dibusb_pid_filter_ctrl(struct dvb_usb_device *, int);
111extern int dibusb_power_ctrl(struct dvb_usb_device *, int);
112extern int dibusb2_0_streaming_ctrl(struct dvb_usb_device *, int);
113extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
114
115#define DEFAULT_RC_INTERVAL 150
116//#define DEFAULT_RC_INTERVAL 100000
117
118extern struct dvb_usb_rc_key dibusb_rc_keys[];
119extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
120extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
121
122#endif
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
new file mode 100644
index 0000000000..5acf3fde95
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -0,0 +1,282 @@
1/* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
2 * receiver
3 *
4 * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) and
5 * Allan Third (allan.third@cs.man.ac.uk)
6 *
7 * partly based on the SDK published by Nebula Electronics (TODO do we want this line ?)
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation, version 2.
12 *
13 * see Documentation/dvb/README.dvb-usb for more information
14 */
15#include "digitv.h"
16
17#include "mt352.h"
18#include "nxt6000.h"
19
20/* debug */
21int dvb_usb_digitv_debug;
22module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
23MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
24
25static int digitv_ctrl_msg(struct dvb_usb_device *d,
26 u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
27{
28 int wo = (rbuf == NULL || rlen == 0); /* write-only */
29 u8 sndbuf[7],rcvbuf[7];
30 memset(sndbuf,0,7); memset(rcvbuf,0,7);
31
32 sndbuf[0] = cmd;
33 sndbuf[1] = vv;
34 sndbuf[2] = wo ? wlen : rlen;
35
36 if (!wo) {
37 memcpy(&sndbuf[3],wbuf,wlen);
38 dvb_usb_generic_write(d,sndbuf,7);
39 } else {
40 dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
41 memcpy(&rbuf,&rcvbuf[3],rlen);
42 }
43 return 0;
44}
45
46/* I2C */
47static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
48{
49 struct dvb_usb_device *d = i2c_get_adapdata(adap);
50 int i;
51
52 if (down_interruptible(&d->i2c_sem) < 0)
53 return -EAGAIN;
54
55 if (num > 2)
56 warn("more than 2 i2c messages at a time is not handled yet. TODO.");
57
58 for (i = 0; i < num; i++) {
59 /* write/read request */
60 if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
61 if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
62 msg[i+1].buf,msg[i+1].len) < 0)
63 break;
64 i++;
65 } else
66 if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
67 &msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
68 break;
69 }
70
71 up(&d->i2c_sem);
72 return i;
73}
74
75static u32 digitv_i2c_func(struct i2c_adapter *adapter)
76{
77 return I2C_FUNC_I2C;
78}
79
80static struct i2c_algorithm digitv_i2c_algo = {
81 .name = "Nebula DigiTV USB I2C algorithm",
82 .id = I2C_ALGO_BIT,
83 .master_xfer = digitv_i2c_xfer,
84 .functionality = digitv_i2c_func,
85};
86
87/* Callbacks for DVB USB */
88static int digitv_identify_state (struct usb_device *udev, struct
89 dvb_usb_properties *props, struct dvb_usb_device_description **desc,
90 int *cold)
91{
92 *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
93 return 0;
94}
95
96static int digitv_mt352_demod_init(struct dvb_frontend *fe)
97{
98 static u8 mt352_clock_config[] = { 0x89, 0x38, 0x2d };
99 static u8 mt352_reset[] = { 0x50, 0x80 };
100 static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
101
102 static u8 mt352_agc_cfg[] = { 0x68, 0xa0 };
103 static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0xa0 };
104 static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
105 static u8 mt352_agc_target[] = { 0x67, 0x20 };
106
107 static u8 mt352_rs_err_per[] = { 0x7c, 0x00, 0x01 };
108 static u8 mt352_snr_select[] = { 0x79, 0x00, 0x20 };
109
110 static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x05 };
111
112 static u8 mt352_scan_ctl[] = { 0x88, 0x0f };
113 static u8 mt352_capt_range[] = { 0x75, 0x32 };
114
115 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
116 mt352_write(fe, mt352_reset, sizeof(mt352_reset));
117 msleep(1);
118 mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
119
120 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
121 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
122 mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
123 mt352_write(fe, mt352_agc_target, sizeof(mt352_agc_target));
124
125
126 mt352_write(fe, mt352_rs_err_per, sizeof(mt352_rs_err_per));
127 mt352_write(fe, mt352_snr_select, sizeof(mt352_snr_select));
128
129 mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
130
131 mt352_write(fe, mt352_scan_ctl, sizeof(mt352_scan_ctl));
132 mt352_write(fe, mt352_capt_range, sizeof(mt352_capt_range));
133
134 return 0;
135}
136
137static struct mt352_config digitv_mt352_config = {
138 .demod_address = 0x0, /* ignored by the digitv anyway */
139 .demod_init = digitv_mt352_demod_init,
140 .pll_set = NULL, /* TODO */
141};
142
143static struct nxt6000_config digitv_nxt6000_config = {
144 .demod_address = 0x0, /* ignored by the digitv anyway */
145 .clock_inversion = 0x0,
146
147 .pll_init = NULL,
148 .pll_set = NULL,
149};
150
151static int digitv_frontend_attach(struct dvb_usb_device *d)
152{
153 if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) == NULL)
154 return 0;
155 if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) == NULL) {
156
157 warn("nxt6000 support is not done yet, in fact you are one of the first "
158 "person who wants to use this device in Linux. Please report to "
159 "linux-dvb@linuxtv.org");
160
161 return 0;
162 }
163 return -EIO;
164}
165
166static struct dvb_usb_rc_key digitv_rc_keys[] = {
167 { 0x00, 0x16, KEY_POWER }, /* dummy key */
168};
169
170/* TODO is it really the NEC protocol ? */
171int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
172{
173 u8 key[5];
174
175 digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
176 /* TODO state, maybe it is VV ? */
177 if (key[1] != 0)
178 key[0] = 0x01; /* if something is inside the buffer, simulate key press */
179
180 /* call the universal NEC remote processor, to find out the key's state and event */
181 dvb_usb_nec_rc_key_to_event(d,key,event,state);
182 if (key[0] != 0)
183 deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
184 return 0;
185}
186
187
188/* DVB USB Driver stuff */
189static struct dvb_usb_properties digitv_properties;
190
191static int digitv_probe(struct usb_interface *intf,
192 const struct usb_device_id *id)
193{
194 return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE);
195}
196
197static struct usb_device_id digitv_table [] = {
198 { USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) },
199 { } /* Terminating entry */
200};
201MODULE_DEVICE_TABLE (usb, digitv_table);
202
203static struct dvb_usb_properties digitv_properties = {
204 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
205
206 .usb_ctrl = CYPRESS_FX2,
207 .firmware = "dvb-usb-digitv-01.fw",
208
209 .size_of_priv = 0,
210
211 .streaming_ctrl = NULL,
212 .pid_filter = NULL,
213 .pid_filter_ctrl = NULL,
214 .power_ctrl = NULL,
215 .frontend_attach = digitv_frontend_attach,
216 .tuner_attach = NULL, // digitv_tuner_attach,
217 .read_mac_address = NULL,
218
219 .rc_interval = 1000,
220 .rc_key_map = digitv_rc_keys,
221 .rc_key_map_size = ARRAY_SIZE(digitv_rc_keys),
222 .rc_query = digitv_rc_query,
223
224 .identify_state = digitv_identify_state,
225
226 .i2c_algo = &digitv_i2c_algo,
227
228 .generic_bulk_ctrl_endpoint = 0x01,
229 /* parameter for the MPEG2-data transfer */
230 .urb = {
231 .type = DVB_USB_BULK,
232 .count = 7,
233 .endpoint = 0x02,
234 .u = {
235 .bulk = {
236 .buffersize = 4096,
237 }
238 }
239 },
240
241 .num_device_descs = 2,
242 .devices = {
243 { "Nebula Electronics uDigiTV DVB-T USB2.0)",
244 { &digitv_table[0], NULL },
245 { NULL },
246 },
247 }
248};
249
250static struct usb_driver digitv_driver = {
251 .owner = THIS_MODULE,
252 .name = "Nebula Electronics uDigiTV DVB-T USB2.0 device",
253 .probe = digitv_probe,
254 .disconnect = dvb_usb_device_exit,
255 .id_table = digitv_table,
256};
257
258/* module stuff */
259static int __init digitv_module_init(void)
260{
261 int result;
262 if ((result = usb_register(&digitv_driver))) {
263 err("usb_register failed. Error number %d",result);
264 return result;
265 }
266
267 return 0;
268}
269
270static void __exit digitv_module_exit(void)
271{
272 /* deregister this driver from the USB subsystem */
273 usb_deregister(&digitv_driver);
274}
275
276module_init (digitv_module_init);
277module_exit (digitv_module_exit);
278
279MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
280MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
281MODULE_VERSION("1.0-alpha");
282MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h
new file mode 100644
index 0000000000..477ee428a7
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/digitv.h
@@ -0,0 +1,65 @@
1#ifndef _DVB_USB_DIGITV_H_
2#define _DVB_USB_DIGITV_H_
3
4#define DVB_USB_LOG_PREFIX "digitv"
5#include "dvb-usb.h"
6
7extern int dvb_usb_digitv_debug;
8#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
9
10/* protocol (from usblogging and the SDK:
11 *
12 * Always 7 bytes bulk message(s) for controlling
13 *
14 * First byte describes the command. Reads are 2 consecutive transfer (as always).
15 *
16 * General structure:
17 *
18 * write or first message of a read:
19 * <cmdbyte> VV <len> B0 B1 B2 B3
20 *
21 * second message of a read
22 * <cmdbyte> VV <len> R0 R1 R2 R3
23 *
24 * whereas 0 < len <= 4
25 *
26 * I2C address is stored somewhere inside the device.
27 *
28 * 0x01 read from EEPROM
29 * VV = offset; B* = 0; R* = value(s)
30 *
31 * 0x02 read register of the COFDM
32 * VV = register; B* = 0; R* = value(s)
33 *
34 * 0x05 write register of the COFDM
35 * VV = register; B* = value(s);
36 *
37 * 0x06 write to the tuner (only for NXT6000)
38 * VV = 0; B* = PLL data; len = 4;
39 *
40 * 0x03 read remote control
41 * VV = 0; B* = 0; len = 4; R* = key
42 *
43 * 0x07 write to the remote (don't know why one should this, resetting ?)
44 * VV = 0; B* = key; len = 4;
45 *
46 * 0x08 write remote type
47 * VV = 0; B[0] = 0x01, len = 4
48 *
49 * 0x09 write device init
50 * TODO
51 */
52#define USB_READ_EEPROM 1
53
54#define USB_READ_COFDM 2
55#define USB_WRITE_COFDM 5
56
57#define USB_WRITE_TUNER 6
58
59#define USB_READ_REMOTE 3
60#define USB_WRITE_REMOTE 7
61#define USB_WRITE_REMOTE_TYPE 8
62
63#define USB_DEV_INIT 9
64
65#endif
diff --git a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index 1872aa6d20..d17d768038 100644
--- a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -1,42 +1,18 @@
1/* 1/* Frontend part of the Linux driver for the Yakumo/Hama/Typhoon DVB-T
2 * dvb-dtt200u-fe.c is a driver which implements the frontend-part of the 2 * USB2.0 receiver.
3 * Yakumo/Typhoon/Hama USB2.0 boxes. It is hard-wired to the dibusb-driver as
4 * it uses the usb-transfer functions directly (maybe creating a
5 * generic-dvb-usb-lib for all usb-drivers will be reduce some more code.)
6 * 3 *
7 * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de> 4 * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
8 * 5 *
9 * see dvb-dibusb-core.c for copyright details. 6 * This program is free software; you can redistribute it and/or modify it
10 */ 7 * under the terms of the GNU General Public License as published by the Free
11 8 * Software Foundation, version 2.
12/* guessed protocol description (reverse engineered):
13 * read
14 * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
15 * 81 - <TS_LOCK> <current frequency divided by 250000>
16 * 82 - crash - do not touch
17 * 83 - crash - do not touch
18 * 84 - remote control
19 * 85 - crash - do not touch (OK, stop testing here)
20 * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
21 * 89 - noise-to-signal
22 * 8a - unkown 1 byte - signal_strength
23 * 8c - ber ???
24 * 8d - ber
25 * 8e - unc
26 * 9 *
27 * write 10 * see Documentation/dvb/README.dvb-usb for more information
28 * 02 - bandwidth
29 * 03 - frequency (divided by 250000)
30 * 04 - pid table (index pid(7:0) pid(12:8))
31 * 05 - reset the pid table
32 * 08 - demod transfer enabled or not (FX2 transfer is enabled by default)
33 */ 11 */
34 12#include "dtt200u.h"
35#include "dvb-dibusb.h"
36#include "dvb_frontend.h"
37 13
38struct dtt200u_fe_state { 14struct dtt200u_fe_state {
39 struct usb_dibusb *dib; 15 struct dvb_usb_device *d;
40 16
41 struct dvb_frontend_parameters fep; 17 struct dvb_frontend_parameters fep;
42 struct dvb_frontend frontend; 18 struct dvb_frontend frontend;
@@ -47,11 +23,11 @@ struct dtt200u_fe_state {
47static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) 23static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
48{ 24{
49 struct dtt200u_fe_state *state = fe->demodulator_priv; 25 struct dtt200u_fe_state *state = fe->demodulator_priv;
50 u8 bw[1] = { 0x81 }; 26 u8 bw = GET_TUNE_STAT;
51 u8 br[3] = { 0 }; 27 u8 br[3] = { 0 };
52// u8 bdeb[5] = { 0 }; 28// u8 bdeb[5] = { 0 };
53 29
54 dibusb_readwrite_usb(state->dib,bw,1,br,3); 30 dvb_usb_generic_rw(state->d,&bw,1,br,3,0);
55 switch (br[0]) { 31 switch (br[0]) {
56 case 0x01: 32 case 0x01:
57 *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 33 *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
@@ -60,12 +36,12 @@ static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
60 *stat = 0; 36 *stat = 0;
61 break; 37 break;
62 default: 38 default:
63 moan("br[0]",0x81); 39 moan("br[0]",GET_TUNE_STAT);
64 break; 40 break;
65 } 41 }
66 42
67// bw[0] = 0x88; 43// bw[0] = 0x88;
68// dibusb_readwrite_usb(state->dib,bw,1,bdeb,5); 44// dvb_usb_generic_rw(state->d,bw,1,bdeb,5,0);
69 45
70// deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]); 46// deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]);
71 47
@@ -74,27 +50,26 @@ static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
74static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) 50static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
75{ 51{
76 struct dtt200u_fe_state *state = fe->demodulator_priv; 52 struct dtt200u_fe_state *state = fe->demodulator_priv;
77 u8 bw[1] = { 0x8d }; 53 u8 bw = GET_BER;
78 *ber = 0; 54 *ber = 0;
79 dibusb_readwrite_usb(state->dib,bw,1,(u8*) ber, 3); 55 dvb_usb_generic_rw(state->d,&bw,1,(u8*) ber,3,0);
80 return 0; 56 return 0;
81} 57}
82 58
83static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) 59static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
84{ 60{
85 struct dtt200u_fe_state *state = fe->demodulator_priv; 61 struct dtt200u_fe_state *state = fe->demodulator_priv;
86 u8 bw[1] = { 0x8c }; 62 u8 bw = GET_UNK;
87 *unc = 0; 63 *unc = 0;
88 dibusb_readwrite_usb(state->dib,bw,1,(u8*) unc, 3); 64 dvb_usb_generic_rw(state->d,&bw,1,(u8*) unc,3,0);
89 return 0; 65 return 0;
90} 66}
91 67
92static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) 68static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
93{ 69{
94 struct dtt200u_fe_state *state = fe->demodulator_priv; 70 struct dtt200u_fe_state *state = fe->demodulator_priv;
95 u8 bw[1] = { 0x8a }; 71 u8 bw = GET_SIG_STRENGTH, b;
96 u8 b; 72 dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
97 dibusb_readwrite_usb(state->dib,bw,1,&b, 1);
98 *strength = (b << 8) | b; 73 *strength = (b << 8) | b;
99 return 0; 74 return 0;
100} 75}
@@ -102,18 +77,17 @@ static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strengt
102static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr) 77static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
103{ 78{
104 struct dtt200u_fe_state *state = fe->demodulator_priv; 79 struct dtt200u_fe_state *state = fe->demodulator_priv;
105 u8 bw[1] = { 0x89 }; 80 u8 bw = GET_SNR,br;
106 u8 br[1] = { 0 }; 81 dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
107 dibusb_readwrite_usb(state->dib,bw,1,br,1); 82 *snr = ~((br << 8) | br);
108 *snr = ((0xff - br[0]) << 8) | (0xff - br[0]);
109 return 0; 83 return 0;
110} 84}
111 85
112static int dtt200u_fe_init(struct dvb_frontend* fe) 86static int dtt200u_fe_init(struct dvb_frontend* fe)
113{ 87{
114 struct dtt200u_fe_state *state = fe->demodulator_priv; 88 struct dtt200u_fe_state *state = fe->demodulator_priv;
115 u8 b[] = { 0x01 }; 89 u8 b = RESET_DEMOD;
116 return dibusb_write_usb(state->dib,b,1); 90 return dvb_usb_generic_write(state->d,&b,1);
117} 91}
118 92
119static int dtt200u_fe_sleep(struct dvb_frontend* fe) 93static int dtt200u_fe_sleep(struct dvb_frontend* fe)
@@ -134,7 +108,7 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
134{ 108{
135 struct dtt200u_fe_state *state = fe->demodulator_priv; 109 struct dtt200u_fe_state *state = fe->demodulator_priv;
136 u16 freq = fep->frequency / 250000; 110 u16 freq = fep->frequency / 250000;
137 u8 bw,bwbuf[2] = { 0x03, 0 }, freqbuf[3] = { 0x02, 0, 0 }; 111 u8 bw,bwbuf[2] = { SET_BANDWIDTH, 0 }, freqbuf[3] = { SET_FREQUENCY, 0, 0 };
138 112
139 switch (fep->u.ofdm.bandwidth) { 113 switch (fep->u.ofdm.bandwidth) {
140 case BANDWIDTH_8_MHZ: bw = 8; break; 114 case BANDWIDTH_8_MHZ: bw = 8; break;
@@ -147,11 +121,11 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
147 deb_info("set_frontend\n"); 121 deb_info("set_frontend\n");
148 122
149 bwbuf[1] = bw; 123 bwbuf[1] = bw;
150 dibusb_write_usb(state->dib,bwbuf,2); 124 dvb_usb_generic_write(state->d,bwbuf,2);
151 125
152 freqbuf[1] = freq & 0xff; 126 freqbuf[1] = freq & 0xff;
153 freqbuf[2] = (freq >> 8) & 0xff; 127 freqbuf[2] = (freq >> 8) & 0xff;
154 dibusb_write_usb(state->dib,freqbuf,3); 128 dvb_usb_generic_write(state->d,freqbuf,3);
155 129
156 memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters)); 130 memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters));
157 131
@@ -172,37 +146,9 @@ static void dtt200u_fe_release(struct dvb_frontend* fe)
172 kfree(state); 146 kfree(state);
173} 147}
174 148
175static int dtt200u_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
176{
177 struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
178 u8 b_pid[4];
179 pid = onoff ? pid : 0;
180
181 b_pid[0] = 0x04;
182 b_pid[1] = index;
183 b_pid[2] = pid & 0xff;
184 b_pid[3] = (pid >> 8) & 0xff;
185
186 dibusb_write_usb(state->dib,b_pid,4);
187 return 0;
188}
189
190static int dtt200u_fifo_control(struct dvb_frontend *fe, int onoff)
191{
192 struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
193 u8 b_streaming[2] = { 0x08, onoff };
194 u8 b_rst_pid[1] = { 0x05 };
195
196 dibusb_write_usb(state->dib,b_streaming,2);
197
198 if (!onoff)
199 dibusb_write_usb(state->dib,b_rst_pid,1);
200 return 0;
201}
202
203static struct dvb_frontend_ops dtt200u_fe_ops; 149static struct dvb_frontend_ops dtt200u_fe_ops;
204 150
205struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *dib, struct dib_fe_xfer_ops *xfer_ops) 151struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
206{ 152{
207 struct dtt200u_fe_state* state = NULL; 153 struct dtt200u_fe_state* state = NULL;
208 154
@@ -214,14 +160,11 @@ struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *dib, struct dib_fe_xfe
214 160
215 deb_info("attaching frontend dtt200u\n"); 161 deb_info("attaching frontend dtt200u\n");
216 162
217 state->dib = dib; 163 state->d = d;
218 164
219 state->frontend.ops = &dtt200u_fe_ops; 165 state->frontend.ops = &dtt200u_fe_ops;
220 state->frontend.demodulator_priv = state; 166 state->frontend.demodulator_priv = state;
221 167
222 xfer_ops->fifo_ctrl = dtt200u_fifo_control;
223 xfer_ops->pid_ctrl = dtt200u_pid_control;
224
225 goto success; 168 goto success;
226error: 169error:
227 return NULL; 170 return NULL;
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
new file mode 100644
index 0000000000..fb2b5a2da1
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -0,0 +1,171 @@
1/* DVB USB library compliant Linux driver for the Yakumo/Hama/Typhoon DVB-T
2 * USB2.0 receiver.
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, version 2.
9 *
10 * see Documentation/dvb/README.dvb-usb for more information
11 */
12#include "dtt200u.h"
13
14/* debug */
15int dvb_usb_dtt200u_debug;
16module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
17MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
18
19static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff)
20{
21 u8 b_streaming[2] = { SET_TS_CTRL, onoff };
22 u8 b_rst_pid = RESET_PID_FILTER;
23
24 dvb_usb_generic_write(d,b_streaming,2);
25
26 if (!onoff)
27 dvb_usb_generic_write(d,&b_rst_pid,1);
28 return 0;
29}
30
31static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
32{
33 u8 b_pid[4];
34 pid = onoff ? pid : 0;
35
36 b_pid[0] = SET_PID_FILTER;
37 b_pid[1] = index;
38 b_pid[2] = pid & 0xff;
39 b_pid[3] = (pid >> 8) & 0xff;
40
41 return dvb_usb_generic_write(d,b_pid,4);
42}
43
44/* remote control */
45/* key list for the tiny remote control (Yakumo, don't know about the others) */
46static struct dvb_usb_rc_key dtt200u_rc_keys[] = {
47 { 0x80, 0x01, KEY_MUTE },
48 { 0x80, 0x02, KEY_CHANNELDOWN },
49 { 0x80, 0x03, KEY_VOLUMEDOWN },
50 { 0x80, 0x04, KEY_1 },
51 { 0x80, 0x05, KEY_2 },
52 { 0x80, 0x06, KEY_3 },
53 { 0x80, 0x07, KEY_4 },
54 { 0x80, 0x08, KEY_5 },
55 { 0x80, 0x09, KEY_6 },
56 { 0x80, 0x0a, KEY_7 },
57 { 0x00, 0x0c, KEY_ZOOM },
58 { 0x80, 0x0d, KEY_0 },
59 { 0x00, 0x0e, KEY_SELECT },
60 { 0x80, 0x12, KEY_POWER },
61 { 0x80, 0x1a, KEY_CHANNELUP },
62 { 0x80, 0x1b, KEY_8 },
63 { 0x80, 0x1e, KEY_VOLUMEUP },
64 { 0x80, 0x1f, KEY_9 },
65};
66
67static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
68{
69 u8 key[5],cmd = GET_RC_KEY;
70 dvb_usb_generic_rw(d,&cmd,1,key,5,0);
71 dvb_usb_nec_rc_key_to_event(d,key,event,state);
72 if (key[0] != 0)
73 deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
74 return 0;
75}
76
77static int dtt200u_frontend_attach(struct dvb_usb_device *d)
78{
79 d->fe = dtt200u_fe_attach(d);
80 return 0;
81}
82
83static struct dvb_usb_properties dtt200u_properties;
84
85static int dtt200u_usb_probe(struct usb_interface *intf,
86 const struct usb_device_id *id)
87{
88 return dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE);
89}
90
91static struct usb_device_id dtt200u_usb_table [] = {
92 { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_COLD) },
93 { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_WARM) },
94 { 0 },
95};
96MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
97
98static struct dvb_usb_properties dtt200u_properties = {
99 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
100 .pid_filter_count = 255, /* It is a guess, but there are at least 10 */
101
102 .usb_ctrl = CYPRESS_FX2,
103 .firmware = "dvb-usb-dtt200u-01.fw",
104
105 .streaming_ctrl = dtt200u_streaming_ctrl,
106 .pid_filter = dtt200u_pid_filter,
107 .frontend_attach = dtt200u_frontend_attach,
108
109 .rc_interval = 200,
110 .rc_key_map = dtt200u_rc_keys,
111 .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
112 .rc_query = dtt200u_rc_query,
113
114 .generic_bulk_ctrl_endpoint = 0x01,
115
116 /* parameter for the MPEG2-data transfer */
117 .urb = {
118 .type = DVB_USB_BULK,
119 .count = 7,
120 .endpoint = 0x02,
121 .u = {
122 .bulk = {
123 .buffersize = 4096,
124 }
125 }
126 },
127
128 .num_device_descs = 1,
129 .devices = {
130 { .name = "Yakumo/Hama/Typhoon DVB-T USB2.0)",
131 .cold_ids = { &dtt200u_usb_table[0], &dtt200u_usb_table[2] },
132 .warm_ids = { &dtt200u_usb_table[1], NULL },
133 },
134 { 0 },
135 }
136};
137
138/* usb specific object needed to register this driver with the usb subsystem */
139static struct usb_driver dtt200u_usb_driver = {
140 .owner = THIS_MODULE,
141 .name = "Yakumo/Hama/Typhoon DVB-T USB2.0",
142 .probe = dtt200u_usb_probe,
143 .disconnect = dvb_usb_device_exit,
144 .id_table = dtt200u_usb_table,
145};
146
147/* module stuff */
148static int __init dtt200u_usb_module_init(void)
149{
150 int result;
151 if ((result = usb_register(&dtt200u_usb_driver))) {
152 err("usb_register failed. (%d)",result);
153 return result;
154 }
155
156 return 0;
157}
158
159static void __exit dtt200u_usb_module_exit(void)
160{
161 /* deregister this driver from the USB subsystem */
162 usb_deregister(&dtt200u_usb_driver);
163}
164
165module_init(dtt200u_usb_module_init);
166module_exit(dtt200u_usb_module_exit);
167
168MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
169MODULE_DESCRIPTION("Driver for the Yakumo/Hama/Typhoon DVB-T USB2.0 device");
170MODULE_VERSION("1.0");
171MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h
new file mode 100644
index 0000000000..ed41420715
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtt200u.h
@@ -0,0 +1,66 @@
1/* Common header file of Linux driver for the Yakumo/Hama/Typhoon DVB-T
2 * USB2.0 receiver.
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, version 2.
9 *
10 * see Documentation/dvb/README.dvb-usb for more information
11 */
12#ifndef _DVB_USB_DTT200U_H_
13#define _DVB_USB_DTT200U_H_
14
15#define DVB_USB_LOG_PREFIX "dtt200u"
16#include "dvb-usb.h"
17
18extern int dvb_usb_dtt200u_debug;
19#define deb_info(args...) dprintk(dvb_usb_dtt200u_debug,0x01,args)
20#define deb_xfer(args...) dprintk(dvb_usb_dtt200u_debug,0x02,args)
21
22/* guessed protocol description (reverse engineered):
23 * read
24 * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
25 * 81 - <TS_LOCK> <current frequency divided by 250000>
26 * 82 - crash - do not touch
27 * 83 - crash - do not touch
28 * 84 - remote control
29 * 85 - crash - do not touch (OK, stop testing here)
30 * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
31 * 89 - noise-to-signal
32 * 8a - unkown 1 byte - signal_strength
33 * 8c - ber ???
34 * 8d - ber
35 * 8e - unc
36 */
37
38#define GET_SPEED 0x00
39#define GET_TUNE_STAT 0x81
40#define GET_RC_KEY 0x84
41#define GET_STATUS 0x88
42#define GET_SNR 0x89
43#define GET_SIG_STRENGTH 0x8a
44#define GET_UNK 0x8c
45#define GET_BER 0x8d
46#define GET_UNC 0x8e
47
48/* write
49 * 01 - reset the demod
50 * 02 - frequency (divided by 250000)
51 * 03 - bandwidth
52 * 04 - pid table (index pid(7:0) pid(12:8))
53 * 05 - reset the pid table
54 * 08 - demod transfer enabled or not (FX2 transfer is enabled by default)
55 */
56
57#define RESET_DEMOD 0x01
58#define SET_FREQUENCY 0x02
59#define SET_BANDWIDTH 0x03
60#define SET_PID_FILTER 0x04
61#define RESET_PID_FILTER 0x05
62#define SET_TS_CTRL 0x08
63
64extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
65
66#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
new file mode 100644
index 0000000000..67e0d73fbc
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
@@ -0,0 +1,44 @@
1/* dvb-usb-common.h is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * a header file containing prototypes and types for internal use of the dvb-usb-lib
7 */
8#ifndef _DVB_USB_COMMON_H_
9#define _DVB_USB_COMMON_H_
10
11#define DVB_USB_LOG_PREFIX "dvb-usb"
12#include "dvb-usb.h"
13
14extern int dvb_usb_debug;
15
16#define deb_info(args...) dprintk(dvb_usb_debug,0x01,args)
17#define deb_xfer(args...) dprintk(dvb_usb_debug,0x02,args)
18#define deb_pll(args...) dprintk(dvb_usb_debug,0x04,args)
19#define deb_ts(args...) dprintk(dvb_usb_debug,0x08,args)
20#define deb_err(args...) dprintk(dvb_usb_debug,0x10,args)
21#define deb_rc(args...) dprintk(dvb_usb_debug,0x20,args)
22#define deb_fw(args...) dprintk(dvb_usb_debug,0x40,args)
23
24/* commonly used methods */
25extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
26
27extern int dvb_usb_urb_submit(struct dvb_usb_device *);
28extern int dvb_usb_urb_kill(struct dvb_usb_device *);
29extern int dvb_usb_urb_init(struct dvb_usb_device *);
30extern int dvb_usb_urb_exit(struct dvb_usb_device *);
31
32extern int dvb_usb_i2c_init(struct dvb_usb_device *);
33extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
34
35extern int dvb_usb_dvb_init(struct dvb_usb_device *);
36extern int dvb_usb_dvb_exit(struct dvb_usb_device *);
37
38extern int dvb_usb_fe_init(struct dvb_usb_device *);
39extern int dvb_usb_fe_exit(struct dvb_usb_device *);
40
41extern int dvb_usb_remote_init(struct dvb_usb_device *);
42extern int dvb_usb_remote_exit(struct dvb_usb_device *);
43
44#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
new file mode 100644
index 0000000000..bdd72f7797
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -0,0 +1,210 @@
1/* dvb-usb-dvb.c is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * This file contains functions for initializing and handling the
7 * linux-dvb API.
8 */
9#include "dvb-usb-common.h"
10
11static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
12{
13 struct dvb_usb_device *d = dvbdmxfeed->demux->priv;
14 int newfeedcount,ret;
15
16 if (d == NULL)
17 return -ENODEV;
18
19 newfeedcount = d->feedcount + (onoff ? 1 : -1);
20
21 /*
22 * stop feed before setting a new pid if there will be no pid anymore
23 */
24 if (newfeedcount == 0) {
25 deb_ts("stop feeding\n");
26
27 if (d->props.streaming_ctrl != NULL)
28 if ((ret = d->props.streaming_ctrl(d,0)))
29 err("error while stopping stream.");
30
31 dvb_usb_urb_kill(d);
32 }
33
34 d->feedcount = newfeedcount;
35
36 /* activate the pid on the device specific pid_filter */
37 deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
38 if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
39 d->pid_filtering &&
40 d->props.pid_filter != NULL)
41 d->props.pid_filter(d,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
42
43 /* start the feed if this was the first feed and there is still a feed
44 * for reception.
45 */
46 if (d->feedcount == onoff && d->feedcount > 0) {
47
48 deb_ts("controlling pid parser\n");
49 if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
50 d->props.caps & DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF &&
51 d->props.pid_filter_ctrl != NULL)
52 if (d->props.pid_filter_ctrl(d,d->pid_filtering) < 0)
53 err("could not handle pid_parser");
54
55 deb_ts("start feeding\n");
56 if (d->props.streaming_ctrl != NULL)
57 if (d->props.streaming_ctrl(d,1)) {
58 err("error while enabling fifo.");
59 return -ENODEV;
60 }
61
62 dvb_usb_urb_submit(d);
63 }
64 return 0;
65}
66
67static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
68{
69 deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
70 return dvb_usb_ctrl_feed(dvbdmxfeed,1);
71}
72
73static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
74{
75 deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
76 return dvb_usb_ctrl_feed(dvbdmxfeed,0);
77}
78
79int dvb_usb_dvb_init(struct dvb_usb_device *d)
80{
81 int ret;
82
83 if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
84 d->owner)) < 0) {
85 deb_info("dvb_register_adapter failed: error %d", ret);
86 goto err;
87 }
88 d->dvb_adap.priv = d;
89
90 if (d->props.read_mac_address) {
91 if (d->props.read_mac_address(d,d->dvb_adap.proposed_mac) == 0)
92 info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",d->dvb_adap.proposed_mac[0],
93 d->dvb_adap.proposed_mac[1],d->dvb_adap.proposed_mac[2],
94 d->dvb_adap.proposed_mac[3],d->dvb_adap.proposed_mac[4],
95 d->dvb_adap.proposed_mac[5]);
96 else
97 err("MAC address reading failed.");
98 }
99
100
101 d->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
102 d->demux.priv = d;
103
104 d->demux.feednum = d->demux.filternum = d->max_feed_count;
105 d->demux.start_feed = dvb_usb_start_feed;
106 d->demux.stop_feed = dvb_usb_stop_feed;
107 d->demux.write_to_decoder = NULL;
108 if ((ret = dvb_dmx_init(&d->demux)) < 0) {
109 err("dvb_dmx_init failed: error %d",ret);
110 goto err_dmx;
111 }
112
113 d->dmxdev.filternum = d->demux.filternum;
114 d->dmxdev.demux = &d->demux.dmx;
115 d->dmxdev.capabilities = 0;
116 if ((ret = dvb_dmxdev_init(&d->dmxdev, &d->dvb_adap)) < 0) {
117 err("dvb_dmxdev_init failed: error %d",ret);
118 goto err_dmx_dev;
119 }
120
121 dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
122
123 goto success;
124err_dmx_dev:
125 dvb_dmx_release(&d->demux);
126err_dmx:
127 dvb_unregister_adapter(&d->dvb_adap);
128err:
129 return ret;
130success:
131 d->state |= DVB_USB_STATE_DVB;
132 return 0;
133}
134
135int dvb_usb_dvb_exit(struct dvb_usb_device *d)
136{
137 if (d->state & DVB_USB_STATE_DVB) {
138 deb_info("unregistering DVB part\n");
139 dvb_net_release(&d->dvb_net);
140 d->demux.dmx.close(&d->demux.dmx);
141 dvb_dmxdev_release(&d->dmxdev);
142 dvb_dmx_release(&d->demux);
143 dvb_unregister_adapter(&d->dvb_adap);
144 d->state &= ~DVB_USB_STATE_DVB;
145 }
146 return 0;
147}
148
149static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
150{
151 struct dvb_usb_device *d = fe->dvb->priv;
152
153 if (d->props.power_ctrl)
154 d->props.power_ctrl(d,1);
155
156 if (d->fe_init)
157 d->fe_init(fe);
158
159 return 0;
160}
161
162static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
163{
164 struct dvb_usb_device *d = fe->dvb->priv;
165
166 if (d->fe_sleep)
167 d->fe_sleep(fe);
168
169 if (d->props.power_ctrl)
170 d->props.power_ctrl(d,0);
171
172 return 0;
173}
174
175int dvb_usb_fe_init(struct dvb_usb_device* d)
176{
177 if (d->props.frontend_attach == NULL) {
178 err("strange '%s' don't want to attach a frontend.",d->desc->name);
179 return 0;
180 }
181
182 d->props.frontend_attach(d);
183
184 /* re-assign sleep and wakeup functions */
185 if (d->fe != NULL) {
186 d->fe_init = d->fe->ops->init; d->fe->ops->init = dvb_usb_fe_wakeup;
187 d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep;
188
189 if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
190 err("Frontend registration failed.");
191 if (d->fe->ops->release)
192 d->fe->ops->release(d->fe);
193 d->fe = NULL;
194 return -ENODEV;
195 }
196 } else
197 err("no frontend was attached by '%s'",d->desc->name);
198
199 if (d->props.tuner_attach != NULL)
200 d->props.tuner_attach(d);
201
202 return 0;
203}
204
205int dvb_usb_fe_exit(struct dvb_usb_device *d)
206{
207 if (d->fe != NULL)
208 dvb_unregister_frontend(d->fe);
209 return 0;
210}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
new file mode 100644
index 0000000000..5244e39770
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -0,0 +1,100 @@
1/* dvb-usb-firmware.c is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices.
7 *
8 * FIXME: This part does actually not belong to dvb-usb, but to the usb-subsystem.
9 */
10#include "dvb-usb-common.h"
11
12#include <linux/firmware.h>
13#include <linux/usb.h>
14
15struct usb_cypress_controller {
16 int id;
17 const char *name; /* name of the usb controller */
18 u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */
19};
20
21static struct usb_cypress_controller cypress[] = {
22 { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
23 { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
24 { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
25};
26
27/*
28 * load a firmware packet to the device
29 */
30static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
31{
32 return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
33 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
34}
35
36int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type)
37{
38 const struct firmware *fw = NULL;
39 u16 addr;
40 u8 *b,*p;
41 int ret = 0,i;
42
43 if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) {
44 err("did not find the firmware file. (%s) "
45 "Please see linux/Documentation/dvb/ for more details on firmware-problems.",
46 filename);
47 return ret;
48 }
49
50 info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name);
51
52 p = kmalloc(fw->size,GFP_KERNEL);
53 if (p != NULL) {
54 u8 reset;
55 /*
56 * you cannot use the fw->data as buffer for
57 * usb_control_msg, a new buffer has to be
58 * created
59 */
60 memcpy(p,fw->data,fw->size);
61
62 /* stop the CPU */
63 reset = 1;
64 if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
65 err("could not stop the USB controller CPU.");
66 for(i = 0; p[i+3] == 0 && i < fw->size; ) {
67 b = (u8 *) &p[i];
68 addr = cpu_to_le16( *((u16 *) &b[1]) );
69
70 deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]);
71
72 ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
73
74 if (ret != b[0]) {
75 err("error while transferring firmware "
76 "(transferred size: %d, block size: %d)",
77 ret,b[0]);
78 ret = -EINVAL;
79 break;
80 }
81 i += 5 + b[0];
82 }
83 /* length in ret */
84 if (ret > 0)
85 ret = 0;
86 /* restart the CPU */
87 reset = 0;
88 if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
89 err("could not restart the USB controller CPU.");
90 ret = -EINVAL;
91 }
92
93 kfree(p);
94 } else {
95 ret = -ENOMEM;
96 }
97 release_firmware(fw);
98
99 return ret;
100}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
new file mode 100644
index 0000000000..9f0a8d90d1
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -0,0 +1,118 @@
1/* dvb-usb-i2c.c is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * This file contains functions for (de-)initializing an I2C adapter.
7 */
8#include "dvb-usb-common.h"
9
10int dvb_usb_i2c_init(struct dvb_usb_device *d)
11{
12 int ret = 0;
13
14 if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER))
15 return 0;
16
17 if (d->props.i2c_algo == NULL) {
18 err("no i2c algorithm specified");
19 return -EINVAL;
20 }
21
22 strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE);
23#ifdef I2C_ADAP_CLASS_TV_DIGITAL
24 d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
25#else
26 d->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
27#endif
28 d->i2c_adap.algo = d->props.i2c_algo;
29 d->i2c_adap.algo_data = NULL;
30 d->i2c_adap.id = I2C_ALGO_BIT;
31
32 i2c_set_adapdata(&d->i2c_adap, d);
33
34 if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
35 err("could not add i2c adapter");
36
37 d->state |= DVB_USB_STATE_I2C;
38
39 return ret;
40}
41
42int dvb_usb_i2c_exit(struct dvb_usb_device *d)
43{
44 if (d->state & DVB_USB_STATE_I2C)
45 i2c_del_adapter(&d->i2c_adap);
46 d->state &= ~DVB_USB_STATE_I2C;
47 return 0;
48}
49
50int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
51{
52 struct dvb_usb_device *d = fe->dvb->priv;
53 struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
54 int ret = 0;
55
56 /* if there is nothing to initialize */
57 if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
58 d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
59 return 0;
60
61 if (d->tuner_pass_ctrl)
62 d->tuner_pass_ctrl(fe,1,d->pll_addr);
63
64 deb_pll("pll init: %x\n",d->pll_addr);
65 deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
66 d->pll_init[2],d->pll_init[3]);
67
68 if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
69 err("tuner i2c write failed for pll_init.");
70 ret = -EREMOTEIO;
71 }
72 msleep(1);
73
74 if (d->tuner_pass_ctrl)
75 d->tuner_pass_ctrl(fe,0,d->pll_addr);
76 return ret;
77}
78EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
79
80int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
81{
82 struct dvb_usb_device *d = fe->dvb->priv;
83
84 deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
85
86 b[0] = d->pll_addr << 1;
87 dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
88
89 deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
90
91 return 0;
92}
93EXPORT_SYMBOL(dvb_usb_pll_set);
94
95int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
96{
97 struct dvb_usb_device *d = fe->dvb->priv;
98 int ret = 0;
99 u8 b[5];
100 struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
101
102 dvb_usb_pll_set(fe,fep,b);
103
104 if (d->tuner_pass_ctrl)
105 d->tuner_pass_ctrl(fe,1,d->pll_addr);
106
107 if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
108 err("tuner i2c write failed for pll_set.");
109 ret = -EREMOTEIO;
110 }
111 msleep(1);
112
113 if (d->tuner_pass_ctrl)
114 d->tuner_pass_ctrl(fe,0,d->pll_addr);
115
116 return ret;
117}
118EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
new file mode 100644
index 0000000000..bcb3419186
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -0,0 +1,83 @@
1/* dvb-usb-ids.h is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see
4 * dvb-usb-init.c for copyright information.
5 *
6 * a header file containing define's for the USB device supported by the
7 * various drivers.
8 */
9#ifndef _DVB_USB_IDS_H_
10#define _DVB_USB_IDS_H_
11
12/* Vendor IDs */
13#define USB_VID_ADSTECH 0x06e1
14#define USB_VID_ANCHOR 0x0547
15#define USB_VID_AVERMEDIA_UNK 0x14aa
16#define USB_VID_AVERMEDIA 0x07ca
17#define USB_VID_COMPRO 0x185b
18#define USB_VID_COMPRO_UNK 0x145f
19#define USB_VID_CYPRESS 0x04b4
20#define USB_VID_DIBCOM 0x10b8
21#define USB_VID_DVICO 0x0fe9
22#define USB_VID_EMPIA 0xeb1a
23#define USB_VID_GRANDTEC 0x5032
24#define USB_VID_HANFTEK 0x15f4
25#define USB_VID_HAUPPAUGE 0x2040
26#define USB_VID_HYPER_PALTEK 0x1025
27#define USB_VID_VISIONPLUS 0x13d3
28#define USB_VID_TWINHAN 0x1822
29#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
30
31/* Product IDs */
32#define USB_PID_ADSTECH_USB2_COLD 0xa333
33#define USB_PID_ADSTECH_USB2_WARM 0xa334
34#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
35#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
36#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
37#define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801
38#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
39#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
40#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
41#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
42#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
43#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9
44#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
45#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
46#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
47#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
48#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
49#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
50#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
51#define USB_PID_TWINHAN_VP7041_COLD 0x3201
52#define USB_PID_TWINHAN_VP7041_WARM 0x3202
53#define USB_PID_TWINHAN_VP7045_COLD 0x3205
54#define USB_PID_TWINHAN_VP7045_WARM 0x3206
55#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
56#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
57#define USB_PID_TWINHAN_VP7021_COLD 0x3207
58#define USB_PID_TWINHAN_VP7021_WARM 0x3208
59#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
60#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
61#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
62#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
63#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
64#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
65#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
66#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
67#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
68#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
69#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
70#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
71#define USB_PID_DTT200U_COLD 0x0201
72#define USB_PID_DTT200U_WARM 0x0301
73#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
74#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
75#define USB_PID_NEBULA_DIGITV 0x0201
76#define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00
77#define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10
78#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
79#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01
80#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11
81
82
83#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
new file mode 100644
index 0000000000..3aadec974c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -0,0 +1,211 @@
1/*
2 * DVB USB library - provides a generic interface for a DVB USB device driver.
3 *
4 * dvb-usb-init.c
5 *
6 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation, version 2.
11 *
12 * see Documentation/dvb/README.dvb-usb for more information
13 */
14#include "dvb-usb-common.h"
15
16/* debug */
17int dvb_usb_debug;
18module_param_named(debug,dvb_usb_debug, int, 0644);
19MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS);
20
21/* general initialization functions */
22int dvb_usb_exit(struct dvb_usb_device *d)
23{
24 deb_info("state before exiting everything: %x\n",d->state);
25 dvb_usb_remote_exit(d);
26 dvb_usb_fe_exit(d);
27 dvb_usb_i2c_exit(d);
28 dvb_usb_dvb_exit(d);
29 dvb_usb_urb_exit(d);
30 deb_info("state should be zero now: %x\n",d->state);
31 d->state = DVB_USB_STATE_INIT;
32 kfree(d->priv);
33 kfree(d);
34 return 0;
35}
36
37static int dvb_usb_init(struct dvb_usb_device *d)
38{
39 int ret = 0;
40
41 sema_init(&d->usb_sem, 1);
42 sema_init(&d->i2c_sem, 1);
43
44 d->state = DVB_USB_STATE_INIT;
45
46/* check the capabilites and set appropriate variables */
47
48/* speed - when running at FULL speed we need a HW PID filter */
49 if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) {
50 err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a HW PID filter)");
51 return -ENODEV;
52 }
53
54 if ((d->udev->speed == USB_SPEED_FULL && d->props.caps & DVB_USB_HAS_PID_FILTER) ||
55 (d->props.caps & DVB_USB_NEED_PID_FILTERING)) {
56 info("will use the device's hw PID filter.");
57 d->pid_filtering = 1;
58 d->max_feed_count = d->props.pid_filter_count;
59 } else {
60 info("will pass the complete MPEG2 transport stream to the demuxer.");
61 d->pid_filtering = 0;
62 d->max_feed_count = 255;
63 }
64
65 if (d->props.power_ctrl)
66 d->props.power_ctrl(d,1);
67
68 if ((ret = dvb_usb_urb_init(d)) ||
69 (ret = dvb_usb_dvb_init(d)) ||
70 (ret = dvb_usb_i2c_init(d)) ||
71 (ret = dvb_usb_fe_init(d))) {
72 dvb_usb_exit(d);
73 return ret;
74 }
75
76 if ((ret = dvb_usb_remote_init(d)))
77 err("could not initialize remote control.");
78
79 if (d->props.power_ctrl)
80 d->props.power_ctrl(d,0);
81
82 return 0;
83}
84
85/* determine the name and the state of the just found USB device */
86static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_properties *props, int *cold)
87{
88 int i,j;
89 struct dvb_usb_device_description *desc = NULL;
90 *cold = -1;
91
92 for (i = 0; i < props->num_device_descs; i++) {
93
94 for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) {
95 deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
96 if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
97 props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
98 *cold = 1;
99 desc = &props->devices[i];
100 break;
101 }
102 }
103
104 if (desc != NULL)
105 break;
106
107 for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) {
108 deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
109 if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
110 props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
111 *cold = 0;
112 desc = &props->devices[i];
113 break;
114 }
115 }
116 }
117
118 if (desc != NULL && props->identify_state != NULL)
119 props->identify_state(udev,props,&desc,cold);
120
121 return desc;
122}
123
124/*
125 * USB
126 */
127int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner)
128{
129 struct usb_device *udev = interface_to_usbdev(intf);
130 struct dvb_usb_device *d = NULL;
131 struct dvb_usb_device_description *desc = NULL;
132
133 int ret = -ENOMEM,cold=0;
134
135 if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
136 deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
137 return -ENODEV;
138 }
139
140 if (cold) {
141 info("found a '%s' in cold state, will try to load a firmware",desc->name);
142 ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl);
143 } else {
144 info("found a '%s' in warm state.",desc->name);
145 d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
146 if (d == NULL) {
147 err("no memory for 'struct dvb_usb_device'");
148 return ret;
149 }
150 memset(d,0,sizeof(struct dvb_usb_device));
151
152 d->udev = udev;
153 memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
154 d->desc = desc;
155 d->owner = owner;
156
157 if (d->props.size_of_priv > 0) {
158 d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
159 if (d->priv == NULL) {
160 err("no memory for priv in 'struct dvb_usb_device'");
161 kfree(d);
162 return -ENOMEM;
163 }
164 memset(d->priv,0,d->props.size_of_priv);
165 }
166
167 usb_set_intfdata(intf, d);
168
169 ret = dvb_usb_init(d);
170 }
171
172 if (ret == 0)
173 info("%s successfully initialized and connected.",desc->name);
174 else
175 info("%s error while loading driver (%d)",desc->name,ret);
176 return ret;
177}
178EXPORT_SYMBOL(dvb_usb_device_init);
179
180void dvb_usb_device_exit(struct usb_interface *intf)
181{
182 struct dvb_usb_device *d = usb_get_intfdata(intf);
183 const char *name = "generic DVB-USB module";
184
185 usb_set_intfdata(intf,NULL);
186 if (d != NULL && d->desc != NULL) {
187 name = d->desc->name;
188 dvb_usb_exit(d);
189 }
190 info("%s successfully deinitialized and disconnected.",name);
191
192}
193EXPORT_SYMBOL(dvb_usb_device_exit);
194
195/* module stuff */
196static int __init dvb_usb_module_init(void)
197{
198 return 0;
199}
200
201static void __exit dvb_usb_module_exit(void)
202{
203}
204
205module_init (dvb_usb_module_init);
206module_exit (dvb_usb_module_exit);
207
208MODULE_VERSION("0.3");
209MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
210MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
211MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
new file mode 100644
index 0000000000..9f1e23f82b
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -0,0 +1,175 @@
1/* dvb-usb-remote.c is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * This file contains functions for initializing the the input-device and for handling remote-control-queries.
7 */
8#include "dvb-usb-common.h"
9
10/* Remote-control poll function - called every dib->rc_query_interval ms to see
11 * whether the remote control has received anything.
12 *
13 * TODO: Fix the repeat rate of the input device.
14 */
15static void dvb_usb_read_remote_control(void *data)
16{
17 struct dvb_usb_device *d = data;
18 u32 event;
19 int state;
20
21 /* TODO: need a lock here. We can simply skip checking for the remote control
22 if we're busy. */
23
24 if (d->props.rc_query(d,&event,&state)) {
25 err("error while querying for an remote control event.");
26 goto schedule;
27 }
28
29
30 switch (state) {
31 case REMOTE_NO_KEY_PRESSED:
32 break;
33 case REMOTE_KEY_PRESSED:
34 deb_rc("key pressed\n");
35 d->last_event = event;
36 case REMOTE_KEY_REPEAT:
37 deb_rc("key repeated\n");
38 input_event(&d->rc_input_dev, EV_KEY, event, 1);
39 input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
40 input_sync(&d->rc_input_dev);
41 break;
42 default:
43 break;
44 }
45
46/* improved repeat handling ???
47 switch (state) {
48 case REMOTE_NO_KEY_PRESSED:
49 deb_rc("NO KEY PRESSED\n");
50 if (d->last_state != REMOTE_NO_KEY_PRESSED) {
51 deb_rc("releasing event %d\n",d->last_event);
52 input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
53 input_sync(&d->rc_input_dev);
54 }
55 d->last_state = REMOTE_NO_KEY_PRESSED;
56 d->last_event = 0;
57 break;
58 case REMOTE_KEY_PRESSED:
59 deb_rc("KEY PRESSED\n");
60 deb_rc("pressing event %d\n",event);
61
62 input_event(&d->rc_input_dev, EV_KEY, event, 1);
63 input_sync(&d->rc_input_dev);
64
65 d->last_event = event;
66 d->last_state = REMOTE_KEY_PRESSED;
67 break;
68 case REMOTE_KEY_REPEAT:
69 deb_rc("KEY_REPEAT\n");
70 if (d->last_state != REMOTE_NO_KEY_PRESSED) {
71 deb_rc("repeating event %d\n",d->last_event);
72 input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2);
73 input_sync(&d->rc_input_dev);
74 d->last_state = REMOTE_KEY_REPEAT;
75 }
76 default:
77 break;
78 }
79*/
80
81schedule:
82 schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
83}
84
85int dvb_usb_remote_init(struct dvb_usb_device *d)
86{
87 int i;
88 if (d->props.rc_key_map == NULL)
89 return 0;
90
91 /* Initialise the remote-control structures.*/
92 init_input_dev(&d->rc_input_dev);
93
94 d->rc_input_dev.evbit[0] = BIT(EV_KEY);
95 d->rc_input_dev.keycodesize = sizeof(unsigned char);
96 d->rc_input_dev.keycodemax = KEY_MAX;
97 d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver";
98
99 /* set the bits for the keys */
100 deb_rc("key map size: %d\n",d->props.rc_key_map_size);
101 for (i = 0; i < d->props.rc_key_map_size; i++) {
102 deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
103 set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit);
104 }
105
106 /* Start the remote-control polling. */
107 if (d->props.rc_interval < 40)
108 d->props.rc_interval = 100; /* default */
109
110 /* setting these two values to non-zero, we have to manage key repeats */
111 d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval;
112 d->rc_input_dev.rep[REP_DELAY] = d->props.rc_interval + 150;
113
114 input_register_device(&d->rc_input_dev);
115
116 INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d);
117
118 info("schedule remote query interval to %d msecs.",d->props.rc_interval);
119 schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
120
121 d->state |= DVB_USB_STATE_REMOTE;
122
123 return 0;
124}
125
126int dvb_usb_remote_exit(struct dvb_usb_device *d)
127{
128 if (d->state & DVB_USB_STATE_REMOTE) {
129 cancel_delayed_work(&d->rc_query_work);
130 flush_scheduled_work();
131 input_unregister_device(&d->rc_input_dev);
132 }
133 d->state &= ~DVB_USB_STATE_REMOTE;
134 return 0;
135}
136
137#define DVB_USB_RC_NEC_EMPTY 0x00
138#define DVB_USB_RC_NEC_KEY_PRESSED 0x01
139#define DVB_USB_RC_NEC_KEY_REPEATED 0x02
140int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
141 u8 keybuf[5], u32 *event, int *state)
142{
143 int i;
144 struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
145 *event = 0;
146 *state = REMOTE_NO_KEY_PRESSED;
147 switch (keybuf[0]) {
148 case DVB_USB_RC_NEC_EMPTY:
149 break;
150 case DVB_USB_RC_NEC_KEY_PRESSED:
151 if ((u8) ~keybuf[1] != keybuf[2] ||
152 (u8) ~keybuf[3] != keybuf[4]) {
153 deb_err("remote control checksum failed.\n");
154 break;
155 }
156 /* See if we can match the raw key code. */
157 for (i = 0; i < sizeof(keymap)/sizeof(struct dvb_usb_rc_key); i++)
158 if (keymap[i].custom == keybuf[1] &&
159 keymap[i].data == keybuf[3]) {
160 *event = keymap[i].event;
161 *state = REMOTE_KEY_PRESSED;
162 break;
163 }
164 deb_err("key mapping failed - no appropriate key found in keymapping\n");
165 break;
166 case DVB_USB_RC_NEC_KEY_REPEATED:
167 *state = REMOTE_KEY_REPEAT;
168 break;
169 default:
170 deb_err("unkown type of remote status: %d\n",keybuf[0]);
171 break;
172 }
173 return 0;
174}
175EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
new file mode 100644
index 0000000000..83d476fb41
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -0,0 +1,211 @@
1/* dvb-usb-urb.c is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * This file contains functions for initializing and handling the
7 * USB and URB stuff.
8 */
9#include "dvb-usb-common.h"
10
11int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
12 u16 rlen, int delay_ms)
13{
14 int actlen,ret = -ENOMEM;
15
16 if (d->props.generic_bulk_ctrl_endpoint == 0) {
17 err("endpoint for generic control not specified.");
18 return -EINVAL;
19 }
20
21 if (wbuf == NULL || wlen == 0)
22 return -EINVAL;
23
24 if ((ret = down_interruptible(&d->usb_sem)))
25 return ret;
26
27 debug_dump(wbuf,wlen,deb_xfer);
28
29 ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev,
30 d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen,
31 2*HZ);
32
33 if (ret)
34 err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
35 else
36 ret = actlen != wlen ? -1 : 0;
37
38 /* an answer is expected, and no error before */
39 if (!ret && rbuf && rlen) {
40 if (delay_ms)
41 msleep(delay_ms);
42
43 ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev,
44 d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen,
45 2*HZ);
46
47 if (ret)
48 err("recv bulk message failed: %d",ret);
49 else
50 debug_dump(rbuf,actlen,deb_xfer);
51 }
52
53 up(&d->usb_sem);
54 return ret;
55}
56EXPORT_SYMBOL(dvb_usb_generic_rw);
57
58int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
59{
60 return dvb_usb_generic_rw(d,buf,len,NULL,0,0);
61}
62EXPORT_SYMBOL(dvb_usb_generic_write);
63
64static void dvb_usb_bulk_urb_complete(struct urb *urb, struct pt_regs *ptregs)
65{
66 struct dvb_usb_device *d = urb->context;
67
68 deb_ts("bulk urb completed. feedcount: %d, status: %d, length: %d\n",d->feedcount,urb->status,
69 urb->actual_length);
70
71 switch (urb->status) {
72 case 0: /* success */
73 case -ETIMEDOUT: /* NAK */
74 break;
75 case -ECONNRESET: /* kill */
76 case -ENOENT:
77 case -ESHUTDOWN:
78 return;
79 default: /* error */
80 deb_ts("urb completition error %d.", urb->status);
81 break;
82 }
83
84 if (d->feedcount > 0 && urb->actual_length > 0) {
85 if (d->state & DVB_USB_STATE_DVB)
86 dvb_dmx_swfilter(&d->demux, (u8*) urb->transfer_buffer,urb->actual_length);
87 } else
88 deb_ts("URB dropped because of feedcount.\n");
89
90 usb_submit_urb(urb,GFP_ATOMIC);
91}
92
93int dvb_usb_urb_kill(struct dvb_usb_device *d)
94{
95 int i;
96 for (i = 0; i < d->urbs_submitted; i++) {
97 deb_info("killing URB no. %d.\n",i);
98
99 /* stop the URB */
100 usb_kill_urb(d->urb_list[i]);
101 }
102 d->urbs_submitted = 0;
103 return 0;
104}
105
106int dvb_usb_urb_submit(struct dvb_usb_device *d)
107{
108 int i,ret;
109 for (i = 0; i < d->urbs_initialized; i++) {
110 deb_info("submitting URB no. %d\n",i);
111 if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) {
112 err("could not submit URB no. %d - get them all back\n",i);
113 dvb_usb_urb_kill(d);
114 return ret;
115 }
116 d->urbs_submitted++;
117 }
118 return 0;
119}
120
121static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
122{
123 int i,bufsize = d->props.urb.count * d->props.urb.u.bulk.buffersize;
124
125 deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
126 /* allocate the actual buffer for the URBs */
127 if ((d->buffer = usb_buffer_alloc(d->udev, bufsize, SLAB_ATOMIC, &d->dma_handle)) == NULL) {
128 deb_info("not enough memory for urb-buffer allocation.\n");
129 return -ENOMEM;
130 }
131 deb_info("allocation successful\n");
132 memset(d->buffer,0,bufsize);
133
134 d->state |= DVB_USB_STATE_URB_BUF;
135
136 /* allocate the URBs */
137 for (i = 0; i < d->props.urb.count; i++) {
138 if (!(d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
139 return -ENOMEM;
140 }
141
142 usb_fill_bulk_urb( d->urb_list[i], d->udev,
143 usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
144 &d->buffer[i*d->props.urb.u.bulk.buffersize],
145 d->props.urb.u.bulk.buffersize,
146 dvb_usb_bulk_urb_complete, d);
147
148 d->urb_list[i]->transfer_flags = 0;
149 d->urbs_initialized++;
150 }
151 return 0;
152}
153
154int dvb_usb_urb_init(struct dvb_usb_device *d)
155{
156 /*
157 * when reloading the driver w/o replugging the device
158 * sometimes a timeout occures, this helps
159 */
160 if (d->props.generic_bulk_ctrl_endpoint != 0) {
161 usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
162 usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
163 }
164 usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
165
166 /* allocate the array for the data transfer URBs */
167 d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
168 if (d->urb_list == NULL)
169 return -ENOMEM;
170 memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *));
171 d->state |= DVB_USB_STATE_URB_LIST;
172
173 switch (d->props.urb.type) {
174 case DVB_USB_BULK:
175 return dvb_usb_bulk_urb_init(d);
176 case DVB_USB_ISOC:
177 err("isochronous transfer not yet implemented in dvb-usb.");
178 return -EINVAL;
179 default:
180 err("unkown URB-type for data transfer.");
181 return -EINVAL;
182 }
183}
184
185int dvb_usb_urb_exit(struct dvb_usb_device *d)
186{
187 int i;
188
189 dvb_usb_urb_kill(d);
190
191 if (d->state & DVB_USB_STATE_URB_LIST) {
192 for (i = 0; i < d->urbs_initialized; i++) {
193 if (d->urb_list[i] != NULL) {
194 deb_info("freeing URB no. %d.\n",i);
195 /* free the URBs */
196 usb_free_urb(d->urb_list[i]);
197 }
198 }
199 d->urbs_initialized = 0;
200 /* free the urb array */
201 kfree(d->urb_list);
202 d->state &= ~DVB_USB_STATE_URB_LIST;
203 }
204
205 if (d->state & DVB_USB_STATE_URB_BUF)
206 usb_buffer_free(d->udev, d->props.urb.u.bulk.buffersize * d->props.urb.count,
207 d->buffer, d->dma_handle);
208
209 d->state &= ~DVB_USB_STATE_URB_BUF;
210 return 0;
211}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
new file mode 100644
index 0000000000..abcee1943f
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -0,0 +1,315 @@
1/* dvb-usb.h is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * the headerfile, all dvb-usb-drivers have to include.
7 */
8#ifndef __DVB_USB_H__
9#define __DVB_USB_H__
10
11#include <linux/config.h>
12#include <linux/input.h>
13#include <linux/module.h>
14#include <linux/usb.h>
15
16#include "dvb_frontend.h"
17#include "dvb_demux.h"
18#include "dvb_net.h"
19#include "dmxdev.h"
20
21#include "dvb-pll.h"
22
23#include "dvb-usb-ids.h"
24
25/* debug */
26#ifdef CONFIG_DVB_USB_DEBUG
27#define dprintk(var,level,args...) \
28 do { if ((var & level)) { printk(args); } } while (0)
29
30#define debug_dump(b,l,func) {\
31 int loop_; \
32 for (loop_ = 0; loop_ < l; loop_++) func("%02x ", b[loop_]); \
33 func("\n");\
34}
35#define DVB_USB_DEBUG_STATUS
36#else
37#define dprintk(args...)
38#define debug_dump(b,l,func)
39
40#define DVB_USB_DEBUG_STATUS " (debugging is not enabled)"
41
42#endif
43
44/* generic log methods - taken from usb.h */
45#ifndef DVB_USB_LOG_PREFIX
46 #define DVB_USB_LOG_PREFIX "dvb-usb (please define a log prefix)"
47#endif
48
49#undef err
50#define err(format, arg...) printk(KERN_ERR DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
51#undef info
52#define info(format, arg...) printk(KERN_INFO DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
53#undef warn
54#define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
55
56/**
57 * struct dvb_usb_device_description - name and its according USB IDs
58 * @name: real name of the box, regardless which DVB USB device class is in use
59 * @cold_ids: array of struct usb_device_id which describe the device in
60 * pre-firmware state
61 * @warm_ids: array of struct usb_device_id which describe the device in
62 * post-firmware state
63 *
64 * Each DVB USB device class can have one or more actual devices, this struct
65 * assigns a name to it.
66 */
67struct dvb_usb_device_description {
68 const char *name;
69
70#define DVB_USB_ID_MAX_NUM 15
71 struct usb_device_id *cold_ids[DVB_USB_ID_MAX_NUM];
72 struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
73};
74
75/**
76 * struct dvb_usb_rc_key - a remote control key and its input-event
77 * @custom: the vendor/custom part of the key
78 * @data: the actual key part
79 * @event: the input event assigned to key identified by custom and data
80 */
81struct dvb_usb_rc_key {
82 u8 custom,data;
83 u32 event;
84};
85
86struct dvb_usb_device;
87
88/**
89 * struct dvb_usb_properties - properties of a dvb-usb-device
90 * @caps: capabilites of the DVB USB device.
91 * @pid_filter_count: number of PID filter position in the optional hardware
92 * PID-filter.
93 *
94 * @usb_ctrl: which USB device-side controller is in use. Needed for firmware
95 * download.
96 * @firmware: name of the firmware file.
97 *
98 * @size_of_priv: how many bytes shall be allocated for the private field
99 * of struct dvb_usb_device.
100 *
101 * @power_ctrl: called to enable/disable power of the device.
102 * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the
103 * device (not URB submitting/killing).
104 * @pid_filter_ctrl: called to en/disable the PID filter, if any.
105 * @pid_filter: called to set/unset a PID for filtering.
106 *
107 * @read_mac_address: called to read the MAC address of the device.
108 *
109 * @frontend_attach: called to attach the possible frontends (fill fe-field
110 * of struct dvb_usb_device).
111 * @tuner_attach: called to attach the correct tuner and to fill pll_addr,
112 * pll_desc and pll_init_buf of struct dvb_usb_device).
113 * @identify_state: called to determine the state (cold or warm), when it
114 * is not distinguishable by the USB IDs.
115 *
116 * @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable
117 * remote control handling).
118 * @rc_key_map_size: number of items in @rc_key_map.
119 * @rc_query: called to query an event event.
120 * @rc_interval: time in ms between two queries.
121 *
122 * @i2c_algo: i2c_algorithm if the device has I2CoverUSB.
123 *
124 * @generic_bulk_ctrl_endpoint: most of the DVB USB devices have a generic
125 * endpoint which received control messages with bulk transfers. When this
126 * is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write-
127 * helper functions.
128 *
129 * @urb: describes the kind of USB transfer used for MPEG2-TS-streaming.
130 * Currently only BULK is implemented
131 *
132 * @num_device_descs: number of struct dvb_usb_device_description in @devices
133 * @devices: array of struct dvb_usb_device_description compatibles with these
134 * properties.
135 */
136struct dvb_usb_properties {
137
138#define DVB_USB_HAS_PID_FILTER 0x01
139#define DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF 0x02
140#define DVB_USB_NEED_PID_FILTERING 0x04
141#define DVB_USB_IS_AN_I2C_ADAPTER 0x08
142 int caps;
143 int pid_filter_count;
144
145#define CYPRESS_AN2135 0
146#define CYPRESS_AN2235 1
147#define CYPRESS_FX2 2
148 int usb_ctrl;
149 const char *firmware;
150
151 int size_of_priv;
152
153 int (*power_ctrl) (struct dvb_usb_device *, int);
154 int (*streaming_ctrl) (struct dvb_usb_device *, int);
155 int (*pid_filter_ctrl) (struct dvb_usb_device *, int);
156 int (*pid_filter) (struct dvb_usb_device *, int, u16, int);
157
158 int (*read_mac_address) (struct dvb_usb_device *, u8 []);
159 int (*frontend_attach) (struct dvb_usb_device *);
160 int (*tuner_attach) (struct dvb_usb_device *);
161
162 int (*identify_state) (struct usb_device *, struct dvb_usb_properties *,
163 struct dvb_usb_device_description **, int *);
164
165/* remote control properties */
166#define REMOTE_NO_KEY_PRESSED 0x00
167#define REMOTE_KEY_PRESSED 0x01
168#define REMOTE_KEY_REPEAT 0x02
169 struct dvb_usb_rc_key *rc_key_map;
170 int rc_key_map_size;
171 int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
172 int rc_interval;
173
174 struct i2c_algorithm *i2c_algo;
175
176 int generic_bulk_ctrl_endpoint;
177
178 struct {
179#define DVB_USB_BULK 1
180#define DVB_USB_ISOC 2
181 int type;
182 int count;
183 int endpoint;
184
185 union {
186 struct {
187 int buffersize; /* per URB */
188 } bulk;
189 struct {
190 int framesperurb;
191 int framesize;
192 } isoc;
193 } u;
194 } urb;
195
196 int num_device_descs;
197 struct dvb_usb_device_description devices[8];
198};
199
200
201/**
202 * struct dvb_usb_device - object of a DVB USB device
203 * @props: copy of the struct dvb_usb_properties this device belongs to.
204 * @desc: pointer to the device's struct dvb_usb_device_description.
205 * @state: initialization and runtime state of the device.
206 *
207 * @udev: pointer to the device's struct usb_device.
208 * @urb_list: array of dynamically allocated struct urb for the MPEG2-TS-
209 * streaming.
210 * @buffer: buffer used to streaming.
211 * @dma_handle: dma_addr_t for buffer.
212 * @urbs_initialized: number of URBs initialized.
213 * @urbs_submitted: number of URBs submitted.
214 * @feedcount: number of reqested feeds (used for streaming-activation)
215 * @pid_filtering: is hardware pid_filtering used or not.
216 * @usb_sem: semaphore of USB control messages (reading needs two messages)
217 * @i2c_sem: semaphore for i2c-transfers
218 * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
219 * @pll_addr: I2C address of the tuner for programming
220 * @pll_init: array containing the initialization buffer
221 * @pll_desc: pointer to the appropriate struct dvb_pll_desc
222 * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod
223 * @dvb_adap: device's dvb_adapter.
224 * @dmxdev: device's dmxdev.
225 * @demux: device's software demuxer.
226 * @dvb_net: device's dvb_net interfaces.
227 * @dvb_frontend: device's frontend.
228 * @max_feed_count: how many feeds can be handled simultaneously by this
229 * device
230 * @fe_sleep: rerouted frontend-sleep function.
231 * @fe_init: rerouted frontend-init (wakeup) function.
232 * @rc_input_dev: input device for the remote control.
233 * @rc_query_work: struct work_struct frequent rc queries
234 * @last_event: last triggered event
235 * @last_state: last state (no, pressed, repeat)
236 * @owner: owner of the dvb_adapter
237 * @priv: private data of the actual driver (allocate by dvb-usb, size defined
238 * in size_of_priv of dvb_usb_properties).
239 */
240struct dvb_usb_device {
241 struct dvb_usb_properties props;
242 struct dvb_usb_device_description *desc;
243
244#define DVB_USB_STATE_INIT 0x000
245#define DVB_USB_STATE_URB_LIST 0x001
246#define DVB_USB_STATE_URB_BUF 0x002
247#define DVB_USB_STATE_DVB 0x004
248#define DVB_USB_STATE_I2C 0x008
249#define DVB_USB_STATE_REMOTE 0x010
250#define DVB_USB_STATE_URB_SUBMIT 0x020
251 int state;
252
253 /* usb */
254 struct usb_device *udev;
255 struct urb **urb_list;
256 u8 *buffer;
257 dma_addr_t dma_handle;
258 int urbs_initialized;
259 int urbs_submitted;
260
261 int feedcount;
262 int pid_filtering;
263
264 /* locking */
265 struct semaphore usb_sem;
266
267 /* i2c */
268 struct semaphore i2c_sem;
269 struct i2c_adapter i2c_adap;
270
271 /* tuner programming information */
272 u8 pll_addr;
273 u8 pll_init[4];
274 struct dvb_pll_desc *pll_desc;
275 int (*tuner_pass_ctrl)(struct dvb_frontend *, int, u8);
276
277 /* dvb */
278 struct dvb_adapter dvb_adap;
279 struct dmxdev dmxdev;
280 struct dvb_demux demux;
281 struct dvb_net dvb_net;
282 struct dvb_frontend* fe;
283 int max_feed_count;
284
285 int (*fe_sleep) (struct dvb_frontend *);
286 int (*fe_init) (struct dvb_frontend *);
287
288 /* remote control */
289 struct input_dev rc_input_dev;
290 struct work_struct rc_query_work;
291 u32 last_event;
292 int last_state;
293
294 struct module *owner;
295
296 void *priv;
297};
298
299extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *);
300extern void dvb_usb_device_exit(struct usb_interface *);
301
302/* the generic read/write method for device control */
303extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int);
304extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
305
306/* commonly used remote control parsing */
307extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
308
309/* commonly used pll init and set functions */
310extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
311extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
312extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
313
314
315#endif
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
new file mode 100644
index 0000000000..9d83781aef
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -0,0 +1,236 @@
1/* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2
2 * DVB-T receiver.
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, version 2.
9 *
10 * see Documentation/dvb/README.dvb-usb for more information
11 */
12#include "dibusb.h"
13
14static int debug;
15module_param(debug, int, 0644);
16MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
17
18#define deb_rc(args...) dprintk(debug,0x01,args)
19#define deb_ee(args...) dprintk(debug,0x02,args)
20
21/* Hauppauge NOVA-T USB2 keys */
22static struct dvb_usb_rc_key haupp_rc_keys [] = {
23 { 0x1e, 0x00, KEY_0 },
24 { 0x1e, 0x01, KEY_1 },
25 { 0x1e, 0x02, KEY_2 },
26 { 0x1e, 0x03, KEY_3 },
27 { 0x1e, 0x04, KEY_4 },
28 { 0x1e, 0x05, KEY_5 },
29 { 0x1e, 0x06, KEY_6 },
30 { 0x1e, 0x07, KEY_7 },
31 { 0x1e, 0x08, KEY_8 },
32 { 0x1e, 0x09, KEY_9 },
33 { 0x1e, 0x0a, KEY_KPASTERISK },
34 { 0x1e, 0x0b, KEY_RED },
35 { 0x1e, 0x0c, KEY_RADIO },
36 { 0x1e, 0x0d, KEY_MENU },
37 { 0x1e, 0x0e, KEY_GRAVE }, /* # */
38 { 0x1e, 0x0f, KEY_MUTE },
39 { 0x1e, 0x10, KEY_VOLUMEUP },
40 { 0x1e, 0x11, KEY_VOLUMEDOWN },
41 { 0x1e, 0x12, KEY_CHANNEL },
42 { 0x1e, 0x14, KEY_UP },
43 { 0x1e, 0x15, KEY_DOWN },
44 { 0x1e, 0x16, KEY_LEFT },
45 { 0x1e, 0x17, KEY_RIGHT },
46 { 0x1e, 0x18, KEY_VIDEO },
47 { 0x1e, 0x19, KEY_AUDIO },
48 { 0x1e, 0x1a, KEY_MEDIA },
49 { 0x1e, 0x1b, KEY_EPG },
50 { 0x1e, 0x1c, KEY_TV },
51 { 0x1e, 0x1e, KEY_NEXT },
52 { 0x1e, 0x1f, KEY_BACK },
53 { 0x1e, 0x20, KEY_CHANNELUP },
54 { 0x1e, 0x21, KEY_CHANNELDOWN },
55 { 0x1e, 0x24, KEY_LAST }, /* Skip backwards */
56 { 0x1e, 0x25, KEY_OK },
57 { 0x1e, 0x29, KEY_BLUE},
58 { 0x1e, 0x2e, KEY_GREEN },
59 { 0x1e, 0x30, KEY_PAUSE },
60 { 0x1e, 0x32, KEY_REWIND },
61 { 0x1e, 0x34, KEY_FASTFORWARD },
62 { 0x1e, 0x35, KEY_PLAY },
63 { 0x1e, 0x36, KEY_STOP },
64 { 0x1e, 0x37, KEY_RECORD },
65 { 0x1e, 0x38, KEY_YELLOW },
66 { 0x1e, 0x3b, KEY_GOTO },
67 { 0x1e, 0x3d, KEY_POWER },
68};
69
70/* Firmware bug? sometimes, when a new key is pressed, the previous pressed key
71 * is delivered. No workaround yet, maybe a new firmware.
72 */
73static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
74{
75 u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom;
76 u16 raw;
77 int i;
78 struct dibusb_state *st = d->priv;
79
80 dvb_usb_generic_rw(d,cmd,2,key,5,0);
81
82 *state = REMOTE_NO_KEY_PRESSED;
83 switch (key[0]) {
84 case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
85 raw = ((key[1] << 8) | key[2]) >> 3;
86 toggle = !!(raw & 0x800);
87 data = raw & 0x3f;
88 custom = (raw >> 6) & 0x1f;
89
90 deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle);
91
92 for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) {
93 deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom);
94 if (haupp_rc_keys[i].data == data &&
95 haupp_rc_keys[i].custom == custom) {
96 *event = haupp_rc_keys[i].event;
97 *state = REMOTE_KEY_PRESSED;
98 if (st->old_toggle == toggle) {
99 if (st->last_repeat_count++ < 2)
100 *state = REMOTE_NO_KEY_PRESSED;
101 } else {
102 st->last_repeat_count = 0;
103 st->old_toggle = toggle;
104 }
105 break;
106 }
107 }
108
109 break;
110 case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
111 default:
112 break;
113 }
114
115 return 0;
116}
117
118static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
119{
120 int i;
121 u8 b;
122
123 mac[0] = 0x00;
124 mac[1] = 0x0d;
125 mac[2] = 0xfe;
126
127 /* this is a complete guess, but works for my box */
128 for (i = 136; i < 139; i++) {
129 dibusb_read_eeprom_byte(d,i, &b);
130
131 mac[5 - (i - 136)] = b;
132
133/* deb_ee("%02x ",b);
134 if ((i+1) % 16 == 0)
135 deb_ee("\n");*/
136 }
137
138 return 0;
139}
140
141/* USB Driver stuff */
142static struct dvb_usb_properties nova_t_properties;
143
144static int nova_t_probe(struct usb_interface *intf,
145 const struct usb_device_id *id)
146{
147 return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE);
148}
149
150/* do not change the order of the ID table */
151static struct usb_device_id nova_t_table [] = {
152/* 00 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) },
153/* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
154 { } /* Terminating entry */
155};
156MODULE_DEVICE_TABLE (usb, nova_t_table);
157
158static struct dvb_usb_properties nova_t_properties = {
159 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
160 .pid_filter_count = 32,
161
162 .usb_ctrl = CYPRESS_FX2,
163 .firmware = "dvb-usb-nova-t-usb2-01.fw",
164
165 .size_of_priv = sizeof(struct dibusb_state),
166
167 .streaming_ctrl = dibusb2_0_streaming_ctrl,
168 .pid_filter = dibusb_pid_filter,
169 .pid_filter_ctrl = dibusb_pid_filter_ctrl,
170 .power_ctrl = dibusb2_0_power_ctrl,
171 .frontend_attach = dibusb_dib3000mc_frontend_attach,
172 .tuner_attach = dibusb_dib3000mc_tuner_attach,
173 .read_mac_address = nova_t_read_mac_address,
174
175 .rc_interval = 100,
176 .rc_key_map = haupp_rc_keys,
177 .rc_key_map_size = ARRAY_SIZE(haupp_rc_keys),
178 .rc_query = nova_t_rc_query,
179
180 .i2c_algo = &dibusb_i2c_algo,
181
182 .generic_bulk_ctrl_endpoint = 0x01,
183 /* parameter for the MPEG2-data transfer */
184 .urb = {
185 .type = DVB_USB_BULK,
186 .count = 7,
187 .endpoint = 0x06,
188 .u = {
189 .bulk = {
190 .buffersize = 4096,
191 }
192 }
193 },
194
195 .num_device_descs = 1,
196 .devices = {
197 { "Hauppauge WinTV-NOVA-T usb2",
198 { &nova_t_table[0], NULL },
199 { &nova_t_table[1], NULL },
200 },
201 }
202};
203
204static struct usb_driver nova_t_driver = {
205 .owner = THIS_MODULE,
206 .name = "Hauppauge WinTV-NOVA-T usb2",
207 .probe = nova_t_probe,
208 .disconnect = dvb_usb_device_exit,
209 .id_table = nova_t_table,
210};
211
212/* module stuff */
213static int __init nova_t_module_init(void)
214{
215 int result;
216 if ((result = usb_register(&nova_t_driver))) {
217 err("usb_register failed. Error number %d",result);
218 return result;
219 }
220
221 return 0;
222}
223
224static void __exit nova_t_module_exit(void)
225{
226 /* deregister this driver from the USB subsystem */
227 usb_deregister(&nova_t_driver);
228}
229
230module_init (nova_t_module_init);
231module_exit (nova_t_module_exit);
232
233MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
234MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2");
235MODULE_VERSION("1.0");
236MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
new file mode 100644
index 0000000000..aa560422ce
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -0,0 +1,162 @@
1/* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0
2 * DVB-T receiver.
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, version 2.
9 *
10 * see Documentation/dvb/README.dvb-usb for more information
11 */
12#include "dibusb.h"
13
14#include "mt352.h"
15
16static int umt_mt352_demod_init(struct dvb_frontend *fe)
17{
18 static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
19 static u8 mt352_reset[] = { 0x50, 0x80 };
20 static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
21 static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
22 static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
23
24 static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
25 static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
26 static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
27 static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
28 static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
29
30 static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
31 static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
32
33 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
34 udelay(2000);
35 mt352_write(fe, mt352_reset, sizeof(mt352_reset));
36 mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
37
38 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
39 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
40
41 mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
42 mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
43 mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
44 mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
45 mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
46
47 mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
48 mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
49
50 return 0;
51}
52
53static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
54{
55 struct mt352_config umt_config;
56
57 memset(&umt_config,0,sizeof(struct mt352_config));
58 umt_config.demod_init = umt_mt352_demod_init;
59 umt_config.demod_address = 0xf;
60 umt_config.pll_set = dvb_usb_pll_set;
61
62 d->fe = mt352_attach(&umt_config, &d->i2c_adap);
63
64 return 0;
65}
66
67static int umt_tuner_attach (struct dvb_usb_device *d)
68{
69 d->pll_addr = 0x61;
70 d->pll_desc = &dvb_pll_tua6034;
71 return 0;
72}
73
74/* USB Driver stuff */
75static struct dvb_usb_properties umt_properties;
76
77static int umt_probe(struct usb_interface *intf,
78 const struct usb_device_id *id)
79{
80 if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0)
81 return 0;
82 return -EINVAL;
83}
84
85/* do not change the order of the ID table */
86static struct usb_device_id umt_table [] = {
87/* 00 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
88/* 01 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
89 { } /* Terminating entry */
90};
91MODULE_DEVICE_TABLE (usb, umt_table);
92
93static struct dvb_usb_properties umt_properties = {
94 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
95
96 .usb_ctrl = CYPRESS_FX2,
97 .firmware = "dvb-usb-umt-010-02.fw",
98
99 .size_of_priv = sizeof(struct dibusb_state),
100
101 .streaming_ctrl = dibusb2_0_streaming_ctrl,
102 .power_ctrl = dibusb_power_ctrl,
103 .frontend_attach = umt_mt352_frontend_attach,
104 .tuner_attach = umt_tuner_attach,
105
106 .i2c_algo = &dibusb_i2c_algo,
107
108 .generic_bulk_ctrl_endpoint = 0x01,
109 /* parameter for the MPEG2-data transfer */
110 .urb = {
111 .type = DVB_USB_BULK,
112 .count = 20,
113 .endpoint = 0x06,
114 .u = {
115 .bulk = {
116 .buffersize = 512,
117 }
118 }
119 },
120
121 .num_device_descs = 1,
122 .devices = {
123 { "Hanftek UMT-010 DVB-T USB2.0",
124 { &umt_table[0], NULL },
125 { &umt_table[1], NULL },
126 },
127 }
128};
129
130static struct usb_driver umt_driver = {
131 .owner = THIS_MODULE,
132 .name = "HanfTek UMT-010 USB2.0 DVB-T devices",
133 .probe = umt_probe,
134 .disconnect = dvb_usb_device_exit,
135 .id_table = umt_table,
136};
137
138/* module stuff */
139static int __init umt_module_init(void)
140{
141 int result;
142 if ((result = usb_register(&umt_driver))) {
143 err("usb_register failed. Error number %d",result);
144 return result;
145 }
146
147 return 0;
148}
149
150static void __exit umt_module_exit(void)
151{
152 /* deregister this driver from the USB subsystem */
153 usb_deregister(&umt_driver);
154}
155
156module_init (umt_module_init);
157module_exit (umt_module_exit);
158
159MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
160MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device");
161MODULE_VERSION("1.0");
162MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
new file mode 100644
index 0000000000..2746edfecc
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -0,0 +1,196 @@
1/* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0
2 * DVB-T receiver.
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * Thanks to Twinhan who kindly provided hardware and information.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation, version 2.
11 *
12 * see Documentation/dvb/README.dvb-usb for more information
13 *
14 */
15#include "vp7045.h"
16
17/* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT
18 *
19 * Programming is hidden inside the firmware, so set_frontend is very easy.
20 * Even though there is a Firmware command that one can use to access the demod
21 * via its registers. This is used for status information.
22 */
23
24struct vp7045_fe_state {
25 struct dvb_frontend fe;
26 struct dvb_usb_device *d;
27};
28
29
30static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
31{
32 struct vp7045_fe_state *state = fe->demodulator_priv;
33 u8 s0 = vp7045_read_reg(state->d,0x00),
34 s1 = vp7045_read_reg(state->d,0x01),
35 s3 = vp7045_read_reg(state->d,0x03);
36
37 *status = 0;
38 if (s0 & (1 << 4))
39 *status |= FE_HAS_CARRIER;
40 if (s0 & (1 << 1))
41 *status |= FE_HAS_VITERBI;
42 if (s0 & (1 << 5))
43 *status |= FE_HAS_LOCK;
44 if (s1 & (1 << 1))
45 *status |= FE_HAS_SYNC;
46 if (s3 & (1 << 6))
47 *status |= FE_HAS_SIGNAL;
48
49 if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
50 (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
51 *status &= ~FE_HAS_LOCK;
52
53 return 0;
54}
55
56static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
57{
58 struct vp7045_fe_state *state = fe->demodulator_priv;
59 *ber = (vp7045_read_reg(state->d, 0x0D) << 16) |
60 (vp7045_read_reg(state->d, 0x0E) << 8) |
61 vp7045_read_reg(state->d, 0x0F);
62 return 0;
63}
64
65static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
66{
67 struct vp7045_fe_state *state = fe->demodulator_priv;
68 *unc = (vp7045_read_reg(state->d, 0x10) << 8) |
69 vp7045_read_reg(state->d, 0x11);
70 return 0;
71}
72
73static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
74{
75 struct vp7045_fe_state *state = fe->demodulator_priv;
76 u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) |
77 vp7045_read_reg(state->d, 0x15);
78
79 *strength = ~signal;
80 return 0;
81}
82
83static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
84{
85 struct vp7045_fe_state *state = fe->demodulator_priv;
86 u8 _snr = vp7045_read_reg(state->d, 0x09);
87 *snr = (_snr << 8) | _snr;
88 return 0;
89}
90
91static int vp7045_fe_init(struct dvb_frontend* fe)
92{
93 return 0;
94}
95
96static int vp7045_fe_sleep(struct dvb_frontend* fe)
97{
98 return 0;
99}
100
101static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
102{
103 tune->min_delay_ms = 800;
104 return 0;
105}
106
107static int vp7045_fe_set_frontend(struct dvb_frontend* fe,
108 struct dvb_frontend_parameters *fep)
109{
110 struct vp7045_fe_state *state = fe->demodulator_priv;
111 u8 buf[5];
112 u32 freq = fep->frequency / 1000;
113
114 buf[0] = (freq >> 16) & 0xff;
115 buf[1] = (freq >> 8) & 0xff;
116 buf[2] = freq & 0xff;
117 buf[3] = 0;
118
119 switch (fep->u.ofdm.bandwidth) {
120 case BANDWIDTH_8_MHZ: buf[4] = 8; break;
121 case BANDWIDTH_7_MHZ: buf[4] = 7; break;
122 case BANDWIDTH_6_MHZ: buf[4] = 6; break;
123 case BANDWIDTH_AUTO: return -EOPNOTSUPP;
124 default:
125 return -EINVAL;
126 }
127
128 vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
129 return 0;
130}
131
132static int vp7045_fe_get_frontend(struct dvb_frontend* fe,
133 struct dvb_frontend_parameters *fep)
134{
135 return 0;
136}
137
138static void vp7045_fe_release(struct dvb_frontend* fe)
139{
140 struct vp7045_fe_state *state = fe->demodulator_priv;
141 kfree(state);
142}
143
144static struct dvb_frontend_ops vp7045_fe_ops;
145
146struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
147{
148 struct vp7045_fe_state *s = kmalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
149 if (s == NULL)
150 goto error;
151 memset(s,0,sizeof(struct vp7045_fe_state));
152
153 s->d = d;
154 s->fe.ops = &vp7045_fe_ops;
155 s->fe.demodulator_priv = s;
156
157 goto success;
158error:
159 return NULL;
160success:
161 return &s->fe;
162}
163
164
165static struct dvb_frontend_ops vp7045_fe_ops = {
166 .info = {
167 .name = "Twinhan VP7045/46 USB DVB-T",
168 .type = FE_OFDM,
169 .frequency_min = 44250000,
170 .frequency_max = 867250000,
171 .frequency_stepsize = 1000,
172 .caps = FE_CAN_INVERSION_AUTO |
173 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
174 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
175 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
176 FE_CAN_TRANSMISSION_MODE_AUTO |
177 FE_CAN_GUARD_INTERVAL_AUTO |
178 FE_CAN_RECOVER |
179 FE_CAN_HIERARCHY_AUTO,
180 },
181
182 .release = vp7045_fe_release,
183
184 .init = vp7045_fe_init,
185 .sleep = vp7045_fe_sleep,
186
187 .set_frontend = vp7045_fe_set_frontend,
188 .get_frontend = vp7045_fe_get_frontend,
189 .get_tune_settings = vp7045_fe_get_tune_settings,
190
191 .read_status = vp7045_fe_read_status,
192 .read_ber = vp7045_fe_read_ber,
193 .read_signal_strength = vp7045_fe_read_signal_strength,
194 .read_snr = vp7045_fe_read_snr,
195 .read_ucblocks = vp7045_fe_read_unc_blocks,
196};
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
new file mode 100644
index 0000000000..02ecc9a8e3
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -0,0 +1,263 @@
1/* DVB USB compliant Linux driver for the
2 * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver
3 * - DigitalNow TinyUSB2 DVB-t receiver
4 *
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
7 * Thanks to Twinhan who kindly provided hardware and information.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation, version 2.
12 *
13 * see Documentation/dvb/README.dvb-usb for more information
14 */
15#include "vp7045.h"
16
17/* debug */
18int dvb_usb_vp7045_debug;
19module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
20MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
21
22int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
23{
24 int ret = 0;
25 u8 inbuf[12] = { 0 }, outbuf[20] = { 0 };
26
27 outbuf[0] = cmd;
28
29 if (outlen > 19)
30 outlen = 19;
31
32 if (inlen > 11)
33 inlen = 11;
34
35 if (out != NULL && outlen > 0)
36 memcpy(&outbuf[1], out, outlen);
37
38 deb_xfer("out buffer: ");
39 debug_dump(outbuf,outlen+1,deb_xfer);
40
41 if ((ret = down_interruptible(&d->usb_sem)))
42 return ret;
43
44 if (usb_control_msg(d->udev,
45 usb_sndctrlpipe(d->udev,0),
46 TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
47 outbuf, 20, 2*HZ) != 20) {
48 err("USB control message 'out' went wrong.");
49 ret = -EIO;
50 goto unlock;
51 }
52
53 msleep(msec);
54
55 if (usb_control_msg(d->udev,
56 usb_rcvctrlpipe(d->udev,0),
57 TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
58 inbuf, 12, 2*HZ) != 12) {
59 err("USB control message 'in' went wrong.");
60 ret = -EIO;
61 goto unlock;
62 }
63
64 deb_xfer("in buffer: ");
65 debug_dump(inbuf,12,deb_xfer);
66
67 if (in != NULL && inlen > 0)
68 memcpy(in,&inbuf[1],inlen);
69
70unlock:
71 up(&d->usb_sem);
72
73 return ret;
74}
75
76u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg)
77{
78 u8 obuf[2] = { 0 },v;
79 obuf[1] = reg;
80
81 vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30);
82
83 return v;
84}
85
86static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
87{
88 u8 v = onoff;
89 return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150);
90}
91
92/* remote control stuff */
93
94/* The keymapping struct. Somehow this should be loaded to the driver, but
95 * currently it is hardcoded. */
96static struct dvb_usb_rc_key vp7045_rc_keys[] = {
97 /* insert the keys like this. to make the raw keys visible, enable
98 * debug=0x04 when loading dvb-usb-vp7045. */
99
100 /* these keys are probably wrong. I don't have a working IR-receiver on my
101 * vp7045, so I can't test it. Patches are welcome. */
102 { 0x00, 0x01, KEY_1 },
103 { 0x00, 0x02, KEY_2 },
104};
105
106static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state)
107{
108 u8 key;
109 int i;
110 vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20);
111
112 deb_rc("remote query key: %x %d\n",key,key);
113
114 if (key == 0x44) {
115 *state = REMOTE_NO_KEY_PRESSED;
116 return 0;
117 }
118
119 for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++)
120 if (vp7045_rc_keys[i].data == key) {
121 *state = REMOTE_KEY_PRESSED;
122 *key_buf = vp7045_rc_keys[i].event;
123 break;
124 }
125 return 0;
126}
127
128static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)
129{
130 int i = 0;
131 u8 v,br[2];
132 for (i=0; i < len; i++) {
133 v = offset + i;
134 vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5);
135 buf[i] = br[1];
136 }
137 deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i);
138 debug_dump(buf,i,deb_info);
139 return 0;
140}
141
142
143static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
144{
145 return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
146}
147
148static int vp7045_frontend_attach(struct dvb_usb_device *d)
149{
150 u8 buf[255] = { 0 };
151
152 vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0);
153 buf[10] = '\0';
154 deb_info("firmware says: %s ",buf);
155
156 vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0);
157 buf[10] = '\0';
158 deb_info("%s ",buf);
159
160 vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0);
161 buf[10] = '\0';
162 deb_info("v%s\n",buf);
163
164/* Dump the EEPROM */
165/* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
166
167 d->fe = vp7045_fe_attach(d);
168
169 return 0;
170}
171
172static struct dvb_usb_properties vp7045_properties;
173
174static int vp7045_usb_probe(struct usb_interface *intf,
175 const struct usb_device_id *id)
176{
177 return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE);
178}
179
180static struct usb_device_id vp7045_usb_table [] = {
181 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) },
182 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) },
183 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) },
184 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) },
185 { 0 },
186};
187MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
188
189static struct dvb_usb_properties vp7045_properties = {
190 .caps = 0,
191
192 .usb_ctrl = CYPRESS_FX2,
193 .firmware = "dvb-usb-vp7045-01.fw",
194
195 .power_ctrl = vp7045_power_ctrl,
196 .frontend_attach = vp7045_frontend_attach,
197 .read_mac_address = vp7045_read_mac_addr,
198
199 .rc_interval = 400,
200 .rc_key_map = vp7045_rc_keys,
201 .rc_key_map_size = ARRAY_SIZE(vp7045_rc_keys),
202 .rc_query = vp7045_rc_query,
203
204 /* parameter for the MPEG2-data transfer */
205 .urb = {
206 .type = DVB_USB_BULK,
207 .count = 7,
208 .endpoint = 0x02,
209 .u = {
210 .bulk = {
211 .buffersize = 4096,
212 }
213 }
214 },
215
216 .num_device_descs = 2,
217 .devices = {
218 { .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)",
219 .cold_ids = { &vp7045_usb_table[0], NULL },
220 .warm_ids = { &vp7045_usb_table[1], NULL },
221 },
222 { .name = "DigitalNow TinyUSB 2 DVB-t Receiver",
223 .cold_ids = { &vp7045_usb_table[2], NULL },
224 .warm_ids = { &vp7045_usb_table[3], NULL },
225 },
226 { 0 },
227 }
228};
229
230/* usb specific object needed to register this driver with the usb subsystem */
231static struct usb_driver vp7045_usb_driver = {
232 .owner = THIS_MODULE,
233 .name = "dvb-usb-vp7045",
234 .probe = vp7045_usb_probe,
235 .disconnect = dvb_usb_device_exit,
236 .id_table = vp7045_usb_table,
237};
238
239/* module stuff */
240static int __init vp7045_usb_module_init(void)
241{
242 int result;
243 if ((result = usb_register(&vp7045_usb_driver))) {
244 err("usb_register failed. (%d)",result);
245 return result;
246 }
247
248 return 0;
249}
250
251static void __exit vp7045_usb_module_exit(void)
252{
253 /* deregister this driver from the USB subsystem */
254 usb_deregister(&vp7045_usb_driver);
255}
256
257module_init(vp7045_usb_module_init);
258module_exit(vp7045_usb_module_exit);
259
260MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
261MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0");
262MODULE_VERSION("1.0");
263MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/dvb/dvb-usb/vp7045.h
new file mode 100644
index 0000000000..9ce21a20fa
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045.h
@@ -0,0 +1,78 @@
1/* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII
2 * USB2.0 DVB-T receiver.
3 *
4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
5 *
6 * Thanks to Twinhan who kindly provided hardware and information.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation, version 2.
11 *
12 * see Documentation/dvb/README.dvb-usb for more information
13 */
14#ifndef _DVB_USB_VP7045_H_
15#define _DVB_USB_VP7045_H_
16
17#define DVB_USB_LOG_PREFIX "vp7045"
18#include "dvb-usb.h"
19
20extern int dvb_usb_vp7045_debug;
21#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
22#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
23#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
24
25/* vp7045 commands */
26
27/* Twinhan Vendor requests */
28#define TH_COMMAND_IN 0xC0
29#define TH_COMMAND_OUT 0xC1
30
31/* command bytes */
32#define TUNER_REG_READ 0x03
33#define TUNER_REG_WRITE 0x04
34
35#define RC_VAL_READ 0x05
36 #define RC_NO_KEY 0x44
37
38#define SET_TUNER_POWER 0x06
39#define CHECK_TUNER_POWER 0x12
40 #define Tuner_Power_ON 1
41 #define Tuner_Power_OFF 0
42
43#define GET_USB_SPEED 0x07
44 #define USB_SPEED_LOW 0
45 #define USB_SPEED_FULL 1
46 #define USB_SPEED_HIGH 2
47
48#define LOCK_TUNER_COMMAND 0x09
49
50#define TUNER_SIGNAL_READ 0x0A
51
52/* FX2 eeprom */
53#define SET_EE_VALUE 0x10
54#define GET_EE_VALUE 0x11
55 #define FX2_ID_ADDR 0x00
56 #define VID_MSB_ADDR 0x02
57 #define VID_LSB_ADDR 0x01
58 #define PID_MSB_ADDR 0x04
59 #define PID_LSB_ADDR 0x03
60 #define MAC_0_ADDR 0x07
61 #define MAC_1_ADDR 0x08
62 #define MAC_2_ADDR 0x09
63 #define MAC_3_ADDR 0x0a
64 #define MAC_4_ADDR 0x0b
65 #define MAC_5_ADDR 0x0c
66
67#define RESET_FX2 0x13
68
69#define FW_VERSION_READ 0x0B
70#define VENDOR_STRING_READ 0x0C
71#define PRODUCT_STRING_READ 0x0D
72#define FW_BCD_VERSION_READ 0x14
73
74extern struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d);
75extern int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen,int msec);
76extern u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg);
77
78#endif
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 75fb556ec0..b4fddf513e 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -173,4 +173,12 @@ config DVB_OR51132
173 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want 173 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
174 to support this frontend. 174 to support this frontend.
175 175
176config DVB_BCM3510
177 tristate "Broadcom BCM3510"
178 depends on DVB_CORE
179 select FW_LOADER
180 help
181 An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
182 support this frontend.
183
176endmenu 184endmenu
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 7f8784870e..91d6d3576d 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_DVB_STV0297) += stv0297.o
28obj-$(CONFIG_DVB_NXT2002) += nxt2002.o 28obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
29obj-$(CONFIG_DVB_OR51211) += or51211.o 29obj-$(CONFIG_DVB_OR51211) += or51211.o
30obj-$(CONFIG_DVB_OR51132) += or51132.o 30obj-$(CONFIG_DVB_OR51132) += or51132.o
31obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
new file mode 100644
index 0000000000..f5fdc5c3e6
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -0,0 +1,853 @@
1/*
2 * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
3 *
4 * Copyright (C) 2001-5, B2C2 inc.
5 *
6 * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
7 *
8 * This driver is "hard-coded" to be used with the 1st generation of
9 * Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming
10 * (Panasonic CT10S) is located here, which is actually wrong. Unless there is
11 * another device with a BCM3510, this is no problem.
12 *
13 * The driver works also with QAM64 DVB-C, but had an unreasonable high
14 * UNC. (Tested with the Air2PC ATSC 1st generation)
15 *
16 * You'll need a firmware for this driver in order to get it running. It is
17 * called "dvb-fe-bcm3510-01.fw".
18 *
19 * This program is free software; you can redistribute it and/or modify it
20 * under the terms of the GNU General Public License as published by the Free
21 * Software Foundation; either version 2 of the License, or (at your option)
22 * any later version.
23 *
24 * This program is distributed in the hope that it will be useful, but WITHOUT
25 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
27 * more details.
28 *
29 * You should have received a copy of the GNU General Public License along with
30 * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
31 * Ave, Cambridge, MA 02139, USA.
32 */
33
34#include <linux/init.h>
35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/device.h>
38#include <linux/firmware.h>
39
40#include "dvb_frontend.h"
41#include "bcm3510.h"
42#include "bcm3510_priv.h"
43
44struct bcm3510_state {
45
46 struct i2c_adapter* i2c;
47 struct dvb_frontend_ops ops;
48 const struct bcm3510_config* config;
49 struct dvb_frontend frontend;
50
51 /* demodulator private data */
52 struct semaphore hab_sem;
53 u8 firmware_loaded:1;
54
55 unsigned long next_status_check;
56 unsigned long status_check_interval;
57 struct bcm3510_hab_cmd_status1 status1;
58 struct bcm3510_hab_cmd_status2 status2;
59};
60
61static int debug;
62module_param(debug, int, 0644);
63MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c (|-able)).");
64
65#define dprintk(level,x...) if (level & debug) printk(x)
66#define dbufout(b,l,m) {\
67 int i; \
68 for (i = 0; i < l; i++) \
69 m("%02x ",b[i]); \
70}
71#define deb_info(args...) dprintk(0x01,args)
72#define deb_i2c(args...) dprintk(0x02,args)
73#define deb_hab(args...) dprintk(0x04,args)
74
75/* transfer functions */
76static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
77{
78 u8 b[256];
79 int err;
80 struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = len + 1 };
81
82 b[0] = reg;
83 memcpy(&b[1],buf,len);
84
85 deb_i2c("i2c wr %02x: ",reg);
86 dbufout(buf,len,deb_i2c);
87 deb_i2c("\n");
88
89 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
90
91 deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
92 __FUNCTION__, state->config->demod_address, reg, err);
93 return -EREMOTEIO;
94 }
95
96 return 0;
97}
98
99static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
100{
101 struct i2c_msg msg[] = {
102 { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
103 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len }
104 };
105 int err;
106
107 memset(buf,0,len);
108
109 if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
110 deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
111 __FUNCTION__, state->config->demod_address, reg, err);
112 return -EREMOTEIO;
113 }
114 deb_i2c("i2c rd %02x: ",reg);
115 dbufout(buf,len,deb_i2c);
116 deb_i2c("\n");
117
118 return 0;
119}
120
121static int bcm3510_writeB(struct bcm3510_state *state, u8 reg, bcm3510_register_value v)
122{
123 return bcm3510_writebytes(state,reg,&v.raw,1);
124}
125
126static int bcm3510_readB(struct bcm3510_state *state, u8 reg, bcm3510_register_value *v)
127{
128 return bcm3510_readbytes(state,reg,&v->raw,1);
129}
130
131/* Host Access Buffer transfers */
132static int bcm3510_hab_get_response(struct bcm3510_state *st, u8 *buf, int len)
133{
134 bcm3510_register_value v;
135 int ret,i;
136
137 v.HABADR_a6.HABADR = 0;
138 if ((ret = bcm3510_writeB(st,0xa6,v)) < 0)
139 return ret;
140
141 for (i = 0; i < len; i++) {
142 if ((ret = bcm3510_readB(st,0xa7,&v)) < 0)
143 return ret;
144 buf[i] = v.HABDATA_a7;
145 }
146 return 0;
147}
148
149static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len)
150{
151 bcm3510_register_value v,hab;
152 int ret,i;
153 unsigned long t;
154
155/* Check if any previous HAB request still needs to be serviced by the
156 * Aquisition Processor before sending new request */
157 if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
158 return ret;
159 if (v.HABSTAT_a8.HABR) {
160 deb_info("HAB is running already - clearing it.\n");
161 v.HABSTAT_a8.HABR = 0;
162 bcm3510_writeB(st,0xa8,v);
163// return -EBUSY;
164 }
165
166/* Send the start HAB Address (automatically incremented after write of
167 * HABDATA) and write the HAB Data */
168 hab.HABADR_a6.HABADR = 0;
169 if ((ret = bcm3510_writeB(st,0xa6,hab)) < 0)
170 return ret;
171
172 for (i = 0; i < len; i++) {
173 hab.HABDATA_a7 = buf[i];
174 if ((ret = bcm3510_writeB(st,0xa7,hab)) < 0)
175 return ret;
176 }
177
178/* Set the HABR bit to indicate AP request in progress (LBHABR allows HABR to
179 * be written) */
180 v.raw = 0; v.HABSTAT_a8.HABR = 1; v.HABSTAT_a8.LDHABR = 1;
181 if ((ret = bcm3510_writeB(st,0xa8,v)) < 0)
182 return ret;
183
184/* Polling method: Wait until the AP finishes processing the HAB request */
185 t = jiffies + 1*HZ;
186 while (time_before(jiffies, t)) {
187 deb_info("waiting for HAB to complete\n");
188 msleep(10);
189 if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
190 return ret;
191
192 if (!v.HABSTAT_a8.HABR)
193 return 0;
194 }
195
196 deb_info("send_request execution timed out.\n");
197 return -ETIMEDOUT;
198}
199
200static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen)
201{
202 u8 ob[olen+2],ib[ilen+2];
203 int ret = 0;
204
205 ob[0] = cmd;
206 ob[1] = msgid;
207 memcpy(&ob[2],obuf,olen);
208
209 deb_hab("hab snd: ");
210 dbufout(ob,olen+2,deb_hab);
211 deb_hab("\n");
212
213 if (down_interruptible(&st->hab_sem) < 0)
214 return -EAGAIN;
215
216 if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 ||
217 (ret = bcm3510_hab_get_response(st, ib, ilen+2)) < 0)
218 goto error;
219
220 deb_hab("hab get: ");
221 dbufout(ib,ilen+2,deb_hab);
222 deb_hab("\n");
223
224 memcpy(ibuf,&ib[2],ilen);
225error:
226 up(&st->hab_sem);
227 return ret;
228}
229
230#if 0
231/* not needed, we use a semaphore to prevent HAB races */
232static int bcm3510_is_ap_ready(struct bcm3510_state *st)
233{
234 bcm3510_register_value ap,hab;
235 int ret;
236
237 if ((ret = bcm3510_readB(st,0xa8,&hab)) < 0 ||
238 (ret = bcm3510_readB(st,0xa2,&ap) < 0))
239 return ret;
240
241 if (ap.APSTAT1_a2.RESET || ap.APSTAT1_a2.IDLE || ap.APSTAT1_a2.STOP || hab.HABSTAT_a8.HABR) {
242 deb_info("AP is busy\n");
243 return -EBUSY;
244 }
245
246 return 0;
247}
248#endif
249
250static int bcm3510_bert_reset(struct bcm3510_state *st)
251{
252 bcm3510_register_value b;
253 int ret;
254
255 if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
256 return ret;
257
258 b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
259 b.BERCTL_fa.RESYNC = 1; bcm3510_writeB(st,0xfa,b);
260 b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
261 b.BERCTL_fa.CNTCTL = 1; b.BERCTL_fa.BITCNT = 1; bcm3510_writeB(st,0xfa,b);
262
263 /* clear residual bit counter TODO */
264 return 0;
265}
266
267static int bcm3510_refresh_state(struct bcm3510_state *st)
268{
269 if (time_after(jiffies,st->next_status_check)) {
270 bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS1, NULL,0, (u8 *)&st->status1, sizeof(st->status1));
271 bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS2, NULL,0, (u8 *)&st->status2, sizeof(st->status2));
272 st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
273 }
274 return 0;
275}
276
277static int bcm3510_read_status(struct dvb_frontend *fe, fe_status_t *status)
278{
279 struct bcm3510_state* st = fe->demodulator_priv;
280 bcm3510_refresh_state(st);
281
282 *status = 0;
283 if (st->status1.STATUS1.RECEIVER_LOCK)
284 *status |= FE_HAS_LOCK | FE_HAS_SYNC;
285
286 if (st->status1.STATUS1.FEC_LOCK)
287 *status |= FE_HAS_VITERBI;
288
289 if (st->status1.STATUS1.OUT_PLL_LOCK)
290 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
291
292 if (*status & FE_HAS_LOCK)
293 st->status_check_interval = 1500;
294 else /* more frequently checks if no lock has been achieved yet */
295 st->status_check_interval = 500;
296
297 deb_info("real_status: %02x\n",*status);
298 return 0;
299}
300
301static int bcm3510_read_ber(struct dvb_frontend* fe, u32* ber)
302{
303 struct bcm3510_state* st = fe->demodulator_priv;
304 bcm3510_refresh_state(st);
305
306 *ber = (st->status2.LDBER0 << 16) | (st->status2.LDBER1 << 8) | st->status2.LDBER2;
307 return 0;
308}
309
310static int bcm3510_read_unc(struct dvb_frontend* fe, u32* unc)
311{
312 struct bcm3510_state* st = fe->demodulator_priv;
313 bcm3510_refresh_state(st);
314 *unc = (st->status2.LDUERC0 << 8) | st->status2.LDUERC1;
315 return 0;
316}
317
318static int bcm3510_read_signal_strength(struct dvb_frontend* fe, u16* strength)
319{
320 struct bcm3510_state* st = fe->demodulator_priv;
321 s32 t;
322
323 bcm3510_refresh_state(st);
324 t = st->status2.SIGNAL;
325
326 if (t > 190)
327 t = 190;
328 if (t < 90)
329 t = 90;
330
331 t -= 90;
332 t = t * 0xff / 100;
333 /* normalize if necessary */
334 *strength = (t << 8) | t;
335 return 0;
336}
337
338static int bcm3510_read_snr(struct dvb_frontend* fe, u16* snr)
339{
340 struct bcm3510_state* st = fe->demodulator_priv;
341 bcm3510_refresh_state(st);
342
343 *snr = st->status1.SNR_EST0*1000 + ((st->status1.SNR_EST1*1000) >> 8);
344 return 0;
345}
346
347/* tuner frontend programming */
348static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a)
349{
350 struct bcm3510_hab_cmd_tune c;
351 memset(&c,0,sizeof(struct bcm3510_hab_cmd_tune));
352
353/* I2C Mode disabled, set 16 control / Data pairs */
354 c.length = 0x10;
355 c.clock_width = 0;
356/* CS1, CS0, DATA, CLK bits control the tuner RF_AGC_SEL pin is set to
357 * logic high (as Configuration) */
358 c.misc = 0x10;
359/* Set duration of the initial state of TUNCTL = 3.34 micro Sec */
360 c.TUNCTL_state = 0x40;
361
362/* PRESCALER DEVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
363 c.ctl_dat[0].ctrl.size = BITS_8;
364 c.ctl_dat[0].data = 0x80 | bc;
365
366/* Control DATA pin, 1stosc REFERENCE COUNTER REF_S10 to REF_S3 */
367 c.ctl_dat[1].ctrl.size = BITS_8;
368 c.ctl_dat[1].data = 4;
369
370/* set CONTROL BIT 1 to 1, 1stosc REFERENCE COUNTER REF_S2 to REF_S1 */
371 c.ctl_dat[2].ctrl.size = BITS_3;
372 c.ctl_dat[2].data = 0x20;
373
374/* control CS0 pin, pulse byte ? */
375 c.ctl_dat[3].ctrl.size = BITS_3;
376 c.ctl_dat[3].ctrl.clk_off = 1;
377 c.ctl_dat[3].ctrl.cs0 = 1;
378 c.ctl_dat[3].data = 0x40;
379
380/* PGM_S18 to PGM_S11 */
381 c.ctl_dat[4].ctrl.size = BITS_8;
382 c.ctl_dat[4].data = n >> 3;
383
384/* PGM_S10 to PGM_S8, SWL_S7 to SWL_S3 */
385 c.ctl_dat[5].ctrl.size = BITS_8;
386 c.ctl_dat[5].data = ((n & 0x7) << 5) | (a >> 2);
387
388/* SWL_S2 and SWL_S1, set CONTROL BIT 2 to 0 */
389 c.ctl_dat[6].ctrl.size = BITS_3;
390 c.ctl_dat[6].data = (a << 6) & 0xdf;
391
392/* control CS0 pin, pulse byte ? */
393 c.ctl_dat[7].ctrl.size = BITS_3;
394 c.ctl_dat[7].ctrl.clk_off = 1;
395 c.ctl_dat[7].ctrl.cs0 = 1;
396 c.ctl_dat[7].data = 0x40;
397
398/* PRESCALER DEVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
399 c.ctl_dat[8].ctrl.size = BITS_8;
400 c.ctl_dat[8].data = 0x80;
401
402/* 2ndosc REFERENCE COUNTER REF_S10 to REF_S3 */
403 c.ctl_dat[9].ctrl.size = BITS_8;
404 c.ctl_dat[9].data = 0x10;
405
406/* set CONTROL BIT 1 to 1, 2ndosc REFERENCE COUNTER REF_S2 to REF_S1 */
407 c.ctl_dat[10].ctrl.size = BITS_3;
408 c.ctl_dat[10].data = 0x20;
409
410/* pulse byte */
411 c.ctl_dat[11].ctrl.size = BITS_3;
412 c.ctl_dat[11].ctrl.clk_off = 1;
413 c.ctl_dat[11].ctrl.cs1 = 1;
414 c.ctl_dat[11].data = 0x40;
415
416/* PGM_S18 to PGM_S11 */
417 c.ctl_dat[12].ctrl.size = BITS_8;
418 c.ctl_dat[12].data = 0x2a;
419
420/* PGM_S10 to PGM_S8 and SWL_S7 to SWL_S3 */
421 c.ctl_dat[13].ctrl.size = BITS_8;
422 c.ctl_dat[13].data = 0x8e;
423
424/* SWL_S2 and SWL_S1 and set CONTROL BIT 2 to 0 */
425 c.ctl_dat[14].ctrl.size = BITS_3;
426 c.ctl_dat[14].data = 0;
427
428/* Pulse Byte */
429 c.ctl_dat[15].ctrl.size = BITS_3;
430 c.ctl_dat[15].ctrl.clk_off = 1;
431 c.ctl_dat[15].ctrl.cs1 = 1;
432 c.ctl_dat[15].data = 0x40;
433
434 return bcm3510_do_hab_cmd(st,CMD_TUNE, MSGID_TUNE,(u8 *) &c,sizeof(c), NULL, 0);
435}
436
437static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
438{
439 u8 bc,a;
440 u16 n;
441 s32 YIntercept,Tfvco1;
442
443 freq /= 1000;
444
445 deb_info("%dkHz:",freq);
446 /* set Band Switch */
447 if (freq <= 168000)
448 bc = 0x1c;
449 else if (freq <= 378000)
450 bc = 0x2c;
451 else
452 bc = 0x30;
453
454 if (freq >= 470000) {
455 freq -= 470001;
456 YIntercept = 18805;
457 } else if (freq >= 90000) {
458 freq -= 90001;
459 YIntercept = 15005;
460 } else if (freq >= 76000){
461 freq -= 76001;
462 YIntercept = 14865;
463 } else {
464 freq -= 54001;
465 YIntercept = 14645;
466 }
467
468 Tfvco1 = (((freq/6000)*60 + YIntercept)*4)/10;
469
470 n = Tfvco1 >> 6;
471 a = Tfvco1 & 0x3f;
472
473 deb_info(" BC1_2_3_4: %x, N: %x A: %x\n", bc, n, a);
474 if (n >= 16 && n <= 2047)
475 return bcm3510_tuner_cmd(st,bc,n,a);
476
477 return -EINVAL;
478}
479
480static int bcm3510_set_frontend(struct dvb_frontend* fe,
481 struct dvb_frontend_parameters *p)
482{
483 struct bcm3510_state* st = fe->demodulator_priv;
484 struct bcm3510_hab_cmd_ext_acquire cmd;
485 struct bcm3510_hab_cmd_bert_control bert;
486 int ret;
487
488 memset(&cmd,0,sizeof(cmd));
489 switch (p->u.vsb.modulation) {
490 case QAM_256:
491 cmd.ACQUIRE0.MODE = 0x1;
492 cmd.ACQUIRE1.SYM_RATE = 0x1;
493 cmd.ACQUIRE1.IF_FREQ = 0x1;
494 break;
495 case QAM_64:
496 cmd.ACQUIRE0.MODE = 0x2;
497 cmd.ACQUIRE1.SYM_RATE = 0x2;
498 cmd.ACQUIRE1.IF_FREQ = 0x1;
499 break;
500/* case QAM_256:
501 cmd.ACQUIRE0.MODE = 0x3;
502 break;
503 case QAM_128:
504 cmd.ACQUIRE0.MODE = 0x4;
505 break;
506 case QAM_64:
507 cmd.ACQUIRE0.MODE = 0x5;
508 break;
509 case QAM_32:
510 cmd.ACQUIRE0.MODE = 0x6;
511 break;
512 case QAM_16:
513 cmd.ACQUIRE0.MODE = 0x7;
514 break;*/
515 case VSB_8:
516 cmd.ACQUIRE0.MODE = 0x8;
517 cmd.ACQUIRE1.SYM_RATE = 0x0;
518 cmd.ACQUIRE1.IF_FREQ = 0x0;
519 break;
520 case VSB_16:
521 cmd.ACQUIRE0.MODE = 0x9;
522 cmd.ACQUIRE1.SYM_RATE = 0x0;
523 cmd.ACQUIRE1.IF_FREQ = 0x0;
524 default:
525 return -EINVAL;
526 };
527 cmd.ACQUIRE0.OFFSET = 0;
528 cmd.ACQUIRE0.NTSCSWEEP = 1;
529 cmd.ACQUIRE0.FA = 1;
530 cmd.ACQUIRE0.BW = 0;
531
532/* if (enableOffset) {
533 cmd.IF_OFFSET0 = xx;
534 cmd.IF_OFFSET1 = xx;
535
536 cmd.SYM_OFFSET0 = xx;
537 cmd.SYM_OFFSET1 = xx;
538 if (enableNtscSweep) {
539 cmd.NTSC_OFFSET0;
540 cmd.NTSC_OFFSET1;
541 }
542 } */
543 bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0);
544
545/* doing it with different MSGIDs, data book and source differs */
546 bert.BE = 0;
547 bert.unused = 0;
548 bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0);
549 bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0);
550
551 bcm3510_bert_reset(st);
552
553 if ((ret = bcm3510_set_freq(st,p->frequency)) < 0)
554 return ret;
555
556 memset(&st->status1,0,sizeof(st->status1));
557 memset(&st->status2,0,sizeof(st->status2));
558 st->status_check_interval = 500;
559
560/* Give the AP some time */
561 msleep(200);
562
563 return 0;
564}
565
566static int bcm3510_sleep(struct dvb_frontend* fe)
567{
568 return 0;
569}
570
571static int bcm3510_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s)
572{
573 s->min_delay_ms = 1000;
574 s->step_size = 0;
575 s->max_drift = 0;
576 return 0;
577}
578
579static void bcm3510_release(struct dvb_frontend* fe)
580{
581 struct bcm3510_state* state = fe->demodulator_priv;
582 kfree(state);
583}
584
585/* firmware download:
586 * firmware file is build up like this:
587 * 16bit addr, 16bit length, 8byte of length
588 */
589#define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
590
591static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, u8 *b, u16 len)
592{
593 int ret = 0,i;
594 bcm3510_register_value vH, vL,vD;
595
596 vH.MADRH_a9 = addr >> 8;
597 vL.MADRL_aa = addr;
598 if ((ret = bcm3510_writeB(st,0xa9,vH)) < 0) return ret;
599 if ((ret = bcm3510_writeB(st,0xaa,vL)) < 0) return ret;
600
601 for (i = 0; i < len; i++) {
602 vD.MDATA_ab = b[i];
603 if ((ret = bcm3510_writeB(st,0xab,vD)) < 0)
604 return ret;
605 }
606
607 return 0;
608}
609
610static int bcm3510_download_firmware(struct dvb_frontend* fe)
611{
612 struct bcm3510_state* st = fe->demodulator_priv;
613 const struct firmware *fw;
614 u16 addr,len;
615 u8 *b;
616 int ret,i;
617
618 deb_info("requesting firmware\n");
619 if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) {
620 err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
621 return ret;
622 }
623 deb_info("got firmware: %d\n",fw->size);
624
625 b = fw->data;
626 for (i = 0; i < fw->size;) {
627 addr = le16_to_cpu( *( (u16 *)&b[i] ) );
628 len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
629 deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size);
630 if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
631 err("firmware download failed: %d\n",ret);
632 return ret;
633 }
634 i += 4 + len;
635 }
636 release_firmware(fw);
637 deb_info("firmware download successfully completed\n");
638 return 0;
639}
640
641static int bcm3510_check_firmware_version(struct bcm3510_state *st)
642{
643 struct bcm3510_hab_cmd_get_version_info ver;
644 bcm3510_do_hab_cmd(st,CMD_GET_VERSION_INFO,MSGID_GET_VERSION_INFO,NULL,0,(u8*)&ver,sizeof(ver));
645
646 deb_info("Version information: 0x%02x 0x%02x 0x%02x 0x%02x\n",
647 ver.microcode_version, ver.script_version, ver.config_version, ver.demod_version);
648
649 if (ver.script_version == BCM3510_DEF_SCRIPT_VERSION &&
650 ver.config_version == BCM3510_DEF_CONFIG_VERSION &&
651 ver.demod_version == BCM3510_DEF_DEMOD_VERSION)
652 return 0;
653
654 deb_info("version check failed\n");
655 return -ENODEV;
656}
657
658/* (un)resetting the AP */
659static int bcm3510_reset(struct bcm3510_state *st)
660{
661 int ret;
662 unsigned long t;
663 bcm3510_register_value v;
664
665 bcm3510_readB(st,0xa0,&v); v.HCTL1_a0.RESET = 1;
666 if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
667 return ret;
668
669 t = jiffies + 3*HZ;
670 while (time_before(jiffies, t)) {
671 msleep(10);
672 if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
673 return ret;
674
675 if (v.APSTAT1_a2.RESET)
676 return 0;
677 }
678 deb_info("reset timed out\n");
679 return -ETIMEDOUT;
680}
681
682static int bcm3510_clear_reset(struct bcm3510_state *st)
683{
684 bcm3510_register_value v;
685 int ret;
686 unsigned long t;
687
688 v.raw = 0;
689 if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
690 return ret;
691
692 t = jiffies + 3*HZ;
693 while (time_before(jiffies, t)) {
694 msleep(10);
695 if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
696 return ret;
697
698 /* verify that reset is cleared */
699 if (!v.APSTAT1_a2.RESET)
700 return 0;
701 }
702 deb_info("reset clear timed out\n");
703 return -ETIMEDOUT;
704}
705
706static int bcm3510_init_cold(struct bcm3510_state *st)
707{
708 int ret;
709 bcm3510_register_value v;
710
711 /* read Acquisation Processor status register and check it is not in RUN mode */
712 if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
713 return ret;
714 if (v.APSTAT1_a2.RUN) {
715 deb_info("AP is already running - firmware already loaded.\n");
716 return 0;
717 }
718
719 deb_info("reset?\n");
720 if ((ret = bcm3510_reset(st)) < 0)
721 return ret;
722
723 deb_info("tristate?\n");
724 /* tri-state */
725 v.TSTCTL_2e.CTL = 0;
726 if ((ret = bcm3510_writeB(st,0x2e,v)) < 0)
727 return ret;
728
729 deb_info("firmware?\n");
730 if ((ret = bcm3510_download_firmware(&st->frontend)) < 0 ||
731 (ret = bcm3510_clear_reset(st)) < 0)
732 return ret;
733
734 /* anything left here to Let the acquisition processor begin execution at program counter 0000 ??? */
735
736 return 0;
737}
738
739static int bcm3510_init(struct dvb_frontend* fe)
740{
741 struct bcm3510_state* st = fe->demodulator_priv;
742 bcm3510_register_value j;
743 struct bcm3510_hab_cmd_set_agc c;
744 int ret;
745
746 if ((ret = bcm3510_readB(st,0xca,&j)) < 0)
747 return ret;
748
749 deb_info("JDEC: %02x\n",j.raw);
750
751 switch (j.JDEC_ca.JDEC) {
752 case JDEC_WAIT_AT_RAM:
753 deb_info("attempting to download firmware\n");
754 if ((ret = bcm3510_init_cold(st)) < 0)
755 return ret;
756 case JDEC_EEPROM_LOAD_WAIT: /* fall-through is wanted */
757 deb_info("firmware is loaded\n");
758 bcm3510_check_firmware_version(st);
759 break;
760 default:
761 return -ENODEV;
762 }
763
764 memset(&c,0,1);
765 c.SEL = 1;
766 bcm3510_do_hab_cmd(st,CMD_AUTO_PARAM,MSGID_SET_RF_AGC_SEL,(u8 *)&c,sizeof(c),NULL,0);
767
768 return 0;
769}
770
771
772static struct dvb_frontend_ops bcm3510_ops;
773
774struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
775 struct i2c_adapter *i2c)
776{
777 struct bcm3510_state* state = NULL;
778 int ret;
779 bcm3510_register_value v;
780
781 /* allocate memory for the internal state */
782 state = kmalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
783 if (state == NULL)
784 goto error;
785 memset(state,0,sizeof(struct bcm3510_state));
786
787 /* setup the state */
788
789 state->config = config;
790 state->i2c = i2c;
791 memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
792
793 /* create dvb_frontend */
794 state->frontend.ops = &state->ops;
795 state->frontend.demodulator_priv = state;
796
797 sema_init(&state->hab_sem, 1);
798
799 if ((ret = bcm3510_readB(state,0xe0,&v)) < 0)
800 goto error;
801
802 deb_info("Revision: 0x%1x, Layer: 0x%1x.\n",v.REVID_e0.REV,v.REVID_e0.LAYER);
803
804 if ((v.REVID_e0.REV != 0x1 && v.REVID_e0.LAYER != 0xb) && /* cold */
805 (v.REVID_e0.REV != 0x8 && v.REVID_e0.LAYER != 0x0)) /* warm */
806 goto error;
807
808 info("Revision: 0x%1x, Layer: 0x%1x.",v.REVID_e0.REV,v.REVID_e0.LAYER);
809
810 bcm3510_reset(state);
811
812 return &state->frontend;
813
814error:
815 kfree(state);
816 return NULL;
817}
818EXPORT_SYMBOL(bcm3510_attach);
819
820static struct dvb_frontend_ops bcm3510_ops = {
821
822 .info = {
823 .name = "Broadcom BCM3510 VSB/QAM frontend",
824 .type = FE_ATSC,
825 .frequency_min = 54000000,
826 .frequency_max = 803000000,
827 /* stepsize is just a guess */
828 .frequency_stepsize = 0,
829 .caps =
830 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
831 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
832 FE_CAN_8VSB | FE_CAN_16VSB |
833 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256
834 },
835
836 .release = bcm3510_release,
837
838 .init = bcm3510_init,
839 .sleep = bcm3510_sleep,
840
841 .set_frontend = bcm3510_set_frontend,
842 .get_tune_settings = bcm3510_get_tune_settings,
843
844 .read_status = bcm3510_read_status,
845 .read_ber = bcm3510_read_ber,
846 .read_signal_strength = bcm3510_read_signal_strength,
847 .read_snr = bcm3510_read_snr,
848 .read_ucblocks = bcm3510_read_unc,
849};
850
851MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
852MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
853MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h
new file mode 100644
index 0000000000..80f5d0953d
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510.h
@@ -0,0 +1,40 @@
1/*
2 * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
3 *
4 * Copyright (C) 2001-5, B2C2 inc.
5 *
6 * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22#ifndef BCM3510_H
23#define BCM3510_H
24
25#include <linux/dvb/frontend.h>
26#include <linux/firmware.h>
27
28struct bcm3510_config
29{
30 /* the demodulator's i2c address */
31 u8 demod_address;
32
33 /* request firmware for device */
34 int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
35};
36
37extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
38 struct i2c_adapter* i2c);
39
40#endif
diff --git a/drivers/media/dvb/frontends/bcm3510_priv.h b/drivers/media/dvb/frontends/bcm3510_priv.h
new file mode 100644
index 0000000000..3bb1bc2a04
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510_priv.h
@@ -0,0 +1,460 @@
1/*
2 * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
3 *
4 * Copyright (C) 2001-5, B2C2 inc.
5 *
6 * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22#ifndef __BCM3510_PRIV_H__
23#define __BCM3510_PRIV_H__
24
25#define PACKED __attribute__((packed))
26
27#undef err
28#define err(format, arg...) printk(KERN_ERR "bcm3510: " format "\n" , ## arg)
29#undef info
30#define info(format, arg...) printk(KERN_INFO "bcm3510: " format "\n" , ## arg)
31#undef warn
32#define warn(format, arg...) printk(KERN_WARNING "bcm3510: " format "\n" , ## arg)
33
34
35#define PANASONIC_FIRST_IF_BASE_IN_KHz 1407500
36#define BCM3510_SYMBOL_RATE 5381000
37
38typedef union {
39 u8 raw;
40
41 struct {
42 u8 CTL :8;
43 } TSTCTL_2e;
44
45 u8 LDCERC_4e;
46 u8 LDUERC_4f;
47 u8 LD_BER0_65;
48 u8 LD_BER1_66;
49 u8 LD_BER2_67;
50 u8 LD_BER3_68;
51
52 struct {
53 u8 RESET :1;
54 u8 IDLE :1;
55 u8 STOP :1;
56 u8 HIRQ0 :1;
57 u8 HIRQ1 :1;
58 u8 na0 :1;
59 u8 HABAV :1;
60 u8 na1 :1;
61 } HCTL1_a0;
62
63 struct {
64 u8 na0 :1;
65 u8 IDLMSK :1;
66 u8 STMSK :1;
67 u8 I0MSK :1;
68 u8 I1MSK :1;
69 u8 na1 :1;
70 u8 HABMSK :1;
71 u8 na2 :1;
72 } HCTLMSK_a1;
73
74 struct {
75 u8 RESET :1;
76 u8 IDLE :1;
77 u8 STOP :1;
78 u8 RUN :1;
79 u8 HABAV :1;
80 u8 MEMAV :1;
81 u8 ALDONE :1;
82 u8 REIRQ :1;
83 } APSTAT1_a2;
84
85 struct {
86 u8 RSTMSK :1;
87 u8 IMSK :1;
88 u8 SMSK :1;
89 u8 RMSK :1;
90 u8 HABMSK :1;
91 u8 MAVMSK :1;
92 u8 ALDMSK :1;
93 u8 REMSK :1;
94 } APMSK1_a3;
95
96 u8 APSTAT2_a4;
97 u8 APMSK2_a5;
98
99 struct {
100 u8 HABADR :7;
101 u8 na :1;
102 } HABADR_a6;
103
104 u8 HABDATA_a7;
105
106 struct {
107 u8 HABR :1;
108 u8 LDHABR :1;
109 u8 APMSK :1;
110 u8 HMSK :1;
111 u8 LDMSK :1;
112 u8 na :3;
113 } HABSTAT_a8;
114
115 u8 MADRH_a9;
116 u8 MADRL_aa;
117 u8 MDATA_ab;
118
119 struct {
120#define JDEC_WAIT_AT_RAM 0x7
121#define JDEC_EEPROM_LOAD_WAIT 0x4
122 u8 JDEC :3;
123 u8 na :5;
124 } JDEC_ca;
125
126 struct {
127 u8 REV :4;
128 u8 LAYER :4;
129 } REVID_e0;
130
131 struct {
132 u8 unk0 :1;
133 u8 CNTCTL :1;
134 u8 BITCNT :1;
135 u8 unk1 :1;
136 u8 RESYNC :1;
137 u8 unk2 :3;
138 } BERCTL_fa;
139
140 struct {
141 u8 CSEL0 :1;
142 u8 CLKED0 :1;
143 u8 CSEL1 :1;
144 u8 CLKED1 :1;
145 u8 CLKLEV :1;
146 u8 SPIVAR :1;
147 u8 na :2;
148 } TUNSET_fc;
149
150 struct {
151 u8 CLK :1;
152 u8 DATA :1;
153 u8 CS0 :1;
154 u8 CS1 :1;
155 u8 AGCSEL :1;
156 u8 na0 :1;
157 u8 TUNSEL :1;
158 u8 na1 :1;
159 } TUNCTL_fd;
160
161 u8 TUNSEL0_fe;
162 u8 TUNSEL1_ff;
163
164} bcm3510_register_value;
165
166/* HAB commands */
167
168/* version */
169#define CMD_GET_VERSION_INFO 0x3D
170#define MSGID_GET_VERSION_INFO 0x15
171struct bcm3510_hab_cmd_get_version_info {
172 u8 microcode_version;
173 u8 script_version;
174 u8 config_version;
175 u8 demod_version;
176} PACKED;
177
178#define BCM3510_DEF_MICROCODE_VERSION 0x0E
179#define BCM3510_DEF_SCRIPT_VERSION 0x06
180#define BCM3510_DEF_CONFIG_VERSION 0x01
181#define BCM3510_DEF_DEMOD_VERSION 0xB1
182
183/* acquire */
184#define CMD_ACQUIRE 0x38
185
186#define MSGID_EXT_TUNER_ACQUIRE 0x0A
187struct bcm3510_hab_cmd_ext_acquire {
188 struct {
189 u8 MODE :4;
190 u8 BW :1;
191 u8 FA :1;
192 u8 NTSCSWEEP :1;
193 u8 OFFSET :1;
194 } PACKED ACQUIRE0; /* control_byte */
195
196 struct {
197 u8 IF_FREQ :3;
198 u8 zero0 :1;
199 u8 SYM_RATE :3;
200 u8 zero1 :1;
201 } PACKED ACQUIRE1; /* sym_if */
202
203 u8 IF_OFFSET0; /* IF_Offset_10hz */
204 u8 IF_OFFSET1;
205 u8 SYM_OFFSET0; /* SymbolRateOffset */
206 u8 SYM_OFFSET1;
207 u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
208 u8 NTSC_OFFSET1;
209} PACKED;
210
211#define MSGID_INT_TUNER_ACQUIRE 0x0B
212struct bcm3510_hab_cmd_int_acquire {
213 struct {
214 u8 MODE :4;
215 u8 BW :1;
216 u8 FA :1;
217 u8 NTSCSWEEP :1;
218 u8 OFFSET :1;
219 } PACKED ACQUIRE0; /* control_byte */
220
221 struct {
222 u8 IF_FREQ :3;
223 u8 zero0 :1;
224 u8 SYM_RATE :3;
225 u8 zero1 :1;
226 } PACKED ACQUIRE1; /* sym_if */
227
228 u8 TUNER_FREQ0;
229 u8 TUNER_FREQ1;
230 u8 TUNER_FREQ2;
231 u8 TUNER_FREQ3;
232 u8 IF_OFFSET0; /* IF_Offset_10hz */
233 u8 IF_OFFSET1;
234 u8 SYM_OFFSET0; /* SymbolRateOffset */
235 u8 SYM_OFFSET1;
236 u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
237 u8 NTSC_OFFSET1;
238} PACKED;
239
240/* modes */
241#define BCM3510_QAM16 = 0x01
242#define BCM3510_QAM32 = 0x02
243#define BCM3510_QAM64 = 0x03
244#define BCM3510_QAM128 = 0x04
245#define BCM3510_QAM256 = 0x05
246#define BCM3510_8VSB = 0x0B
247#define BCM3510_16VSB = 0x0D
248
249/* IF_FREQS */
250#define BCM3510_IF_TERRESTRIAL 0x0
251#define BCM3510_IF_CABLE 0x1
252#define BCM3510_IF_USE_CMD 0x7
253
254/* SYM_RATE */
255#define BCM3510_SR_8VSB 0x0 /* 5381119 s/sec */
256#define BCM3510_SR_256QAM 0x1 /* 5360537 s/sec */
257#define BCM3510_SR_16QAM 0x2 /* 5056971 s/sec */
258#define BCM3510_SR_MISC 0x3 /* 5000000 s/sec */
259#define BCM3510_SR_USE_CMD 0x7
260
261/* special symbol rate */
262#define CMD_SET_VALUE_NOT_LISTED 0x2d
263#define MSGID_SET_SYMBOL_RATE_NOT_LISTED 0x0c
264struct bcm3510_hab_cmd_set_sr_not_listed {
265 u8 HOST_SYM_RATE0;
266 u8 HOST_SYM_RATE1;
267 u8 HOST_SYM_RATE2;
268 u8 HOST_SYM_RATE3;
269} PACKED;
270
271/* special IF */
272#define MSGID_SET_IF_FREQ_NOT_LISTED 0x0d
273struct bcm3510_hab_cmd_set_if_freq_not_listed {
274 u8 HOST_IF_FREQ0;
275 u8 HOST_IF_FREQ1;
276 u8 HOST_IF_FREQ2;
277 u8 HOST_IF_FREQ3;
278} PACKED;
279
280/* auto reacquire */
281#define CMD_AUTO_PARAM 0x2a
282#define MSGID_AUTO_REACQUIRE 0x0e
283struct bcm3510_hab_cmd_auto_reacquire {
284 u8 ACQ :1; /* on/off*/
285 u8 unused :7;
286} PACKED;
287
288#define MSGID_SET_RF_AGC_SEL 0x12
289struct bcm3510_hab_cmd_set_agc {
290 u8 LVL :1;
291 u8 unused :6;
292 u8 SEL :1;
293} PACKED;
294
295#define MSGID_SET_AUTO_INVERSION 0x14
296struct bcm3510_hab_cmd_auto_inversion {
297 u8 AI :1;
298 u8 unused :7;
299} PACKED;
300
301
302/* bert control */
303#define CMD_STATE_CONTROL 0x12
304#define MSGID_BERT_CONTROL 0x0e
305#define MSGID_BERT_SET 0xfa
306struct bcm3510_hab_cmd_bert_control {
307 u8 BE :1;
308 u8 unused :7;
309} PACKED;
310
311#define MSGID_TRI_STATE 0x2e
312struct bcm3510_hab_cmd_tri_state {
313 u8 RE :1; /* a/d ram port pins */
314 u8 PE :1; /* baud clock pin */
315 u8 AC :1; /* a/d clock pin */
316 u8 BE :1; /* baud clock pin */
317 u8 unused :4;
318} PACKED;
319
320
321/* tune */
322#define CMD_TUNE 0x38
323#define MSGID_TUNE 0x16
324struct bcm3510_hab_cmd_tune_ctrl_data_pair {
325 struct {
326#define BITS_8 0x07
327#define BITS_7 0x06
328#define BITS_6 0x05
329#define BITS_5 0x04
330#define BITS_4 0x03
331#define BITS_3 0x02
332#define BITS_2 0x01
333#define BITS_1 0x00
334 u8 size :3;
335 u8 unk :2;
336 u8 clk_off :1;
337 u8 cs0 :1;
338 u8 cs1 :1;
339
340 } PACKED ctrl;
341
342 u8 data;
343} PACKED;
344
345struct bcm3510_hab_cmd_tune {
346 u8 length;
347 u8 clock_width;
348 u8 misc;
349 u8 TUNCTL_state;
350
351 struct bcm3510_hab_cmd_tune_ctrl_data_pair ctl_dat[16];
352} PACKED;
353
354#define CMD_STATUS 0x38
355#define MSGID_STATUS1 0x08
356struct bcm3510_hab_cmd_status1 {
357 struct {
358 u8 EQ_MODE :4;
359 u8 reserved :2;
360 u8 QRE :1; /* if QSE and the spectrum is inversed */
361 u8 QSE :1; /* automatic spectral inversion */
362 } PACKED STATUS0;
363
364 struct {
365 u8 RECEIVER_LOCK :1;
366 u8 FEC_LOCK :1;
367 u8 OUT_PLL_LOCK :1;
368 u8 reserved :5;
369 } PACKED STATUS1;
370
371 struct {
372 u8 reserved :2;
373 u8 BW :1;
374 u8 NTE :1; /* NTSC filter sweep enabled */
375 u8 AQI :1; /* currently acquiring */
376 u8 FA :1; /* fast acquisition */
377 u8 ARI :1; /* auto reacquire */
378 u8 TI :1; /* programming the tuner */
379 } PACKED STATUS2;
380 u8 STATUS3;
381 u8 SNR_EST0;
382 u8 SNR_EST1;
383 u8 TUNER_FREQ0;
384 u8 TUNER_FREQ1;
385 u8 TUNER_FREQ2;
386 u8 TUNER_FREQ3;
387 u8 SYM_RATE0;
388 u8 SYM_RATE1;
389 u8 SYM_RATE2;
390 u8 SYM_RATE3;
391 u8 SYM_OFFSET0;
392 u8 SYM_OFFSET1;
393 u8 SYM_ERROR0;
394 u8 SYM_ERROR1;
395 u8 IF_FREQ0;
396 u8 IF_FREQ1;
397 u8 IF_FREQ2;
398 u8 IF_FREQ3;
399 u8 IF_OFFSET0;
400 u8 IF_OFFSET1;
401 u8 IF_ERROR0;
402 u8 IF_ERROR1;
403 u8 NTSC_FILTER0;
404 u8 NTSC_FILTER1;
405 u8 NTSC_FILTER2;
406 u8 NTSC_FILTER3;
407 u8 NTSC_OFFSET0;
408 u8 NTSC_OFFSET1;
409 u8 NTSC_ERROR0;
410 u8 NTSC_ERROR1;
411 u8 INT_AGC_LEVEL0;
412 u8 INT_AGC_LEVEL1;
413 u8 EXT_AGC_LEVEL0;
414 u8 EXT_AGC_LEVEL1;
415} PACKED;
416
417#define MSGID_STATUS2 0x14
418struct bcm3510_hab_cmd_status2 {
419 struct {
420 u8 EQ_MODE :4;
421 u8 reserved :2;
422 u8 QRE :1;
423 u8 QSR :1;
424 } PACKED STATUS0;
425 struct {
426 u8 RL :1;
427 u8 FL :1;
428 u8 OL :1;
429 u8 reserved :5;
430 } PACKED STATUS1;
431 u8 SYMBOL_RATE0;
432 u8 SYMBOL_RATE1;
433 u8 SYMBOL_RATE2;
434 u8 SYMBOL_RATE3;
435 u8 LDCERC0;
436 u8 LDCERC1;
437 u8 LDCERC2;
438 u8 LDCERC3;
439 u8 LDUERC0;
440 u8 LDUERC1;
441 u8 LDUERC2;
442 u8 LDUERC3;
443 u8 LDBER0;
444 u8 LDBER1;
445 u8 LDBER2;
446 u8 LDBER3;
447 struct {
448 u8 MODE_TYPE :4; /* acquire mode 0 */
449 u8 reservd :4;
450 } MODE_TYPE;
451 u8 SNR_EST0;
452 u8 SNR_EST1;
453 u8 SIGNAL;
454} PACKED;
455
456#define CMD_SET_RF_BW_NOT_LISTED 0x3f
457#define MSGID_SET_RF_BW_NOT_LISTED 0x11
458/* TODO */
459
460#endif
diff --git a/drivers/media/dvb/frontends/dib3000-common.c b/drivers/media/dvb/frontends/dib3000-common.c
index 47ab02e133..1a4f1f7c22 100644
--- a/drivers/media/dvb/frontends/dib3000-common.c
+++ b/drivers/media/dvb/frontends/dib3000-common.c
@@ -73,7 +73,7 @@ u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
73 }; 73 };
74 74
75MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de"); 75MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
76MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb-frontend drivers"); 76MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
77MODULE_LICENSE("GPL"); 77MODULE_LICENSE("GPL");
78 78
79EXPORT_SYMBOL(dib3000_seq); 79EXPORT_SYMBOL(dib3000_seq);
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
index 80687c1308..2d5475b5c0 100644
--- a/drivers/media/dvb/frontends/dib3000.h
+++ b/drivers/media/dvb/frontends/dib3000.h
@@ -32,9 +32,8 @@ struct dib3000_config
32 u8 demod_address; 32 u8 demod_address;
33 33
34 /* PLL maintenance and the i2c address of the PLL */ 34 /* PLL maintenance and the i2c address of the PLL */
35 u8 (*pll_addr)(struct dvb_frontend *fe); 35 int (*pll_init)(struct dvb_frontend *fe);
36 int (*pll_init)(struct dvb_frontend *fe, u8 pll_buf[5]); 36 int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
37 int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params, u8 pll_buf[5]);
38}; 37};
39 38
40struct dib_fe_xfer_ops 39struct dib_fe_xfer_ops
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index 6f52d649e9..cd434b7cf9 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -48,8 +48,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a
48#define deb_setf(args...) dprintk(0x04,args) 48#define deb_setf(args...) dprintk(0x04,args)
49#define deb_getf(args...) dprintk(0x08,args) 49#define deb_getf(args...) dprintk(0x08,args)
50 50
51static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr);
52
53static int dib3000mb_get_frontend(struct dvb_frontend* fe, 51static int dib3000mb_get_frontend(struct dvb_frontend* fe,
54 struct dvb_frontend_parameters *fep); 52 struct dvb_frontend_parameters *fep);
55 53
@@ -61,10 +59,8 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
61 fe_code_rate_t fe_cr = FEC_NONE; 59 fe_code_rate_t fe_cr = FEC_NONE;
62 int search_state, seq; 60 int search_state, seq;
63 61
64 if (tuner && state->config.pll_addr && state->config.pll_set) { 62 if (tuner && state->config.pll_set) {
65 dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); 63 state->config.pll_set(fe, fep);
66 state->config.pll_set(fe, fep, NULL);
67 dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
68 64
69 deb_setf("bandwidth: "); 65 deb_setf("bandwidth: ");
70 switch (ofdm->bandwidth) { 66 switch (ofdm->bandwidth) {
@@ -389,11 +385,8 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
389 385
390 wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF); 386 wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
391 387
392 if (state->config.pll_init) { 388 if (state->config.pll_init)
393 dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); 389 state->config.pll_init(fe);
394 state->config.pll_init(fe,NULL);
395 dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
396 }
397 390
398 return 0; 391 return 0;
399} 392}
@@ -623,7 +616,7 @@ static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
623{ 616{
624 struct dib3000_state* state = fe->demodulator_priv; 617 struct dib3000_state* state = fe->demodulator_priv;
625 618
626 *unc = rd(DIB3000MB_REG_UNC); 619 *unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);
627 return 0; 620 return 0;
628} 621}
629 622
@@ -638,9 +631,6 @@ static int dib3000mb_sleep(struct dvb_frontend* fe)
638static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) 631static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
639{ 632{
640 tune->min_delay_ms = 800; 633 tune->min_delay_ms = 800;
641 tune->step_size = 166667;
642 tune->max_drift = 166667 * 2;
643
644 return 0; 634 return 0;
645} 635}
646 636
diff --git a/drivers/media/dvb/frontends/dib3000mb_priv.h b/drivers/media/dvb/frontends/dib3000mb_priv.h
index 57e61aa5b0..999b190478 100644
--- a/drivers/media/dvb/frontends/dib3000mb_priv.h
+++ b/drivers/media/dvb/frontends/dib3000mb_priv.h
@@ -294,7 +294,7 @@ static u16 dib3000mb_reg_filter_coeffs[] = {
294 294
295static u16 dib3000mb_filter_coeffs[] = { 295static u16 dib3000mb_filter_coeffs[] = {
296 226, 160, 29, 296 226, 160, 29,
297 979, 998, 19, 297 979, 998, 19,
298 22, 1019, 1006, 298 22, 1019, 1006,
299 1022, 12, 6, 299 1022, 12, 6,
300 1017, 1017, 3, 300 1017, 1017, 3,
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 888f10a5e9..cd33705a43 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -48,8 +48,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=s
48#define deb_getf(args...) dprintk(0x08,args) 48#define deb_getf(args...) dprintk(0x08,args)
49#define deb_stat(args...) dprintk(0x10,args) 49#define deb_stat(args...) dprintk(0x10,args)
50 50
51static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr);
52
53static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode, 51static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,
54 fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth) 52 fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth)
55{ 53{
@@ -463,10 +461,8 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
463 int search_state,auto_val; 461 int search_state,auto_val;
464 u16 val; 462 u16 val;
465 463
466 if (tuner && state->config.pll_addr && state->config.pll_set) { /* initial call from dvb */ 464 if (tuner && state->config.pll_set) { /* initial call from dvb */
467 dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); 465 state->config.pll_set(fe,fep);
468 state->config.pll_set(fe,fep,NULL);
469 dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
470 466
471 state->last_tuned_freq = fep->frequency; 467 state->last_tuned_freq = fep->frequency;
472 // if (!scanboost) { 468 // if (!scanboost) {
@@ -554,19 +550,15 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
554 dib3000mc_set_adp_cfg(state,ofdm->constellation); 550 dib3000mc_set_adp_cfg(state,ofdm->constellation);
555 wr_foreach(dib3000mc_reg_offset, 551 wr_foreach(dib3000mc_reg_offset,
556 dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]); 552 dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
557
558
559 } 553 }
560 return 0; 554 return 0;
561} 555}
562 556
563static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode) 557static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
564{ 558{
565 struct dib3000_state *state; 559 struct dib3000_state *state = fe->demodulator_priv;
566
567 deb_info("init start\n"); 560 deb_info("init start\n");
568 561
569 state = fe->demodulator_priv;
570 state->timing_offset = 0; 562 state->timing_offset = 0;
571 state->timing_offset_comp_done = 0; 563 state->timing_offset_comp_done = 0;
572 564
@@ -649,11 +641,9 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
649 641
650 set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF); 642 set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
651 643
652/* if (state->config->pll_init) { 644 if (state->config.pll_init)
653 dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe)); 645 state->config.pll_init(fe);
654 state->config->pll_init(fe,NULL); 646
655 dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
656 }*/
657 deb_info("init end\n"); 647 deb_info("init end\n");
658 return 0; 648 return 0;
659} 649}
@@ -688,7 +678,7 @@ static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
688{ 678{
689 struct dib3000_state* state = fe->demodulator_priv; 679 struct dib3000_state* state = fe->demodulator_priv;
690 680
691 *unc = rd(DIB3000MC_REG_PACKET_ERROR_COUNT); 681 *unc = rd(DIB3000MC_REG_PACKET_ERRORS);
692 return 0; 682 return 0;
693} 683}
694 684
@@ -737,10 +727,7 @@ static int dib3000mc_sleep(struct dvb_frontend* fe)
737 727
738static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) 728static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
739{ 729{
740 tune->min_delay_ms = 2000; 730 tune->min_delay_ms = 1000;
741 tune->step_size = 166667;
742 tune->max_drift = 166667 * 2;
743
744 return 0; 731 return 0;
745} 732}
746 733
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 2a3c2ce7b2..f73b5f48e2 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -1,6 +1,4 @@
1/* 1/*
2 * $Id: dvb-pll.c,v 1.7 2005/02/10 11:52:02 kraxel Exp $
3 *
4 * descriptions + helper functions for simple dvb plls. 2 * descriptions + helper functions for simple dvb plls.
5 * 3 *
6 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 4 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
@@ -114,6 +112,92 @@ struct dvb_pll_desc dvb_pll_unknown_1 = {
114}; 112};
115EXPORT_SYMBOL(dvb_pll_unknown_1); 113EXPORT_SYMBOL(dvb_pll_unknown_1);
116 114
115/* Infineon TUA6010XS
116 * used in Thomson Cable Tuner
117 */
118struct dvb_pll_desc dvb_pll_tua6010xs = {
119 .name = "Infineon TUA6010XS",
120 .min = 44250000,
121 .max = 858000000,
122 .count = 3,
123 .entries = {
124 { 115750000, 36125000, 62500, 0x8e, 0x03 },
125 { 403250000, 36125000, 62500, 0x8e, 0x06 },
126 { 999999999, 36125000, 62500, 0x8e, 0x85 },
127 },
128};
129EXPORT_SYMBOL(dvb_pll_tua6010xs);
130
131/* Panasonic env57h1xd5 (some Philips PLL ?) */
132struct dvb_pll_desc dvb_pll_env57h1xd5 = {
133 .name = "Panasonic ENV57H1XD5",
134 .min = 44250000,
135 .max = 858000000,
136 .count = 4,
137 .entries = {
138 { 153000000, 36291666, 166666, 0xc2, 0x41 },
139 { 470000000, 36291666, 166666, 0xc2, 0x42 },
140 { 526000000, 36291666, 166666, 0xc2, 0x84 },
141 { 999999999, 36291666, 166666, 0xc2, 0xa4 },
142 },
143};
144EXPORT_SYMBOL(dvb_pll_env57h1xd5);
145
146/* Philips TDA6650/TDA6651
147 * used in Panasonic ENV77H11D5
148 */
149static void tda665x_bw(u8 *buf, int bandwidth)
150{
151 if (bandwidth == BANDWIDTH_8_MHZ)
152 buf[3] |= 0x08;
153}
154
155struct dvb_pll_desc dvb_pll_tda665x = {
156 .name = "Philips TDA6650/TDA6651",
157 .min = 44250000,
158 .max = 858000000,
159 .setbw = tda665x_bw,
160 .count = 12,
161 .entries = {
162 { 93834000, 36249333, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ },
163 { 123834000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ },
164 { 161000000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ },
165 { 163834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ },
166 { 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ },
167 { 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ },
168 { 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ },
169 { 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
170 { 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ },
171 { 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ },
172 { 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
173 { 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ },
174 }
175};
176EXPORT_SYMBOL(dvb_pll_tda665x);
177
178/* Infineon TUA6034
179 * used in LG TDTP E102P
180 */
181static void tua6034_bw(u8 *buf, int bandwidth)
182{
183 if (BANDWIDTH_7_MHZ != bandwidth)
184 buf[3] |= 0x08;
185}
186
187struct dvb_pll_desc dvb_pll_tua6034 = {
188 .name = "Infineon TUA6034",
189 .min = 44250000,
190 .max = 858000000,
191 .count = 3,
192 .setbw = tua6034_bw,
193 .entries = {
194 { 174500000, 36166667, 62500, 0xce, 0x01 },
195 { 230000000, 36166667, 62500, 0xce, 0x02 },
196 { 999999999, 36166667, 62500, 0xce, 0x04 },
197 },
198};
199EXPORT_SYMBOL(dvb_pll_tua6034);
200
117/* ----------------------------------------------------------- */ 201/* ----------------------------------------------------------- */
118/* code */ 202/* code */
119 203
@@ -160,9 +244,3 @@ EXPORT_SYMBOL(dvb_pll_configure);
160MODULE_DESCRIPTION("dvb pll library"); 244MODULE_DESCRIPTION("dvb pll library");
161MODULE_AUTHOR("Gerd Knorr"); 245MODULE_AUTHOR("Gerd Knorr");
162MODULE_LICENSE("GPL"); 246MODULE_LICENSE("GPL");
163
164/*
165 * Local variables:
166 * c-basic-offset: 8
167 * End:
168 */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index c4c3c56c4a..b796778624 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: dvb-pll.h,v 1.2 2005/02/10 11:43:41 kraxel Exp $ 2 * descriptions + helper functions for simple dvb plls.
3 */ 3 */
4 4
5#ifndef __DVB_PLL_H__ 5#ifndef __DVB_PLL_H__
@@ -17,7 +17,7 @@ struct dvb_pll_desc {
17 u32 stepsize; 17 u32 stepsize;
18 u8 cb1; 18 u8 cb1;
19 u8 cb2; 19 u8 cb2;
20 } entries[9]; 20 } entries[12];
21}; 21};
22 22
23extern struct dvb_pll_desc dvb_pll_thomson_dtt7579; 23extern struct dvb_pll_desc dvb_pll_thomson_dtt7579;
@@ -26,6 +26,11 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
26extern struct dvb_pll_desc dvb_pll_lg_z201; 26extern struct dvb_pll_desc dvb_pll_lg_z201;
27extern struct dvb_pll_desc dvb_pll_unknown_1; 27extern struct dvb_pll_desc dvb_pll_unknown_1;
28 28
29extern struct dvb_pll_desc dvb_pll_tua6010xs;
30extern struct dvb_pll_desc dvb_pll_env57h1xd5;
31extern struct dvb_pll_desc dvb_pll_tua6034;
32extern struct dvb_pll_desc dvb_pll_tda665x;
33
29int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, 34int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
30 u32 freq, int bandwidth); 35 u32 freq, int bandwidth);
31 36
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 6c05fddb69..f9383e7f34 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -7,6 +7,19 @@ menu "Video For Linux"
7 7
8comment "Video Adapters" 8comment "Video Adapters"
9 9
10config CONFIG_TUNER_MULTI_I2C
11 bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)"
12 depends on VIDEO_DEV && EXPERIMENTAL
13 ---help---
14 Some video adapters have more than one tuner inside. This patch
15 enables support for using more than one tuner. This is required
16 for some cards to allow tunning both video and radio.
17 It also improves I2C autodetection for these cards.
18
19 Only few tuners currently is supporting this. More to come.
20
21 It is safe to say 'Y' here even if your card has only one I2C tuner.
22
10config VIDEO_BT848 23config VIDEO_BT848
11 tristate "BT848 Video For Linux" 24 tristate "BT848 Video For Linux"
12 depends on VIDEO_DEV && PCI && I2C 25 depends on VIDEO_DEV && PCI && I2C
@@ -330,6 +343,7 @@ config VIDEO_CX88_DVB
330 select VIDEO_BUF_DVB 343 select VIDEO_BUF_DVB
331 select DVB_MT352 344 select DVB_MT352
332 select DVB_OR51132 345 select DVB_OR51132
346 select DVB_CX22702
333 ---help--- 347 ---help---
334 This adds support for DVB/ATSC cards based on the 348 This adds support for DVB/ATSC cards based on the
335 Connexant 2388x chip. 349 Connexant 2388x chip.
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index 07f72f64c5..9a642c7de5 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -6,7 +6,7 @@
6 It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly 6 It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly
7 connected to bt848/bt878 GPIO pins on this purpose. 7 connected to bt848/bt878 GPIO pins on this purpose.
8 (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets) 8 (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets)
9 9
10 Supported Cards: 10 Supported Cards:
11 - Pixelview Rev.4E: 0x8a 11 - Pixelview Rev.4E: 0x8a
12 GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 ! 12 GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 !
@@ -31,8 +31,8 @@
31#include <linux/errno.h> 31#include <linux/errno.h>
32#include <linux/slab.h> 32#include <linux/slab.h>
33 33
34#include "id.h" 34#include <media/audiochip.h>
35#include "audiochip.h" 35#include <media/id.h>
36#include "bttv.h" 36#include "bttv.h"
37#include "bt832.h" 37#include "bt832.h"
38 38
@@ -95,7 +95,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
95 95
96 buf=kmalloc(65,GFP_KERNEL); 96 buf=kmalloc(65,GFP_KERNEL);
97 bt832_hexdump(i2c_client_s,buf); 97 bt832_hexdump(i2c_client_s,buf);
98 98
99 if(buf[0x40] != 0x31) { 99 if(buf[0x40] != 0x31) {
100 printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]); 100 printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
101 kfree(buf); 101 kfree(buf);
@@ -135,7 +135,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
135 buf[1]= 0x27 & (~0x01); // Default | !skip 135 buf[1]= 0x27 & (~0x01); // Default | !skip
136 if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) 136 if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
137 printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); 137 printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc);
138 138
139 bt832_hexdump(i2c_client_s,buf); 139 bt832_hexdump(i2c_client_s,buf);
140 140
141#if 0 141#if 0
@@ -168,8 +168,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
168 168
169 169
170 170
171static int bt832_attach(struct i2c_adapter *adap, int addr, 171static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
172 unsigned short flags, int kind)
173{ 172{
174 struct bt832 *t; 173 struct bt832 *t;
175 174
@@ -184,27 +183,32 @@ static int bt832_attach(struct i2c_adapter *adap, int addr,
184 return -ENOMEM; 183 return -ENOMEM;
185 memset(t,0,sizeof(*t)); 184 memset(t,0,sizeof(*t));
186 t->client = client_template; 185 t->client = client_template;
187 t->client.data = t; 186 i2c_set_clientdata(&t->client, t);
188 i2c_attach_client(&t->client); 187 i2c_attach_client(&t->client);
189 188
190 if(! bt832_init(&t->client)) { 189 if(! bt832_init(&t->client)) {
191 bt832_detach(&t->client); 190 bt832_detach(&t->client);
192 return -1; 191 return -1;
193 } 192 }
194 193
195 return 0; 194 return 0;
196} 195}
197 196
198static int bt832_probe(struct i2c_adapter *adap) 197static int bt832_probe(struct i2c_adapter *adap)
199{ 198{
199#ifdef I2C_CLASS_TV_ANALOG
200 if (adap->class & I2C_CLASS_TV_ANALOG) 200 if (adap->class & I2C_CLASS_TV_ANALOG)
201 return i2c_probe(adap, &addr_data, bt832_attach); 201 return i2c_probe(adap, &addr_data, bt832_attach);
202#else
203 if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
204 return i2c_probe(adap, &addr_data, bt832_attach);
205#endif
202 return 0; 206 return 0;
203} 207}
204 208
205static int bt832_detach(struct i2c_client *client) 209static int bt832_detach(struct i2c_client *client)
206{ 210{
207 struct bt832 *t = (struct bt832*)client->data; 211 struct bt832 *t = i2c_get_clientdata(client);
208 212
209 printk("bt832: detach.\n"); 213 printk("bt832: detach.\n");
210 i2c_detach_client(client); 214 i2c_detach_client(client);
@@ -215,7 +219,7 @@ static int bt832_detach(struct i2c_client *client)
215static int 219static int
216bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) 220bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
217{ 221{
218 struct bt832 *t = (struct bt832*)client->data; 222 struct bt832 *t = i2c_get_clientdata(client);
219 223
220 printk("bt832: command %x\n",cmd); 224 printk("bt832: command %x\n",cmd);
221 225
@@ -249,19 +253,18 @@ static struct i2c_driver driver = {
249}; 253};
250static struct i2c_client client_template = 254static struct i2c_client client_template =
251{ 255{
252 .name = "bt832", 256 I2C_DEVNAME("bt832"),
253 .flags = I2C_CLIENT_ALLOW_USE, 257 .flags = I2C_CLIENT_ALLOW_USE,
254 .driver = &driver, 258 .driver = &driver,
255}; 259};
256 260
257 261
258int bt832_init_module(void) 262static int __init bt832_init_module(void)
259{ 263{
260 i2c_add_driver(&driver); 264 return i2c_add_driver(&driver);
261 return 0;
262} 265}
263 266
264static void bt832_cleanup_module(void) 267static void __exit bt832_cleanup_module(void)
265{ 268{
266 i2c_del_driver(&driver); 269 i2c_del_driver(&driver);
267} 270}
@@ -269,3 +272,10 @@ static void bt832_cleanup_module(void)
269module_init(bt832_init_module); 272module_init(bt832_init_module);
270module_exit(bt832_cleanup_module); 273module_exit(bt832_cleanup_module);
271 274
275/*
276 * Overrides for Emacs so that we follow Linus's tabbing style.
277 * ---------------------------------------------------------------------------
278 * Local variables:
279 * c-basic-offset: 8
280 * End:
281 */
diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h
index 7a98c06e0e..9b6a8d2c96 100644
--- a/drivers/media/video/bt832.h
+++ b/drivers/media/video/bt832.h
@@ -1,6 +1,6 @@
1/* Bt832 CMOS Camera Video Processor (VP) 1/* Bt832 CMOS Camera Video Processor (VP)
2 2
3 The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS 3 The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS
4 color digital camera directly to video capture devices via an 8-bit, 4 color digital camera directly to video capture devices via an 8-bit,
5 4:2:2 YUV or YCrCb video interface. 5 4:2:2 YUV or YCrCb video interface.
6 6
@@ -85,7 +85,7 @@
85#define BT832_DEVICE_ID 63 85#define BT832_DEVICE_ID 63
86# define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31 86# define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31
87 87
88/* STMicroelectronivcs VV5404 camera module 88/* STMicroelectronivcs VV5404 camera module
89 i2c: 0x20: sensor address 89 i2c: 0x20: sensor address
90 i2c: 0xa0: eeprom for ccd defect map 90 i2c: 0xa0: eeprom for ccd defect map
91 */ 91 */
@@ -256,26 +256,26 @@ For the CCIR-601 standards, the sampling is based on a static orthogonal samplin
256//=========================================================================== 256//===========================================================================
257// Timing generator SRAM table values for CCIR601 720x480 NTSC 257// Timing generator SRAM table values for CCIR601 720x480 NTSC
258//=========================================================================== 258//===========================================================================
259// For NTSC CCIR656 259// For NTSC CCIR656
260BYTE BtCard::SRAMTable_NTSC[] = 260BYTE BtCard::SRAMTable_NTSC[] =
261{ 261{
262 // SRAM Timing Table for NTSC 262 // SRAM Timing Table for NTSC
263 0x0c, 0xc0, 0x00, 263 0x0c, 0xc0, 0x00,
264 0x00, 0x90, 0xc2, 264 0x00, 0x90, 0xc2,
265 0x03, 0x10, 0x03, 265 0x03, 0x10, 0x03,
266 0x06, 0x10, 0x34, 266 0x06, 0x10, 0x34,
267 0x12, 0x12, 0x65, 267 0x12, 0x12, 0x65,
268 0x02, 0x13, 0x24, 268 0x02, 0x13, 0x24,
269 0x19, 0x00, 0x24, 269 0x19, 0x00, 0x24,
270 0x39, 0x00, 0x96, 270 0x39, 0x00, 0x96,
271 0x59, 0x08, 0x93, 271 0x59, 0x08, 0x93,
272 0x83, 0x08, 0x97, 272 0x83, 0x08, 0x97,
273 0x03, 0x50, 0x30, 273 0x03, 0x50, 0x30,
274 0xc0, 0x40, 0x30, 274 0xc0, 0x40, 0x30,
275 0x86, 0x01, 0x01, 275 0x86, 0x01, 0x01,
276 0xa6, 0x0d, 0x62, 276 0xa6, 0x0d, 0x62,
277 0x03, 0x11, 0x61, 277 0x03, 0x11, 0x61,
278 0x05, 0x37, 0x30, 278 0x05, 0x37, 0x30,
279 0xac, 0x21, 0x50 279 0xac, 0x21, 0x50
280}; 280};
281 281
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 6334122704..251092e7f1 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -1,5 +1,5 @@
1/* 1/*
2 $Id: bttv-cards.c,v 1.47 2005/02/22 14:06:32 kraxel Exp $ 2 $Id: bttv-cards.c,v 1.49 2005/06/10 17:20:24 mchehab Exp $
3 3
4 bttv-cards.c 4 bttv-cards.c
5 5
@@ -51,6 +51,7 @@ static void avermedia_eeprom(struct bttv *btv);
51static void osprey_eeprom(struct bttv *btv); 51static void osprey_eeprom(struct bttv *btv);
52static void modtec_eeprom(struct bttv *btv); 52static void modtec_eeprom(struct bttv *btv);
53static void init_PXC200(struct bttv *btv); 53static void init_PXC200(struct bttv *btv);
54static void init_RTV24(struct bttv *btv);
54 55
55static void winview_audio(struct bttv *btv, struct video_audio *v, int set); 56static void winview_audio(struct bttv *btv, struct video_audio *v, int set);
56static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); 57static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set);
@@ -2251,6 +2252,20 @@ struct tvcard bttv_tvcards[] = {
2251 .no_tda7432 = 1, 2252 .no_tda7432 = 1,
2252 .no_tda9875 = 1, 2253 .no_tda9875 = 1,
2253 .muxsel_hook = kodicom4400r_muxsel, 2254 .muxsel_hook = kodicom4400r_muxsel,
2255},
2256{
2257 /* ---- card 0x85---------------------------------- */
2258 /* Michael Henson <mhenson@clarityvi.com> */
2259 /* Adlink RTV24 with special unlock codes */
2260 .name = "Adlink RTV24",
2261 .video_inputs = 4,
2262 .audio_inputs = 1,
2263 .tuner = 0,
2264 .svhs = 2,
2265 .muxsel = { 2, 3, 1, 0},
2266 .tuner_type = -1,
2267 .pll = PLL_28,
2268
2254}}; 2269}};
2255 2270
2256static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); 2271static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2636,6 +2651,10 @@ void __devinit bttv_init_card1(struct bttv *btv)
2636 case BTTV_AVDVBT_771: 2651 case BTTV_AVDVBT_771:
2637 btv->use_i2c_hw = 1; 2652 btv->use_i2c_hw = 1;
2638 break; 2653 break;
2654 case BTTV_ADLINK_RTV24:
2655 init_RTV24( btv );
2656 break;
2657
2639 } 2658 }
2640 if (!bttv_tvcards[btv->c.type].has_dvb) 2659 if (!bttv_tvcards[btv->c.type].has_dvb)
2641 bttv_reset_audio(btv); 2660 bttv_reset_audio(btv);
@@ -2784,6 +2803,8 @@ void __devinit bttv_init_card2(struct bttv *btv)
2784 } 2803 }
2785 btv->pll.pll_current = -1; 2804 btv->pll.pll_current = -1;
2786 2805
2806 bttv_reset_audio(btv);
2807
2787 /* tuner configuration (from card list / autodetect / insmod option) */ 2808 /* tuner configuration (from card list / autodetect / insmod option) */
2788 if (UNSET != bttv_tvcards[btv->c.type].tuner_type) 2809 if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
2789 if(UNSET == btv->tuner_type) 2810 if(UNSET == btv->tuner_type)
@@ -3304,6 +3325,83 @@ static void __devinit init_PXC200(struct bttv *btv)
3304} 3325}
3305 3326
3306 3327
3328
3329/* ----------------------------------------------------------------------- */
3330/*
3331 * The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock
3332 * it. This apparently involves the following procedure for each 878 chip:
3333 *
3334 * 1) write 0x00C3FEFF to the GPIO_OUT_EN register
3335 *
3336 * 2) write to GPIO_DATA
3337 * - 0x0E
3338 * - sleep 1ms
3339 * - 0x10 + 0x0E
3340 * - sleep 10ms
3341 * - 0x0E
3342 * read from GPIO_DATA into buf (uint_32)
3343 * - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 )
3344 * error. ERROR_CPLD_Check_Failed stop.
3345 *
3346 * 3) write to GPIO_DATA
3347 * - write 0x4400 + 0x0E
3348 * - sleep 10ms
3349 * - write 0x4410 + 0x0E
3350 * - sleep 1ms
3351 * - write 0x0E
3352 * read from GPIO_DATA into buf (uint_32)
3353 * - if ( buf>>18 & 0x01 ) || ( buf>>19 && 0x01 != 0 )
3354 * error. ERROR_CPLD_Check_Failed.
3355 */
3356/* ----------------------------------------------------------------------- */
3357void
3358init_RTV24 (struct bttv *btv)
3359{
3360 uint32_t dataRead = 0;
3361 long watchdog_value = 0x0E;
3362
3363 printk (KERN_INFO
3364 "bttv%d: Adlink RTV-24 initialisation in progress ...\n",
3365 btv->c.nr);
3366
3367 btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
3368
3369 btwrite (0 + watchdog_value, BT848_GPIO_DATA);
3370 msleep (1);
3371 btwrite (0x10 + watchdog_value, BT848_GPIO_DATA);
3372 msleep (10);
3373 btwrite (0 + watchdog_value, BT848_GPIO_DATA);
3374
3375 dataRead = btread (BT848_GPIO_DATA);
3376
3377 if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
3378 printk (KERN_INFO
3379 "bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
3380 btv->c.nr, dataRead);
3381 }
3382
3383 btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA);
3384 msleep (10);
3385 btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA);
3386 msleep (1);
3387 btwrite (watchdog_value, BT848_GPIO_DATA);
3388 msleep (1);
3389 dataRead = btread (BT848_GPIO_DATA);
3390
3391 if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
3392 printk (KERN_INFO
3393 "bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
3394 btv->c.nr, dataRead);
3395
3396 return;
3397 }
3398
3399 printk (KERN_INFO
3400 "bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr);
3401}
3402
3403
3404
3307/* ----------------------------------------------------------------------- */ 3405/* ----------------------------------------------------------------------- */
3308/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */ 3406/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */
3309/* 3407/*
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 033cc5498f..290289a997 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1,5 +1,5 @@
1/* 1/*
2 $Id: bttv-driver.c,v 1.37 2005/02/21 13:57:59 kraxel Exp $ 2 $Id: bttv-driver.c,v 1.38 2005/06/10 17:20:24 mchehab Exp $
3 3
4 bttv - Bt848 frame grabber driver 4 bttv - Bt848 frame grabber driver
5 5
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index c2368bc832..da448a5f9e 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -1,5 +1,5 @@
1/* 1/*
2 $Id: bttv-i2c.c,v 1.18 2005/02/16 12:14:10 kraxel Exp $ 2 $Id: bttv-i2c.c,v 1.21 2005/06/10 17:20:24 mchehab Exp $
3 3
4 bttv-i2c.c -- all the i2c code is here 4 bttv-i2c.c -- all the i2c code is here
5 5
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 8322b66e09..191eaf1714 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: bttv.h,v 1.17 2005/02/22 14:06:32 kraxel Exp $ 2 * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $
3 * 3 *
4 * bttv - Bt848 frame grabber driver 4 * bttv - Bt848 frame grabber driver
5 * 5 *
@@ -135,6 +135,7 @@
135#define BTTV_DVICO_DVBT_LITE 0x80 135#define BTTV_DVICO_DVBT_LITE 0x80
136#define BTTV_TIBET_CS16 0x83 136#define BTTV_TIBET_CS16 0x83
137#define BTTV_KODICOM_4400R 0x84 137#define BTTV_KODICOM_4400R 0x84
138#define BTTV_ADLINK_RTV24 0x85
138 139
139/* i2c address list */ 140/* i2c address list */
140#define I2C_TSA5522 0xc2 141#define I2C_TSA5522 0xc2
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 1a9ba7e1cf..7b6f1e8560 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -226,10 +226,6 @@ extern int fini_bttv_i2c(struct bttv *btv);
226#define dprintk if (bttv_debug >= 1) printk 226#define dprintk if (bttv_debug >= 1) printk
227#define d2printk if (bttv_debug >= 2) printk 227#define d2printk if (bttv_debug >= 2) printk
228 228
229/* our devices */
230#define BTTV_MAX 16
231extern unsigned int bttv_num;
232
233#define BTTV_MAX_FBUF 0x208000 229#define BTTV_MAX_FBUF 0x208000
234#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) 230#define VBIBUF_SIZE (2048*VBI_MAXLINES*2)
235#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ 231#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */
@@ -375,6 +371,10 @@ struct bttv {
375 unsigned int users; 371 unsigned int users;
376 struct bttv_fh init; 372 struct bttv_fh init;
377}; 373};
374
375/* our devices */
376#define BTTV_MAX 16
377extern unsigned int bttv_num;
378extern struct bttv bttvs[BTTV_MAX]; 378extern struct bttv bttvs[BTTV_MAX];
379 379
380/* private ioctls */ 380/* private ioctls */
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 46d6778b86..91f8afeded 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $ 2 * $Id: cx88-blackbird.c,v 1.27 2005/06/03 13:31:50 mchehab Exp $
3 * 3 *
4 * Support for a cx23416 mpeg encoder via cx2388x host port. 4 * Support for a cx23416 mpeg encoder via cx2388x host port.
5 * "blackbird" reference design. 5 * "blackbird" reference design.
@@ -61,37 +61,304 @@ static LIST_HEAD(cx8802_devlist);
61 61
62#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF 62#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
63 63
64/*Firmware API commands*/ 64/* Firmware API commands */
65#define IVTV_API_ENC_PING_FW 0x00000080 65/* #define IVTV_API_STD_TIMEOUT 0x00010000 // 65536, units?? */
66#define IVTV_API_ENC_GETVER 0x000000C4 66#define IVTV_API_STD_TIMEOUT 500
67#define IVTV_API_ENC_HALT_FW 0x000000C3 67
68#define IVTV_API_STD_TIMEOUT 0x00010000 /*units??*/ 68#define BLACKBIRD_API_PING 0x80
69//#define IVTV_API_ASSIGN_PGM_INDEX_INFO 0x000000c7 69#define BLACKBIRD_API_BEGIN_CAPTURE 0x81
70#define IVTV_API_ASSIGN_STREAM_TYPE 0x000000b9 70enum blackbird_capture_type {
71#define IVTV_API_ASSIGN_OUTPUT_PORT 0x000000bb 71 BLACKBIRD_MPEG_CAPTURE,
72#define IVTV_API_ASSIGN_FRAMERATE 0x0000008f 72 BLACKBIRD_RAW_CAPTURE,
73#define IVTV_API_ASSIGN_FRAME_SIZE 0x00000091 73 BLACKBIRD_RAW_PASSTHRU_CAPTURE
74#define IVTV_API_ASSIGN_ASPECT_RATIO 0x00000099 74};
75#define IVTV_API_ASSIGN_BITRATES 0x00000095 75enum blackbird_capture_bits {
76#define IVTV_API_ASSIGN_GOP_PROPERTIES 0x00000097 76 BLACKBIRD_RAW_BITS_NONE = 0x00,
77#define IVTV_API_ASSIGN_3_2_PULLDOWN 0x000000b1 77 BLACKBIRD_RAW_BITS_YUV_CAPTURE = 0x01,
78#define IVTV_API_ASSIGN_GOP_CLOSURE 0x000000c5 78 BLACKBIRD_RAW_BITS_PCM_CAPTURE = 0x02,
79#define IVTV_API_ASSIGN_AUDIO_PROPERTIES 0x000000bd 79 BLACKBIRD_RAW_BITS_VBI_CAPTURE = 0x04,
80#define IVTV_API_ASSIGN_DNR_FILTER_MODE 0x0000009b 80 BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
81#define IVTV_API_ASSIGN_DNR_FILTER_PROPS 0x0000009d 81 BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10
82#define IVTV_API_ASSIGN_CORING_LEVELS 0x0000009f 82};
83#define IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE 0x000000a1 83#define BLACKBIRD_API_END_CAPTURE 0x82
84#define IVTV_API_ASSIGN_FRAME_DROP_RATE 0x000000d0 84enum blackbird_capture_end {
85#define IVTV_API_ASSIGN_PLACEHOLDER 0x000000d8 85 BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
86#define IVTV_API_MUTE_VIDEO 0x000000d9 86 BLACKBIRD_END_NOW, /* stop immediately, no irq */
87#define IVTV_API_MUTE_AUDIO 0x000000da 87};
88#define IVTV_API_INITIALIZE_INPUT 0x000000cd 88#define BLACKBIRD_API_SET_AUDIO_ID 0x89
89#define IVTV_API_REFRESH_INPUT 0x000000d3 89#define BLACKBIRD_API_SET_VIDEO_ID 0x8B
90#define IVTV_API_ASSIGN_NUM_VSYNC_LINES 0x000000d6 90#define BLACKBIRD_API_SET_PCR_ID 0x8D
91#define IVTV_API_BEGIN_CAPTURE 0x00000081 91#define BLACKBIRD_API_SET_FRAMERATE 0x8F
92//#define IVTV_API_PAUSE_ENCODER 0x000000d2 92enum blackbird_framerate {
93//#define IVTV_API_EVENT_NOTIFICATION 0x000000d5 93 BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
94#define IVTV_API_END_CAPTURE 0x00000082 94 BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */
95};
96#define BLACKBIRD_API_SET_RESOLUTION 0x91
97#define BLACKBIRD_API_SET_VIDEO_BITRATE 0x95
98enum blackbird_video_bitrate_type {
99 BLACKBIRD_VIDEO_VBR,
100 BLACKBIRD_VIDEO_CBR
101};
102#define BLACKBIRD_PEAK_RATE_DIVISOR 400
103enum blackbird_mux_rate {
104 BLACKBIRD_MUX_RATE_DEFAULT,
105 /* dvd mux rate: multiply by 400 to get the actual rate */
106 BLACKBIRD_MUX_RATE_DVD = 25200
107};
108#define BLACKBIRD_API_SET_GOP_STRUCTURE 0x97
109#define BLACKBIRD_API_SET_ASPECT_RATIO 0x99
110enum blackbird_aspect_ratio {
111 BLACKBIRD_ASPECT_RATIO_FORBIDDEN,
112 BLACKBIRD_ASPECT_RATIO_1_1_SQUARE,
113 BLACKBIRD_ASPECT_RATIO_4_3,
114 BLACKBIRD_ASPECT_RATIO_16_9,
115 BLACKBIRD_ASPECT_RATIO_221_100,
116 BLACKBIRD_ASPECT_RATIO_RESERVED
117};
118#define BLACKBIRD_API_SET_DNR_MODE 0x9B
119enum blackbird_dnr_bits {
120 BLACKBIRD_DNR_BITS_MANUAL,
121 BLACKBIRD_DNR_BITS_AUTO_SPATIAL,
122 BLACKBIRD_DNR_BITS_AUTO_TEMPORAL,
123 BLACKBIRD_DNR_BITS_AUTO
124};
125enum blackbird_median_filter {
126 BLACKBIRD_MEDIAN_FILTER_DISABLED,
127 BLACKBIRD_MEDIAN_FILTER_HORIZONTAL,
128 BLACKBIRD_MEDIAN_FILTER_VERTICAL,
129 BLACKBIRD_MEDIAN_FILTER_HV,
130 BLACKBIRD_MEDIAN_FILTER_DIAGONAL
131};
132#define BLACKBIRD_API_SET_MANUAL_DNR 0x9D
133#define BLACKBIRD_API_SET_DNR_MEDIAN 0x9F
134#define BLACKBIRD_API_SET_SPATIAL_FILTER 0xA1
135enum blackbird_spatial_filter_luma {
136 BLACKBIRD_SPATIAL_FILTER_LUMA_DISABLED,
137 BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
138 BLACKBIRD_SPATIAL_FILTER_LUMA_1D_VERT,
139 BLACKBIRD_SPATIAL_FILTER_LUMA_2D_HV, /* separable, default */
140 BLACKBIRD_SPATIAL_FILTER_LUMA_2D_SYMM /* symmetric non-separable */
141};
142enum blackbird_spatial_filter_chroma {
143 BLACKBIRD_SPATIAL_FILTER_CHROMA_DISABLED,
144 BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ /* default */
145};
146#define BLACKBIRD_API_SET_3_2_PULLDOWN 0xB1
147enum blackbird_pulldown {
148 BLACKBIRD_3_2_PULLDOWN_DISABLED,
149 BLACKBIRD_3_2_PULLDOWN_ENABLED
150};
151#define BLACKBIRD_API_SET_VBI_LINE_NO 0xB7
152enum blackbird_vbi_line_bits {
153 BLACKBIRD_VBI_LINE_BITS_TOP_FIELD,
154 BLACKBIRD_VBI_LINE_BITS_BOT_FIELD = (1 << 31),
155 BLACKBIRD_VBI_LINE_BITS_ALL_LINES = 0xFFFFFFFF
156};
157enum blackbird_vbi_line {
158 BLACKBIRD_VBI_LINE_DISABLED,
159 BLACKBIRD_VBI_LINE_ENABLED
160};
161enum blackbird_vbi_slicing {
162 BLACKBIRD_VBI_SLICING_NONE,
163 BLACKBIRD_VBI_SLICING_CLOSED_CAPTION
164};
165#define BLACKBIRD_API_SET_STREAM_TYPE 0xB9
166enum blackbird_stream_type {
167 BLACKBIRD_STREAM_PROGRAM,
168 BLACKBIRD_STREAM_TRANSPORT,
169 BLACKBIRD_STREAM_MPEG1,
170 BLACKBIRD_STREAM_PES_AV,
171 BLACKBIRD_STREAM_UNKNOWN4,
172 BLACKBIRD_STREAM_PES_VIDEO,
173 BLACKBIRD_STREAM_UNKNOWN6,
174 BLACKBIRD_STREAM_PES_AUDIO,
175 BLACKBIRD_STREAM_UNKNOWN8,
176 BLACKBIRD_STREAM_UNKNOWN9, /* audio/pcm ? */
177 BLACKBIRD_STREAM_DVD,
178 BLACKBIRD_STREAM_VCD,
179 BLACKBIRD_STREAM_UNKNOWN12 /* svcd/xvcd ? */
180};
181#define BLACKBIRD_API_SET_OUTPUT_PORT 0xBB
182enum blackbird_stream_port {
183 BLACKBIRD_OUTPUT_PORT_MEMORY,
184 BLACKBIRD_OUTPUT_PORT_STREAMING,
185 BLACKBIRD_OUTPUT_PORT_SERIAL
186};
187#define BLACKBIRD_API_SET_AUDIO_PARAMS 0xBD
188enum blackbird_audio_bits_sample_rate {
189 BLACKBIRD_AUDIO_BITS_44100HZ,
190 BLACKBIRD_AUDIO_BITS_48000HZ,
191 BLACKBIRD_AUDIO_BITS_32000HZ,
192 BLACKBIRD_AUDIO_BITS_RESERVED_HZ,
193};
194enum blackbird_audio_bits_encoding {
195 BLACKBIRD_AUDIO_BITS_LAYER_1 = 0x1 << 2,
196 BLACKBIRD_AUDIO_BITS_LAYER_2 = 0x2 << 2,
197};
198enum blackbird_audio_bits_bitrate_layer_1 {
199 BLACKBIRD_AUDIO_BITS_LAYER_1_FREE_FORMAT,
200 BLACKBIRD_AUDIO_BITS_LAYER_1_32 = 0x01 << 4,
201 BLACKBIRD_AUDIO_BITS_LAYER_1_64 = 0x02 << 4,
202 BLACKBIRD_AUDIO_BITS_LAYER_1_96 = 0x03 << 4,
203 BLACKBIRD_AUDIO_BITS_LAYER_1_128 = 0x04 << 4,
204 BLACKBIRD_AUDIO_BITS_LAYER_1_160 = 0x05 << 4,
205 BLACKBIRD_AUDIO_BITS_LAYER_1_192 = 0x06 << 4,
206 BLACKBIRD_AUDIO_BITS_LAYER_1_224 = 0x07 << 4,
207 BLACKBIRD_AUDIO_BITS_LAYER_1_256 = 0x08 << 4,
208 BLACKBIRD_AUDIO_BITS_LAYER_1_288 = 0x09 << 4,
209 BLACKBIRD_AUDIO_BITS_LAYER_1_320 = 0x0A << 4,
210 BLACKBIRD_AUDIO_BITS_LAYER_1_352 = 0x0B << 4,
211 BLACKBIRD_AUDIO_BITS_LAYER_1_384 = 0x0C << 4,
212 BLACKBIRD_AUDIO_BITS_LAYER_1_416 = 0x0D << 4,
213 BLACKBIRD_AUDIO_BITS_LAYER_1_448 = 0x0E << 4,
214};
215enum blackbird_audio_bits_bitrate_layer_2 {
216 BLACKBIRD_AUDIO_BITS_LAYER_2_FREE_FORMAT,
217 BLACKBIRD_AUDIO_BITS_LAYER_2_32 = 0x01 << 4,
218 BLACKBIRD_AUDIO_BITS_LAYER_2_48 = 0x02 << 4,
219 BLACKBIRD_AUDIO_BITS_LAYER_2_56 = 0x03 << 4,
220 BLACKBIRD_AUDIO_BITS_LAYER_2_64 = 0x04 << 4,
221 BLACKBIRD_AUDIO_BITS_LAYER_2_80 = 0x05 << 4,
222 BLACKBIRD_AUDIO_BITS_LAYER_2_96 = 0x06 << 4,
223 BLACKBIRD_AUDIO_BITS_LAYER_2_112 = 0x07 << 4,
224 BLACKBIRD_AUDIO_BITS_LAYER_2_128 = 0x08 << 4,
225 BLACKBIRD_AUDIO_BITS_LAYER_2_160 = 0x09 << 4,
226 BLACKBIRD_AUDIO_BITS_LAYER_2_192 = 0x0A << 4,
227 BLACKBIRD_AUDIO_BITS_LAYER_2_224 = 0x0B << 4,
228 BLACKBIRD_AUDIO_BITS_LAYER_2_256 = 0x0C << 4,
229 BLACKBIRD_AUDIO_BITS_LAYER_2_320 = 0x0D << 4,
230 BLACKBIRD_AUDIO_BITS_LAYER_2_384 = 0x0E << 4,
231};
232enum blackbird_audio_bits_mode {
233 BLACKBIRD_AUDIO_BITS_STEREO,
234 BLACKBIRD_AUDIO_BITS_JOINT_STEREO = 0x1 << 8,
235 BLACKBIRD_AUDIO_BITS_DUAL = 0x2 << 8,
236 BLACKBIRD_AUDIO_BITS_MONO = 0x3 << 8,
237};
238enum blackbird_audio_bits_mode_extension {
239 BLACKBIRD_AUDIO_BITS_BOUND_4,
240 BLACKBIRD_AUDIO_BITS_BOUND_8 = 0x1 << 10,
241 BLACKBIRD_AUDIO_BITS_BOUND_12 = 0x2 << 10,
242 BLACKBIRD_AUDIO_BITS_BOUND_16 = 0x3 << 10,
243};
244enum blackbird_audio_bits_emphasis {
245 BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE,
246 BLACKBIRD_AUDIO_BITS_EMPHASIS_50_15 = 0x1 << 12,
247 BLACKBIRD_AUDIO_BITS_EMPHASIS_RESERVED = 0x2 << 12,
248 BLACKBIRD_AUDIO_BITS_EMPHASIS_CCITT_J17 = 0x3 << 12,
249};
250enum blackbird_audio_bits_crc {
251 BLACKBIRD_AUDIO_BITS_CRC_OFF,
252 BLACKBIRD_AUDIO_BITS_CRC_ON = 0x1 << 14,
253};
254enum blackbird_audio_bits_copyright {
255 BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF,
256 BLACKBIRD_AUDIO_BITS_COPYRIGHT_ON = 0x1 << 15,
257};
258enum blackbird_audio_bits_original {
259 BLACKBIRD_AUDIO_BITS_COPY,
260 BLACKBIRD_AUDIO_BITS_ORIGINAL = 0x1 << 16,
261};
262#define BLACKBIRD_API_HALT 0xC3
263#define BLACKBIRD_API_GET_VERSION 0xC4
264#define BLACKBIRD_API_SET_GOP_CLOSURE 0xC5
265enum blackbird_gop_closure {
266 BLACKBIRD_GOP_CLOSURE_OFF,
267 BLACKBIRD_GOP_CLOSURE_ON,
268};
269#define BLACKBIRD_API_DATA_XFER_STATUS 0xC6
270enum blackbird_data_xfer_status {
271 BLACKBIRD_MORE_BUFFERS_FOLLOW,
272 BLACKBIRD_LAST_BUFFER,
273};
274#define BLACKBIRD_API_PROGRAM_INDEX_INFO 0xC7
275enum blackbird_picture_mask {
276 BLACKBIRD_PICTURE_MASK_NONE,
277 BLACKBIRD_PICTURE_MASK_I_FRAMES,
278 BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
279 BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
280};
281#define BLACKBIRD_API_SET_VBI_PARAMS 0xC8
282enum blackbird_vbi_mode_bits {
283 BLACKBIRD_VBI_BITS_SLICED,
284 BLACKBIRD_VBI_BITS_RAW,
285};
286enum blackbird_vbi_insertion_bits {
287 BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
288 BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
289 BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
290 BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
291 BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
292};
293#define BLACKBIRD_API_SET_DMA_BLOCK_SIZE 0xC9
294enum blackbird_dma_unit {
295 BLACKBIRD_DMA_BYTES,
296 BLACKBIRD_DMA_FRAMES,
297};
298#define BLACKBIRD_API_DMA_TRANSFER_INFO 0xCA
299#define BLACKBIRD_API_DMA_TRANSFER_STAT 0xCB
300enum blackbird_dma_transfer_status_bits {
301 BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
302 BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
303 BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
304};
305#define BLACKBIRD_API_SET_DMA2HOST_ADDR 0xCC
306#define BLACKBIRD_API_INIT_VIDEO_INPUT 0xCD
307#define BLACKBIRD_API_SET_FRAMESKIP 0xD0
308#define BLACKBIRD_API_PAUSE 0xD2
309enum blackbird_pause {
310 BLACKBIRD_PAUSE_ENCODING,
311 BLACKBIRD_RESUME_ENCODING,
312};
313#define BLACKBIRD_API_REFRESH_INPUT 0xD3
314#define BLACKBIRD_API_SET_COPYRIGHT 0xD4
315enum blackbird_copyright {
316 BLACKBIRD_COPYRIGHT_OFF,
317 BLACKBIRD_COPYRIGHT_ON,
318};
319#define BLACKBIRD_API_SET_NOTIFICATION 0xD5
320enum blackbird_notification_type {
321 BLACKBIRD_NOTIFICATION_REFRESH,
322};
323enum blackbird_notification_status {
324 BLACKBIRD_NOTIFICATION_OFF,
325 BLACKBIRD_NOTIFICATION_ON,
326};
327enum blackbird_notification_mailbox {
328 BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
329};
330#define BLACKBIRD_API_SET_CAPTURE_LINES 0xD6
331enum blackbird_field1_lines {
332 BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
333 BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
334 BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
335};
336enum blackbird_field2_lines {
337 BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
338 BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
339 BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
340};
341#define BLACKBIRD_API_SET_CUSTOM_DATA 0xD7
342enum blackbird_custom_data_type {
343 BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
344 BLACKBIRD_CUSTOM_PRIVATE_PACKET,
345};
346#define BLACKBIRD_API_MUTE_VIDEO 0xD9
347enum blackbird_mute {
348 BLACKBIRD_UNMUTE,
349 BLACKBIRD_MUTE,
350};
351enum blackbird_mute_video_mask {
352 BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
353 BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
354 BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
355};
356enum blackbird_mute_video_shift {
357 BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
358 BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
359 BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
360};
361#define BLACKBIRD_API_MUTE_AUDIO 0xDA
95 362
96/* Registers */ 363/* Registers */
97#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/) 364#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
@@ -405,68 +672,100 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
405 return 0; 672 return 0;
406} 673}
407 674
675/**
676 Settings used by the windows tv app for PVR2000:
677=================================================================================================================
678Profile | Codec | Resolution | CBR/VBR | Video Qlty | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
679-----------------------------------------------------------------------------------------------------------------
680MPEG-1 | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 2000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
681MPEG-2 | MPEG2 | 720x576PAL | VBR | 600 :Good | 4000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
682VCD | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 1150 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
683DVD | MPEG2 | 720x576PAL | VBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
684DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
685=================================================================================================================
686*DB: "DirectBurn"
687*/
408static void blackbird_codec_settings(struct cx8802_dev *dev) 688static void blackbird_codec_settings(struct cx8802_dev *dev)
409{ 689{
410 int bitrate_mode = 1; 690 int bitrate_mode = 1;
411 int bitrate = 7500000; 691 int bitrate = 7500000;
412 int bitrate_peak = 7500000; 692 int bitrate_peak = 7500000;
693#if 1
694 bitrate_mode = BLACKBIRD_VIDEO_CBR;
695 bitrate = 4000*1024;
696 bitrate_peak = 4000*1024;
697#endif
413 698
414 /* assign stream type */ 699 /* assign stream type */
415 blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 0); /* program stream */ 700 blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_PROGRAM);
416 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 2); /* MPEG1 stream */ 701 /* blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_TRANSPORT); */
417 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 3); /* PES A/V */
418 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 10); /* DVD stream */
419 702
420 /* assign output port */ 703 /* assign output port */
421 blackbird_api_cmd(dev, IVTV_API_ASSIGN_OUTPUT_PORT, 1, 0, 1); /* 1 = Host */ 704 blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
422 705
423 /* assign framerate */ 706 /* assign framerate */
424 blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0); 707 blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
425 708
426 /* assign frame size */ 709 /* assign frame size */
427 blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, 710 blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0,
428 dev->height, dev->width); 711 dev->height, dev->width);
429 712
430 /* assign aspect ratio */ 713 /* assign aspect ratio */
431 blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2); 714 blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, BLACKBIRD_ASPECT_RATIO_4_3);
432 715
433 /* assign bitrates */ 716 /* assign bitrates */
434 blackbird_api_cmd(dev, IVTV_API_ASSIGN_BITRATES, 5, 0, 717 blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 5, 0,
435 bitrate_mode, /* mode */ 718 bitrate_mode, /* mode */
436 bitrate, /* bps */ 719 bitrate, /* bps */
437 bitrate_peak / 400, /* peak/400 */ 720 bitrate_peak / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */
438 0, 0x70); /* encoding buffer, ckennedy */ 721 BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */
439 722
440 /* assign gop properties */ 723 /* assign gop properties */
441 blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 15, 3); 724 blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, 15, 3);
442 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 2, 1); 725
443 726 /* assign 3 2 pulldown */
444 /* assign 3 2 pulldown */ 727 blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, BLACKBIRD_3_2_PULLDOWN_DISABLED);
445 blackbird_api_cmd(dev, IVTV_API_ASSIGN_3_2_PULLDOWN, 1, 0, 0); 728
446 729 /* assign audio properties */
447 /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ 730 /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
448 blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4)); 731 /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4));
732 blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4)); */
733 blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0,
734 BLACKBIRD_AUDIO_BITS_44100HZ |
735 BLACKBIRD_AUDIO_BITS_LAYER_2 |
736 BLACKBIRD_AUDIO_BITS_LAYER_2_224 |
737 BLACKBIRD_AUDIO_BITS_STEREO |
738 /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */
739 BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE |
740 BLACKBIRD_AUDIO_BITS_CRC_OFF |
741 BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF |
742 BLACKBIRD_AUDIO_BITS_COPY
743 );
449 744
450 /* assign gop closure */ 745 /* assign gop closure */
451 blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_CLOSURE, 1, 0, 0); 746 blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, BLACKBIRD_GOP_CLOSURE_OFF);
452 747
453 /* assign audio properties */
454 blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4));
455 748
456 /* assign dnr filter mode */ 749 /* assign dnr filter mode */
457 blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_MODE, 2, 0, 0, 0); 750 blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0,
751 BLACKBIRD_DNR_BITS_MANUAL,
752 BLACKBIRD_MEDIAN_FILTER_DISABLED
753 );
458 754
459 /* assign dnr filter props*/ 755 /* assign dnr filter props*/
460 blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_PROPS, 2, 0, 0, 0); 756 blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, 0, 0);
461 757
462 /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */ 758 /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */
463 blackbird_api_cmd(dev, IVTV_API_ASSIGN_CORING_LEVELS, 4, 0, 0, 255, 0, 255); 759 blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255);
464 760
465 /* assign spatial filter type: luma_t: 1 = horiz_only, chroma_t: 1 = horiz_only */ 761 /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */
466 blackbird_api_cmd(dev, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, 2, 0, 1, 1); 762 blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0,
763 BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
764 BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ
765 );
467 766
468 /* assign frame drop rate */ 767 /* assign frame drop rate */
469 blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); 768 /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */
470} 769}
471 770
472static int blackbird_initialize_codec(struct cx8802_dev *dev) 771static int blackbird_initialize_codec(struct cx8802_dev *dev)
@@ -476,7 +775,7 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
476 int retval; 775 int retval;
477 776
478 dprintk(1,"Initialize codec\n"); 777 dprintk(1,"Initialize codec\n");
479 retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */ 778 retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
480 if (retval < 0) { 779 if (retval < 0) {
481 /* ping was not successful, reset and upload firmware */ 780 /* ping was not successful, reset and upload firmware */
482 cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ 781 cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
@@ -491,13 +790,13 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
491 if (dev->mailbox < 0) 790 if (dev->mailbox < 0)
492 return -1; 791 return -1;
493 792
494 retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */ 793 retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
495 if (retval < 0) { 794 if (retval < 0) {
496 dprintk(0, "ERROR: Firmware ping failed!\n"); 795 dprintk(0, "ERROR: Firmware ping failed!\n");
497 return -1; 796 return -1;
498 } 797 }
499 798
500 retval = blackbird_api_cmd(dev, IVTV_API_ENC_GETVER, 0, 1, &version); 799 retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version);
501 if (retval < 0) { 800 if (retval < 0) {
502 dprintk(0, "ERROR: Firmware get encoder version failed!\n"); 801 dprintk(0, "ERROR: Firmware get encoder version failed!\n");
503 return -1; 802 return -1;
@@ -517,25 +816,36 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
517 blackbird_codec_settings(dev); 816 blackbird_codec_settings(dev);
518 msleep(1); 817 msleep(1);
519 818
520 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); 819 /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef);
521 blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); 820 blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0);
522 //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); 821 blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */
523 blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 822 blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0,
823 BLACKBIRD_FIELD1_SAA7115,
824 BLACKBIRD_FIELD1_SAA7115
825 );
826
827 /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */
828 blackbird_api_cmd(dev, BLACKBIRD_API_SET_CUSTOM_DATA, 12, 0,
829 BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
830 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
524 831
525 blackbird_api_cmd(dev, IVTV_API_INITIALIZE_INPUT, 0, 0); /* initialize the video input */ 832 blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); /* initialize the video input */
526 833
527 msleep(1); 834 msleep(1);
528 835
529 blackbird_api_cmd(dev, IVTV_API_MUTE_VIDEO, 1, 0, 0); 836 blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
530 msleep(1); 837 msleep(1);
531 blackbird_api_cmd(dev, IVTV_API_MUTE_AUDIO, 1, 0, 0); 838 blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
532 msleep(1); 839 msleep(1);
533 840
534 blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); /* start capturing to the host interface */ 841 /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); // start capturing to the host interface */
535 //blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0); /* start capturing to the host interface */ 842 blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0,
536 msleep(1); 843 BLACKBIRD_MPEG_CAPTURE,
844 BLACKBIRD_RAW_BITS_NONE
845 ); /* start capturing to the host interface */
846 msleep(10);
537 847
538 blackbird_api_cmd(dev, IVTV_API_REFRESH_INPUT, 0,0); 848 blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0);
539 return 0; 849 return 0;
540} 850}
541 851
@@ -709,7 +1019,12 @@ static int mpeg_release(struct inode *inode, struct file *file)
709{ 1019{
710 struct cx8802_fh *fh = file->private_data; 1020 struct cx8802_fh *fh = file->private_data;
711 1021
712 blackbird_api_cmd(fh->dev, IVTV_API_END_CAPTURE, 3, 0, 1, 0, 0x13); 1022 /* blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
1023 blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0,
1024 BLACKBIRD_END_NOW,
1025 BLACKBIRD_MPEG_CAPTURE,
1026 BLACKBIRD_RAW_BITS_NONE
1027 );
713 1028
714 /* stop mpeg capture */ 1029 /* stop mpeg capture */
715 if (fh->mpegq.streaming) 1030 if (fh->mpegq.streaming)
@@ -908,4 +1223,5 @@ module_exit(blackbird_fini);
908 * Local variables: 1223 * Local variables:
909 * c-basic-offset: 8 1224 * c-basic-offset: 8
910 * End: 1225 * End:
1226 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
911 */ 1227 */
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 367624822d..b3fb04356b 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $ 2 * $Id: cx88-cards.c,v 1.76 2005/06/08 01:28:09 mchehab Exp $
3 * 3 *
4 * device driver for Conexant 2388x based TV cards 4 * device driver for Conexant 2388x based TV cards
5 * card-specific stuff. 5 * card-specific stuff.
@@ -35,6 +35,9 @@ struct cx88_board cx88_boards[] = {
35 [CX88_BOARD_UNKNOWN] = { 35 [CX88_BOARD_UNKNOWN] = {
36 .name = "UNKNOWN/GENERIC", 36 .name = "UNKNOWN/GENERIC",
37 .tuner_type = UNSET, 37 .tuner_type = UNSET,
38 .radio_type = UNSET,
39 .tuner_addr = ADDR_UNSET,
40 .radio_addr = ADDR_UNSET,
38 .input = {{ 41 .input = {{
39 .type = CX88_VMUX_COMPOSITE1, 42 .type = CX88_VMUX_COMPOSITE1,
40 .vmux = 0, 43 .vmux = 0,
@@ -52,6 +55,9 @@ struct cx88_board cx88_boards[] = {
52 [CX88_BOARD_HAUPPAUGE] = { 55 [CX88_BOARD_HAUPPAUGE] = {
53 .name = "Hauppauge WinTV 34xxx models", 56 .name = "Hauppauge WinTV 34xxx models",
54 .tuner_type = UNSET, 57 .tuner_type = UNSET,
58 .radio_type = UNSET,
59 .tuner_addr = ADDR_UNSET,
60 .radio_addr = ADDR_UNSET,
55 .tda9887_conf = TDA9887_PRESENT, 61 .tda9887_conf = TDA9887_PRESENT,
56 .input = {{ 62 .input = {{
57 .type = CX88_VMUX_TELEVISION, 63 .type = CX88_VMUX_TELEVISION,
@@ -78,6 +84,9 @@ struct cx88_board cx88_boards[] = {
78 [CX88_BOARD_GDI] = { 84 [CX88_BOARD_GDI] = {
79 .name = "GDI Black Gold", 85 .name = "GDI Black Gold",
80 .tuner_type = UNSET, 86 .tuner_type = UNSET,
87 .radio_type = UNSET,
88 .tuner_addr = ADDR_UNSET,
89 .radio_addr = ADDR_UNSET,
81 .input = {{ 90 .input = {{
82 .type = CX88_VMUX_TELEVISION, 91 .type = CX88_VMUX_TELEVISION,
83 .vmux = 0, 92 .vmux = 0,
@@ -85,7 +94,10 @@ struct cx88_board cx88_boards[] = {
85 }, 94 },
86 [CX88_BOARD_PIXELVIEW] = { 95 [CX88_BOARD_PIXELVIEW] = {
87 .name = "PixelView", 96 .name = "PixelView",
88 .tuner_type = 5, 97 .tuner_type = TUNER_PHILIPS_PAL,
98 .radio_type = UNSET,
99 .tuner_addr = ADDR_UNSET,
100 .radio_addr = ADDR_UNSET,
89 .input = {{ 101 .input = {{
90 .type = CX88_VMUX_TELEVISION, 102 .type = CX88_VMUX_TELEVISION,
91 .vmux = 0, 103 .vmux = 0,
@@ -104,7 +116,10 @@ struct cx88_board cx88_boards[] = {
104 }, 116 },
105 [CX88_BOARD_ATI_WONDER_PRO] = { 117 [CX88_BOARD_ATI_WONDER_PRO] = {
106 .name = "ATI TV Wonder Pro", 118 .name = "ATI TV Wonder Pro",
107 .tuner_type = 44, 119 .tuner_type = TUNER_PHILIPS_4IN1,
120 .radio_type = UNSET,
121 .tuner_addr = ADDR_UNSET,
122 .radio_addr = ADDR_UNSET,
108 .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER, 123 .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER,
109 .input = {{ 124 .input = {{
110 .type = CX88_VMUX_TELEVISION, 125 .type = CX88_VMUX_TELEVISION,
@@ -122,7 +137,10 @@ struct cx88_board cx88_boards[] = {
122 }, 137 },
123 [CX88_BOARD_WINFAST2000XP_EXPERT] = { 138 [CX88_BOARD_WINFAST2000XP_EXPERT] = {
124 .name = "Leadtek Winfast 2000XP Expert", 139 .name = "Leadtek Winfast 2000XP Expert",
125 .tuner_type = 44, 140 .tuner_type = TUNER_PHILIPS_4IN1,
141 .radio_type = UNSET,
142 .tuner_addr = ADDR_UNSET,
143 .radio_addr = ADDR_UNSET,
126 .tda9887_conf = TDA9887_PRESENT, 144 .tda9887_conf = TDA9887_PRESENT,
127 .input = {{ 145 .input = {{
128 .type = CX88_VMUX_TELEVISION, 146 .type = CX88_VMUX_TELEVISION,
@@ -156,7 +174,10 @@ struct cx88_board cx88_boards[] = {
156 }, 174 },
157 [CX88_BOARD_AVERTV_303] = { 175 [CX88_BOARD_AVERTV_303] = {
158 .name = "AverTV Studio 303 (M126)", 176 .name = "AverTV Studio 303 (M126)",
159 .tuner_type = 38, 177 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
178 .radio_type = UNSET,
179 .tuner_addr = ADDR_UNSET,
180 .radio_addr = ADDR_UNSET,
160 .tda9887_conf = TDA9887_PRESENT, 181 .tda9887_conf = TDA9887_PRESENT,
161 .input = {{ 182 .input = {{
162 .type = CX88_VMUX_TELEVISION, 183 .type = CX88_VMUX_TELEVISION,
@@ -179,7 +200,10 @@ struct cx88_board cx88_boards[] = {
179 // added gpio values thanks to Michal 200 // added gpio values thanks to Michal
180 // values for PAL from DScaler 201 // values for PAL from DScaler
181 .name = "MSI TV-@nywhere Master", 202 .name = "MSI TV-@nywhere Master",
182 .tuner_type = 33, 203 .tuner_type = TUNER_MT2032,
204 .radio_type = UNSET,
205 .tuner_addr = ADDR_UNSET,
206 .radio_addr = ADDR_UNSET,
183 .tda9887_conf = TDA9887_PRESENT, 207 .tda9887_conf = TDA9887_PRESENT,
184 .input = {{ 208 .input = {{
185 .type = CX88_VMUX_TELEVISION, 209 .type = CX88_VMUX_TELEVISION,
@@ -206,7 +230,10 @@ struct cx88_board cx88_boards[] = {
206 }, 230 },
207 [CX88_BOARD_WINFAST_DV2000] = { 231 [CX88_BOARD_WINFAST_DV2000] = {
208 .name = "Leadtek Winfast DV2000", 232 .name = "Leadtek Winfast DV2000",
209 .tuner_type = 38, 233 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
234 .radio_type = UNSET,
235 .tuner_addr = ADDR_UNSET,
236 .radio_addr = ADDR_UNSET,
210 .tda9887_conf = TDA9887_PRESENT, 237 .tda9887_conf = TDA9887_PRESENT,
211 .input = {{ 238 .input = {{
212 .type = CX88_VMUX_TELEVISION, 239 .type = CX88_VMUX_TELEVISION,
@@ -239,34 +266,40 @@ struct cx88_board cx88_boards[] = {
239 .gpio3 = 0x02000000, 266 .gpio3 = 0x02000000,
240 }, 267 },
241 }, 268 },
242 [CX88_BOARD_LEADTEK_PVR2000] = { 269 [CX88_BOARD_LEADTEK_PVR2000] = {
243 // gpio values for PAL version from regspy by DScaler 270 // gpio values for PAL version from regspy by DScaler
244 .name = "Leadtek PVR 2000", 271 .name = "Leadtek PVR 2000",
245 .tuner_type = 38, 272 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
273 .radio_type = UNSET,
274 .tuner_addr = ADDR_UNSET,
275 .radio_addr = ADDR_UNSET,
246 .tda9887_conf = TDA9887_PRESENT, 276 .tda9887_conf = TDA9887_PRESENT,
247 .input = {{ 277 .input = {{
248 .type = CX88_VMUX_TELEVISION, 278 .type = CX88_VMUX_TELEVISION,
249 .vmux = 0, 279 .vmux = 0,
250 .gpio0 = 0x0000bde6, 280 .gpio0 = 0x0000bde2,
251 },{ 281 },{
252 .type = CX88_VMUX_COMPOSITE1, 282 .type = CX88_VMUX_COMPOSITE1,
253 .vmux = 1, 283 .vmux = 1,
254 .gpio0 = 0x0000bde6, 284 .gpio0 = 0x0000bde6,
255 },{ 285 },{
256 .type = CX88_VMUX_SVIDEO, 286 .type = CX88_VMUX_SVIDEO,
257 .vmux = 2, 287 .vmux = 2,
258 .gpio0 = 0x0000bde6, 288 .gpio0 = 0x0000bde6,
259 }}, 289 }},
260 .radio = { 290 .radio = {
261 .type = CX88_RADIO, 291 .type = CX88_RADIO,
262 .gpio0 = 0x0000bd62, 292 .gpio0 = 0x0000bd62,
263 }, 293 },
264 .blackbird = 1, 294 .blackbird = 1,
265 }, 295 },
266 [CX88_BOARD_IODATA_GVVCP3PCI] = { 296 [CX88_BOARD_IODATA_GVVCP3PCI] = {
267 .name = "IODATA GV-VCP3/PCI", 297 .name = "IODATA GV-VCP3/PCI",
268 .tuner_type = TUNER_ABSENT, 298 .tuner_type = TUNER_ABSENT,
269 .input = {{ 299 .radio_type = UNSET,
300 .tuner_addr = ADDR_UNSET,
301 .radio_addr = ADDR_UNSET,
302 .input = {{
270 .type = CX88_VMUX_COMPOSITE1, 303 .type = CX88_VMUX_COMPOSITE1,
271 .vmux = 0, 304 .vmux = 0,
272 },{ 305 },{
@@ -279,7 +312,10 @@ struct cx88_board cx88_boards[] = {
279 }, 312 },
280 [CX88_BOARD_PROLINK_PLAYTVPVR] = { 313 [CX88_BOARD_PROLINK_PLAYTVPVR] = {
281 .name = "Prolink PlayTV PVR", 314 .name = "Prolink PlayTV PVR",
282 .tuner_type = 43, 315 .tuner_type = TUNER_PHILIPS_FM1236_MK3,
316 .radio_type = UNSET,
317 .tuner_addr = ADDR_UNSET,
318 .radio_addr = ADDR_UNSET,
283 .tda9887_conf = TDA9887_PRESENT, 319 .tda9887_conf = TDA9887_PRESENT,
284 .input = {{ 320 .input = {{
285 .type = CX88_VMUX_TELEVISION, 321 .type = CX88_VMUX_TELEVISION,
@@ -301,8 +337,11 @@ struct cx88_board cx88_boards[] = {
301 }, 337 },
302 [CX88_BOARD_ASUS_PVR_416] = { 338 [CX88_BOARD_ASUS_PVR_416] = {
303 .name = "ASUS PVR-416", 339 .name = "ASUS PVR-416",
304 .tuner_type = 43, 340 .tuner_type = TUNER_PHILIPS_FM1236_MK3,
305 .tda9887_conf = TDA9887_PRESENT, 341 .radio_type = UNSET,
342 .tuner_addr = ADDR_UNSET,
343 .radio_addr = ADDR_UNSET,
344 .tda9887_conf = TDA9887_PRESENT,
306 .input = {{ 345 .input = {{
307 .type = CX88_VMUX_TELEVISION, 346 .type = CX88_VMUX_TELEVISION,
308 .vmux = 0, 347 .vmux = 0,
@@ -320,7 +359,10 @@ struct cx88_board cx88_boards[] = {
320 }, 359 },
321 [CX88_BOARD_MSI_TVANYWHERE] = { 360 [CX88_BOARD_MSI_TVANYWHERE] = {
322 .name = "MSI TV-@nywhere", 361 .name = "MSI TV-@nywhere",
323 .tuner_type = 33, 362 .tuner_type = TUNER_MT2032,
363 .radio_type = UNSET,
364 .tuner_addr = ADDR_UNSET,
365 .radio_addr = ADDR_UNSET,
324 .tda9887_conf = TDA9887_PRESENT, 366 .tda9887_conf = TDA9887_PRESENT,
325 .input = {{ 367 .input = {{
326 .type = CX88_VMUX_TELEVISION, 368 .type = CX88_VMUX_TELEVISION,
@@ -342,6 +384,9 @@ struct cx88_board cx88_boards[] = {
342 [CX88_BOARD_KWORLD_DVB_T] = { 384 [CX88_BOARD_KWORLD_DVB_T] = {
343 .name = "KWorld/VStream XPert DVB-T", 385 .name = "KWorld/VStream XPert DVB-T",
344 .tuner_type = TUNER_ABSENT, 386 .tuner_type = TUNER_ABSENT,
387 .radio_type = UNSET,
388 .tuner_addr = ADDR_UNSET,
389 .radio_addr = ADDR_UNSET,
345 .input = {{ 390 .input = {{
346 .type = CX88_VMUX_COMPOSITE1, 391 .type = CX88_VMUX_COMPOSITE1,
347 .vmux = 1, 392 .vmux = 1,
@@ -358,6 +403,9 @@ struct cx88_board cx88_boards[] = {
358 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { 403 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
359 .name = "DVICO FusionHDTV DVB-T1", 404 .name = "DVICO FusionHDTV DVB-T1",
360 .tuner_type = TUNER_ABSENT, /* No analog tuner */ 405 .tuner_type = TUNER_ABSENT, /* No analog tuner */
406 .radio_type = UNSET,
407 .tuner_addr = ADDR_UNSET,
408 .radio_addr = ADDR_UNSET,
361 .input = {{ 409 .input = {{
362 .type = CX88_VMUX_COMPOSITE1, 410 .type = CX88_VMUX_COMPOSITE1,
363 .vmux = 1, 411 .vmux = 1,
@@ -371,7 +419,10 @@ struct cx88_board cx88_boards[] = {
371 }, 419 },
372 [CX88_BOARD_KWORLD_LTV883] = { 420 [CX88_BOARD_KWORLD_LTV883] = {
373 .name = "KWorld LTV883RF", 421 .name = "KWorld LTV883RF",
374 .tuner_type = 48, 422 .tuner_type = TUNER_TNF_8831BGFF,
423 .radio_type = UNSET,
424 .tuner_addr = ADDR_UNSET,
425 .radio_addr = ADDR_UNSET,
375 .input = {{ 426 .input = {{
376 .type = CX88_VMUX_TELEVISION, 427 .type = CX88_VMUX_TELEVISION,
377 .vmux = 0, 428 .vmux = 0,
@@ -397,6 +448,9 @@ struct cx88_board cx88_boards[] = {
397 [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = { 448 [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = {
398 .name = "DViCO - FusionHDTV 3 Gold", 449 .name = "DViCO - FusionHDTV 3 Gold",
399 .tuner_type = TUNER_MICROTUNE_4042FI5, 450 .tuner_type = TUNER_MICROTUNE_4042FI5,
451 .radio_type = UNSET,
452 .tuner_addr = ADDR_UNSET,
453 .radio_addr = ADDR_UNSET,
400 /* 454 /*
401 GPIO[0] resets DT3302 DTV receiver 455 GPIO[0] resets DT3302 DTV receiver
402 0 - reset asserted 456 0 - reset asserted
@@ -428,17 +482,14 @@ struct cx88_board cx88_boards[] = {
428 .vmux = 2, 482 .vmux = 2,
429 .gpio0 = 0x0f00, 483 .gpio0 = 0x0f00,
430 }}, 484 }},
431#if 0
432 .ts = {
433 .type = CX88_TS,
434 .gpio0 = 0x00000f01, /* Hooked to tuner reset bit */
435 }
436#endif
437 }, 485 },
438 [CX88_BOARD_HAUPPAUGE_DVB_T1] = { 486 [CX88_BOARD_HAUPPAUGE_DVB_T1] = {
439 .name = "Hauppauge Nova-T DVB-T", 487 .name = "Hauppauge Nova-T DVB-T",
440 .tuner_type = TUNER_ABSENT, 488 .tuner_type = TUNER_ABSENT,
441 .input = {{ 489 .radio_type = UNSET,
490 .tuner_addr = ADDR_UNSET,
491 .radio_addr = ADDR_UNSET,
492 .input = {{
442 .type = CX88_VMUX_DVB, 493 .type = CX88_VMUX_DVB,
443 .vmux = 0, 494 .vmux = 0,
444 }}, 495 }},
@@ -447,6 +498,9 @@ struct cx88_board cx88_boards[] = {
447 [CX88_BOARD_CONEXANT_DVB_T1] = { 498 [CX88_BOARD_CONEXANT_DVB_T1] = {
448 .name = "Conexant DVB-T reference design", 499 .name = "Conexant DVB-T reference design",
449 .tuner_type = TUNER_ABSENT, 500 .tuner_type = TUNER_ABSENT,
501 .radio_type = UNSET,
502 .tuner_addr = ADDR_UNSET,
503 .radio_addr = ADDR_UNSET,
450 .input = {{ 504 .input = {{
451 .type = CX88_VMUX_DVB, 505 .type = CX88_VMUX_DVB,
452 .vmux = 0, 506 .vmux = 0,
@@ -456,6 +510,9 @@ struct cx88_board cx88_boards[] = {
456 [CX88_BOARD_PROVIDEO_PV259] = { 510 [CX88_BOARD_PROVIDEO_PV259] = {
457 .name = "Provideo PV259", 511 .name = "Provideo PV259",
458 .tuner_type = TUNER_PHILIPS_FQ1216ME, 512 .tuner_type = TUNER_PHILIPS_FQ1216ME,
513 .radio_type = UNSET,
514 .tuner_addr = ADDR_UNSET,
515 .radio_addr = ADDR_UNSET,
459 .input = {{ 516 .input = {{
460 .type = CX88_VMUX_TELEVISION, 517 .type = CX88_VMUX_TELEVISION,
461 .vmux = 0, 518 .vmux = 0,
@@ -465,6 +522,9 @@ struct cx88_board cx88_boards[] = {
465 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = { 522 [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
466 .name = "DVICO FusionHDTV DVB-T Plus", 523 .name = "DVICO FusionHDTV DVB-T Plus",
467 .tuner_type = TUNER_ABSENT, /* No analog tuner */ 524 .tuner_type = TUNER_ABSENT, /* No analog tuner */
525 .radio_type = UNSET,
526 .tuner_addr = ADDR_UNSET,
527 .radio_addr = ADDR_UNSET,
468 .input = {{ 528 .input = {{
469 .type = CX88_VMUX_COMPOSITE1, 529 .type = CX88_VMUX_COMPOSITE1,
470 .vmux = 1, 530 .vmux = 1,
@@ -479,6 +539,9 @@ struct cx88_board cx88_boards[] = {
479 [CX88_BOARD_DNTV_LIVE_DVB_T] = { 539 [CX88_BOARD_DNTV_LIVE_DVB_T] = {
480 .name = "digitalnow DNTV Live! DVB-T", 540 .name = "digitalnow DNTV Live! DVB-T",
481 .tuner_type = TUNER_ABSENT, 541 .tuner_type = TUNER_ABSENT,
542 .radio_type = UNSET,
543 .tuner_addr = ADDR_UNSET,
544 .radio_addr = ADDR_UNSET,
482 .input = {{ 545 .input = {{
483 .type = CX88_VMUX_COMPOSITE1, 546 .type = CX88_VMUX_COMPOSITE1,
484 .vmux = 1, 547 .vmux = 1,
@@ -495,6 +558,9 @@ struct cx88_board cx88_boards[] = {
495 [CX88_BOARD_PCHDTV_HD3000] = { 558 [CX88_BOARD_PCHDTV_HD3000] = {
496 .name = "pcHDTV HD3000 HDTV", 559 .name = "pcHDTV HD3000 HDTV",
497 .tuner_type = TUNER_THOMSON_DTT7610, 560 .tuner_type = TUNER_THOMSON_DTT7610,
561 .radio_type = UNSET,
562 .tuner_addr = ADDR_UNSET,
563 .radio_addr = ADDR_UNSET,
498 .input = {{ 564 .input = {{
499 .type = CX88_VMUX_TELEVISION, 565 .type = CX88_VMUX_TELEVISION,
500 .vmux = 0, 566 .vmux = 0,
@@ -530,8 +596,11 @@ struct cx88_board cx88_boards[] = {
530 [CX88_BOARD_HAUPPAUGE_ROSLYN] = { 596 [CX88_BOARD_HAUPPAUGE_ROSLYN] = {
531 // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu> 597 // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
532 // GPIO values obtained from regspy, courtesy Sean Covel 598 // GPIO values obtained from regspy, courtesy Sean Covel
533 .name = "Hauppauge WinTV 28xxx (Roslyn) models", 599 .name = "Hauppauge WinTV 28xxx (Roslyn) models",
534 .tuner_type = UNSET, 600 .tuner_type = UNSET,
601 .radio_type = UNSET,
602 .tuner_addr = ADDR_UNSET,
603 .radio_addr = ADDR_UNSET,
535 .input = {{ 604 .input = {{
536 .type = CX88_VMUX_TELEVISION, 605 .type = CX88_VMUX_TELEVISION,
537 .vmux = 0, 606 .vmux = 0,
@@ -559,33 +628,37 @@ struct cx88_board cx88_boards[] = {
559 .blackbird = 1, 628 .blackbird = 1,
560 }, 629 },
561 [CX88_BOARD_DIGITALLOGIC_MEC] = { 630 [CX88_BOARD_DIGITALLOGIC_MEC] = {
562 /* params copied over from Leadtek PVR 2000 */
563 .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)", 631 .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
564 /* not sure yet about the tuner type */ 632 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
565 .tuner_type = 38, 633 .radio_type = UNSET,
634 .tuner_addr = ADDR_UNSET,
635 .radio_addr = ADDR_UNSET,
566 .tda9887_conf = TDA9887_PRESENT, 636 .tda9887_conf = TDA9887_PRESENT,
567 .input = {{ 637 .input = {{
568 .type = CX88_VMUX_TELEVISION, 638 .type = CX88_VMUX_TELEVISION,
569 .vmux = 0, 639 .vmux = 0,
570 .gpio0 = 0x0000bde6, 640 .gpio0 = 0x00009d80,
571 },{ 641 },{
572 .type = CX88_VMUX_COMPOSITE1, 642 .type = CX88_VMUX_COMPOSITE1,
573 .vmux = 1, 643 .vmux = 1,
574 .gpio0 = 0x0000bde6, 644 .gpio0 = 0x00009d76,
575 },{ 645 },{
576 .type = CX88_VMUX_SVIDEO, 646 .type = CX88_VMUX_SVIDEO,
577 .vmux = 2, 647 .vmux = 2,
578 .gpio0 = 0x0000bde6, 648 .gpio0 = 0x00009d76,
579 }}, 649 }},
580 .radio = { 650 .radio = {
581 .type = CX88_RADIO, 651 .type = CX88_RADIO,
582 .gpio0 = 0x0000bd62, 652 .gpio0 = 0x00009d00,
583 }, 653 },
584 .blackbird = 1, 654 .blackbird = 1,
585 }, 655 },
586 [CX88_BOARD_IODATA_GVBCTV7E] = { 656 [CX88_BOARD_IODATA_GVBCTV7E] = {
587 .name = "IODATA GV/BCTV7E", 657 .name = "IODATA GV/BCTV7E",
588 .tuner_type = TUNER_PHILIPS_FQ1286, 658 .tuner_type = TUNER_PHILIPS_FQ1286,
659 .radio_type = UNSET,
660 .tuner_addr = ADDR_UNSET,
661 .radio_addr = ADDR_UNSET,
589 .tda9887_conf = TDA9887_PRESENT, 662 .tda9887_conf = TDA9887_PRESENT,
590 .input = {{ 663 .input = {{
591 .type = CX88_VMUX_TELEVISION, 664 .type = CX88_VMUX_TELEVISION,
@@ -601,6 +674,56 @@ struct cx88_board cx88_boards[] = {
601 .gpio1 = 0x0000e07f, 674 .gpio1 = 0x0000e07f,
602 }} 675 }}
603 }, 676 },
677 [CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = {
678 .name = "PixelView PlayTV Ultra Pro (Stereo)",
679 /* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
680 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
681 .radio_type = TUNER_TEA5767,
682 .tuner_addr = 0xc2>>1,
683 .radio_addr = 0xc0>>1,
684 .input = {{
685 .type = CX88_VMUX_TELEVISION,
686 .vmux = 0,
687 .gpio0 = 0xbf61, /* internal decoder */
688 },{
689 .type = CX88_VMUX_COMPOSITE1,
690 .vmux = 1,
691 .gpio0 = 0xbf63,
692 },{
693 .type = CX88_VMUX_SVIDEO,
694 .vmux = 2,
695 .gpio0 = 0xbf63,
696 }},
697 .radio = {
698 .type = CX88_RADIO,
699 .gpio0 = 0xbf60,
700 },
701 },
702 [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
703 .name = "DViCO - FusionHDTV 3 Gold-T",
704 .tuner_type = TUNER_THOMSON_DTT7611,
705 .radio_type = UNSET,
706 .tuner_addr = ADDR_UNSET,
707 .radio_addr = ADDR_UNSET,
708 /* See DViCO FusionHDTV 3 Gold for GPIO documentation. */
709 .input = {{
710 .type = CX88_VMUX_TELEVISION,
711 .vmux = 0,
712 .gpio0 = 0x0f0d,
713 },{
714 .type = CX88_VMUX_CABLE,
715 .vmux = 0,
716 .gpio0 = 0x0f05,
717 },{
718 .type = CX88_VMUX_COMPOSITE1,
719 .vmux = 1,
720 .gpio0 = 0x0f00,
721 },{
722 .type = CX88_VMUX_SVIDEO,
723 .vmux = 2,
724 .gpio0 = 0x0f00,
725 }},
726 },
604}; 727};
605const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); 728const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
606 729
@@ -673,6 +796,10 @@ struct cx88_subid cx88_subids[] = {
673 .subdevice = 0xd810, 796 .subdevice = 0xd810,
674 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD, 797 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD,
675 },{ 798 },{
799 .subvendor = 0x18ac,
800 .subdevice = 0xd820,
801 .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T,
802 },{
676 .subvendor = 0x18AC, 803 .subvendor = 0x18AC,
677 .subdevice = 0xDB00, 804 .subdevice = 0xDB00,
678 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, 805 .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
@@ -935,4 +1062,5 @@ EXPORT_SYMBOL(cx88_card_setup);
935 * Local variables: 1062 * Local variables:
936 * c-basic-offset: 8 1063 * c-basic-offset: 8
937 * End: 1064 * End:
1065 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
938 */ 1066 */
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 1ff79b5a88..c046a23537 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $ 2 * $Id: cx88-core.c,v 1.28 2005/06/12 04:19:19 mchehab Exp $
3 * 3 *
4 * device driver for Conexant 2388x based TV cards 4 * device driver for Conexant 2388x based TV cards
5 * driver core 5 * driver core
@@ -51,12 +51,15 @@ module_param(latency,int,0444);
51MODULE_PARM_DESC(latency,"pci latency timer"); 51MODULE_PARM_DESC(latency,"pci latency timer");
52 52
53static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; 53static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
54static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
54static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; 55static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
55 56
56module_param_array(tuner, int, NULL, 0444); 57module_param_array(tuner, int, NULL, 0444);
58module_param_array(radio, int, NULL, 0444);
57module_param_array(card, int, NULL, 0444); 59module_param_array(card, int, NULL, 0444);
58 60
59MODULE_PARM_DESC(tuner,"tuner type"); 61MODULE_PARM_DESC(tuner,"tuner type");
62MODULE_PARM_DESC(radio,"radio tuner type");
60MODULE_PARM_DESC(card,"card type"); 63MODULE_PARM_DESC(card,"card type");
61 64
62static unsigned int nicam = 0; 65static unsigned int nicam = 0;
@@ -429,7 +432,7 @@ int cx88_sram_channel_setup(struct cx88_core *core,
429/* ------------------------------------------------------------------ */ 432/* ------------------------------------------------------------------ */
430/* debug helper code */ 433/* debug helper code */
431 434
432static int cx88_risc_decode(u32 risc) 435int cx88_risc_decode(u32 risc)
433{ 436{
434 static char *instr[16] = { 437 static char *instr[16] = {
435 [ RISC_SYNC >> 28 ] = "sync", 438 [ RISC_SYNC >> 28 ] = "sync",
@@ -736,6 +739,10 @@ static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
736{ 739{
737 static const unsigned int ntsc = 28636360; 740 static const unsigned int ntsc = 28636360;
738 static const unsigned int pal = 35468950; 741 static const unsigned int pal = 35468950;
742 static const unsigned int palm = 28604892;
743
744 if (norm->id & V4L2_STD_PAL_M)
745 return palm;
739 746
740 return (norm->id & V4L2_STD_625_50) ? pal : ntsc; 747 return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
741} 748}
@@ -749,6 +756,11 @@ static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
749 756
750static unsigned int inline norm_htotal(struct cx88_tvnorm *norm) 757static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
751{ 758{
759 /* Should always be Line Draw Time / (4*FSC) */
760
761 if (norm->id & V4L2_STD_PAL_M)
762 return 909;
763
752 return (norm->id & V4L2_STD_625_50) ? 1135 : 910; 764 return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
753} 765}
754 766
@@ -1164,8 +1176,20 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
1164 "insmod option" : "autodetected"); 1176 "insmod option" : "autodetected");
1165 1177
1166 core->tuner_type = tuner[core->nr]; 1178 core->tuner_type = tuner[core->nr];
1179 core->radio_type = radio[core->nr];
1167 if (UNSET == core->tuner_type) 1180 if (UNSET == core->tuner_type)
1168 core->tuner_type = cx88_boards[core->board].tuner_type; 1181 core->tuner_type = cx88_boards[core->board].tuner_type;
1182 if (UNSET == core->radio_type)
1183 core->radio_type = cx88_boards[core->board].radio_type;
1184 if (!core->tuner_addr)
1185 core->tuner_addr = cx88_boards[core->board].tuner_addr;
1186 if (!core->radio_addr)
1187 core->radio_addr = cx88_boards[core->board].radio_addr;
1188
1189 printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
1190 core->tuner_type, core->tuner_addr<<1,
1191 core->radio_type, core->radio_addr<<1);
1192
1169 core->tda9887_conf = cx88_boards[core->board].tda9887_conf; 1193 core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
1170 1194
1171 /* init hardware */ 1195 /* init hardware */
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 9d15d3d5a2..1a259c3966 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $ 2 * $Id: cx88-dvb.c,v 1.33 2005/06/12 04:19:19 mchehab Exp $
3 * 3 *
4 * device driver for Conexant 2388x based TV cards 4 * device driver for Conexant 2388x based TV cards
5 * MPEG Transport Stream (DVB) routines 5 * MPEG Transport Stream (DVB) routines
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 0725b1288f..e20adefcfc 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -1,5 +1,5 @@
1/* 1/*
2 $Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $ 2 $Id: cx88-i2c.c,v 1.23 2005/06/12 04:19:19 mchehab Exp $
3 3
4 cx88-i2c.c -- all the i2c code is here 4 cx88-i2c.c -- all the i2c code is here
5 5
@@ -91,6 +91,7 @@ static int cx8800_bit_getsda(void *data)
91 91
92static int attach_inform(struct i2c_client *client) 92static int attach_inform(struct i2c_client *client)
93{ 93{
94 struct tuner_addr tun_addr;
94 struct cx88_core *core = i2c_get_adapdata(client->adapter); 95 struct cx88_core *core = i2c_get_adapdata(client->adapter);
95 96
96 dprintk(1, "i2c attach [addr=0x%x,client=%s]\n", 97 dprintk(1, "i2c attach [addr=0x%x,client=%s]\n",
@@ -98,8 +99,19 @@ static int attach_inform(struct i2c_client *client)
98 if (!client->driver->command) 99 if (!client->driver->command)
99 return 0; 100 return 0;
100 101
101 if (core->tuner_type != UNSET) 102 if (core->radio_type != UNSET) {
102 client->driver->command(client, TUNER_SET_TYPE, &core->tuner_type); 103 tun_addr.v4l2_tuner = V4L2_TUNER_RADIO;
104 tun_addr.type = core->radio_type;
105 tun_addr.addr = core->radio_addr;
106 client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
107 }
108 if (core->tuner_type != UNSET) {
109 tun_addr.v4l2_tuner = V4L2_TUNER_ANALOG_TV;
110 tun_addr.type = core->tuner_type;
111 tun_addr.addr = core->tuner_addr;
112 client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
113 }
114
103 if (core->tda9887_conf) 115 if (core->tda9887_conf)
104 client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); 116 client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf);
105 return 0; 117 return 0;
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index af6ad8cdbd..dc0dcf249a 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $ 2 * $Id: cx88-input.c,v 1.11 2005/05/22 20:57:56 nsh Exp $
3 * 3 *
4 * Device driver for GPIO attached remote control interfaces 4 * Device driver for GPIO attached remote control interfaces
5 * on Conexant 2388x based TV/DVB cards. 5 * on Conexant 2388x based TV/DVB cards.
@@ -235,6 +235,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
235 /* detect & configure */ 235 /* detect & configure */
236 switch (core->board) { 236 switch (core->board) {
237 case CX88_BOARD_DNTV_LIVE_DVB_T: 237 case CX88_BOARD_DNTV_LIVE_DVB_T:
238 case CX88_BOARD_KWORLD_DVB_T:
238 ir_codes = ir_codes_dntv_live_dvb_t; 239 ir_codes = ir_codes_dntv_live_dvb_t;
239 ir->gpio_addr = MO_GP1_IO; 240 ir->gpio_addr = MO_GP1_IO;
240 ir->mask_keycode = 0x1f; 241 ir->mask_keycode = 0x1f;
@@ -261,7 +262,15 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
261 ir->mask_keydown = 0x02; 262 ir->mask_keydown = 0x02;
262 ir->polling = 5; // ms 263 ir->polling = 5; // ms
263 break; 264 break;
265 case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
266 ir_codes = ir_codes_pixelview;
267 ir->gpio_addr = MO_GP1_IO;
268 ir->mask_keycode = 0x1f;
269 ir->mask_keyup = 0x80;
270 ir->polling = 1; // ms
271 break;
264 } 272 }
273
265 if (NULL == ir_codes) { 274 if (NULL == ir_codes) {
266 kfree(ir); 275 kfree(ir);
267 return -ENODEV; 276 return -ENODEV;
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 07aae1899e..9ade2ae91e 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $ 2 * $Id: cx88-mpeg.c,v 1.26 2005/06/03 13:31:51 mchehab Exp $
3 * 3 *
4 * Support for the mpeg transport stream transfers 4 * Support for the mpeg transport stream transfers
5 * PCI function #2 of the cx2388x. 5 * PCI function #2 of the cx2388x.
@@ -55,7 +55,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
55{ 55{
56 struct cx88_core *core = dev->core; 56 struct cx88_core *core = dev->core;
57 57
58 dprintk(1, "cx8802_start_mpegport_dma %d\n", buf->vb.width); 58 dprintk(0, "cx8802_start_dma %d\n", buf->vb.width);
59 59
60 /* setup fifo + format */ 60 /* setup fifo + format */
61 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 61 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
@@ -100,18 +100,21 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
100 q->count = 1; 100 q->count = 1;
101 101
102 /* enable irqs */ 102 /* enable irqs */
103 dprintk( 0, "setting the interrupt mask\n" );
103 cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); 104 cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
104 cx_write(MO_TS_INTMSK, 0x1f0011); 105 cx_set(MO_TS_INTMSK, 0x1f0011);
106 //cx_write(MO_TS_INTMSK, 0x0f0011);
105 107
106 /* start dma */ 108 /* start dma */
107 cx_write(MO_DEV_CNTRL2, (1<<5)); /* FIXME: s/write/set/ ??? */ 109 cx_set(MO_DEV_CNTRL2, (1<<5));
108 cx_write(MO_TS_DMACNTRL, 0x11); 110 cx_set(MO_TS_DMACNTRL, 0x11);
109 return 0; 111 return 0;
110} 112}
111 113
112static int cx8802_stop_dma(struct cx8802_dev *dev) 114static int cx8802_stop_dma(struct cx8802_dev *dev)
113{ 115{
114 struct cx88_core *core = dev->core; 116 struct cx88_core *core = dev->core;
117 dprintk( 0, "cx8802_stop_dma\n" );
115 118
116 /* stop dma */ 119 /* stop dma */
117 cx_clear(MO_TS_DMACNTRL, 0x11); 120 cx_clear(MO_TS_DMACNTRL, 0x11);
@@ -131,8 +134,12 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
131 struct cx88_buffer *buf; 134 struct cx88_buffer *buf;
132 struct list_head *item; 135 struct list_head *item;
133 136
137 dprintk( 0, "cx8802_restart_queue\n" );
134 if (list_empty(&q->active)) 138 if (list_empty(&q->active))
139 {
140 dprintk( 0, "cx8802_restart_queue: queue is empty\n" );
135 return 0; 141 return 0;
142 }
136 143
137 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); 144 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
138 dprintk(2,"restart_queue [%p/%d]: restart dma\n", 145 dprintk(2,"restart_queue [%p/%d]: restart dma\n",
@@ -182,27 +189,32 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
182 struct cx88_buffer *prev; 189 struct cx88_buffer *prev;
183 struct cx88_dmaqueue *q = &dev->mpegq; 190 struct cx88_dmaqueue *q = &dev->mpegq;
184 191
192 dprintk( 1, "cx8802_buf_queue\n" );
185 /* add jump to stopper */ 193 /* add jump to stopper */
186 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); 194 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
187 buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); 195 buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
188 196
189 if (list_empty(&q->active)) { 197 if (list_empty(&q->active)) {
198 dprintk( 0, "queue is empty - first active\n" );
190 list_add_tail(&buf->vb.queue,&q->active); 199 list_add_tail(&buf->vb.queue,&q->active);
191 cx8802_start_dma(dev, q, buf); 200 cx8802_start_dma(dev, q, buf);
192 buf->vb.state = STATE_ACTIVE; 201 buf->vb.state = STATE_ACTIVE;
193 buf->count = q->count++; 202 buf->count = q->count++;
194 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); 203 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
195 dprintk(2,"[%p/%d] %s - first active\n", 204 dprintk(0,"[%p/%d] %s - first active\n",
196 buf, buf->vb.i, __FUNCTION__); 205 buf, buf->vb.i, __FUNCTION__);
206 //udelay(100);
197 207
198 } else { 208 } else {
209 dprintk( 1, "queue is not empty - append to active\n" );
199 prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); 210 prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
200 list_add_tail(&buf->vb.queue,&q->active); 211 list_add_tail(&buf->vb.queue,&q->active);
201 buf->vb.state = STATE_ACTIVE; 212 buf->vb.state = STATE_ACTIVE;
202 buf->count = q->count++; 213 buf->count = q->count++;
203 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); 214 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
204 dprintk(2,"[%p/%d] %s - append to active\n", 215 dprintk( 1, "[%p/%d] %s - append to active\n",
205 buf, buf->vb.i, __FUNCTION__); 216 buf, buf->vb.i, __FUNCTION__);
217 //udelay(100);
206 } 218 }
207} 219}
208 220
@@ -224,7 +236,10 @@ static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart)
224 buf, buf->vb.i, reason, (unsigned long)buf->risc.dma); 236 buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
225 } 237 }
226 if (restart) 238 if (restart)
239 {
240 dprintk(0, "restarting queue\n" );
227 cx8802_restart_queue(dev,q); 241 cx8802_restart_queue(dev,q);
242 }
228 spin_unlock_irqrestore(&dev->slock,flags); 243 spin_unlock_irqrestore(&dev->slock,flags);
229} 244}
230 245
@@ -232,6 +247,7 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev)
232{ 247{
233 struct cx88_dmaqueue *q = &dev->mpegq; 248 struct cx88_dmaqueue *q = &dev->mpegq;
234 249
250 dprintk( 1, "cx8802_cancel_buffers" );
235 del_timer_sync(&q->timeout); 251 del_timer_sync(&q->timeout);
236 cx8802_stop_dma(dev); 252 cx8802_stop_dma(dev);
237 do_cancel_buffers(dev,"cancel",0); 253 do_cancel_buffers(dev,"cancel",0);
@@ -241,7 +257,7 @@ static void cx8802_timeout(unsigned long data)
241{ 257{
242 struct cx8802_dev *dev = (struct cx8802_dev*)data; 258 struct cx8802_dev *dev = (struct cx8802_dev*)data;
243 259
244 dprintk(1, "%s\n",__FUNCTION__); 260 dprintk(0, "%s\n",__FUNCTION__);
245 261
246 if (debug) 262 if (debug)
247 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); 263 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
@@ -254,12 +270,17 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
254 struct cx88_core *core = dev->core; 270 struct cx88_core *core = dev->core;
255 u32 status, mask, count; 271 u32 status, mask, count;
256 272
273 dprintk( 1, "cx8802_mpeg_irq\n" );
257 status = cx_read(MO_TS_INTSTAT); 274 status = cx_read(MO_TS_INTSTAT);
258 mask = cx_read(MO_TS_INTMSK); 275 mask = cx_read(MO_TS_INTMSK);
259 if (0 == (status & mask)) 276 if (0 == (status & mask))
260 return; 277 return;
261 278
262 cx_write(MO_TS_INTSTAT, status); 279 cx_write(MO_TS_INTSTAT, status);
280#if 0
281 cx88_print_irqbits(core->name, "irq mpeg ",
282 cx88_mpeg_irqs, status, mask);
283#endif
263 if (debug || (status & mask & ~0xff)) 284 if (debug || (status & mask & ~0xff))
264 cx88_print_irqbits(core->name, "irq mpeg ", 285 cx88_print_irqbits(core->name, "irq mpeg ",
265 cx88_mpeg_irqs, status, mask); 286 cx88_mpeg_irqs, status, mask);
@@ -273,6 +294,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
273 294
274 /* risc1 y */ 295 /* risc1 y */
275 if (status & 0x01) { 296 if (status & 0x01) {
297 dprintk( 1, "wake up\n" );
276 spin_lock(&dev->slock); 298 spin_lock(&dev->slock);
277 count = cx_read(MO_TS_GPCNT); 299 count = cx_read(MO_TS_GPCNT);
278 cx88_wakeup(dev->core, &dev->mpegq, count); 300 cx88_wakeup(dev->core, &dev->mpegq, count);
@@ -288,6 +310,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
288 310
289 /* other general errors */ 311 /* other general errors */
290 if (status & 0x1f0100) { 312 if (status & 0x1f0100) {
313 dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
291 spin_lock(&dev->slock); 314 spin_lock(&dev->slock);
292 cx8802_stop_dma(dev); 315 cx8802_stop_dma(dev);
293 cx8802_restart_queue(dev,&dev->mpegq); 316 cx8802_restart_queue(dev,&dev->mpegq);
@@ -295,6 +318,8 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
295 } 318 }
296} 319}
297 320
321#define MAX_IRQ_LOOP 10
322
298static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs) 323static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
299{ 324{
300 struct cx8802_dev *dev = dev_id; 325 struct cx8802_dev *dev = dev_id;
@@ -302,10 +327,13 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
302 u32 status; 327 u32 status;
303 int loop, handled = 0; 328 int loop, handled = 0;
304 329
305 for (loop = 0; loop < 10; loop++) { 330 for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
306 status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04); 331 status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
307 if (0 == status) 332 if (0 == status)
308 goto out; 333 goto out;
334 dprintk( 1, "cx8802_irq\n" );
335 dprintk( 1, " loop: %d/%d\n", loop, MAX_IRQ_LOOP );
336 dprintk( 1, " status: %d\n", status );
309 handled = 1; 337 handled = 1;
310 cx_write(MO_PCI_INTSTAT, status); 338 cx_write(MO_PCI_INTSTAT, status);
311 339
@@ -314,7 +342,8 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
314 if (status & 0x04) 342 if (status & 0x04)
315 cx8802_mpeg_irq(dev); 343 cx8802_mpeg_irq(dev);
316 }; 344 };
317 if (10 == loop) { 345 if (MAX_IRQ_LOOP == loop) {
346 dprintk( 0, "clearing mask\n" );
318 printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", 347 printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
319 core->name); 348 core->name);
320 cx_write(MO_PCI_INTMSK,0); 349 cx_write(MO_PCI_INTMSK,0);
@@ -378,6 +407,7 @@ int cx8802_init_common(struct cx8802_dev *dev)
378 407
379void cx8802_fini_common(struct cx8802_dev *dev) 408void cx8802_fini_common(struct cx8802_dev *dev)
380{ 409{
410 dprintk( 2, "cx8802_fini_common\n" );
381 cx8802_stop_dma(dev); 411 cx8802_stop_dma(dev);
382 pci_disable_device(dev->pci); 412 pci_disable_device(dev->pci);
383 413
@@ -399,6 +429,7 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
399 /* stop mpeg dma */ 429 /* stop mpeg dma */
400 spin_lock(&dev->slock); 430 spin_lock(&dev->slock);
401 if (!list_empty(&dev->mpegq.active)) { 431 if (!list_empty(&dev->mpegq.active)) {
432 dprintk( 2, "suspend\n" );
402 printk("%s: suspend mpeg\n", core->name); 433 printk("%s: suspend mpeg\n", core->name);
403 cx8802_stop_dma(dev); 434 cx8802_stop_dma(dev);
404 del_timer(&dev->mpegq.timeout); 435 del_timer(&dev->mpegq.timeout);
@@ -463,4 +494,5 @@ EXPORT_SYMBOL(cx8802_resume_common);
463 * Local variables: 494 * Local variables:
464 * c-basic-offset: 8 495 * c-basic-offset: 8
465 * End: 496 * End:
497 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
466 */ 498 */
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
index 8638ce57d8..63ad33f581 100644
--- a/drivers/media/video/cx88/cx88-reg.h
+++ b/drivers/media/video/cx88/cx88-reg.h
@@ -1,5 +1,5 @@
1/* 1/*
2 $Id: cx88-reg.h,v 1.6 2004/10/13 10:39:00 kraxel Exp $ 2 $Id: cx88-reg.h,v 1.7 2005/06/03 13:31:51 mchehab Exp $
3 3
4 cx88x-hw.h - CX2388x register offsets 4 cx88x-hw.h - CX2388x register offsets
5 5
@@ -397,6 +397,7 @@
397#define AUD_RATE_ADJ4 0x3205e4 397#define AUD_RATE_ADJ4 0x3205e4
398#define AUD_RATE_ADJ5 0x3205e8 398#define AUD_RATE_ADJ5 0x3205e8
399#define AUD_APB_IN_RATE_ADJ 0x3205ec 399#define AUD_APB_IN_RATE_ADJ 0x3205ec
400#define AUD_I2SCNTL 0x3205ec
400#define AUD_PHASE_FIX_CTL 0x3205f0 401#define AUD_PHASE_FIX_CTL 0x3205f0
401#define AUD_PLL_PRESCALE 0x320600 402#define AUD_PLL_PRESCALE 0x320600
402#define AUD_PLL_DDS 0x320604 403#define AUD_PLL_DDS 0x320604
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index f2a9475a2f..46d78b1dc9 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -1,5 +1,5 @@
1/* 1/*
2 $Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $ 2 $Id: cx88-tvaudio.c,v 1.36 2005/06/05 05:53:45 mchehab Exp $
3 3
4 cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver 4 cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
5 5
@@ -127,7 +127,8 @@ static void set_audio_start(struct cx88_core *core,
127 cx_write(AUD_VOL_CTL, (1 << 6)); 127 cx_write(AUD_VOL_CTL, (1 << 6));
128 128
129 // increase level of input by 12dB 129 // increase level of input by 12dB
130 cx_write(AUD_AFE_12DB_EN, 0x0001); 130// cx_write(AUD_AFE_12DB_EN, 0x0001);
131 cx_write(AUD_AFE_12DB_EN, 0x0000);
131 132
132 // start programming 133 // start programming
133 cx_write(AUD_CTL, 0x0000); 134 cx_write(AUD_CTL, 0x0000);
@@ -143,9 +144,15 @@ static void set_audio_finish(struct cx88_core *core)
143 u32 volume; 144 u32 volume;
144 145
145 if (cx88_boards[core->board].blackbird) { 146 if (cx88_boards[core->board].blackbird) {
147 // sets sound input from external adc
148 cx_set(AUD_CTL, EN_I2SIN_ENABLE);
149 //cx_write(AUD_I2SINPUTCNTL, 0);
150 cx_write(AUD_I2SINPUTCNTL, 4);
151 cx_write(AUD_BAUDRATE, 1);
146 // 'pass-thru mode': this enables the i2s output to the mpeg encoder 152 // 'pass-thru mode': this enables the i2s output to the mpeg encoder
147 cx_set(AUD_CTL, 0x2000); 153 cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
148 cx_write(AUD_I2SOUTPUTCNTL, 1); 154 cx_write(AUD_I2SOUTPUTCNTL, 1);
155 cx_write(AUD_I2SCNTL, 0);
149 //cx_write(AUD_APB_IN_RATE_ADJ, 0); 156 //cx_write(AUD_APB_IN_RATE_ADJ, 0);
150 } 157 }
151 158
@@ -707,50 +714,65 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
707 set_audio_finish(core); 714 set_audio_finish(core);
708} 715}
709 716
710static void set_audio_standard_FM(struct cx88_core *core) 717static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type deemph)
711{ 718{
712#if 0 /* FIXME */ 719 static const struct rlist fm_deemph_50[] = {
713 switch (dev->audio_properties.FM_deemphasis) 720 { AUD_DEEMPH0_G0, 0x0C45 },
714 { 721 { AUD_DEEMPH0_A0, 0x6262 },
715 case WW_FM_DEEMPH_50: 722 { AUD_DEEMPH0_B0, 0x1C29 },
716 //Set De-emphasis filter coefficients for 50 usec 723 { AUD_DEEMPH0_A1, 0x3FC66},
717 cx_write(AUD_DEEMPH0_G0, 0x0C45); 724 { AUD_DEEMPH0_B1, 0x399A },
718 cx_write(AUD_DEEMPH0_A0, 0x6262); 725
719 cx_write(AUD_DEEMPH0_B0, 0x1C29); 726 { AUD_DEEMPH1_G0, 0x0D80 },
720 cx_write(AUD_DEEMPH0_A1, 0x3FC66); 727 { AUD_DEEMPH1_A0, 0x6262 },
721 cx_write(AUD_DEEMPH0_B1, 0x399A); 728 { AUD_DEEMPH1_B0, 0x1C29 },
722 729 { AUD_DEEMPH1_A1, 0x3FC66},
723 cx_write(AUD_DEEMPH1_G0, 0x0D80); 730 { AUD_DEEMPH1_B1, 0x399A},
724 cx_write(AUD_DEEMPH1_A0, 0x6262); 731
725 cx_write(AUD_DEEMPH1_B0, 0x1C29); 732 { AUD_POLYPH80SCALEFAC, 0x0003},
726 cx_write(AUD_DEEMPH1_A1, 0x3FC66); 733 { /* end of list */ },
727 cx_write(AUD_DEEMPH1_B1, 0x399A); 734 };
735 static const struct rlist fm_deemph_75[] = {
736 { AUD_DEEMPH0_G0, 0x091B },
737 { AUD_DEEMPH0_A0, 0x6B68 },
738 { AUD_DEEMPH0_B0, 0x11EC },
739 { AUD_DEEMPH0_A1, 0x3FC66},
740 { AUD_DEEMPH0_B1, 0x399A },
741
742 { AUD_DEEMPH1_G0, 0x0AA0 },
743 { AUD_DEEMPH1_A0, 0x6B68 },
744 { AUD_DEEMPH1_B0, 0x11EC },
745 { AUD_DEEMPH1_A1, 0x3FC66},
746 { AUD_DEEMPH1_B1, 0x399A},
747
748 { AUD_POLYPH80SCALEFAC, 0x0003},
749 { /* end of list */ },
750 };
728 751
729 break; 752 /* It is enough to leave default values? */
753 static const struct rlist fm_no_deemph[] = {
730 754
731 case WW_FM_DEEMPH_75: 755 { AUD_POLYPH80SCALEFAC, 0x0003},
732 //Set De-emphasis filter coefficients for 75 usec 756 { /* end of list */ },
733 cx_write(AUD_DEEMPH0_G0, 0x91B ); 757 };
734 cx_write(AUD_DEEMPH0_A0, 0x6B68);
735 cx_write(AUD_DEEMPH0_B0, 0x11EC);
736 cx_write(AUD_DEEMPH0_A1, 0x3FC66);
737 cx_write(AUD_DEEMPH0_B1, 0x399A);
738 758
739 cx_write(AUD_DEEMPH1_G0, 0xAA0 ); 759 dprintk("%s (status: unknown)\n",__FUNCTION__);
740 cx_write(AUD_DEEMPH1_A0, 0x6B68); 760 set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO);
741 cx_write(AUD_DEEMPH1_B0, 0x11EC);
742 cx_write(AUD_DEEMPH1_A1, 0x3FC66);
743 cx_write(AUD_DEEMPH1_B1, 0x399A);
744 761
762 switch (deemph)
763 {
764 case FM_NO_DEEMPH:
765 set_audio_registers(core, fm_no_deemph);
745 break; 766 break;
746 }
747#endif
748 767
749 dprintk("%s (status: unknown)\n",__FUNCTION__); 768 case FM_DEEMPH_50:
750 set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO); 769 set_audio_registers(core, fm_deemph_50);
770 break;
751 771
752 // AB: 10/2/01: this register is not being reset appropriately on occasion. 772 case FM_DEEMPH_75:
753 cx_write(AUD_POLYPH80SCALEFAC,3); 773 set_audio_registers(core, fm_deemph_75);
774 break;
775 }
754 776
755 set_audio_finish(core); 777 set_audio_finish(core);
756} 778}
@@ -778,7 +800,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
778 set_audio_standard_EIAJ(core); 800 set_audio_standard_EIAJ(core);
779 break; 801 break;
780 case WW_FM: 802 case WW_FM:
781 set_audio_standard_FM(core); 803 set_audio_standard_FM(core,FM_NO_DEEMPH);
782 break; 804 break;
783 case WW_SYSTEM_L_AM: 805 case WW_SYSTEM_L_AM:
784 set_audio_standard_NICAM_L(core, 1); 806 set_audio_standard_NICAM_L(core, 1);
@@ -1029,4 +1051,5 @@ EXPORT_SYMBOL(cx88_audio_thread);
1029 * Local variables: 1051 * Local variables:
1030 * c-basic-offset: 8 1052 * c-basic-offset: 8
1031 * End: 1053 * End:
1054 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
1032 */ 1055 */
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 0584ff4763..320d57888b 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $ 2 * $Id: cx88-vbi.c,v 1.17 2005/06/12 04:19:19 mchehab Exp $
3 */ 3 */
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <linux/module.h> 5#include <linux/module.h>
@@ -47,8 +47,8 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
47} 47}
48 48
49static int cx8800_start_vbi_dma(struct cx8800_dev *dev, 49static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
50 struct cx88_dmaqueue *q, 50 struct cx88_dmaqueue *q,
51 struct cx88_buffer *buf) 51 struct cx88_buffer *buf)
52{ 52{
53 struct cx88_core *core = dev->core; 53 struct cx88_core *core = dev->core;
54 54
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index d1f5c92f0c..e4ca7350df 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $ 2 * $Id: cx88-video.c,v 1.63 2005/06/12 04:19:19 mchehab Exp $
3 * 3 *
4 * device driver for Conexant 2388x based TV cards 4 * device driver for Conexant 2388x based TV cards
5 * video4linux video interface 5 * video4linux video interface
@@ -1187,9 +1187,24 @@ static void init_controls(struct cx8800_dev *dev)
1187 .id = V4L2_CID_AUDIO_VOLUME, 1187 .id = V4L2_CID_AUDIO_VOLUME,
1188 .value = 0x3f, 1188 .value = 0x3f,
1189 }; 1189 };
1190 static struct v4l2_control hue = {
1191 .id = V4L2_CID_HUE,
1192 .value = 0x80,
1193 };
1194 static struct v4l2_control contrast = {
1195 .id = V4L2_CID_CONTRAST,
1196 .value = 0x80,
1197 };
1198 static struct v4l2_control brightness = {
1199 .id = V4L2_CID_BRIGHTNESS,
1200 .value = 0x80,
1201 };
1190 1202
1191 set_control(dev,&mute); 1203 set_control(dev,&mute);
1192 set_control(dev,&volume); 1204 set_control(dev,&volume);
1205 set_control(dev,&hue);
1206 set_control(dev,&contrast);
1207 set_control(dev,&brightness);
1193} 1208}
1194 1209
1195/* ------------------------------------------------------------------ */ 1210/* ------------------------------------------------------------------ */
@@ -1336,6 +1351,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
1336 V4L2_CAP_STREAMING | 1351 V4L2_CAP_STREAMING |
1337 V4L2_CAP_VBI_CAPTURE | 1352 V4L2_CAP_VBI_CAPTURE |
1338#if 0 1353#if 0
1354 V4L2_TUNER_CAP_LOW |
1355#endif
1356#if 0
1339 V4L2_CAP_VIDEO_OVERLAY | 1357 V4L2_CAP_VIDEO_OVERLAY |
1340#endif 1358#endif
1341 0; 1359 0;
@@ -1696,7 +1714,11 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
1696 sizeof(cap->card)); 1714 sizeof(cap->card));
1697 sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); 1715 sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
1698 cap->version = CX88_VERSION_CODE; 1716 cap->version = CX88_VERSION_CODE;
1699 cap->capabilities = V4L2_CAP_TUNER; 1717 cap->capabilities = V4L2_CAP_TUNER
1718#if 0
1719 | V4L2_TUNER_CAP_LOW
1720#endif
1721 ;
1700 return 0; 1722 return 0;
1701 } 1723 }
1702 case VIDIOC_G_TUNER: 1724 case VIDIOC_G_TUNER:
@@ -1992,6 +2014,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1992{ 2014{
1993 struct cx8800_dev *dev; 2015 struct cx8800_dev *dev;
1994 struct cx88_core *core; 2016 struct cx88_core *core;
2017 struct tuner_addr tun_addr;
1995 int err; 2018 int err;
1996 2019
1997 dev = kmalloc(sizeof(*dev),GFP_KERNEL); 2020 dev = kmalloc(sizeof(*dev),GFP_KERNEL);
@@ -2065,8 +2088,19 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
2065 request_module("tuner"); 2088 request_module("tuner");
2066 if (core->tda9887_conf) 2089 if (core->tda9887_conf)
2067 request_module("tda9887"); 2090 request_module("tda9887");
2068 if (core->tuner_type != UNSET) 2091 if (core->radio_type != UNSET) {
2069 cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE,&core->tuner_type); 2092 tun_addr.v4l2_tuner = V4L2_TUNER_RADIO;
2093 tun_addr.type = core->radio_type;
2094 tun_addr.addr = core->radio_addr;
2095 cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE_ADDR, &tun_addr);
2096 }
2097 if (core->tuner_type != UNSET) {
2098 tun_addr.v4l2_tuner = V4L2_TUNER_ANALOG_TV;
2099 tun_addr.type = core->tuner_type;
2100 tun_addr.addr = core->tuner_addr;
2101 cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE_ADDR, &tun_addr);
2102 }
2103
2070 if (core->tda9887_conf) 2104 if (core->tda9887_conf)
2071 cx88_call_i2c_clients(dev->core,TDA9887_SET_CONFIG,&core->tda9887_conf); 2105 cx88_call_i2c_clients(dev->core,TDA9887_SET_CONFIG,&core->tda9887_conf);
2072 2106
@@ -2162,7 +2196,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
2162 2196
2163static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) 2197static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
2164{ 2198{
2165 struct cx8800_dev *dev = pci_get_drvdata(pci_dev); 2199 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
2166 struct cx88_core *core = dev->core; 2200 struct cx88_core *core = dev->core;
2167 2201
2168 /* stop video+vbi capture */ 2202 /* stop video+vbi capture */
@@ -2194,7 +2228,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
2194 2228
2195static int cx8800_resume(struct pci_dev *pci_dev) 2229static int cx8800_resume(struct pci_dev *pci_dev)
2196{ 2230{
2197 struct cx8800_dev *dev = pci_get_drvdata(pci_dev); 2231 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
2198 struct cx88_core *core = dev->core; 2232 struct cx88_core *core = dev->core;
2199 2233
2200 if (dev->state.disabled) { 2234 if (dev->state.disabled) {
@@ -2230,8 +2264,8 @@ static struct pci_device_id cx8800_pci_tbl[] = {
2230 { 2264 {
2231 .vendor = 0x14f1, 2265 .vendor = 0x14f1,
2232 .device = 0x8800, 2266 .device = 0x8800,
2233 .subvendor = PCI_ANY_ID, 2267 .subvendor = PCI_ANY_ID,
2234 .subdevice = PCI_ANY_ID, 2268 .subdevice = PCI_ANY_ID,
2235 },{ 2269 },{
2236 /* --- end of list --- */ 2270 /* --- end of list --- */
2237 } 2271 }
@@ -2239,10 +2273,10 @@ static struct pci_device_id cx8800_pci_tbl[] = {
2239MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl); 2273MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
2240 2274
2241static struct pci_driver cx8800_pci_driver = { 2275static struct pci_driver cx8800_pci_driver = {
2242 .name = "cx8800", 2276 .name = "cx8800",
2243 .id_table = cx8800_pci_tbl, 2277 .id_table = cx8800_pci_tbl,
2244 .probe = cx8800_initdev, 2278 .probe = cx8800_initdev,
2245 .remove = __devexit_p(cx8800_finidev), 2279 .remove = __devexit_p(cx8800_finidev),
2246 2280
2247 .suspend = cx8800_suspend, 2281 .suspend = cx8800_suspend,
2248 .resume = cx8800_resume, 2282 .resume = cx8800_resume,
@@ -2274,4 +2308,5 @@ module_exit(cx8800_fini);
2274 * Local variables: 2308 * Local variables:
2275 * c-basic-offset: 8 2309 * c-basic-offset: 8
2276 * End: 2310 * End:
2311 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
2277 */ 2312 */
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 88eaaaba5a..ac0dc27bb3 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $ 2 * $Id: cx88.h,v 1.62 2005/06/12 04:19:19 mchehab Exp $
3 * 3 *
4 * v4l2 device driver for cx2388x based TV cards 4 * v4l2 device driver for cx2388x based TV cards
5 * 5 *
@@ -64,6 +64,13 @@
64#define SHADOW_AUD_BAL_CTL 2 64#define SHADOW_AUD_BAL_CTL 2
65#define SHADOW_MAX 2 65#define SHADOW_MAX 2
66 66
67/* FM Radio deemphasis type */
68enum cx88_deemph_type {
69 FM_NO_DEEMPH = 0,
70 FM_DEEMPH_50,
71 FM_DEEMPH_75
72};
73
67/* ----------------------------------------------------------- */ 74/* ----------------------------------------------------------- */
68/* tv norms */ 75/* tv norms */
69 76
@@ -162,6 +169,8 @@ extern struct sram_channel cx88_sram_channels[];
162#define CX88_BOARD_HAUPPAUGE_ROSLYN 24 169#define CX88_BOARD_HAUPPAUGE_ROSLYN 24
163#define CX88_BOARD_DIGITALLOGIC_MEC 25 170#define CX88_BOARD_DIGITALLOGIC_MEC 25
164#define CX88_BOARD_IODATA_GVBCTV7E 26 171#define CX88_BOARD_IODATA_GVBCTV7E 26
172#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
173#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28
165 174
166enum cx88_itype { 175enum cx88_itype {
167 CX88_VMUX_COMPOSITE1 = 1, 176 CX88_VMUX_COMPOSITE1 = 1,
@@ -185,6 +194,9 @@ struct cx88_input {
185struct cx88_board { 194struct cx88_board {
186 char *name; 195 char *name;
187 unsigned int tuner_type; 196 unsigned int tuner_type;
197 unsigned int radio_type;
198 unsigned char tuner_addr;
199 unsigned char radio_addr;
188 int tda9887_conf; 200 int tda9887_conf;
189 struct cx88_input input[8]; 201 struct cx88_input input[8];
190 struct cx88_input radio; 202 struct cx88_input radio;
@@ -255,6 +267,9 @@ struct cx88_core {
255 /* config info -- analog */ 267 /* config info -- analog */
256 unsigned int board; 268 unsigned int board;
257 unsigned int tuner_type; 269 unsigned int tuner_type;
270 unsigned int radio_type;
271 unsigned char tuner_addr;
272 unsigned char radio_addr;
258 unsigned int tda9887_conf; 273 unsigned int tda9887_conf;
259 unsigned int has_radio; 274 unsigned int has_radio;
260 275
@@ -420,6 +435,7 @@ struct cx8802_dev {
420/* ----------------------------------------------------------- */ 435/* ----------------------------------------------------------- */
421/* cx88-core.c */ 436/* cx88-core.c */
422 437
438extern char *cx88_pci_irqs[32];
423extern char *cx88_vid_irqs[32]; 439extern char *cx88_vid_irqs[32];
424extern char *cx88_mpeg_irqs[32]; 440extern char *cx88_mpeg_irqs[32];
425extern void cx88_print_irqbits(char *name, char *tag, char **strings, 441extern void cx88_print_irqbits(char *name, char *tag, char **strings,
@@ -471,6 +487,11 @@ extern void cx88_core_put(struct cx88_core *core,
471/* cx88-vbi.c */ 487/* cx88-vbi.c */
472 488
473void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f); 489void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f);
490/*
491int cx8800_start_vbi_dma(struct cx8800_dev *dev,
492 struct cx88_dmaqueue *q,
493 struct cx88_buffer *buf);
494*/
474int cx8800_stop_vbi_dma(struct cx8800_dev *dev); 495int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
475int cx8800_restart_vbi_queue(struct cx8800_dev *dev, 496int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
476 struct cx88_dmaqueue *q); 497 struct cx88_dmaqueue *q);
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index ab6620de4b..a565823330 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: ir-kbd-gpio.c,v 1.12 2005/02/22 12:28:40 kraxel Exp $ 2 * $Id: ir-kbd-gpio.c,v 1.13 2005/05/15 19:01:26 mchehab Exp $
3 * 3 *
4 * Copyright (c) 2003 Gerd Knorr 4 * Copyright (c) 2003 Gerd Knorr
5 * Copyright (c) 2003 Pavel Machek 5 * Copyright (c) 2003 Pavel Machek
@@ -114,38 +114,6 @@ static IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
114 [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' 114 [ 0x3e ] = KEY_VOLUMEUP, // 'volume +'
115}; 115};
116 116
117static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
118 [ 2 ] = KEY_KP0,
119 [ 1 ] = KEY_KP1,
120 [ 11 ] = KEY_KP2,
121 [ 27 ] = KEY_KP3,
122 [ 5 ] = KEY_KP4,
123 [ 9 ] = KEY_KP5,
124 [ 21 ] = KEY_KP6,
125 [ 6 ] = KEY_KP7,
126 [ 10 ] = KEY_KP8,
127 [ 18 ] = KEY_KP9,
128
129 [ 3 ] = KEY_TUNER, // TV/FM
130 [ 7 ] = KEY_SEARCH, // scan
131 [ 28 ] = KEY_ZOOM, // full screen
132 [ 30 ] = KEY_POWER,
133 [ 23 ] = KEY_VOLUMEDOWN,
134 [ 31 ] = KEY_VOLUMEUP,
135 [ 20 ] = KEY_CHANNELDOWN,
136 [ 22 ] = KEY_CHANNELUP,
137 [ 24 ] = KEY_MUTE,
138
139 [ 0 ] = KEY_LIST, // source
140 [ 19 ] = KEY_INFO, // loop
141 [ 16 ] = KEY_LAST, // +100
142 [ 13 ] = KEY_CLEAR, // reset
143 [ 12 ] = BTN_RIGHT, // fun++
144 [ 4 ] = BTN_LEFT, // fun--
145 [ 14 ] = KEY_GOTO, // function
146 [ 15 ] = KEY_STOP, // freeze
147};
148
149/* Attila Kondoros <attila.kondoros@chello.hu> */ 117/* Attila Kondoros <attila.kondoros@chello.hu> */
150static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { 118static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
151 119
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 09464d624a..1b7d38e96f 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -735,7 +735,6 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout)
735{ 735{
736 DECLARE_WAITQUEUE(wait, current); 736 DECLARE_WAITQUEUE(wait, current);
737 737
738again:
739 add_wait_queue(&msp->wq, &wait); 738 add_wait_queue(&msp->wq, &wait);
740 if (!kthread_should_stop()) { 739 if (!kthread_should_stop()) {
741 if (timeout < 0) { 740 if (timeout < 0) {
@@ -751,12 +750,9 @@ again:
751#endif 750#endif
752 } 751 }
753 } 752 }
754 753 if (current->flags & PF_FREEZE)
754 refrigerator(PF_FREEZE);
755 remove_wait_queue(&msp->wq, &wait); 755 remove_wait_queue(&msp->wq, &wait);
756
757 if (try_to_freeze(PF_FREEZE))
758 goto again;
759
760 return msp->restart; 756 return msp->restart;
761} 757}
762 758
@@ -1436,7 +1432,7 @@ static int msp_detach(struct i2c_client *client);
1436static int msp_probe(struct i2c_adapter *adap); 1432static int msp_probe(struct i2c_adapter *adap);
1437static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg); 1433static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
1438 1434
1439static int msp_suspend(struct device * dev, pm_message_t state, u32 level); 1435static int msp_suspend(struct device * dev, u32 state, u32 level);
1440static int msp_resume(struct device * dev, u32 level); 1436static int msp_resume(struct device * dev, u32 level);
1441 1437
1442static void msp_wake_thread(struct i2c_client *client); 1438static void msp_wake_thread(struct i2c_client *client);
@@ -1841,7 +1837,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
1841 return 0; 1837 return 0;
1842} 1838}
1843 1839
1844static int msp_suspend(struct device * dev, pm_message_t state, u32 level) 1840static int msp_suspend(struct device * dev, u32 state, u32 level)
1845{ 1841{
1846 struct i2c_client *c = container_of(dev, struct i2c_client, dev); 1842 struct i2c_client *c = container_of(dev, struct i2c_client, dev);
1847 1843
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h
index d70a954e13..023f33056a 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -1,3 +1,7 @@
1/*
2 * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
3 */
4
1#ifndef MSP3400_H 5#ifndef MSP3400_H
2#define MSP3400_H 6#define MSP3400_H
3 7
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 42c2b565c9..e6d0a18833 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -41,16 +41,16 @@ enum saa6752hs_videoformat {
41 41
42static const struct v4l2_format v4l2_format_table[] = 42static const struct v4l2_format v4l2_format_table[] =
43{ 43{
44 [SAA6752HS_VF_D1] = { 44 [SAA6752HS_VF_D1] =
45 .fmt = { .pix = { .width = 720, .height = 576 }, }, }, 45 { .fmt = { .pix = { .width = 720, .height = 576 }}},
46 [SAA6752HS_VF_2_3_D1] = { 46 [SAA6752HS_VF_2_3_D1] =
47 .fmt = { .pix = { .width = 480, .height = 576 }, }, }, 47 { .fmt = { .pix = { .width = 480, .height = 576 }}},
48 [SAA6752HS_VF_1_2_D1] = { 48 [SAA6752HS_VF_1_2_D1] =
49 .fmt = { .pix = { .width = 352, .height = 576 }, }, }, 49 { .fmt = { .pix = { .width = 352, .height = 576 }}},
50 [SAA6752HS_VF_SIF] = { 50 [SAA6752HS_VF_SIF] =
51 .fmt = { .pix = { .width = 352, .height = 288 }, }, }, 51 { .fmt = { .pix = { .width = 352, .height = 288 }}},
52 [SAA6752HS_VF_UNKNOWN] = { 52 [SAA6752HS_VF_UNKNOWN] =
53 .fmt = { .pix = { .width = 0, .height = 0 }, }, }, 53 { .fmt = { .pix = { .width = 0, .height = 0}}},
54}; 54};
55 55
56struct saa6752hs_state { 56struct saa6752hs_state {
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index c51eb7f078..0c781e24c4 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -1,6 +1,6 @@
1 1
2/* 2/*
3 * $Id: saa7134-cards.c,v 1.54 2005/03/07 12:01:51 kraxel Exp $ 3 * $Id: saa7134-cards.c,v 1.58 2005/06/07 18:05:00 nsh Exp $
4 * 4 *
5 * device driver for philips saa7134 based TV cards 5 * device driver for philips saa7134 based TV cards
6 * card-specific stuff. 6 * card-specific stuff.
@@ -165,7 +165,7 @@ struct saa7134_board saa7134_boards[] = {
165 .inputs = {{ 165 .inputs = {{
166 .name = name_tv, 166 .name = name_tv,
167 .vmux = 1, 167 .vmux = 1,
168 .amux = LINE2, 168 .amux = TV,
169 .tv = 1, 169 .tv = 1,
170 },{ 170 },{
171 .name = name_comp1, 171 .name = name_comp1,
@@ -878,7 +878,7 @@ struct saa7134_board saa7134_boards[] = {
878 }, 878 },
879 [SAA7134_BOARD_MANLI_MTV002] = { 879 [SAA7134_BOARD_MANLI_MTV002] = {
880 /* Ognjen Nastic <ognjen@logosoft.ba> */ 880 /* Ognjen Nastic <ognjen@logosoft.ba> */
881 .name = "Manli MuchTV M-TV002", 881 .name = "Manli MuchTV M-TV002/Behold TV 403 FM",
882 .audio_clock = 0x00200000, 882 .audio_clock = 0x00200000,
883 .tuner_type = TUNER_PHILIPS_PAL, 883 .tuner_type = TUNER_PHILIPS_PAL,
884 .inputs = {{ 884 .inputs = {{
@@ -899,14 +899,10 @@ struct saa7134_board saa7134_boards[] = {
899 .name = name_radio, 899 .name = name_radio,
900 .amux = LINE2, 900 .amux = LINE2,
901 }, 901 },
902 .mute = {
903 .name = name_mute,
904 .amux = LINE1,
905 },
906 }, 902 },
907 [SAA7134_BOARD_MANLI_MTV001] = { 903 [SAA7134_BOARD_MANLI_MTV001] = {
908 /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */ 904 /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
909 .name = "Manli MuchTV M-TV001", 905 .name = "Manli MuchTV M-TV001/Behold TV 401",
910 .audio_clock = 0x00200000, 906 .audio_clock = 0x00200000,
911 .tuner_type = TUNER_PHILIPS_PAL, 907 .tuner_type = TUNER_PHILIPS_PAL,
912 .inputs = {{ 908 .inputs = {{
@@ -923,6 +919,10 @@ struct saa7134_board saa7134_boards[] = {
923 .amux = LINE2, 919 .amux = LINE2,
924 .tv = 1, 920 .tv = 1,
925 }}, 921 }},
922 .mute = {
923 .name = name_mute,
924 .amux = LINE1,
925 },
926 }, 926 },
927 [SAA7134_BOARD_TG3000TV] = { 927 [SAA7134_BOARD_TG3000TV] = {
928 /* TransGear 3000TV */ 928 /* TransGear 3000TV */
@@ -1078,7 +1078,6 @@ struct saa7134_board saa7134_boards[] = {
1078 .audio_clock = 0x00187de7, 1078 .audio_clock = 0x00187de7,
1079 .tuner_type = TUNER_PHILIPS_FM1256_IH3, 1079 .tuner_type = TUNER_PHILIPS_FM1256_IH3,
1080 .tda9887_conf = TDA9887_PRESENT, 1080 .tda9887_conf = TDA9887_PRESENT,
1081 .gpiomask = 0x3,
1082 .inputs = {{ 1081 .inputs = {{
1083 .name = name_tv, 1082 .name = name_tv,
1084 .vmux = 1, 1083 .vmux = 1,
@@ -1285,7 +1284,7 @@ struct saa7134_board saa7134_boards[] = {
1285 .gpio =0x8000, 1284 .gpio =0x8000,
1286 } 1285 }
1287 }, 1286 },
1288 [SAA7134_BOARD_AVERMEDIA_307] = { 1287 [SAA7134_BOARD_AVERMEDIA_STUDIO_307] = {
1289 /* 1288 /*
1290 Nickolay V. Shmyrev <nshmyrev@yandex.ru> 1289 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
1291 Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru> 1290 Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru>
@@ -1323,6 +1322,35 @@ struct saa7134_board saa7134_boards[] = {
1323 .gpio = 0x01, 1322 .gpio = 0x01,
1324 }, 1323 },
1325 }, 1324 },
1325 [SAA7134_BOARD_AVERMEDIA_GO_007_FM] = {
1326 .name = "Avermedia AVerTV GO 007 FM",
1327 .audio_clock = 0x00187de7,
1328 .tuner_type = TUNER_PHILIPS_TDA8290,
1329 .gpiomask = 0x00300003,
1330// .gpiomask = 0x8c240003,
1331 .inputs = {{
1332 .name = name_tv,
1333 .vmux = 1,
1334 .amux = TV,
1335 .tv = 1,
1336 .gpio = 0x01,
1337 },{
1338 .name = name_comp1,
1339 .vmux = 0,
1340 .amux = LINE2,
1341 .gpio = 0x02,
1342 },{
1343 .name = name_svideo,
1344 .vmux = 6,
1345 .amux = LINE2,
1346 .gpio = 0x02,
1347 }},
1348 .radio = {
1349 .name = name_radio,
1350 .amux = LINE1,
1351 .gpio = 0x00300001,
1352 },
1353 },
1326 [SAA7134_BOARD_AVERMEDIA_CARDBUS] = { 1354 [SAA7134_BOARD_AVERMEDIA_CARDBUS] = {
1327 /* Jon Westgate <oryn@oryn.fsck.tv> */ 1355 /* Jon Westgate <oryn@oryn.fsck.tv> */
1328 .name = "AVerMedia Cardbus TV/Radio", 1356 .name = "AVerMedia Cardbus TV/Radio",
@@ -1492,7 +1520,6 @@ struct saa7134_board saa7134_boards[] = {
1492 .audio_clock = 0x00187de7, 1520 .audio_clock = 0x00187de7,
1493 .tuner_type = TUNER_PHILIPS_FQ1216ME, 1521 .tuner_type = TUNER_PHILIPS_FQ1216ME,
1494 .tda9887_conf = TDA9887_PRESENT, 1522 .tda9887_conf = TDA9887_PRESENT,
1495 .gpiomask = 0x3,
1496 .inputs = {{ 1523 .inputs = {{
1497 .name = name_tv, 1524 .name = name_tv,
1498 .vmux = 1, 1525 .vmux = 1,
@@ -1546,7 +1573,82 @@ struct saa7134_board saa7134_boards[] = {
1546// .gpio = 0x4000, 1573// .gpio = 0x4000,
1547 }}, 1574 }},
1548 }, 1575 },
1549}; 1576 [SAA7134_BOARD_AVERMEDIA_307] = {
1577 /*
1578 Davydov Vladimir <vladimir@iqmedia.com>
1579 */
1580 .name = "Avermedia AVerTV 307",
1581 .audio_clock = 0x00187de7,
1582 .tuner_type = TUNER_PHILIPS_FQ1216ME,
1583 .tda9887_conf = TDA9887_PRESENT,
1584 .inputs = {{
1585 .name = name_tv,
1586 .vmux = 1,
1587 .amux = TV,
1588 .tv = 1,
1589 },{
1590 .name = name_comp1,
1591 .vmux = 0,
1592 .amux = LINE1,
1593 },{
1594 .name = name_comp2,
1595 .vmux = 3,
1596 .amux = LINE1,
1597 },{
1598 .name = name_svideo,
1599 .vmux = 8,
1600 .amux = LINE1,
1601 }},
1602 },
1603 [SAA7134_BOARD_ADS_INSTANT_TV] = {
1604 .name = "ADS Tech Instant TV (saa7135)",
1605 .audio_clock = 0x00187de7,
1606 .tuner_type = TUNER_PHILIPS_TDA8290,
1607 .inputs = {{
1608 .name = name_tv,
1609 .vmux = 1,
1610 .amux = TV,
1611 .tv = 1,
1612 },{
1613 .name = name_comp1,
1614 .vmux = 3,
1615 .amux = LINE2,
1616 },{
1617 .name = name_svideo,
1618 .vmux = 8,
1619 .amux = LINE2,
1620 }},
1621 },
1622 [SAA7134_BOARD_KWORLD_VSTREAM_XPERT] = {
1623 .name = "Kworld/Tevion V-Stream Xpert TV PVR7134",
1624 .audio_clock = 0x00187de7,
1625 .tuner_type = TUNER_PHILIPS_PAL_I,
1626 .gpiomask = 0x0700,
1627 .inputs = {{
1628 .name = name_tv,
1629 .vmux = 1,
1630 .amux = TV,
1631 .tv = 1,
1632 .gpio = 0x000,
1633 },{
1634 .name = name_comp1,
1635 .vmux = 3,
1636 .amux = LINE1,
1637 .gpio = 0x200, //gpio by DScaler
1638 },{
1639 .name = name_svideo,
1640 .vmux = 0,
1641 .amux = LINE1,
1642 .gpio = 0x200,
1643 }},
1644 .radio = {
1645 .name = name_radio,
1646 .amux = LINE1,
1647 .gpio = 0x100,
1648 },
1649 },
1650 };
1651
1550const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); 1652const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
1551 1653
1552/* ------------------------------------------------------------------ */ 1654/* ------------------------------------------------------------------ */
@@ -1663,7 +1765,7 @@ struct pci_device_id saa7134_pci_tbl[] = {
1663 .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, 1765 .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134,
1664 },{ 1766 },{
1665 .vendor = PCI_VENDOR_ID_PHILIPS, 1767 .vendor = PCI_VENDOR_ID_PHILIPS,
1666 .device = PCI_DEVICE_ID_PHILIPS_SAA7133, 1768 .device = PCI_DEVICE_ID_PHILIPS_SAA7135,
1667 .subvendor = PCI_VENDOR_ID_ASUSTEK, 1769 .subvendor = PCI_VENDOR_ID_ASUSTEK,
1668 .subdevice = 0x4845, 1770 .subdevice = 0x4845,
1669 .driver_data = SAA7135_BOARD_ASUSTeK_TVFM7135, 1771 .driver_data = SAA7135_BOARD_ASUSTeK_TVFM7135,
@@ -1824,6 +1926,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
1824 .device = PCI_DEVICE_ID_PHILIPS_SAA7134, 1926 .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
1825 .subvendor = 0x1461, /* Avermedia Technologies Inc */ 1927 .subvendor = 0x1461, /* Avermedia Technologies Inc */
1826 .subdevice = 0x9715, 1928 .subdevice = 0x9715,
1929 .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_307,
1930 },{
1931 .vendor = PCI_VENDOR_ID_PHILIPS,
1932 .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
1933 .subvendor = 0x1461, /* Avermedia Technologies Inc */
1934 .subdevice = 0xa70a,
1827 .driver_data = SAA7134_BOARD_AVERMEDIA_307, 1935 .driver_data = SAA7134_BOARD_AVERMEDIA_307,
1828 },{ 1936 },{
1829 .vendor = PCI_VENDOR_ID_PHILIPS, 1937 .vendor = PCI_VENDOR_ID_PHILIPS,
@@ -1844,6 +1952,26 @@ struct pci_device_id saa7134_pci_tbl[] = {
1844 .subvendor = 0x5168, 1952 .subvendor = 0x5168,
1845 .subdevice = 0x0306, 1953 .subdevice = 0x0306,
1846 .driver_data = SAA7134_BOARD_FLYDVBTDUO, 1954 .driver_data = SAA7134_BOARD_FLYDVBTDUO,
1955 },{
1956 .vendor = PCI_VENDOR_ID_PHILIPS,
1957 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
1958 .subvendor = 0x1461, /* Avermedia Technologies Inc */
1959 .subdevice = 0xf31f,
1960 .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM,
1961
1962 },{
1963 .vendor = PCI_VENDOR_ID_PHILIPS,
1964 .device = PCI_DEVICE_ID_PHILIPS_SAA7135,
1965 .subvendor = 0x1421,
1966 .subdevice = 0x0350, /* PCI version */
1967 .driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
1968
1969 },{
1970 .vendor = PCI_VENDOR_ID_PHILIPS,
1971 .device = PCI_DEVICE_ID_PHILIPS_SAA7135,
1972 .subvendor = 0x1421,
1973 .subdevice = 0x0370, /* cardbus version */
1974 .driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
1847 1975
1848 },{ 1976 },{
1849 /* --- boards without eeprom + subsystem ID --- */ 1977 /* --- boards without eeprom + subsystem ID --- */
@@ -1954,20 +2082,23 @@ int saa7134_board_init1(struct saa7134_dev *dev)
1954 dev->has_remote = 1; 2082 dev->has_remote = 1;
1955 board_flyvideo(dev); 2083 board_flyvideo(dev);
1956 break; 2084 break;
1957 case SAA7134_BOARD_FLYTVPLATINUM_FM: 2085 case SAA7134_BOARD_FLYTVPLATINUM_FM:
1958 case SAA7134_BOARD_CINERGY400: 2086 case SAA7134_BOARD_CINERGY400:
1959 case SAA7134_BOARD_CINERGY600: 2087 case SAA7134_BOARD_CINERGY600:
1960 case SAA7134_BOARD_CINERGY600_MK3: 2088 case SAA7134_BOARD_CINERGY600_MK3:
1961 case SAA7134_BOARD_ECS_TVP3XP: 2089 case SAA7134_BOARD_ECS_TVP3XP:
1962 case SAA7134_BOARD_ECS_TVP3XP_4CB5: 2090 case SAA7134_BOARD_ECS_TVP3XP_4CB5:
1963 case SAA7134_BOARD_MD2819: 2091 case SAA7134_BOARD_MD2819:
2092 case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
1964 case SAA7134_BOARD_AVERMEDIA_STUDIO_305: 2093 case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
1965 case SAA7134_BOARD_AVERMEDIA_305: 2094 case SAA7134_BOARD_AVERMEDIA_305:
2095 case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
1966 case SAA7134_BOARD_AVERMEDIA_307: 2096 case SAA7134_BOARD_AVERMEDIA_307:
2097 case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
1967// case SAA7134_BOARD_SABRENT_SBTTVFM: /* not finished yet */ 2098// case SAA7134_BOARD_SABRENT_SBTTVFM: /* not finished yet */
1968 case SAA7134_BOARD_VIDEOMATE_TV_PVR: 2099 case SAA7134_BOARD_VIDEOMATE_TV_PVR:
1969 dev->has_remote = 1; 2100 case SAA7134_BOARD_MANLI_MTV001:
1970 break; 2101 case SAA7134_BOARD_MANLI_MTV002:
1971 case SAA7134_BOARD_AVACSSMARTTV: 2102 case SAA7134_BOARD_AVACSSMARTTV:
1972 dev->has_remote = 1; 2103 dev->has_remote = 1;
1973 break; 2104 break;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index d506cafba8..f61ed1849a 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-core.c,v 1.28 2005/02/22 09:56:29 kraxel Exp $ 2 * $Id: saa7134-core.c,v 1.30 2005/05/22 19:23:39 nsh Exp $
3 * 3 *
4 * device driver for philips saa7134 based TV cards 4 * device driver for philips saa7134 based TV cards
5 * driver core 5 * driver core
@@ -316,7 +316,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
316 316
317int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) 317int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
318{ 318{
319 u32 *cpu; 319 __le32 *cpu;
320 dma_addr_t dma_addr; 320 dma_addr_t dma_addr;
321 321
322 cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); 322 cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
@@ -332,7 +332,7 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
332 struct scatterlist *list, unsigned int length, 332 struct scatterlist *list, unsigned int length,
333 unsigned int startpage) 333 unsigned int startpage)
334{ 334{
335 u32 *ptr; 335 __le32 *ptr;
336 unsigned int i,p; 336 unsigned int i,p;
337 337
338 BUG_ON(NULL == pt || NULL == pt->cpu); 338 BUG_ON(NULL == pt || NULL == pt->cpu);
@@ -340,7 +340,7 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
340 ptr = pt->cpu + startpage; 340 ptr = pt->cpu + startpage;
341 for (i = 0; i < length; i++, list++) 341 for (i = 0; i < length; i++, list++)
342 for (p = 0; p * 4096 < list->length; p++, ptr++) 342 for (p = 0; p * 4096 < list->length; p++, ptr++)
343 *ptr = sg_dma_address(list) - list->offset; 343 *ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
344 return 0; 344 return 0;
345} 345}
346 346
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index c2873ae029..aa8e2cf62d 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-dvb.c,v 1.12 2005/02/18 12:28:29 kraxel Exp $ 2 * $Id: saa7134-dvb.c,v 1.13 2005/06/12 04:19:19 mchehab Exp $
3 * 3 *
4 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 4 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
5 * 5 *
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index fa13573369..c85348d023 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-empress.c,v 1.10 2005/02/03 10:24:33 kraxel Exp $ 2 * $Id: saa7134-empress.c,v 1.11 2005/05/22 19:23:39 nsh Exp $
3 * 3 *
4 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 4 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
5 * 5 *
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 702bb63d98..b6f002e842 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-i2c.c,v 1.10 2005/01/24 17:37:23 kraxel Exp $ 2 * $Id: saa7134-i2c.c,v 1.11 2005/06/12 01:36:14 mchehab Exp $
3 * 3 *
4 * device driver for philips saa7134 based TV cards 4 * device driver for philips saa7134 based TV cards
5 * i2c interface support 5 * i2c interface support
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index ca50cf531f..aba2b9de60 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-input.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $ 2 * $Id: saa7134-input.c,v 1.19 2005/06/07 18:02:26 nsh Exp $
3 * 3 *
4 * handle saa7134 IR remotes via linux kernel input layer. 4 * handle saa7134 IR remotes via linux kernel input layer.
5 * 5 *
@@ -308,6 +308,102 @@ static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = {
308 [ 32 ] = KEY_LANGUAGE, 308 [ 32 ] = KEY_LANGUAGE,
309 [ 33 ] = KEY_SLEEP, 309 [ 33 ] = KEY_SLEEP,
310}; 310};
311
312/* Michael Tokarev <mjt@tls.msk.ru>
313 http://www.corpit.ru/mjt/beholdTV/remote_control.jpg
314 keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at
315 least, and probably other cards too.
316 The "ascii-art picture" below (in comments, first row
317 is the keycode in hex, and subsequent row(s) shows
318 the button labels (several variants when appropriate)
319 helps to descide which keycodes to assign to the buttons.
320 */
321static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = {
322
323 /* 0x1c 0x12 *
324 * FUNCTION POWER *
325 * FM (|) *
326 * */
327 [ 0x1c ] = KEY_RADIO, /*XXX*/
328 [ 0x12 ] = KEY_POWER,
329
330 /* 0x01 0x02 0x03 *
331 * 1 2 3 *
332 * *
333 * 0x04 0x05 0x06 *
334 * 4 5 6 *
335 * *
336 * 0x07 0x08 0x09 *
337 * 7 8 9 *
338 * */
339 [ 0x01 ] = KEY_KP1,
340 [ 0x02 ] = KEY_KP2,
341 [ 0x03 ] = KEY_KP3,
342 [ 0x04 ] = KEY_KP4,
343 [ 0x05 ] = KEY_KP5,
344 [ 0x06 ] = KEY_KP6,
345 [ 0x07 ] = KEY_KP7,
346 [ 0x08 ] = KEY_KP8,
347 [ 0x09 ] = KEY_KP9,
348
349 /* 0x0a 0x00 0x17 *
350 * RECALL 0 +100 *
351 * PLUS *
352 * */
353 [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */
354 [ 0x00 ] = KEY_KP0,
355 [ 0x17 ] = KEY_DIGITS, /*XXX*/
356
357 /* 0x14 0x10 *
358 * MENU INFO *
359 * OSD */
360 [ 0x14 ] = KEY_MENU,
361 [ 0x10 ] = KEY_INFO,
362
363 /* 0x0b *
364 * Up *
365 * *
366 * 0x18 0x16 0x0c *
367 * Left Ok Right *
368 * *
369 * 0x015 *
370 * Down *
371 * */
372 [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */
373 [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */
374 [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */
375 [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */
376 [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */
377
378 /* 0x11 0x0d *
379 * TV/AV MODE *
380 * SOURCE STEREO *
381 * */
382 [ 0x11 ] = KEY_TV, /*XXX*/
383 [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */
384
385 /* 0x0f 0x1b 0x1a *
386 * AUDIO Vol+ Chan+ *
387 * TIMESHIFT??? *
388 * *
389 * 0x0e 0x1f 0x1e *
390 * SLEEP Vol- Chan- *
391 * */
392 [ 0x0f ] = KEY_AUDIO,
393 [ 0x1b ] = KEY_VOLUMEUP,
394 [ 0x1a ] = KEY_CHANNELUP,
395 [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */
396 [ 0x1f ] = KEY_VOLUMEDOWN,
397 [ 0x1e ] = KEY_CHANNELDOWN,
398
399 /* 0x13 0x19 *
400 * MUTE SNAPSHOT*
401 * */
402 [ 0x13 ] = KEY_MUTE,
403 [ 0x19 ] = KEY_RECORD, /*XXX*/
404
405 // 0x1d unused ?
406};
311/* ---------------------------------------------------------------------- */ 407/* ---------------------------------------------------------------------- */
312 408
313static int build_key(struct saa7134_dev *dev) 409static int build_key(struct saa7134_dev *dev)
@@ -379,7 +475,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
379 switch (dev->board) { 475 switch (dev->board) {
380 case SAA7134_BOARD_FLYVIDEO2000: 476 case SAA7134_BOARD_FLYVIDEO2000:
381 case SAA7134_BOARD_FLYVIDEO3000: 477 case SAA7134_BOARD_FLYVIDEO3000:
382 case SAA7134_BOARD_FLYTVPLATINUM_FM: 478 case SAA7134_BOARD_FLYTVPLATINUM_FM:
383 ir_codes = flyvideo_codes; 479 ir_codes = flyvideo_codes;
384 mask_keycode = 0xEC00000; 480 mask_keycode = 0xEC00000;
385 mask_keydown = 0x0040000; 481 mask_keydown = 0x0040000;
@@ -405,8 +501,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
405 polling = 50; // ms 501 polling = 50; // ms
406 break; 502 break;
407 case SAA7134_BOARD_MD2819: 503 case SAA7134_BOARD_MD2819:
504 case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
408 case SAA7134_BOARD_AVERMEDIA_305: 505 case SAA7134_BOARD_AVERMEDIA_305:
409 case SAA7134_BOARD_AVERMEDIA_307: 506 case SAA7134_BOARD_AVERMEDIA_307:
507 case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
508 case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
509 case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
410 ir_codes = md2819_codes; 510 ir_codes = md2819_codes;
411 mask_keycode = 0x0007C8; 511 mask_keycode = 0x0007C8;
412 mask_keydown = 0x000010; 512 mask_keydown = 0x000010;
@@ -415,6 +515,14 @@ int saa7134_input_init1(struct saa7134_dev *dev)
415 saa_setb(SAA7134_GPIO_GPMODE0, 0x4); 515 saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
416 saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); 516 saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
417 break; 517 break;
518 case SAA7134_BOARD_MANLI_MTV001:
519 case SAA7134_BOARD_MANLI_MTV002:
520 ir_codes = manli_codes;
521 mask_keycode = 0x001f00;
522 mask_keyup = 0x004000;
523 mask_keydown = 0x002000;
524 polling = 50; // ms
525 break;
418 case SAA7134_BOARD_VIDEOMATE_TV_PVR: 526 case SAA7134_BOARD_VIDEOMATE_TV_PVR:
419 ir_codes = videomate_tv_pvr_codes; 527 ir_codes = videomate_tv_pvr_codes;
420 mask_keycode = 0x00003F; 528 mask_keycode = 0x00003F;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 6b6a643bf1..8173290462 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-oss.c,v 1.13 2004/12/10 12:33:39 kraxel Exp $ 2 * $Id: saa7134-oss.c,v 1.14 2005/05/18 22:45:16 hhackmann Exp $
3 * 3 *
4 * device driver for philips saa7134 based TV cards 4 * device driver for philips saa7134 based TV cards
5 * oss dsp interface 5 * oss dsp interface
@@ -49,7 +49,6 @@ MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)");
49 49
50static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) 50static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
51{ 51{
52 blksize &= ~0xff;
53 if (blksize < 0x100) 52 if (blksize < 0x100)
54 blksize = 0x100; 53 blksize = 0x100;
55 if (blksize > 0x10000) 54 if (blksize > 0x10000)
@@ -57,8 +56,6 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
57 56
58 if (blocks < 2) 57 if (blocks < 2)
59 blocks = 2; 58 blocks = 2;
60 while ((blksize * blocks) & ~PAGE_MASK)
61 blocks++;
62 if ((blksize * blocks) > 1024*1024) 59 if ((blksize * blocks) > 1024*1024)
63 blocks = 1024*1024 / blksize; 60 blocks = 1024*1024 / blksize;
64 61
@@ -79,7 +76,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
79 BUG(); 76 BUG();
80 videobuf_dma_init(&dev->oss.dma); 77 videobuf_dma_init(&dev->oss.dma);
81 err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, 78 err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE,
82 dev->oss.bufsize >> PAGE_SHIFT); 79 (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
83 if (0 != err) 80 if (0 != err)
84 return err; 81 return err;
85 return 0; 82 return 0;
@@ -163,10 +160,11 @@ static int dsp_rec_start(struct saa7134_dev *dev)
163 fmt |= 0x04; 160 fmt |= 0x04;
164 fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80; 161 fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
165 162
166 saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff)); 163 saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff));
167 saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >> 8); 164 saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8);
168 saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16); 165 saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16);
169 saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); 166 saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
167
170 break; 168 break;
171 case PCI_DEVICE_ID_PHILIPS_SAA7133: 169 case PCI_DEVICE_ID_PHILIPS_SAA7133:
172 case PCI_DEVICE_ID_PHILIPS_SAA7135: 170 case PCI_DEVICE_ID_PHILIPS_SAA7135:
@@ -817,7 +815,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
817 reg = SAA7134_RS_BA1(6); 815 reg = SAA7134_RS_BA1(6);
818 } else { 816 } else {
819 /* even */ 817 /* even */
820 if (0 == (dev->oss.dma_blk & 0x00)) 818 if (1 == (dev->oss.dma_blk & 0x01))
821 reg = SAA7134_RS_BA2(6); 819 reg = SAA7134_RS_BA2(6);
822 } 820 }
823 if (0 == reg) { 821 if (0 == reg) {
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index ecac13c006..3617e7f7a4 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-tvaudio.c,v 1.22 2005/01/07 13:11:19 kraxel Exp $ 2 * $Id: saa7134-tvaudio.c,v 1.25 2005/06/07 19:00:38 nsh Exp $
3 * 3 *
4 * device driver for philips saa7134 based TV cards 4 * device driver for philips saa7134 based TV cards
5 * tv audio decoder (fm stereo, nicam, ...) 5 * tv audio decoder (fm stereo, nicam, ...)
@@ -181,7 +181,8 @@ static void tvaudio_init(struct saa7134_dev *dev)
181 saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff); 181 saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff);
182 saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff); 182 saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff);
183 saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff); 183 saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff);
184 saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01); 184 // frame locked audio was reported not to be reliable
185 saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x02);
185 186
186 saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14); 187 saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14);
187 saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50); 188 saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50);
@@ -250,6 +251,11 @@ static void mute_input_7134(struct saa7134_dev *dev)
250 saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel); 251 saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel);
251 saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics); 252 saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics);
252 saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs); 253 saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs);
254 // for oss, we need to change the clock configuration
255 if (in->amux == TV)
256 saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00);
257 else
258 saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x01);
253 259
254 /* switch gpio-connected external audio mux */ 260 /* switch gpio-connected external audio mux */
255 if (0 == card(dev).gpiomask) 261 if (0 == card(dev).gpiomask)
@@ -439,16 +445,15 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au
439 nicam = saa_readb(SAA7134_NICAM_STATUS); 445 nicam = saa_readb(SAA7134_NICAM_STATUS);
440 dprintk("getstereo: nicam=0x%x\n",nicam); 446 dprintk("getstereo: nicam=0x%x\n",nicam);
441 switch (nicam & 0x0b) { 447 switch (nicam & 0x0b) {
448 case 0x08:
449 retval = V4L2_TUNER_SUB_MONO;
450 break;
442 case 0x09: 451 case 0x09:
443 retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 452 retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
444 break; 453 break;
445 case 0x0a: 454 case 0x0a:
446 retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; 455 retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
447 break; 456 break;
448 case 0x08:
449 default:
450 retval = V4L2_TUNER_SUB_MONO;
451 break;
452 } 457 }
453 break; 458 break;
454 } 459 }
@@ -572,14 +577,14 @@ static int tvaudio_thread(void *data)
572 } else if (0 != dev->last_carrier) { 577 } else if (0 != dev->last_carrier) {
573 /* no carrier -- try last detected one as fallback */ 578 /* no carrier -- try last detected one as fallback */
574 carrier = dev->last_carrier; 579 carrier = dev->last_carrier;
575 printk(KERN_WARNING "%s/audio: audio carrier scan failed, " 580 dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, "
576 "using %d.%03d MHz [last detected]\n", 581 "using %d.%03d MHz [last detected]\n",
577 dev->name, carrier/1000, carrier%1000); 582 dev->name, carrier/1000, carrier%1000);
578 583
579 } else { 584 } else {
580 /* no carrier + no fallback -- use default */ 585 /* no carrier + no fallback -- use default */
581 carrier = default_carrier; 586 carrier = default_carrier;
582 printk(KERN_WARNING "%s/audio: audio carrier scan failed, " 587 dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, "
583 "using %d.%03d MHz [default]\n", 588 "using %d.%03d MHz [default]\n",
584 dev->name, carrier/1000, carrier%1000); 589 dev->name, carrier/1000, carrier%1000);
585 } 590 }
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index 86954cc7c3..3c33c591cc 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-vbi.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $ 2 * $Id: saa7134-vbi.c,v 1.7 2005/05/24 23:13:06 nsh Exp $
3 * 3 *
4 * device driver for philips saa7134 based TV cards 4 * device driver for philips saa7134 based TV cards
5 * video4linux video interface 5 * video4linux video interface
@@ -60,10 +60,10 @@ static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf,
60 saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start >> 8); 60 saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start >> 8);
61 saa_writeb(SAA7134_VBI_H_STOP1(task), norm->h_stop & 0xff); 61 saa_writeb(SAA7134_VBI_H_STOP1(task), norm->h_stop & 0xff);
62 saa_writeb(SAA7134_VBI_H_STOP2(task), norm->h_stop >> 8); 62 saa_writeb(SAA7134_VBI_H_STOP2(task), norm->h_stop >> 8);
63 saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start & 0xff); 63 saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 & 0xff);
64 saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start >> 8); 64 saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8);
65 saa_writeb(SAA7134_VBI_V_STOP1(task), norm->vbi_v_stop & 0xff); 65 saa_writeb(SAA7134_VBI_V_STOP1(task), norm->vbi_v_stop_0 & 0xff);
66 saa_writeb(SAA7134_VBI_V_STOP2(task), norm->vbi_v_stop >> 8); 66 saa_writeb(SAA7134_VBI_V_STOP2(task), norm->vbi_v_stop_0 >> 8);
67 67
68 saa_writeb(SAA7134_VBI_H_SCALE_INC1(task), VBI_SCALE & 0xff); 68 saa_writeb(SAA7134_VBI_H_SCALE_INC1(task), VBI_SCALE & 0xff);
69 saa_writeb(SAA7134_VBI_H_SCALE_INC2(task), VBI_SCALE >> 8); 69 saa_writeb(SAA7134_VBI_H_SCALE_INC2(task), VBI_SCALE >> 8);
@@ -127,7 +127,7 @@ static int buffer_prepare(struct videobuf_queue *q,
127 unsigned int lines, llength, size; 127 unsigned int lines, llength, size;
128 int err; 128 int err;
129 129
130 lines = norm->vbi_v_stop - norm->vbi_v_start +1; 130 lines = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
131 if (lines > VBI_LINE_COUNT) 131 if (lines > VBI_LINE_COUNT)
132 lines = VBI_LINE_COUNT; 132 lines = VBI_LINE_COUNT;
133#if 1 133#if 1
@@ -177,7 +177,7 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
177 struct saa7134_dev *dev = fh->dev; 177 struct saa7134_dev *dev = fh->dev;
178 int llength,lines; 178 int llength,lines;
179 179
180 lines = dev->tvnorm->vbi_v_stop - dev->tvnorm->vbi_v_start +1; 180 lines = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1;
181#if 1 181#if 1
182 llength = VBI_LINE_LENGTH; 182 llength = VBI_LINE_LENGTH;
183#else 183#else
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 5d66060026..c0a2ee5205 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134-video.c,v 1.28 2005/02/15 15:59:35 kraxel Exp $ 2 * $Id: saa7134-video.c,v 1.30 2005/06/07 19:00:38 nsh Exp $
3 * 3 *
4 * device driver for philips saa7134 based TV cards 4 * device driver for philips saa7134 based TV cards
5 * video4linux video interface 5 * video4linux video interface
@@ -31,8 +31,6 @@
31#include "saa7134-reg.h" 31#include "saa7134-reg.h"
32#include "saa7134.h" 32#include "saa7134.h"
33 33
34#define V4L2_I2C_CLIENTS 1
35
36/* ------------------------------------------------------------------ */ 34/* ------------------------------------------------------------------ */
37 35
38static unsigned int video_debug = 0; 36static unsigned int video_debug = 0;
@@ -158,18 +156,20 @@ static struct saa7134_format formats[] = {
158 .h_stop = 719, \ 156 .h_stop = 719, \
159 .video_v_start = 24, \ 157 .video_v_start = 24, \
160 .video_v_stop = 311, \ 158 .video_v_stop = 311, \
161 .vbi_v_start = 7, \ 159 .vbi_v_start_0 = 7, \
162 .vbi_v_stop = 22, \ 160 .vbi_v_stop_0 = 22, \
161 .vbi_v_start_1 = 319, \
163 .src_timing = 4 162 .src_timing = 4
164 163
165#define NORM_525_60 \ 164#define NORM_525_60 \
166 .h_start = 0, \ 165 .h_start = 0, \
167 .h_stop = 703, \ 166 .h_stop = 703, \
168 .video_v_start = 22, \ 167 .video_v_start = 23, \
169 .video_v_stop = 22+239, \ 168 .video_v_stop = 262, \
170 .vbi_v_start = 10, /* FIXME */ \ 169 .vbi_v_start_0 = 10, \
171 .vbi_v_stop = 21, /* FIXME */ \ 170 .vbi_v_stop_0 = 21, \
172 .src_timing = 1 171 .vbi_v_start_1 = 273, \
172 .src_timing = 7
173 173
174static struct saa7134_tvnorm tvnorms[] = { 174static struct saa7134_tvnorm tvnorms[] = {
175 { 175 {
@@ -274,11 +274,12 @@ static struct saa7134_tvnorm tvnorms[] = {
274 274
275 .h_start = 0, 275 .h_start = 0,
276 .h_stop = 719, 276 .h_stop = 719,
277 .video_v_start = 22, 277 .video_v_start = 23,
278 .video_v_stop = 22+239, 278 .video_v_stop = 262,
279 .vbi_v_start = 10, /* FIXME */ 279 .vbi_v_start_0 = 10,
280 .vbi_v_stop = 21, /* FIXME */ 280 .vbi_v_stop_0 = 21,
281 .src_timing = 1, 281 .vbi_v_start_1 = 273,
282 .src_timing = 7,
282 283
283 .sync_control = 0x18, 284 .sync_control = 0x18,
284 .luma_control = 0x40, 285 .luma_control = 0x40,
@@ -335,8 +336,8 @@ static const struct v4l2_queryctrl video_ctrls[] = {
335 .default_value = 0, 336 .default_value = 0,
336 .type = V4L2_CTRL_TYPE_INTEGER, 337 .type = V4L2_CTRL_TYPE_INTEGER,
337 },{ 338 },{
338 .id = V4L2_CID_VFLIP, 339 .id = V4L2_CID_HFLIP,
339 .name = "vertical flip", 340 .name = "Mirror",
340 .minimum = 0, 341 .minimum = 0,
341 .maximum = 1, 342 .maximum = 1,
342 .type = V4L2_CTRL_TYPE_BOOLEAN, 343 .type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -482,7 +483,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
482 dev->crop_bounds.width = norm->h_stop - norm->h_start +1; 483 dev->crop_bounds.width = norm->h_stop - norm->h_start +1;
483 dev->crop_defrect.width = norm->h_stop - norm->h_start +1; 484 dev->crop_defrect.width = norm->h_stop - norm->h_start +1;
484 485
485 dev->crop_bounds.top = (norm->vbi_v_stop+1)*2; 486 dev->crop_bounds.top = (norm->vbi_v_stop_0+1)*2;
486 dev->crop_defrect.top = norm->video_v_start*2; 487 dev->crop_defrect.top = norm->video_v_start*2;
487 dev->crop_bounds.height = ((norm->id & V4L2_STD_525_60) ? 524 : 624) 488 dev->crop_bounds.height = ((norm->id & V4L2_STD_525_60) ? 524 : 624)
488 - dev->crop_bounds.top; 489 - dev->crop_bounds.top;
@@ -521,22 +522,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
521 saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40); 522 saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40);
522 saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80); 523 saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
523 524
524#ifdef V4L2_I2C_CLIENTS
525 saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id); 525 saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id);
526#else
527 {
528 /* pass down info to the i2c chips (v4l1) */
529 struct video_channel c;
530 memset(&c,0,sizeof(c));
531 c.channel = dev->ctl_input;
532 c.norm = VIDEO_MODE_PAL;
533 if (norm->id & V4L2_STD_NTSC)
534 c.norm = VIDEO_MODE_NTSC;
535 if (norm->id & V4L2_STD_SECAM)
536 c.norm = VIDEO_MODE_SECAM;
537 saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c);
538 }
539#endif
540} 526}
541 527
542static void video_mux(struct saa7134_dev *dev, int input) 528static void video_mux(struct saa7134_dev *dev, int input)
@@ -1064,7 +1050,7 @@ static int get_control(struct saa7134_dev *dev, struct v4l2_control *c)
1064 case V4L2_CID_PRIVATE_INVERT: 1050 case V4L2_CID_PRIVATE_INVERT:
1065 c->value = dev->ctl_invert; 1051 c->value = dev->ctl_invert;
1066 break; 1052 break;
1067 case V4L2_CID_VFLIP: 1053 case V4L2_CID_HFLIP:
1068 c->value = dev->ctl_mirror; 1054 c->value = dev->ctl_mirror;
1069 break; 1055 break;
1070 case V4L2_CID_PRIVATE_Y_EVEN: 1056 case V4L2_CID_PRIVATE_Y_EVEN:
@@ -1139,7 +1125,7 @@ static int set_control(struct saa7134_dev *dev, struct saa7134_fh *fh,
1139 saa_writeb(SAA7134_DEC_CHROMA_SATURATION, 1125 saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
1140 dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation); 1126 dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
1141 break; 1127 break;
1142 case V4L2_CID_VFLIP: 1128 case V4L2_CID_HFLIP:
1143 dev->ctl_mirror = c->value; 1129 dev->ctl_mirror = c->value;
1144 restart_overlay = 1; 1130 restart_overlay = 1;
1145 break; 1131 break;
@@ -1407,9 +1393,9 @@ static void saa7134_vbi_fmt(struct saa7134_dev *dev, struct v4l2_format *f)
1407 f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */; 1393 f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
1408 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; 1394 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1409 f->fmt.vbi.offset = 64 * 4; 1395 f->fmt.vbi.offset = 64 * 4;
1410 f->fmt.vbi.start[0] = norm->vbi_v_start; 1396 f->fmt.vbi.start[0] = norm->vbi_v_start_0;
1411 f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1; 1397 f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
1412 f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start +1; 1398 f->fmt.vbi.start[1] = norm->vbi_v_start_1;
1413 f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; 1399 f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
1414 f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */ 1400 f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */
1415 1401
@@ -1880,11 +1866,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
1880 return -EINVAL; 1866 return -EINVAL;
1881 down(&dev->lock); 1867 down(&dev->lock);
1882 dev->ctl_freq = f->frequency; 1868 dev->ctl_freq = f->frequency;
1883#ifdef V4L2_I2C_CLIENTS 1869
1884 saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f); 1870 saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f);
1885#else 1871
1886 saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&dev->ctl_freq);
1887#endif
1888 saa7134_tvaudio_do_scan(dev); 1872 saa7134_tvaudio_do_scan(dev);
1889 up(&dev->lock); 1873 up(&dev->lock);
1890 return 0; 1874 return 0;
@@ -2139,16 +2123,19 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
2139 t->rangelow = (int)(65*16); 2123 t->rangelow = (int)(65*16);
2140 t->rangehigh = (int)(108*16); 2124 t->rangehigh = (int)(108*16);
2141 2125
2142#ifdef V4L2_I2C_CLIENTS 2126 saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
2143 saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,t); 2127
2144#else 2128 return 0;
2145 { 2129 }
2146 struct video_tuner vt; 2130 case VIDIOC_S_TUNER:
2147 memset(&vt,0,sizeof(vt)); 2131 {
2148 saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt); 2132 struct v4l2_tuner *t = arg;
2149 t->signal = vt.signal; 2133
2150 } 2134 if (0 != t->index)
2151#endif 2135 return -EINVAL;
2136
2137 saa7134_i2c_call_clients(dev,VIDIOC_S_TUNER,t);
2138
2152 return 0; 2139 return 0;
2153 } 2140 }
2154 case VIDIOC_ENUMINPUT: 2141 case VIDIOC_ENUMINPUT:
@@ -2182,7 +2169,6 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
2182 return 0; 2169 return 0;
2183 } 2170 }
2184 case VIDIOC_S_AUDIO: 2171 case VIDIOC_S_AUDIO:
2185 case VIDIOC_S_TUNER:
2186 case VIDIOC_S_INPUT: 2172 case VIDIOC_S_INPUT:
2187 case VIDIOC_S_STD: 2173 case VIDIOC_S_STD:
2188 return 0; 2174 return 0;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index ac90a98532..d6b1c0d4d0 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: saa7134.h,v 1.38 2005/03/07 12:01:51 kraxel Exp $ 2 * $Id: saa7134.h,v 1.41 2005/06/07 18:02:26 nsh Exp $
3 * 3 *
4 * v4l2 device driver for philips saa7134 based TV cards 4 * v4l2 device driver for philips saa7134 based TV cards
5 * 5 *
@@ -21,7 +21,7 @@
21 */ 21 */
22 22
23#include <linux/version.h> 23#include <linux/version.h>
24#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,12) 24#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13)
25 25
26#include <linux/pci.h> 26#include <linux/pci.h>
27#include <linux/i2c.h> 27#include <linux/i2c.h>
@@ -91,9 +91,10 @@ struct saa7134_tvnorm {
91 unsigned int h_stop; 91 unsigned int h_stop;
92 unsigned int video_v_start; 92 unsigned int video_v_start;
93 unsigned int video_v_stop; 93 unsigned int video_v_stop;
94 unsigned int vbi_v_start; 94 unsigned int vbi_v_start_0;
95 unsigned int vbi_v_stop; 95 unsigned int vbi_v_stop_0;
96 unsigned int src_timing; 96 unsigned int src_timing;
97 unsigned int vbi_v_start_1;
97}; 98};
98 99
99struct saa7134_tvaudio { 100struct saa7134_tvaudio {
@@ -167,7 +168,7 @@ struct saa7134_format {
167#define SAA7134_BOARD_SABRENT_SBTTVFM 42 168#define SAA7134_BOARD_SABRENT_SBTTVFM 42
168#define SAA7134_BOARD_ZOLID_XPERT_TV7134 43 169#define SAA7134_BOARD_ZOLID_XPERT_TV7134 43
169#define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44 170#define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44
170#define SAA7134_BOARD_AVERMEDIA_307 45 171#define SAA7134_BOARD_AVERMEDIA_STUDIO_307 45
171#define SAA7134_BOARD_AVERMEDIA_CARDBUS 46 172#define SAA7134_BOARD_AVERMEDIA_CARDBUS 46
172#define SAA7134_BOARD_CINERGY400_CARDBUS 47 173#define SAA7134_BOARD_CINERGY400_CARDBUS 47
173#define SAA7134_BOARD_CINERGY600_MK3 48 174#define SAA7134_BOARD_CINERGY600_MK3 48
@@ -178,6 +179,10 @@ struct saa7134_format {
178#define SAA7135_BOARD_ASUSTeK_TVFM7135 53 179#define SAA7135_BOARD_ASUSTeK_TVFM7135 53
179#define SAA7134_BOARD_FLYTVPLATINUM_FM 54 180#define SAA7134_BOARD_FLYTVPLATINUM_FM 54
180#define SAA7134_BOARD_FLYDVBTDUO 55 181#define SAA7134_BOARD_FLYDVBTDUO 55
182#define SAA7134_BOARD_AVERMEDIA_307 56
183#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
184#define SAA7134_BOARD_ADS_INSTANT_TV 58
185#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
181 186
182#define SAA7134_MAXBOARDS 8 187#define SAA7134_MAXBOARDS 8
183#define SAA7134_INPUT_MAX 8 188#define SAA7134_INPUT_MAX 8
@@ -241,7 +246,7 @@ struct saa7134_dma;
241/* saa7134 page table */ 246/* saa7134 page table */
242struct saa7134_pgtable { 247struct saa7134_pgtable {
243 unsigned int size; 248 unsigned int size;
244 u32 *cpu; 249 __le32 *cpu;
245 dma_addr_t dma; 250 dma_addr_t dma;
246}; 251};
247 252
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 7e6e6dd966..39773633cc 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -53,6 +53,7 @@ struct tda9887 {
53 unsigned int config; 53 unsigned int config;
54 unsigned int pinnacle_id; 54 unsigned int pinnacle_id;
55 unsigned int using_v4l2; 55 unsigned int using_v4l2;
56 unsigned int radio_mode;
56}; 57};
57 58
58struct tvnorm { 59struct tvnorm {
@@ -212,12 +213,22 @@ static struct tvnorm tvnorms[] = {
212 } 213 }
213}; 214};
214 215
215static struct tvnorm radio = { 216static struct tvnorm radio_stereo = {
216 .name = "radio", 217 .name = "Radio Stereo",
218 .b = ( cFmRadio |
219 cQSS ),
220 .c = ( cDeemphasisOFF |
221 cAudioGain6 ),
222 .e = ( cAudioIF_5_5 |
223 cRadioIF_38_90 ),
224};
225
226static struct tvnorm radio_mono = {
227 .name = "Radio Mono",
217 .b = ( cFmRadio | 228 .b = ( cFmRadio |
218 cQSS ), 229 cQSS ),
219 .c = ( cDeemphasisON | 230 .c = ( cDeemphasisON |
220 cDeemphasis50 ), 231 cDeemphasis50),
221 .e = ( cAudioIF_5_5 | 232 .e = ( cAudioIF_5_5 |
222 cRadioIF_38_90 ), 233 cRadioIF_38_90 ),
223}; 234};
@@ -354,7 +365,10 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
354 int i; 365 int i;
355 366
356 if (t->radio) { 367 if (t->radio) {
357 norm = &radio; 368 if (t->radio_mode == V4L2_TUNER_MODE_MONO)
369 norm = &radio_mono;
370 else
371 norm = &radio_stereo;
358 } else { 372 } else {
359 for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { 373 for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
360 if (tvnorms[i].std & t->std) { 374 if (tvnorms[i].std & t->std) {
@@ -545,11 +559,14 @@ static int tda9887_configure(struct tda9887 *t)
545 559
546 memset(buf,0,sizeof(buf)); 560 memset(buf,0,sizeof(buf));
547 tda9887_set_tvnorm(t,buf); 561 tda9887_set_tvnorm(t,buf);
562
548 buf[1] |= cOutputPort1Inactive; 563 buf[1] |= cOutputPort1Inactive;
549 buf[1] |= cOutputPort2Inactive; 564 buf[1] |= cOutputPort2Inactive;
565
550 if (UNSET != t->pinnacle_id) { 566 if (UNSET != t->pinnacle_id) {
551 tda9887_set_pinnacle(t,buf); 567 tda9887_set_pinnacle(t,buf);
552 } 568 }
569
553 tda9887_set_config(t,buf); 570 tda9887_set_config(t,buf);
554 tda9887_set_insmod(t,buf); 571 tda9887_set_insmod(t,buf);
555 572
@@ -592,9 +609,12 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
592 if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) 609 if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
593 return -ENOMEM; 610 return -ENOMEM;
594 memset(t,0,sizeof(*t)); 611 memset(t,0,sizeof(*t));
612
595 t->client = client_template; 613 t->client = client_template;
596 t->std = 0; 614 t->std = 0;
597 t->pinnacle_id = UNSET; 615 t->pinnacle_id = UNSET;
616 t->radio_mode = V4L2_TUNER_MODE_STEREO;
617
598 i2c_set_clientdata(&t->client, t); 618 i2c_set_clientdata(&t->client, t);
599 i2c_attach_client(&t->client); 619 i2c_attach_client(&t->client);
600 620
@@ -733,6 +753,16 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
733 } 753 }
734 break; 754 break;
735 } 755 }
756 case VIDIOC_S_TUNER:
757 {
758 struct v4l2_tuner* tuner = arg;
759
760 if (t->radio) {
761 t->radio_mode = tuner->audmode;
762 tda9887_configure (t);
763 }
764 break;
765 }
736 default: 766 default:
737 /* nothing */ 767 /* nothing */
738 break; 768 break;
@@ -740,7 +770,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
740 return 0; 770 return 0;
741} 771}
742 772
743static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level) 773static int tda9887_suspend(struct device * dev, u32 state, u32 level)
744{ 774{
745 dprintk("tda9887: suspend\n"); 775 dprintk("tda9887: suspend\n");
746 return 0; 776 return 0;
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 81882ddab8..eaabfc8587 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: tuner-core.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $ 2 * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $
3 * 3 *
4 * i2c tv tuner chip device driver 4 * i2c tv tuner chip device driver
5 * core core, i.e. kernel interfaces, registering and so on 5 * core core, i.e. kernel interfaces, registering and so on
@@ -23,6 +23,11 @@
23#include <media/tuner.h> 23#include <media/tuner.h>
24#include <media/audiochip.h> 24#include <media/audiochip.h>
25 25
26/*
27 * comment line bellow to return to old behavor, where only one I2C device is supported
28 */
29#define CONFIG_TUNER_MULTI_I2C /**/
30
26#define UNSET (-1U) 31#define UNSET (-1U)
27 32
28/* standard i2c insmod options */ 33/* standard i2c insmod options */
@@ -53,13 +58,16 @@ MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
53MODULE_LICENSE("GPL"); 58MODULE_LICENSE("GPL");
54 59
55static int this_adap; 60static int this_adap;
61#ifdef CONFIG_TUNER_MULTI_I2C
62static unsigned short first_tuner, tv_tuner, radio_tuner;
63#endif
56 64
57static struct i2c_driver driver; 65static struct i2c_driver driver;
58static struct i2c_client client_template; 66static struct i2c_client client_template;
59 67
60/* ---------------------------------------------------------------------- */ 68/* ---------------------------------------------------------------------- */
61 69
62// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz 70/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */
63static void set_tv_freq(struct i2c_client *c, unsigned int freq) 71static void set_tv_freq(struct i2c_client *c, unsigned int freq)
64{ 72{
65 struct tuner *t = i2c_get_clientdata(c); 73 struct tuner *t = i2c_get_clientdata(c);
@@ -73,14 +81,26 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
73 return; 81 return;
74 } 82 }
75 if (freq < tv_range[0]*16 || freq > tv_range[1]*16) { 83 if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
76 /* FIXME: better do that chip-specific, but 84
77 right now we don't have that in the config 85 if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
78 struct and this way is still better than no 86 /* V4L2_TUNER_CAP_LOW frequency */
79 check at all */ 87
80 tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n", 88 tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n");
81 freq/16,freq%16*100/16,tv_range[0],tv_range[1]); 89
82 return; 90 t->tv_freq(c,freq>>10);
91
92 return;
93 } else {
94 /* FIXME: better do that chip-specific, but
95 right now we don't have that in the config
96 struct and this way is still better than no
97 check at all */
98 tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
99 freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
100 return;
101 }
83 } 102 }
103 tuner_dbg("62.5 Khz freq step selected for TV.\n");
84 t->tv_freq(c,freq); 104 t->tv_freq(c,freq);
85} 105}
86 106
@@ -97,11 +117,29 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
97 return; 117 return;
98 } 118 }
99 if (freq < radio_range[0]*16 || freq > radio_range[1]*16) { 119 if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
100 tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n", 120 if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
121 /* V4L2_TUNER_CAP_LOW frequency */
122 if (t->type == TUNER_TEA5767) {
123 tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
124 t->radio_freq(c,freq>>10);
125 return;
126 }
127
128 tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n");
129
130 tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
131
132 t->radio_freq(c,freq>>10);
133 return;
134
135 } else {
136 tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
101 freq/16,freq%16*100/16, 137 freq/16,freq%16*100/16,
102 radio_range[0],radio_range[1]); 138 radio_range[0],radio_range[1]);
103 return; 139 return;
140 }
104 } 141 }
142 tuner_dbg("62.5 Khz freq step selected for Radio.\n");
105 t->radio_freq(c,freq); 143 t->radio_freq(c,freq);
106} 144}
107 145
@@ -129,8 +167,9 @@ static void set_type(struct i2c_client *c, unsigned int type)
129{ 167{
130 struct tuner *t = i2c_get_clientdata(c); 168 struct tuner *t = i2c_get_clientdata(c);
131 169
170 tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
132 /* sanity check */ 171 /* sanity check */
133 if (type == UNSET || type == TUNER_ABSENT) 172 if (type == UNSET || type == TUNER_ABSENT)
134 return; 173 return;
135 if (type >= tuner_count) 174 if (type >= tuner_count)
136 return; 175 return;
@@ -145,6 +184,7 @@ static void set_type(struct i2c_client *c, unsigned int type)
145 return; 184 return;
146 185
147 t->initialized = 1; 186 t->initialized = 1;
187
148 t->type = type; 188 t->type = type;
149 switch (t->type) { 189 switch (t->type) {
150 case TUNER_MT2032: 190 case TUNER_MT2032:
@@ -159,6 +199,53 @@ static void set_type(struct i2c_client *c, unsigned int type)
159 } 199 }
160} 200}
161 201
202#ifdef CONFIG_TUNER_MULTI_I2C
203#define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \
204 return 0; } else \
205 tuner_info ("Cmd %s accepted to "tun"\n",cmd);
206#define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \
207 CHECK_ADDR(radio_tuner,cmd,"radio") } else \
208 { CHECK_ADDR(tv_tuner,cmd,"TV"); }
209#else
210#define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd);
211#define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd);
212#endif
213
214#ifdef CONFIG_TUNER_MULTI_I2C
215
216static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
217{
218 /* ADDR_UNSET defaults to first available tuner */
219 if ( tun_addr->addr == ADDR_UNSET ) {
220 if (first_tuner != c->addr)
221 return;
222 switch (tun_addr->v4l2_tuner) {
223 case V4L2_TUNER_RADIO:
224 radio_tuner=c->addr;
225 break;
226 default:
227 tv_tuner=c->addr;
228 break;
229 }
230 } else {
231 /* Sets tuner to its configured value */
232 switch (tun_addr->v4l2_tuner) {
233 case V4L2_TUNER_RADIO:
234 radio_tuner=tun_addr->addr;
235 if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type);
236 return;
237 default:
238 tv_tuner=tun_addr->addr;
239 if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type);
240 return;
241 }
242 }
243 set_type(c,tun_addr->type);
244}
245#else
246#define set_addr(c,tun_addr) set_type(c,(tun_addr)->type)
247#endif
248
162static char pal[] = "-"; 249static char pal[] = "-";
163module_param_string(pal, pal, sizeof(pal), 0644); 250module_param_string(pal, pal, sizeof(pal), 0644);
164 251
@@ -197,8 +284,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
197{ 284{
198 struct tuner *t; 285 struct tuner *t;
199 286
287#ifndef CONFIG_TUNER_MULTI_I2C
200 if (this_adap > 0) 288 if (this_adap > 0)
201 return -1; 289 return -1;
290#else
291 /* by default, first I2C card is both tv and radio tuner */
292 if (this_adap == 0) {
293 first_tuner = addr;
294 tv_tuner = addr;
295 radio_tuner = addr;
296 }
297#endif
202 this_adap++; 298 this_adap++;
203 299
204 client_template.adapter = adap; 300 client_template.adapter = adap;
@@ -211,11 +307,12 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
211 memcpy(&t->i2c,&client_template,sizeof(struct i2c_client)); 307 memcpy(&t->i2c,&client_template,sizeof(struct i2c_client));
212 i2c_set_clientdata(&t->i2c, t); 308 i2c_set_clientdata(&t->i2c, t);
213 t->type = UNSET; 309 t->type = UNSET;
214 t->radio_if2 = 10700*1000; // 10.7MHz - FM radio 310 t->radio_if2 = 10700*1000; /* 10.7MHz - FM radio */
215 311
216 i2c_attach_client(&t->i2c); 312 i2c_attach_client(&t->i2c);
217 tuner_info("chip found @ 0x%x (%s)\n", 313 tuner_info("chip found @ 0x%x (%s)\n",
218 addr << 1, adap->name); 314 addr << 1, adap->name);
315
219 set_type(&t->i2c, t->type); 316 set_type(&t->i2c, t->type);
220 return 0; 317 return 0;
221} 318}
@@ -228,6 +325,12 @@ static int tuner_probe(struct i2c_adapter *adap)
228 } 325 }
229 this_adap = 0; 326 this_adap = 0;
230 327
328#ifdef CONFIG_TUNER_MULTI_I2C
329 first_tuner = 0;
330 tv_tuner = 0;
331 radio_tuner = 0;
332#endif
333
231 if (adap->class & I2C_CLASS_TV_ANALOG) 334 if (adap->class & I2C_CLASS_TV_ANALOG)
232 return i2c_probe(adap, &addr_data, tuner_attach); 335 return i2c_probe(adap, &addr_data, tuner_attach);
233 return 0; 336 return 0;
@@ -236,8 +339,14 @@ static int tuner_probe(struct i2c_adapter *adap)
236static int tuner_detach(struct i2c_client *client) 339static int tuner_detach(struct i2c_client *client)
237{ 340{
238 struct tuner *t = i2c_get_clientdata(client); 341 struct tuner *t = i2c_get_clientdata(client);
342 int err;
343
344 err=i2c_detach_client(&t->i2c);
345 if (err) {
346 tuner_warn ("Client deregistration failed, client not detached.\n");
347 return err;
348 }
239 349
240 i2c_detach_client(&t->i2c);
241 kfree(t); 350 kfree(t);
242 return 0; 351 return 0;
243} 352}
@@ -256,18 +365,23 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
256 unsigned int *iarg = (int*)arg; 365 unsigned int *iarg = (int*)arg;
257 366
258 switch (cmd) { 367 switch (cmd) {
259
260 /* --- configuration --- */ 368 /* --- configuration --- */
261 case TUNER_SET_TYPE: 369 case TUNER_SET_TYPE:
262 set_type(client,*iarg); 370 set_type(client,*iarg);
263 break; 371 break;
372 case TUNER_SET_TYPE_ADDR:
373 set_addr(client,(struct tuner_addr *)arg);
374 break;
264 case AUDC_SET_RADIO: 375 case AUDC_SET_RADIO:
376 t->mode = V4L2_TUNER_RADIO;
377 CHECK_ADDR(tv_tuner,"AUDC_SET_RADIO","TV");
378
265 if (V4L2_TUNER_RADIO != t->mode) { 379 if (V4L2_TUNER_RADIO != t->mode) {
266 set_tv_freq(client,400 * 16); 380 set_tv_freq(client,400 * 16);
267 t->mode = V4L2_TUNER_RADIO;
268 } 381 }
269 break; 382 break;
270 case AUDC_CONFIG_PINNACLE: 383 case AUDC_CONFIG_PINNACLE:
384 CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE","TV");
271 switch (*iarg) { 385 switch (*iarg) {
272 case 2: 386 case 2:
273 tuner_dbg("pinnacle pal\n"); 387 tuner_dbg("pinnacle pal\n");
@@ -297,6 +411,8 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
297 411
298 CHECK_V4L2; 412 CHECK_V4L2;
299 t->mode = V4L2_TUNER_ANALOG_TV; 413 t->mode = V4L2_TUNER_ANALOG_TV;
414 CHECK_ADDR(tv_tuner,"VIDIOCSCHAN","TV");
415
300 if (vc->norm < ARRAY_SIZE(map)) 416 if (vc->norm < ARRAY_SIZE(map))
301 t->std = map[vc->norm]; 417 t->std = map[vc->norm];
302 tuner_fixup_std(t); 418 tuner_fixup_std(t);
@@ -308,6 +424,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
308 { 424 {
309 unsigned long *v = arg; 425 unsigned long *v = arg;
310 426
427 CHECK_MODE("VIDIOCSFREQ");
311 CHECK_V4L2; 428 CHECK_V4L2;
312 set_freq(client,*v); 429 set_freq(client,*v);
313 return 0; 430 return 0;
@@ -316,15 +433,27 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
316 { 433 {
317 struct video_tuner *vt = arg; 434 struct video_tuner *vt = arg;
318 435
436 CHECK_ADDR(radio_tuner,"VIDIOCGTUNER","radio");
319 CHECK_V4L2; 437 CHECK_V4L2;
320 if (V4L2_TUNER_RADIO == t->mode && t->has_signal) 438 if (V4L2_TUNER_RADIO == t->mode) {
321 vt->signal = t->has_signal(client); 439 if (t->has_signal)
440 vt->signal = t->has_signal(client);
441 if (t->is_stereo) {
442 if (t->is_stereo(client))
443 vt-> flags |= VIDEO_TUNER_STEREO_ON;
444 else
445 vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON;
446 }
447 vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */
448 }
449
322 return 0; 450 return 0;
323 } 451 }
324 case VIDIOCGAUDIO: 452 case VIDIOCGAUDIO:
325 { 453 {
326 struct video_audio *va = arg; 454 struct video_audio *va = arg;
327 455
456 CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO","radio");
328 CHECK_V4L2; 457 CHECK_V4L2;
329 if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) 458 if (V4L2_TUNER_RADIO == t->mode && t->is_stereo)
330 va->mode = t->is_stereo(client) 459 va->mode = t->is_stereo(client)
@@ -339,6 +468,8 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
339 468
340 SWITCH_V4L2; 469 SWITCH_V4L2;
341 t->mode = V4L2_TUNER_ANALOG_TV; 470 t->mode = V4L2_TUNER_ANALOG_TV;
471 CHECK_ADDR(tv_tuner,"VIDIOC_S_STD","TV");
472
342 t->std = *id; 473 t->std = *id;
343 tuner_fixup_std(t); 474 tuner_fixup_std(t);
344 if (t->freq) 475 if (t->freq)
@@ -349,6 +480,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
349 { 480 {
350 struct v4l2_frequency *f = arg; 481 struct v4l2_frequency *f = arg;
351 482
483 CHECK_MODE("VIDIOC_S_FREQUENCY");
352 SWITCH_V4L2; 484 SWITCH_V4L2;
353 if (V4L2_TUNER_RADIO == f->type && 485 if (V4L2_TUNER_RADIO == f->type &&
354 V4L2_TUNER_RADIO != t->mode) 486 V4L2_TUNER_RADIO != t->mode)
@@ -361,6 +493,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
361 { 493 {
362 struct v4l2_frequency *f = arg; 494 struct v4l2_frequency *f = arg;
363 495
496 CHECK_MODE("VIDIOC_G_FREQUENCY");
364 SWITCH_V4L2; 497 SWITCH_V4L2;
365 f->type = t->mode; 498 f->type = t->mode;
366 f->frequency = t->freq; 499 f->frequency = t->freq;
@@ -370,14 +503,29 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
370 { 503 {
371 struct v4l2_tuner *tuner = arg; 504 struct v4l2_tuner *tuner = arg;
372 505
506 CHECK_MODE("VIDIOC_G_TUNER");
373 SWITCH_V4L2; 507 SWITCH_V4L2;
374 if (V4L2_TUNER_RADIO == t->mode && t->has_signal) 508 if (V4L2_TUNER_RADIO == t->mode) {
375 tuner->signal = t->has_signal(client); 509 if (t->has_signal)
510 tuner -> signal = t->has_signal(client);
511 if (t->is_stereo) {
512 if (t->is_stereo(client)) {
513 tuner -> capability |= V4L2_TUNER_CAP_STEREO;
514 tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO;
515 } else {
516 tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO;
517 }
518 }
519 }
520 /* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step to high at 62.5 Hz */
376 tuner->rangelow = tv_range[0] * 16; 521 tuner->rangelow = tv_range[0] * 16;
377 tuner->rangehigh = tv_range[1] * 16; 522// tuner->rangehigh = tv_range[1] * 16;
523// tuner->rangelow = tv_range[0] * 16384;
524 tuner->rangehigh = tv_range[1] * 16384;
378 break; 525 break;
379 } 526 }
380 default: 527 default:
528 tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
381 /* nothing */ 529 /* nothing */
382 break; 530 break;
383 } 531 }
@@ -385,7 +533,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
385 return 0; 533 return 0;
386} 534}
387 535
388static int tuner_suspend(struct device * dev, pm_message_t state, u32 level) 536static int tuner_suspend(struct device * dev, u32 state, u32 level)
389{ 537{
390 struct i2c_client *c = container_of(dev, struct i2c_client, dev); 538 struct i2c_client *c = container_of(dev, struct i2c_client, dev);
391 struct tuner *t = i2c_get_clientdata(c); 539 struct tuner *t = i2c_get_clientdata(c);
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index 48c6ceff1d..539f305573 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: tuner-simple.c,v 1.10 2005/03/08 08:38:00 kraxel Exp $ 2 * $Id: tuner-simple.c,v 1.21 2005/06/10 19:53:26 nsh Exp $
3 * 3 *
4 * i2c tv tuner chip device driver 4 * i2c tv tuner chip device driver
5 * controls all those simple 4-control-bytes style tuners. 5 * controls all those simple 4-control-bytes style tuners.
@@ -212,7 +212,25 @@ static struct tunertype tuners[] = {
212 { "Philips FQ1236A MK4", Philips, NTSC, 212 { "Philips FQ1236A MK4", Philips, NTSC,
213 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, 213 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
214 214
215 /* Should work for TVF8531MF, TVF8831MF, TVF8731MF */
216 { "Ymec TVision TVF-8531MF", Philips, NTSC,
217 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
218 { "Ymec TVision TVF-5533MF", Philips, NTSC,
219 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
220
221 { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
222 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
223 { "Tena TNF9533-D/IF", LGINNOTEK, PAL,
224 16*160.25, 16*464.25, 0x01,0x02,0x08,0x8e,623},
225
226 /*
227 * This entry is for TEA5767 FM radio only chip used on several boards
228 * w/TV tuner
229 */
230 { TEA5767_TUNER_NAME, Philips, RADIO,
231 -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0},
215}; 232};
233
216unsigned const int tuner_count = ARRAY_SIZE(tuners); 234unsigned const int tuner_count = ARRAY_SIZE(tuners);
217 235
218/* ---------------------------------------------------------------------- */ 236/* ---------------------------------------------------------------------- */
@@ -223,6 +241,7 @@ static int tuner_getstatus(struct i2c_client *c)
223 241
224 if (1 != i2c_master_recv(c,&byte,1)) 242 if (1 != i2c_master_recv(c,&byte,1))
225 return 0; 243 return 0;
244
226 return byte; 245 return byte;
227} 246}
228 247
@@ -231,17 +250,33 @@ static int tuner_getstatus(struct i2c_client *c)
231#define TUNER_MODE 0x38 250#define TUNER_MODE 0x38
232#define TUNER_AFC 0x07 251#define TUNER_AFC 0x07
233 252
234#define TUNER_STEREO 0x10 /* radio mode */ 253#define TUNER_STEREO 0x10 /* radio mode */
235#define TUNER_SIGNAL 0x07 /* radio mode */ 254#define TUNER_STEREO_MK3 0x04 /* radio mode */
255#define TUNER_SIGNAL 0x07 /* radio mode */
236 256
237static int tuner_signal(struct i2c_client *c) 257static int tuner_signal(struct i2c_client *c)
238{ 258{
239 return (tuner_getstatus(c) & TUNER_SIGNAL)<<13; 259 return (tuner_getstatus(c) & TUNER_SIGNAL) << 13;
240} 260}
241 261
242static int tuner_stereo(struct i2c_client *c) 262static int tuner_stereo(struct i2c_client *c)
243{ 263{
244 return (tuner_getstatus (c) & TUNER_STEREO); 264 int stereo, status;
265 struct tuner *t = i2c_get_clientdata(c);
266
267 status = tuner_getstatus (c);
268
269 switch (t->type) {
270 case TUNER_PHILIPS_FM1216ME_MK3:
271 case TUNER_PHILIPS_FM1236_MK3:
272 case TUNER_PHILIPS_FM1256_IH3:
273 stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
274 break;
275 default:
276 stereo = status & TUNER_STEREO;
277 }
278
279 return stereo;
245} 280}
246 281
247#if 0 /* unused */ 282#if 0 /* unused */
@@ -424,6 +459,14 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
424 buffer[2] = tun->config; 459 buffer[2] = tun->config;
425 460
426 switch (t->type) { 461 switch (t->type) {
462 case TUNER_TENA_9533_DI:
463 case TUNER_YMEC_TVF_5533MF:
464
465 /*These values are empirically determinated */
466 div = (freq*122)/16 - 20;
467 buffer[2] = 0x88; /* could be also 0x80 */
468 buffer[3] = 0x19; /* could be also 0x10, 0x18, 0x99 */
469 break;
427 case TUNER_PHILIPS_FM1216ME_MK3: 470 case TUNER_PHILIPS_FM1216ME_MK3:
428 case TUNER_PHILIPS_FM1236_MK3: 471 case TUNER_PHILIPS_FM1236_MK3:
429 buffer[3] = 0x19; 472 buffer[3] = 0x19;
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 41b635e0d3..9a493bea76 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -285,7 +285,6 @@ static int chip_thread(void *data)
285 schedule(); 285 schedule();
286 } 286 }
287 remove_wait_queue(&chip->wq, &wait); 287 remove_wait_queue(&chip->wq, &wait);
288 try_to_freeze(PF_FREEZE);
289 if (chip->done || signal_pending(current)) 288 if (chip->done || signal_pending(current))
290 break; 289 break;
291 dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c)); 290 dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
@@ -1237,17 +1236,17 @@ static int ta8874z_checkit(struct CHIPSTATE *chip)
1237/* audio chip descriptions - struct CHIPDESC */ 1236/* audio chip descriptions - struct CHIPDESC */
1238 1237
1239/* insmod options to enable/disable individual audio chips */ 1238/* insmod options to enable/disable individual audio chips */
1240int tda8425 = 1; 1239static int tda8425 = 1;
1241int tda9840 = 1; 1240static int tda9840 = 1;
1242int tda9850 = 1; 1241static int tda9850 = 1;
1243int tda9855 = 1; 1242static int tda9855 = 1;
1244int tda9873 = 1; 1243static int tda9873 = 1;
1245int tda9874a = 1; 1244static int tda9874a = 1;
1246int tea6300 = 0; // address clash with msp34xx 1245static int tea6300 = 0; // address clash with msp34xx
1247int tea6320 = 0; // address clash with msp34xx 1246static int tea6320 = 0; // address clash with msp34xx
1248int tea6420 = 1; 1247static int tea6420 = 1;
1249int pic16c54 = 1; 1248static int pic16c54 = 1;
1250int ta8874z = 0; // address clash with tda9840 1249static int ta8874z = 0; // address clash with tda9840
1251 1250
1252module_param(tda8425, int, 0444); 1251module_param(tda8425, int, 0444);
1253module_param(tda9840, int, 0444); 1252module_param(tda9840, int, 0444);
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 3d21697379..0f03c25489 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -75,7 +75,7 @@ hauppauge_tuner_fmt[] =
75 { 0x00000007, "PAL(B/G)" }, 75 { 0x00000007, "PAL(B/G)" },
76 { 0x00001000, "NTSC(M)" }, 76 { 0x00001000, "NTSC(M)" },
77 { 0x00000010, "PAL(I)" }, 77 { 0x00000010, "PAL(I)" },
78 { 0x00400000, "SECAM(L/L�)" }, 78 { 0x00400000, "SECAM(L/L´)" },
79 { 0x00000e00, "PAL(D/K)" }, 79 { 0x00000e00, "PAL(D/K)" },
80 { 0x03000000, "ATSC Digital" }, 80 { 0x03000000, "ATSC Digital" },
81}; 81};
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index eafd7061b3..51b99cdbf2 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -1,3 +1,7 @@
1/*
2 * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $
3 */
4
1#include <linux/module.h> 5#include <linux/module.h>
2#include <linux/moduleparam.h> 6#include <linux/moduleparam.h>
3#include <linux/kernel.h> 7#include <linux/kernel.h>
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index b0d4bcb027..70ecbdb802 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -1,4 +1,6 @@
1/* 1/*
2 * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $
3 *
2 * Video for Linux Two 4 * Video for Linux Two
3 * Backward Compatibility Layer 5 * Backward Compatibility Layer
4 * 6 *
@@ -15,14 +17,11 @@
15 * 17 *
16 */ 18 */
17 19
18#ifndef __KERNEL__
19#define __KERNEL__
20#endif
21
22#include <linux/config.h> 20#include <linux/config.h>
23 21
24#include <linux/init.h> 22#include <linux/init.h>
25#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/moduleparam.h>
26#include <linux/types.h> 25#include <linux/types.h>
27#include <linux/kernel.h> 26#include <linux/kernel.h>
28#include <linux/sched.h> 27#include <linux/sched.h>
@@ -787,12 +786,15 @@ v4l_compat_translate_ioctl(struct inode *inode,
787 !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) 786 !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
788 aud->step = qctrl2.step; 787 aud->step = qctrl2.step;
789 aud->mode = 0; 788 aud->mode = 0;
789
790 memset(&tun2,0,sizeof(tun2));
790 err = drv(inode, file, VIDIOC_G_TUNER, &tun2); 791 err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
791 if (err < 0) { 792 if (err < 0) {
792 dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err); 793 dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
793 err = 0; 794 err = 0;
794 break; 795 break;
795 } 796 }
797
796 if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) 798 if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
797 aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; 799 aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
798 else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) 800 else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 8d132b0d6b..06e8eb19a0 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -24,10 +24,28 @@ config I2O
24 24
25 If unsure, say N. 25 If unsure, say N.
26 26
27config I2O_EXT_ADAPTEC
28 bool "Enable Adaptec extensions"
29 depends on I2O
30 default y
31 ---help---
32 Say Y for support of raidutils for Adaptec I2O controllers. You also
33 have to say Y to "I2O Configuration support", "I2O SCSI OSM" below
34 and to "SCSI generic support" under "SCSI device configuration".
35
36config I2O_EXT_ADAPTEC_DMA64
37 bool "Enable 64-bit DMA"
38 depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G )
39 default y
40 ---help---
41 Say Y for support of 64-bit DMA transfer mode on Adaptec I2O
42 controllers.
43 Note: You need at least firmware version 3709.
44
27config I2O_CONFIG 45config I2O_CONFIG
28 tristate "I2O Configuration support" 46 tristate "I2O Configuration support"
29 depends on PCI && I2O 47 depends on I2O
30 help 48 ---help---
31 Say Y for support of the configuration interface for the I2O adapters. 49 Say Y for support of the configuration interface for the I2O adapters.
32 If you have a RAID controller from Adaptec and you want to use the 50 If you have a RAID controller from Adaptec and you want to use the
33 raidutils to manage your RAID array, you have to say Y here. 51 raidutils to manage your RAID array, you have to say Y here.
@@ -35,10 +53,28 @@ config I2O_CONFIG
35 To compile this support as a module, choose M here: the 53 To compile this support as a module, choose M here: the
36 module will be called i2o_config. 54 module will be called i2o_config.
37 55
56config I2O_CONFIG_OLD_IOCTL
57 bool "Enable ioctls (OBSOLETE)"
58 depends on I2O_CONFIG
59 default y
60 ---help---
61 Enables old ioctls.
62
63config I2O_BUS
64 tristate "I2O Bus Adapter OSM"
65 depends on I2O
66 ---help---
67 Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM
68 provides access to the busses on the I2O controller. The main purpose
69 is to rescan the bus to find new devices.
70
71 To compile this support as a module, choose M here: the
72 module will be called i2o_bus.
73
38config I2O_BLOCK 74config I2O_BLOCK
39 tristate "I2O Block OSM" 75 tristate "I2O Block OSM"
40 depends on I2O 76 depends on I2O
41 help 77 ---help---
42 Include support for the I2O Block OSM. The Block OSM presents disk 78 Include support for the I2O Block OSM. The Block OSM presents disk
43 and other structured block devices to the operating system. If you 79 and other structured block devices to the operating system. If you
44 are using an RAID controller, you could access the array only by 80 are using an RAID controller, you could access the array only by
@@ -51,7 +87,7 @@ config I2O_BLOCK
51config I2O_SCSI 87config I2O_SCSI
52 tristate "I2O SCSI OSM" 88 tristate "I2O SCSI OSM"
53 depends on I2O && SCSI 89 depends on I2O && SCSI
54 help 90 ---help---
55 Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel 91 Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel
56 I2O controller. You can use both the SCSI and Block OSM together if 92 I2O controller. You can use both the SCSI and Block OSM together if
57 you wish. To access a RAID array, you must use the Block OSM driver. 93 you wish. To access a RAID array, you must use the Block OSM driver.
@@ -63,7 +99,7 @@ config I2O_SCSI
63config I2O_PROC 99config I2O_PROC
64 tristate "I2O /proc support" 100 tristate "I2O /proc support"
65 depends on I2O 101 depends on I2O
66 help 102 ---help---
67 If you say Y here and to "/proc file system support", you will be 103 If you say Y here and to "/proc file system support", you will be
68 able to read I2O related information from the virtual directory 104 able to read I2O related information from the virtual directory
69 /proc/i2o. 105 /proc/i2o.
diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile
index aabc6cdc3f..2c2e39aa1e 100644
--- a/drivers/message/i2o/Makefile
+++ b/drivers/message/i2o/Makefile
@@ -6,8 +6,11 @@
6# 6#
7 7
8i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o 8i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o
9i2o_bus-y += bus-osm.o
10i2o_config-y += config-osm.o
9obj-$(CONFIG_I2O) += i2o_core.o 11obj-$(CONFIG_I2O) += i2o_core.o
10obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o 12obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o
13obj-$(CONFIG_I2O_BUS) += i2o_bus.o
11obj-$(CONFIG_I2O_BLOCK) += i2o_block.o 14obj-$(CONFIG_I2O_BLOCK) += i2o_block.o
12obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o 15obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o
13obj-$(CONFIG_I2O_PROC) += i2o_proc.o 16obj-$(CONFIG_I2O_PROC) += i2o_proc.o
diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c
new file mode 100644
index 0000000000..151b228e1c
--- /dev/null
+++ b/drivers/message/i2o/bus-osm.c
@@ -0,0 +1,164 @@
1/*
2 * Bus Adapter OSM
3 *
4 * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Fixes/additions:
12 * Markus Lidel <Markus.Lidel@shadowconnect.com>
13 * initial version.
14 */
15
16#include <linux/module.h>
17#include <linux/i2o.h>
18
19#define OSM_NAME "bus-osm"
20#define OSM_VERSION "$Rev$"
21#define OSM_DESCRIPTION "I2O Bus Adapter OSM"
22
23static struct i2o_driver i2o_bus_driver;
24
25/* Bus OSM class handling definition */
26static struct i2o_class_id i2o_bus_class_id[] = {
27 {I2O_CLASS_BUS_ADAPTER},
28 {I2O_CLASS_END}
29};
30
31/**
32 * i2o_bus_scan - Scan the bus for new devices
33 * @dev: I2O device of the bus, which should be scanned
34 *
35 * Scans the bus dev for new / removed devices. After the scan a new LCT
36 * will be fetched automatically.
37 *
38 * Returns 0 on success or negative error code on failure.
39 */
40static int i2o_bus_scan(struct i2o_device *dev)
41{
42 struct i2o_message __iomem *msg;
43 u32 m;
44
45 m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
46 if (m == I2O_QUEUE_EMPTY)
47 return -ETIMEDOUT;
48
49 writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
50 writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid,
51 &msg->u.head[1]);
52
53 return i2o_msg_post_wait(dev->iop, m, 60);
54};
55
56/**
57 * i2o_bus_store_scan - Scan the I2O Bus Adapter
58 * @d: device which should be scanned
59 *
60 * Returns count.
61 */
62static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf,
63 size_t count)
64{
65 struct i2o_device *i2o_dev = to_i2o_device(d);
66 int rc;
67
68 if ((rc = i2o_bus_scan(i2o_dev)))
69 osm_warn("bus scan failed %d\n", rc);
70
71 return count;
72}
73
74/* Bus Adapter OSM device attributes */
75static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan);
76
77/**
78 * i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it
79 * @dev: device to verify if it is a I2O Bus Adapter device
80 *
81 * Because we want all Bus Adapters always return 0.
82 *
83 * Returns 0.
84 */
85static int i2o_bus_probe(struct device *dev)
86{
87 struct i2o_device *i2o_dev = to_i2o_device(get_device(dev));
88
89 device_create_file(dev, &dev_attr_scan);
90
91 osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid);
92
93 return 0;
94};
95
96/**
97 * i2o_bus_remove - remove the I2O Bus Adapter device from the system again
98 * @dev: I2O Bus Adapter device which should be removed
99 *
100 * Always returns 0.
101 */
102static int i2o_bus_remove(struct device *dev)
103{
104 struct i2o_device *i2o_dev = to_i2o_device(dev);
105
106 device_remove_file(dev, &dev_attr_scan);
107
108 put_device(dev);
109
110 osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
111
112 return 0;
113};
114
115/* Bus Adapter OSM driver struct */
116static struct i2o_driver i2o_bus_driver = {
117 .name = OSM_NAME,
118 .classes = i2o_bus_class_id,
119 .driver = {
120 .probe = i2o_bus_probe,
121 .remove = i2o_bus_remove,
122 },
123};
124
125/**
126 * i2o_bus_init - Bus Adapter OSM initialization function
127 *
128 * Only register the Bus Adapter OSM in the I2O core.
129 *
130 * Returns 0 on success or negative error code on failure.
131 */
132static int __init i2o_bus_init(void)
133{
134 int rc;
135
136 printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
137
138 /* Register Bus Adapter OSM into I2O core */
139 rc = i2o_driver_register(&i2o_bus_driver);
140 if (rc) {
141 osm_err("Could not register Bus Adapter OSM\n");
142 return rc;
143 }
144
145 return 0;
146};
147
148/**
149 * i2o_bus_exit - Bus Adapter OSM exit function
150 *
151 * Unregisters Bus Adapter OSM from I2O core.
152 */
153static void __exit i2o_bus_exit(void)
154{
155 i2o_driver_unregister(&i2o_bus_driver);
156};
157
158MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>");
159MODULE_LICENSE("GPL");
160MODULE_DESCRIPTION(OSM_DESCRIPTION);
161MODULE_VERSION(OSM_VERSION);
162
163module_init(i2o_bus_init);
164module_exit(i2o_bus_exit);
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
new file mode 100644
index 0000000000..d0267609a9
--- /dev/null
+++ b/drivers/message/i2o/config-osm.c
@@ -0,0 +1,579 @@
1/*
2 * Configuration OSM
3 *
4 * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Fixes/additions:
12 * Markus Lidel <Markus.Lidel@shadowconnect.com>
13 * initial version.
14 */
15
16#include <linux/module.h>
17#include <linux/i2o.h>
18#include <linux/namei.h>
19
20#include <asm/uaccess.h>
21
22#define OSM_NAME "config-osm"
23#define OSM_VERSION "1.248"
24#define OSM_DESCRIPTION "I2O Configuration OSM"
25
26/* access mode user rw */
27#define S_IWRSR (S_IRUSR | S_IWUSR)
28
29static struct i2o_driver i2o_config_driver;
30
31/* Special file operations for sysfs */
32struct fops_attribute {
33 struct bin_attribute bin;
34 struct file_operations fops;
35};
36
37/**
38 * sysfs_read_dummy
39 */
40static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset,
41 size_t count)
42{
43 return 0;
44};
45
46/**
47 * sysfs_write_dummy
48 */
49static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset,
50 size_t count)
51{
52 return 0;
53};
54
55/**
56 * sysfs_create_fops_file - Creates attribute with special file operations
57 * @kobj: kobject which should contains the attribute
58 * @attr: attributes which should be used to create file
59 *
60 * First creates attribute @attr in kobject @kobj. If it is the first time
61 * this function is called, merge old fops from sysfs with new one and
62 * write it back. Afterwords the new fops will be set for the created
63 * attribute.
64 *
65 * Returns 0 on success or negative error code on failure.
66 */
67static int sysfs_create_fops_file(struct kobject *kobj,
68 struct fops_attribute *attr)
69{
70 struct file_operations tmp, *fops;
71 struct dentry *d;
72 struct qstr qstr;
73 int rc;
74
75 fops = &attr->fops;
76
77 if (fops->read)
78 attr->bin.read = sysfs_read_dummy;
79
80 if (fops->write)
81 attr->bin.write = sysfs_write_dummy;
82
83 if ((rc = sysfs_create_bin_file(kobj, &attr->bin)))
84 return rc;
85
86 qstr.name = attr->bin.attr.name;
87 qstr.len = strlen(qstr.name);
88 qstr.hash = full_name_hash(qstr.name, qstr.len);
89
90 if ((d = lookup_hash(&qstr, kobj->dentry))) {
91 if (!fops->owner) {
92 memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp));
93 if (fops->read)
94 tmp.read = fops->read;
95 if (fops->write)
96 tmp.write = fops->write;
97 memcpy(fops, &tmp, sizeof(tmp));
98 }
99
100 d->d_inode->i_fop = fops;
101 } else
102 sysfs_remove_bin_file(kobj, &attr->bin);
103
104 return -ENOENT;
105};
106
107/**
108 * sysfs_remove_fops_file - Remove attribute with special file operations
109 * @kobj: kobject which contains the attribute
110 * @attr: attributes which are used to create file
111 *
112 * Only wrapper arround sysfs_remove_bin_file()
113 *
114 * Returns 0 on success or negative error code on failure.
115 */
116static inline int sysfs_remove_fops_file(struct kobject *kobj,
117 struct fops_attribute *attr)
118{
119 return sysfs_remove_bin_file(kobj, &attr->bin);
120};
121
122/**
123 * i2o_config_read_hrt - Returns the HRT of the controller
124 * @kob: kernel object handle
125 * @buf: buffer into which the HRT should be copied
126 * @off: file offset
127 * @count: number of bytes to read
128 *
129 * Put @count bytes starting at @off into @buf from the HRT of the I2O
130 * controller corresponding to @kobj.
131 *
132 * Returns number of bytes copied into buffer.
133 */
134static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf,
135 loff_t offset, size_t count)
136{
137 struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
138 i2o_hrt *hrt = c->hrt.virt;
139
140 u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4;
141
142 if (offset > size)
143 return 0;
144
145 if (offset + count > size)
146 count = size - offset;
147
148 memcpy(buf, (u8 *) hrt + offset, count);
149
150 return count;
151};
152
153/**
154 * i2o_config_read_lct - Returns the LCT of the controller
155 * @kob: kernel object handle
156 * @buf: buffer into which the LCT should be copied
157 * @off: file offset
158 * @count: number of bytes to read
159 *
160 * Put @count bytes starting at @off into @buf from the LCT of the I2O
161 * controller corresponding to @kobj.
162 *
163 * Returns number of bytes copied into buffer.
164 */
165static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf,
166 loff_t offset, size_t count)
167{
168 struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
169 u32 size = c->lct->table_size * 4;
170
171 if (offset > size)
172 return 0;
173
174 if (offset + count > size)
175 count = size - offset;
176
177 memcpy(buf, (u8 *) c->lct + offset, count);
178
179 return count;
180};
181
182#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \
183static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \
184 return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \
185};\
186\
187static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \
188 return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \
189}; \
190\
191static struct fops_attribute i2o_config_attr_##_name = { \
192 .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \
193 .owner = THIS_MODULE }, \
194 .size = 0, }, \
195 .fops = { .write = i2o_config_##_name##_write, \
196 .read = i2o_config_##_name##_read} \
197};
198
199#ifdef CONFIG_I2O_EXT_ADAPTEC
200
201/**
202 * i2o_config_dpt_reagion - Converts type and id to flash region
203 * @swtype: type of software module reading
204 * @swid: id of software which should be read
205 *
206 * Converts type and id from I2O spec to the matching region for DPT /
207 * Adaptec controllers.
208 *
209 * Returns region which match type and id or -1 on error.
210 */
211static u32 i2o_config_dpt_region(u8 swtype, u8 swid)
212{
213 switch (swtype) {
214 case I2O_SOFTWARE_MODULE_IRTOS:
215 /*
216 * content: operation firmware
217 * region size:
218 * 0xbc000 for 2554, 3754, 2564, 3757
219 * 0x170000 for 2865
220 * 0x17c000 for 3966
221 */
222 if (!swid)
223 return 0;
224
225 break;
226
227 case I2O_SOFTWARE_MODULE_IOP_PRIVATE:
228 /*
229 * content: BIOS and SMOR
230 * BIOS size: first 0x8000 bytes
231 * region size:
232 * 0x40000 for 2554, 3754, 2564, 3757
233 * 0x80000 for 2865, 3966
234 */
235 if (!swid)
236 return 1;
237
238 break;
239
240 case I2O_SOFTWARE_MODULE_IOP_CONFIG:
241 switch (swid) {
242 case 0:
243 /*
244 * content: NVRAM defaults
245 * region size: 0x2000 bytes
246 */
247 return 2;
248 case 1:
249 /*
250 * content: serial number
251 * region size: 0x2000 bytes
252 */
253 return 3;
254 }
255 break;
256 }
257
258 return -1;
259};
260
261#endif
262
263/**
264 * i2o_config_sw_read - Read a software module from controller
265 * @file: file pointer
266 * @buf: buffer into which the data should be copied
267 * @count: number of bytes to read
268 * @off: file offset
269 * @swtype: type of software module reading
270 * @swid: id of software which should be read
271 *
272 * Transfers @count bytes at offset @offset from IOP into buffer using
273 * type @swtype and id @swid as described in I2O spec.
274 *
275 * Returns number of bytes copied into buffer or error code on failure.
276 */
277static ssize_t i2o_config_sw_read(struct file *file, char __user * buf,
278 size_t count, loff_t * offset, u8 swtype,
279 u32 swid)
280{
281 struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
282 struct kobject *kobj = sd->s_element;
283 struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
284 u32 m, function = I2O_CMD_SW_UPLOAD;
285 struct i2o_dma buffer;
286 struct i2o_message __iomem *msg;
287 u32 __iomem *mptr;
288 int rc, status;
289
290 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
291 if (m == I2O_QUEUE_EMPTY)
292 return -EBUSY;
293
294 mptr = &msg->body[3];
295
296 if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) {
297 i2o_msg_nop(c, m);
298 return rc;
299 }
300#ifdef CONFIG_I2O_EXT_ADAPTEC
301 if (c->adaptec) {
302 mptr = &msg->body[4];
303 function = I2O_CMD_PRIVATE;
304
305 writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
306
307 writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ,
308 &msg->body[0]);
309 writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
310 writel(*offset, &msg->body[2]);
311 writel(count, &msg->body[3]);
312 } else
313#endif
314 writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
315
316 writel(0xD0000000 | count, mptr++);
317 writel(buffer.phys, mptr);
318
319 writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
320 writel(i2o_config_driver.context, &msg->u.head[2]);
321 writel(0, &msg->u.head[3]);
322
323#ifdef CONFIG_I2O_EXT_ADAPTEC
324 if (!c->adaptec)
325#endif
326 {
327 writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
328 writel(0, &msg->body[1]);
329 writel(swid, &msg->body[2]);
330 }
331
332 status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
333
334 if (status == I2O_POST_WAIT_OK) {
335 if (!(rc = copy_to_user(buf, buffer.virt, count))) {
336 rc = count;
337 *offset += count;
338 }
339 } else
340 rc = -EIO;
341
342 if (status != -ETIMEDOUT)
343 i2o_dma_free(&c->pdev->dev, &buffer);
344
345 return rc;
346};
347
348/**
349 * i2o_config_sw_write - Write a software module to controller
350 * @file: file pointer
351 * @buf: buffer into which the data should be copied
352 * @count: number of bytes to read
353 * @off: file offset
354 * @swtype: type of software module writing
355 * @swid: id of software which should be written
356 *
357 * Transfers @count bytes at offset @offset from buffer to IOP using
358 * type @swtype and id @swid as described in I2O spec.
359 *
360 * Returns number of bytes copied from buffer or error code on failure.
361 */
362static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf,
363 size_t count, loff_t * offset, u8 swtype,
364 u32 swid)
365{
366 struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
367 struct kobject *kobj = sd->s_element;
368 struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
369 u32 m, function = I2O_CMD_SW_DOWNLOAD;
370 struct i2o_dma buffer;
371 struct i2o_message __iomem *msg;
372 u32 __iomem *mptr;
373 int rc, status;
374
375 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
376 if (m == I2O_QUEUE_EMPTY)
377 return -EBUSY;
378
379 mptr = &msg->body[3];
380
381 if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL)))
382 goto nop_msg;
383
384 if ((rc = copy_from_user(buffer.virt, buf, count)))
385 goto free_buffer;
386
387#ifdef CONFIG_I2O_EXT_ADAPTEC
388 if (c->adaptec) {
389 mptr = &msg->body[4];
390 function = I2O_CMD_PRIVATE;
391
392 writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
393
394 writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE,
395 &msg->body[0]);
396 writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
397 writel(*offset, &msg->body[2]);
398 writel(count, &msg->body[3]);
399 } else
400#endif
401 writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
402
403 writel(0xD4000000 | count, mptr++);
404 writel(buffer.phys, mptr);
405
406 writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
407 writel(i2o_config_driver.context, &msg->u.head[2]);
408 writel(0, &msg->u.head[3]);
409
410#ifdef CONFIG_I2O_EXT_ADAPTEC
411 if (!c->adaptec)
412#endif
413 {
414 writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
415 writel(0, &msg->body[1]);
416 writel(swid, &msg->body[2]);
417 }
418
419 status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
420
421 if (status != -ETIMEDOUT)
422 i2o_dma_free(&c->pdev->dev, &buffer);
423
424 if (status != I2O_POST_WAIT_OK)
425 return -EIO;
426
427 *offset += count;
428
429 return count;
430
431 free_buffer:
432 i2o_dma_free(&c->pdev->dev, &buffer);
433
434 nop_msg:
435 i2o_msg_nop(c, m);
436
437 return rc;
438};
439
440/* attribute for HRT in sysfs */
441static struct bin_attribute i2o_config_hrt_attr = {
442 .attr = {
443 .name = "hrt",
444 .mode = S_IRUGO,
445 .owner = THIS_MODULE},
446 .size = 0,
447 .read = i2o_config_read_hrt
448};
449
450/* attribute for LCT in sysfs */
451static struct bin_attribute i2o_config_lct_attr = {
452 .attr = {
453 .name = "lct",
454 .mode = S_IRUGO,
455 .owner = THIS_MODULE},
456 .size = 0,
457 .read = i2o_config_read_lct
458};
459
460/* IRTOS firmware access */
461I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0);
462
463#ifdef CONFIG_I2O_EXT_ADAPTEC
464
465/*
466 * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec
467 * controllers
468 */
469I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0);
470I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0);
471I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1);
472
473#endif
474
475/**
476 * i2o_config_notify_controller_add - Notify of added controller
477 * @c: the controller which was added
478 *
479 * If a I2O controller is added, we catch the notification to add sysfs
480 * entries.
481 */
482static void i2o_config_notify_controller_add(struct i2o_controller *c)
483{
484 struct kobject *kobj = &c->exec->device.kobj;
485
486 sysfs_create_bin_file(kobj, &i2o_config_hrt_attr);
487 sysfs_create_bin_file(kobj, &i2o_config_lct_attr);
488
489 sysfs_create_fops_file(kobj, &i2o_config_attr_irtos);
490#ifdef CONFIG_I2O_EXT_ADAPTEC
491 if (c->adaptec) {
492 sysfs_create_fops_file(kobj, &i2o_config_attr_bios);
493 sysfs_create_fops_file(kobj, &i2o_config_attr_nvram);
494 sysfs_create_fops_file(kobj, &i2o_config_attr_serial);
495 }
496#endif
497};
498
499/**
500 * i2o_config_notify_controller_remove - Notify of removed controller
501 * @c: the controller which was removed
502 *
503 * If a I2O controller is removed, we catch the notification to remove the
504 * sysfs entries.
505 */
506static void i2o_config_notify_controller_remove(struct i2o_controller *c)
507{
508 struct kobject *kobj = &c->exec->device.kobj;
509
510#ifdef CONFIG_I2O_EXT_ADAPTEC
511 if (c->adaptec) {
512 sysfs_remove_fops_file(kobj, &i2o_config_attr_serial);
513 sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram);
514 sysfs_remove_fops_file(kobj, &i2o_config_attr_bios);
515 }
516#endif
517 sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos);
518
519 sysfs_remove_bin_file(kobj, &i2o_config_lct_attr);
520 sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr);
521};
522
523/* Config OSM driver struct */
524static struct i2o_driver i2o_config_driver = {
525 .name = OSM_NAME,
526 .notify_controller_add = i2o_config_notify_controller_add,
527 .notify_controller_remove = i2o_config_notify_controller_remove
528};
529
530#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
531#include "i2o_config.c"
532#endif
533
534/**
535 * i2o_config_init - Configuration OSM initialization function
536 *
537 * Registers Configuration OSM in the I2O core and if old ioctl's are
538 * compiled in initialize them.
539 *
540 * Returns 0 on success or negative error code on failure.
541 */
542static int __init i2o_config_init(void)
543{
544 printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
545
546 if (i2o_driver_register(&i2o_config_driver)) {
547 osm_err("handler register failed.\n");
548 return -EBUSY;
549 }
550#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
551 if (i2o_config_old_init())
552 i2o_driver_unregister(&i2o_config_driver);
553#endif
554
555 return 0;
556}
557
558/**
559 * i2o_config_exit - Configuration OSM exit function
560 *
561 * If old ioctl's are compiled in exit remove them and unregisters
562 * Configuration OSM from I2O core.
563 */
564static void i2o_config_exit(void)
565{
566#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
567 i2o_config_old_exit();
568#endif
569
570 i2o_driver_unregister(&i2o_config_driver);
571}
572
573MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>");
574MODULE_LICENSE("GPL");
575MODULE_DESCRIPTION(OSM_DESCRIPTION);
576MODULE_VERSION(OSM_VERSION);
577
578module_init(i2o_config_init);
579module_exit(i2o_config_exit);
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
new file mode 100644
index 0000000000..c5bcfd70f7
--- /dev/null
+++ b/drivers/message/i2o/core.h
@@ -0,0 +1,58 @@
1/*
2 * I2O core internal declarations
3 *
4 * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Fixes/additions:
12 * Markus Lidel <Markus.Lidel@shadowconnect.com>
13 * initial version.
14 */
15
16/* Exec-OSM */
17extern struct bus_type i2o_bus_type;
18
19extern struct i2o_driver i2o_exec_driver;
20extern int i2o_exec_lct_get(struct i2o_controller *);
21
22extern int __init i2o_exec_init(void);
23extern void __exit i2o_exec_exit(void);
24
25/* driver */
26extern int i2o_driver_dispatch(struct i2o_controller *, u32);
27
28extern int __init i2o_driver_init(void);
29extern void __exit i2o_driver_exit(void);
30
31/* PCI */
32extern int __init i2o_pci_init(void);
33extern void __exit i2o_pci_exit(void);
34
35/* device */
36extern void i2o_device_remove(struct i2o_device *);
37extern int i2o_device_parse_lct(struct i2o_controller *);
38
39extern int i2o_device_init(void);
40extern void i2o_device_exit(void);
41
42/* IOP */
43extern struct i2o_controller *i2o_iop_alloc(void);
44extern void i2o_iop_free(struct i2o_controller *);
45
46extern int i2o_iop_add(struct i2o_controller *);
47extern void i2o_iop_remove(struct i2o_controller *);
48
49/* config */
50extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
51
52/* control registers relative to c->base */
53#define I2O_IRQ_STATUS 0x30
54#define I2O_IRQ_MASK 0x34
55#define I2O_IN_PORT 0x40
56#define I2O_OUT_PORT 0x44
57
58#define I2O_IRQ_OUTBOUND_POST 0x00000008
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 2a5d478fc6..018ca887ca 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -4,8 +4,6 @@
4#include <linux/pci.h> 4#include <linux/pci.h>
5#include <linux/i2o.h> 5#include <linux/i2o.h>
6 6
7extern struct i2o_driver **i2o_drivers;
8extern unsigned int i2o_max_drivers;
9static void i2o_report_util_cmd(u8 cmd); 7static void i2o_report_util_cmd(u8 cmd);
10static void i2o_report_exec_cmd(u8 cmd); 8static void i2o_report_exec_cmd(u8 cmd);
11static void i2o_report_fail_status(u8 req_status, u32 * msg); 9static void i2o_report_fail_status(u8 req_status, u32 * msg);
@@ -23,7 +21,6 @@ void i2o_report_status(const char *severity, const char *str,
23 u8 cmd = (msg[1] >> 24) & 0xFF; 21 u8 cmd = (msg[1] >> 24) & 0xFF;
24 u8 req_status = (msg[4] >> 24) & 0xFF; 22 u8 req_status = (msg[4] >> 24) & 0xFF;
25 u16 detailed_status = msg[4] & 0xFFFF; 23 u16 detailed_status = msg[4] & 0xFFFF;
26 //struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)];
27 24
28 if (cmd == I2O_CMD_UTIL_EVT_REGISTER) 25 if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
29 return; // No status in this reply 26 return; // No status in this reply
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index eb907e87bc..21f16ba3ac 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -16,9 +16,7 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/i2o.h> 17#include <linux/i2o.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19 19#include "core.h"
20/* Exec OSM functions */
21extern struct bus_type i2o_bus_type;
22 20
23/** 21/**
24 * i2o_device_issue_claim - claim or release a device 22 * i2o_device_issue_claim - claim or release a device
@@ -282,8 +280,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
282 280
283 down(&c->lct_lock); 281 down(&c->lct_lock);
284 282
285 if (c->lct) 283 kfree(c->lct);
286 kfree(c->lct);
287 284
288 lct = c->dlct.virt; 285 lct = c->dlct.virt;
289 286
@@ -294,12 +291,12 @@ int i2o_device_parse_lct(struct i2o_controller *c)
294 } 291 }
295 292
296 if (lct->table_size * 4 > c->dlct.len) { 293 if (lct->table_size * 4 > c->dlct.len) {
297 memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len); 294 memcpy(c->lct, c->dlct.virt, c->dlct.len);
298 up(&c->lct_lock); 295 up(&c->lct_lock);
299 return -EAGAIN; 296 return -EAGAIN;
300 } 297 }
301 298
302 memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4); 299 memcpy(c->lct, c->dlct.virt, lct->table_size * 4);
303 300
304 lct = c->lct; 301 lct = c->lct;
305 302
@@ -354,7 +351,7 @@ static ssize_t i2o_device_class_show_class_id(struct class_device *cd,
354{ 351{
355 struct i2o_device *dev = to_i2o_device(cd->dev); 352 struct i2o_device *dev = to_i2o_device(cd->dev);
356 353
357 sprintf(buf, "%03x\n", dev->lct_data.class_id); 354 sprintf(buf, "0x%03x\n", dev->lct_data.class_id);
358 return strlen(buf) + 1; 355 return strlen(buf) + 1;
359}; 356};
360 357
@@ -369,7 +366,7 @@ static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf)
369{ 366{
370 struct i2o_device *dev = to_i2o_device(cd->dev); 367 struct i2o_device *dev = to_i2o_device(cd->dev);
371 368
372 sprintf(buf, "%03x\n", dev->lct_data.tid); 369 sprintf(buf, "0x%03x\n", dev->lct_data.tid);
373 return strlen(buf) + 1; 370 return strlen(buf) + 1;
374}; 371};
375 372
@@ -401,25 +398,27 @@ static int i2o_device_class_add(struct class_device *cd)
401 398
402 /* create user entries for this device */ 399 /* create user entries for this device */
403 tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); 400 tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
404 if (tmp) 401 if (tmp && (tmp != i2o_dev))
405 sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, 402 sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
406 "user"); 403 "user");
407 404
408 /* create user entries refering to this device */ 405 /* create user entries refering to this device */
409 list_for_each_entry(tmp, &c->devices, list) 406 list_for_each_entry(tmp, &c->devices, list)
410 if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) 407 if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
408 && (tmp != i2o_dev))
411 sysfs_create_link(&tmp->device.kobj, 409 sysfs_create_link(&tmp->device.kobj,
412 &i2o_dev->device.kobj, "user"); 410 &i2o_dev->device.kobj, "user");
413 411
414 /* create parent entries for this device */ 412 /* create parent entries for this device */
415 tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); 413 tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
416 if (tmp) 414 if (tmp && (tmp != i2o_dev))
417 sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, 415 sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
418 "parent"); 416 "parent");
419 417
420 /* create parent entries refering to this device */ 418 /* create parent entries refering to this device */
421 list_for_each_entry(tmp, &c->devices, list) 419 list_for_each_entry(tmp, &c->devices, list)
422 if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) 420 if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
421 && (tmp != i2o_dev))
423 sysfs_create_link(&tmp->device.kobj, 422 sysfs_create_link(&tmp->device.kobj,
424 &i2o_dev->device.kobj, "parent"); 423 &i2o_dev->device.kobj, "parent");
425 424
@@ -444,9 +443,8 @@ static struct class_interface i2o_device_class_interface = {
444 * Note that the minimum sized reslist is 8 bytes and contains 443 * Note that the minimum sized reslist is 8 bytes and contains
445 * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. 444 * ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
446 */ 445 */
447
448int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, 446int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
449 int oplen, void *reslist, int reslen) 447 int oplen, void *reslist, int reslen)
450{ 448{
451 struct i2o_message __iomem *msg; 449 struct i2o_message __iomem *msg;
452 u32 m; 450 u32 m;
@@ -489,7 +487,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
489 if (rc == -ETIMEDOUT) 487 if (rc == -ETIMEDOUT)
490 return rc; 488 return rc;
491 489
492 memcpy_fromio(reslist, res.virt, res.len); 490 memcpy(reslist, res.virt, res.len);
493 i2o_dma_free(dev, &res); 491 i2o_dma_free(dev, &res);
494 492
495 /* Query failed */ 493 /* Query failed */
@@ -531,17 +529,23 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
531 void *buf, int buflen) 529 void *buf, int buflen)
532{ 530{
533 u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; 531 u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
534 u8 resblk[8 + buflen]; /* 8 bytes for header */ 532 u8 *resblk; /* 8 bytes for header */
535 int size; 533 int size;
536 534
537 if (field == -1) /* whole group */ 535 if (field == -1) /* whole group */
538 opblk[4] = -1; 536 opblk[4] = -1;
539 537
538 resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC);
539 if (!resblk)
540 return -ENOMEM;
541
540 size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, 542 size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
541 sizeof(opblk), resblk, sizeof(resblk)); 543 sizeof(opblk), resblk, buflen + 8);
542 544
543 memcpy(buf, resblk + 8, buflen); /* cut off header */ 545 memcpy(buf, resblk + 8, buflen); /* cut off header */
544 546
547 kfree(resblk);
548
545 if (size > buflen) 549 if (size > buflen)
546 return buflen; 550 return buflen;
547 551
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 91f4edbb2a..739bfdef0c 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -17,9 +17,12 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/rwsem.h> 18#include <linux/rwsem.h>
19#include <linux/i2o.h> 19#include <linux/i2o.h>
20#include "core.h"
21
22#define OSM_NAME "i2o"
20 23
21/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ 24/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
22unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; 25static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
23module_param_named(max_drivers, i2o_max_drivers, uint, 0); 26module_param_named(max_drivers, i2o_max_drivers, uint, 0);
24MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); 27MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
25 28
@@ -76,17 +79,16 @@ int i2o_driver_register(struct i2o_driver *drv)
76 int rc = 0; 79 int rc = 0;
77 unsigned long flags; 80 unsigned long flags;
78 81
79 pr_debug("i2o: Register driver %s\n", drv->name); 82 osm_debug("Register driver %s\n", drv->name);
80 83
81 if (drv->event) { 84 if (drv->event) {
82 drv->event_queue = create_workqueue(drv->name); 85 drv->event_queue = create_workqueue(drv->name);
83 if (!drv->event_queue) { 86 if (!drv->event_queue) {
84 printk(KERN_ERR "i2o: Could not initialize event queue " 87 osm_err("Could not initialize event queue for driver "
85 "for driver %s\n", drv->name); 88 "%s\n", drv->name);
86 return -EFAULT; 89 return -EFAULT;
87 } 90 }
88 pr_debug("i2o: Event queue initialized for driver %s\n", 91 osm_debug("Event queue initialized for driver %s\n", drv->name);
89 drv->name);
90 } else 92 } else
91 drv->event_queue = NULL; 93 drv->event_queue = NULL;
92 94
@@ -97,8 +99,8 @@ int i2o_driver_register(struct i2o_driver *drv)
97 99
98 for (i = 0; i2o_drivers[i]; i++) 100 for (i = 0; i2o_drivers[i]; i++)
99 if (i >= i2o_max_drivers) { 101 if (i >= i2o_max_drivers) {
100 printk(KERN_ERR "i2o: too many drivers registered, " 102 osm_err("too many drivers registered, increase "
101 "increase max_drivers\n"); 103 "max_drivers\n");
102 spin_unlock_irqrestore(&i2o_drivers_lock, flags); 104 spin_unlock_irqrestore(&i2o_drivers_lock, flags);
103 return -EFAULT; 105 return -EFAULT;
104 } 106 }
@@ -108,18 +110,16 @@ int i2o_driver_register(struct i2o_driver *drv)
108 110
109 spin_unlock_irqrestore(&i2o_drivers_lock, flags); 111 spin_unlock_irqrestore(&i2o_drivers_lock, flags);
110 112
111 pr_debug("i2o: driver %s gets context id %d\n", drv->name, 113 osm_debug("driver %s gets context id %d\n", drv->name, drv->context);
112 drv->context);
113 114
114 list_for_each_entry(c, &i2o_controllers, list) { 115 list_for_each_entry(c, &i2o_controllers, list) {
115 struct i2o_device *i2o_dev; 116 struct i2o_device *i2o_dev;
116 117
117 i2o_driver_notify_controller_add(drv, c); 118 i2o_driver_notify_controller_add(drv, c);
118 list_for_each_entry(i2o_dev, &c->devices, list) 119 list_for_each_entry(i2o_dev, &c->devices, list)
119 i2o_driver_notify_device_add(drv, i2o_dev); 120 i2o_driver_notify_device_add(drv, i2o_dev);
120 } 121 }
121 122
122
123 rc = driver_register(&drv->driver); 123 rc = driver_register(&drv->driver);
124 if (rc) 124 if (rc)
125 destroy_workqueue(drv->event_queue); 125 destroy_workqueue(drv->event_queue);
@@ -139,7 +139,7 @@ void i2o_driver_unregister(struct i2o_driver *drv)
139 struct i2o_controller *c; 139 struct i2o_controller *c;
140 unsigned long flags; 140 unsigned long flags;
141 141
142 pr_debug("i2o: unregister driver %s\n", drv->name); 142 osm_debug("unregister driver %s\n", drv->name);
143 143
144 driver_unregister(&drv->driver); 144 driver_unregister(&drv->driver);
145 145
@@ -159,7 +159,7 @@ void i2o_driver_unregister(struct i2o_driver *drv)
159 if (drv->event_queue) { 159 if (drv->event_queue) {
160 destroy_workqueue(drv->event_queue); 160 destroy_workqueue(drv->event_queue);
161 drv->event_queue = NULL; 161 drv->event_queue = NULL;
162 pr_debug("i2o: event queue removed for %s\n", drv->name); 162 osm_debug("event queue removed for %s\n", drv->name);
163 } 163 }
164}; 164};
165 165
@@ -176,68 +176,70 @@ void i2o_driver_unregister(struct i2o_driver *drv)
176 * on success and if the message should be flushed afterwords. Returns 176 * on success and if the message should be flushed afterwords. Returns
177 * negative error code on failure (the message will be flushed too). 177 * negative error code on failure (the message will be flushed too).
178 */ 178 */
179int i2o_driver_dispatch(struct i2o_controller *c, u32 m, 179int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
180 struct i2o_message __iomem *msg)
181{ 180{
182 struct i2o_driver *drv; 181 struct i2o_driver *drv;
183 u32 context = readl(&msg->u.s.icntxt); 182 struct i2o_message *msg = i2o_msg_out_to_virt(c, m);
183 u32 context = le32_to_cpu(msg->u.s.icntxt);
184 unsigned long flags;
184 185
185 if (likely(context < i2o_max_drivers)) { 186 if (unlikely(context >= i2o_max_drivers)) {
186 spin_lock(&i2o_drivers_lock); 187 osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
187 drv = i2o_drivers[context]; 188 context);
188 spin_unlock(&i2o_drivers_lock); 189 return -EIO;
190 }
189 191
190 if (unlikely(!drv)) { 192 spin_lock_irqsave(&i2o_drivers_lock, flags);
191 printk(KERN_WARNING "%s: Spurious reply to unknown " 193 drv = i2o_drivers[context];
192 "driver %d\n", c->name, context); 194 spin_unlock_irqrestore(&i2o_drivers_lock, flags);
193 return -EIO;
194 }
195 195
196 if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { 196 if (unlikely(!drv)) {
197 struct i2o_device *dev, *tmp; 197 osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
198 struct i2o_event *evt; 198 context);
199 u16 size; 199 return -EIO;
200 u16 tid; 200 }
201 201
202 tid = readl(&msg->u.head[1]) & 0x1fff; 202 if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
203 struct i2o_device *dev, *tmp;
204 struct i2o_event *evt;
205 u16 size;
206 u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff;
203 207
204 pr_debug("%s: event received from device %d\n", c->name, 208 osm_debug("event received from device %d\n", tid);
205 tid);
206 209
207 /* cut of header from message size (in 32-bit words) */ 210 if (!drv->event)
208 size = (readl(&msg->u.head[0]) >> 16) - 5; 211 return -EIO;
209 212
210 evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); 213 /* cut of header from message size (in 32-bit words) */
211 if (!evt) 214 size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
212 return -ENOMEM;
213 memset(evt, 0, size * 4 + sizeof(*evt));
214 215
215 evt->size = size; 216 evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
216 memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, 217 if (!evt)
217 (size + 2) * 4); 218 return -ENOMEM;
218 219
219 list_for_each_entry_safe(dev, tmp, &c->devices, list) 220 evt->size = size;
220 if (dev->lct_data.tid == tid) { 221 evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
221 evt->i2o_dev = dev; 222 evt->event_indicator = le32_to_cpu(msg->body[0]);
222 break; 223 memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
223 }
224 224
225 INIT_WORK(&evt->work, (void (*)(void *))drv->event, 225 list_for_each_entry_safe(dev, tmp, &c->devices, list)
226 evt); 226 if (dev->lct_data.tid == tid) {
227 queue_work(drv->event_queue, &evt->work); 227 evt->i2o_dev = dev;
228 return 1; 228 break;
229 } 229 }
230 230
231 if (likely(drv->reply)) 231 INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt);
232 return drv->reply(c, m, msg); 232 queue_work(drv->event_queue, &evt->work);
233 else 233 return 1;
234 pr_debug("%s: Reply to driver %s, but no reply function" 234 }
235 " defined!\n", c->name, drv->name); 235
236 if (unlikely(!drv->reply)) {
237 osm_debug("%s: Reply to driver %s, but no reply function"
238 " defined!\n", c->name, drv->name);
236 return -EIO; 239 return -EIO;
237 } else 240 }
238 printk(KERN_WARNING "%s: Spurious reply to unknown driver " 241
239 "%d\n", c->name, readl(&msg->u.s.icntxt)); 242 return drv->reply(c, m, msg);
240 return -EIO;
241} 243}
242 244
243/** 245/**
@@ -334,11 +336,11 @@ int __init i2o_driver_init(void)
334 if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) || 336 if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
335 ((i2o_max_drivers ^ (i2o_max_drivers - 1)) != 337 ((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
336 (2 * i2o_max_drivers - 1))) { 338 (2 * i2o_max_drivers - 1))) {
337 printk(KERN_WARNING "i2o: max_drivers set to %d, but must be " 339 osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and "
338 ">=2 and <= 64 and a power of 2\n", i2o_max_drivers); 340 "a power of 2\n", i2o_max_drivers);
339 i2o_max_drivers = I2O_MAX_DRIVERS; 341 i2o_max_drivers = I2O_MAX_DRIVERS;
340 } 342 }
341 printk(KERN_INFO "i2o: max drivers = %d\n", i2o_max_drivers); 343 osm_info("max drivers = %d\n", i2o_max_drivers);
342 344
343 i2o_drivers = 345 i2o_drivers =
344 kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); 346 kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 79c1cbfb8f..bda2c62648 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -30,6 +30,7 @@
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/i2o.h> 31#include <linux/i2o.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include "core.h"
33 34
34#define OSM_NAME "exec-osm" 35#define OSM_NAME "exec-osm"
35 36
@@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver;
37 38
38static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); 39static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind);
39 40
40/* Module internal functions from other sources */
41extern int i2o_device_parse_lct(struct i2o_controller *);
42
43/* global wait list for POST WAIT */ 41/* global wait list for POST WAIT */
44static LIST_HEAD(i2o_exec_wait_list); 42static LIST_HEAD(i2o_exec_wait_list);
45 43
@@ -50,7 +48,7 @@ struct i2o_exec_wait {
50 u32 tcntxt; /* transaction context from reply */ 48 u32 tcntxt; /* transaction context from reply */
51 int complete; /* 1 if reply received otherwise 0 */ 49 int complete; /* 1 if reply received otherwise 0 */
52 u32 m; /* message id */ 50 u32 m; /* message id */
53 struct i2o_message __iomem *msg; /* pointer to the reply message */ 51 struct i2o_message *msg; /* pointer to the reply message */
54 struct list_head list; /* node in global wait list */ 52 struct list_head list; /* node in global wait list */
55}; 53};
56 54
@@ -108,7 +106,8 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
108 * buffer must not be freed. Instead the event completion will free them 106 * buffer must not be freed. Instead the event completion will free them
109 * for you. In all other cases the buffer are your problem. 107 * for you. In all other cases the buffer are your problem.
110 * 108 *
111 * Returns 0 on success or negative error code on failure. 109 * Returns 0 on success, negative error code on timeout or positive error
110 * code from reply.
112 */ 111 */
113int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long 112int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
114 timeout, struct i2o_dma *dma) 113 timeout, struct i2o_dma *dma)
@@ -116,7 +115,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
116 DECLARE_WAIT_QUEUE_HEAD(wq); 115 DECLARE_WAIT_QUEUE_HEAD(wq);
117 struct i2o_exec_wait *wait; 116 struct i2o_exec_wait *wait;
118 static u32 tcntxt = 0x80000000; 117 static u32 tcntxt = 0x80000000;
119 struct i2o_message __iomem *msg = c->in_queue.virt + m; 118 struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
120 int rc = 0; 119 int rc = 0;
121 120
122 wait = i2o_exec_wait_alloc(); 121 wait = i2o_exec_wait_alloc();
@@ -153,7 +152,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
153 list_add(&wait->list, &i2o_exec_wait_list); 152 list_add(&wait->list, &i2o_exec_wait_list);
154 153
155 wait_event_interruptible_timeout(wq, wait->complete, 154 wait_event_interruptible_timeout(wq, wait->complete,
156 timeout * HZ); 155 timeout * HZ);
157 156
158 wait->wq = NULL; 157 wait->wq = NULL;
159 } 158 }
@@ -161,8 +160,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
161 barrier(); 160 barrier();
162 161
163 if (wait->complete) { 162 if (wait->complete) {
164 if (readl(&wait->msg->body[0]) >> 24) 163 rc = le32_to_cpu(wait->msg->body[0]) >> 24;
165 rc = readl(&wait->msg->body[0]) & 0xff;
166 i2o_flush_reply(c, wait->m); 164 i2o_flush_reply(c, wait->m);
167 i2o_exec_wait_free(wait); 165 i2o_exec_wait_free(wait);
168 } else { 166 } else {
@@ -187,6 +185,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
187 * @c: I2O controller which answers 185 * @c: I2O controller which answers
188 * @m: message id 186 * @m: message id
189 * @msg: pointer to the I2O reply message 187 * @msg: pointer to the I2O reply message
188 * @context: transaction context of request
190 * 189 *
191 * This function is called in interrupt context only. If the reply reached 190 * This function is called in interrupt context only. If the reply reached
192 * before the timeout, the i2o_exec_wait struct is filled with the message 191 * before the timeout, the i2o_exec_wait struct is filled with the message
@@ -201,16 +200,12 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
201 * message must also be given back to the controller. 200 * message must also be given back to the controller.
202 */ 201 */
203static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, 202static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
204 struct i2o_message __iomem *msg) 203 struct i2o_message *msg, u32 context)
205{ 204{
206 struct i2o_exec_wait *wait, *tmp; 205 struct i2o_exec_wait *wait, *tmp;
207 static spinlock_t lock; 206 unsigned long flags;
207 static spinlock_t lock = SPIN_LOCK_UNLOCKED;
208 int rc = 1; 208 int rc = 1;
209 u32 context;
210
211 spin_lock_init(&lock);
212
213 context = readl(&msg->u.s.tcntxt);
214 209
215 /* 210 /*
216 * We need to search through the i2o_exec_wait_list to see if the given 211 * We need to search through the i2o_exec_wait_list to see if the given
@@ -219,11 +214,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
219 * already expired. Not much we can do about that except log it for 214 * already expired. Not much we can do about that except log it for
220 * debug purposes, increase timeout, and recompile. 215 * debug purposes, increase timeout, and recompile.
221 */ 216 */
222 spin_lock(&lock); 217 spin_lock_irqsave(&lock, flags);
223 list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { 218 list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
224 if (wait->tcntxt == context) { 219 if (wait->tcntxt == context) {
225 list_del(&wait->list); 220 list_del(&wait->list);
226 221
222 spin_unlock_irqrestore(&lock, flags);
223
227 wait->m = m; 224 wait->m = m;
228 wait->msg = msg; 225 wait->msg = msg;
229 wait->complete = 1; 226 wait->complete = 1;
@@ -245,21 +242,63 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
245 rc = -1; 242 rc = -1;
246 } 243 }
247 244
248 spin_unlock(&lock);
249
250 return rc; 245 return rc;
251 } 246 }
252 } 247 }
253 248
254 spin_unlock(&lock); 249 spin_unlock_irqrestore(&lock, flags);
255 250
256 pr_debug("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, 251 osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
257 context); 252 context);
258 253
259 return -1; 254 return -1;
260}; 255};
261 256
262/** 257/**
258 * i2o_exec_show_vendor_id - Displays Vendor ID of controller
259 * @d: device of which the Vendor ID should be displayed
260 * @buf: buffer into which the Vendor ID should be printed
261 *
262 * Returns number of bytes printed into buffer.
263 */
264static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf)
265{
266 struct i2o_device *dev = to_i2o_device(d);
267 u16 id;
268
269 if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
270 sprintf(buf, "0x%04x", id);
271 return strlen(buf) + 1;
272 }
273
274 return 0;
275};
276
277/**
278 * i2o_exec_show_product_id - Displays Product ID of controller
279 * @d: device of which the Product ID should be displayed
280 * @buf: buffer into which the Product ID should be printed
281 *
282 * Returns number of bytes printed into buffer.
283 */
284static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf)
285{
286 struct i2o_device *dev = to_i2o_device(d);
287 u16 id;
288
289 if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
290 sprintf(buf, "0x%04x", id);
291 return strlen(buf) + 1;
292 }
293
294 return 0;
295};
296
297/* Exec-OSM device attributes */
298static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL);
299static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL);
300
301/**
263 * i2o_exec_probe - Called if a new I2O device (executive class) appears 302 * i2o_exec_probe - Called if a new I2O device (executive class) appears
264 * @dev: I2O device which should be probed 303 * @dev: I2O device which should be probed
265 * 304 *
@@ -271,10 +310,16 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
271static int i2o_exec_probe(struct device *dev) 310static int i2o_exec_probe(struct device *dev)
272{ 311{
273 struct i2o_device *i2o_dev = to_i2o_device(dev); 312 struct i2o_device *i2o_dev = to_i2o_device(dev);
313 struct i2o_controller *c = i2o_dev->iop;
274 314
275 i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); 315 i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
276 316
277 i2o_dev->iop->exec = i2o_dev; 317 c->exec = i2o_dev;
318
319 i2o_exec_lct_notify(c, c->lct->change_ind + 1);
320
321 device_create_file(dev, &dev_attr_vendor_id);
322 device_create_file(dev, &dev_attr_product_id);
278 323
279 return 0; 324 return 0;
280}; 325};
@@ -289,6 +334,9 @@ static int i2o_exec_probe(struct device *dev)
289 */ 334 */
290static int i2o_exec_remove(struct device *dev) 335static int i2o_exec_remove(struct device *dev)
291{ 336{
337 device_remove_file(dev, &dev_attr_product_id);
338 device_remove_file(dev, &dev_attr_vendor_id);
339
292 i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); 340 i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
293 341
294 return 0; 342 return 0;
@@ -300,12 +348,16 @@ static int i2o_exec_remove(struct device *dev)
300 * 348 *
301 * This function handles asynchronus LCT NOTIFY replies. It parses the 349 * This function handles asynchronus LCT NOTIFY replies. It parses the
302 * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY 350 * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
303 * again. 351 * again, otherwise send LCT NOTIFY to get informed on next LCT change.
304 */ 352 */
305static void i2o_exec_lct_modified(struct i2o_controller *c) 353static void i2o_exec_lct_modified(struct i2o_controller *c)
306{ 354{
307 if (i2o_device_parse_lct(c) == -EAGAIN) 355 u32 change_ind = 0;
308 i2o_exec_lct_notify(c, 0); 356
357 if (i2o_device_parse_lct(c) != -EAGAIN)
358 change_ind = c->lct->change_ind + 1;
359
360 i2o_exec_lct_notify(c, change_ind);
309}; 361};
310 362
311/** 363/**
@@ -325,8 +377,14 @@ static void i2o_exec_lct_modified(struct i2o_controller *c)
325static int i2o_exec_reply(struct i2o_controller *c, u32 m, 377static int i2o_exec_reply(struct i2o_controller *c, u32 m,
326 struct i2o_message *msg) 378 struct i2o_message *msg)
327{ 379{
328 if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { // Fail bit is set 380 u32 context;
329 struct i2o_message __iomem *pmsg; /* preserved message */ 381
382 if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) {
383 /*
384 * If Fail bit is set we must take the transaction context of
385 * the preserved message to find the right request again.
386 */
387 struct i2o_message __iomem *pmsg;
330 u32 pm; 388 u32 pm;
331 389
332 pm = le32_to_cpu(msg->body[3]); 390 pm = le32_to_cpu(msg->body[3]);
@@ -335,15 +393,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
335 393
336 i2o_report_status(KERN_INFO, "i2o_core", msg); 394 i2o_report_status(KERN_INFO, "i2o_core", msg);
337 395
338 /* Release the preserved msg by resubmitting it as a NOP */ 396 context = readl(&pmsg->u.s.tcntxt);
339 i2o_msg_nop(c, pm);
340 397
341 /* If reply to i2o_post_wait failed, return causes a timeout */ 398 /* Release the preserved msg */
342 return -1; 399 i2o_msg_nop(c, pm);
343 } 400 } else
401 context = le32_to_cpu(msg->u.s.tcntxt);
344 402
345 if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000) 403 if (context & 0x80000000)
346 return i2o_msg_post_wait_complete(c, m, msg); 404 return i2o_msg_post_wait_complete(c, m, msg, context);
347 405
348 if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { 406 if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
349 struct work_struct *work; 407 struct work_struct *work;
@@ -381,8 +439,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
381 */ 439 */
382static void i2o_exec_event(struct i2o_event *evt) 440static void i2o_exec_event(struct i2o_event *evt)
383{ 441{
384 osm_info("Event received from device: %d\n", 442 if (likely(evt->i2o_dev))
385 evt->i2o_dev->lct_data.tid); 443 osm_debug("Event received from device: %d\n",
444 evt->i2o_dev->lct_data.tid);
386 kfree(evt); 445 kfree(evt);
387}; 446};
388 447
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 4830b77590..f283b5bafd 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -62,7 +62,7 @@
62#include "i2o_block.h" 62#include "i2o_block.h"
63 63
64#define OSM_NAME "block-osm" 64#define OSM_NAME "block-osm"
65#define OSM_VERSION "$Rev$" 65#define OSM_VERSION "1.287"
66#define OSM_DESCRIPTION "I2O Block Device OSM" 66#define OSM_DESCRIPTION "I2O Block Device OSM"
67 67
68static struct i2o_driver i2o_block_driver; 68static struct i2o_driver i2o_block_driver;
@@ -104,7 +104,8 @@ static int i2o_block_remove(struct device *dev)
104 struct i2o_device *i2o_dev = to_i2o_device(dev); 104 struct i2o_device *i2o_dev = to_i2o_device(dev);
105 struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev); 105 struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev);
106 106
107 osm_info("Device removed %s\n", i2o_blk_dev->gd->disk_name); 107 osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid,
108 i2o_blk_dev->gd->disk_name);
108 109
109 i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0); 110 i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);
110 111
@@ -146,6 +147,29 @@ static int i2o_block_device_flush(struct i2o_device *dev)
146}; 147};
147 148
148/** 149/**
150 * i2o_block_issue_flush - device-flush interface for block-layer
151 * @queue: the request queue of the device which should be flushed
152 * @disk: gendisk
153 * @error_sector: error offset
154 *
155 * Helper function to provide flush functionality to block-layer.
156 *
157 * Returns 0 on success or negative error code on failure.
158 */
159
160static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk,
161 sector_t * error_sector)
162{
163 struct i2o_block_device *i2o_blk_dev = queue->queuedata;
164 int rc = -ENODEV;
165
166 if (likely(i2o_blk_dev))
167 rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev);
168
169 return rc;
170}
171
172/**
149 * i2o_block_device_mount - Mount (load) the media of device dev 173 * i2o_block_device_mount - Mount (load) the media of device dev
150 * @dev: I2O device which should receive the mount request 174 * @dev: I2O device which should receive the mount request
151 * @media_id: Media Identifier 175 * @media_id: Media Identifier
@@ -298,28 +322,31 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq)
298 322
299/** 323/**
300 * i2o_block_sglist_alloc - Allocate the SG list and map it 324 * i2o_block_sglist_alloc - Allocate the SG list and map it
325 * @c: I2O controller to which the request belongs
301 * @ireq: I2O block request 326 * @ireq: I2O block request
302 * 327 *
303 * Builds the SG list and map it into to be accessable by the controller. 328 * Builds the SG list and map it to be accessable by the controller.
304 * 329 *
305 * Returns the number of elements in the SG list or 0 on failure. 330 * Returns 0 on failure or 1 on success.
306 */ 331 */
307static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq) 332static inline int i2o_block_sglist_alloc(struct i2o_controller *c,
333 struct i2o_block_request *ireq,
334 u32 __iomem ** mptr)
308{ 335{
309 struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
310 int nents; 336 int nents;
337 enum dma_data_direction direction;
311 338
339 ireq->dev = &c->pdev->dev;
312 nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); 340 nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table);
313 341
314 if (rq_data_dir(ireq->req) == READ) 342 if (rq_data_dir(ireq->req) == READ)
315 ireq->sg_dma_direction = PCI_DMA_FROMDEVICE; 343 direction = PCI_DMA_FROMDEVICE;
316 else 344 else
317 ireq->sg_dma_direction = PCI_DMA_TODEVICE; 345 direction = PCI_DMA_TODEVICE;
318 346
319 ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents, 347 ireq->sg_nents = nents;
320 ireq->sg_dma_direction);
321 348
322 return ireq->sg_nents; 349 return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr);
323}; 350};
324 351
325/** 352/**
@@ -330,10 +357,14 @@ static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq)
330 */ 357 */
331static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) 358static inline void i2o_block_sglist_free(struct i2o_block_request *ireq)
332{ 359{
333 struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; 360 enum dma_data_direction direction;
334 361
335 dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents, 362 if (rq_data_dir(ireq->req) == READ)
336 ireq->sg_dma_direction); 363 direction = PCI_DMA_FROMDEVICE;
364 else
365 direction = PCI_DMA_TODEVICE;
366
367 dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction);
337}; 368};
338 369
339/** 370/**
@@ -351,6 +382,11 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
351 struct i2o_block_device *i2o_blk_dev = q->queuedata; 382 struct i2o_block_device *i2o_blk_dev = q->queuedata;
352 struct i2o_block_request *ireq; 383 struct i2o_block_request *ireq;
353 384
385 if (unlikely(!i2o_blk_dev)) {
386 osm_err("block device already removed\n");
387 return BLKPREP_KILL;
388 }
389
354 /* request is already processed by us, so return */ 390 /* request is already processed by us, so return */
355 if (req->flags & REQ_SPECIAL) { 391 if (req->flags & REQ_SPECIAL) {
356 osm_debug("REQ_SPECIAL already set!\n"); 392 osm_debug("REQ_SPECIAL already set!\n");
@@ -400,71 +436,65 @@ static void i2o_block_delayed_request_fn(void *delayed_request)
400}; 436};
401 437
402/** 438/**
403 * i2o_block_reply - Block OSM reply handler. 439 * i2o_block_end_request - Post-processing of completed commands
404 * @c: I2O controller from which the message arrives 440 * @req: request which should be completed
405 * @m: message id of reply 441 * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
406 * qmsg: the actuall I2O message reply 442 * @nr_bytes: number of bytes to complete
407 * 443 *
408 * This function gets all the message replies. 444 * Mark the request as complete. The lock must not be held when entering.
409 * 445 *
410 */ 446 */
411static int i2o_block_reply(struct i2o_controller *c, u32 m, 447static void i2o_block_end_request(struct request *req, int uptodate,
412 struct i2o_message *msg) 448 int nr_bytes)
413{ 449{
414 struct i2o_block_request *ireq; 450 struct i2o_block_request *ireq = req->special;
415 struct request *req; 451 struct i2o_block_device *dev = ireq->i2o_blk_dev;
416 struct i2o_block_device *dev; 452 request_queue_t *q = req->q;
417 struct request_queue *q;
418 u8 st;
419 unsigned long flags; 453 unsigned long flags;
420 454
421 /* FAILed message */ 455 if (end_that_request_chunk(req, uptodate, nr_bytes)) {
422 if (unlikely(le32_to_cpu(msg->u.head[0]) & (1 << 13))) { 456 int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT);
423 struct i2o_message *pmsg;
424 u32 pm;
425 457
426 /* 458 if (blk_pc_request(req))
427 * FAILed message from controller 459 leftover = req->data_len;
428 * We increment the error count and abort it
429 *
430 * In theory this will never happen. The I2O block class
431 * specification states that block devices never return
432 * FAILs but instead use the REQ status field...but
433 * better be on the safe side since no one really follows
434 * the spec to the book :)
435 */
436 pm = le32_to_cpu(msg->body[3]);
437 pmsg = i2o_msg_in_to_virt(c, pm);
438 460
439 req = i2o_cntxt_list_get(c, le32_to_cpu(pmsg->u.s.tcntxt)); 461 if (end_io_error(uptodate))
440 if (unlikely(!req)) { 462 end_that_request_chunk(req, 0, leftover);
441 osm_err("NULL reply received!\n"); 463 }
442 return -1;
443 }
444 464
445 ireq = req->special; 465 add_disk_randomness(req->rq_disk);
446 dev = ireq->i2o_blk_dev;
447 q = dev->gd->queue;
448 466
449 req->errors++; 467 spin_lock_irqsave(q->queue_lock, flags);
450
451 spin_lock_irqsave(q->queue_lock, flags);
452 468
453 while (end_that_request_chunk(req, !req->errors, 469 end_that_request_last(req);
454 le32_to_cpu(pmsg->body[1]))) ;
455 end_that_request_last(req);
456 470
471 if (likely(dev)) {
457 dev->open_queue_depth--; 472 dev->open_queue_depth--;
458 list_del(&ireq->queue); 473 list_del(&ireq->queue);
459 blk_start_queue(q); 474 }
460 475
461 spin_unlock_irqrestore(q->queue_lock, flags); 476 blk_start_queue(q);
462 477
463 /* Now flush the message by making it a NOP */ 478 spin_unlock_irqrestore(q->queue_lock, flags);
464 i2o_msg_nop(c, pm);
465 479
466 return -1; 480 i2o_block_sglist_free(ireq);
467 } 481 i2o_block_request_free(ireq);
482};
483
484/**
485 * i2o_block_reply - Block OSM reply handler.
486 * @c: I2O controller from which the message arrives
487 * @m: message id of reply
488 * qmsg: the actuall I2O message reply
489 *
490 * This function gets all the message replies.
491 *
492 */
493static int i2o_block_reply(struct i2o_controller *c, u32 m,
494 struct i2o_message *msg)
495{
496 struct request *req;
497 int uptodate = 1;
468 498
469 req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); 499 req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
470 if (unlikely(!req)) { 500 if (unlikely(!req)) {
@@ -472,61 +502,13 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
472 return -1; 502 return -1;
473 } 503 }
474 504
475 ireq = req->special;
476 dev = ireq->i2o_blk_dev;
477 q = dev->gd->queue;
478
479 if (unlikely(!dev->i2o_dev)) {
480 /*
481 * This is HACK, but Intel Integrated RAID allows user
482 * to delete a volume that is claimed, locked, and in use
483 * by the OS. We have to check for a reply from a
484 * non-existent device and flag it as an error or the system
485 * goes kaput...
486 */
487 req->errors++;
488 osm_warn("Data transfer to deleted device!\n");
489 spin_lock_irqsave(q->queue_lock, flags);
490 while (end_that_request_chunk
491 (req, !req->errors, le32_to_cpu(msg->body[1]))) ;
492 end_that_request_last(req);
493
494 dev->open_queue_depth--;
495 list_del(&ireq->queue);
496 blk_start_queue(q);
497
498 spin_unlock_irqrestore(q->queue_lock, flags);
499 return -1;
500 }
501
502 /* 505 /*
503 * Lets see what is cooking. We stuffed the 506 * Lets see what is cooking. We stuffed the
504 * request in the context. 507 * request in the context.
505 */ 508 */
506 509
507 st = le32_to_cpu(msg->body[0]) >> 24; 510 if ((le32_to_cpu(msg->body[0]) >> 24) != 0) {
508 511 u32 status = le32_to_cpu(msg->body[0]);
509 if (st != 0) {
510 int err;
511 char *bsa_errors[] = {
512 "Success",
513 "Media Error",
514 "Failure communicating to device",
515 "Device Failure",
516 "Device is not ready",
517 "Media not present",
518 "Media is locked by another user",
519 "Media has failed",
520 "Failure communicating to device",
521 "Device bus failure",
522 "Device is locked by another user",
523 "Device is write protected",
524 "Device has reset",
525 "Volume has changed, waiting for acknowledgement"
526 };
527
528 err = le32_to_cpu(msg->body[0]) & 0xffff;
529
530 /* 512 /*
531 * Device not ready means two things. One is that the 513 * Device not ready means two things. One is that the
532 * the thing went offline (but not a removal media) 514 * the thing went offline (but not a removal media)
@@ -539,40 +521,23 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
539 * Don't stick a supertrak100 into cache aggressive modes 521 * Don't stick a supertrak100 into cache aggressive modes
540 */ 522 */
541 523
542 osm_err("block-osm: /dev/%s error: %s", dev->gd->disk_name, 524 osm_err("TID %03x error status: 0x%02x, detailed status: "
543 bsa_errors[le32_to_cpu(msg->body[0]) & 0xffff]); 525 "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff),
544 if (le32_to_cpu(msg->body[0]) & 0x00ff0000) 526 status >> 24, status & 0xffff);
545 printk(KERN_ERR " - DDM attempted %d retries",
546 (le32_to_cpu(msg->body[0]) >> 16) & 0x00ff);
547 printk(KERN_ERR ".\n");
548 req->errors++;
549 } else
550 req->errors = 0;
551 527
552 if (!end_that_request_chunk 528 req->errors++;
553 (req, !req->errors, le32_to_cpu(msg->body[1]))) {
554 add_disk_randomness(req->rq_disk);
555 spin_lock_irqsave(q->queue_lock, flags);
556
557 end_that_request_last(req);
558 529
559 dev->open_queue_depth--; 530 uptodate = 0;
560 list_del(&ireq->queue); 531 }
561 blk_start_queue(q);
562 532
563 spin_unlock_irqrestore(q->queue_lock, flags); 533 i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1]));
564
565 i2o_block_sglist_free(ireq);
566 i2o_block_request_free(ireq);
567 } else
568 osm_err("still remaining chunks\n");
569 534
570 return 1; 535 return 1;
571}; 536};
572 537
573static void i2o_block_event(struct i2o_event *evt) 538static void i2o_block_event(struct i2o_event *evt)
574{ 539{
575 osm_info("block-osm: event received\n"); 540 osm_debug("event received\n");
576 kfree(evt); 541 kfree(evt);
577}; 542};
578 543
@@ -778,18 +743,25 @@ static int i2o_block_media_changed(struct gendisk *disk)
778static int i2o_block_transfer(struct request *req) 743static int i2o_block_transfer(struct request *req)
779{ 744{
780 struct i2o_block_device *dev = req->rq_disk->private_data; 745 struct i2o_block_device *dev = req->rq_disk->private_data;
781 struct i2o_controller *c = dev->i2o_dev->iop; 746 struct i2o_controller *c;
782 int tid = dev->i2o_dev->lct_data.tid; 747 int tid = dev->i2o_dev->lct_data.tid;
783 struct i2o_message __iomem *msg; 748 struct i2o_message __iomem *msg;
784 void __iomem *mptr; 749 u32 __iomem *mptr;
785 struct i2o_block_request *ireq = req->special; 750 struct i2o_block_request *ireq = req->special;
786 struct scatterlist *sg;
787 int sgnum;
788 int i;
789 u32 m; 751 u32 m;
790 u32 tcntxt; 752 u32 tcntxt;
791 u32 sg_flags; 753 u32 sgl_offset = SGL_OFFSET_8;
754 u32 ctl_flags = 0x00000000;
792 int rc; 755 int rc;
756 u32 cmd;
757
758 if (unlikely(!dev->i2o_dev)) {
759 osm_err("transfer to removed drive\n");
760 rc = -ENODEV;
761 goto exit;
762 }
763
764 c = dev->i2o_dev->iop;
793 765
794 m = i2o_msg_get(c, &msg); 766 m = i2o_msg_get(c, &msg);
795 if (m == I2O_QUEUE_EMPTY) { 767 if (m == I2O_QUEUE_EMPTY) {
@@ -803,82 +775,109 @@ static int i2o_block_transfer(struct request *req)
803 goto nop_msg; 775 goto nop_msg;
804 } 776 }
805 777
806 if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) {
807 rc = -ENOMEM;
808 goto context_remove;
809 }
810
811 /* Build the message based on the request. */
812 writel(i2o_block_driver.context, &msg->u.s.icntxt); 778 writel(i2o_block_driver.context, &msg->u.s.icntxt);
813 writel(tcntxt, &msg->u.s.tcntxt); 779 writel(tcntxt, &msg->u.s.tcntxt);
814 writel(req->nr_sectors << 9, &msg->body[1]);
815
816 writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]);
817 writel(req->sector >> 23, &msg->body[3]);
818 780
819 mptr = &msg->body[4]; 781 mptr = &msg->body[0];
820
821 sg = ireq->sg_table;
822 782
823 if (rq_data_dir(req) == READ) { 783 if (rq_data_dir(req) == READ) {
824 writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid, 784 cmd = I2O_CMD_BLOCK_READ << 24;
825 &msg->u.head[1]); 785
826 sg_flags = 0x10000000;
827 switch (dev->rcache) { 786 switch (dev->rcache) {
828 case CACHE_NULL:
829 writel(0, &msg->body[0]);
830 break;
831 case CACHE_PREFETCH: 787 case CACHE_PREFETCH:
832 writel(0x201F0008, &msg->body[0]); 788 ctl_flags = 0x201F0008;
833 break; 789 break;
790
834 case CACHE_SMARTFETCH: 791 case CACHE_SMARTFETCH:
835 if (req->nr_sectors > 16) 792 if (req->nr_sectors > 16)
836 writel(0x201F0008, &msg->body[0]); 793 ctl_flags = 0x201F0008;
837 else 794 else
838 writel(0x001F0000, &msg->body[0]); 795 ctl_flags = 0x001F0000;
796 break;
797
798 default:
839 break; 799 break;
840 } 800 }
841 } else { 801 } else {
842 writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid, 802 cmd = I2O_CMD_BLOCK_WRITE << 24;
843 &msg->u.head[1]); 803
844 sg_flags = 0x14000000;
845 switch (dev->wcache) { 804 switch (dev->wcache) {
846 case CACHE_NULL:
847 writel(0, &msg->body[0]);
848 break;
849 case CACHE_WRITETHROUGH: 805 case CACHE_WRITETHROUGH:
850 writel(0x001F0008, &msg->body[0]); 806 ctl_flags = 0x001F0008;
851 break; 807 break;
852 case CACHE_WRITEBACK: 808 case CACHE_WRITEBACK:
853 writel(0x001F0010, &msg->body[0]); 809 ctl_flags = 0x001F0010;
854 break; 810 break;
855 case CACHE_SMARTBACK: 811 case CACHE_SMARTBACK:
856 if (req->nr_sectors > 16) 812 if (req->nr_sectors > 16)
857 writel(0x001F0004, &msg->body[0]); 813 ctl_flags = 0x001F0004;
858 else 814 else
859 writel(0x001F0010, &msg->body[0]); 815 ctl_flags = 0x001F0010;
860 break; 816 break;
861 case CACHE_SMARTTHROUGH: 817 case CACHE_SMARTTHROUGH:
862 if (req->nr_sectors > 16) 818 if (req->nr_sectors > 16)
863 writel(0x001F0004, &msg->body[0]); 819 ctl_flags = 0x001F0004;
864 else 820 else
865 writel(0x001F0010, &msg->body[0]); 821 ctl_flags = 0x001F0010;
822 default:
823 break;
824 }
825 }
826
827#ifdef CONFIG_I2O_EXT_ADAPTEC
828 if (c->adaptec) {
829 u8 cmd[10];
830 u32 scsi_flags;
831 u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT;
832
833 memset(cmd, 0, 10);
834
835 sgl_offset = SGL_OFFSET_12;
836
837 writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid,
838 &msg->u.head[1]);
839
840 writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
841 writel(tid, mptr++);
842
843 /*
844 * ENABLE_DISCONNECT
845 * SIMPLE_TAG
846 * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
847 */
848 if (rq_data_dir(req) == READ) {
849 cmd[0] = 0x28;
850 scsi_flags = 0x60a0000a;
851 } else {
852 cmd[0] = 0x2A;
853 scsi_flags = 0xa0a0000a;
866 } 854 }
855
856 writel(scsi_flags, mptr++);
857
858 *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec);
859 *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec);
860
861 memcpy_toio(mptr, cmd, 10);
862 mptr += 4;
863 writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
864 } else
865#endif
866 {
867 writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
868 writel(ctl_flags, mptr++);
869 writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
870 writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++);
871 writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++);
867 } 872 }
868 873
869 for (i = sgnum; i > 0; i--) { 874 if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
870 if (i == 1) 875 rc = -ENOMEM;
871 sg_flags |= 0x80000000; 876 goto context_remove;
872 writel(sg_flags | sg_dma_len(sg), mptr);
873 writel(sg_dma_address(sg), mptr + 4);
874 mptr += 8;
875 sg++;
876 } 877 }
877 878
878 writel(I2O_MESSAGE_SIZE 879 writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) |
879 (((unsigned long)mptr - 880 sgl_offset, &msg->u.head[0]);
880 (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8,
881 &msg->u.head[0]);
882 881
883 list_add_tail(&ireq->queue, &dev->open_queue); 882 list_add_tail(&ireq->queue, &dev->open_queue);
884 dev->open_queue_depth++; 883 dev->open_queue_depth++;
@@ -921,11 +920,13 @@ static void i2o_block_request_fn(struct request_queue *q)
921 920
922 queue_depth = ireq->i2o_blk_dev->open_queue_depth; 921 queue_depth = ireq->i2o_blk_dev->open_queue_depth;
923 922
924 if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) 923 if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) {
925 if (!i2o_block_transfer(req)) { 924 if (!i2o_block_transfer(req)) {
926 blkdev_dequeue_request(req); 925 blkdev_dequeue_request(req);
927 continue; 926 continue;
928 } 927 } else
928 osm_info("transfer error\n");
929 }
929 930
930 if (queue_depth) 931 if (queue_depth)
931 break; 932 break;
@@ -939,7 +940,6 @@ static void i2o_block_request_fn(struct request_queue *q)
939 INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, 940 INIT_WORK(&dreq->work, i2o_block_delayed_request_fn,
940 dreq); 941 dreq);
941 942
942 osm_info("transfer error\n");
943 if (!queue_delayed_work(i2o_block_driver.event_queue, 943 if (!queue_delayed_work(i2o_block_driver.event_queue,
944 &dreq->work, 944 &dreq->work,
945 I2O_BLOCK_RETRY_TIME)) 945 I2O_BLOCK_RETRY_TIME))
@@ -1008,6 +1008,7 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
1008 } 1008 }
1009 1009
1010 blk_queue_prep_rq(queue, i2o_block_prep_req_fn); 1010 blk_queue_prep_rq(queue, i2o_block_prep_req_fn);
1011 blk_queue_issue_flush_fn(queue, i2o_block_issue_flush);
1011 1012
1012 gd->major = I2O_MAJOR; 1013 gd->major = I2O_MAJOR;
1013 gd->queue = queue; 1014 gd->queue = queue;
@@ -1040,17 +1041,27 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
1040static int i2o_block_probe(struct device *dev) 1041static int i2o_block_probe(struct device *dev)
1041{ 1042{
1042 struct i2o_device *i2o_dev = to_i2o_device(dev); 1043 struct i2o_device *i2o_dev = to_i2o_device(dev);
1043 struct i2o_block_device *i2o_blk_dev;
1044 struct i2o_controller *c = i2o_dev->iop; 1044 struct i2o_controller *c = i2o_dev->iop;
1045 struct i2o_block_device *i2o_blk_dev;
1045 struct gendisk *gd; 1046 struct gendisk *gd;
1046 struct request_queue *queue; 1047 struct request_queue *queue;
1047 static int unit = 0; 1048 static int unit = 0;
1048 int rc; 1049 int rc;
1049 u64 size; 1050 u64 size;
1050 u32 blocksize; 1051 u32 blocksize;
1051 u16 power;
1052 u32 flags, status; 1052 u32 flags, status;
1053 int segments; 1053 u16 body_size = 4;
1054 unsigned short max_sectors;
1055
1056#ifdef CONFIG_I2O_EXT_ADAPTEC
1057 if (c->adaptec)
1058 body_size = 8;
1059#endif
1060
1061 if (c->limit_sectors)
1062 max_sectors = I2O_MAX_SECTORS_LIMITED;
1063 else
1064 max_sectors = I2O_MAX_SECTORS;
1054 1065
1055 /* skip devices which are used by IOP */ 1066 /* skip devices which are used by IOP */
1056 if (i2o_dev->lct_data.user_tid != 0xfff) { 1067 if (i2o_dev->lct_data.user_tid != 0xfff) {
@@ -1058,8 +1069,6 @@ static int i2o_block_probe(struct device *dev)
1058 return -ENODEV; 1069 return -ENODEV;
1059 } 1070 }
1060 1071
1061 osm_info("New device detected (TID: %03x)\n", i2o_dev->lct_data.tid);
1062
1063 if (i2o_device_claim(i2o_dev)) { 1072 if (i2o_device_claim(i2o_dev)) {
1064 osm_warn("Unable to claim device. Installation aborted\n"); 1073 osm_warn("Unable to claim device. Installation aborted\n");
1065 rc = -EFAULT; 1074 rc = -EFAULT;
@@ -1087,50 +1096,44 @@ static int i2o_block_probe(struct device *dev)
1087 queue = gd->queue; 1096 queue = gd->queue;
1088 queue->queuedata = i2o_blk_dev; 1097 queue->queuedata = i2o_blk_dev;
1089 1098
1090 blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS); 1099 blk_queue_max_phys_segments(queue, I2O_MAX_PHYS_SEGMENTS);
1091 blk_queue_max_sectors(queue, I2O_MAX_SECTORS); 1100 blk_queue_max_sectors(queue, max_sectors);
1092 1101 blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size));
1093 if (c->short_req)
1094 segments = 8;
1095 else {
1096 i2o_status_block *sb;
1097 1102
1098 sb = c->status_block.virt; 1103 osm_debug("max sectors = %d\n", queue->max_phys_segments);
1099 1104 osm_debug("phys segments = %d\n", queue->max_sectors);
1100 segments = (sb->inbound_frame_size - 1105 osm_debug("max hw segments = %d\n", queue->max_hw_segments);
1101 sizeof(struct i2o_message) / 4 - 4) / 2;
1102 }
1103
1104 blk_queue_max_hw_segments(queue, segments);
1105
1106 osm_debug("max sectors = %d\n", I2O_MAX_SECTORS);
1107 osm_debug("phys segments = %d\n", I2O_MAX_SEGMENTS);
1108 osm_debug("hw segments = %d\n", segments);
1109 1106
1110 /* 1107 /*
1111 * Ask for the current media data. If that isn't supported 1108 * Ask for the current media data. If that isn't supported
1112 * then we ask for the device capacity data 1109 * then we ask for the device capacity data
1113 */ 1110 */
1114 if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0 1111 if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
1115 || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) { 1112 i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
1116 i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4); 1113 blk_queue_hardsect_size(queue, blocksize);
1117 i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8); 1114 } else
1118 } 1115 osm_warn("unable to get blocksize of %s\n", gd->disk_name);
1119 osm_debug("blocksize = %d\n", blocksize);
1120 1116
1121 if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) 1117 if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
1122 power = 0; 1118 i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
1119 set_capacity(gd, size >> KERNEL_SECTOR_SHIFT);
1120 } else
1121 osm_warn("could not get size of %s\n", gd->disk_name);
1122
1123 if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2))
1124 i2o_blk_dev->power = 0;
1123 i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4); 1125 i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
1124 i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4); 1126 i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
1125 1127
1126 set_capacity(gd, size >> 9);
1127
1128 i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); 1128 i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
1129 1129
1130 add_disk(gd); 1130 add_disk(gd);
1131 1131
1132 unit++; 1132 unit++;
1133 1133
1134 osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid,
1135 i2o_blk_dev->gd->disk_name);
1136
1134 return 0; 1137 return 0;
1135 1138
1136 claim_release: 1139 claim_release:
@@ -1178,7 +1181,7 @@ static int __init i2o_block_init(void)
1178 goto exit; 1181 goto exit;
1179 } 1182 }
1180 1183
1181 i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE, 1184 i2o_blk_req_pool.pool = mempool_create(I2O_BLOCK_REQ_MEMPOOL_SIZE,
1182 mempool_alloc_slab, 1185 mempool_alloc_slab,
1183 mempool_free_slab, 1186 mempool_free_slab,
1184 i2o_blk_req_pool.slab); 1187 i2o_blk_req_pool.slab);
diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h
index ddd9a15679..4fdaa5bda4 100644
--- a/drivers/message/i2o/i2o_block.h
+++ b/drivers/message/i2o/i2o_block.h
@@ -56,42 +56,46 @@
56#define I2O_BLOCK_RETRY_TIME HZ/4 56#define I2O_BLOCK_RETRY_TIME HZ/4
57#define I2O_BLOCK_MAX_OPEN_REQUESTS 50 57#define I2O_BLOCK_MAX_OPEN_REQUESTS 50
58 58
59/* request queue sizes */
60#define I2O_BLOCK_REQ_MEMPOOL_SIZE 32
61
62#define KERNEL_SECTOR_SHIFT 9
63#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT)
64
59/* I2O Block OSM mempool struct */ 65/* I2O Block OSM mempool struct */
60struct i2o_block_mempool { 66struct i2o_block_mempool {
61 kmem_cache_t *slab; 67 kmem_cache_t *slab;
62 mempool_t *pool; 68 mempool_t *pool;
63}; 69};
64 70
65/* I2O Block device descriptor */ 71/* I2O Block device descriptor */
66struct i2o_block_device { 72struct i2o_block_device {
67 struct i2o_device *i2o_dev; /* pointer to I2O device */ 73 struct i2o_device *i2o_dev; /* pointer to I2O device */
68 struct gendisk *gd; 74 struct gendisk *gd;
69 spinlock_t lock; /* queue lock */ 75 spinlock_t lock; /* queue lock */
70 struct list_head open_queue; /* list of transfered, but unfinished 76 struct list_head open_queue; /* list of transfered, but unfinished
71 requests */ 77 requests */
72 unsigned int open_queue_depth; /* number of requests in the queue */ 78 unsigned int open_queue_depth; /* number of requests in the queue */
73 79
74 int rcache; /* read cache flags */ 80 int rcache; /* read cache flags */
75 int wcache; /* write cache flags */ 81 int wcache; /* write cache flags */
76 int flags; 82 int flags;
77 int power; /* power state */ 83 u16 power; /* power state */
78 int media_change_flag; /* media changed flag */ 84 int media_change_flag; /* media changed flag */
79}; 85};
80 86
81/* I2O Block device request */ 87/* I2O Block device request */
82struct i2o_block_request 88struct i2o_block_request {
83{
84 struct list_head queue; 89 struct list_head queue;
85 struct request *req; /* corresponding request */ 90 struct request *req; /* corresponding request */
86 struct i2o_block_device *i2o_blk_dev; /* I2O block device */ 91 struct i2o_block_device *i2o_blk_dev; /* I2O block device */
87 int sg_dma_direction; /* direction of DMA buffer read/write */ 92 struct device *dev; /* device used for DMA */
88 int sg_nents; /* number of SG elements */ 93 int sg_nents; /* number of SG elements */
89 struct scatterlist sg_table[I2O_MAX_SEGMENTS]; /* SG table */ 94 struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS]; /* SG table */
90}; 95};
91 96
92/* I2O Block device delayed request */ 97/* I2O Block device delayed request */
93struct i2o_block_delayed_request 98struct i2o_block_delayed_request {
94{
95 struct work_struct work; 99 struct work_struct work;
96 struct request_queue *queue; 100 struct request_queue *queue;
97}; 101};
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 1fb5cdf67f..3c3a7abebb 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -30,29 +30,15 @@
30 * 2 of the License, or (at your option) any later version. 30 * 2 of the License, or (at your option) any later version.
31 */ 31 */
32 32
33#include <linux/module.h>
34#include <linux/kernel.h>
35#include <linux/pci.h>
36#include <linux/i2o.h>
37#include <linux/errno.h>
38#include <linux/init.h>
39#include <linux/slab.h>
40#include <linux/miscdevice.h> 33#include <linux/miscdevice.h>
41#include <linux/mm.h>
42#include <linux/spinlock.h>
43#include <linux/smp_lock.h> 34#include <linux/smp_lock.h>
44#include <linux/ioctl32.h>
45#include <linux/compat.h> 35#include <linux/compat.h>
46#include <linux/syscalls.h>
47 36
48#include <asm/uaccess.h> 37#include <asm/uaccess.h>
49#include <asm/io.h>
50 38
51#define OSM_NAME "config-osm" 39#include "core.h"
52#define OSM_VERSION "$Rev$"
53#define OSM_DESCRIPTION "I2O Configuration OSM"
54 40
55extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); 41#define SG_TABLESIZE 30
56 42
57static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, 43static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
58 unsigned long arg); 44 unsigned long arg);
@@ -80,15 +66,6 @@ struct i2o_cfg_info {
80static struct i2o_cfg_info *open_files = NULL; 66static struct i2o_cfg_info *open_files = NULL;
81static ulong i2o_cfg_info_id = 0; 67static ulong i2o_cfg_info_id = 0;
82 68
83/*
84 * Each of these describes an i2o message handler. They are
85 * multiplexed by the i2o_core code
86 */
87
88static struct i2o_driver i2o_config_driver = {
89 .name = OSM_NAME
90};
91
92static int i2o_cfg_getiops(unsigned long arg) 69static int i2o_cfg_getiops(unsigned long arg)
93{ 70{
94 struct i2o_controller *c; 71 struct i2o_controller *c;
@@ -391,9 +368,9 @@ static int i2o_cfg_swul(unsigned long arg)
391 368
392 i2o_dma_free(&c->pdev->dev, &buffer); 369 i2o_dma_free(&c->pdev->dev, &buffer);
393 370
394return_ret: 371 return_ret:
395 return ret; 372 return ret;
396return_fault: 373 return_fault:
397 ret = -EFAULT; 374 ret = -EFAULT;
398 goto return_ret; 375 goto return_ret;
399}; 376};
@@ -540,8 +517,10 @@ static int i2o_cfg_evt_get(unsigned long arg, struct file *fp)
540 return 0; 517 return 0;
541} 518}
542 519
520#ifdef CONFIG_I2O_EXT_ADAPTEC
543#ifdef CONFIG_COMPAT 521#ifdef CONFIG_COMPAT
544static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg) 522static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
523 unsigned long arg)
545{ 524{
546 struct i2o_cmd_passthru32 __user *cmd; 525 struct i2o_cmd_passthru32 __user *cmd;
547 struct i2o_controller *c; 526 struct i2o_controller *c;
@@ -555,6 +534,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
555 u32 sg_offset = 0; 534 u32 sg_offset = 0;
556 u32 sg_count = 0; 535 u32 sg_count = 0;
557 u32 i = 0; 536 u32 i = 0;
537 u32 sg_index = 0;
558 i2o_status_block *sb; 538 i2o_status_block *sb;
559 struct i2o_message *msg; 539 struct i2o_message *msg;
560 u32 m; 540 u32 m;
@@ -634,8 +614,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
634 if (sg_count > SG_TABLESIZE) { 614 if (sg_count > SG_TABLESIZE) {
635 printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", 615 printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
636 c->name, sg_count); 616 c->name, sg_count);
637 kfree(reply); 617 rcode = -EINVAL;
638 return -EINVAL; 618 goto cleanup;
639 } 619 }
640 620
641 for (i = 0; i < sg_count; i++) { 621 for (i = 0; i < sg_count; i++) {
@@ -651,7 +631,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
651 goto cleanup; 631 goto cleanup;
652 } 632 }
653 sg_size = sg[i].flag_count & 0xffffff; 633 sg_size = sg[i].flag_count & 0xffffff;
654 p = &(sg_list[i]); 634 p = &(sg_list[sg_index++]);
655 /* Allocate memory for the transfer */ 635 /* Allocate memory for the transfer */
656 if (i2o_dma_alloc 636 if (i2o_dma_alloc
657 (&c->pdev->dev, p, sg_size, 637 (&c->pdev->dev, p, sg_size,
@@ -660,20 +640,21 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
660 "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", 640 "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
661 c->name, sg_size, i, sg_count); 641 c->name, sg_size, i, sg_count);
662 rcode = -ENOMEM; 642 rcode = -ENOMEM;
663 goto cleanup; 643 goto sg_list_cleanup;
664 } 644 }
665 /* Copy in the user's SG buffer if necessary */ 645 /* Copy in the user's SG buffer if necessary */
666 if (sg[i]. 646 if (sg[i].
667 flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { 647 flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
668 // TODO 64bit fix 648 // TODO 64bit fix
669 if (copy_from_user 649 if (copy_from_user
670 (p->virt, (void __user *)(unsigned long)sg[i].addr_bus, 650 (p->virt,
671 sg_size)) { 651 (void __user *)(unsigned long)sg[i].
652 addr_bus, sg_size)) {
672 printk(KERN_DEBUG 653 printk(KERN_DEBUG
673 "%s: Could not copy SG buf %d FROM user\n", 654 "%s: Could not copy SG buf %d FROM user\n",
674 c->name, i); 655 c->name, i);
675 rcode = -EFAULT; 656 rcode = -EFAULT;
676 goto cleanup; 657 goto sg_list_cleanup;
677 } 658 }
678 } 659 }
679 //TODO 64bit fix 660 //TODO 64bit fix
@@ -683,10 +664,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
683 664
684 rcode = i2o_msg_post_wait(c, m, 60); 665 rcode = i2o_msg_post_wait(c, m, 60);
685 if (rcode) 666 if (rcode)
686 goto cleanup; 667 goto sg_list_cleanup;
687 668
688 if (sg_offset) { 669 if (sg_offset) {
689 u32 msg[128]; 670 u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
690 /* Copy back the Scatter Gather buffers back to user space */ 671 /* Copy back the Scatter Gather buffers back to user space */
691 u32 j; 672 u32 j;
692 // TODO 64bit fix 673 // TODO 64bit fix
@@ -694,18 +675,18 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
694 int sg_size; 675 int sg_size;
695 676
696 // re-acquire the original message to handle correctly the sg copy operation 677 // re-acquire the original message to handle correctly the sg copy operation
697 memset(&msg, 0, MSG_FRAME_SIZE * 4); 678 memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
698 // get user msg size in u32s 679 // get user msg size in u32s
699 if (get_user(size, &user_msg[0])) { 680 if (get_user(size, &user_msg[0])) {
700 rcode = -EFAULT; 681 rcode = -EFAULT;
701 goto cleanup; 682 goto sg_list_cleanup;
702 } 683 }
703 size = size >> 16; 684 size = size >> 16;
704 size *= 4; 685 size *= 4;
705 /* Copy in the user's I2O command */ 686 /* Copy in the user's I2O command */
706 if (copy_from_user(msg, user_msg, size)) { 687 if (copy_from_user(msg, user_msg, size)) {
707 rcode = -EFAULT; 688 rcode = -EFAULT;
708 goto cleanup; 689 goto sg_list_cleanup;
709 } 690 }
710 sg_count = 691 sg_count =
711 (size - sg_offset * 4) / sizeof(struct sg_simple_element); 692 (size - sg_offset * 4) / sizeof(struct sg_simple_element);
@@ -727,7 +708,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
727 c->name, sg_list[j].virt, 708 c->name, sg_list[j].virt,
728 sg[j].addr_bus); 709 sg[j].addr_bus);
729 rcode = -EFAULT; 710 rcode = -EFAULT;
730 goto cleanup; 711 goto sg_list_cleanup;
731 } 712 }
732 } 713 }
733 } 714 }
@@ -741,6 +722,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
741 "%s: Could not copy message context FROM user\n", 722 "%s: Could not copy message context FROM user\n",
742 c->name); 723 c->name);
743 rcode = -EFAULT; 724 rcode = -EFAULT;
725 goto sg_list_cleanup;
744 } 726 }
745 if (copy_to_user(user_reply, reply, reply_size)) { 727 if (copy_to_user(user_reply, reply, reply_size)) {
746 printk(KERN_WARNING 728 printk(KERN_WARNING
@@ -749,16 +731,21 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
749 } 731 }
750 } 732 }
751 733
734 sg_list_cleanup:
735 for (i = 0; i < sg_index; i++)
736 i2o_dma_free(&c->pdev->dev, &sg_list[i]);
737
752 cleanup: 738 cleanup:
753 kfree(reply); 739 kfree(reply);
754 return rcode; 740 return rcode;
755} 741}
756 742
757static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) 743static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
744 unsigned long arg)
758{ 745{
759 int ret; 746 int ret;
760 lock_kernel(); 747 lock_kernel();
761 switch (cmd) { 748 switch (cmd) {
762 case I2OGETIOPS: 749 case I2OGETIOPS:
763 ret = i2o_cfg_ioctl(NULL, file, cmd, arg); 750 ret = i2o_cfg_ioctl(NULL, file, cmd, arg);
764 break; 751 break;
@@ -862,8 +849,8 @@ static int i2o_cfg_passthru(unsigned long arg)
862 if (sg_count > SG_TABLESIZE) { 849 if (sg_count > SG_TABLESIZE) {
863 printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", 850 printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
864 c->name, sg_count); 851 c->name, sg_count);
865 kfree(reply); 852 rcode = -EINVAL;
866 return -EINVAL; 853 goto cleanup;
867 } 854 }
868 855
869 for (i = 0; i < sg_count; i++) { 856 for (i = 0; i < sg_count; i++) {
@@ -875,7 +862,7 @@ static int i2o_cfg_passthru(unsigned long arg)
875 "%s:Bad SG element %d - not simple (%x)\n", 862 "%s:Bad SG element %d - not simple (%x)\n",
876 c->name, i, sg[i].flag_count); 863 c->name, i, sg[i].flag_count);
877 rcode = -EINVAL; 864 rcode = -EINVAL;
878 goto cleanup; 865 goto sg_list_cleanup;
879 } 866 }
880 sg_size = sg[i].flag_count & 0xffffff; 867 sg_size = sg[i].flag_count & 0xffffff;
881 /* Allocate memory for the transfer */ 868 /* Allocate memory for the transfer */
@@ -885,7 +872,7 @@ static int i2o_cfg_passthru(unsigned long arg)
885 "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", 872 "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
886 c->name, sg_size, i, sg_count); 873 c->name, sg_size, i, sg_count);
887 rcode = -ENOMEM; 874 rcode = -ENOMEM;
888 goto cleanup; 875 goto sg_list_cleanup;
889 } 876 }
890 sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. 877 sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
891 /* Copy in the user's SG buffer if necessary */ 878 /* Copy in the user's SG buffer if necessary */
@@ -899,7 +886,7 @@ static int i2o_cfg_passthru(unsigned long arg)
899 "%s: Could not copy SG buf %d FROM user\n", 886 "%s: Could not copy SG buf %d FROM user\n",
900 c->name, i); 887 c->name, i);
901 rcode = -EFAULT; 888 rcode = -EFAULT;
902 goto cleanup; 889 goto sg_list_cleanup;
903 } 890 }
904 } 891 }
905 //TODO 64bit fix 892 //TODO 64bit fix
@@ -909,7 +896,7 @@ static int i2o_cfg_passthru(unsigned long arg)
909 896
910 rcode = i2o_msg_post_wait(c, m, 60); 897 rcode = i2o_msg_post_wait(c, m, 60);
911 if (rcode) 898 if (rcode)
912 goto cleanup; 899 goto sg_list_cleanup;
913 900
914 if (sg_offset) { 901 if (sg_offset) {
915 u32 msg[128]; 902 u32 msg[128];
@@ -920,18 +907,18 @@ static int i2o_cfg_passthru(unsigned long arg)
920 int sg_size; 907 int sg_size;
921 908
922 // re-acquire the original message to handle correctly the sg copy operation 909 // re-acquire the original message to handle correctly the sg copy operation
923 memset(&msg, 0, MSG_FRAME_SIZE * 4); 910 memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
924 // get user msg size in u32s 911 // get user msg size in u32s
925 if (get_user(size, &user_msg[0])) { 912 if (get_user(size, &user_msg[0])) {
926 rcode = -EFAULT; 913 rcode = -EFAULT;
927 goto cleanup; 914 goto sg_list_cleanup;
928 } 915 }
929 size = size >> 16; 916 size = size >> 16;
930 size *= 4; 917 size *= 4;
931 /* Copy in the user's I2O command */ 918 /* Copy in the user's I2O command */
932 if (copy_from_user(msg, user_msg, size)) { 919 if (copy_from_user(msg, user_msg, size)) {
933 rcode = -EFAULT; 920 rcode = -EFAULT;
934 goto cleanup; 921 goto sg_list_cleanup;
935 } 922 }
936 sg_count = 923 sg_count =
937 (size - sg_offset * 4) / sizeof(struct sg_simple_element); 924 (size - sg_offset * 4) / sizeof(struct sg_simple_element);
@@ -953,7 +940,7 @@ static int i2o_cfg_passthru(unsigned long arg)
953 c->name, sg_list[j], 940 c->name, sg_list[j],
954 sg[j].addr_bus); 941 sg[j].addr_bus);
955 rcode = -EFAULT; 942 rcode = -EFAULT;
956 goto cleanup; 943 goto sg_list_cleanup;
957 } 944 }
958 } 945 }
959 } 946 }
@@ -975,10 +962,15 @@ static int i2o_cfg_passthru(unsigned long arg)
975 } 962 }
976 } 963 }
977 964
965 sg_list_cleanup:
966 for (i = 0; i < sg_index; i++)
967 kfree(sg_list[i]);
968
978 cleanup: 969 cleanup:
979 kfree(reply); 970 kfree(reply);
980 return rcode; 971 return rcode;
981} 972}
973#endif
982 974
983/* 975/*
984 * IOCTL Handler 976 * IOCTL Handler
@@ -1033,9 +1025,11 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
1033 ret = i2o_cfg_evt_get(arg, fp); 1025 ret = i2o_cfg_evt_get(arg, fp);
1034 break; 1026 break;
1035 1027
1028#ifdef CONFIG_I2O_EXT_ADAPTEC
1036 case I2OPASSTHRU: 1029 case I2OPASSTHRU:
1037 ret = i2o_cfg_passthru(arg); 1030 ret = i2o_cfg_passthru(arg);
1038 break; 1031 break;
1032#endif
1039 1033
1040 default: 1034 default:
1041 osm_debug("unknown ioctl called!\n"); 1035 osm_debug("unknown ioctl called!\n");
@@ -1137,37 +1131,21 @@ static struct miscdevice i2o_miscdev = {
1137 &config_fops 1131 &config_fops
1138}; 1132};
1139 1133
1140static int __init i2o_config_init(void) 1134static int __init i2o_config_old_init(void)
1141{ 1135{
1142 printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
1143
1144 spin_lock_init(&i2o_config_lock); 1136 spin_lock_init(&i2o_config_lock);
1145 1137
1146 if (misc_register(&i2o_miscdev) < 0) { 1138 if (misc_register(&i2o_miscdev) < 0) {
1147 osm_err("can't register device.\n"); 1139 osm_err("can't register device.\n");
1148 return -EBUSY; 1140 return -EBUSY;
1149 } 1141 }
1150 /* 1142
1151 * Install our handler
1152 */
1153 if (i2o_driver_register(&i2o_config_driver)) {
1154 osm_err("handler register failed.\n");
1155 misc_deregister(&i2o_miscdev);
1156 return -EBUSY;
1157 }
1158 return 0; 1143 return 0;
1159} 1144}
1160 1145
1161static void i2o_config_exit(void) 1146static void i2o_config_old_exit(void)
1162{ 1147{
1163 misc_deregister(&i2o_miscdev); 1148 misc_deregister(&i2o_miscdev);
1164 i2o_driver_unregister(&i2o_config_driver);
1165} 1149}
1166 1150
1167MODULE_AUTHOR("Red Hat Software"); 1151MODULE_AUTHOR("Red Hat Software");
1168MODULE_LICENSE("GPL");
1169MODULE_DESCRIPTION(OSM_DESCRIPTION);
1170MODULE_VERSION(OSM_VERSION);
1171
1172module_init(i2o_config_init);
1173module_exit(i2o_config_exit);
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index b176d0eeff..d559a17583 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#define OSM_NAME "proc-osm" 30#define OSM_NAME "proc-osm"
31#define OSM_VERSION "$Rev$" 31#define OSM_VERSION "1.145"
32#define OSM_DESCRIPTION "I2O ProcFS OSM" 32#define OSM_DESCRIPTION "I2O ProcFS OSM"
33 33
34#define I2O_MAX_MODULES 4 34#define I2O_MAX_MODULES 4
@@ -228,7 +228,7 @@ static const char *i2o_get_class_name(int class)
228 case I2O_CLASS_FLOPPY_DEVICE: 228 case I2O_CLASS_FLOPPY_DEVICE:
229 idx = 12; 229 idx = 12;
230 break; 230 break;
231 case I2O_CLASS_BUS_ADAPTER_PORT: 231 case I2O_CLASS_BUS_ADAPTER:
232 idx = 13; 232 idx = 13;
233 break; 233 break;
234 case I2O_CLASS_PEER_TRANSPORT_AGENT: 234 case I2O_CLASS_PEER_TRANSPORT_AGENT:
@@ -490,7 +490,7 @@ static int i2o_seq_show_lct(struct seq_file *seq, void *v)
490 seq_printf(seq, ", Unknown Device Type"); 490 seq_printf(seq, ", Unknown Device Type");
491 break; 491 break;
492 492
493 case I2O_CLASS_BUS_ADAPTER_PORT: 493 case I2O_CLASS_BUS_ADAPTER:
494 if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) 494 if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
495 seq_printf(seq, ", %s", 495 seq_printf(seq, ", %s",
496 bus_ports[lct->lct_entry[i]. 496 bus_ports[lct->lct_entry[i].
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 43f5875e0b..9f1744c393 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -54,6 +54,7 @@
54#include <linux/pci.h> 54#include <linux/pci.h>
55#include <linux/blkdev.h> 55#include <linux/blkdev.h>
56#include <linux/i2o.h> 56#include <linux/i2o.h>
57#include <linux/scatterlist.h>
57 58
58#include <asm/dma.h> 59#include <asm/dma.h>
59#include <asm/system.h> 60#include <asm/system.h>
@@ -64,19 +65,23 @@
64#include <scsi/scsi_host.h> 65#include <scsi/scsi_host.h>
65#include <scsi/scsi_device.h> 66#include <scsi/scsi_device.h>
66#include <scsi/scsi_cmnd.h> 67#include <scsi/scsi_cmnd.h>
68#include <scsi/scsi_request.h>
69#include <scsi/sg.h>
70#include <scsi/sg_request.h>
67 71
68#define OSM_NAME "scsi-osm" 72#define OSM_NAME "scsi-osm"
69#define OSM_VERSION "$Rev$" 73#define OSM_VERSION "1.282"
70#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" 74#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM"
71 75
72static struct i2o_driver i2o_scsi_driver; 76static struct i2o_driver i2o_scsi_driver;
73 77
74static int i2o_scsi_max_id = 16; 78static unsigned int i2o_scsi_max_id = 16;
75static int i2o_scsi_max_lun = 8; 79static unsigned int i2o_scsi_max_lun = 255;
76 80
77struct i2o_scsi_host { 81struct i2o_scsi_host {
78 struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ 82 struct Scsi_Host *scsi_host; /* pointer to the SCSI host */
79 struct i2o_controller *iop; /* pointer to the I2O controller */ 83 struct i2o_controller *iop; /* pointer to the I2O controller */
84 unsigned int lun; /* lun's used for block devices */
80 struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ 85 struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */
81}; 86};
82 87
@@ -99,11 +104,17 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
99 u8 type; 104 u8 type;
100 int i; 105 int i;
101 size_t size; 106 size_t size;
102 i2o_status_block *sb; 107 u16 body_size = 6;
108
109#ifdef CONFIG_I2O_EXT_ADAPTEC
110 if (c->adaptec)
111 body_size = 8;
112#endif
103 113
104 list_for_each_entry(i2o_dev, &c->devices, list) 114 list_for_each_entry(i2o_dev, &c->devices, list)
105 if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { 115 if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
106 if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* SCSI bus */ 116 if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
117 && (type == 0x01)) /* SCSI bus */
107 max_channel++; 118 max_channel++;
108 } 119 }
109 120
@@ -125,20 +136,18 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
125 scsi_host->max_id = i2o_scsi_max_id; 136 scsi_host->max_id = i2o_scsi_max_id;
126 scsi_host->max_lun = i2o_scsi_max_lun; 137 scsi_host->max_lun = i2o_scsi_max_lun;
127 scsi_host->this_id = c->unit; 138 scsi_host->this_id = c->unit;
128 139 scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size);
129 sb = c->status_block.virt;
130
131 scsi_host->sg_tablesize = (sb->inbound_frame_size -
132 sizeof(struct i2o_message) / 4 - 6) / 2;
133 140
134 i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; 141 i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata;
135 i2o_shost->scsi_host = scsi_host; 142 i2o_shost->scsi_host = scsi_host;
136 i2o_shost->iop = c; 143 i2o_shost->iop = c;
144 i2o_shost->lun = 1;
137 145
138 i = 0; 146 i = 0;
139 list_for_each_entry(i2o_dev, &c->devices, list) 147 list_for_each_entry(i2o_dev, &c->devices, list)
140 if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { 148 if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
141 if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* only SCSI bus */ 149 if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
150 && (type == 0x01)) /* only SCSI bus */
142 i2o_shost->channel[i++] = i2o_dev; 151 i2o_shost->channel[i++] = i2o_dev;
143 152
144 if (i >= max_channel) 153 if (i >= max_channel)
@@ -178,10 +187,13 @@ static int i2o_scsi_remove(struct device *dev)
178 struct i2o_scsi_host *i2o_shost; 187 struct i2o_scsi_host *i2o_shost;
179 struct scsi_device *scsi_dev; 188 struct scsi_device *scsi_dev;
180 189
190 osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
191
181 i2o_shost = i2o_scsi_get_host(c); 192 i2o_shost = i2o_scsi_get_host(c);
182 193
183 shost_for_each_device(scsi_dev, i2o_shost->scsi_host) 194 shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
184 if (scsi_dev->hostdata == i2o_dev) { 195 if (scsi_dev->hostdata == i2o_dev) {
196 sysfs_remove_link(&i2o_dev->device.kobj, "scsi");
185 scsi_remove_device(scsi_dev); 197 scsi_remove_device(scsi_dev);
186 scsi_device_put(scsi_dev); 198 scsi_device_put(scsi_dev);
187 break; 199 break;
@@ -207,8 +219,8 @@ static int i2o_scsi_probe(struct device *dev)
207 struct Scsi_Host *scsi_host; 219 struct Scsi_Host *scsi_host;
208 struct i2o_device *parent; 220 struct i2o_device *parent;
209 struct scsi_device *scsi_dev; 221 struct scsi_device *scsi_dev;
210 u32 id; 222 u32 id = -1;
211 u64 lun; 223 u64 lun = -1;
212 int channel = -1; 224 int channel = -1;
213 int i; 225 int i;
214 226
@@ -218,8 +230,56 @@ static int i2o_scsi_probe(struct device *dev)
218 230
219 scsi_host = i2o_shost->scsi_host; 231 scsi_host = i2o_shost->scsi_host;
220 232
221 if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0) 233 switch (i2o_dev->lct_data.class_id) {
234 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
235 case I2O_CLASS_EXECUTIVE:
236#ifdef CONFIG_I2O_EXT_ADAPTEC
237 if (c->adaptec) {
238 u8 type;
239 struct i2o_device *d = i2o_shost->channel[0];
240
241 if (i2o_parm_field_get(d, 0x0000, 0, &type, 1)
242 && (type == 0x01)) /* SCSI bus */
243 if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
244 channel = 0;
245 if (i2o_dev->lct_data.class_id ==
246 I2O_CLASS_RANDOM_BLOCK_STORAGE)
247 lun = i2o_shost->lun++;
248 else
249 lun = 0;
250 }
251 }
252#endif
253 break;
254
255 case I2O_CLASS_SCSI_PERIPHERAL:
256 if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0)
257 return -EFAULT;
258
259 if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0)
260 return -EFAULT;
261
262 parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
263 if (!parent) {
264 osm_warn("can not find parent of device %03x\n",
265 i2o_dev->lct_data.tid);
266 return -EFAULT;
267 }
268
269 for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
270 if (i2o_shost->channel[i] == parent)
271 channel = i;
272 break;
273
274 default:
222 return -EFAULT; 275 return -EFAULT;
276 }
277
278 if (channel == -1) {
279 osm_warn("can not find channel of device %03x\n",
280 i2o_dev->lct_data.tid);
281 return -EFAULT;
282 }
223 283
224 if (id >= scsi_host->max_id) { 284 if (id >= scsi_host->max_id) {
225 osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id, 285 osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id,
@@ -227,42 +287,26 @@ static int i2o_scsi_probe(struct device *dev)
227 return -EFAULT; 287 return -EFAULT;
228 } 288 }
229 289
230 if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0)
231 return -EFAULT;
232 if (lun >= scsi_host->max_lun) { 290 if (lun >= scsi_host->max_lun) {
233 osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)", 291 osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)",
234 (unsigned int)lun, scsi_host->max_lun); 292 (unsigned int)lun, scsi_host->max_lun);
235 return -EFAULT; 293 return -EFAULT;
236 } 294 }
237 295
238 parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
239 if (!parent) {
240 osm_warn("can not find parent of device %03x\n",
241 i2o_dev->lct_data.tid);
242 return -EFAULT;
243 }
244
245 for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
246 if (i2o_shost->channel[i] == parent)
247 channel = i;
248
249 if (channel == -1) {
250 osm_warn("can not find channel of device %03x\n",
251 i2o_dev->lct_data.tid);
252 return -EFAULT;
253 }
254
255 scsi_dev = 296 scsi_dev =
256 __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); 297 __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
257 298
258 if (!scsi_dev) { 299 if (IS_ERR(scsi_dev)) {
259 osm_warn("can not add SCSI device %03x\n", 300 osm_warn("can not add SCSI device %03x\n",
260 i2o_dev->lct_data.tid); 301 i2o_dev->lct_data.tid);
261 return -EFAULT; 302 return PTR_ERR(scsi_dev);
262 } 303 }
263 304
264 osm_debug("added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n", 305 sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj,
265 i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); 306 "scsi");
307
308 osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n",
309 i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
266 310
267 return 0; 311 return 0;
268}; 312};
@@ -293,162 +337,89 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
293 struct i2o_message *msg) 337 struct i2o_message *msg)
294{ 338{
295 struct scsi_cmnd *cmd; 339 struct scsi_cmnd *cmd;
340 u32 error;
296 struct device *dev; 341 struct device *dev;
297 u8 as, ds, st;
298 342
299 cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); 343 cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
300 344 if (unlikely(!cmd)) {
301 if (msg->u.head[0] & (1 << 13)) { 345 osm_err("NULL reply received!\n");
302 struct i2o_message __iomem *pmsg; /* preserved message */ 346 return -1;
303 u32 pm;
304 int err = DID_ERROR;
305
306 pm = le32_to_cpu(msg->body[3]);
307
308 pmsg = i2o_msg_in_to_virt(c, pm);
309
310 osm_err("IOP fail.\n");
311 osm_err("From %d To %d Cmd %d.\n",
312 (msg->u.head[1] >> 12) & 0xFFF,
313 msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24);
314 osm_err("Failure Code %d.\n", msg->body[0] >> 24);
315 if (msg->body[0] & (1 << 16))
316 osm_err("Format error.\n");
317 if (msg->body[0] & (1 << 17))
318 osm_err("Path error.\n");
319 if (msg->body[0] & (1 << 18))
320 osm_err("Path State.\n");
321 if (msg->body[0] & (1 << 18))
322 {
323 osm_err("Congestion.\n");
324 err = DID_BUS_BUSY;
325 }
326
327 osm_debug("Failing message is %p.\n", pmsg);
328
329 cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
330 if (!cmd)
331 return 1;
332
333 cmd->result = err << 16;
334 cmd->scsi_done(cmd);
335
336 /* Now flush the message by making it a NOP */
337 i2o_msg_nop(c, pm);
338
339 return 1;
340 } 347 }
341 348
342 /* 349 /*
343 * Low byte is device status, next is adapter status, 350 * Low byte is device status, next is adapter status,
344 * (then one byte reserved), then request status. 351 * (then one byte reserved), then request status.
345 */ 352 */
346 ds = (u8) le32_to_cpu(msg->body[0]); 353 error = le32_to_cpu(msg->body[0]);
347 as = (u8) (le32_to_cpu(msg->body[0]) >> 8); 354
348 st = (u8) (le32_to_cpu(msg->body[0]) >> 24); 355 osm_debug("Completed %ld\n", cmd->serial_number);
349 356
357 cmd->result = error & 0xff;
350 /* 358 /*
351 * Is this a control request coming back - eg an abort ? 359 * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let
360 * the SCSI layer handle the error
352 */ 361 */
362 if (cmd->result)
363 memcpy(cmd->sense_buffer, &msg->body[3],
364 min(sizeof(cmd->sense_buffer), (size_t) 40));
353 365
354 if (!cmd) { 366 /* only output error code if AdapterStatus is not HBA_SUCCESS */
355 if (st) 367 if ((error >> 8) & 0xff)
356 osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0])); 368 osm_err("SCSI error %08x\n", error);
357 osm_info("SCSI abort completed.\n");
358 return -EFAULT;
359 }
360 369
361 osm_debug("Completed %ld\n", cmd->serial_number); 370 dev = &c->pdev->dev;
371 if (cmd->use_sg)
372 dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
373 cmd->sc_data_direction);
374 else if (cmd->SCp.dma_handle)
375 dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen,
376 cmd->sc_data_direction);
362 377
363 if (st) { 378 cmd->scsi_done(cmd);
364 u32 count, error;
365 /* An error has occurred */
366
367 switch (st) {
368 case 0x06:
369 count = le32_to_cpu(msg->body[1]);
370 if (count < cmd->underflow) {
371 int i;
372
373 osm_err("SCSI underflow 0x%08X 0x%08X\n", count,
374 cmd->underflow);
375 osm_debug("Cmd: ");
376 for (i = 0; i < 15; i++)
377 pr_debug("%02X ", cmd->cmnd[i]);
378 pr_debug(".\n");
379 cmd->result = (DID_ERROR << 16);
380 }
381 break;
382 379
383 default: 380 return 1;
384 error = le32_to_cpu(msg->body[0]); 381};
385
386 osm_err("SCSI error %08x\n", error);
387
388 if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) {
389 int i;
390 u32 len = sizeof(cmd->sense_buffer);
391 len = (len > 40) ? 40 : len;
392 // Copy over the sense data
393 memcpy(cmd->sense_buffer, (void *)&msg->body[3],
394 len);
395 for (i = 0; i <= len; i++)
396 osm_info("%02x\n",
397 cmd->sense_buffer[i]);
398 if (cmd->sense_buffer[0] == 0x70
399 && cmd->sense_buffer[2] == DATA_PROTECT) {
400 /* This is to handle an array failed */
401 cmd->result = (DID_TIME_OUT << 16);
402 printk(KERN_WARNING "%s: SCSI Data "
403 "Protect-Device (%d,%d,%d) "
404 "hba_status=0x%x, dev_status="
405 "0x%x, cmd=0x%x\n", c->name,
406 (u32) cmd->device->channel,
407 (u32) cmd->device->id,
408 (u32) cmd->device->lun,
409 (error >> 8) & 0xff,
410 error & 0xff, cmd->cmnd[0]);
411 } else
412 cmd->result = (DID_ERROR << 16);
413
414 break;
415 }
416
417 switch (as) {
418 case 0x0E:
419 /* SCSI Reset */
420 cmd->result = DID_RESET << 16;
421 break;
422
423 case 0x0F:
424 cmd->result = DID_PARITY << 16;
425 break;
426
427 default:
428 cmd->result = DID_ERROR << 16;
429 break;
430 }
431 382
432 break; 383/**
433 } 384 * i2o_scsi_notify_device_add - Retrieve notifications of added devices
385 * @i2o_dev: the I2O device which was added
386 *
387 * If a I2O device is added we catch the notification, because I2O classes
388 * other then SCSI peripheral will not be received through
389 * i2o_scsi_probe().
390 */
391static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev)
392{
393 switch (i2o_dev->lct_data.class_id) {
394 case I2O_CLASS_EXECUTIVE:
395 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
396 i2o_scsi_probe(&i2o_dev->device);
397 break;
434 398
435 cmd->scsi_done(cmd); 399 default:
436 return 1; 400 break;
437 } 401 }
402};
438 403
439 cmd->result = DID_OK << 16 | ds; 404/**
440 405 * i2o_scsi_notify_device_remove - Retrieve notifications of removed
441 cmd->scsi_done(cmd); 406 * devices
442 407 * @i2o_dev: the I2O device which was removed
443 dev = &c->pdev->dev; 408 *
444 if (cmd->use_sg) 409 * If a I2O device is removed, we catch the notification to remove the
445 dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer, 410 * corresponding SCSI device.
446 cmd->use_sg, cmd->sc_data_direction); 411 */
447 else if (cmd->request_bufflen) 412static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev)
448 dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr), 413{
449 cmd->request_bufflen, cmd->sc_data_direction); 414 switch (i2o_dev->lct_data.class_id) {
415 case I2O_CLASS_EXECUTIVE:
416 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
417 i2o_scsi_remove(&i2o_dev->device);
418 break;
450 419
451 return 1; 420 default:
421 break;
422 }
452}; 423};
453 424
454/** 425/**
@@ -501,7 +472,7 @@ static void i2o_scsi_notify_controller_remove(struct i2o_controller *c)
501 472
502 scsi_remove_host(i2o_shost->scsi_host); 473 scsi_remove_host(i2o_shost->scsi_host);
503 scsi_host_put(i2o_shost->scsi_host); 474 scsi_host_put(i2o_shost->scsi_host);
504 pr_info("I2O SCSI host removed\n"); 475 osm_debug("I2O SCSI host removed\n");
505}; 476};
506 477
507/* SCSI OSM driver struct */ 478/* SCSI OSM driver struct */
@@ -509,6 +480,8 @@ static struct i2o_driver i2o_scsi_driver = {
509 .name = OSM_NAME, 480 .name = OSM_NAME,
510 .reply = i2o_scsi_reply, 481 .reply = i2o_scsi_reply,
511 .classes = i2o_scsi_class_id, 482 .classes = i2o_scsi_class_id,
483 .notify_device_add = i2o_scsi_notify_device_add,
484 .notify_device_remove = i2o_scsi_notify_device_remove,
512 .notify_controller_add = i2o_scsi_notify_controller_add, 485 .notify_controller_add = i2o_scsi_notify_controller_add,
513 .notify_controller_remove = i2o_scsi_notify_controller_remove, 486 .notify_controller_remove = i2o_scsi_notify_controller_remove,
514 .driver = { 487 .driver = {
@@ -535,26 +508,26 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
535 void (*done) (struct scsi_cmnd *)) 508 void (*done) (struct scsi_cmnd *))
536{ 509{
537 struct i2o_controller *c; 510 struct i2o_controller *c;
538 struct Scsi_Host *host;
539 struct i2o_device *i2o_dev; 511 struct i2o_device *i2o_dev;
540 struct device *dev;
541 int tid; 512 int tid;
542 struct i2o_message __iomem *msg; 513 struct i2o_message __iomem *msg;
543 u32 m; 514 u32 m;
544 u32 scsi_flags, sg_flags; 515 /*
516 * ENABLE_DISCONNECT
517 * SIMPLE_TAG
518 * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
519 */
520 u32 scsi_flags = 0x20a00000;
521 u32 sgl_offset;
545 u32 __iomem *mptr; 522 u32 __iomem *mptr;
546 u32 __iomem *lenptr; 523 u32 cmd = I2O_CMD_SCSI_EXEC << 24;
547 u32 len, reqlen; 524 int rc = 0;
548 int i;
549 525
550 /* 526 /*
551 * Do the incoming paperwork 527 * Do the incoming paperwork
552 */ 528 */
553
554 i2o_dev = SCpnt->device->hostdata; 529 i2o_dev = SCpnt->device->hostdata;
555 host = SCpnt->device->host;
556 c = i2o_dev->iop; 530 c = i2o_dev->iop;
557 dev = &c->pdev->dev;
558 531
559 SCpnt->scsi_done = done; 532 SCpnt->scsi_done = done;
560 533
@@ -562,7 +535,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
562 osm_warn("no I2O device in request\n"); 535 osm_warn("no I2O device in request\n");
563 SCpnt->result = DID_NO_CONNECT << 16; 536 SCpnt->result = DID_NO_CONNECT << 16;
564 done(SCpnt); 537 done(SCpnt);
565 return 0; 538 goto exit;
566 } 539 }
567 540
568 tid = i2o_dev->lct_data.tid; 541 tid = i2o_dev->lct_data.tid;
@@ -571,44 +544,85 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
571 osm_debug("Real scsi messages.\n"); 544 osm_debug("Real scsi messages.\n");
572 545
573 /* 546 /*
574 * Obtain an I2O message. If there are none free then
575 * throw it back to the scsi layer
576 */
577
578 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
579 if (m == I2O_QUEUE_EMPTY)
580 return SCSI_MLQUEUE_HOST_BUSY;
581
582 /*
583 * Put together a scsi execscb message 547 * Put together a scsi execscb message
584 */ 548 */
585
586 len = SCpnt->request_bufflen;
587
588 switch (SCpnt->sc_data_direction) { 549 switch (SCpnt->sc_data_direction) {
589 case PCI_DMA_NONE: 550 case PCI_DMA_NONE:
590 scsi_flags = 0x00000000; // DATA NO XFER 551 /* DATA NO XFER */
591 sg_flags = 0x00000000; 552 sgl_offset = SGL_OFFSET_0;
592 break; 553 break;
593 554
594 case PCI_DMA_TODEVICE: 555 case PCI_DMA_TODEVICE:
595 scsi_flags = 0x80000000; // DATA OUT (iop-->dev) 556 /* DATA OUT (iop-->dev) */
596 sg_flags = 0x14000000; 557 scsi_flags |= 0x80000000;
558 sgl_offset = SGL_OFFSET_10;
597 break; 559 break;
598 560
599 case PCI_DMA_FROMDEVICE: 561 case PCI_DMA_FROMDEVICE:
600 scsi_flags = 0x40000000; // DATA IN (iop<--dev) 562 /* DATA IN (iop<--dev) */
601 sg_flags = 0x10000000; 563 scsi_flags |= 0x40000000;
564 sgl_offset = SGL_OFFSET_10;
602 break; 565 break;
603 566
604 default: 567 default:
605 /* Unknown - kill the command */ 568 /* Unknown - kill the command */
606 SCpnt->result = DID_NO_CONNECT << 16; 569 SCpnt->result = DID_NO_CONNECT << 16;
607 done(SCpnt); 570 done(SCpnt);
608 return 0; 571 goto exit;
609 } 572 }
610 573
611 writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]); 574 /*
575 * Obtain an I2O message. If there are none free then
576 * throw it back to the scsi layer
577 */
578
579 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
580 if (m == I2O_QUEUE_EMPTY) {
581 rc = SCSI_MLQUEUE_HOST_BUSY;
582 goto exit;
583 }
584
585 mptr = &msg->body[0];
586
587#ifdef CONFIG_I2O_EXT_ADAPTEC
588 if (c->adaptec) {
589 u32 adpt_flags = 0;
590
591 if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) {
592 i2o_sg_io_hdr_t __user *usr_ptr =
593 ((Sg_request *) (SCpnt->sc_request->
594 upper_private_data))->header.
595 usr_ptr;
596
597 if (usr_ptr)
598 get_user(adpt_flags, &usr_ptr->flags);
599 }
600
601 switch (i2o_dev->lct_data.class_id) {
602 case I2O_CLASS_EXECUTIVE:
603 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
604 /* interpret flag has to be set for executive */
605 adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET;
606 break;
607
608 default:
609 break;
610 }
611
612 /*
613 * for Adaptec controllers we use the PRIVATE command, because
614 * the normal SCSI EXEC doesn't support all SCSI commands on
615 * all controllers (for example READ CAPACITY).
616 */
617 if (sgl_offset == SGL_OFFSET_10)
618 sgl_offset = SGL_OFFSET_12;
619 cmd = I2O_CMD_PRIVATE << 24;
620 writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
621 writel(adpt_flags | tid, mptr++);
622 }
623#endif
624
625 writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
612 writel(i2o_scsi_driver.context, &msg->u.s.icntxt); 626 writel(i2o_scsi_driver.context, &msg->u.s.icntxt);
613 627
614 /* We want the SCSI control block back */ 628 /* We want the SCSI control block back */
@@ -626,7 +640,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
626 */ 640 */
627 641
628 /* Attach tags to the devices */ 642 /* Attach tags to the devices */
629 /* 643 /* FIXME: implement
630 if(SCpnt->device->tagged_supported) { 644 if(SCpnt->device->tagged_supported) {
631 if(SCpnt->tag == HEAD_OF_QUEUE_TAG) 645 if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
632 scsi_flags |= 0x01000000; 646 scsi_flags |= 0x01000000;
@@ -635,67 +649,35 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
635 } 649 }
636 */ 650 */
637 651
638 /* Direction, disconnect ok, tag, CDBLen */ 652 writel(scsi_flags | SCpnt->cmd_len, mptr++);
639 writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]);
640
641 mptr = &msg->body[1];
642 653
643 /* Write SCSI command into the message - always 16 byte block */ 654 /* Write SCSI command into the message - always 16 byte block */
644 memcpy_toio(mptr, SCpnt->cmnd, 16); 655 memcpy_toio(mptr, SCpnt->cmnd, 16);
645 mptr += 4; 656 mptr += 4;
646 lenptr = mptr++; /* Remember me - fill in when we know */
647
648 reqlen = 12; // SINGLE SGE
649
650 /* Now fill in the SGList and command */
651 if (SCpnt->use_sg) {
652 struct scatterlist *sg;
653 int sg_count;
654
655 sg = SCpnt->request_buffer;
656 len = 0;
657
658 sg_count = dma_map_sg(dev, sg, SCpnt->use_sg,
659 SCpnt->sc_data_direction);
660 657
661 if (unlikely(sg_count <= 0)) 658 if (sgl_offset != SGL_OFFSET_0) {
662 return -ENOMEM; 659 /* write size of data addressed by SGL */
663 660 writel(SCpnt->request_bufflen, mptr++);
664 for (i = SCpnt->use_sg; i > 0; i--) { 661
665 if (i == 1) 662 /* Now fill in the SGList and command */
666 sg_flags |= 0xC0000000; 663 if (SCpnt->use_sg) {
667 writel(sg_flags | sg_dma_len(sg), mptr++); 664 if (!i2o_dma_map_sg(c, SCpnt->request_buffer,
668 writel(sg_dma_address(sg), mptr++); 665 SCpnt->use_sg,
669 len += sg_dma_len(sg); 666 SCpnt->sc_data_direction, &mptr))
670 sg++; 667 goto nomem;
668 } else {
669 SCpnt->SCp.dma_handle =
670 i2o_dma_map_single(c, SCpnt->request_buffer,
671 SCpnt->request_bufflen,
672 SCpnt->sc_data_direction, &mptr);
673 if (dma_mapping_error(SCpnt->SCp.dma_handle))
674 goto nomem;
671 } 675 }
672
673 reqlen = mptr - &msg->u.head[0];
674 writel(len, lenptr);
675 } else {
676 len = SCpnt->request_bufflen;
677
678 writel(len, lenptr);
679
680 if (len > 0) {
681 dma_addr_t dma_addr;
682
683 dma_addr = dma_map_single(dev, SCpnt->request_buffer,
684 SCpnt->request_bufflen,
685 SCpnt->sc_data_direction);
686 if (!dma_addr)
687 return -ENOMEM;
688
689 SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr;
690 sg_flags |= 0xC0000000;
691 writel(sg_flags | SCpnt->request_bufflen, mptr++);
692 writel(dma_addr, mptr++);
693 } else
694 reqlen = 9;
695 } 676 }
696 677
697 /* Stick the headers on */ 678 /* Stick the headers on */
698 writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]); 679 writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset,
680 &msg->u.head[0]);
699 681
700 /* Queue the message */ 682 /* Queue the message */
701 i2o_msg_post(c, m); 683 i2o_msg_post(c, m);
@@ -703,6 +685,13 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
703 osm_debug("Issued %ld\n", SCpnt->serial_number); 685 osm_debug("Issued %ld\n", SCpnt->serial_number);
704 686
705 return 0; 687 return 0;
688
689 nomem:
690 rc = -ENOMEM;
691 i2o_msg_nop(c, m);
692
693 exit:
694 return rc;
706}; 695};
707 696
708/** 697/**
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 50c8cedf7a..42f8b810d6 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -28,8 +28,10 @@
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/i2o.h> 29#include <linux/i2o.h>
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include "core.h"
31 32
32#define OSM_VERSION "$Rev$" 33#define OSM_NAME "i2o"
34#define OSM_VERSION "1.288"
33#define OSM_DESCRIPTION "I2O subsystem" 35#define OSM_DESCRIPTION "I2O subsystem"
34 36
35/* global I2O controller list */ 37/* global I2O controller list */
@@ -43,20 +45,6 @@ static struct i2o_dma i2o_systab;
43 45
44static int i2o_hrt_get(struct i2o_controller *c); 46static int i2o_hrt_get(struct i2o_controller *c);
45 47
46/* Module internal functions from other sources */
47extern struct i2o_driver i2o_exec_driver;
48extern int i2o_exec_lct_get(struct i2o_controller *);
49extern void i2o_device_remove(struct i2o_device *);
50
51extern int __init i2o_driver_init(void);
52extern void __exit i2o_driver_exit(void);
53extern int __init i2o_exec_init(void);
54extern void __exit i2o_exec_exit(void);
55extern int __init i2o_pci_init(void);
56extern void __exit i2o_pci_exit(void);
57extern int i2o_device_init(void);
58extern void i2o_device_exit(void);
59
60/** 48/**
61 * i2o_msg_nop - Returns a message which is not used 49 * i2o_msg_nop - Returns a message which is not used
62 * @c: I2O controller from which the message was created 50 * @c: I2O controller from which the message was created
@@ -68,7 +56,7 @@ extern void i2o_device_exit(void);
68 */ 56 */
69void i2o_msg_nop(struct i2o_controller *c, u32 m) 57void i2o_msg_nop(struct i2o_controller *c, u32 m)
70{ 58{
71 struct i2o_message __iomem *msg = c->in_queue.virt + m; 59 struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
72 60
73 writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); 61 writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
74 writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, 62 writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
@@ -92,16 +80,16 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m)
92 * address from the read port (see the i2o spec). If no message is 80 * address from the read port (see the i2o spec). If no message is
93 * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. 81 * available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
94 */ 82 */
95u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg, 83u32 i2o_msg_get_wait(struct i2o_controller *c,
96 int wait) 84 struct i2o_message __iomem ** msg, int wait)
97{ 85{
98 unsigned long timeout = jiffies + wait * HZ; 86 unsigned long timeout = jiffies + wait * HZ;
99 u32 m; 87 u32 m;
100 88
101 while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) { 89 while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
102 if (time_after(jiffies, timeout)) { 90 if (time_after(jiffies, timeout)) {
103 pr_debug("%s: Timeout waiting for message frame.\n", 91 osm_debug("%s: Timeout waiting for message frame.\n",
104 c->name); 92 c->name);
105 return I2O_QUEUE_EMPTY; 93 return I2O_QUEUE_EMPTY;
106 } 94 }
107 set_current_state(TASK_UNINTERRUPTIBLE); 95 set_current_state(TASK_UNINTERRUPTIBLE);
@@ -129,13 +117,13 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr)
129 unsigned long flags; 117 unsigned long flags;
130 118
131 if (!ptr) 119 if (!ptr)
132 printk(KERN_ERR "%s: couldn't add NULL pointer to context list!" 120 osm_err("%s: couldn't add NULL pointer to context list!\n",
133 "\n", c->name); 121 c->name);
134 122
135 entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 123 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
136 if (!entry) { 124 if (!entry) {
137 printk(KERN_ERR "%s: Could not allocate memory for context " 125 osm_err("%s: Could not allocate memory for context list element"
138 "list element\n", c->name); 126 "\n", c->name);
139 return 0; 127 return 0;
140 } 128 }
141 129
@@ -154,7 +142,7 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr)
154 142
155 spin_unlock_irqrestore(&c->context_list_lock, flags); 143 spin_unlock_irqrestore(&c->context_list_lock, flags);
156 144
157 pr_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); 145 osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context);
158 146
159 return entry->context; 147 return entry->context;
160}; 148};
@@ -186,11 +174,11 @@ u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr)
186 spin_unlock_irqrestore(&c->context_list_lock, flags); 174 spin_unlock_irqrestore(&c->context_list_lock, flags);
187 175
188 if (!context) 176 if (!context)
189 printk(KERN_WARNING "%s: Could not remove nonexistent ptr " 177 osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name,
190 "%p\n", c->name, ptr); 178 ptr);
191 179
192 pr_debug("%s: remove ptr from context list %d -> %p\n", c->name, 180 osm_debug("%s: remove ptr from context list %d -> %p\n", c->name,
193 context, ptr); 181 context, ptr);
194 182
195 return context; 183 return context;
196}; 184};
@@ -220,11 +208,10 @@ void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context)
220 spin_unlock_irqrestore(&c->context_list_lock, flags); 208 spin_unlock_irqrestore(&c->context_list_lock, flags);
221 209
222 if (!ptr) 210 if (!ptr)
223 printk(KERN_WARNING "%s: context id %d not found\n", c->name, 211 osm_warn("%s: context id %d not found\n", c->name, context);
224 context);
225 212
226 pr_debug("%s: get ptr from context list %d -> %p\n", c->name, context, 213 osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context,
227 ptr); 214 ptr);
228 215
229 return ptr; 216 return ptr;
230}; 217};
@@ -252,11 +239,11 @@ u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr)
252 spin_unlock_irqrestore(&c->context_list_lock, flags); 239 spin_unlock_irqrestore(&c->context_list_lock, flags);
253 240
254 if (!context) 241 if (!context)
255 printk(KERN_WARNING "%s: Could not find nonexistent ptr " 242 osm_warn("%s: Could not find nonexistent ptr %p\n", c->name,
256 "%p\n", c->name, ptr); 243 ptr);
257 244
258 pr_debug("%s: get context id from context list %p -> %d\n", c->name, 245 osm_debug("%s: get context id from context list %p -> %d\n", c->name,
259 ptr, context); 246 ptr, context);
260 247
261 return context; 248 return context;
262}; 249};
@@ -336,10 +323,9 @@ static int i2o_iop_quiesce(struct i2o_controller *c)
336 323
337 /* Long timeout needed for quiesce if lots of devices */ 324 /* Long timeout needed for quiesce if lots of devices */
338 if ((rc = i2o_msg_post_wait(c, m, 240))) 325 if ((rc = i2o_msg_post_wait(c, m, 240)))
339 printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n", 326 osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc);
340 c->name, -rc);
341 else 327 else
342 pr_debug("%s: Quiesced.\n", c->name); 328 osm_debug("%s: Quiesced.\n", c->name);
343 329
344 i2o_status_get(c); // Entered READY state 330 i2o_status_get(c); // Entered READY state
345 331
@@ -377,10 +363,9 @@ static int i2o_iop_enable(struct i2o_controller *c)
377 363
378 /* How long of a timeout do we need? */ 364 /* How long of a timeout do we need? */
379 if ((rc = i2o_msg_post_wait(c, m, 240))) 365 if ((rc = i2o_msg_post_wait(c, m, 240)))
380 printk(KERN_ERR "%s: Could not enable (status=%#x).\n", 366 osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc);
381 c->name, -rc);
382 else 367 else
383 pr_debug("%s: Enabled.\n", c->name); 368 osm_debug("%s: Enabled.\n", c->name);
384 369
385 i2o_status_get(c); // entered OPERATIONAL state 370 i2o_status_get(c); // entered OPERATIONAL state
386 371
@@ -444,20 +429,78 @@ static int i2o_iop_clear(struct i2o_controller *c)
444 &msg->u.head[1]); 429 &msg->u.head[1]);
445 430
446 if ((rc = i2o_msg_post_wait(c, m, 30))) 431 if ((rc = i2o_msg_post_wait(c, m, 30)))
447 printk(KERN_INFO "%s: Unable to clear (status=%#x).\n", 432 osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc);
448 c->name, -rc);
449 else 433 else
450 pr_debug("%s: Cleared.\n", c->name); 434 osm_debug("%s: Cleared.\n", c->name);
451 435
452 /* Enable all IOPs */ 436 /* Enable all IOPs */
453 i2o_iop_enable_all(); 437 i2o_iop_enable_all();
454 438
455 i2o_status_get(c);
456
457 return rc; 439 return rc;
458} 440}
459 441
460/** 442/**
443 * i2o_iop_init_outbound_queue - setup the outbound message queue
444 * @c: I2O controller
445 *
446 * Clear and (re)initialize IOP's outbound queue and post the message
447 * frames to the IOP.
448 *
449 * Returns 0 on success or a negative errno code on failure.
450 */
451static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
452{
453 volatile u8 *status = c->status.virt;
454 u32 m;
455 struct i2o_message __iomem *msg;
456 ulong timeout;
457 int i;
458
459 osm_debug("%s: Initializing Outbound Queue...\n", c->name);
460
461 memset(c->status.virt, 0, 4);
462
463 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
464 if (m == I2O_QUEUE_EMPTY)
465 return -ETIMEDOUT;
466
467 writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
468 writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
469 &msg->u.head[1]);
470 writel(i2o_exec_driver.context, &msg->u.s.icntxt);
471 writel(0x00000000, &msg->u.s.tcntxt);
472 writel(PAGE_SIZE, &msg->body[0]);
473 /* Outbound msg frame size in words and Initcode */
474 writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);
475 writel(0xd0000004, &msg->body[2]);
476 writel(i2o_dma_low(c->status.phys), &msg->body[3]);
477 writel(i2o_dma_high(c->status.phys), &msg->body[4]);
478
479 i2o_msg_post(c, m);
480
481 timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
482 while (*status <= I2O_CMD_IN_PROGRESS) {
483 if (time_after(jiffies, timeout)) {
484 osm_warn("%s: Timeout Initializing\n", c->name);
485 return -ETIMEDOUT;
486 }
487 set_current_state(TASK_UNINTERRUPTIBLE);
488 schedule_timeout(1);
489 }
490
491 m = c->out_queue.phys;
492
493 /* Post frames */
494 for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) {
495 i2o_flush_reply(c, m);
496 udelay(1); /* Promise */
497 m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32);
498 }
499
500 return 0;
501}
502
503/**
461 * i2o_iop_reset - reset an I2O controller 504 * i2o_iop_reset - reset an I2O controller
462 * @c: controller to reset 505 * @c: controller to reset
463 * 506 *
@@ -468,20 +511,20 @@ static int i2o_iop_clear(struct i2o_controller *c)
468 */ 511 */
469static int i2o_iop_reset(struct i2o_controller *c) 512static int i2o_iop_reset(struct i2o_controller *c)
470{ 513{
471 u8 *status = c->status.virt; 514 volatile u8 *status = c->status.virt;
472 struct i2o_message __iomem *msg; 515 struct i2o_message __iomem *msg;
473 u32 m; 516 u32 m;
474 unsigned long timeout; 517 unsigned long timeout;
475 i2o_status_block *sb = c->status_block.virt; 518 i2o_status_block *sb = c->status_block.virt;
476 int rc = 0; 519 int rc = 0;
477 520
478 pr_debug("%s: Resetting controller\n", c->name); 521 osm_debug("%s: Resetting controller\n", c->name);
479 522
480 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); 523 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
481 if (m == I2O_QUEUE_EMPTY) 524 if (m == I2O_QUEUE_EMPTY)
482 return -ETIMEDOUT; 525 return -ETIMEDOUT;
483 526
484 memset(status, 0, 8); 527 memset(c->status_block.virt, 0, 8);
485 528
486 /* Quiesce all IOPs first */ 529 /* Quiesce all IOPs first */
487 i2o_iop_quiesce_all(); 530 i2o_iop_quiesce_all();
@@ -493,49 +536,43 @@ static int i2o_iop_reset(struct i2o_controller *c)
493 writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context 536 writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context
494 writel(0, &msg->body[0]); 537 writel(0, &msg->body[0]);
495 writel(0, &msg->body[1]); 538 writel(0, &msg->body[1]);
496 writel(i2o_ptr_low((void *)c->status.phys), &msg->body[2]); 539 writel(i2o_dma_low(c->status.phys), &msg->body[2]);
497 writel(i2o_ptr_high((void *)c->status.phys), &msg->body[3]); 540 writel(i2o_dma_high(c->status.phys), &msg->body[3]);
498 541
499 i2o_msg_post(c, m); 542 i2o_msg_post(c, m);
500 543
501 /* Wait for a reply */ 544 /* Wait for a reply */
502 timeout = jiffies + I2O_TIMEOUT_RESET * HZ; 545 timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
503 while (!*status) { 546 while (!*status) {
504 if (time_after(jiffies, timeout)) { 547 if (time_after(jiffies, timeout))
505 printk(KERN_ERR "%s: IOP reset timeout.\n", c->name);
506 rc = -ETIMEDOUT;
507 goto exit;
508 }
509
510 /* Promise bug */
511 if (status[1] || status[4]) {
512 *status = 0;
513 break; 548 break;
514 }
515 549
516 set_current_state(TASK_UNINTERRUPTIBLE); 550 set_current_state(TASK_UNINTERRUPTIBLE);
517 schedule_timeout(1); 551 schedule_timeout(1);
518
519 rmb();
520 } 552 }
521 553
522 if (*status == I2O_CMD_IN_PROGRESS) { 554 switch (*status) {
555 case I2O_CMD_REJECTED:
556 osm_warn("%s: IOP reset rejected\n", c->name);
557 rc = -EPERM;
558 break;
559
560 case I2O_CMD_IN_PROGRESS:
523 /* 561 /*
524 * Once the reset is sent, the IOP goes into the INIT state 562 * Once the reset is sent, the IOP goes into the INIT state
525 * which is indeterminate. We need to wait until the IOP 563 * which is indeterminate. We need to wait until the IOP has
526 * has rebooted before we can let the system talk to 564 * rebooted before we can let the system talk to it. We read
527 * it. We read the inbound Free_List until a message is 565 * the inbound Free_List until a message is available. If we
528 * available. If we can't read one in the given ammount of 566 * can't read one in the given ammount of time, we assume the
529 * time, we assume the IOP could not reboot properly. 567 * IOP could not reboot properly.
530 */ 568 */
531 pr_debug("%s: Reset in progress, waiting for reboot...\n", 569 osm_debug("%s: Reset in progress, waiting for reboot...\n",
532 c->name); 570 c->name);
533 571
534 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); 572 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
535 while (m == I2O_QUEUE_EMPTY) { 573 while (m == I2O_QUEUE_EMPTY) {
536 if (time_after(jiffies, timeout)) { 574 if (time_after(jiffies, timeout)) {
537 printk(KERN_ERR "%s: IOP reset timeout.\n", 575 osm_err("%s: IOP reset timeout.\n", c->name);
538 c->name);
539 rc = -ETIMEDOUT; 576 rc = -ETIMEDOUT;
540 goto exit; 577 goto exit;
541 } 578 }
@@ -545,19 +582,26 @@ static int i2o_iop_reset(struct i2o_controller *c)
545 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); 582 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
546 } 583 }
547 i2o_msg_nop(c, m); 584 i2o_msg_nop(c, m);
548 }
549 585
550 /* from here all quiesce commands are safe */ 586 /* from here all quiesce commands are safe */
551 c->no_quiesce = 0; 587 c->no_quiesce = 0;
552 588
553 /* If IopReset was rejected or didn't perform reset, try IopClear */ 589 /* verify if controller is in state RESET */
554 i2o_status_get(c); 590 i2o_status_get(c);
555 if (*status == I2O_CMD_REJECTED || sb->iop_state != ADAPTER_STATE_RESET) { 591
556 printk(KERN_WARNING "%s: Reset rejected, trying to clear\n", 592 if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET))
557 c->name); 593 osm_warn("%s: reset completed, but adapter not in RESET"
558 i2o_iop_clear(c); 594 " state.\n", c->name);
559 } else 595 else
560 pr_debug("%s: Reset completed.\n", c->name); 596 osm_debug("%s: reset completed.\n", c->name);
597
598 break;
599
600 default:
601 osm_err("%s: IOP reset timeout.\n", c->name);
602 rc = -ETIMEDOUT;
603 break;
604 }
561 605
562 exit: 606 exit:
563 /* Enable all IOPs */ 607 /* Enable all IOPs */
@@ -567,88 +611,6 @@ static int i2o_iop_reset(struct i2o_controller *c)
567}; 611};
568 612
569/** 613/**
570 * i2o_iop_init_outbound_queue - setup the outbound message queue
571 * @c: I2O controller
572 *
573 * Clear and (re)initialize IOP's outbound queue and post the message
574 * frames to the IOP.
575 *
576 * Returns 0 on success or a negative errno code on failure.
577 */
578static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
579{
580 u8 *status = c->status.virt;
581 u32 m;
582 struct i2o_message __iomem *msg;
583 ulong timeout;
584 int i;
585
586 pr_debug("%s: Initializing Outbound Queue...\n", c->name);
587
588 memset(status, 0, 4);
589
590 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
591 if (m == I2O_QUEUE_EMPTY)
592 return -ETIMEDOUT;
593
594 writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]);
595 writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
596 &msg->u.head[1]);
597 writel(i2o_exec_driver.context, &msg->u.s.icntxt);
598 writel(0x0106, &msg->u.s.tcntxt); /* FIXME: why 0x0106, maybe in
599 Spec? */
600 writel(PAGE_SIZE, &msg->body[0]);
601 writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); /* Outbound msg frame
602 size in words and Initcode */
603 writel(0xd0000004, &msg->body[2]);
604 writel(i2o_ptr_low((void *)c->status.phys), &msg->body[3]);
605 writel(i2o_ptr_high((void *)c->status.phys), &msg->body[4]);
606
607 i2o_msg_post(c, m);
608
609 timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
610 while (*status <= I2O_CMD_IN_PROGRESS) {
611 if (time_after(jiffies, timeout)) {
612 printk(KERN_WARNING "%s: Timeout Initializing\n",
613 c->name);
614 return -ETIMEDOUT;
615 }
616 set_current_state(TASK_UNINTERRUPTIBLE);
617 schedule_timeout(1);
618
619 rmb();
620 }
621
622 m = c->out_queue.phys;
623
624 /* Post frames */
625 for (i = 0; i < NMBR_MSG_FRAMES; i++) {
626 i2o_flush_reply(c, m);
627 udelay(1); /* Promise */
628 m += MSG_FRAME_SIZE * 4;
629 }
630
631 return 0;
632}
633
634/**
635 * i2o_iop_send_nop - send a core NOP message
636 * @c: controller
637 *
638 * Send a no-operation message with a reply set to cause no
639 * action either. Needed for bringing up promise controllers.
640 */
641static int i2o_iop_send_nop(struct i2o_controller *c)
642{
643 struct i2o_message __iomem *msg;
644 u32 m = i2o_msg_get_wait(c, &msg, HZ);
645 if (m == I2O_QUEUE_EMPTY)
646 return -ETIMEDOUT;
647 i2o_msg_nop(c, m);
648 return 0;
649}
650
651/**
652 * i2o_iop_activate - Bring controller up to HOLD 614 * i2o_iop_activate - Bring controller up to HOLD
653 * @c: controller 615 * @c: controller
654 * 616 *
@@ -659,78 +621,62 @@ static int i2o_iop_send_nop(struct i2o_controller *c)
659 */ 621 */
660static int i2o_iop_activate(struct i2o_controller *c) 622static int i2o_iop_activate(struct i2o_controller *c)
661{ 623{
662 struct pci_dev *i960 = NULL;
663 i2o_status_block *sb = c->status_block.virt; 624 i2o_status_block *sb = c->status_block.virt;
664 int rc; 625 int rc;
665 626 int state;
666 if (c->promise) {
667 /* Beat up the hardware first of all */
668 i960 =
669 pci_find_slot(c->pdev->bus->number,
670 PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
671 if (i960)
672 pci_write_config_word(i960, 0x42, 0);
673
674 /* Follow this sequence precisely or the controller
675 ceases to perform useful functions until reboot */
676 if ((rc = i2o_iop_send_nop(c)))
677 return rc;
678
679 if ((rc = i2o_iop_reset(c)))
680 return rc;
681 }
682 627
683 /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ 628 /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
684 /* In READY state, Get status */ 629 /* In READY state, Get status */
685 630
686 rc = i2o_status_get(c); 631 rc = i2o_status_get(c);
687 if (rc) { 632 if (rc) {
688 printk(KERN_INFO "%s: Unable to obtain status, " 633 osm_info("%s: Unable to obtain status, attempting a reset.\n",
689 "attempting a reset.\n", c->name); 634 c->name);
690 if (i2o_iop_reset(c)) 635 rc = i2o_iop_reset(c);
636 if (rc)
691 return rc; 637 return rc;
692 } 638 }
693 639
694 if (sb->i2o_version > I2OVER15) { 640 if (sb->i2o_version > I2OVER15) {
695 printk(KERN_ERR "%s: Not running version 1.5 of the I2O " 641 osm_err("%s: Not running version 1.5 of the I2O Specification."
696 "Specification.\n", c->name); 642 "\n", c->name);
697 return -ENODEV; 643 return -ENODEV;
698 } 644 }
699 645
700 switch (sb->iop_state) { 646 switch (sb->iop_state) {
701 case ADAPTER_STATE_FAULTED: 647 case ADAPTER_STATE_FAULTED:
702 printk(KERN_CRIT "%s: hardware fault\n", c->name); 648 osm_err("%s: hardware fault\n", c->name);
703 return -ENODEV; 649 return -EFAULT;
704 650
705 case ADAPTER_STATE_READY: 651 case ADAPTER_STATE_READY:
706 case ADAPTER_STATE_OPERATIONAL: 652 case ADAPTER_STATE_OPERATIONAL:
707 case ADAPTER_STATE_HOLD: 653 case ADAPTER_STATE_HOLD:
708 case ADAPTER_STATE_FAILED: 654 case ADAPTER_STATE_FAILED:
709 pr_debug("%s: already running, trying to reset...\n", c->name); 655 osm_debug("%s: already running, trying to reset...\n", c->name);
710 if (i2o_iop_reset(c)) 656 rc = i2o_iop_reset(c);
711 return -ENODEV; 657 if (rc)
658 return rc;
712 } 659 }
713 660
661 /* preserve state */
662 state = sb->iop_state;
663
714 rc = i2o_iop_init_outbound_queue(c); 664 rc = i2o_iop_init_outbound_queue(c);
715 if (rc) 665 if (rc)
716 return rc; 666 return rc;
717 667
718 if (c->promise) { 668 /* if adapter was not in RESET state clear now */
719 if ((rc = i2o_iop_send_nop(c))) 669 if (state != ADAPTER_STATE_RESET)
720 return rc; 670 i2o_iop_clear(c);
721 671
722 if ((rc = i2o_status_get(c))) 672 i2o_status_get(c);
723 return rc;
724 673
725 if (i960) 674 if (sb->iop_state != ADAPTER_STATE_HOLD) {
726 pci_write_config_word(i960, 0x42, 0x3FF); 675 osm_err("%s: failed to bring IOP into HOLD state\n", c->name);
676 return -EIO;
727 } 677 }
728 678
729 /* In HOLD state */ 679 return i2o_hrt_get(c);
730
731 rc = i2o_hrt_get(c);
732
733 return rc;
734}; 680};
735 681
736/** 682/**
@@ -756,20 +702,18 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
756 res->flags = IORESOURCE_MEM; 702 res->flags = IORESOURCE_MEM;
757 res->start = 0; 703 res->start = 0;
758 res->end = 0; 704 res->end = 0;
759 printk(KERN_INFO "%s: requires private memory resources.\n", 705 osm_info("%s: requires private memory resources.\n", c->name);
760 c->name);
761 root = pci_find_parent_resource(c->pdev, res); 706 root = pci_find_parent_resource(c->pdev, res);
762 if (root == NULL) 707 if (root == NULL)
763 printk(KERN_WARNING "%s: Can't find parent resource!\n", 708 osm_warn("%s: Can't find parent resource!\n", c->name);
764 c->name);
765 if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ 709 if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
766 NULL, NULL) >= 0) { 710 NULL, NULL) >= 0) {
767 c->mem_alloc = 1; 711 c->mem_alloc = 1;
768 sb->current_mem_size = 1 + res->end - res->start; 712 sb->current_mem_size = 1 + res->end - res->start;
769 sb->current_mem_base = res->start; 713 sb->current_mem_base = res->start;
770 printk(KERN_INFO "%s: allocated %ld bytes of PCI memory" 714 osm_info("%s: allocated %ld bytes of PCI memory at "
771 " at 0x%08lX.\n", c->name, 715 "0x%08lX.\n", c->name,
772 1 + res->end - res->start, res->start); 716 1 + res->end - res->start, res->start);
773 } 717 }
774 } 718 }
775 719
@@ -779,20 +723,18 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
779 res->flags = IORESOURCE_IO; 723 res->flags = IORESOURCE_IO;
780 res->start = 0; 724 res->start = 0;
781 res->end = 0; 725 res->end = 0;
782 printk(KERN_INFO "%s: requires private memory resources.\n", 726 osm_info("%s: requires private memory resources.\n", c->name);
783 c->name);
784 root = pci_find_parent_resource(c->pdev, res); 727 root = pci_find_parent_resource(c->pdev, res);
785 if (root == NULL) 728 if (root == NULL)
786 printk(KERN_WARNING "%s: Can't find parent resource!\n", 729 osm_warn("%s: Can't find parent resource!\n", c->name);
787 c->name);
788 if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ 730 if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
789 NULL, NULL) >= 0) { 731 NULL, NULL) >= 0) {
790 c->io_alloc = 1; 732 c->io_alloc = 1;
791 sb->current_io_size = 1 + res->end - res->start; 733 sb->current_io_size = 1 + res->end - res->start;
792 sb->current_mem_base = res->start; 734 sb->current_mem_base = res->start;
793 printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at" 735 osm_info("%s: allocated %ld bytes of PCI I/O at 0x%08lX"
794 " 0x%08lX.\n", c->name, 736 ".\n", c->name, 1 + res->end - res->start,
795 1 + res->end - res->start, res->start); 737 res->start);
796 } 738 }
797 } 739 }
798 740
@@ -836,10 +778,10 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
836 PCI_DMA_TODEVICE); 778 PCI_DMA_TODEVICE);
837 779
838 if (rc < 0) 780 if (rc < 0)
839 printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n", 781 osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name,
840 c->name, -rc); 782 -rc);
841 else 783 else
842 pr_debug("%s: SysTab set.\n", c->name); 784 osm_debug("%s: SysTab set.\n", c->name);
843 785
844 i2o_status_get(c); // Entered READY state 786 i2o_status_get(c); // Entered READY state
845 787
@@ -863,7 +805,7 @@ static int i2o_iop_online(struct i2o_controller *c)
863 return rc; 805 return rc;
864 806
865 /* In READY state */ 807 /* In READY state */
866 pr_debug("%s: Attempting to enable...\n", c->name); 808 osm_debug("%s: Attempting to enable...\n", c->name);
867 rc = i2o_iop_enable(c); 809 rc = i2o_iop_enable(c);
868 if (rc) 810 if (rc)
869 return rc; 811 return rc;
@@ -882,7 +824,7 @@ void i2o_iop_remove(struct i2o_controller *c)
882{ 824{
883 struct i2o_device *dev, *tmp; 825 struct i2o_device *dev, *tmp;
884 826
885 pr_debug("%s: deleting controller\n", c->name); 827 osm_debug("%s: deleting controller\n", c->name);
886 828
887 i2o_driver_notify_controller_remove_all(c); 829 i2o_driver_notify_controller_remove_all(c);
888 830
@@ -891,8 +833,12 @@ void i2o_iop_remove(struct i2o_controller *c)
891 list_for_each_entry_safe(dev, tmp, &c->devices, list) 833 list_for_each_entry_safe(dev, tmp, &c->devices, list)
892 i2o_device_remove(dev); 834 i2o_device_remove(dev);
893 835
836 device_del(&c->device);
837
894 /* Ask the IOP to switch to RESET state */ 838 /* Ask the IOP to switch to RESET state */
895 i2o_iop_reset(c); 839 i2o_iop_reset(c);
840
841 put_device(&c->device);
896} 842}
897 843
898/** 844/**
@@ -927,8 +873,7 @@ static int i2o_systab_build(void)
927 873
928 systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL); 874 systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);
929 if (!systab) { 875 if (!systab) {
930 printk(KERN_ERR "i2o: unable to allocate memory for System " 876 osm_err("unable to allocate memory for System Table\n");
931 "Table\n");
932 return -ENOMEM; 877 return -ENOMEM;
933 } 878 }
934 memset(systab, 0, i2o_systab.len); 879 memset(systab, 0, i2o_systab.len);
@@ -940,8 +885,8 @@ static int i2o_systab_build(void)
940 i2o_status_block *sb; 885 i2o_status_block *sb;
941 886
942 if (count >= num_controllers) { 887 if (count >= num_controllers) {
943 printk(KERN_ERR "i2o: controller added while building " 888 osm_err("controller added while building system table"
944 "system table\n"); 889 "\n");
945 break; 890 break;
946 } 891 }
947 892
@@ -955,9 +900,8 @@ static int i2o_systab_build(void)
955 * it is techninically not part of the I2O subsystem... 900 * it is techninically not part of the I2O subsystem...
956 */ 901 */
957 if (unlikely(i2o_status_get(c))) { 902 if (unlikely(i2o_status_get(c))) {
958 printk(KERN_ERR "%s: Deleting b/c could not get status" 903 osm_err("%s: Deleting b/c could not get status while "
959 " while attempting to build system table\n", 904 "attempting to build system table\n", c->name);
960 c->name);
961 i2o_iop_remove(c); 905 i2o_iop_remove(c);
962 continue; // try the next one 906 continue; // try the next one
963 } 907 }
@@ -971,8 +915,10 @@ static int i2o_systab_build(void)
971 systab->iops[count].frame_size = sb->inbound_frame_size; 915 systab->iops[count].frame_size = sb->inbound_frame_size;
972 systab->iops[count].last_changed = change_ind; 916 systab->iops[count].last_changed = change_ind;
973 systab->iops[count].iop_capabilities = sb->iop_capabilities; 917 systab->iops[count].iop_capabilities = sb->iop_capabilities;
974 systab->iops[count].inbound_low = i2o_ptr_low(c->post_port); 918 systab->iops[count].inbound_low =
975 systab->iops[count].inbound_high = i2o_ptr_high(c->post_port); 919 i2o_dma_low(c->base.phys + I2O_IN_PORT);
920 systab->iops[count].inbound_high =
921 i2o_dma_high(c->base.phys + I2O_IN_PORT);
976 922
977 count++; 923 count++;
978 } 924 }
@@ -1010,11 +956,11 @@ int i2o_status_get(struct i2o_controller *c)
1010{ 956{
1011 struct i2o_message __iomem *msg; 957 struct i2o_message __iomem *msg;
1012 u32 m; 958 u32 m;
1013 u8 *status_block; 959 volatile u8 *status_block;
1014 unsigned long timeout; 960 unsigned long timeout;
1015 961
1016 status_block = (u8 *) c->status_block.virt; 962 status_block = (u8 *) c->status_block.virt;
1017 memset(status_block, 0, sizeof(i2o_status_block)); 963 memset(c->status_block.virt, 0, sizeof(i2o_status_block));
1018 964
1019 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); 965 m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
1020 if (m == I2O_QUEUE_EMPTY) 966 if (m == I2O_QUEUE_EMPTY)
@@ -1027,8 +973,8 @@ int i2o_status_get(struct i2o_controller *c)
1027 writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context 973 writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context
1028 writel(0, &msg->body[0]); 974 writel(0, &msg->body[0]);
1029 writel(0, &msg->body[1]); 975 writel(0, &msg->body[1]);
1030 writel(i2o_ptr_low((void *)c->status_block.phys), &msg->body[2]); 976 writel(i2o_dma_low(c->status_block.phys), &msg->body[2]);
1031 writel(i2o_ptr_high((void *)c->status_block.phys), &msg->body[3]); 977 writel(i2o_dma_high(c->status_block.phys), &msg->body[3]);
1032 writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */ 978 writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */
1033 979
1034 i2o_msg_post(c, m); 980 i2o_msg_post(c, m);
@@ -1037,14 +983,12 @@ int i2o_status_get(struct i2o_controller *c)
1037 timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; 983 timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
1038 while (status_block[87] != 0xFF) { 984 while (status_block[87] != 0xFF) {
1039 if (time_after(jiffies, timeout)) { 985 if (time_after(jiffies, timeout)) {
1040 printk(KERN_ERR "%s: Get status timeout.\n", c->name); 986 osm_err("%s: Get status timeout.\n", c->name);
1041 return -ETIMEDOUT; 987 return -ETIMEDOUT;
1042 } 988 }
1043 989
1044 set_current_state(TASK_UNINTERRUPTIBLE); 990 set_current_state(TASK_UNINTERRUPTIBLE);
1045 schedule_timeout(1); 991 schedule_timeout(1);
1046
1047 rmb();
1048 } 992 }
1049 993
1050#ifdef DEBUG 994#ifdef DEBUG
@@ -1088,8 +1032,8 @@ static int i2o_hrt_get(struct i2o_controller *c)
1088 rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt); 1032 rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt);
1089 1033
1090 if (rc < 0) { 1034 if (rc < 0) {
1091 printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n", 1035 osm_err("%s: Unable to get HRT (status=%#x)\n", c->name,
1092 c->name, -rc); 1036 -rc);
1093 return rc; 1037 return rc;
1094 } 1038 }
1095 1039
@@ -1103,13 +1047,41 @@ static int i2o_hrt_get(struct i2o_controller *c)
1103 return i2o_parse_hrt(c); 1047 return i2o_parse_hrt(c);
1104 } 1048 }
1105 1049
1106 printk(KERN_ERR "%s: Unable to get HRT after %d tries, giving up\n", 1050 osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name,
1107 c->name, I2O_HRT_GET_TRIES); 1051 I2O_HRT_GET_TRIES);
1108 1052
1109 return -EBUSY; 1053 return -EBUSY;
1110} 1054}
1111 1055
1112/** 1056/**
1057 * i2o_iop_free - Free the i2o_controller struct
1058 * @c: I2O controller to free
1059 */
1060void i2o_iop_free(struct i2o_controller *c)
1061{
1062 kfree(c);
1063};
1064
1065/**
1066 * i2o_iop_release - release the memory for a I2O controller
1067 * @dev: I2O controller which should be released
1068 *
1069 * Release the allocated memory. This function is called if refcount of
1070 * device reaches 0 automatically.
1071 */
1072static void i2o_iop_release(struct device *dev)
1073{
1074 struct i2o_controller *c = to_i2o_controller(dev);
1075
1076 i2o_iop_free(c);
1077};
1078
1079/* I2O controller class */
1080static struct class i2o_controller_class = {
1081 .name = "i2o_controller",
1082};
1083
1084/**
1113 * i2o_iop_alloc - Allocate and initialize a i2o_controller struct 1085 * i2o_iop_alloc - Allocate and initialize a i2o_controller struct
1114 * 1086 *
1115 * Allocate the necessary memory for a i2o_controller struct and 1087 * Allocate the necessary memory for a i2o_controller struct and
@@ -1125,8 +1097,8 @@ struct i2o_controller *i2o_iop_alloc(void)
1125 1097
1126 c = kmalloc(sizeof(*c), GFP_KERNEL); 1098 c = kmalloc(sizeof(*c), GFP_KERNEL);
1127 if (!c) { 1099 if (!c) {
1128 printk(KERN_ERR "i2o: Insufficient memory to allocate a I2O " 1100 osm_err("i2o: Insufficient memory to allocate a I2O controller."
1129 "controller.\n"); 1101 "\n");
1130 return ERR_PTR(-ENOMEM); 1102 return ERR_PTR(-ENOMEM);
1131 } 1103 }
1132 memset(c, 0, sizeof(*c)); 1104 memset(c, 0, sizeof(*c));
@@ -1137,6 +1109,16 @@ struct i2o_controller *i2o_iop_alloc(void)
1137 c->unit = unit++; 1109 c->unit = unit++;
1138 sprintf(c->name, "iop%d", c->unit); 1110 sprintf(c->name, "iop%d", c->unit);
1139 1111
1112 device_initialize(&c->device);
1113 class_device_initialize(&c->classdev);
1114
1115 c->device.release = &i2o_iop_release;
1116 c->classdev.class = &i2o_controller_class;
1117 c->classdev.dev = &c->device;
1118
1119 snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
1120 snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit);
1121
1140#if BITS_PER_LONG == 64 1122#if BITS_PER_LONG == 64
1141 spin_lock_init(&c->context_list_lock); 1123 spin_lock_init(&c->context_list_lock);
1142 atomic_set(&c->context_list_counter, 0); 1124 atomic_set(&c->context_list_counter, 0);
@@ -1147,15 +1129,6 @@ struct i2o_controller *i2o_iop_alloc(void)
1147}; 1129};
1148 1130
1149/** 1131/**
1150 * i2o_iop_free - Free the i2o_controller struct
1151 * @c: I2O controller to free
1152 */
1153void i2o_iop_free(struct i2o_controller *c)
1154{
1155 kfree(c);
1156};
1157
1158/**
1159 * i2o_iop_add - Initialize the I2O controller and add him to the I2O core 1132 * i2o_iop_add - Initialize the I2O controller and add him to the I2O core
1160 * @c: controller 1133 * @c: controller
1161 * 1134 *
@@ -1168,45 +1141,58 @@ int i2o_iop_add(struct i2o_controller *c)
1168{ 1141{
1169 int rc; 1142 int rc;
1170 1143
1171 printk(KERN_INFO "%s: Activating I2O controller...\n", c->name); 1144 if ((rc = device_add(&c->device))) {
1172 printk(KERN_INFO "%s: This may take a few minutes if there are many " 1145 osm_err("%s: could not add controller\n", c->name);
1173 "devices\n", c->name); 1146 goto iop_reset;
1147 }
1174 1148
1175 if ((rc = i2o_iop_activate(c))) { 1149 if ((rc = class_device_add(&c->classdev))) {
1176 printk(KERN_ERR "%s: could not activate controller\n", 1150 osm_err("%s: could not add controller class\n", c->name);
1177 c->name); 1151 goto device_del;
1178 i2o_iop_reset(c);
1179 return rc;
1180 } 1152 }
1181 1153
1182 pr_debug("%s: building sys table...\n", c->name); 1154 osm_info("%s: Activating I2O controller...\n", c->name);
1155 osm_info("%s: This may take a few minutes if there are many devices\n",
1156 c->name);
1183 1157
1184 if ((rc = i2o_systab_build())) { 1158 if ((rc = i2o_iop_activate(c))) {
1185 i2o_iop_reset(c); 1159 osm_err("%s: could not activate controller\n", c->name);
1186 return rc; 1160 goto class_del;
1187 } 1161 }
1188 1162
1189 pr_debug("%s: online controller...\n", c->name); 1163 osm_debug("%s: building sys table...\n", c->name);
1190 1164
1191 if ((rc = i2o_iop_online(c))) { 1165 if ((rc = i2o_systab_build()))
1192 i2o_iop_reset(c); 1166 goto class_del;
1193 return rc;
1194 }
1195 1167
1196 pr_debug("%s: getting LCT...\n", c->name); 1168 osm_debug("%s: online controller...\n", c->name);
1197 1169
1198 if ((rc = i2o_exec_lct_get(c))) { 1170 if ((rc = i2o_iop_online(c)))
1199 i2o_iop_reset(c); 1171 goto class_del;
1200 return rc; 1172
1201 } 1173 osm_debug("%s: getting LCT...\n", c->name);
1174
1175 if ((rc = i2o_exec_lct_get(c)))
1176 goto class_del;
1202 1177
1203 list_add(&c->list, &i2o_controllers); 1178 list_add(&c->list, &i2o_controllers);
1204 1179
1205 i2o_driver_notify_controller_add_all(c); 1180 i2o_driver_notify_controller_add_all(c);
1206 1181
1207 printk(KERN_INFO "%s: Controller added\n", c->name); 1182 osm_info("%s: Controller added\n", c->name);
1208 1183
1209 return 0; 1184 return 0;
1185
1186 class_del:
1187 class_device_del(&c->classdev);
1188
1189 device_del:
1190 device_del(&c->device);
1191
1192 iop_reset:
1193 i2o_iop_reset(c);
1194
1195 return rc;
1210}; 1196};
1211 1197
1212/** 1198/**
@@ -1264,16 +1250,18 @@ static int __init i2o_iop_init(void)
1264 if (rc) 1250 if (rc)
1265 goto exit; 1251 goto exit;
1266 1252
1267 rc = i2o_driver_init(); 1253 if ((rc = class_register(&i2o_controller_class))) {
1268 if (rc) 1254 osm_err("can't register class i2o_controller\n");
1269 goto device_exit; 1255 goto device_exit;
1256 }
1270 1257
1271 rc = i2o_exec_init(); 1258 if ((rc = i2o_driver_init()))
1272 if (rc) 1259 goto class_exit;
1260
1261 if ((rc = i2o_exec_init()))
1273 goto driver_exit; 1262 goto driver_exit;
1274 1263
1275 rc = i2o_pci_init(); 1264 if ((rc = i2o_pci_init()))
1276 if (rc < 0)
1277 goto exec_exit; 1265 goto exec_exit;
1278 1266
1279 return 0; 1267 return 0;
@@ -1284,6 +1272,9 @@ static int __init i2o_iop_init(void)
1284 driver_exit: 1272 driver_exit:
1285 i2o_driver_exit(); 1273 i2o_driver_exit();
1286 1274
1275 class_exit:
1276 class_unregister(&i2o_controller_class);
1277
1287 device_exit: 1278 device_exit:
1288 i2o_device_exit(); 1279 i2o_device_exit();
1289 1280
@@ -1301,6 +1292,7 @@ static void __exit i2o_iop_exit(void)
1301 i2o_pci_exit(); 1292 i2o_pci_exit();
1302 i2o_exec_exit(); 1293 i2o_exec_exit();
1303 i2o_driver_exit(); 1294 i2o_driver_exit();
1295 class_unregister(&i2o_controller_class);
1304 i2o_device_exit(); 1296 i2o_device_exit();
1305}; 1297};
1306 1298
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index e772752f05..7a60fd7be8 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -30,53 +30,18 @@
30#include <linux/pci.h> 30#include <linux/pci.h>
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/i2o.h> 32#include <linux/i2o.h>
33 33#include "core.h"
34#ifdef CONFIG_MTRR
35#include <asm/mtrr.h>
36#endif // CONFIG_MTRR
37
38/* Module internal functions from other sources */
39extern struct i2o_controller *i2o_iop_alloc(void);
40extern void i2o_iop_free(struct i2o_controller *);
41
42extern int i2o_iop_add(struct i2o_controller *);
43extern void i2o_iop_remove(struct i2o_controller *);
44
45extern int i2o_driver_dispatch(struct i2o_controller *, u32,
46 struct i2o_message *);
47 34
48/* PCI device id table for all I2O controllers */ 35/* PCI device id table for all I2O controllers */
49static struct pci_device_id __devinitdata i2o_pci_ids[] = { 36static struct pci_device_id __devinitdata i2o_pci_ids[] = {
50 {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, 37 {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
51 {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, 38 {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},
39 {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962,
40 .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID},
52 {0} 41 {0}
53}; 42};
54 43
55/** 44/**
56 * i2o_dma_realloc - Realloc DMA memory
57 * @dev: struct device pointer to the PCI device of the I2O controller
58 * @addr: pointer to a i2o_dma struct DMA buffer
59 * @len: new length of memory
60 * @gfp_mask: GFP mask
61 *
62 * If there was something allocated in the addr, free it first. If len > 0
63 * than try to allocate it and write the addresses back to the addr
64 * structure. If len == 0 set the virtual address to NULL.
65 *
66 * Returns the 0 on success or negative error code on failure.
67 */
68int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len,
69 unsigned int gfp_mask)
70{
71 i2o_dma_free(dev, addr);
72
73 if (len)
74 return i2o_dma_alloc(dev, addr, len, gfp_mask);
75
76 return 0;
77};
78
79/**
80 * i2o_pci_free - Frees the DMA memory for the I2O controller 45 * i2o_pci_free - Frees the DMA memory for the I2O controller
81 * @c: I2O controller to free 46 * @c: I2O controller to free
82 * 47 *
@@ -91,19 +56,11 @@ static void i2o_pci_free(struct i2o_controller *c)
91 56
92 i2o_dma_free(dev, &c->out_queue); 57 i2o_dma_free(dev, &c->out_queue);
93 i2o_dma_free(dev, &c->status_block); 58 i2o_dma_free(dev, &c->status_block);
94 if (c->lct) 59 kfree(c->lct);
95 kfree(c->lct);
96 i2o_dma_free(dev, &c->dlct); 60 i2o_dma_free(dev, &c->dlct);
97 i2o_dma_free(dev, &c->hrt); 61 i2o_dma_free(dev, &c->hrt);
98 i2o_dma_free(dev, &c->status); 62 i2o_dma_free(dev, &c->status);
99 63
100#ifdef CONFIG_MTRR
101 if (c->mtrr_reg0 >= 0)
102 mtrr_del(c->mtrr_reg0, 0, 0);
103 if (c->mtrr_reg1 >= 0)
104 mtrr_del(c->mtrr_reg1, 0, 0);
105#endif
106
107 if (c->raptor && c->in_queue.virt) 64 if (c->raptor && c->in_queue.virt)
108 iounmap(c->in_queue.virt); 65 iounmap(c->in_queue.virt);
109 66
@@ -178,14 +135,15 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
178 c->name, (unsigned long)c->base.phys, 135 c->name, (unsigned long)c->base.phys,
179 (unsigned long)c->base.len); 136 (unsigned long)c->base.len);
180 137
181 c->base.virt = ioremap(c->base.phys, c->base.len); 138 c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
182 if (!c->base.virt) { 139 if (!c->base.virt) {
183 printk(KERN_ERR "%s: Unable to map controller.\n", c->name); 140 printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
184 return -ENOMEM; 141 return -ENOMEM;
185 } 142 }
186 143
187 if (c->raptor) { 144 if (c->raptor) {
188 c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len); 145 c->in_queue.virt =
146 ioremap_nocache(c->in_queue.phys, c->in_queue.len);
189 if (!c->in_queue.virt) { 147 if (!c->in_queue.virt) {
190 printk(KERN_ERR "%s: Unable to map controller.\n", 148 printk(KERN_ERR "%s: Unable to map controller.\n",
191 c->name); 149 c->name);
@@ -195,43 +153,10 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
195 } else 153 } else
196 c->in_queue = c->base; 154 c->in_queue = c->base;
197 155
198 c->irq_mask = c->base.virt + 0x34; 156 c->irq_status = c->base.virt + I2O_IRQ_STATUS;
199 c->post_port = c->base.virt + 0x40; 157 c->irq_mask = c->base.virt + I2O_IRQ_MASK;
200 c->reply_port = c->base.virt + 0x44; 158 c->in_port = c->base.virt + I2O_IN_PORT;
201 159 c->out_port = c->base.virt + I2O_OUT_PORT;
202#ifdef CONFIG_MTRR
203 /* Enable Write Combining MTRR for IOP's memory region */
204 c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len,
205 MTRR_TYPE_WRCOMB, 1);
206 c->mtrr_reg1 = -1;
207
208 if (c->mtrr_reg0 < 0)
209 printk(KERN_WARNING "%s: could not enable write combining "
210 "MTRR\n", c->name);
211 else
212 printk(KERN_INFO "%s: using write combining MTRR\n", c->name);
213
214 /*
215 * If it is an INTEL i960 I/O processor then set the first 64K to
216 * Uncacheable since the region contains the messaging unit which
217 * shouldn't be cached.
218 */
219 if ((pdev->vendor == PCI_VENDOR_ID_INTEL ||
220 pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) {
221 printk(KERN_INFO "%s: MTRR workaround for Intel i960 processor"
222 "\n", c->name);
223 c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000,
224 MTRR_TYPE_UNCACHABLE, 1);
225
226 if (c->mtrr_reg1 < 0) {
227 printk(KERN_WARNING "%s: Error in setting "
228 "MTRR_TYPE_UNCACHABLE\n", c->name);
229 mtrr_del(c->mtrr_reg0, c->in_queue.phys,
230 c->in_queue.len);
231 c->mtrr_reg0 = -1;
232 }
233 }
234#endif
235 160
236 if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { 161 if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
237 i2o_pci_free(c); 162 i2o_pci_free(c);
@@ -254,7 +179,10 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
254 return -ENOMEM; 179 return -ENOMEM;
255 } 180 }
256 181
257 if (i2o_dma_alloc(dev, &c->out_queue, MSG_POOL_SIZE, GFP_KERNEL)) { 182 if (i2o_dma_alloc
183 (dev, &c->out_queue,
184 I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE *
185 sizeof(u32), GFP_KERNEL)) {
258 i2o_pci_free(c); 186 i2o_pci_free(c);
259 return -ENOMEM; 187 return -ENOMEM;
260 } 188 }
@@ -276,51 +204,30 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
276static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) 204static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
277{ 205{
278 struct i2o_controller *c = dev_id; 206 struct i2o_controller *c = dev_id;
279 struct device *dev = &c->pdev->dev; 207 u32 m;
280 struct i2o_message *m; 208 irqreturn_t rc = IRQ_NONE;
281 u32 mv; 209
282 210 while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) {
283 /* 211 m = readl(c->out_port);
284 * Old 960 steppings had a bug in the I2O unit that caused 212 if (m == I2O_QUEUE_EMPTY) {
285 * the queue to appear empty when it wasn't. 213 /*
286 */ 214 * Old 960 steppings had a bug in the I2O unit that
287 mv = I2O_REPLY_READ32(c); 215 * caused the queue to appear empty when it wasn't.
288 if (mv == I2O_QUEUE_EMPTY) { 216 */
289 mv = I2O_REPLY_READ32(c); 217 m = readl(c->out_port);
290 if (unlikely(mv == I2O_QUEUE_EMPTY)) { 218 if (unlikely(m == I2O_QUEUE_EMPTY))
291 return IRQ_NONE; 219 break;
292 } else 220 }
293 pr_debug("%s: 960 bug detected\n", c->name);
294 }
295
296 while (mv != I2O_QUEUE_EMPTY) {
297 /*
298 * Map the message from the page frame map to kernel virtual.
299 * Because bus_to_virt is deprecated, we have calculate the
300 * location by ourself!
301 */
302 m = i2o_msg_out_to_virt(c, mv);
303
304 /*
305 * Ensure this message is seen coherently but cachably by
306 * the processor
307 */
308 dma_sync_single_for_cpu(dev, mv, MSG_FRAME_SIZE * 4,
309 PCI_DMA_FROMDEVICE);
310 221
311 /* dispatch it */ 222 /* dispatch it */
312 if (i2o_driver_dispatch(c, mv, m)) 223 if (i2o_driver_dispatch(c, m))
313 /* flush it if result != 0 */ 224 /* flush it if result != 0 */
314 i2o_flush_reply(c, mv); 225 i2o_flush_reply(c, m);
315 226
316 /* 227 rc = IRQ_HANDLED;
317 * That 960 bug again...
318 */
319 mv = I2O_REPLY_READ32(c);
320 if (mv == I2O_QUEUE_EMPTY)
321 mv = I2O_REPLY_READ32(c);
322 } 228 }
323 return IRQ_HANDLED; 229
230 return rc;
324} 231}
325 232
326/** 233/**
@@ -336,7 +243,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
336 struct pci_dev *pdev = c->pdev; 243 struct pci_dev *pdev = c->pdev;
337 int rc; 244 int rc;
338 245
339 I2O_IRQ_WRITE32(c, 0xffffffff); 246 writel(0xffffffff, c->irq_mask);
340 247
341 if (pdev->irq) { 248 if (pdev->irq) {
342 rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ, 249 rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ,
@@ -348,7 +255,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
348 } 255 }
349 } 256 }
350 257
351 I2O_IRQ_WRITE32(c, 0x00000000); 258 writel(0x00000000, c->irq_mask);
352 259
353 printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq); 260 printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq);
354 261
@@ -363,7 +270,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
363 */ 270 */
364static void i2o_pci_irq_disable(struct i2o_controller *c) 271static void i2o_pci_irq_disable(struct i2o_controller *c)
365{ 272{
366 I2O_IRQ_WRITE32(c, 0xffffffff); 273 writel(0xffffffff, c->irq_mask);
367 274
368 if (c->pdev->irq > 0) 275 if (c->pdev->irq > 0)
369 free_irq(c->pdev->irq, c); 276 free_irq(c->pdev->irq, c);
@@ -385,28 +292,25 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
385{ 292{
386 struct i2o_controller *c; 293 struct i2o_controller *c;
387 int rc; 294 int rc;
295 struct pci_dev *i960 = NULL;
388 296
389 printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); 297 printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
390 298
391 if ((pdev->class & 0xff) > 1) { 299 if ((pdev->class & 0xff) > 1) {
392 printk(KERN_WARNING "i2o: I2O controller found but does not " 300 printk(KERN_WARNING "i2o: %s does not support I2O 1.5 "
393 "support I2O 1.5 (skipping).\n"); 301 "(skipping).\n", pci_name(pdev));
394 return -ENODEV; 302 return -ENODEV;
395 } 303 }
396 304
397 if ((rc = pci_enable_device(pdev))) { 305 if ((rc = pci_enable_device(pdev))) {
398 printk(KERN_WARNING "i2o: I2O controller found but could not be" 306 printk(KERN_WARNING "i2o: couldn't enable device %s\n",
399 " enabled.\n"); 307 pci_name(pdev));
400 return rc; 308 return rc;
401 } 309 }
402 310
403 printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n",
404 pdev->bus->number, pdev->devfn);
405
406 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { 311 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
407 printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No " 312 printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
408 "suitable DMA available!\n", pdev->bus->number, 313 pci_name(pdev));
409 pdev->devfn);
410 rc = -ENODEV; 314 rc = -ENODEV;
411 goto disable; 315 goto disable;
412 } 316 }
@@ -415,14 +319,16 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
415 319
416 c = i2o_iop_alloc(); 320 c = i2o_iop_alloc();
417 if (IS_ERR(c)) { 321 if (IS_ERR(c)) {
418 printk(KERN_ERR "i2o: memory for I2O controller could not be " 322 printk(KERN_ERR "i2o: couldn't allocate memory for %s\n",
419 "allocated\n"); 323 pci_name(pdev));
420 rc = PTR_ERR(c); 324 rc = PTR_ERR(c);
421 goto disable; 325 goto disable;
422 } 326 } else
327 printk(KERN_INFO "%s: controller found (%s)\n", c->name,
328 pci_name(pdev));
423 329
424 c->pdev = pdev; 330 c->pdev = pdev;
425 c->device = pdev->dev; 331 c->device.parent = get_device(&pdev->dev);
426 332
427 /* Cards that fall apart if you hit them with large I/O loads... */ 333 /* Cards that fall apart if you hit them with large I/O loads... */
428 if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { 334 if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
@@ -432,16 +338,48 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
432 } 338 }
433 339
434 if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { 340 if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) {
341 /*
342 * Expose the ship behind i960 for initialization, or it will
343 * failed
344 */
345 i960 =
346 pci_find_slot(c->pdev->bus->number,
347 PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
348
349 if (i960)
350 pci_write_config_word(i960, 0x42, 0);
351
435 c->promise = 1; 352 c->promise = 1;
436 printk(KERN_INFO "%s: Promise workarounds activated.\n", 353 c->limit_sectors = 1;
437 c->name);
438 } 354 }
439 355
356 if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT)
357 c->adaptec = 1;
358
440 /* Cards that go bananas if you quiesce them before you reset them. */ 359 /* Cards that go bananas if you quiesce them before you reset them. */
441 if (pdev->vendor == PCI_VENDOR_ID_DPT) { 360 if (pdev->vendor == PCI_VENDOR_ID_DPT) {
442 c->no_quiesce = 1; 361 c->no_quiesce = 1;
443 if (pdev->device == 0xa511) 362 if (pdev->device == 0xa511)
444 c->raptor = 1; 363 c->raptor = 1;
364
365 if (pdev->subsystem_device == 0xc05a) {
366 c->limit_sectors = 1;
367 printk(KERN_INFO
368 "%s: limit sectors per request to %d\n", c->name,
369 I2O_MAX_SECTORS_LIMITED);
370 }
371#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
372 if (sizeof(dma_addr_t) > 4) {
373 if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
374 printk(KERN_INFO "%s: 64-bit DMA unavailable\n",
375 c->name);
376 else {
377 c->pae_support = 1;
378 printk(KERN_INFO "%s: using 64-bit DMA\n",
379 c->name);
380 }
381 }
382#endif
445 } 383 }
446 384
447 if ((rc = i2o_pci_alloc(c))) { 385 if ((rc = i2o_pci_alloc(c))) {
@@ -459,6 +397,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
459 if ((rc = i2o_iop_add(c))) 397 if ((rc = i2o_iop_add(c)))
460 goto uninstall; 398 goto uninstall;
461 399
400 get_device(&c->device);
401
402 if (i960)
403 pci_write_config_word(i960, 0x42, 0x03ff);
404
462 return 0; 405 return 0;
463 406
464 uninstall: 407 uninstall:
@@ -469,6 +412,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
469 412
470 free_controller: 413 free_controller:
471 i2o_iop_free(c); 414 i2o_iop_free(c);
415 put_device(c->device.parent);
472 416
473 disable: 417 disable:
474 pci_disable_device(pdev); 418 pci_disable_device(pdev);
@@ -492,15 +436,17 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev)
492 i2o_pci_irq_disable(c); 436 i2o_pci_irq_disable(c);
493 i2o_pci_free(c); 437 i2o_pci_free(c);
494 438
439 pci_disable_device(pdev);
440
495 printk(KERN_INFO "%s: Controller removed.\n", c->name); 441 printk(KERN_INFO "%s: Controller removed.\n", c->name);
496 442
497 i2o_iop_free(c); 443 put_device(c->device.parent);
498 pci_disable_device(pdev); 444 put_device(&c->device);
499}; 445};
500 446
501/* PCI driver for I2O controller */ 447/* PCI driver for I2O controller */
502static struct pci_driver i2o_pci_driver = { 448static struct pci_driver i2o_pci_driver = {
503 .name = "I2O controller", 449 .name = "PCI_I2O",
504 .id_table = i2o_pci_ids, 450 .id_table = i2o_pci_ids,
505 .probe = i2o_pci_probe, 451 .probe = i2o_pci_probe,
506 .remove = __devexit_p(i2o_pci_remove), 452 .remove = __devexit_p(i2o_pci_remove),
@@ -523,6 +469,4 @@ void __exit i2o_pci_exit(void)
523{ 469{
524 pci_unregister_driver(&i2o_pci_driver); 470 pci_unregister_driver(&i2o_pci_driver);
525}; 471};
526
527EXPORT_SYMBOL(i2o_dma_realloc);
528MODULE_DEVICE_TABLE(pci, i2o_pci_ids); 472MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 745a141836..531b073131 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -206,7 +206,7 @@ static inline unsigned long fast_get_dcookie(struct dentry * dentry,
206 */ 206 */
207static unsigned long get_exec_dcookie(struct mm_struct * mm) 207static unsigned long get_exec_dcookie(struct mm_struct * mm)
208{ 208{
209 unsigned long cookie = 0; 209 unsigned long cookie = NO_COOKIE;
210 struct vm_area_struct * vma; 210 struct vm_area_struct * vma;
211 211
212 if (!mm) 212 if (!mm)
@@ -234,35 +234,42 @@ out:
234 */ 234 */
235static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset) 235static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset)
236{ 236{
237 unsigned long cookie = 0; 237 unsigned long cookie = NO_COOKIE;
238 struct vm_area_struct * vma; 238 struct vm_area_struct * vma;
239 239
240 for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { 240 for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
241 241
242 if (!vma->vm_file)
243 continue;
244
245 if (addr < vma->vm_start || addr >= vma->vm_end) 242 if (addr < vma->vm_start || addr >= vma->vm_end)
246 continue; 243 continue;
247 244
248 cookie = fast_get_dcookie(vma->vm_file->f_dentry, 245 if (vma->vm_file) {
249 vma->vm_file->f_vfsmnt); 246 cookie = fast_get_dcookie(vma->vm_file->f_dentry,
250 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; 247 vma->vm_file->f_vfsmnt);
248 *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr -
249 vma->vm_start;
250 } else {
251 /* must be an anonymous map */
252 *offset = addr;
253 }
254
251 break; 255 break;
252 } 256 }
253 257
258 if (!vma)
259 cookie = INVALID_COOKIE;
260
254 return cookie; 261 return cookie;
255} 262}
256 263
257 264
258static unsigned long last_cookie = ~0UL; 265static unsigned long last_cookie = INVALID_COOKIE;
259 266
260static void add_cpu_switch(int i) 267static void add_cpu_switch(int i)
261{ 268{
262 add_event_entry(ESCAPE_CODE); 269 add_event_entry(ESCAPE_CODE);
263 add_event_entry(CPU_SWITCH_CODE); 270 add_event_entry(CPU_SWITCH_CODE);
264 add_event_entry(i); 271 add_event_entry(i);
265 last_cookie = ~0UL; 272 last_cookie = INVALID_COOKIE;
266} 273}
267 274
268static void add_kernel_ctx_switch(unsigned int in_kernel) 275static void add_kernel_ctx_switch(unsigned int in_kernel)
@@ -317,7 +324,7 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s)
317 324
318 cookie = lookup_dcookie(mm, s->eip, &offset); 325 cookie = lookup_dcookie(mm, s->eip, &offset);
319 326
320 if (!cookie) { 327 if (cookie == INVALID_COOKIE) {
321 atomic_inc(&oprofile_stats.sample_lost_no_mapping); 328 atomic_inc(&oprofile_stats.sample_lost_no_mapping);
322 return 0; 329 return 0;
323 } 330 }
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 442aaad391..0180236305 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -35,6 +35,9 @@ void wake_up_buffer_waiter(void);
35#define TRACE_BEGIN_CODE 8 35#define TRACE_BEGIN_CODE 8
36#define TRACE_END_CODE 9 36#define TRACE_END_CODE 9
37 37
38#define INVALID_COOKIE ~0UL
39#define NO_COOKIE 0UL
40
38/* add data to the event buffer */ 41/* add data to the event buffer */
39void add_event_entry(unsigned long data); 42void add_event_entry(unsigned long data);
40 43
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 3252662958..add12f7c48 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -259,7 +259,6 @@ int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev)
259 259
260/** 260/**
261 * pnp_remove_card_device- removes a device from the specified card 261 * pnp_remove_card_device- removes a device from the specified card
262 * @card: pointer to the card to remove from
263 * @dev: pointer to the device to remove 262 * @dev: pointer to the device to remove
264 */ 263 */
265 264
@@ -274,7 +273,7 @@ void pnp_remove_card_device(struct pnp_dev * dev)
274 273
275/** 274/**
276 * pnp_request_card_device - Searches for a PnP device under the specified card 275 * pnp_request_card_device - Searches for a PnP device under the specified card
277 * @lcard: pointer to the card link, cannot be NULL 276 * @clink: pointer to the card link, cannot be NULL
278 * @id: pointer to a PnP ID structure that explains the rules for finding the device 277 * @id: pointer to a PnP ID structure that explains the rules for finding the device
279 * @from: Starting place to search from. If NULL it will start from the begining. 278 * @from: Starting place to search from. If NULL it will start from the begining.
280 */ 279 */
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 65ecef7385..6c510c19ad 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -390,6 +390,7 @@ fail:
390 * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table 390 * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
391 * @dev: pointer to the desired device 391 * @dev: pointer to the desired device
392 * @res: pointer to the new resource config 392 * @res: pointer to the new resource config
393 * @mode: 0 or PNP_CONFIG_FORCE
393 * 394 *
394 * This function can be used by drivers that want to manually set thier resources. 395 * This function can be used by drivers that want to manually set thier resources.
395 */ 396 */
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 16ab8d363a..6bc27d5232 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -35,14 +35,17 @@
35static int dcssblk_open(struct inode *inode, struct file *filp); 35static int dcssblk_open(struct inode *inode, struct file *filp);
36static int dcssblk_release(struct inode *inode, struct file *filp); 36static int dcssblk_release(struct inode *inode, struct file *filp);
37static int dcssblk_make_request(struct request_queue *q, struct bio *bio); 37static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
38static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
39 unsigned long *data);
38 40
39static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; 41static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
40 42
41static int dcssblk_major; 43static int dcssblk_major;
42static struct block_device_operations dcssblk_devops = { 44static struct block_device_operations dcssblk_devops = {
43 .owner = THIS_MODULE, 45 .owner = THIS_MODULE,
44 .open = dcssblk_open, 46 .open = dcssblk_open,
45 .release = dcssblk_release, 47 .release = dcssblk_release,
48 .direct_access = dcssblk_direct_access,
46}; 49};
47 50
48static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf, 51static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
@@ -641,6 +644,20 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio)
641 /* Request beyond end of DCSS segment. */ 644 /* Request beyond end of DCSS segment. */
642 goto fail; 645 goto fail;
643 } 646 }
647 /* verify data transfer direction */
648 if (dev_info->is_shared) {
649 switch (dev_info->segment_type) {
650 case SEG_TYPE_SR:
651 case SEG_TYPE_ER:
652 case SEG_TYPE_SC:
653 /* cannot write to these segments */
654 if (bio_data_dir(bio) == WRITE) {
655 PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id);
656 goto fail;
657 }
658 }
659 }
660
644 index = (bio->bi_sector >> 3); 661 index = (bio->bi_sector >> 3);
645 bio_for_each_segment(bvec, bio, i) { 662 bio_for_each_segment(bvec, bio, i) {
646 page_addr = (unsigned long) 663 page_addr = (unsigned long)
@@ -661,7 +678,26 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio)
661 bio_endio(bio, bytes_done, 0); 678 bio_endio(bio, bytes_done, 0);
662 return 0; 679 return 0;
663fail: 680fail:
664 bio_io_error(bio, bytes_done); 681 bio_io_error(bio, bio->bi_size);
682 return 0;
683}
684
685static int
686dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
687 unsigned long *data)
688{
689 struct dcssblk_dev_info *dev_info;
690 unsigned long pgoff;
691
692 dev_info = bdev->bd_disk->private_data;
693 if (!dev_info)
694 return -ENODEV;
695 if (secnum % (PAGE_SIZE/512))
696 return -EINVAL;
697 pgoff = secnum / (PAGE_SIZE / 512);
698 if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
699 return -ERANGE;
700 *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE);
665 return 0; 701 return 0;
666} 702}
667 703
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index ba347576d9..d7a38b6713 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -56,7 +56,7 @@ static struct class shost_class = {
56 * @shost: pointer to struct Scsi_Host 56 * @shost: pointer to struct Scsi_Host
57 * recovery: recovery requested to run. 57 * recovery: recovery requested to run.
58 **/ 58 **/
59void scsi_host_cancel(struct Scsi_Host *shost, int recovery) 59static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
60{ 60{
61 struct scsi_device *sdev; 61 struct scsi_device *sdev;
62 62
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 5578ae9a9e..1cb5f7d4f2 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -68,6 +68,8 @@
68#include "scsi_priv.h" 68#include "scsi_priv.h"
69#include "scsi_logging.h" 69#include "scsi_logging.h"
70 70
71static void scsi_done(struct scsi_cmnd *cmd);
72static int scsi_retry_command(struct scsi_cmnd *cmd);
71 73
72/* 74/*
73 * Definitions and constants. 75 * Definitions and constants.
@@ -741,7 +743,7 @@ static DEFINE_PER_CPU(struct list_head, scsi_done_q);
741 * 743 *
742 * This function is interrupt context safe. 744 * This function is interrupt context safe.
743 */ 745 */
744void scsi_done(struct scsi_cmnd *cmd) 746static void scsi_done(struct scsi_cmnd *cmd)
745{ 747{
746 /* 748 /*
747 * We don't have to worry about this one timing out any more. 749 * We don't have to worry about this one timing out any more.
@@ -836,7 +838,7 @@ static void scsi_softirq(struct softirq_action *h)
836 * level drivers should not become re-entrant as a result of 838 * level drivers should not become re-entrant as a result of
837 * this. 839 * this.
838 */ 840 */
839int scsi_retry_command(struct scsi_cmnd *cmd) 841static int scsi_retry_command(struct scsi_cmnd *cmd)
840{ 842{
841 /* 843 /*
842 * Restore the SCSI command state. 844 * Restore the SCSI command state.
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index e0208886b4..322b5a41a3 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1783,7 +1783,7 @@ static void __exit scsi_debug_exit(void)
1783device_initcall(scsi_debug_init); 1783device_initcall(scsi_debug_init);
1784module_exit(scsi_debug_exit); 1784module_exit(scsi_debug_exit);
1785 1785
1786void pseudo_0_release(struct device * dev) 1786static void pseudo_0_release(struct device * dev)
1787{ 1787{
1788 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 1788 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
1789 printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n"); 1789 printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 9f996499fa..621dee8b8c 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -44,7 +44,7 @@ struct scsi_host_sg_pool {
44#endif 44#endif
45 45
46#define SP(x) { x, "sgpool-" #x } 46#define SP(x) { x, "sgpool-" #x }
47struct scsi_host_sg_pool scsi_sg_pools[] = { 47static struct scsi_host_sg_pool scsi_sg_pools[] = {
48 SP(8), 48 SP(8),
49 SP(16), 49 SP(16),
50 SP(32), 50 SP(32),
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index c01580df44..96d4f74597 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -61,8 +61,6 @@ extern void scsi_exit_hosts(void);
61extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); 61extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
62extern int scsi_setup_command_freelist(struct Scsi_Host *shost); 62extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
63extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); 63extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
64extern void scsi_done(struct scsi_cmnd *cmd);
65extern int scsi_retry_command(struct scsi_cmnd *cmd);
66extern int scsi_insert_special_req(struct scsi_request *sreq, int); 64extern int scsi_insert_special_req(struct scsi_request *sreq, int);
67extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, 65extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
68 struct scsi_request *sreq); 66 struct scsi_request *sreq);
@@ -136,7 +134,6 @@ extern void scsi_exit_sysctl(void);
136#endif /* CONFIG_SYSCTL */ 134#endif /* CONFIG_SYSCTL */
137 135
138/* scsi_sysfs.c */ 136/* scsi_sysfs.c */
139extern void scsi_device_dev_release(struct device *);
140extern int scsi_sysfs_add_sdev(struct scsi_device *); 137extern int scsi_sysfs_add_sdev(struct scsi_device *);
141extern int scsi_sysfs_add_host(struct Scsi_Host *); 138extern int scsi_sysfs_add_host(struct Scsi_Host *);
142extern int scsi_sysfs_register(void); 139extern int scsi_sysfs_register(void);
@@ -145,7 +142,6 @@ extern void scsi_sysfs_device_initialize(struct scsi_device *);
145extern int scsi_sysfs_target_initialize(struct scsi_device *); 142extern int scsi_sysfs_target_initialize(struct scsi_device *);
146extern struct scsi_transport_template blank_transport_template; 143extern struct scsi_transport_template blank_transport_template;
147 144
148extern struct class sdev_class;
149extern struct bus_type scsi_bus_type; 145extern struct bus_type scsi_bus_type;
150 146
151/* 147/*
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 93b41100a6..beed7fbe1c 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -150,7 +150,7 @@ static void scsi_device_cls_release(struct class_device *class_dev)
150 put_device(&sdev->sdev_gendev); 150 put_device(&sdev->sdev_gendev);
151} 151}
152 152
153void scsi_device_dev_release(struct device *dev) 153static void scsi_device_dev_release(struct device *dev)
154{ 154{
155 struct scsi_device *sdev; 155 struct scsi_device *sdev;
156 struct device *parent; 156 struct device *parent;
@@ -185,7 +185,7 @@ void scsi_device_dev_release(struct device *dev)
185 put_device(parent); 185 put_device(parent);
186} 186}
187 187
188struct class sdev_class = { 188static struct class sdev_class = {
189 .name = "scsi_device", 189 .name = "scsi_device",
190 .release = scsi_device_cls_release, 190 .release = scsi_device_cls_release,
191}; 191};
diff --git a/fs/Kconfig b/fs/Kconfig
index a7c0cc3203..8157f2e2d5 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -50,6 +50,23 @@ config EXT2_FS_SECURITY
50 If you are not using a security module that requires using 50 If you are not using a security module that requires using
51 extended attributes for file security labels, say N. 51 extended attributes for file security labels, say N.
52 52
53config EXT2_FS_XIP
54 bool "Ext2 execute in place support"
55 depends on EXT2_FS
56 help
57 Execute in place can be used on memory-backed block devices. If you
58 enable this option, you can select to mount block devices which are
59 capable of this feature without using the page cache.
60
61 If you do not use a block device that is capable of using this,
62 or if unsure, say N.
63
64config FS_XIP
65# execute in place
66 bool
67 depends on EXT2_FS_XIP
68 default y
69
53config EXT3_FS 70config EXT3_FS
54 tristate "Ext3 journalling file system support" 71 tristate "Ext3 journalling file system support"
55 help 72 help
@@ -1413,6 +1430,8 @@ config NFSD_V4
1413 bool "Provide NFSv4 server support (EXPERIMENTAL)" 1430 bool "Provide NFSv4 server support (EXPERIMENTAL)"
1414 depends on NFSD_V3 && EXPERIMENTAL 1431 depends on NFSD_V3 && EXPERIMENTAL
1415 select NFSD_TCP 1432 select NFSD_TCP
1433 select CRYPTO_MD5
1434 select CRYPTO
1416 help 1435 help
1417 If you would like to include the NFSv4 server as well as the NFSv2 1436 If you would like to include the NFSv4 server as well as the NFSv2
1418 and NFSv3 servers, say Y here. This feature is experimental, and 1437 and NFSv3 servers, say Y here. This feature is experimental, and
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 1d55e7e673..0d06097bc9 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -215,7 +215,7 @@ static struct page *dio_get_page(struct dio *dio)
215static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes) 215static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
216{ 216{
217 if (dio->end_io && dio->result) 217 if (dio->end_io && dio->result)
218 dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private); 218 dio->end_io(dio->iocb, offset, bytes, dio->map_bh.b_private);
219 if (dio->lock_type == DIO_LOCKING) 219 if (dio->lock_type == DIO_LOCKING)
220 up_read(&dio->inode->i_alloc_sem); 220 up_read(&dio->inode->i_alloc_sem);
221} 221}
diff --git a/fs/ext2/Makefile b/fs/ext2/Makefile
index ee240a14e7..c5d02da73b 100644
--- a/fs/ext2/Makefile
+++ b/fs/ext2/Makefile
@@ -10,3 +10,4 @@ ext2-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
10ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o 10ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
11ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o 11ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o
12ext2-$(CONFIG_EXT2_FS_SECURITY) += xattr_security.o 12ext2-$(CONFIG_EXT2_FS_SECURITY) += xattr_security.o
13ext2-$(CONFIG_EXT2_FS_XIP) += xip.o
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 8f0fd726c3..eed521d22c 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -147,9 +147,11 @@ extern struct file_operations ext2_dir_operations;
147/* file.c */ 147/* file.c */
148extern struct inode_operations ext2_file_inode_operations; 148extern struct inode_operations ext2_file_inode_operations;
149extern struct file_operations ext2_file_operations; 149extern struct file_operations ext2_file_operations;
150extern struct file_operations ext2_xip_file_operations;
150 151
151/* inode.c */ 152/* inode.c */
152extern struct address_space_operations ext2_aops; 153extern struct address_space_operations ext2_aops;
154extern struct address_space_operations ext2_aops_xip;
153extern struct address_space_operations ext2_nobh_aops; 155extern struct address_space_operations ext2_nobh_aops;
154 156
155/* namei.c */ 157/* namei.c */
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index f5e86141ec..a484412fc7 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -55,6 +55,20 @@ struct file_operations ext2_file_operations = {
55 .sendfile = generic_file_sendfile, 55 .sendfile = generic_file_sendfile,
56}; 56};
57 57
58#ifdef CONFIG_EXT2_FS_XIP
59struct file_operations ext2_xip_file_operations = {
60 .llseek = generic_file_llseek,
61 .read = xip_file_read,
62 .write = xip_file_write,
63 .ioctl = ext2_ioctl,
64 .mmap = xip_file_mmap,
65 .open = generic_file_open,
66 .release = ext2_release_file,
67 .fsync = ext2_sync_file,
68 .sendfile = xip_file_sendfile,
69};
70#endif
71
58struct inode_operations ext2_file_inode_operations = { 72struct inode_operations ext2_file_inode_operations = {
59 .truncate = ext2_truncate, 73 .truncate = ext2_truncate,
60#ifdef CONFIG_EXT2_FS_XATTR 74#ifdef CONFIG_EXT2_FS_XATTR
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index a50d9db4b6..53dceb0c65 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -33,6 +33,7 @@
33#include <linux/mpage.h> 33#include <linux/mpage.h>
34#include "ext2.h" 34#include "ext2.h"
35#include "acl.h" 35#include "acl.h"
36#include "xip.h"
36 37
37MODULE_AUTHOR("Remy Card and others"); 38MODULE_AUTHOR("Remy Card and others");
38MODULE_DESCRIPTION("Second Extended Filesystem"); 39MODULE_DESCRIPTION("Second Extended Filesystem");
@@ -594,6 +595,16 @@ out:
594 if (err) 595 if (err)
595 goto cleanup; 596 goto cleanup;
596 597
598 if (ext2_use_xip(inode->i_sb)) {
599 /*
600 * we need to clear the block
601 */
602 err = ext2_clear_xip_target (inode,
603 le32_to_cpu(chain[depth-1].key));
604 if (err)
605 goto cleanup;
606 }
607
597 if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0) 608 if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0)
598 goto changed; 609 goto changed;
599 610
@@ -691,6 +702,11 @@ struct address_space_operations ext2_aops = {
691 .writepages = ext2_writepages, 702 .writepages = ext2_writepages,
692}; 703};
693 704
705struct address_space_operations ext2_aops_xip = {
706 .bmap = ext2_bmap,
707 .get_xip_page = ext2_get_xip_page,
708};
709
694struct address_space_operations ext2_nobh_aops = { 710struct address_space_operations ext2_nobh_aops = {
695 .readpage = ext2_readpage, 711 .readpage = ext2_readpage,
696 .readpages = ext2_readpages, 712 .readpages = ext2_readpages,
@@ -910,7 +926,9 @@ void ext2_truncate (struct inode * inode)
910 iblock = (inode->i_size + blocksize-1) 926 iblock = (inode->i_size + blocksize-1)
911 >> EXT2_BLOCK_SIZE_BITS(inode->i_sb); 927 >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
912 928
913 if (test_opt(inode->i_sb, NOBH)) 929 if (mapping_is_xip(inode->i_mapping))
930 xip_truncate_page(inode->i_mapping, inode->i_size);
931 else if (test_opt(inode->i_sb, NOBH))
914 nobh_truncate_page(inode->i_mapping, inode->i_size); 932 nobh_truncate_page(inode->i_mapping, inode->i_size);
915 else 933 else
916 block_truncate_page(inode->i_mapping, 934 block_truncate_page(inode->i_mapping,
@@ -1110,11 +1128,16 @@ void ext2_read_inode (struct inode * inode)
1110 1128
1111 if (S_ISREG(inode->i_mode)) { 1129 if (S_ISREG(inode->i_mode)) {
1112 inode->i_op = &ext2_file_inode_operations; 1130 inode->i_op = &ext2_file_inode_operations;
1113 inode->i_fop = &ext2_file_operations; 1131 if (ext2_use_xip(inode->i_sb)) {
1114 if (test_opt(inode->i_sb, NOBH)) 1132 inode->i_mapping->a_ops = &ext2_aops_xip;
1133 inode->i_fop = &ext2_xip_file_operations;
1134 } else if (test_opt(inode->i_sb, NOBH)) {
1115 inode->i_mapping->a_ops = &ext2_nobh_aops; 1135 inode->i_mapping->a_ops = &ext2_nobh_aops;
1116 else 1136 inode->i_fop = &ext2_file_operations;
1137 } else {
1117 inode->i_mapping->a_ops = &ext2_aops; 1138 inode->i_mapping->a_ops = &ext2_aops;
1139 inode->i_fop = &ext2_file_operations;
1140 }
1118 } else if (S_ISDIR(inode->i_mode)) { 1141 } else if (S_ISDIR(inode->i_mode)) {
1119 inode->i_op = &ext2_dir_inode_operations; 1142 inode->i_op = &ext2_dir_inode_operations;
1120 inode->i_fop = &ext2_dir_operations; 1143 inode->i_fop = &ext2_dir_operations;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 3176b3d3ff..c5513953c8 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -34,6 +34,7 @@
34#include "ext2.h" 34#include "ext2.h"
35#include "xattr.h" 35#include "xattr.h"
36#include "acl.h" 36#include "acl.h"
37#include "xip.h"
37 38
38/* 39/*
39 * Couple of helper functions - make the code slightly cleaner. 40 * Couple of helper functions - make the code slightly cleaner.
@@ -127,11 +128,16 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st
127 int err = PTR_ERR(inode); 128 int err = PTR_ERR(inode);
128 if (!IS_ERR(inode)) { 129 if (!IS_ERR(inode)) {
129 inode->i_op = &ext2_file_inode_operations; 130 inode->i_op = &ext2_file_inode_operations;
130 inode->i_fop = &ext2_file_operations; 131 if (ext2_use_xip(inode->i_sb)) {
131 if (test_opt(inode->i_sb, NOBH)) 132 inode->i_mapping->a_ops = &ext2_aops_xip;
133 inode->i_fop = &ext2_xip_file_operations;
134 } else if (test_opt(inode->i_sb, NOBH)) {
132 inode->i_mapping->a_ops = &ext2_nobh_aops; 135 inode->i_mapping->a_ops = &ext2_nobh_aops;
133 else 136 inode->i_fop = &ext2_file_operations;
137 } else {
134 inode->i_mapping->a_ops = &ext2_aops; 138 inode->i_mapping->a_ops = &ext2_aops;
139 inode->i_fop = &ext2_file_operations;
140 }
135 mark_inode_dirty(inode); 141 mark_inode_dirty(inode);
136 err = ext2_add_nondir(dentry, inode); 142 err = ext2_add_nondir(dentry, inode);
137 } 143 }
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 661c3d98d9..876e391f28 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -31,6 +31,7 @@
31#include "ext2.h" 31#include "ext2.h"
32#include "xattr.h" 32#include "xattr.h"
33#include "acl.h" 33#include "acl.h"
34#include "xip.h"
34 35
35static void ext2_sync_super(struct super_block *sb, 36static void ext2_sync_super(struct super_block *sb,
36 struct ext2_super_block *es); 37 struct ext2_super_block *es);
@@ -257,7 +258,7 @@ enum {
257 Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, 258 Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
258 Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, 259 Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
259 Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh, 260 Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh,
260 Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, 261 Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip,
261 Opt_ignore, Opt_err, 262 Opt_ignore, Opt_err,
262}; 263};
263 264
@@ -286,6 +287,7 @@ static match_table_t tokens = {
286 {Opt_nouser_xattr, "nouser_xattr"}, 287 {Opt_nouser_xattr, "nouser_xattr"},
287 {Opt_acl, "acl"}, 288 {Opt_acl, "acl"},
288 {Opt_noacl, "noacl"}, 289 {Opt_noacl, "noacl"},
290 {Opt_xip, "xip"},
289 {Opt_ignore, "grpquota"}, 291 {Opt_ignore, "grpquota"},
290 {Opt_ignore, "noquota"}, 292 {Opt_ignore, "noquota"},
291 {Opt_ignore, "quota"}, 293 {Opt_ignore, "quota"},
@@ -397,6 +399,13 @@ static int parse_options (char * options,
397 printk("EXT2 (no)acl options not supported\n"); 399 printk("EXT2 (no)acl options not supported\n");
398 break; 400 break;
399#endif 401#endif
402 case Opt_xip:
403#ifdef CONFIG_EXT2_FS_XIP
404 set_opt (sbi->s_mount_opt, XIP);
405#else
406 printk("EXT2 xip option not supported\n");
407#endif
408 break;
400 case Opt_ignore: 409 case Opt_ignore:
401 break; 410 break;
402 default: 411 default:
@@ -640,6 +649,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
640 ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? 649 ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ?
641 MS_POSIXACL : 0); 650 MS_POSIXACL : 0);
642 651
652 ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
653 EXT2_MOUNT_XIP if not */
654
643 if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV && 655 if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
644 (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) || 656 (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
645 EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) || 657 EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
@@ -668,6 +680,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
668 680
669 blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); 681 blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
670 682
683 if ((ext2_use_xip(sb)) && ((blocksize != PAGE_SIZE) ||
684 (sb->s_blocksize != blocksize))) {
685 if (!silent)
686 printk("XIP: Unsupported blocksize\n");
687 goto failed_mount;
688 }
689
671 /* If the blocksize doesn't match, re-read the thing.. */ 690 /* If the blocksize doesn't match, re-read the thing.. */
672 if (sb->s_blocksize != blocksize) { 691 if (sb->s_blocksize != blocksize) {
673 brelse(bh); 692 brelse(bh);
@@ -916,6 +935,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
916{ 935{
917 struct ext2_sb_info * sbi = EXT2_SB(sb); 936 struct ext2_sb_info * sbi = EXT2_SB(sb);
918 struct ext2_super_block * es; 937 struct ext2_super_block * es;
938 unsigned long old_mount_opt = sbi->s_mount_opt;
919 939
920 /* 940 /*
921 * Allow the "check" option to be passed as a remount option. 941 * Allow the "check" option to be passed as a remount option.
@@ -927,6 +947,11 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
927 ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); 947 ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
928 948
929 es = sbi->s_es; 949 es = sbi->s_es;
950 if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
951 (old_mount_opt & EXT2_MOUNT_XIP)) &&
952 invalidate_inodes(sb))
953 ext2_warning(sb, __FUNCTION__, "busy inodes while remounting "\
954 "xip remain in cache (no functional problem)");
930 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) 955 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
931 return 0; 956 return 0;
932 if (*flags & MS_RDONLY) { 957 if (*flags & MS_RDONLY) {
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c
new file mode 100644
index 0000000000..d44431d1a3
--- /dev/null
+++ b/fs/ext2/xip.c
@@ -0,0 +1,80 @@
1/*
2 * linux/fs/ext2/xip.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 * Author: Carsten Otte (cotte@de.ibm.com)
6 */
7
8#include <linux/mm.h>
9#include <linux/fs.h>
10#include <linux/genhd.h>
11#include <linux/buffer_head.h>
12#include <linux/ext2_fs_sb.h>
13#include <linux/ext2_fs.h>
14#include "ext2.h"
15#include "xip.h"
16
17static inline int
18__inode_direct_access(struct inode *inode, sector_t sector, unsigned long *data) {
19 BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access);
20 return inode->i_sb->s_bdev->bd_disk->fops
21 ->direct_access(inode->i_sb->s_bdev,sector,data);
22}
23
24int
25ext2_clear_xip_target(struct inode *inode, int block) {
26 sector_t sector = block*(PAGE_SIZE/512);
27 unsigned long data;
28 int rc;
29
30 rc = __inode_direct_access(inode, sector, &data);
31 if (rc)
32 return rc;
33 clear_page((void*)data);
34 return 0;
35}
36
37void ext2_xip_verify_sb(struct super_block *sb)
38{
39 struct ext2_sb_info *sbi = EXT2_SB(sb);
40
41 if ((sbi->s_mount_opt & EXT2_MOUNT_XIP)) {
42 if ((sb->s_bdev == NULL) ||
43 sb->s_bdev->bd_disk == NULL ||
44 sb->s_bdev->bd_disk->fops == NULL ||
45 sb->s_bdev->bd_disk->fops->direct_access == NULL) {
46 sbi->s_mount_opt &= (~EXT2_MOUNT_XIP);
47 ext2_warning(sb, __FUNCTION__,
48 "ignoring xip option - not supported by bdev");
49 }
50 }
51}
52
53struct page*
54ext2_get_xip_page(struct address_space *mapping, sector_t blockno,
55 int create)
56{
57 int rc;
58 unsigned long data;
59 struct buffer_head tmp;
60
61 tmp.b_state = 0;
62 tmp.b_blocknr = 0;
63 rc = ext2_get_block(mapping->host, blockno/(PAGE_SIZE/512) , &tmp,
64 create);
65 if (rc)
66 return ERR_PTR(rc);
67 if (tmp.b_blocknr == 0) {
68 /* SPARSE block */
69 BUG_ON(create);
70 return ERR_PTR(-ENODATA);
71 }
72
73 rc = __inode_direct_access
74 (mapping->host,tmp.b_blocknr*(PAGE_SIZE/512) ,&data);
75 if (rc)
76 return ERR_PTR(rc);
77
78 SetPageUptodate(virt_to_page(data));
79 return virt_to_page(data);
80}
diff --git a/fs/ext2/xip.h b/fs/ext2/xip.h
new file mode 100644
index 0000000000..aa85331d6c
--- /dev/null
+++ b/fs/ext2/xip.h
@@ -0,0 +1,25 @@
1/*
2 * linux/fs/ext2/xip.h
3 *
4 * Copyright (C) 2005 IBM Corporation
5 * Author: Carsten Otte (cotte@de.ibm.com)
6 */
7
8#ifdef CONFIG_EXT2_FS_XIP
9extern void ext2_xip_verify_sb (struct super_block *);
10extern int ext2_clear_xip_target (struct inode *, int);
11
12static inline int ext2_use_xip (struct super_block *sb)
13{
14 struct ext2_sb_info *sbi = EXT2_SB(sb);
15 return (sbi->s_mount_opt & EXT2_MOUNT_XIP);
16}
17struct page* ext2_get_xip_page (struct address_space *, sector_t, int);
18#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page)
19#else
20#define mapping_is_xip(map) 0
21#define ext2_xip_verify_sb(sb) do { } while (0)
22#define ext2_use_xip(sb) 0
23#define ext2_clear_xip_target(inode, chain) 0
24#define ext2_get_xip_page NULL
25#endif
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 133f5aa581..3ac38266fc 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -393,7 +393,8 @@ ext3_acl_chmod(struct inode *inode)
393 int retries = 0; 393 int retries = 0;
394 394
395 retry: 395 retry:
396 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); 396 handle = ext3_journal_start(inode,
397 EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
397 if (IS_ERR(handle)) { 398 if (IS_ERR(handle)) {
398 error = PTR_ERR(handle); 399 error = PTR_ERR(handle);
399 ext3_std_error(inode->i_sb, error); 400 ext3_std_error(inode->i_sb, error);
@@ -503,7 +504,7 @@ ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
503 acl = NULL; 504 acl = NULL;
504 505
505retry: 506retry:
506 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); 507 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
507 if (IS_ERR(handle)) 508 if (IS_ERR(handle))
508 return PTR_ERR(handle); 509 return PTR_ERR(handle);
509 error = ext3_set_acl(handle, inode, type, acl); 510 error = ext3_set_acl(handle, inode, type, acl);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 0d5fa73b18..0b2db4f618 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -128,7 +128,7 @@ static unsigned long blocks_for_truncate(struct inode *inode)
128 if (needed > EXT3_MAX_TRANS_DATA) 128 if (needed > EXT3_MAX_TRANS_DATA)
129 needed = EXT3_MAX_TRANS_DATA; 129 needed = EXT3_MAX_TRANS_DATA;
130 130
131 return EXT3_DATA_TRANS_BLOCKS + needed; 131 return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
132} 132}
133 133
134/* 134/*
@@ -2763,7 +2763,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
2763 2763
2764 /* (user+group)*(old+new) structure, inode write (sb, 2764 /* (user+group)*(old+new) structure, inode write (sb,
2765 * inode block, ? - but truncate inode update has it) */ 2765 * inode block, ? - but truncate inode update has it) */
2766 handle = ext3_journal_start(inode, 4*EXT3_QUOTA_INIT_BLOCKS+3); 2766 handle = ext3_journal_start(inode, 2*(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+
2767 EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
2767 if (IS_ERR(handle)) { 2768 if (IS_ERR(handle)) {
2768 error = PTR_ERR(handle); 2769 error = PTR_ERR(handle);
2769 goto err_out; 2770 goto err_out;
@@ -2861,7 +2862,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode)
2861#ifdef CONFIG_QUOTA 2862#ifdef CONFIG_QUOTA
2862 /* We know that structure was already allocated during DQUOT_INIT so 2863 /* We know that structure was already allocated during DQUOT_INIT so
2863 * we will be updating only the data blocks + inodes */ 2864 * we will be updating only the data blocks + inodes */
2864 ret += 2*EXT3_QUOTA_TRANS_BLOCKS; 2865 ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb);
2865#endif 2866#endif
2866 2867
2867 return ret; 2868 return ret;
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 60e44e6dd7..50378d8ff8 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1645,9 +1645,9 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
1645 int err, retries = 0; 1645 int err, retries = 0;
1646 1646
1647retry: 1647retry:
1648 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 1648 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
1649 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + 1649 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
1650 2*EXT3_QUOTA_INIT_BLOCKS); 1650 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
1651 if (IS_ERR(handle)) 1651 if (IS_ERR(handle))
1652 return PTR_ERR(handle); 1652 return PTR_ERR(handle);
1653 1653
@@ -1679,9 +1679,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
1679 return -EINVAL; 1679 return -EINVAL;
1680 1680
1681retry: 1681retry:
1682 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 1682 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
1683 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + 1683 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
1684 2*EXT3_QUOTA_INIT_BLOCKS); 1684 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
1685 if (IS_ERR(handle)) 1685 if (IS_ERR(handle))
1686 return PTR_ERR(handle); 1686 return PTR_ERR(handle);
1687 1687
@@ -1715,9 +1715,9 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
1715 return -EMLINK; 1715 return -EMLINK;
1716 1716
1717retry: 1717retry:
1718 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 1718 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
1719 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + 1719 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
1720 2*EXT3_QUOTA_INIT_BLOCKS); 1720 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
1721 if (IS_ERR(handle)) 1721 if (IS_ERR(handle))
1722 return PTR_ERR(handle); 1722 return PTR_ERR(handle);
1723 1723
@@ -2006,7 +2006,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
2006 /* Initialize quotas before so that eventual writes go in 2006 /* Initialize quotas before so that eventual writes go in
2007 * separate transaction */ 2007 * separate transaction */
2008 DQUOT_INIT(dentry->d_inode); 2008 DQUOT_INIT(dentry->d_inode);
2009 handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); 2009 handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
2010 if (IS_ERR(handle)) 2010 if (IS_ERR(handle))
2011 return PTR_ERR(handle); 2011 return PTR_ERR(handle);
2012 2012
@@ -2065,7 +2065,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
2065 /* Initialize quotas before so that eventual writes go 2065 /* Initialize quotas before so that eventual writes go
2066 * in separate transaction */ 2066 * in separate transaction */
2067 DQUOT_INIT(dentry->d_inode); 2067 DQUOT_INIT(dentry->d_inode);
2068 handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); 2068 handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
2069 if (IS_ERR(handle)) 2069 if (IS_ERR(handle))
2070 return PTR_ERR(handle); 2070 return PTR_ERR(handle);
2071 2071
@@ -2120,9 +2120,9 @@ static int ext3_symlink (struct inode * dir,
2120 return -ENAMETOOLONG; 2120 return -ENAMETOOLONG;
2121 2121
2122retry: 2122retry:
2123 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 2123 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
2124 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + 2124 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
2125 2*EXT3_QUOTA_INIT_BLOCKS); 2125 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
2126 if (IS_ERR(handle)) 2126 if (IS_ERR(handle))
2127 return PTR_ERR(handle); 2127 return PTR_ERR(handle);
2128 2128
@@ -2174,7 +2174,7 @@ static int ext3_link (struct dentry * old_dentry,
2174 return -EMLINK; 2174 return -EMLINK;
2175 2175
2176retry: 2176retry:
2177 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 2177 handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
2178 EXT3_INDEX_EXTRA_TRANS_BLOCKS); 2178 EXT3_INDEX_EXTRA_TRANS_BLOCKS);
2179 if (IS_ERR(handle)) 2179 if (IS_ERR(handle))
2180 return PTR_ERR(handle); 2180 return PTR_ERR(handle);
@@ -2216,7 +2216,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
2216 * in separate transaction */ 2216 * in separate transaction */
2217 if (new_dentry->d_inode) 2217 if (new_dentry->d_inode)
2218 DQUOT_INIT(new_dentry->d_inode); 2218 DQUOT_INIT(new_dentry->d_inode);
2219 handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2219 handle = ext3_journal_start(old_dir, 2 *
2220 EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
2220 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); 2221 EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
2221 if (IS_ERR(handle)) 2222 if (IS_ERR(handle))
2222 return PTR_ERR(handle); 2223 return PTR_ERR(handle);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 9630fbfdc2..b4b3e8a391 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -589,7 +589,7 @@ enum {
589 Opt_commit, Opt_journal_update, Opt_journal_inum, 589 Opt_commit, Opt_journal_update, Opt_journal_inum,
590 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, 590 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
591 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, 591 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
592 Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, 592 Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
593 Opt_ignore, Opt_barrier, Opt_err, Opt_resize, 593 Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
594}; 594};
595 595
@@ -634,10 +634,10 @@ static match_table_t tokens = {
634 {Opt_grpjquota, "grpjquota=%s"}, 634 {Opt_grpjquota, "grpjquota=%s"},
635 {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, 635 {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
636 {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, 636 {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
637 {Opt_ignore, "grpquota"}, 637 {Opt_quota, "grpquota"},
638 {Opt_ignore, "noquota"}, 638 {Opt_noquota, "noquota"},
639 {Opt_ignore, "quota"}, 639 {Opt_quota, "quota"},
640 {Opt_ignore, "usrquota"}, 640 {Opt_quota, "usrquota"},
641 {Opt_barrier, "barrier=%u"}, 641 {Opt_barrier, "barrier=%u"},
642 {Opt_err, NULL}, 642 {Opt_err, NULL},
643 {Opt_resize, "resize"}, 643 {Opt_resize, "resize"},
@@ -876,6 +876,7 @@ set_qf_name:
876 sbi->s_qf_names[qtype] = NULL; 876 sbi->s_qf_names[qtype] = NULL;
877 return 0; 877 return 0;
878 } 878 }
879 set_opt(sbi->s_mount_opt, QUOTA);
879 break; 880 break;
880 case Opt_offusrjquota: 881 case Opt_offusrjquota:
881 qtype = USRQUOTA; 882 qtype = USRQUOTA;
@@ -898,6 +899,17 @@ clear_qf_name:
898 case Opt_jqfmt_vfsv0: 899 case Opt_jqfmt_vfsv0:
899 sbi->s_jquota_fmt = QFMT_VFS_V0; 900 sbi->s_jquota_fmt = QFMT_VFS_V0;
900 break; 901 break;
902 case Opt_quota:
903 set_opt(sbi->s_mount_opt, QUOTA);
904 break;
905 case Opt_noquota:
906 if (sb_any_quota_enabled(sb)) {
907 printk(KERN_ERR "EXT3-fs: Cannot change quota "
908 "options when quota turned on.\n");
909 return 0;
910 }
911 clear_opt(sbi->s_mount_opt, QUOTA);
912 break;
901#else 913#else
902 case Opt_usrjquota: 914 case Opt_usrjquota:
903 case Opt_grpjquota: 915 case Opt_grpjquota:
@@ -909,6 +921,9 @@ clear_qf_name:
909 "EXT3-fs: journalled quota options not " 921 "EXT3-fs: journalled quota options not "
910 "supported.\n"); 922 "supported.\n");
911 break; 923 break;
924 case Opt_quota:
925 case Opt_noquota:
926 break;
912#endif 927#endif
913 case Opt_abort: 928 case Opt_abort:
914 set_opt(sbi->s_mount_opt, ABORT); 929 set_opt(sbi->s_mount_opt, ABORT);
@@ -2238,7 +2253,7 @@ static int ext3_dquot_initialize(struct inode *inode, int type)
2238 int ret, err; 2253 int ret, err;
2239 2254
2240 /* We may create quota structure so we need to reserve enough blocks */ 2255 /* We may create quota structure so we need to reserve enough blocks */
2241 handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); 2256 handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
2242 if (IS_ERR(handle)) 2257 if (IS_ERR(handle))
2243 return PTR_ERR(handle); 2258 return PTR_ERR(handle);
2244 ret = dquot_initialize(inode, type); 2259 ret = dquot_initialize(inode, type);
@@ -2254,7 +2269,7 @@ static int ext3_dquot_drop(struct inode *inode)
2254 int ret, err; 2269 int ret, err;
2255 2270
2256 /* We may delete quota structure so we need to reserve enough blocks */ 2271 /* We may delete quota structure so we need to reserve enough blocks */
2257 handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); 2272 handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
2258 if (IS_ERR(handle)) 2273 if (IS_ERR(handle))
2259 return PTR_ERR(handle); 2274 return PTR_ERR(handle);
2260 ret = dquot_drop(inode); 2275 ret = dquot_drop(inode);
@@ -2272,7 +2287,7 @@ static int ext3_write_dquot(struct dquot *dquot)
2272 2287
2273 inode = dquot_to_inode(dquot); 2288 inode = dquot_to_inode(dquot);
2274 handle = ext3_journal_start(inode, 2289 handle = ext3_journal_start(inode,
2275 EXT3_QUOTA_TRANS_BLOCKS); 2290 EXT3_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
2276 if (IS_ERR(handle)) 2291 if (IS_ERR(handle))
2277 return PTR_ERR(handle); 2292 return PTR_ERR(handle);
2278 ret = dquot_commit(dquot); 2293 ret = dquot_commit(dquot);
@@ -2288,7 +2303,7 @@ static int ext3_acquire_dquot(struct dquot *dquot)
2288 handle_t *handle; 2303 handle_t *handle;
2289 2304
2290 handle = ext3_journal_start(dquot_to_inode(dquot), 2305 handle = ext3_journal_start(dquot_to_inode(dquot),
2291 EXT3_QUOTA_INIT_BLOCKS); 2306 EXT3_QUOTA_INIT_BLOCKS(dquot->dq_sb));
2292 if (IS_ERR(handle)) 2307 if (IS_ERR(handle))
2293 return PTR_ERR(handle); 2308 return PTR_ERR(handle);
2294 ret = dquot_acquire(dquot); 2309 ret = dquot_acquire(dquot);
@@ -2304,7 +2319,7 @@ static int ext3_release_dquot(struct dquot *dquot)
2304 handle_t *handle; 2319 handle_t *handle;
2305 2320
2306 handle = ext3_journal_start(dquot_to_inode(dquot), 2321 handle = ext3_journal_start(dquot_to_inode(dquot),
2307 EXT3_QUOTA_INIT_BLOCKS); 2322 EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
2308 if (IS_ERR(handle)) 2323 if (IS_ERR(handle))
2309 return PTR_ERR(handle); 2324 return PTR_ERR(handle);
2310 ret = dquot_release(dquot); 2325 ret = dquot_release(dquot);
@@ -2361,6 +2376,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
2361 int err; 2376 int err;
2362 struct nameidata nd; 2377 struct nameidata nd;
2363 2378
2379 if (!test_opt(sb, QUOTA))
2380 return -EINVAL;
2364 /* Not journalling quota? */ 2381 /* Not journalling quota? */
2365 if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] && 2382 if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
2366 !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) 2383 !EXT3_SB(sb)->s_qf_names[GRPQUOTA])
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 4cbc6d0212..3f9dfa643b 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -1044,7 +1044,7 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name,
1044 int error, retries = 0; 1044 int error, retries = 0;
1045 1045
1046retry: 1046retry:
1047 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS); 1047 handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
1048 if (IS_ERR(handle)) { 1048 if (IS_ERR(handle)) {
1049 error = PTR_ERR(handle); 1049 error = PTR_ERR(handle);
1050 } else { 1050 } else {
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index b82e470912..6e242556b9 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -191,7 +191,9 @@ lockd(struct svc_rqst *rqstp)
191 printk(KERN_DEBUG 191 printk(KERN_DEBUG
192 "lockd: new process, skipping host shutdown\n"); 192 "lockd: new process, skipping host shutdown\n");
193 wake_up(&lockd_exit); 193 wake_up(&lockd_exit);
194 194
195 flush_signals(current);
196
195 /* Exit the RPC thread */ 197 /* Exit the RPC thread */
196 svc_exit_thread(rqstp); 198 svc_exit_thread(rqstp);
197 199
diff --git a/fs/namespace.c b/fs/namespace.c
index 3b93e5d750..208c079e9f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -337,7 +337,7 @@ int may_umount(struct vfsmount *mnt)
337 337
338EXPORT_SYMBOL(may_umount); 338EXPORT_SYMBOL(may_umount);
339 339
340void umount_tree(struct vfsmount *mnt) 340static void umount_tree(struct vfsmount *mnt)
341{ 341{
342 struct vfsmount *p; 342 struct vfsmount *p;
343 LIST_HEAD(kill); 343 LIST_HEAD(kill);
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
index 9f043f44c9..ce341dc76d 100644
--- a/fs/nfsd/Makefile
+++ b/fs/nfsd/Makefile
@@ -10,5 +10,5 @@ nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
10nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o 10nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
11nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o 11nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
12nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \ 12nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
13 nfs4acl.o nfs4callback.o 13 nfs4acl.o nfs4callback.o nfs4recover.o
14nfsd-objs := $(nfsd-y) 14nfsd-objs := $(nfsd-y)
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 11ebf6c4aa..4a2105552a 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -125,7 +125,7 @@ static short ace2type(struct nfs4_ace *);
125static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); 125static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
126static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int); 126static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
127int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); 127int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
128int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *); 128static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
129 129
130struct nfs4_acl * 130struct nfs4_acl *
131nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, 131nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
@@ -775,7 +775,7 @@ out_err:
775 return pacl; 775 return pacl;
776} 776}
777 777
778int 778static int
779nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl) 779nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
780{ 780{
781 struct list_head *h, *n; 781 struct list_head *h, *n;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 634465e9cf..583c0710e4 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -54,7 +54,6 @@
54 54
55/* declarations */ 55/* declarations */
56static void nfs4_cb_null(struct rpc_task *task); 56static void nfs4_cb_null(struct rpc_task *task);
57extern spinlock_t recall_lock;
58 57
59/* Index of predefined Linux callback client operations */ 58/* Index of predefined Linux callback client operations */
60 59
@@ -329,12 +328,12 @@ out:
329 .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \ 328 .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \
330} 329}
331 330
332struct rpc_procinfo nfs4_cb_procedures[] = { 331static struct rpc_procinfo nfs4_cb_procedures[] = {
333 PROC(CB_NULL, NULL, enc_cb_null, dec_cb_null), 332 PROC(CB_NULL, NULL, enc_cb_null, dec_cb_null),
334 PROC(CB_RECALL, COMPOUND, enc_cb_recall, dec_cb_recall), 333 PROC(CB_RECALL, COMPOUND, enc_cb_recall, dec_cb_recall),
335}; 334};
336 335
337struct rpc_version nfs_cb_version4 = { 336static struct rpc_version nfs_cb_version4 = {
338 .number = 1, 337 .number = 1,
339 .nrprocs = sizeof(nfs4_cb_procedures)/sizeof(nfs4_cb_procedures[0]), 338 .nrprocs = sizeof(nfs4_cb_procedures)/sizeof(nfs4_cb_procedures[0]),
340 .procs = nfs4_cb_procedures 339 .procs = nfs4_cb_procedures
@@ -348,7 +347,7 @@ static struct rpc_version * nfs_cb_version[] = {
348/* 347/*
349 * Use the SETCLIENTID credential 348 * Use the SETCLIENTID credential
350 */ 349 */
351struct rpc_cred * 350static struct rpc_cred *
352nfsd4_lookupcred(struct nfs4_client *clp, int taskflags) 351nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
353{ 352{
354 struct auth_cred acred; 353 struct auth_cred acred;
@@ -387,9 +386,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
387 char hostname[32]; 386 char hostname[32];
388 int status; 387 int status;
389 388
390 dprintk("NFSD: probe_callback. cb_parsed %d cb_set %d\n", 389 if (atomic_read(&cb->cb_set))
391 cb->cb_parsed, atomic_read(&cb->cb_set));
392 if (!cb->cb_parsed || atomic_read(&cb->cb_set))
393 return; 390 return;
394 391
395 /* Initialize address */ 392 /* Initialize address */
@@ -427,7 +424,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
427 * XXX AUTH_UNIX only - need AUTH_GSS.... 424 * XXX AUTH_UNIX only - need AUTH_GSS....
428 */ 425 */
429 sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr)); 426 sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr));
430 clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX); 427 clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
431 if (IS_ERR(clnt)) { 428 if (IS_ERR(clnt)) {
432 dprintk("NFSD: couldn't create callback client\n"); 429 dprintk("NFSD: couldn't create callback client\n");
433 goto out_err; 430 goto out_err;
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 4ba540841c..5605a26efc 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -104,7 +104,7 @@ ent_update(struct ent *new, struct ent *itm)
104 ent_init(new, itm); 104 ent_init(new, itm);
105} 105}
106 106
107void 107static void
108ent_put(struct cache_head *ch, struct cache_detail *cd) 108ent_put(struct cache_head *ch, struct cache_detail *cd)
109{ 109{
110 if (cache_put(ch, cd)) { 110 if (cache_put(ch, cd)) {
@@ -186,7 +186,7 @@ warn_no_idmapd(struct cache_detail *detail)
186static int idtoname_parse(struct cache_detail *, char *, int); 186static int idtoname_parse(struct cache_detail *, char *, int);
187static struct ent *idtoname_lookup(struct ent *, int); 187static struct ent *idtoname_lookup(struct ent *, int);
188 188
189struct cache_detail idtoname_cache = { 189static struct cache_detail idtoname_cache = {
190 .hash_size = ENT_HASHMAX, 190 .hash_size = ENT_HASHMAX,
191 .hash_table = idtoname_table, 191 .hash_table = idtoname_table,
192 .name = "nfs4.idtoname", 192 .name = "nfs4.idtoname",
@@ -277,7 +277,7 @@ nametoid_hash(struct ent *ent)
277 return hash_str(ent->name, ENT_HASHBITS); 277 return hash_str(ent->name, ENT_HASHBITS);
278} 278}
279 279
280void 280static void
281nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, 281nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
282 int *blen) 282 int *blen)
283{ 283{
@@ -317,9 +317,9 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
317} 317}
318 318
319static struct ent *nametoid_lookup(struct ent *, int); 319static struct ent *nametoid_lookup(struct ent *, int);
320int nametoid_parse(struct cache_detail *, char *, int); 320static int nametoid_parse(struct cache_detail *, char *, int);
321 321
322struct cache_detail nametoid_cache = { 322static struct cache_detail nametoid_cache = {
323 .hash_size = ENT_HASHMAX, 323 .hash_size = ENT_HASHMAX,
324 .hash_table = nametoid_table, 324 .hash_table = nametoid_table,
325 .name = "nfs4.nametoid", 325 .name = "nfs4.nametoid",
@@ -330,7 +330,7 @@ struct cache_detail nametoid_cache = {
330 .warn_no_listener = warn_no_idmapd, 330 .warn_no_listener = warn_no_idmapd,
331}; 331};
332 332
333int 333static int
334nametoid_parse(struct cache_detail *cd, char *buf, int buflen) 334nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
335{ 335{
336 struct ent ent, *res; 336 struct ent ent, *res;
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e8158741e8..d71f14517b 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -45,6 +45,7 @@
45#include <linux/param.h> 45#include <linux/param.h>
46#include <linux/major.h> 46#include <linux/major.h>
47#include <linux/slab.h> 47#include <linux/slab.h>
48#include <linux/file.h>
48 49
49#include <linux/sunrpc/svc.h> 50#include <linux/sunrpc/svc.h>
50#include <linux/nfsd/nfsd.h> 51#include <linux/nfsd/nfsd.h>
@@ -198,6 +199,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
198 if (status) 199 if (status)
199 goto out; 200 goto out;
200 switch (open->op_claim_type) { 201 switch (open->op_claim_type) {
202 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
203 status = nfserr_inval;
204 if (open->op_create)
205 goto out;
206 /* fall through */
201 case NFS4_OPEN_CLAIM_NULL: 207 case NFS4_OPEN_CLAIM_NULL:
202 /* 208 /*
203 * (1) set CURRENT_FH to the file being opened, 209 * (1) set CURRENT_FH to the file being opened,
@@ -220,7 +226,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
220 if (status) 226 if (status)
221 goto out; 227 goto out;
222 break; 228 break;
223 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
224 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 229 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
225 printk("NFSD: unsupported OPEN claim type %d\n", 230 printk("NFSD: unsupported OPEN claim type %d\n",
226 open->op_claim_type); 231 open->op_claim_type);
@@ -473,26 +478,27 @@ static inline int
473nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) 478nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
474{ 479{
475 int status; 480 int status;
476 struct file *filp = NULL;
477 481
478 /* no need to check permission - this will be done in nfsd_read() */ 482 /* no need to check permission - this will be done in nfsd_read() */
479 483
484 read->rd_filp = NULL;
480 if (read->rd_offset >= OFFSET_MAX) 485 if (read->rd_offset >= OFFSET_MAX)
481 return nfserr_inval; 486 return nfserr_inval;
482 487
483 nfs4_lock_state(); 488 nfs4_lock_state();
484 /* check stateid */ 489 /* check stateid */
485 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 490 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
486 CHECK_FH | RD_STATE, &filp))) { 491 CHECK_FH | RD_STATE, &read->rd_filp))) {
487 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 492 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
488 goto out; 493 goto out;
489 } 494 }
495 if (read->rd_filp)
496 get_file(read->rd_filp);
490 status = nfs_ok; 497 status = nfs_ok;
491out: 498out:
492 nfs4_unlock_state(); 499 nfs4_unlock_state();
493 read->rd_rqstp = rqstp; 500 read->rd_rqstp = rqstp;
494 read->rd_fhp = current_fh; 501 read->rd_fhp = current_fh;
495 read->rd_filp = filp;
496 return status; 502 return status;
497} 503}
498 504
@@ -532,6 +538,8 @@ nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_rem
532{ 538{
533 int status; 539 int status;
534 540
541 if (nfs4_in_grace())
542 return nfserr_grace;
535 status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen); 543 status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
536 if (status == nfserr_symlink) 544 if (status == nfserr_symlink)
537 return nfserr_notdir; 545 return nfserr_notdir;
@@ -550,6 +558,9 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
550 558
551 if (!save_fh->fh_dentry) 559 if (!save_fh->fh_dentry)
552 return status; 560 return status;
561 if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
562 & NFSEXP_NOSUBTREECHECK))
563 return nfserr_grace;
553 status = nfsd_rename(rqstp, save_fh, rename->rn_sname, 564 status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
554 rename->rn_snamelen, current_fh, 565 rename->rn_snamelen, current_fh,
555 rename->rn_tname, rename->rn_tnamelen); 566 rename->rn_tname, rename->rn_tnamelen);
@@ -624,6 +635,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
624 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); 635 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
625 goto out; 636 goto out;
626 } 637 }
638 if (filp)
639 get_file(filp);
627 nfs4_unlock_state(); 640 nfs4_unlock_state();
628 641
629 write->wr_bytes_written = write->wr_buflen; 642 write->wr_bytes_written = write->wr_buflen;
@@ -635,6 +648,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
635 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset, 648 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset,
636 write->wr_vec, write->wr_vlen, write->wr_buflen, 649 write->wr_vec, write->wr_vlen, write->wr_buflen,
637 &write->wr_how_written); 650 &write->wr_how_written);
651 if (filp)
652 fput(filp);
638 653
639 if (status == nfserr_symlink) 654 if (status == nfserr_symlink)
640 status = nfserr_inval; 655 status = nfserr_inval;
@@ -923,6 +938,9 @@ encode_op:
923 nfs4_put_stateowner(replay_owner); 938 nfs4_put_stateowner(replay_owner);
924 replay_owner = NULL; 939 replay_owner = NULL;
925 } 940 }
941 /* XXX Ugh, we need to get rid of this kind of special case: */
942 if (op->opnum == OP_READ && op->u.read.rd_filp)
943 fput(op->u.read.rd_filp);
926 } 944 }
927 945
928out: 946out:
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
new file mode 100644
index 0000000000..095f1740f3
--- /dev/null
+++ b/fs/nfsd/nfs4recover.c
@@ -0,0 +1,431 @@
1/*
2* linux/fs/nfsd/nfs4recover.c
3*
4* Copyright (c) 2004 The Regents of the University of Michigan.
5* All rights reserved.
6*
7* Andy Adamson <andros@citi.umich.edu>
8*
9* Redistribution and use in source and binary forms, with or without
10* modification, are permitted provided that the following conditions
11* are met:
12*
13* 1. Redistributions of source code must retain the above copyright
14* notice, this list of conditions and the following disclaimer.
15* 2. Redistributions in binary form must reproduce the above copyright
16* notice, this list of conditions and the following disclaimer in the
17* documentation and/or other materials provided with the distribution.
18* 3. Neither the name of the University nor the names of its
19* contributors may be used to endorse or promote products derived
20* from this software without specific prior written permission.
21*
22* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*
34*/
35
36
37#include <linux/sunrpc/svc.h>
38#include <linux/nfsd/nfsd.h>
39#include <linux/nfs4.h>
40#include <linux/nfsd/state.h>
41#include <linux/nfsd/xdr4.h>
42#include <linux/param.h>
43#include <linux/file.h>
44#include <linux/namei.h>
45#include <asm/uaccess.h>
46#include <asm/scatterlist.h>
47#include <linux/crypto.h>
48
49
50#define NFSDDBG_FACILITY NFSDDBG_PROC
51
52/* Globals */
53static struct nameidata rec_dir;
54static int rec_dir_init = 0;
55
56static void
57nfs4_save_user(uid_t *saveuid, gid_t *savegid)
58{
59 *saveuid = current->fsuid;
60 *savegid = current->fsgid;
61 current->fsuid = 0;
62 current->fsgid = 0;
63}
64
65static void
66nfs4_reset_user(uid_t saveuid, gid_t savegid)
67{
68 current->fsuid = saveuid;
69 current->fsgid = savegid;
70}
71
72static void
73md5_to_hex(char *out, char *md5)
74{
75 int i;
76
77 for (i=0; i<16; i++) {
78 unsigned char c = md5[i];
79
80 *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
81 *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
82 }
83 *out = '\0';
84}
85
86int
87nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
88{
89 struct xdr_netobj cksum;
90 struct crypto_tfm *tfm;
91 struct scatterlist sg[1];
92 int status = nfserr_resource;
93
94 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
95 clname->len, clname->data);
96 tfm = crypto_alloc_tfm("md5", 0);
97 if (tfm == NULL)
98 goto out;
99 cksum.len = crypto_tfm_alg_digestsize(tfm);
100 cksum.data = kmalloc(cksum.len, GFP_KERNEL);
101 if (cksum.data == NULL)
102 goto out;
103 crypto_digest_init(tfm);
104
105 sg[0].page = virt_to_page(clname->data);
106 sg[0].offset = offset_in_page(clname->data);
107 sg[0].length = clname->len;
108
109 crypto_digest_update(tfm, sg, 1);
110 crypto_digest_final(tfm, cksum.data);
111
112 md5_to_hex(dname, cksum.data);
113
114 kfree(cksum.data);
115 status = nfs_ok;
116out:
117 if (tfm)
118 crypto_free_tfm(tfm);
119 return status;
120}
121
122static int
123nfsd4_rec_fsync(struct dentry *dentry)
124{
125 struct file *filp;
126 int status = nfs_ok;
127
128 dprintk("NFSD: nfs4_fsync_rec_dir\n");
129 filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR);
130 if (IS_ERR(filp)) {
131 status = PTR_ERR(filp);
132 goto out;
133 }
134 if (filp->f_op && filp->f_op->fsync)
135 status = filp->f_op->fsync(filp, filp->f_dentry, 0);
136 fput(filp);
137out:
138 if (status)
139 printk("nfsd4: unable to sync recovery directory\n");
140 return status;
141}
142
143int
144nfsd4_create_clid_dir(struct nfs4_client *clp)
145{
146 char *dname = clp->cl_recdir;
147 struct dentry *dentry;
148 uid_t uid;
149 gid_t gid;
150 int status;
151
152 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
153
154 if (!rec_dir_init || clp->cl_firststate)
155 return 0;
156
157 nfs4_save_user(&uid, &gid);
158
159 /* lock the parent */
160 down(&rec_dir.dentry->d_inode->i_sem);
161
162 dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
163 if (IS_ERR(dentry)) {
164 status = PTR_ERR(dentry);
165 goto out_unlock;
166 }
167 status = -EEXIST;
168 if (dentry->d_inode) {
169 dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
170 goto out_put;
171 }
172 status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
173out_put:
174 dput(dentry);
175out_unlock:
176 up(&rec_dir.dentry->d_inode->i_sem);
177 if (status == 0) {
178 clp->cl_firststate = 1;
179 status = nfsd4_rec_fsync(rec_dir.dentry);
180 }
181 nfs4_reset_user(uid, gid);
182 dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
183 return status;
184}
185
186typedef int (recdir_func)(struct dentry *, struct dentry *);
187
188struct dentry_list {
189 struct dentry *dentry;
190 struct list_head list;
191};
192
193struct dentry_list_arg {
194 struct list_head dentries;
195 struct dentry *parent;
196};
197
198static int
199nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
200 loff_t offset, ino_t ino, unsigned int d_type)
201{
202 struct dentry_list_arg *dla = arg;
203 struct list_head *dentries = &dla->dentries;
204 struct dentry *parent = dla->parent;
205 struct dentry *dentry;
206 struct dentry_list *child;
207
208 if (name && isdotent(name, namlen))
209 return nfs_ok;
210 dentry = lookup_one_len(name, parent, namlen);
211 if (IS_ERR(dentry))
212 return PTR_ERR(dentry);
213 child = kmalloc(sizeof(*child), GFP_KERNEL);
214 if (child == NULL)
215 return -ENOMEM;
216 child->dentry = dentry;
217 list_add(&child->list, dentries);
218 return 0;
219}
220
221static int
222nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
223{
224 struct file *filp;
225 struct dentry_list_arg dla = {
226 .parent = dir,
227 };
228 struct list_head *dentries = &dla.dentries;
229 struct dentry_list *child;
230 uid_t uid;
231 gid_t gid;
232 int status;
233
234 if (!rec_dir_init)
235 return 0;
236
237 nfs4_save_user(&uid, &gid);
238
239 filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
240 O_RDWR);
241 status = PTR_ERR(filp);
242 if (IS_ERR(filp))
243 goto out;
244 INIT_LIST_HEAD(dentries);
245 status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
246 fput(filp);
247 while (!list_empty(dentries)) {
248 child = list_entry(dentries->next, struct dentry_list, list);
249 status = f(dir, child->dentry);
250 if (status)
251 goto out;
252 list_del(&child->list);
253 dput(child->dentry);
254 kfree(child);
255 }
256out:
257 while (!list_empty(dentries)) {
258 child = list_entry(dentries->next, struct dentry_list, list);
259 list_del(&child->list);
260 dput(child->dentry);
261 kfree(child);
262 }
263 nfs4_reset_user(uid, gid);
264 return status;
265}
266
267static int
268nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
269{
270 int status;
271
272 if (!S_ISREG(dir->d_inode->i_mode)) {
273 printk("nfsd4: non-file found in client recovery directory\n");
274 return -EINVAL;
275 }
276 down(&dir->d_inode->i_sem);
277 status = vfs_unlink(dir->d_inode, dentry);
278 up(&dir->d_inode->i_sem);
279 return status;
280}
281
282static int
283nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
284{
285 int status;
286
287 /* For now this directory should already be empty, but we empty it of
288 * any regular files anyway, just in case the directory was created by
289 * a kernel from the future.... */
290 nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
291 down(&dir->d_inode->i_sem);
292 status = vfs_rmdir(dir->d_inode, dentry);
293 up(&dir->d_inode->i_sem);
294 return status;
295}
296
297static int
298nfsd4_unlink_clid_dir(char *name, int namlen)
299{
300 struct dentry *dentry;
301 int status;
302
303 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
304
305 dentry = lookup_one_len(name, rec_dir.dentry, namlen);
306 if (IS_ERR(dentry)) {
307 status = PTR_ERR(dentry);
308 return status;
309 }
310 status = -ENOENT;
311 if (!dentry->d_inode)
312 goto out;
313
314 status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
315out:
316 dput(dentry);
317 return status;
318}
319
320void
321nfsd4_remove_clid_dir(struct nfs4_client *clp)
322{
323 uid_t uid;
324 gid_t gid;
325 int status;
326
327 if (!rec_dir_init || !clp->cl_firststate)
328 return;
329
330 nfs4_save_user(&uid, &gid);
331 status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
332 nfs4_reset_user(uid, gid);
333 if (status == 0)
334 status = nfsd4_rec_fsync(rec_dir.dentry);
335 if (status)
336 printk("NFSD: Failed to remove expired client state directory"
337 " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
338 return;
339}
340
341static int
342purge_old(struct dentry *parent, struct dentry *child)
343{
344 int status;
345
346 if (nfs4_has_reclaimed_state(child->d_name.name))
347 return nfs_ok;
348
349 status = nfsd4_clear_clid_dir(parent, child);
350 if (status)
351 printk("failed to remove client recovery directory %s\n",
352 child->d_name.name);
353 /* Keep trying, success or failure: */
354 return nfs_ok;
355}
356
357void
358nfsd4_recdir_purge_old(void) {
359 int status;
360
361 if (!rec_dir_init)
362 return;
363 status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
364 if (status == 0)
365 status = nfsd4_rec_fsync(rec_dir.dentry);
366 if (status)
367 printk("nfsd4: failed to purge old clients from recovery"
368 " directory %s\n", rec_dir.dentry->d_name.name);
369 return;
370}
371
372static int
373load_recdir(struct dentry *parent, struct dentry *child)
374{
375 if (child->d_name.len != HEXDIR_LEN - 1) {
376 printk("nfsd4: illegal name %s in recovery directory\n",
377 child->d_name.name);
378 /* Keep trying; maybe the others are OK: */
379 return nfs_ok;
380 }
381 nfs4_client_to_reclaim(child->d_name.name);
382 return nfs_ok;
383}
384
385int
386nfsd4_recdir_load(void) {
387 int status;
388
389 status = nfsd4_list_rec_dir(rec_dir.dentry, load_recdir);
390 if (status)
391 printk("nfsd4: failed loading clients from recovery"
392 " directory %s\n", rec_dir.dentry->d_name.name);
393 return status;
394}
395
396/*
397 * Hold reference to the recovery directory.
398 */
399
400void
401nfsd4_init_recdir(char *rec_dirname)
402{
403 uid_t uid = 0;
404 gid_t gid = 0;
405 int status;
406
407 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
408 rec_dirname);
409
410 BUG_ON(rec_dir_init);
411
412 nfs4_save_user(&uid, &gid);
413
414 status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
415 if (status == -ENOENT)
416 printk("NFSD: recovery directory %s doesn't exist\n",
417 rec_dirname);
418
419 if (!status)
420 rec_dir_init = 1;
421 nfs4_reset_user(uid, gid);
422}
423
424void
425nfsd4_shutdown_recdir(void)
426{
427 if (!rec_dir_init)
428 return;
429 rec_dir_init = 0;
430 path_release(&rec_dir);
431}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 75e8b13758..89e36526d7 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -48,39 +48,32 @@
48#include <linux/nfs4.h> 48#include <linux/nfs4.h>
49#include <linux/nfsd/state.h> 49#include <linux/nfsd/state.h>
50#include <linux/nfsd/xdr4.h> 50#include <linux/nfsd/xdr4.h>
51#include <linux/namei.h>
51 52
52#define NFSDDBG_FACILITY NFSDDBG_PROC 53#define NFSDDBG_FACILITY NFSDDBG_PROC
53 54
54/* Globals */ 55/* Globals */
55static time_t lease_time = 90; /* default lease time */ 56static time_t lease_time = 90; /* default lease time */
56static time_t old_lease_time = 90; /* past incarnation lease time */ 57static time_t user_lease_time = 90;
57static u32 nfs4_reclaim_init = 0; 58static time_t boot_time;
58time_t boot_time; 59static int in_grace = 1;
59static time_t grace_end = 0;
60static u32 current_clientid = 1; 60static u32 current_clientid = 1;
61static u32 current_ownerid = 1; 61static u32 current_ownerid = 1;
62static u32 current_fileid = 1; 62static u32 current_fileid = 1;
63static u32 current_delegid = 1; 63static u32 current_delegid = 1;
64static u32 nfs4_init; 64static u32 nfs4_init;
65stateid_t zerostateid; /* bits all 0 */ 65static stateid_t zerostateid; /* bits all 0 */
66stateid_t onestateid; /* bits all 1 */ 66static stateid_t onestateid; /* bits all 1 */
67 67
68/* debug counters */ 68#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
69u32 list_add_perfile = 0; 69#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
70u32 list_del_perfile = 0;
71u32 add_perclient = 0;
72u32 del_perclient = 0;
73u32 alloc_file = 0;
74u32 free_file = 0;
75u32 vfsopen = 0;
76u32 vfsclose = 0;
77u32 alloc_delegation= 0;
78u32 free_delegation= 0;
79 70
80/* forward declarations */ 71/* forward declarations */
81struct nfs4_stateid * find_stateid(stateid_t *stid, int flags); 72static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
82static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid); 73static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
83static void release_stateid_lockowners(struct nfs4_stateid *open_stp); 74static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
75static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
76static void nfs4_set_recdir(char *recdir);
84 77
85/* Locking: 78/* Locking:
86 * 79 *
@@ -90,6 +83,11 @@ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
90 */ 83 */
91static DECLARE_MUTEX(client_sema); 84static DECLARE_MUTEX(client_sema);
92 85
86static kmem_cache_t *stateowner_slab = NULL;
87static kmem_cache_t *file_slab = NULL;
88static kmem_cache_t *stateid_slab = NULL;
89static kmem_cache_t *deleg_slab = NULL;
90
93void 91void
94nfs4_lock_state(void) 92nfs4_lock_state(void)
95{ 93{
@@ -118,16 +116,36 @@ opaque_hashval(const void *ptr, int nbytes)
118/* forward declarations */ 116/* forward declarations */
119static void release_stateowner(struct nfs4_stateowner *sop); 117static void release_stateowner(struct nfs4_stateowner *sop);
120static void release_stateid(struct nfs4_stateid *stp, int flags); 118static void release_stateid(struct nfs4_stateid *stp, int flags);
121static void release_file(struct nfs4_file *fp);
122 119
123/* 120/*
124 * Delegation state 121 * Delegation state
125 */ 122 */
126 123
127/* recall_lock protects the del_recall_lru */ 124/* recall_lock protects the del_recall_lru */
128spinlock_t recall_lock; 125static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
129static struct list_head del_recall_lru; 126static struct list_head del_recall_lru;
130 127
128static void
129free_nfs4_file(struct kref *kref)
130{
131 struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
132 list_del(&fp->fi_hash);
133 iput(fp->fi_inode);
134 kmem_cache_free(file_slab, fp);
135}
136
137static inline void
138put_nfs4_file(struct nfs4_file *fi)
139{
140 kref_put(&fi->fi_ref, free_nfs4_file);
141}
142
143static inline void
144get_nfs4_file(struct nfs4_file *fi)
145{
146 kref_get(&fi->fi_ref);
147}
148
131static struct nfs4_delegation * 149static struct nfs4_delegation *
132alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) 150alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
133{ 151{
@@ -136,13 +154,14 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
136 struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback; 154 struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
137 155
138 dprintk("NFSD alloc_init_deleg\n"); 156 dprintk("NFSD alloc_init_deleg\n");
139 if ((dp = kmalloc(sizeof(struct nfs4_delegation), 157 dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
140 GFP_KERNEL)) == NULL) 158 if (dp == NULL)
141 return dp; 159 return dp;
142 INIT_LIST_HEAD(&dp->dl_del_perfile); 160 INIT_LIST_HEAD(&dp->dl_perfile);
143 INIT_LIST_HEAD(&dp->dl_del_perclnt); 161 INIT_LIST_HEAD(&dp->dl_perclnt);
144 INIT_LIST_HEAD(&dp->dl_recall_lru); 162 INIT_LIST_HEAD(&dp->dl_recall_lru);
145 dp->dl_client = clp; 163 dp->dl_client = clp;
164 get_nfs4_file(fp);
146 dp->dl_file = fp; 165 dp->dl_file = fp;
147 dp->dl_flock = NULL; 166 dp->dl_flock = NULL;
148 get_file(stp->st_vfs_file); 167 get_file(stp->st_vfs_file);
@@ -160,9 +179,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
160 current_fh->fh_handle.fh_size); 179 current_fh->fh_handle.fh_size);
161 dp->dl_time = 0; 180 dp->dl_time = 0;
162 atomic_set(&dp->dl_count, 1); 181 atomic_set(&dp->dl_count, 1);
163 list_add(&dp->dl_del_perfile, &fp->fi_del_perfile); 182 list_add(&dp->dl_perfile, &fp->fi_delegations);
164 list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt); 183 list_add(&dp->dl_perclnt, &clp->cl_delegations);
165 alloc_delegation++;
166 return dp; 184 return dp;
167} 185}
168 186
@@ -171,8 +189,8 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
171{ 189{
172 if (atomic_dec_and_test(&dp->dl_count)) { 190 if (atomic_dec_and_test(&dp->dl_count)) {
173 dprintk("NFSD: freeing dp %p\n",dp); 191 dprintk("NFSD: freeing dp %p\n",dp);
174 kfree(dp); 192 put_nfs4_file(dp->dl_file);
175 free_delegation++; 193 kmem_cache_free(deleg_slab, dp);
176 } 194 }
177} 195}
178 196
@@ -193,15 +211,14 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
193 if (dp->dl_flock) 211 if (dp->dl_flock)
194 setlease(filp, F_UNLCK, &dp->dl_flock); 212 setlease(filp, F_UNLCK, &dp->dl_flock);
195 nfsd_close(filp); 213 nfsd_close(filp);
196 vfsclose++;
197} 214}
198 215
199/* Called under the state lock. */ 216/* Called under the state lock. */
200static void 217static void
201unhash_delegation(struct nfs4_delegation *dp) 218unhash_delegation(struct nfs4_delegation *dp)
202{ 219{
203 list_del_init(&dp->dl_del_perfile); 220 list_del_init(&dp->dl_perfile);
204 list_del_init(&dp->dl_del_perclnt); 221 list_del_init(&dp->dl_perclnt);
205 spin_lock(&recall_lock); 222 spin_lock(&recall_lock);
206 list_del_init(&dp->dl_recall_lru); 223 list_del_init(&dp->dl_recall_lru);
207 spin_unlock(&recall_lock); 224 spin_unlock(&recall_lock);
@@ -220,8 +237,8 @@ unhash_delegation(struct nfs4_delegation *dp)
220 237
221#define clientid_hashval(id) \ 238#define clientid_hashval(id) \
222 ((id) & CLIENT_HASH_MASK) 239 ((id) & CLIENT_HASH_MASK)
223#define clientstr_hashval(name, namelen) \ 240#define clientstr_hashval(name) \
224 (opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK) 241 (opaque_hashval((name), 8) & CLIENT_HASH_MASK)
225/* 242/*
226 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot 243 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
227 * used in reboot/reset lease grace period processing 244 * used in reboot/reset lease grace period processing
@@ -331,11 +348,11 @@ expire_client(struct nfs4_client *clp)
331 348
332 INIT_LIST_HEAD(&reaplist); 349 INIT_LIST_HEAD(&reaplist);
333 spin_lock(&recall_lock); 350 spin_lock(&recall_lock);
334 while (!list_empty(&clp->cl_del_perclnt)) { 351 while (!list_empty(&clp->cl_delegations)) {
335 dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt); 352 dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
336 dprintk("NFSD: expire client. dp %p, fp %p\n", dp, 353 dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
337 dp->dl_flock); 354 dp->dl_flock);
338 list_del_init(&dp->dl_del_perclnt); 355 list_del_init(&dp->dl_perclnt);
339 list_move(&dp->dl_recall_lru, &reaplist); 356 list_move(&dp->dl_recall_lru, &reaplist);
340 } 357 }
341 spin_unlock(&recall_lock); 358 spin_unlock(&recall_lock);
@@ -347,26 +364,26 @@ expire_client(struct nfs4_client *clp)
347 list_del(&clp->cl_idhash); 364 list_del(&clp->cl_idhash);
348 list_del(&clp->cl_strhash); 365 list_del(&clp->cl_strhash);
349 list_del(&clp->cl_lru); 366 list_del(&clp->cl_lru);
350 while (!list_empty(&clp->cl_perclient)) { 367 while (!list_empty(&clp->cl_openowners)) {
351 sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient); 368 sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
352 release_stateowner(sop); 369 release_stateowner(sop);
353 } 370 }
354 put_nfs4_client(clp); 371 put_nfs4_client(clp);
355} 372}
356 373
357static struct nfs4_client * 374static struct nfs4_client *
358create_client(struct xdr_netobj name) { 375create_client(struct xdr_netobj name, char *recdir) {
359 struct nfs4_client *clp; 376 struct nfs4_client *clp;
360 377
361 if (!(clp = alloc_client(name))) 378 if (!(clp = alloc_client(name)))
362 goto out; 379 goto out;
380 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
363 atomic_set(&clp->cl_count, 1); 381 atomic_set(&clp->cl_count, 1);
364 atomic_set(&clp->cl_callback.cb_set, 0); 382 atomic_set(&clp->cl_callback.cb_set, 0);
365 clp->cl_callback.cb_parsed = 0;
366 INIT_LIST_HEAD(&clp->cl_idhash); 383 INIT_LIST_HEAD(&clp->cl_idhash);
367 INIT_LIST_HEAD(&clp->cl_strhash); 384 INIT_LIST_HEAD(&clp->cl_strhash);
368 INIT_LIST_HEAD(&clp->cl_perclient); 385 INIT_LIST_HEAD(&clp->cl_openowners);
369 INIT_LIST_HEAD(&clp->cl_del_perclnt); 386 INIT_LIST_HEAD(&clp->cl_delegations);
370 INIT_LIST_HEAD(&clp->cl_lru); 387 INIT_LIST_HEAD(&clp->cl_lru);
371out: 388out:
372 return clp; 389 return clp;
@@ -392,11 +409,9 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) {
392 get_group_info(target->cr_group_info); 409 get_group_info(target->cr_group_info);
393} 410}
394 411
395static int 412static inline int
396cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) { 413same_name(const char *n1, const char *n2) {
397 if (!n1 || !n2) 414 return 0 == memcmp(n1, n2, HEXDIR_LEN);
398 return 0;
399 return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
400} 415}
401 416
402static int 417static int
@@ -446,7 +461,7 @@ check_name(struct xdr_netobj name) {
446 return 1; 461 return 1;
447} 462}
448 463
449void 464static void
450add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval) 465add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
451{ 466{
452 unsigned int idhashval; 467 unsigned int idhashval;
@@ -458,7 +473,7 @@ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
458 clp->cl_time = get_seconds(); 473 clp->cl_time = get_seconds();
459} 474}
460 475
461void 476static void
462move_to_confirmed(struct nfs4_client *clp) 477move_to_confirmed(struct nfs4_client *clp)
463{ 478{
464 unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id); 479 unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
@@ -468,8 +483,7 @@ move_to_confirmed(struct nfs4_client *clp)
468 list_del_init(&clp->cl_strhash); 483 list_del_init(&clp->cl_strhash);
469 list_del_init(&clp->cl_idhash); 484 list_del_init(&clp->cl_idhash);
470 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); 485 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
471 strhashval = clientstr_hashval(clp->cl_name.data, 486 strhashval = clientstr_hashval(clp->cl_recdir);
472 clp->cl_name.len);
473 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); 487 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
474 renew_client(clp); 488 renew_client(clp);
475} 489}
@@ -500,6 +514,30 @@ find_unconfirmed_client(clientid_t *clid)
500 return NULL; 514 return NULL;
501} 515}
502 516
517static struct nfs4_client *
518find_confirmed_client_by_str(const char *dname, unsigned int hashval)
519{
520 struct nfs4_client *clp;
521
522 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
523 if (same_name(clp->cl_recdir, dname))
524 return clp;
525 }
526 return NULL;
527}
528
529static struct nfs4_client *
530find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
531{
532 struct nfs4_client *clp;
533
534 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
535 if (same_name(clp->cl_recdir, dname))
536 return clp;
537 }
538 return NULL;
539}
540
503/* a helper function for parse_callback */ 541/* a helper function for parse_callback */
504static int 542static int
505parse_octet(unsigned int *lenp, char **addrp) 543parse_octet(unsigned int *lenp, char **addrp)
@@ -534,7 +572,7 @@ parse_octet(unsigned int *lenp, char **addrp)
534} 572}
535 573
536/* parse and set the setclientid ipv4 callback address */ 574/* parse and set the setclientid ipv4 callback address */
537int 575static int
538parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp) 576parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
539{ 577{
540 int temp = 0; 578 int temp = 0;
@@ -570,7 +608,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
570 return 1; 608 return 1;
571} 609}
572 610
573void 611static void
574gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) 612gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
575{ 613{
576 struct nfs4_callback *cb = &clp->cl_callback; 614 struct nfs4_callback *cb = &clp->cl_callback;
@@ -584,14 +622,12 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
584 goto out_err; 622 goto out_err;
585 cb->cb_prog = se->se_callback_prog; 623 cb->cb_prog = se->se_callback_prog;
586 cb->cb_ident = se->se_callback_ident; 624 cb->cb_ident = se->se_callback_ident;
587 cb->cb_parsed = 1;
588 return; 625 return;
589out_err: 626out_err:
590 printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) " 627 printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
591 "will not receive delegations\n", 628 "will not receive delegations\n",
592 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); 629 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
593 630
594 cb->cb_parsed = 0;
595 return; 631 return;
596} 632}
597 633
@@ -638,59 +674,43 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
638 }; 674 };
639 nfs4_verifier clverifier = setclid->se_verf; 675 nfs4_verifier clverifier = setclid->se_verf;
640 unsigned int strhashval; 676 unsigned int strhashval;
641 struct nfs4_client * conf, * unconf, * new, * clp; 677 struct nfs4_client *conf, *unconf, *new;
642 int status; 678 int status;
679 char dname[HEXDIR_LEN];
643 680
644 status = nfserr_inval; 681 status = nfserr_inval;
645 if (!check_name(clname)) 682 if (!check_name(clname))
646 goto out; 683 goto out;
647 684
685 status = nfs4_make_rec_clidname(dname, &clname);
686 if (status)
687 goto out;
688
648 /* 689 /*
649 * XXX The Duplicate Request Cache (DRC) has been checked (??) 690 * XXX The Duplicate Request Cache (DRC) has been checked (??)
650 * We get here on a DRC miss. 691 * We get here on a DRC miss.
651 */ 692 */
652 693
653 strhashval = clientstr_hashval(clname.data, clname.len); 694 strhashval = clientstr_hashval(dname);
654 695
655 conf = NULL;
656 nfs4_lock_state(); 696 nfs4_lock_state();
657 list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) { 697 conf = find_confirmed_client_by_str(dname, strhashval);
658 if (!cmp_name(&clp->cl_name, &clname)) 698 if (conf) {
659 continue;
660 /* 699 /*
661 * CASE 0: 700 * CASE 0:
662 * clname match, confirmed, different principal 701 * clname match, confirmed, different principal
663 * or different ip_address 702 * or different ip_address
664 */ 703 */
665 status = nfserr_clid_inuse; 704 status = nfserr_clid_inuse;
666 if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) { 705 if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
667 printk("NFSD: setclientid: string in use by client" 706 || conf->cl_addr != ip_addr) {
668 "(clientid %08x/%08x)\n",
669 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
670 goto out;
671 }
672 if (clp->cl_addr != ip_addr) {
673 printk("NFSD: setclientid: string in use by client" 707 printk("NFSD: setclientid: string in use by client"
674 "(clientid %08x/%08x)\n", 708 "(clientid %08x/%08x)\n",
675 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); 709 conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
676 goto out; 710 goto out;
677 } 711 }
678
679 /*
680 * cl_name match from a previous SETCLIENTID operation
681 * XXX check for additional matches?
682 */
683 conf = clp;
684 break;
685 }
686 unconf = NULL;
687 list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
688 if (!cmp_name(&clp->cl_name, &clname))
689 continue;
690 /* cl_name match from a previous SETCLIENTID operation */
691 unconf = clp;
692 break;
693 } 712 }
713 unconf = find_unconfirmed_client_by_str(dname, strhashval);
694 status = nfserr_resource; 714 status = nfserr_resource;
695 if (!conf) { 715 if (!conf) {
696 /* 716 /*
@@ -699,7 +719,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
699 */ 719 */
700 if (unconf) 720 if (unconf)
701 expire_client(unconf); 721 expire_client(unconf);
702 if (!(new = create_client(clname))) 722 new = create_client(clname, dname);
723 if (new == NULL)
703 goto out; 724 goto out;
704 copy_verf(new, &clverifier); 725 copy_verf(new, &clverifier);
705 new->cl_addr = ip_addr; 726 new->cl_addr = ip_addr;
@@ -722,12 +743,16 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
722 * nfs4_client, but with the new callback info and a 743 * nfs4_client, but with the new callback info and a
723 * new cl_confirm 744 * new cl_confirm
724 */ 745 */
725 if ((unconf) && 746 if (unconf) {
726 cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) && 747 /* Note this is removing unconfirmed {*x***},
727 cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) { 748 * which is stronger than RFC recommended {vxc**}.
728 expire_client(unconf); 749 * This has the advantage that there is at most
750 * one {*x***} in either list at any time.
751 */
752 expire_client(unconf);
729 } 753 }
730 if (!(new = create_client(clname))) 754 new = create_client(clname, dname);
755 if (new == NULL)
731 goto out; 756 goto out;
732 copy_verf(new,&conf->cl_verifier); 757 copy_verf(new,&conf->cl_verifier);
733 new->cl_addr = ip_addr; 758 new->cl_addr = ip_addr;
@@ -745,7 +770,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
745 * using input clverifier, clname, and callback info 770 * using input clverifier, clname, and callback info
746 * and generate a new cl_clientid and cl_confirm. 771 * and generate a new cl_clientid and cl_confirm.
747 */ 772 */
748 if (!(new = create_client(clname))) 773 new = create_client(clname, dname);
774 if (new == NULL)
749 goto out; 775 goto out;
750 copy_verf(new,&clverifier); 776 copy_verf(new,&clverifier);
751 new->cl_addr = ip_addr; 777 new->cl_addr = ip_addr;
@@ -771,7 +797,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
771 * new cl_verifier and a new cl_confirm 797 * new cl_verifier and a new cl_confirm
772 */ 798 */
773 expire_client(unconf); 799 expire_client(unconf);
774 if (!(new = create_client(clname))) 800 new = create_client(clname, dname);
801 if (new == NULL)
775 goto out; 802 goto out;
776 copy_verf(new,&clverifier); 803 copy_verf(new,&clverifier);
777 new->cl_addr = ip_addr; 804 new->cl_addr = ip_addr;
@@ -807,7 +834,7 @@ int
807nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm) 834nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
808{ 835{
809 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; 836 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
810 struct nfs4_client *clp, *conf = NULL, *unconf = NULL; 837 struct nfs4_client *conf, *unconf;
811 nfs4_verifier confirm = setclientid_confirm->sc_confirm; 838 nfs4_verifier confirm = setclientid_confirm->sc_confirm;
812 clientid_t * clid = &setclientid_confirm->sc_clientid; 839 clientid_t * clid = &setclientid_confirm->sc_clientid;
813 int status; 840 int status;
@@ -820,102 +847,90 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
820 */ 847 */
821 848
822 nfs4_lock_state(); 849 nfs4_lock_state();
823 clp = find_confirmed_client(clid); 850
824 if (clp) { 851 conf = find_confirmed_client(clid);
825 status = nfserr_inval; 852 unconf = find_unconfirmed_client(clid);
826 /* 853
827 * Found a record for this clientid. If the IP addresses 854 status = nfserr_clid_inuse;
828 * don't match, return ERR_INVAL just as if the record had 855 if (conf && conf->cl_addr != ip_addr)
829 * not been found. 856 goto out;
830 */ 857 if (unconf && unconf->cl_addr != ip_addr)
831 if (clp->cl_addr != ip_addr) { 858 goto out;
832 printk("NFSD: setclientid: string in use by client" 859
833 "(clientid %08x/%08x)\n",
834 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
835 goto out;
836 }
837 conf = clp;
838 }
839 clp = find_unconfirmed_client(clid);
840 if (clp) {
841 status = nfserr_inval;
842 if (clp->cl_addr != ip_addr) {
843 printk("NFSD: setclientid: string in use by client"
844 "(clientid %08x/%08x)\n",
845 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
846 goto out;
847 }
848 unconf = clp;
849 }
850 /* CASE 1:
851 * unconf record that matches input clientid and input confirm.
852 * conf record that matches input clientid.
853 * conf and unconf records match names, verifiers
854 */
855 if ((conf && unconf) && 860 if ((conf && unconf) &&
856 (cmp_verf(&unconf->cl_confirm, &confirm)) && 861 (cmp_verf(&unconf->cl_confirm, &confirm)) &&
857 (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) && 862 (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
858 (cmp_name(&conf->cl_name,&unconf->cl_name)) && 863 (same_name(conf->cl_recdir,unconf->cl_recdir)) &&
859 (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) { 864 (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
865 /* CASE 1:
866 * unconf record that matches input clientid and input confirm.
867 * conf record that matches input clientid.
868 * conf and unconf records match names, verifiers
869 */
860 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 870 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred))
861 status = nfserr_clid_inuse; 871 status = nfserr_clid_inuse;
862 else { 872 else {
863 expire_client(conf); 873 /* XXX: We just turn off callbacks until we can handle
864 clp = unconf; 874 * change request correctly. */
865 move_to_confirmed(unconf); 875 atomic_set(&conf->cl_callback.cb_set, 0);
876 gen_confirm(conf);
877 expire_client(unconf);
866 status = nfs_ok; 878 status = nfs_ok;
879
867 } 880 }
868 goto out; 881 } else if ((conf && !unconf) ||
869 }
870 /* CASE 2:
871 * conf record that matches input clientid.
872 * if unconf record that matches input clientid, then unconf->cl_name
873 * or unconf->cl_verifier don't match the conf record.
874 */
875 if ((conf && !unconf) ||
876 ((conf && unconf) && 882 ((conf && unconf) &&
877 (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) || 883 (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
878 !cmp_name(&conf->cl_name, &unconf->cl_name)))) { 884 !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
879 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) { 885 /* CASE 2:
886 * conf record that matches input clientid.
887 * if unconf record matches input clientid, then
888 * unconf->cl_name or unconf->cl_verifier don't match the
889 * conf record.
890 */
891 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred))
880 status = nfserr_clid_inuse; 892 status = nfserr_clid_inuse;
881 } else { 893 else
882 clp = conf;
883 status = nfs_ok; 894 status = nfs_ok;
884 } 895 } else if (!conf && unconf
885 goto out; 896 && cmp_verf(&unconf->cl_confirm, &confirm)) {
886 } 897 /* CASE 3:
887 /* CASE 3: 898 * conf record not found.
888 * conf record not found. 899 * unconf record found.
889 * unconf record found. 900 * unconf->cl_confirm matches input confirm
890 * unconf->cl_confirm matches input confirm 901 */
891 */
892 if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
893 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) { 902 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
894 status = nfserr_clid_inuse; 903 status = nfserr_clid_inuse;
895 } else { 904 } else {
896 status = nfs_ok; 905 unsigned int hash =
897 clp = unconf; 906 clientstr_hashval(unconf->cl_recdir);
907 conf = find_confirmed_client_by_str(unconf->cl_recdir,
908 hash);
909 if (conf) {
910 nfsd4_remove_clid_dir(conf);
911 expire_client(conf);
912 }
898 move_to_confirmed(unconf); 913 move_to_confirmed(unconf);
914 conf = unconf;
915 status = nfs_ok;
899 } 916 }
900 goto out; 917 } else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm)))
901 } 918 && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm,
902 /* CASE 4: 919 &confirm)))) {
903 * conf record not found, or if conf, then conf->cl_confirm does not 920 /* CASE 4:
904 * match input confirm. 921 * conf record not found, or if conf, conf->cl_confirm does not
905 * unconf record not found, or if unconf, then unconf->cl_confirm 922 * match input confirm.
906 * does not match input confirm. 923 * unconf record not found, or if unconf, unconf->cl_confirm
907 */ 924 * does not match input confirm.
908 if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) && 925 */
909 (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
910 status = nfserr_stale_clientid; 926 status = nfserr_stale_clientid;
911 goto out; 927 } else {
928 /* check that we have hit one of the cases...*/
929 status = nfserr_clid_inuse;
912 } 930 }
913 /* check that we have hit one of the cases...*/
914 status = nfserr_inval;
915 goto out;
916out: 931out:
917 if (!status) 932 if (!status)
918 nfsd4_probe_callback(clp); 933 nfsd4_probe_callback(conf);
919 nfs4_unlock_state(); 934 nfs4_unlock_state();
920 return status; 935 return status;
921} 936}
@@ -961,60 +976,65 @@ alloc_init_file(struct inode *ino)
961 struct nfs4_file *fp; 976 struct nfs4_file *fp;
962 unsigned int hashval = file_hashval(ino); 977 unsigned int hashval = file_hashval(ino);
963 978
964 if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) { 979 fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
980 if (fp) {
981 kref_init(&fp->fi_ref);
965 INIT_LIST_HEAD(&fp->fi_hash); 982 INIT_LIST_HEAD(&fp->fi_hash);
966 INIT_LIST_HEAD(&fp->fi_perfile); 983 INIT_LIST_HEAD(&fp->fi_stateids);
967 INIT_LIST_HEAD(&fp->fi_del_perfile); 984 INIT_LIST_HEAD(&fp->fi_delegations);
968 list_add(&fp->fi_hash, &file_hashtbl[hashval]); 985 list_add(&fp->fi_hash, &file_hashtbl[hashval]);
969 fp->fi_inode = igrab(ino); 986 fp->fi_inode = igrab(ino);
970 fp->fi_id = current_fileid++; 987 fp->fi_id = current_fileid++;
971 alloc_file++;
972 return fp; 988 return fp;
973 } 989 }
974 return NULL; 990 return NULL;
975} 991}
976 992
977static void 993static void
978release_all_files(void) 994nfsd4_free_slab(kmem_cache_t **slab)
979{ 995{
980 int i; 996 int status;
981 struct nfs4_file *fp;
982 997
983 for (i=0;i<FILE_HASH_SIZE;i++) { 998 if (*slab == NULL)
984 while (!list_empty(&file_hashtbl[i])) { 999 return;
985 fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash); 1000 status = kmem_cache_destroy(*slab);
986 /* this should never be more than once... */ 1001 *slab = NULL;
987 if (!list_empty(&fp->fi_perfile) || !list_empty(&fp->fi_del_perfile)) { 1002 WARN_ON(status);
988 printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
989 }
990 release_file(fp);
991 }
992 }
993} 1003}
994 1004
995kmem_cache_t *stateowner_slab = NULL; 1005static void
1006nfsd4_free_slabs(void)
1007{
1008 nfsd4_free_slab(&stateowner_slab);
1009 nfsd4_free_slab(&file_slab);
1010 nfsd4_free_slab(&stateid_slab);
1011 nfsd4_free_slab(&deleg_slab);
1012}
996 1013
997static int 1014static int
998nfsd4_init_slabs(void) 1015nfsd4_init_slabs(void)
999{ 1016{
1000 stateowner_slab = kmem_cache_create("nfsd4_stateowners", 1017 stateowner_slab = kmem_cache_create("nfsd4_stateowners",
1001 sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL); 1018 sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
1002 if (stateowner_slab == NULL) { 1019 if (stateowner_slab == NULL)
1003 dprintk("nfsd4: out of memory while initializing nfsv4\n"); 1020 goto out_nomem;
1004 return -ENOMEM; 1021 file_slab = kmem_cache_create("nfsd4_files",
1005 } 1022 sizeof(struct nfs4_file), 0, 0, NULL, NULL);
1023 if (file_slab == NULL)
1024 goto out_nomem;
1025 stateid_slab = kmem_cache_create("nfsd4_stateids",
1026 sizeof(struct nfs4_stateid), 0, 0, NULL, NULL);
1027 if (stateid_slab == NULL)
1028 goto out_nomem;
1029 deleg_slab = kmem_cache_create("nfsd4_delegations",
1030 sizeof(struct nfs4_delegation), 0, 0, NULL, NULL);
1031 if (deleg_slab == NULL)
1032 goto out_nomem;
1006 return 0; 1033 return 0;
1007} 1034out_nomem:
1008 1035 nfsd4_free_slabs();
1009static void 1036 dprintk("nfsd4: out of memory while initializing nfsv4\n");
1010nfsd4_free_slabs(void) 1037 return -ENOMEM;
1011{
1012 int status = 0;
1013
1014 if (stateowner_slab)
1015 status = kmem_cache_destroy(stateowner_slab);
1016 stateowner_slab = NULL;
1017 BUG_ON(status);
1018} 1038}
1019 1039
1020void 1040void
@@ -1055,14 +1075,13 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
1055 INIT_LIST_HEAD(&sop->so_idhash); 1075 INIT_LIST_HEAD(&sop->so_idhash);
1056 INIT_LIST_HEAD(&sop->so_strhash); 1076 INIT_LIST_HEAD(&sop->so_strhash);
1057 INIT_LIST_HEAD(&sop->so_perclient); 1077 INIT_LIST_HEAD(&sop->so_perclient);
1058 INIT_LIST_HEAD(&sop->so_perfilestate); 1078 INIT_LIST_HEAD(&sop->so_stateids);
1059 INIT_LIST_HEAD(&sop->so_perlockowner); /* not used */ 1079 INIT_LIST_HEAD(&sop->so_perstateid); /* not used */
1060 INIT_LIST_HEAD(&sop->so_close_lru); 1080 INIT_LIST_HEAD(&sop->so_close_lru);
1061 sop->so_time = 0; 1081 sop->so_time = 0;
1062 list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]); 1082 list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
1063 list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]); 1083 list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
1064 list_add(&sop->so_perclient, &clp->cl_perclient); 1084 list_add(&sop->so_perclient, &clp->cl_openowners);
1065 add_perclient++;
1066 sop->so_is_open_owner = 1; 1085 sop->so_is_open_owner = 1;
1067 sop->so_id = current_ownerid++; 1086 sop->so_id = current_ownerid++;
1068 sop->so_client = clp; 1087 sop->so_client = clp;
@@ -1080,10 +1099,10 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp)
1080{ 1099{
1081 struct nfs4_stateowner *lock_sop; 1100 struct nfs4_stateowner *lock_sop;
1082 1101
1083 while (!list_empty(&open_stp->st_perlockowner)) { 1102 while (!list_empty(&open_stp->st_lockowners)) {
1084 lock_sop = list_entry(open_stp->st_perlockowner.next, 1103 lock_sop = list_entry(open_stp->st_lockowners.next,
1085 struct nfs4_stateowner, so_perlockowner); 1104 struct nfs4_stateowner, so_perstateid);
1086 /* list_del(&open_stp->st_perlockowner); */ 1105 /* list_del(&open_stp->st_lockowners); */
1087 BUG_ON(lock_sop->so_is_open_owner); 1106 BUG_ON(lock_sop->so_is_open_owner);
1088 release_stateowner(lock_sop); 1107 release_stateowner(lock_sop);
1089 } 1108 }
@@ -1096,14 +1115,12 @@ unhash_stateowner(struct nfs4_stateowner *sop)
1096 1115
1097 list_del(&sop->so_idhash); 1116 list_del(&sop->so_idhash);
1098 list_del(&sop->so_strhash); 1117 list_del(&sop->so_strhash);
1099 if (sop->so_is_open_owner) { 1118 if (sop->so_is_open_owner)
1100 list_del(&sop->so_perclient); 1119 list_del(&sop->so_perclient);
1101 del_perclient++; 1120 list_del(&sop->so_perstateid);
1102 } 1121 while (!list_empty(&sop->so_stateids)) {
1103 list_del(&sop->so_perlockowner); 1122 stp = list_entry(sop->so_stateids.next,
1104 while (!list_empty(&sop->so_perfilestate)) { 1123 struct nfs4_stateid, st_perstateowner);
1105 stp = list_entry(sop->so_perfilestate.next,
1106 struct nfs4_stateid, st_perfilestate);
1107 if (sop->so_is_open_owner) 1124 if (sop->so_is_open_owner)
1108 release_stateid(stp, OPEN_STATE); 1125 release_stateid(stp, OPEN_STATE);
1109 else 1126 else
@@ -1125,14 +1142,14 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
1125 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id); 1142 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
1126 1143
1127 INIT_LIST_HEAD(&stp->st_hash); 1144 INIT_LIST_HEAD(&stp->st_hash);
1128 INIT_LIST_HEAD(&stp->st_perfilestate); 1145 INIT_LIST_HEAD(&stp->st_perstateowner);
1129 INIT_LIST_HEAD(&stp->st_perlockowner); 1146 INIT_LIST_HEAD(&stp->st_lockowners);
1130 INIT_LIST_HEAD(&stp->st_perfile); 1147 INIT_LIST_HEAD(&stp->st_perfile);
1131 list_add(&stp->st_hash, &stateid_hashtbl[hashval]); 1148 list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
1132 list_add(&stp->st_perfilestate, &sop->so_perfilestate); 1149 list_add(&stp->st_perstateowner, &sop->so_stateids);
1133 list_add_perfile++; 1150 list_add(&stp->st_perfile, &fp->fi_stateids);
1134 list_add(&stp->st_perfile, &fp->fi_perfile);
1135 stp->st_stateowner = sop; 1151 stp->st_stateowner = sop;
1152 get_nfs4_file(fp);
1136 stp->st_file = fp; 1153 stp->st_file = fp;
1137 stp->st_stateid.si_boot = boot_time; 1154 stp->st_stateid.si_boot = boot_time;
1138 stp->st_stateid.si_stateownerid = sop->so_id; 1155 stp->st_stateid.si_stateownerid = sop->so_id;
@@ -1150,30 +1167,20 @@ release_stateid(struct nfs4_stateid *stp, int flags)
1150 struct file *filp = stp->st_vfs_file; 1167 struct file *filp = stp->st_vfs_file;
1151 1168
1152 list_del(&stp->st_hash); 1169 list_del(&stp->st_hash);
1153 list_del_perfile++;
1154 list_del(&stp->st_perfile); 1170 list_del(&stp->st_perfile);
1155 list_del(&stp->st_perfilestate); 1171 list_del(&stp->st_perstateowner);
1156 if (flags & OPEN_STATE) { 1172 if (flags & OPEN_STATE) {
1157 release_stateid_lockowners(stp); 1173 release_stateid_lockowners(stp);
1158 stp->st_vfs_file = NULL; 1174 stp->st_vfs_file = NULL;
1159 nfsd_close(filp); 1175 nfsd_close(filp);
1160 vfsclose++;
1161 } else if (flags & LOCK_STATE) 1176 } else if (flags & LOCK_STATE)
1162 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); 1177 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
1163 kfree(stp); 1178 put_nfs4_file(stp->st_file);
1179 kmem_cache_free(stateid_slab, stp);
1164 stp = NULL; 1180 stp = NULL;
1165} 1181}
1166 1182
1167static void 1183static void
1168release_file(struct nfs4_file *fp)
1169{
1170 free_file++;
1171 list_del(&fp->fi_hash);
1172 iput(fp->fi_inode);
1173 kfree(fp);
1174}
1175
1176void
1177move_to_close_lru(struct nfs4_stateowner *sop) 1184move_to_close_lru(struct nfs4_stateowner *sop)
1178{ 1185{
1179 dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop); 1186 dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
@@ -1183,11 +1190,10 @@ move_to_close_lru(struct nfs4_stateowner *sop)
1183 sop->so_time = get_seconds(); 1190 sop->so_time = get_seconds();
1184} 1191}
1185 1192
1186void 1193static void
1187release_state_owner(struct nfs4_stateid *stp, int flag) 1194release_state_owner(struct nfs4_stateid *stp, int flag)
1188{ 1195{
1189 struct nfs4_stateowner *sop = stp->st_stateowner; 1196 struct nfs4_stateowner *sop = stp->st_stateowner;
1190 struct nfs4_file *fp = stp->st_file;
1191 1197
1192 dprintk("NFSD: release_state_owner\n"); 1198 dprintk("NFSD: release_state_owner\n");
1193 release_stateid(stp, flag); 1199 release_stateid(stp, flag);
@@ -1196,12 +1202,8 @@ release_state_owner(struct nfs4_stateid *stp, int flag)
1196 * released by the laundromat service after the lease period 1202 * released by the laundromat service after the lease period
1197 * to enable us to handle CLOSE replay 1203 * to enable us to handle CLOSE replay
1198 */ 1204 */
1199 if (sop->so_confirmed && list_empty(&sop->so_perfilestate)) 1205 if (sop->so_confirmed && list_empty(&sop->so_stateids))
1200 move_to_close_lru(sop); 1206 move_to_close_lru(sop);
1201 /* unused nfs4_file's are releseed. XXX slab cache? */
1202 if (list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) {
1203 release_file(fp);
1204 }
1205} 1207}
1206 1208
1207static int 1209static int
@@ -1231,8 +1233,10 @@ find_file(struct inode *ino)
1231 struct nfs4_file *fp; 1233 struct nfs4_file *fp;
1232 1234
1233 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { 1235 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
1234 if (fp->fi_inode == ino) 1236 if (fp->fi_inode == ino) {
1237 get_nfs4_file(fp);
1235 return fp; 1238 return fp;
1239 }
1236 } 1240 }
1237 return NULL; 1241 return NULL;
1238} 1242}
@@ -1240,7 +1244,7 @@ find_file(struct inode *ino)
1240#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0) 1244#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
1241#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0) 1245#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
1242 1246
1243void 1247static void
1244set_access(unsigned int *access, unsigned long bmap) { 1248set_access(unsigned int *access, unsigned long bmap) {
1245 int i; 1249 int i;
1246 1250
@@ -1251,7 +1255,7 @@ set_access(unsigned int *access, unsigned long bmap) {
1251 } 1255 }
1252} 1256}
1253 1257
1254void 1258static void
1255set_deny(unsigned int *deny, unsigned long bmap) { 1259set_deny(unsigned int *deny, unsigned long bmap) {
1256 int i; 1260 int i;
1257 1261
@@ -1277,25 +1281,30 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
1277 * Called to check deny when READ with all zero stateid or 1281 * Called to check deny when READ with all zero stateid or
1278 * WRITE with all zero or all one stateid 1282 * WRITE with all zero or all one stateid
1279 */ 1283 */
1280int 1284static int
1281nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) 1285nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
1282{ 1286{
1283 struct inode *ino = current_fh->fh_dentry->d_inode; 1287 struct inode *ino = current_fh->fh_dentry->d_inode;
1284 struct nfs4_file *fp; 1288 struct nfs4_file *fp;
1285 struct nfs4_stateid *stp; 1289 struct nfs4_stateid *stp;
1290 int ret;
1286 1291
1287 dprintk("NFSD: nfs4_share_conflict\n"); 1292 dprintk("NFSD: nfs4_share_conflict\n");
1288 1293
1289 fp = find_file(ino); 1294 fp = find_file(ino);
1290 if (fp) { 1295 if (!fp)
1296 return nfs_ok;
1297 ret = nfserr_share_denied;
1291 /* Search for conflicting share reservations */ 1298 /* Search for conflicting share reservations */
1292 list_for_each_entry(stp, &fp->fi_perfile, st_perfile) { 1299 list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
1293 if (test_bit(deny_type, &stp->st_deny_bmap) || 1300 if (test_bit(deny_type, &stp->st_deny_bmap) ||
1294 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap)) 1301 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
1295 return nfserr_share_denied; 1302 goto out;
1296 }
1297 } 1303 }
1298 return nfs_ok; 1304 ret = nfs_ok;
1305out:
1306 put_nfs4_file(fp);
1307 return ret;
1299} 1308}
1300 1309
1301static inline void 1310static inline void
@@ -1427,7 +1436,7 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
1427 return -EAGAIN; 1436 return -EAGAIN;
1428} 1437}
1429 1438
1430struct lock_manager_operations nfsd_lease_mng_ops = { 1439static struct lock_manager_operations nfsd_lease_mng_ops = {
1431 .fl_break = nfsd_break_deleg_cb, 1440 .fl_break = nfsd_break_deleg_cb,
1432 .fl_release_private = nfsd_release_deleg_cb, 1441 .fl_release_private = nfsd_release_deleg_cb,
1433 .fl_copy_lock = nfsd_copy_lock_deleg_cb, 1442 .fl_copy_lock = nfsd_copy_lock_deleg_cb,
@@ -1526,6 +1535,51 @@ out:
1526 return status; 1535 return status;
1527} 1536}
1528 1537
1538static inline int
1539nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
1540{
1541 if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
1542 return nfserr_openmode;
1543 else
1544 return nfs_ok;
1545}
1546
1547static struct nfs4_delegation *
1548find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
1549{
1550 struct nfs4_delegation *dp;
1551
1552 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) {
1553 if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid)
1554 return dp;
1555 }
1556 return NULL;
1557}
1558
1559static int
1560nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
1561 struct nfs4_delegation **dp)
1562{
1563 int flags;
1564 int status = nfserr_bad_stateid;
1565
1566 *dp = find_delegation_file(fp, &open->op_delegate_stateid);
1567 if (*dp == NULL)
1568 goto out;
1569 flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ?
1570 RD_STATE : WR_STATE;
1571 status = nfs4_check_delegmode(*dp, flags);
1572 if (status)
1573 *dp = NULL;
1574out:
1575 if (open->op_claim_type != NFS4_OPEN_CLAIM_DELEGATE_CUR)
1576 return nfs_ok;
1577 if (status)
1578 return status;
1579 open->op_stateowner->so_confirmed = 1;
1580 return nfs_ok;
1581}
1582
1529static int 1583static int
1530nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp) 1584nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
1531{ 1585{
@@ -1533,7 +1587,7 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_state
1533 int status = nfserr_share_denied; 1587 int status = nfserr_share_denied;
1534 struct nfs4_stateowner *sop = open->op_stateowner; 1588 struct nfs4_stateowner *sop = open->op_stateowner;
1535 1589
1536 list_for_each_entry(local, &fp->fi_perfile, st_perfile) { 1590 list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
1537 /* ignore lock owners */ 1591 /* ignore lock owners */
1538 if (local->st_stateowner->so_is_open_owner == 0) 1592 if (local->st_stateowner->so_is_open_owner == 0)
1539 continue; 1593 continue;
@@ -1549,25 +1603,37 @@ out:
1549 return status; 1603 return status;
1550} 1604}
1551 1605
1606static inline struct nfs4_stateid *
1607nfs4_alloc_stateid(void)
1608{
1609 return kmem_cache_alloc(stateid_slab, GFP_KERNEL);
1610}
1611
1552static int 1612static int
1553nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, 1613nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
1614 struct nfs4_delegation *dp,
1554 struct svc_fh *cur_fh, int flags) 1615 struct svc_fh *cur_fh, int flags)
1555{ 1616{
1556 struct nfs4_stateid *stp; 1617 struct nfs4_stateid *stp;
1557 int status;
1558 1618
1559 stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL); 1619 stp = nfs4_alloc_stateid();
1560 if (stp == NULL) 1620 if (stp == NULL)
1561 return nfserr_resource; 1621 return nfserr_resource;
1562 1622
1563 status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file); 1623 if (dp) {
1564 if (status) { 1624 get_file(dp->dl_vfs_file);
1565 if (status == nfserr_dropit) 1625 stp->st_vfs_file = dp->dl_vfs_file;
1566 status = nfserr_jukebox; 1626 } else {
1567 kfree(stp); 1627 int status;
1568 return status; 1628 status = nfsd_open(rqstp, cur_fh, S_IFREG, flags,
1629 &stp->st_vfs_file);
1630 if (status) {
1631 if (status == nfserr_dropit)
1632 status = nfserr_jukebox;
1633 kmem_cache_free(stateid_slab, stp);
1634 return status;
1635 }
1569 } 1636 }
1570 vfsopen++;
1571 *stpp = stp; 1637 *stpp = stp;
1572 return 0; 1638 return 0;
1573} 1639}
@@ -1628,6 +1694,7 @@ nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
1628 *status = nfserr_reclaim_bad; 1694 *status = nfserr_reclaim_bad;
1629 else { 1695 else {
1630 open->op_stateowner->so_confirmed = 1; 1696 open->op_stateowner->so_confirmed = 1;
1697 open->op_stateowner->so_client->cl_firststate = 1;
1631 open->op_stateowner->so_seqid--; 1698 open->op_stateowner->so_seqid--;
1632 } 1699 }
1633 } 1700 }
@@ -1646,14 +1713,30 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1646 int status, flag = 0; 1713 int status, flag = 0;
1647 1714
1648 flag = NFS4_OPEN_DELEGATE_NONE; 1715 flag = NFS4_OPEN_DELEGATE_NONE;
1649 if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL 1716 open->op_recall = 0;
1650 || !atomic_read(&cb->cb_set) || !sop->so_confirmed) 1717 switch (open->op_claim_type) {
1651 goto out; 1718 case NFS4_OPEN_CLAIM_PREVIOUS:
1652 1719 if (!atomic_read(&cb->cb_set))
1653 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 1720 open->op_recall = 1;
1654 flag = NFS4_OPEN_DELEGATE_WRITE; 1721 flag = open->op_delegate_type;
1655 else 1722 if (flag == NFS4_OPEN_DELEGATE_NONE)
1656 flag = NFS4_OPEN_DELEGATE_READ; 1723 goto out;
1724 break;
1725 case NFS4_OPEN_CLAIM_NULL:
1726 /* Let's not give out any delegations till everyone's
1727 * had the chance to reclaim theirs.... */
1728 if (nfs4_in_grace())
1729 goto out;
1730 if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
1731 goto out;
1732 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
1733 flag = NFS4_OPEN_DELEGATE_WRITE;
1734 else
1735 flag = NFS4_OPEN_DELEGATE_READ;
1736 break;
1737 default:
1738 goto out;
1739 }
1657 1740
1658 dp = alloc_init_deleg(sop->so_client, stp, fh, flag); 1741 dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
1659 if (dp == NULL) { 1742 if (dp == NULL) {
@@ -1687,6 +1770,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1687 dp->dl_stateid.si_fileid, 1770 dp->dl_stateid.si_fileid,
1688 dp->dl_stateid.si_generation); 1771 dp->dl_stateid.si_generation);
1689out: 1772out:
1773 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
1774 && flag == NFS4_OPEN_DELEGATE_NONE
1775 && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
1776 printk("NFSD: WARNING: refusing delegation reclaim\n");
1690 open->op_delegate_type = flag; 1777 open->op_delegate_type = flag;
1691} 1778}
1692 1779
@@ -1699,6 +1786,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1699 struct nfs4_file *fp = NULL; 1786 struct nfs4_file *fp = NULL;
1700 struct inode *ino = current_fh->fh_dentry->d_inode; 1787 struct inode *ino = current_fh->fh_dentry->d_inode;
1701 struct nfs4_stateid *stp = NULL; 1788 struct nfs4_stateid *stp = NULL;
1789 struct nfs4_delegation *dp = NULL;
1702 int status; 1790 int status;
1703 1791
1704 status = nfserr_inval; 1792 status = nfserr_inval;
@@ -1713,7 +1801,13 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1713 if (fp) { 1801 if (fp) {
1714 if ((status = nfs4_check_open(fp, open, &stp))) 1802 if ((status = nfs4_check_open(fp, open, &stp)))
1715 goto out; 1803 goto out;
1804 status = nfs4_check_deleg(fp, open, &dp);
1805 if (status)
1806 goto out;
1716 } else { 1807 } else {
1808 status = nfserr_bad_stateid;
1809 if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
1810 goto out;
1717 status = nfserr_resource; 1811 status = nfserr_resource;
1718 fp = alloc_init_file(ino); 1812 fp = alloc_init_file(ino);
1719 if (fp == NULL) 1813 if (fp == NULL)
@@ -1736,7 +1830,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1736 flags = MAY_WRITE; 1830 flags = MAY_WRITE;
1737 else 1831 else
1738 flags = MAY_READ; 1832 flags = MAY_READ;
1739 if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags))) 1833 status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
1834 if (status)
1740 goto out; 1835 goto out;
1741 init_stateid(stp, fp, open); 1836 init_stateid(stp, fp, open);
1742 status = nfsd4_truncate(rqstp, current_fh, open); 1837 status = nfsd4_truncate(rqstp, current_fh, open);
@@ -1759,10 +1854,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1759 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid, 1854 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
1760 stp->st_stateid.si_fileid, stp->st_stateid.si_generation); 1855 stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
1761out: 1856out:
1762 /* take the opportunity to clean up unused state */ 1857 if (fp)
1763 if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) 1858 put_nfs4_file(fp);
1764 release_file(fp);
1765
1766 /* CLAIM_PREVIOUS has different error returns */ 1859 /* CLAIM_PREVIOUS has different error returns */
1767 nfs4_set_claim_prev(open, &status); 1860 nfs4_set_claim_prev(open, &status);
1768 /* 1861 /*
@@ -1775,6 +1868,7 @@ out:
1775 return status; 1868 return status;
1776} 1869}
1777 1870
1871static struct workqueue_struct *laundry_wq;
1778static struct work_struct laundromat_work; 1872static struct work_struct laundromat_work;
1779static void laundromat_main(void *); 1873static void laundromat_main(void *);
1780static DECLARE_WORK(laundromat_work, laundromat_main, NULL); 1874static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
@@ -1800,7 +1894,7 @@ nfsd4_renew(clientid_t *clid)
1800 } 1894 }
1801 renew_client(clp); 1895 renew_client(clp);
1802 status = nfserr_cb_path_down; 1896 status = nfserr_cb_path_down;
1803 if (!list_empty(&clp->cl_del_perclnt) 1897 if (!list_empty(&clp->cl_delegations)
1804 && !atomic_read(&clp->cl_callback.cb_set)) 1898 && !atomic_read(&clp->cl_callback.cb_set))
1805 goto out; 1899 goto out;
1806 status = nfs_ok; 1900 status = nfs_ok;
@@ -1809,7 +1903,15 @@ out:
1809 return status; 1903 return status;
1810} 1904}
1811 1905
1812time_t 1906static void
1907end_grace(void)
1908{
1909 dprintk("NFSD: end of grace period\n");
1910 nfsd4_recdir_purge_old();
1911 in_grace = 0;
1912}
1913
1914static time_t
1813nfs4_laundromat(void) 1915nfs4_laundromat(void)
1814{ 1916{
1815 struct nfs4_client *clp; 1917 struct nfs4_client *clp;
@@ -1823,6 +1925,8 @@ nfs4_laundromat(void)
1823 nfs4_lock_state(); 1925 nfs4_lock_state();
1824 1926
1825 dprintk("NFSD: laundromat service - starting\n"); 1927 dprintk("NFSD: laundromat service - starting\n");
1928 if (in_grace)
1929 end_grace();
1826 list_for_each_safe(pos, next, &client_lru) { 1930 list_for_each_safe(pos, next, &client_lru) {
1827 clp = list_entry(pos, struct nfs4_client, cl_lru); 1931 clp = list_entry(pos, struct nfs4_client, cl_lru);
1828 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { 1932 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
@@ -1833,6 +1937,7 @@ nfs4_laundromat(void)
1833 } 1937 }
1834 dprintk("NFSD: purging unused client (clientid %08x)\n", 1938 dprintk("NFSD: purging unused client (clientid %08x)\n",
1835 clp->cl_clientid.cl_id); 1939 clp->cl_clientid.cl_id);
1940 nfsd4_remove_clid_dir(clp);
1836 expire_client(clp); 1941 expire_client(clp);
1837 } 1942 }
1838 INIT_LIST_HEAD(&reaplist); 1943 INIT_LIST_HEAD(&reaplist);
@@ -1882,13 +1987,13 @@ laundromat_main(void *not_used)
1882 1987
1883 t = nfs4_laundromat(); 1988 t = nfs4_laundromat();
1884 dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t); 1989 dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
1885 schedule_delayed_work(&laundromat_work, t*HZ); 1990 queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
1886} 1991}
1887 1992
1888/* search ownerid_hashtbl[] and close_lru for stateid owner 1993/* search ownerid_hashtbl[] and close_lru for stateid owner
1889 * (stateid->si_stateownerid) 1994 * (stateid->si_stateownerid)
1890 */ 1995 */
1891struct nfs4_stateowner * 1996static struct nfs4_stateowner *
1892find_openstateowner_id(u32 st_id, int flags) { 1997find_openstateowner_id(u32 st_id, int flags) {
1893 struct nfs4_stateowner *local = NULL; 1998 struct nfs4_stateowner *local = NULL;
1894 1999
@@ -1949,15 +2054,6 @@ out:
1949} 2054}
1950 2055
1951static inline int 2056static inline int
1952nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
1953{
1954 if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
1955 return nfserr_openmode;
1956 else
1957 return nfs_ok;
1958}
1959
1960static inline int
1961check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) 2057check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
1962{ 2058{
1963 /* Trying to call delegreturn with a special stateid? Yuch: */ 2059 /* Trying to call delegreturn with a special stateid? Yuch: */
@@ -2071,7 +2167,7 @@ out:
2071/* 2167/*
2072 * Checks for sequence id mutating operations. 2168 * Checks for sequence id mutating operations.
2073 */ 2169 */
2074int 2170static int
2075nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid) 2171nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
2076{ 2172{
2077 int status; 2173 int status;
@@ -2230,6 +2326,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
2230 stp->st_stateid.si_stateownerid, 2326 stp->st_stateid.si_stateownerid,
2231 stp->st_stateid.si_fileid, 2327 stp->st_stateid.si_fileid,
2232 stp->st_stateid.si_generation); 2328 stp->st_stateid.si_generation);
2329
2330 nfsd4_create_clid_dir(sop->so_client);
2233out: 2331out:
2234 if (oc->oc_stateowner) 2332 if (oc->oc_stateowner)
2235 nfs4_get_stateowner(oc->oc_stateowner); 2333 nfs4_get_stateowner(oc->oc_stateowner);
@@ -2387,7 +2485,7 @@ static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
2387static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; 2485static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
2388static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE]; 2486static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
2389 2487
2390struct nfs4_stateid * 2488static struct nfs4_stateid *
2391find_stateid(stateid_t *stid, int flags) 2489find_stateid(stateid_t *stid, int flags)
2392{ 2490{
2393 struct nfs4_stateid *local = NULL; 2491 struct nfs4_stateid *local = NULL;
@@ -2419,25 +2517,19 @@ find_stateid(stateid_t *stid, int flags)
2419static struct nfs4_delegation * 2517static struct nfs4_delegation *
2420find_delegation_stateid(struct inode *ino, stateid_t *stid) 2518find_delegation_stateid(struct inode *ino, stateid_t *stid)
2421{ 2519{
2422 struct nfs4_delegation *dp = NULL; 2520 struct nfs4_file *fp;
2423 struct nfs4_file *fp = NULL; 2521 struct nfs4_delegation *dl;
2424 u32 st_id;
2425 2522
2426 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n", 2523 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
2427 stid->si_boot, stid->si_stateownerid, 2524 stid->si_boot, stid->si_stateownerid,
2428 stid->si_fileid, stid->si_generation); 2525 stid->si_fileid, stid->si_generation);
2429 2526
2430 st_id = stid->si_stateownerid;
2431 fp = find_file(ino); 2527 fp = find_file(ino);
2432 if (fp) { 2528 if (!fp)
2433 list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) { 2529 return NULL;
2434 if(dp->dl_stateid.si_stateownerid == st_id) { 2530 dl = find_delegation_file(fp, stid);
2435 dprintk("NFSD: find_delegation dp %p\n",dp); 2531 put_nfs4_file(fp);
2436 return dp; 2532 return dl;
2437 }
2438 }
2439 }
2440 return NULL;
2441} 2533}
2442 2534
2443/* 2535/*
@@ -2457,7 +2549,7 @@ nfs4_transform_lock_offset(struct file_lock *lock)
2457 lock->fl_end = OFFSET_MAX; 2549 lock->fl_end = OFFSET_MAX;
2458} 2550}
2459 2551
2460int 2552static int
2461nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval) 2553nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
2462{ 2554{
2463 struct nfs4_stateowner *local = NULL; 2555 struct nfs4_stateowner *local = NULL;
@@ -2498,22 +2590,6 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
2498} 2590}
2499 2591
2500static struct nfs4_stateowner * 2592static struct nfs4_stateowner *
2501find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
2502{
2503 struct nfs4_stateowner *local = NULL;
2504 int i;
2505
2506 for (i = 0; i < LOCK_HASH_SIZE; i++) {
2507 list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
2508 if (!cmp_owner_str(local, owner, clid))
2509 continue;
2510 return local;
2511 }
2512 }
2513 return NULL;
2514}
2515
2516static struct nfs4_stateowner *
2517find_lockstateowner_str(struct inode *inode, clientid_t *clid, 2593find_lockstateowner_str(struct inode *inode, clientid_t *clid,
2518 struct xdr_netobj *owner) 2594 struct xdr_netobj *owner)
2519{ 2595{
@@ -2548,13 +2624,13 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2548 INIT_LIST_HEAD(&sop->so_idhash); 2624 INIT_LIST_HEAD(&sop->so_idhash);
2549 INIT_LIST_HEAD(&sop->so_strhash); 2625 INIT_LIST_HEAD(&sop->so_strhash);
2550 INIT_LIST_HEAD(&sop->so_perclient); 2626 INIT_LIST_HEAD(&sop->so_perclient);
2551 INIT_LIST_HEAD(&sop->so_perfilestate); 2627 INIT_LIST_HEAD(&sop->so_stateids);
2552 INIT_LIST_HEAD(&sop->so_perlockowner); 2628 INIT_LIST_HEAD(&sop->so_perstateid);
2553 INIT_LIST_HEAD(&sop->so_close_lru); /* not used */ 2629 INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
2554 sop->so_time = 0; 2630 sop->so_time = 0;
2555 list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]); 2631 list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
2556 list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]); 2632 list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
2557 list_add(&sop->so_perlockowner, &open_stp->st_perlockowner); 2633 list_add(&sop->so_perstateid, &open_stp->st_lockowners);
2558 sop->so_is_open_owner = 0; 2634 sop->so_is_open_owner = 0;
2559 sop->so_id = current_ownerid++; 2635 sop->so_id = current_ownerid++;
2560 sop->so_client = clp; 2636 sop->so_client = clp;
@@ -2567,24 +2643,24 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2567 return sop; 2643 return sop;
2568} 2644}
2569 2645
2570struct nfs4_stateid * 2646static struct nfs4_stateid *
2571alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp) 2647alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
2572{ 2648{
2573 struct nfs4_stateid *stp; 2649 struct nfs4_stateid *stp;
2574 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id); 2650 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
2575 2651
2576 if ((stp = kmalloc(sizeof(struct nfs4_stateid), 2652 stp = nfs4_alloc_stateid();
2577 GFP_KERNEL)) == NULL) 2653 if (stp == NULL)
2578 goto out; 2654 goto out;
2579 INIT_LIST_HEAD(&stp->st_hash); 2655 INIT_LIST_HEAD(&stp->st_hash);
2580 INIT_LIST_HEAD(&stp->st_perfile); 2656 INIT_LIST_HEAD(&stp->st_perfile);
2581 INIT_LIST_HEAD(&stp->st_perfilestate); 2657 INIT_LIST_HEAD(&stp->st_perstateowner);
2582 INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */ 2658 INIT_LIST_HEAD(&stp->st_lockowners); /* not used */
2583 list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]); 2659 list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
2584 list_add(&stp->st_perfile, &fp->fi_perfile); 2660 list_add(&stp->st_perfile, &fp->fi_stateids);
2585 list_add_perfile++; 2661 list_add(&stp->st_perstateowner, &sop->so_stateids);
2586 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
2587 stp->st_stateowner = sop; 2662 stp->st_stateowner = sop;
2663 get_nfs4_file(fp);
2588 stp->st_file = fp; 2664 stp->st_file = fp;
2589 stp->st_stateid.si_boot = boot_time; 2665 stp->st_stateid.si_boot = boot_time;
2590 stp->st_stateid.si_stateownerid = sop->so_id; 2666 stp->st_stateid.si_stateownerid = sop->so_id;
@@ -2598,7 +2674,7 @@ out:
2598 return stp; 2674 return stp;
2599} 2675}
2600 2676
2601int 2677static int
2602check_lock_length(u64 offset, u64 length) 2678check_lock_length(u64 offset, u64 length)
2603{ 2679{
2604 return ((length == 0) || ((length != ~(u64)0) && 2680 return ((length == 0) || ((length != ~(u64)0) &&
@@ -2611,7 +2687,7 @@ check_lock_length(u64 offset, u64 length)
2611int 2687int
2612nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock) 2688nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
2613{ 2689{
2614 struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL; 2690 struct nfs4_stateowner *open_sop = NULL;
2615 struct nfs4_stateid *lock_stp; 2691 struct nfs4_stateid *lock_stp;
2616 struct file *filp; 2692 struct file *filp;
2617 struct file_lock file_lock; 2693 struct file_lock file_lock;
@@ -2670,16 +2746,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2670 strhashval = lock_ownerstr_hashval(fp->fi_inode, 2746 strhashval = lock_ownerstr_hashval(fp->fi_inode,
2671 open_sop->so_client->cl_clientid.cl_id, 2747 open_sop->so_client->cl_clientid.cl_id,
2672 &lock->v.new.owner); 2748 &lock->v.new.owner);
2673 /* 2749 /* XXX: Do we need to check for duplicate stateowners on
2674 * If we already have this lock owner, the client is in 2750 * the same file, or should they just be allowed (and
2675 * error (or our bookeeping is wrong!) 2751 * create new stateids)? */
2676 * for asking for a 'new lock'.
2677 */
2678 status = nfserr_bad_stateid;
2679 lock_sop = find_lockstateowner(&lock->v.new.owner,
2680 &lock->v.new.clientid);
2681 if (lock_sop)
2682 goto out;
2683 status = nfserr_resource; 2752 status = nfserr_resource;
2684 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock))) 2753 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
2685 goto out; 2754 goto out;
@@ -2970,8 +3039,11 @@ int
2970nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner) 3039nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
2971{ 3040{
2972 clientid_t *clid = &rlockowner->rl_clientid; 3041 clientid_t *clid = &rlockowner->rl_clientid;
2973 struct nfs4_stateowner *local = NULL; 3042 struct nfs4_stateowner *sop;
3043 struct nfs4_stateid *stp;
2974 struct xdr_netobj *owner = &rlockowner->rl_owner; 3044 struct xdr_netobj *owner = &rlockowner->rl_owner;
3045 struct list_head matches;
3046 int i;
2975 int status; 3047 int status;
2976 3048
2977 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", 3049 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
@@ -2987,22 +3059,32 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
2987 3059
2988 nfs4_lock_state(); 3060 nfs4_lock_state();
2989 3061
2990 status = nfs_ok; 3062 status = nfserr_locks_held;
2991 local = find_lockstateowner(owner, clid); 3063 /* XXX: we're doing a linear search through all the lockowners.
2992 if (local) { 3064 * Yipes! For now we'll just hope clients aren't really using
2993 struct nfs4_stateid *stp; 3065 * release_lockowner much, but eventually we have to fix these
2994 3066 * data structures. */
2995 /* check for any locks held by any stateid 3067 INIT_LIST_HEAD(&matches);
2996 * associated with the (lock) stateowner */ 3068 for (i = 0; i < LOCK_HASH_SIZE; i++) {
2997 status = nfserr_locks_held; 3069 list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) {
2998 list_for_each_entry(stp, &local->so_perfilestate, 3070 if (!cmp_owner_str(sop, owner, clid))
2999 st_perfilestate) { 3071 continue;
3000 if (check_for_locks(stp->st_vfs_file, local)) 3072 list_for_each_entry(stp, &sop->so_stateids,
3001 goto out; 3073 st_perstateowner) {
3074 if (check_for_locks(stp->st_vfs_file, sop))
3075 goto out;
3076 /* Note: so_perclient unused for lockowners,
3077 * so it's OK to fool with here. */
3078 list_add(&sop->so_perclient, &matches);
3079 }
3002 } 3080 }
3003 /* no locks held by (lock) stateowner */ 3081 }
3004 status = nfs_ok; 3082 /* Clients probably won't expect us to return with some (but not all)
3005 release_stateowner(local); 3083 * of the lockowner state released; so don't release any until all
3084 * have been checked. */
3085 status = nfs_ok;
3086 list_for_each_entry(sop, &matches, so_perclient) {
3087 release_stateowner(sop);
3006 } 3088 }
3007out: 3089out:
3008 nfs4_unlock_state(); 3090 nfs4_unlock_state();
@@ -3010,39 +3092,38 @@ out:
3010} 3092}
3011 3093
3012static inline struct nfs4_client_reclaim * 3094static inline struct nfs4_client_reclaim *
3013alloc_reclaim(int namelen) 3095alloc_reclaim(void)
3014{ 3096{
3015 struct nfs4_client_reclaim *crp = NULL; 3097 return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
3098}
3016 3099
3017 crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL); 3100int
3018 if (!crp) 3101nfs4_has_reclaimed_state(const char *name)
3019 return NULL; 3102{
3020 crp->cr_name.data = kmalloc(namelen, GFP_KERNEL); 3103 unsigned int strhashval = clientstr_hashval(name);
3021 if (!crp->cr_name.data) { 3104 struct nfs4_client *clp;
3022 kfree(crp); 3105
3023 return NULL; 3106 clp = find_confirmed_client_by_str(name, strhashval);
3024 } 3107 return clp ? 1 : 0;
3025 return crp;
3026} 3108}
3027 3109
3028/* 3110/*
3029 * failure => all reset bets are off, nfserr_no_grace... 3111 * failure => all reset bets are off, nfserr_no_grace...
3030 */ 3112 */
3031static int 3113int
3032nfs4_client_to_reclaim(char *name, int namlen) 3114nfs4_client_to_reclaim(const char *name)
3033{ 3115{
3034 unsigned int strhashval; 3116 unsigned int strhashval;
3035 struct nfs4_client_reclaim *crp = NULL; 3117 struct nfs4_client_reclaim *crp = NULL;
3036 3118
3037 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name); 3119 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
3038 crp = alloc_reclaim(namlen); 3120 crp = alloc_reclaim();
3039 if (!crp) 3121 if (!crp)
3040 return 0; 3122 return 0;
3041 strhashval = clientstr_hashval(name, namlen); 3123 strhashval = clientstr_hashval(name);
3042 INIT_LIST_HEAD(&crp->cr_strhash); 3124 INIT_LIST_HEAD(&crp->cr_strhash);
3043 list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]); 3125 list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
3044 memcpy(crp->cr_name.data, name, namlen); 3126 memcpy(crp->cr_recdir, name, HEXDIR_LEN);
3045 crp->cr_name.len = namlen;
3046 reclaim_str_hashtbl_size++; 3127 reclaim_str_hashtbl_size++;
3047 return 1; 3128 return 1;
3048} 3129}
@@ -3053,13 +3134,11 @@ nfs4_release_reclaim(void)
3053 struct nfs4_client_reclaim *crp = NULL; 3134 struct nfs4_client_reclaim *crp = NULL;
3054 int i; 3135 int i;
3055 3136
3056 BUG_ON(!nfs4_reclaim_init);
3057 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 3137 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3058 while (!list_empty(&reclaim_str_hashtbl[i])) { 3138 while (!list_empty(&reclaim_str_hashtbl[i])) {
3059 crp = list_entry(reclaim_str_hashtbl[i].next, 3139 crp = list_entry(reclaim_str_hashtbl[i].next,
3060 struct nfs4_client_reclaim, cr_strhash); 3140 struct nfs4_client_reclaim, cr_strhash);
3061 list_del(&crp->cr_strhash); 3141 list_del(&crp->cr_strhash);
3062 kfree(crp->cr_name.data);
3063 kfree(crp); 3142 kfree(crp);
3064 reclaim_str_hashtbl_size--; 3143 reclaim_str_hashtbl_size--;
3065 } 3144 }
@@ -3069,7 +3148,7 @@ nfs4_release_reclaim(void)
3069 3148
3070/* 3149/*
3071 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ 3150 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
3072struct nfs4_client_reclaim * 3151static struct nfs4_client_reclaim *
3073nfs4_find_reclaim_client(clientid_t *clid) 3152nfs4_find_reclaim_client(clientid_t *clid)
3074{ 3153{
3075 unsigned int strhashval; 3154 unsigned int strhashval;
@@ -3082,13 +3161,14 @@ nfs4_find_reclaim_client(clientid_t *clid)
3082 if (clp == NULL) 3161 if (clp == NULL)
3083 return NULL; 3162 return NULL;
3084 3163
3085 dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n", 3164 dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
3086 clp->cl_name.len, clp->cl_name.data); 3165 clp->cl_name.len, clp->cl_name.data,
3166 clp->cl_recdir);
3087 3167
3088 /* find clp->cl_name in reclaim_str_hashtbl */ 3168 /* find clp->cl_name in reclaim_str_hashtbl */
3089 strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len); 3169 strhashval = clientstr_hashval(clp->cl_recdir);
3090 list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) { 3170 list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
3091 if (cmp_name(&crp->cr_name, &clp->cl_name)) { 3171 if (same_name(crp->cr_recdir, clp->cl_recdir)) {
3092 return crp; 3172 return crp;
3093 } 3173 }
3094 } 3174 }
@@ -3101,30 +3181,16 @@ nfs4_find_reclaim_client(clientid_t *clid)
3101int 3181int
3102nfs4_check_open_reclaim(clientid_t *clid) 3182nfs4_check_open_reclaim(clientid_t *clid)
3103{ 3183{
3104 struct nfs4_client_reclaim *crp; 3184 return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
3105
3106 if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
3107 return nfserr_reclaim_bad;
3108 return nfs_ok;
3109} 3185}
3110 3186
3187/* initialization to perform at module load time: */
3111 3188
3112/* 3189void
3113 * Start and stop routines 3190nfs4_state_init(void)
3114 */
3115
3116static void
3117__nfs4_state_init(void)
3118{ 3191{
3119 int i; 3192 int i;
3120 time_t grace_time;
3121 3193
3122 if (!nfs4_reclaim_init) {
3123 for (i = 0; i < CLIENT_HASH_SIZE; i++)
3124 INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
3125 reclaim_str_hashtbl_size = 0;
3126 nfs4_reclaim_init = 1;
3127 }
3128 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 3194 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3129 INIT_LIST_HEAD(&conf_id_hashtbl[i]); 3195 INIT_LIST_HEAD(&conf_id_hashtbl[i]);
3130 INIT_LIST_HEAD(&conf_str_hashtbl[i]); 3196 INIT_LIST_HEAD(&conf_str_hashtbl[i]);
@@ -3146,26 +3212,46 @@ __nfs4_state_init(void)
3146 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]); 3212 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
3147 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]); 3213 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
3148 } 3214 }
3149 memset(&zerostateid, 0, sizeof(stateid_t));
3150 memset(&onestateid, ~0, sizeof(stateid_t)); 3215 memset(&onestateid, ~0, sizeof(stateid_t));
3151
3152 INIT_LIST_HEAD(&close_lru); 3216 INIT_LIST_HEAD(&close_lru);
3153 INIT_LIST_HEAD(&client_lru); 3217 INIT_LIST_HEAD(&client_lru);
3154 INIT_LIST_HEAD(&del_recall_lru); 3218 INIT_LIST_HEAD(&del_recall_lru);
3155 spin_lock_init(&recall_lock); 3219 for (i = 0; i < CLIENT_HASH_SIZE; i++)
3220 INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
3221 reclaim_str_hashtbl_size = 0;
3222}
3223
3224static void
3225nfsd4_load_reboot_recovery_data(void)
3226{
3227 int status;
3228
3229 nfs4_lock_state();
3230 nfsd4_init_recdir(user_recovery_dirname);
3231 status = nfsd4_recdir_load();
3232 nfs4_unlock_state();
3233 if (status)
3234 printk("NFSD: Failure reading reboot recovery data\n");
3235}
3236
3237/* initialization to perform when the nfsd service is started: */
3238
3239static void
3240__nfs4_state_start(void)
3241{
3242 time_t grace_time;
3243
3156 boot_time = get_seconds(); 3244 boot_time = get_seconds();
3157 grace_time = max(old_lease_time, lease_time); 3245 grace_time = max(user_lease_time, lease_time);
3158 if (reclaim_str_hashtbl_size == 0) 3246 lease_time = user_lease_time;
3159 grace_time = 0; 3247 in_grace = 1;
3160 if (grace_time) 3248 printk("NFSD: starting %ld-second grace period\n", grace_time);
3161 printk("NFSD: starting %ld-second grace period\n", grace_time); 3249 laundry_wq = create_singlethread_workqueue("nfsd4");
3162 grace_end = boot_time + grace_time; 3250 queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
3163 INIT_WORK(&laundromat_work,laundromat_main, NULL);
3164 schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
3165} 3251}
3166 3252
3167int 3253int
3168nfs4_state_init(void) 3254nfs4_state_start(void)
3169{ 3255{
3170 int status; 3256 int status;
3171 3257
@@ -3174,7 +3260,8 @@ nfs4_state_init(void)
3174 status = nfsd4_init_slabs(); 3260 status = nfsd4_init_slabs();
3175 if (status) 3261 if (status)
3176 return status; 3262 return status;
3177 __nfs4_state_init(); 3263 nfsd4_load_reboot_recovery_data();
3264 __nfs4_state_start();
3178 nfs4_init = 1; 3265 nfs4_init = 1;
3179 return 0; 3266 return 0;
3180} 3267}
@@ -3182,14 +3269,7 @@ nfs4_state_init(void)
3182int 3269int
3183nfs4_in_grace(void) 3270nfs4_in_grace(void)
3184{ 3271{
3185 return get_seconds() < grace_end; 3272 return in_grace;
3186}
3187
3188void
3189set_no_grace(void)
3190{
3191 printk("NFSD: ERROR in reboot recovery. State reclaims will fail.\n");
3192 grace_end = get_seconds();
3193} 3273}
3194 3274
3195time_t 3275time_t
@@ -3236,21 +3316,11 @@ __nfs4_state_shutdown(void)
3236 unhash_delegation(dp); 3316 unhash_delegation(dp);
3237 } 3317 }
3238 3318
3239 release_all_files();
3240 cancel_delayed_work(&laundromat_work); 3319 cancel_delayed_work(&laundromat_work);
3241 flush_scheduled_work(); 3320 flush_workqueue(laundry_wq);
3321 destroy_workqueue(laundry_wq);
3322 nfsd4_shutdown_recdir();
3242 nfs4_init = 0; 3323 nfs4_init = 0;
3243 dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
3244 list_add_perfile, list_del_perfile);
3245 dprintk("NFSD: add_perclient %d del_perclient %d\n",
3246 add_perclient, del_perclient);
3247 dprintk("NFSD: alloc_file %d free_file %d\n",
3248 alloc_file, free_file);
3249 dprintk("NFSD: vfsopen %d vfsclose %d\n",
3250 vfsopen, vfsclose);
3251 dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
3252 alloc_delegation, free_delegation);
3253
3254} 3324}
3255 3325
3256void 3326void
@@ -3263,56 +3333,48 @@ nfs4_state_shutdown(void)
3263 nfs4_unlock_state(); 3333 nfs4_unlock_state();
3264} 3334}
3265 3335
3336static void
3337nfs4_set_recdir(char *recdir)
3338{
3339 nfs4_lock_state();
3340 strcpy(user_recovery_dirname, recdir);
3341 nfs4_unlock_state();
3342}
3343
3344/*
3345 * Change the NFSv4 recovery directory to recdir.
3346 */
3347int
3348nfs4_reset_recoverydir(char *recdir)
3349{
3350 int status;
3351 struct nameidata nd;
3352
3353 status = path_lookup(recdir, LOOKUP_FOLLOW, &nd);
3354 if (status)
3355 return status;
3356 status = -ENOTDIR;
3357 if (S_ISDIR(nd.dentry->d_inode->i_mode)) {
3358 nfs4_set_recdir(recdir);
3359 status = 0;
3360 }
3361 path_release(&nd);
3362 return status;
3363}
3364
3266/* 3365/*
3267 * Called when leasetime is changed. 3366 * Called when leasetime is changed.
3268 * 3367 *
3269 * if nfsd is not started, simply set the global lease. 3368 * The only way the protocol gives us to handle on-the-fly lease changes is to
3270 * 3369 * simulate a reboot. Instead of doing that, we just wait till the next time
3271 * if nfsd(s) are running, lease change requires nfsv4 state to be reset. 3370 * we start to register any changes in lease time. If the administrator
3272 * e.g: boot_time is reset, existing nfs4_client structs are 3371 * really wants to change the lease time *now*, they can go ahead and bring
3273 * used to fill reclaim_str_hashtbl, then all state (except for the 3372 * nfsd down and then back up again after changing the lease time.
3274 * reclaim_str_hashtbl) is re-initialized.
3275 *
3276 * if the old lease time is greater than the new lease time, the grace
3277 * period needs to be set to the old lease time to allow clients to reclaim
3278 * their state. XXX - we may want to set the grace period == lease time
3279 * after an initial grace period == old lease time
3280 *
3281 * if an error occurs in this process, the new lease is set, but the server
3282 * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
3283 * which means OPEN/LOCK/READ/WRITE will fail during grace period.
3284 *
3285 * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
3286 * OPEN and LOCK reclaims.
3287 */ 3373 */
3288void 3374void
3289nfs4_reset_lease(time_t leasetime) 3375nfs4_reset_lease(time_t leasetime)
3290{ 3376{
3291 struct nfs4_client *clp; 3377 lock_kernel();
3292 int i; 3378 user_lease_time = leasetime;
3293 3379 unlock_kernel();
3294 printk("NFSD: New leasetime %ld\n",leasetime);
3295 if (!nfs4_init)
3296 return;
3297 nfs4_lock_state();
3298 old_lease_time = lease_time;
3299 lease_time = leasetime;
3300
3301 nfs4_release_reclaim();
3302
3303 /* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
3304 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3305 list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
3306 if (!nfs4_client_to_reclaim(clp->cl_name.data,
3307 clp->cl_name.len)) {
3308 nfs4_release_reclaim();
3309 goto init_state;
3310 }
3311 }
3312 }
3313init_state:
3314 __nfs4_state_shutdown();
3315 __nfs4_state_init();
3316 nfs4_unlock_state();
3317} 3380}
3318
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 36a058a112..91fb171d2a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -136,7 +136,7 @@ xdr_error: \
136 } \ 136 } \
137} while (0) 137} while (0)
138 138
139u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) 139static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
140{ 140{
141 /* We want more bytes than seem to be available. 141 /* We want more bytes than seem to be available.
142 * Maybe we need a new page, maybe we have just run out 142 * Maybe we need a new page, maybe we have just run out
@@ -190,7 +190,7 @@ defer_free(struct nfsd4_compoundargs *argp,
190 return 0; 190 return 0;
191} 191}
192 192
193char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes) 193static char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
194{ 194{
195 void *new = NULL; 195 void *new = NULL;
196 if (p == argp->tmp) { 196 if (p == argp->tmp) {
@@ -1366,7 +1366,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1366 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { 1366 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
1367 if ((buflen -= 4) < 0) 1367 if ((buflen -= 4) < 0)
1368 goto out_resource; 1368 goto out_resource;
1369 WRITE32( NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME ); 1369 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
1370 WRITE32(NFS4_FH_VOLATILE_ANY);
1371 else
1372 WRITE32(NFS4_FH_VOLATILE_ANY|NFS4_FH_VOL_RENAME);
1370 } 1373 }
1371 if (bmval0 & FATTR4_WORD0_CHANGE) { 1374 if (bmval0 & FATTR4_WORD0_CHANGE) {
1372 /* 1375 /*
@@ -1969,7 +1972,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open
1969 case NFS4_OPEN_DELEGATE_READ: 1972 case NFS4_OPEN_DELEGATE_READ:
1970 RESERVE_SPACE(20 + sizeof(stateid_t)); 1973 RESERVE_SPACE(20 + sizeof(stateid_t));
1971 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t)); 1974 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
1972 WRITE32(0); 1975 WRITE32(open->op_recall);
1973 1976
1974 /* 1977 /*
1975 * TODO: ACE's in delegations 1978 * TODO: ACE's in delegations
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 161afdcb8f..841c562991 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -51,6 +51,7 @@ enum {
51 NFSD_Fh, 51 NFSD_Fh,
52 NFSD_Threads, 52 NFSD_Threads,
53 NFSD_Leasetime, 53 NFSD_Leasetime,
54 NFSD_RecoveryDir,
54}; 55};
55 56
56/* 57/*
@@ -66,6 +67,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size);
66static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 67static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
67static ssize_t write_threads(struct file *file, char *buf, size_t size); 68static ssize_t write_threads(struct file *file, char *buf, size_t size);
68static ssize_t write_leasetime(struct file *file, char *buf, size_t size); 69static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
70static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
69 71
70static ssize_t (*write_op[])(struct file *, char *, size_t) = { 72static ssize_t (*write_op[])(struct file *, char *, size_t) = {
71 [NFSD_Svc] = write_svc, 73 [NFSD_Svc] = write_svc,
@@ -78,6 +80,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
78 [NFSD_Fh] = write_filehandle, 80 [NFSD_Fh] = write_filehandle,
79 [NFSD_Threads] = write_threads, 81 [NFSD_Threads] = write_threads,
80 [NFSD_Leasetime] = write_leasetime, 82 [NFSD_Leasetime] = write_leasetime,
83 [NFSD_RecoveryDir] = write_recoverydir,
81}; 84};
82 85
83static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) 86static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
@@ -349,6 +352,25 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
349 return strlen(buf); 352 return strlen(buf);
350} 353}
351 354
355static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
356{
357 char *mesg = buf;
358 char *recdir;
359 int len, status;
360
361 if (size > PATH_MAX || buf[size-1] != '\n')
362 return -EINVAL;
363 buf[size-1] = 0;
364
365 recdir = mesg;
366 len = qword_get(&mesg, recdir, size);
367 if (len <= 0)
368 return -EINVAL;
369
370 status = nfs4_reset_recoverydir(recdir);
371 return strlen(buf);
372}
373
352/*----------------------------------------------------------------------------*/ 374/*----------------------------------------------------------------------------*/
353/* 375/*
354 * populating the filesystem. 376 * populating the filesystem.
@@ -369,6 +391,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
369 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, 391 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
370#ifdef CONFIG_NFSD_V4 392#ifdef CONFIG_NFSD_V4
371 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, 393 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
394 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
372#endif 395#endif
373 /* last one */ {""} 396 /* last one */ {""}
374 }; 397 };
@@ -397,9 +420,8 @@ static int __init init_nfsd(void)
397 nfsd_cache_init(); /* RPC reply cache */ 420 nfsd_cache_init(); /* RPC reply cache */
398 nfsd_export_init(); /* Exports table */ 421 nfsd_export_init(); /* Exports table */
399 nfsd_lockd_init(); /* lockd->nfsd callbacks */ 422 nfsd_lockd_init(); /* lockd->nfsd callbacks */
400#ifdef CONFIG_NFSD_V4 423 nfs4_state_init(); /* NFSv4 locking state */
401 nfsd_idmap_init(); /* Name to ID mapping */ 424 nfsd_idmap_init(); /* Name to ID mapping */
402#endif /* CONFIG_NFSD_V4 */
403 if (proc_mkdir("fs/nfs", NULL)) { 425 if (proc_mkdir("fs/nfs", NULL)) {
404 struct proc_dir_entry *entry; 426 struct proc_dir_entry *entry;
405 entry = create_proc_entry("fs/nfs/exports", 0, NULL); 427 entry = create_proc_entry("fs/nfs/exports", 0, NULL);
@@ -426,9 +448,7 @@ static void __exit exit_nfsd(void)
426 remove_proc_entry("fs/nfs", NULL); 448 remove_proc_entry("fs/nfs", NULL);
427 nfsd_stat_shutdown(); 449 nfsd_stat_shutdown();
428 nfsd_lockd_shutdown(); 450 nfsd_lockd_shutdown();
429#ifdef CONFIG_NFSD_V4
430 nfsd_idmap_shutdown(); 451 nfsd_idmap_shutdown();
431#endif /* CONFIG_NFSD_V4 */
432 unregister_filesystem(&nfsd_fs_type); 452 unregister_filesystem(&nfsd_fs_type);
433} 453}
434 454
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 904df604e8..07b9a065e9 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -95,7 +95,7 @@ nfsd_svc(unsigned short port, int nrservs)
95 error = nfsd_racache_init(2*nrservs); 95 error = nfsd_racache_init(2*nrservs);
96 if (error<0) 96 if (error<0)
97 goto out; 97 goto out;
98 error = nfs4_state_init(); 98 error = nfs4_state_start();
99 if (error<0) 99 if (error<0)
100 goto out; 100 goto out;
101 if (!nfsd_serv) { 101 if (!nfsd_serv) {
diff --git a/fs/open.c b/fs/open.c
index 8ec63f7359..3f4a4286fd 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -808,7 +808,9 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
808 808
809 /* NB: we're sure to have correct a_ops only after f_op->open */ 809 /* NB: we're sure to have correct a_ops only after f_op->open */
810 if (f->f_flags & O_DIRECT) { 810 if (f->f_flags & O_DIRECT) {
811 if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO) { 811 if (!f->f_mapping->a_ops ||
812 ((!f->f_mapping->a_ops->direct_IO) &&
813 (!f->f_mapping->a_ops->get_xip_page))) {
812 fput(f); 814 fput(f);
813 f = ERR_PTR(-EINVAL); 815 f = ERR_PTR(-EINVAL);
814 } 816 }
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 2230afff18..12e9120954 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -201,7 +201,7 @@ static int reiserfs_allocate_blocks_for_region(
201 /* If we came here, it means we absolutely need to open a transaction, 201 /* If we came here, it means we absolutely need to open a transaction,
202 since we need to allocate some blocks */ 202 since we need to allocate some blocks */
203 reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that. 203 reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that.
204 res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); // Wish I know if this number enough 204 res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb)); // Wish I know if this number enough
205 if (res) 205 if (res)
206 goto error_exit; 206 goto error_exit;
207 reiserfs_update_inode_transaction(inode) ; 207 reiserfs_update_inode_transaction(inode) ;
@@ -576,7 +576,7 @@ error_exit:
576 int err; 576 int err;
577 // update any changes we made to blk count 577 // update any changes we made to blk count
578 reiserfs_update_sd(th, inode); 578 reiserfs_update_sd(th, inode);
579 err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); 579 err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb));
580 if (err) 580 if (err)
581 res = err; 581 res = err;
582 } 582 }
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 2711dff1b7..0d5817f819 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -28,7 +28,7 @@ static int reiserfs_prepare_write(struct file *f, struct page *page,
28void reiserfs_delete_inode (struct inode * inode) 28void reiserfs_delete_inode (struct inode * inode)
29{ 29{
30 /* We need blocks for transaction + (user+group) quota update (possibly delete) */ 30 /* We need blocks for transaction + (user+group) quota update (possibly delete) */
31 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS; 31 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
32 struct reiserfs_transaction_handle th ; 32 struct reiserfs_transaction_handle th ;
33 33
34 reiserfs_write_lock(inode->i_sb); 34 reiserfs_write_lock(inode->i_sb);
@@ -591,7 +591,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
591 XXX in practically impossible worst case direct2indirect() 591 XXX in practically impossible worst case direct2indirect()
592 can incur (much) more than 3 balancings. 592 can incur (much) more than 3 balancings.
593 quota update for user, group */ 593 quota update for user, group */
594 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS; 594 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
595 int version; 595 int version;
596 int dangle = 1; 596 int dangle = 1;
597 loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ; 597 loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
@@ -2796,12 +2796,15 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
2796 2796
2797 if (!error) { 2797 if (!error) {
2798 struct reiserfs_transaction_handle th; 2798 struct reiserfs_transaction_handle th;
2799 int jbegin_count = 2*(REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb)+REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb))+2;
2799 2800
2800 /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ 2801 /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
2801 journal_begin(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2); 2802 error = journal_begin(&th, inode->i_sb, jbegin_count);
2803 if (error)
2804 goto out;
2802 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; 2805 error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
2803 if (error) { 2806 if (error) {
2804 journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2); 2807 journal_end(&th, inode->i_sb, jbegin_count);
2805 goto out; 2808 goto out;
2806 } 2809 }
2807 /* Update corresponding info in inode so that everything is in 2810 /* Update corresponding info in inode so that everything is in
@@ -2811,7 +2814,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
2811 if (attr->ia_valid & ATTR_GID) 2814 if (attr->ia_valid & ATTR_GID)
2812 inode->i_gid = attr->ia_gid; 2815 inode->i_gid = attr->ia_gid;
2813 mark_inode_dirty(inode); 2816 mark_inode_dirty(inode);
2814 journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2); 2817 error = journal_end(&th, inode->i_sb, jbegin_count);
2815 } 2818 }
2816 } 2819 }
2817 if (!error) 2820 if (!error)
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 3072cfdee9..7b87707acc 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2631,6 +2631,8 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, struct sup
2631 int retval; 2631 int retval;
2632 2632
2633 reiserfs_check_lock_depth(p_s_sb, "journal_begin") ; 2633 reiserfs_check_lock_depth(p_s_sb, "journal_begin") ;
2634 if (nblocks > journal->j_trans_max)
2635 BUG();
2634 2636
2635 PROC_INFO_INC( p_s_sb, journal.journal_being ); 2637 PROC_INFO_INC( p_s_sb, journal.journal_being );
2636 /* set here for journal_join */ 2638 /* set here for journal_join */
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 7d4dc5f5aa..4a333255f2 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -586,7 +586,7 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode,
586 int retval; 586 int retval;
587 struct inode * inode; 587 struct inode * inode;
588 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 588 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
589 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 589 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
590 struct reiserfs_transaction_handle th ; 590 struct reiserfs_transaction_handle th ;
591 int locked; 591 int locked;
592 592
@@ -653,7 +653,7 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode,
653 struct inode * inode; 653 struct inode * inode;
654 struct reiserfs_transaction_handle th ; 654 struct reiserfs_transaction_handle th ;
655 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 655 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
656 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 656 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
657 int locked; 657 int locked;
658 658
659 if (!new_valid_dev(rdev)) 659 if (!new_valid_dev(rdev))
@@ -727,7 +727,7 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
727 struct inode * inode; 727 struct inode * inode;
728 struct reiserfs_transaction_handle th ; 728 struct reiserfs_transaction_handle th ;
729 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 729 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
730 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 730 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
731 int locked; 731 int locked;
732 732
733#ifdef DISPLACE_NEW_PACKING_LOCALITIES 733#ifdef DISPLACE_NEW_PACKING_LOCALITIES
@@ -829,8 +829,10 @@ static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry)
829 829
830 830
831 /* we will be doing 2 balancings and update 2 stat data, we change quotas 831 /* we will be doing 2 balancings and update 2 stat data, we change quotas
832 * of the owner of the directory and of the owner of the parent directory */ 832 * of the owner of the directory and of the owner of the parent directory.
833 jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 833 * The quota structure is possibly deleted only on last iput => outside
834 * of this transaction */
835 jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
834 836
835 reiserfs_write_lock(dir->i_sb); 837 reiserfs_write_lock(dir->i_sb);
836 retval = journal_begin(&th, dir->i_sb, jbegin_count) ; 838 retval = journal_begin(&th, dir->i_sb, jbegin_count) ;
@@ -913,9 +915,10 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
913 inode = dentry->d_inode; 915 inode = dentry->d_inode;
914 916
915 /* in this transaction we can be doing at max two balancings and update 917 /* in this transaction we can be doing at max two balancings and update
916 two stat datas, we change quotas of the owner of the directory and of 918 * two stat datas, we change quotas of the owner of the directory and of
917 the owner of the parent directory */ 919 * the owner of the parent directory. The quota structure is possibly
918 jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 920 * deleted only on iput => outside of this transaction */
921 jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
919 922
920 reiserfs_write_lock(dir->i_sb); 923 reiserfs_write_lock(dir->i_sb);
921 retval = journal_begin(&th, dir->i_sb, jbegin_count) ; 924 retval = journal_begin(&th, dir->i_sb, jbegin_count) ;
@@ -1000,7 +1003,7 @@ static int reiserfs_symlink (struct inode * parent_dir,
1000 struct reiserfs_transaction_handle th ; 1003 struct reiserfs_transaction_handle th ;
1001 int mode = S_IFLNK | S_IRWXUGO; 1004 int mode = S_IFLNK | S_IRWXUGO;
1002 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ 1005 /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
1003 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS); 1006 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
1004 1007
1005 if (!(inode = new_inode(parent_dir->i_sb))) { 1008 if (!(inode = new_inode(parent_dir->i_sb))) {
1006 return -ENOMEM ; 1009 return -ENOMEM ;
@@ -1076,7 +1079,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
1076 struct inode *inode = old_dentry->d_inode; 1079 struct inode *inode = old_dentry->d_inode;
1077 struct reiserfs_transaction_handle th ; 1080 struct reiserfs_transaction_handle th ;
1078 /* We need blocks for transaction + update of quotas for the owners of the directory */ 1081 /* We need blocks for transaction + update of quotas for the owners of the directory */
1079 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS; 1082 int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
1080 1083
1081 reiserfs_write_lock(dir->i_sb); 1084 reiserfs_write_lock(dir->i_sb);
1082 if (inode->i_nlink >= REISERFS_LINK_MAX) { 1085 if (inode->i_nlink >= REISERFS_LINK_MAX) {
@@ -1196,7 +1199,7 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
1196 pointed initially and (5) maybe block containing ".." of 1199 pointed initially and (5) maybe block containing ".." of
1197 renamed directory 1200 renamed directory
1198 quota updates: two parent directories */ 1201 quota updates: two parent directories */
1199 jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS; 1202 jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
1200 1203
1201 old_inode = old_dentry->d_inode; 1204 old_inode = old_dentry->d_inode;
1202 new_dentry_inode = new_dentry->d_inode; 1205 new_dentry_inode = new_dentry->d_inode;
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index c47f8fd31a..63158491e1 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -223,7 +223,7 @@ extern struct tree_balance * cur_tb;
223const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}}; 223const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}};
224 224
225/* Maximal possible key. It is never in the tree. */ 225/* Maximal possible key. It is never in the tree. */
226const struct reiserfs_key MAX_KEY = { 226static const struct reiserfs_key MAX_KEY = {
227 __constant_cpu_to_le32(0xffffffff), 227 __constant_cpu_to_le32(0xffffffff),
228 __constant_cpu_to_le32(0xffffffff), 228 __constant_cpu_to_le32(0xffffffff),
229 {{__constant_cpu_to_le32(0xffffffff), 229 {{__constant_cpu_to_le32(0xffffffff),
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index aae0779ed5..660aefca1f 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -866,8 +866,9 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
866 {"jdev", .arg_required = 'j', .values = NULL}, 866 {"jdev", .arg_required = 'j', .values = NULL},
867 {"nolargeio", .arg_required = 'w', .values = NULL}, 867 {"nolargeio", .arg_required = 'w', .values = NULL},
868 {"commit", .arg_required = 'c', .values = NULL}, 868 {"commit", .arg_required = 'c', .values = NULL},
869 {"usrquota",}, 869 {"usrquota", .setmask = 1<<REISERFS_QUOTA},
870 {"grpquota",}, 870 {"grpquota", .setmask = 1<<REISERFS_QUOTA},
871 {"noquota", .clrmask = 1<<REISERFS_QUOTA},
871 {"errors", .arg_required = 'e', .values = error_actions}, 872 {"errors", .arg_required = 'e', .values = error_actions},
872 {"usrjquota", .arg_required = 'u'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL}, 873 {"usrjquota", .arg_required = 'u'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL},
873 {"grpjquota", .arg_required = 'g'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL}, 874 {"grpjquota", .arg_required = 'g'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL},
@@ -964,6 +965,7 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
964 return 0; 965 return 0;
965 } 966 }
966 strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg); 967 strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
968 *mount_options |= 1<<REISERFS_QUOTA;
967 } 969 }
968 else { 970 else {
969 if (REISERFS_SB(s)->s_qf_names[qtype]) { 971 if (REISERFS_SB(s)->s_qf_names[qtype]) {
@@ -995,7 +997,13 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
995 reiserfs_warning(s, "reiserfs_parse_options: journalled quota format not specified."); 997 reiserfs_warning(s, "reiserfs_parse_options: journalled quota format not specified.");
996 return 0; 998 return 0;
997 } 999 }
1000 /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
1001 if (!(*mount_options & (1<<REISERFS_QUOTA)) && sb_any_quota_enabled(s)) {
1002 reiserfs_warning(s, "reiserfs_parse_options: quota options must be present when quota is turned on.");
1003 return 0;
1004 }
998#endif 1005#endif
1006
999 return 1; 1007 return 1;
1000} 1008}
1001 1009
@@ -1105,6 +1113,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
1105 safe_mask |= 1 << REISERFS_ERROR_RO; 1113 safe_mask |= 1 << REISERFS_ERROR_RO;
1106 safe_mask |= 1 << REISERFS_ERROR_CONTINUE; 1114 safe_mask |= 1 << REISERFS_ERROR_CONTINUE;
1107 safe_mask |= 1 << REISERFS_ERROR_PANIC; 1115 safe_mask |= 1 << REISERFS_ERROR_PANIC;
1116 safe_mask |= 1 << REISERFS_QUOTA;
1108 1117
1109 /* Update the bitmask, taking care to keep 1118 /* Update the bitmask, taking care to keep
1110 * the bits we're not allowed to change here */ 1119 * the bits we're not allowed to change here */
@@ -1841,13 +1850,18 @@ static int reiserfs_statfs (struct super_block * s, struct kstatfs * buf)
1841static int reiserfs_dquot_initialize(struct inode *inode, int type) 1850static int reiserfs_dquot_initialize(struct inode *inode, int type)
1842{ 1851{
1843 struct reiserfs_transaction_handle th; 1852 struct reiserfs_transaction_handle th;
1844 int ret; 1853 int ret, err;
1845 1854
1846 /* We may create quota structure so we need to reserve enough blocks */ 1855 /* We may create quota structure so we need to reserve enough blocks */
1847 reiserfs_write_lock(inode->i_sb); 1856 reiserfs_write_lock(inode->i_sb);
1848 journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS); 1857 ret = journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
1858 if (ret)
1859 goto out;
1849 ret = dquot_initialize(inode, type); 1860 ret = dquot_initialize(inode, type);
1850 journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS); 1861 err = journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
1862 if (!ret && err)
1863 ret = err;
1864out:
1851 reiserfs_write_unlock(inode->i_sb); 1865 reiserfs_write_unlock(inode->i_sb);
1852 return ret; 1866 return ret;
1853} 1867}
@@ -1855,13 +1869,18 @@ static int reiserfs_dquot_initialize(struct inode *inode, int type)
1855static int reiserfs_dquot_drop(struct inode *inode) 1869static int reiserfs_dquot_drop(struct inode *inode)
1856{ 1870{
1857 struct reiserfs_transaction_handle th; 1871 struct reiserfs_transaction_handle th;
1858 int ret; 1872 int ret, err;
1859 1873
1860 /* We may delete quota structure so we need to reserve enough blocks */ 1874 /* We may delete quota structure so we need to reserve enough blocks */
1861 reiserfs_write_lock(inode->i_sb); 1875 reiserfs_write_lock(inode->i_sb);
1862 journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS); 1876 ret = journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
1877 if (ret)
1878 goto out;
1863 ret = dquot_drop(inode); 1879 ret = dquot_drop(inode);
1864 journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS); 1880 err = journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
1881 if (!ret && err)
1882 ret = err;
1883out:
1865 reiserfs_write_unlock(inode->i_sb); 1884 reiserfs_write_unlock(inode->i_sb);
1866 return ret; 1885 return ret;
1867} 1886}
@@ -1869,12 +1888,17 @@ static int reiserfs_dquot_drop(struct inode *inode)
1869static int reiserfs_write_dquot(struct dquot *dquot) 1888static int reiserfs_write_dquot(struct dquot *dquot)
1870{ 1889{
1871 struct reiserfs_transaction_handle th; 1890 struct reiserfs_transaction_handle th;
1872 int ret; 1891 int ret, err;
1873 1892
1874 reiserfs_write_lock(dquot->dq_sb); 1893 reiserfs_write_lock(dquot->dq_sb);
1875 journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS); 1894 ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
1895 if (ret)
1896 goto out;
1876 ret = dquot_commit(dquot); 1897 ret = dquot_commit(dquot);
1877 journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS); 1898 err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
1899 if (!ret && err)
1900 ret = err;
1901out:
1878 reiserfs_write_unlock(dquot->dq_sb); 1902 reiserfs_write_unlock(dquot->dq_sb);
1879 return ret; 1903 return ret;
1880} 1904}
@@ -1882,12 +1906,17 @@ static int reiserfs_write_dquot(struct dquot *dquot)
1882static int reiserfs_acquire_dquot(struct dquot *dquot) 1906static int reiserfs_acquire_dquot(struct dquot *dquot)
1883{ 1907{
1884 struct reiserfs_transaction_handle th; 1908 struct reiserfs_transaction_handle th;
1885 int ret; 1909 int ret, err;
1886 1910
1887 reiserfs_write_lock(dquot->dq_sb); 1911 reiserfs_write_lock(dquot->dq_sb);
1888 journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS); 1912 ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
1913 if (ret)
1914 goto out;
1889 ret = dquot_acquire(dquot); 1915 ret = dquot_acquire(dquot);
1890 journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS); 1916 err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
1917 if (!ret && err)
1918 ret = err;
1919out:
1891 reiserfs_write_unlock(dquot->dq_sb); 1920 reiserfs_write_unlock(dquot->dq_sb);
1892 return ret; 1921 return ret;
1893} 1922}
@@ -1895,12 +1924,17 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
1895static int reiserfs_release_dquot(struct dquot *dquot) 1924static int reiserfs_release_dquot(struct dquot *dquot)
1896{ 1925{
1897 struct reiserfs_transaction_handle th; 1926 struct reiserfs_transaction_handle th;
1898 int ret; 1927 int ret, err;
1899 1928
1900 reiserfs_write_lock(dquot->dq_sb); 1929 reiserfs_write_lock(dquot->dq_sb);
1901 journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS); 1930 ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
1931 if (ret)
1932 goto out;
1902 ret = dquot_release(dquot); 1933 ret = dquot_release(dquot);
1903 journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS); 1934 err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
1935 if (!ret && err)
1936 ret = err;
1937out:
1904 reiserfs_write_unlock(dquot->dq_sb); 1938 reiserfs_write_unlock(dquot->dq_sb);
1905 return ret; 1939 return ret;
1906} 1940}
@@ -1920,13 +1954,18 @@ static int reiserfs_mark_dquot_dirty(struct dquot *dquot)
1920static int reiserfs_write_info(struct super_block *sb, int type) 1954static int reiserfs_write_info(struct super_block *sb, int type)
1921{ 1955{
1922 struct reiserfs_transaction_handle th; 1956 struct reiserfs_transaction_handle th;
1923 int ret; 1957 int ret, err;
1924 1958
1925 /* Data block + inode block */ 1959 /* Data block + inode block */
1926 reiserfs_write_lock(sb); 1960 reiserfs_write_lock(sb);
1927 journal_begin(&th, sb, 2); 1961 ret = journal_begin(&th, sb, 2);
1962 if (ret)
1963 goto out;
1928 ret = dquot_commit_info(sb, type); 1964 ret = dquot_commit_info(sb, type);
1929 journal_end(&th, sb, 2); 1965 err = journal_end(&th, sb, 2);
1966 if (!ret && err)
1967 ret = err;
1968out:
1930 reiserfs_write_unlock(sb); 1969 reiserfs_write_unlock(sb);
1931 return ret; 1970 return ret;
1932} 1971}
@@ -1948,6 +1987,8 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, ch
1948 int err; 1987 int err;
1949 struct nameidata nd; 1988 struct nameidata nd;
1950 1989
1990 if (!(REISERFS_SB(sb)->s_mount_opt & (1<<REISERFS_QUOTA)))
1991 return -EINVAL;
1951 err = path_lookup(path, LOOKUP_FOLLOW, &nd); 1992 err = path_lookup(path, LOOKUP_FOLLOW, &nd);
1952 if (err) 1993 if (err)
1953 return err; 1994 return err;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index e9cfa39f40..d72c1ce485 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -14,7 +14,7 @@
14#define to_subsys(k) container_of(k,struct subsystem,kset.kobj) 14#define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
15#define to_sattr(a) container_of(a,struct subsys_attribute,attr) 15#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
16 16
17/** 17/*
18 * Subsystem file operations. 18 * Subsystem file operations.
19 * These operations allow subsystems to have files that can be 19 * These operations allow subsystems to have files that can be
20 * read/written. 20 * read/written.
@@ -192,8 +192,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
192 192
193/** 193/**
194 * flush_write_buffer - push buffer to kobject. 194 * flush_write_buffer - push buffer to kobject.
195 * @file: file pointer. 195 * @dentry: dentry to the attribute
196 * @buffer: data buffer for file. 196 * @buffer: data buffer for file.
197 * @count: number of bytes
197 * 198 *
198 * Get the correct pointers for the kobject and the attribute we're 199 * Get the correct pointers for the kobject and the attribute we're
199 * dealing with, then call the store() method for the attribute, 200 * dealing with, then call the store() method for the attribute,
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 93ce257cd1..a3a4b5aaf5 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -149,11 +149,12 @@ linvfs_unwritten_convert(
149 */ 149 */
150STATIC void 150STATIC void
151linvfs_unwritten_convert_direct( 151linvfs_unwritten_convert_direct(
152 struct inode *inode, 152 struct kiocb *iocb,
153 loff_t offset, 153 loff_t offset,
154 ssize_t size, 154 ssize_t size,
155 void *private) 155 void *private)
156{ 156{
157 struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
157 ASSERT(!private || inode == (struct inode *)private); 158 ASSERT(!private || inode == (struct inode *)private);
158 159
159 /* private indicates an unwritten extent lay beneath this IO */ 160 /* private indicates an unwritten extent lay beneath this IO */
diff --git a/include/asm-xtensa/a.out.h b/include/asm-xtensa/a.out.h
new file mode 100644
index 0000000000..3be701dfe0
--- /dev/null
+++ b/include/asm-xtensa/a.out.h
@@ -0,0 +1,33 @@
1/*
2 * include/asm-xtensa/addrspace.h
3 *
4 * Dummy a.out file. Xtensa does not support the a.out format, but the kernel
5 * seems to depend on it.
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 *
11 * Copyright (C) 2001 - 2005 Tensilica Inc.
12 */
13
14#ifndef _XTENSA_A_OUT_H
15#define _XTENSA_A_OUT_H
16
17/* Note: the kernel needs the a.out definitions, even if only ELF is used. */
18
19#define STACK_TOP TASK_SIZE
20
21struct exec
22{
23 unsigned long a_info;
24 unsigned a_text;
25 unsigned a_data;
26 unsigned a_bss;
27 unsigned a_syms;
28 unsigned a_entry;
29 unsigned a_trsize;
30 unsigned a_drsize;
31};
32
33#endif /* _XTENSA_A_OUT_H */
diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h
new file mode 100644
index 0000000000..d72bcb32ba
--- /dev/null
+++ b/include/asm-xtensa/atomic.h
@@ -0,0 +1,272 @@
1/*
2 * include/asm-xtensa/atomic.h
3 *
4 * Atomic operations that C can't guarantee us. Useful for resource counting..
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_ATOMIC_H
14#define _XTENSA_ATOMIC_H
15
16#include <linux/config.h>
17#include <linux/stringify.h>
18
19typedef struct { volatile int counter; } atomic_t;
20
21#ifdef __KERNEL__
22#include <asm/processor.h>
23#include <asm/system.h>
24
25#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
26
27/*
28 * This Xtensa implementation assumes that the right mechanism
29 * for exclusion is for locking interrupts to level 1.
30 *
31 * Locking interrupts looks like this:
32 *
33 * rsil a15, 1
34 * <code>
35 * wsr a15, PS
36 * rsync
37 *
38 * Note that a15 is used here because the register allocation
39 * done by the compiler is not guaranteed and a window overflow
40 * may not occur between the rsil and wsr instructions. By using
41 * a15 in the rsil, the machine is guaranteed to be in a state
42 * where no register reference will cause an overflow.
43 */
44
45/**
46 * atomic_read - read atomic variable
47 * @v: pointer of type atomic_t
48 *
49 * Atomically reads the value of @v.
50 */
51#define atomic_read(v) ((v)->counter)
52
53/**
54 * atomic_set - set atomic variable
55 * @v: pointer of type atomic_t
56 * @i: required value
57 *
58 * Atomically sets the value of @v to @i.
59 */
60#define atomic_set(v,i) ((v)->counter = (i))
61
62/**
63 * atomic_add - add integer to atomic variable
64 * @i: integer value to add
65 * @v: pointer of type atomic_t
66 *
67 * Atomically adds @i to @v.
68 */
69extern __inline__ void atomic_add(int i, atomic_t * v)
70{
71 unsigned int vval;
72
73 __asm__ __volatile__(
74 "rsil a15, "__stringify(LOCKLEVEL)"\n\t"
75 "l32i %0, %2, 0 \n\t"
76 "add %0, %0, %1 \n\t"
77 "s32i %0, %2, 0 \n\t"
78 "wsr a15, "__stringify(PS)" \n\t"
79 "rsync \n"
80 : "=&a" (vval)
81 : "a" (i), "a" (v)
82 : "a15", "memory"
83 );
84}
85
86/**
87 * atomic_sub - subtract the atomic variable
88 * @i: integer value to subtract
89 * @v: pointer of type atomic_t
90 *
91 * Atomically subtracts @i from @v.
92 */
93extern __inline__ void atomic_sub(int i, atomic_t *v)
94{
95 unsigned int vval;
96
97 __asm__ __volatile__(
98 "rsil a15, "__stringify(LOCKLEVEL)"\n\t"
99 "l32i %0, %2, 0 \n\t"
100 "sub %0, %0, %1 \n\t"
101 "s32i %0, %2, 0 \n\t"
102 "wsr a15, "__stringify(PS)" \n\t"
103 "rsync \n"
104 : "=&a" (vval)
105 : "a" (i), "a" (v)
106 : "a15", "memory"
107 );
108}
109
110/*
111 * We use atomic_{add|sub}_return to define other functions.
112 */
113
114extern __inline__ int atomic_add_return(int i, atomic_t * v)
115{
116 unsigned int vval;
117
118 __asm__ __volatile__(
119 "rsil a15,"__stringify(LOCKLEVEL)"\n\t"
120 "l32i %0, %2, 0 \n\t"
121 "add %0, %0, %1 \n\t"
122 "s32i %0, %2, 0 \n\t"
123 "wsr a15, "__stringify(PS)" \n\t"
124 "rsync \n"
125 : "=&a" (vval)
126 : "a" (i), "a" (v)
127 : "a15", "memory"
128 );
129
130 return vval;
131}
132
133extern __inline__ int atomic_sub_return(int i, atomic_t * v)
134{
135 unsigned int vval;
136
137 __asm__ __volatile__(
138 "rsil a15,"__stringify(LOCKLEVEL)"\n\t"
139 "l32i %0, %2, 0 \n\t"
140 "sub %0, %0, %1 \n\t"
141 "s32i %0, %2, 0 \n\t"
142 "wsr a15, "__stringify(PS)" \n\t"
143 "rsync \n"
144 : "=&a" (vval)
145 : "a" (i), "a" (v)
146 : "a15", "memory"
147 );
148
149 return vval;
150}
151
152/**
153 * atomic_sub_and_test - subtract value from variable and test result
154 * @i: integer value to subtract
155 * @v: pointer of type atomic_t
156 *
157 * Atomically subtracts @i from @v and returns
158 * true if the result is zero, or false for all
159 * other cases.
160 */
161#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
162
163/**
164 * atomic_inc - increment atomic variable
165 * @v: pointer of type atomic_t
166 *
167 * Atomically increments @v by 1.
168 */
169#define atomic_inc(v) atomic_add(1,(v))
170
171/**
172 * atomic_inc - increment atomic variable
173 * @v: pointer of type atomic_t
174 *
175 * Atomically increments @v by 1.
176 */
177#define atomic_inc_return(v) atomic_add_return(1,(v))
178
179/**
180 * atomic_dec - decrement atomic variable
181 * @v: pointer of type atomic_t
182 *
183 * Atomically decrements @v by 1.
184 */
185#define atomic_dec(v) atomic_sub(1,(v))
186
187/**
188 * atomic_dec_return - decrement atomic variable
189 * @v: pointer of type atomic_t
190 *
191 * Atomically decrements @v by 1.
192 */
193#define atomic_dec_return(v) atomic_sub_return(1,(v))
194
195/**
196 * atomic_dec_and_test - decrement and test
197 * @v: pointer of type atomic_t
198 *
199 * Atomically decrements @v by 1 and
200 * returns true if the result is 0, or false for all other
201 * cases.
202 */
203#define atomic_dec_and_test(v) (atomic_sub_return(1,(v)) == 0)
204
205/**
206 * atomic_inc_and_test - increment and test
207 * @v: pointer of type atomic_t
208 *
209 * Atomically increments @v by 1
210 * and returns true if the result is zero, or false for all
211 * other cases.
212 */
213#define atomic_inc_and_test(v) (atomic_add_return(1,(v)) == 0)
214
215/**
216 * atomic_add_negative - add and test if negative
217 * @v: pointer of type atomic_t
218 * @i: integer value to add
219 *
220 * Atomically adds @i to @v and returns true
221 * if the result is negative, or false when
222 * result is greater than or equal to zero.
223 */
224#define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0)
225
226
227extern __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
228{
229 unsigned int all_f = -1;
230 unsigned int vval;
231
232 __asm__ __volatile__(
233 "rsil a15,"__stringify(LOCKLEVEL)"\n\t"
234 "l32i %0, %2, 0 \n\t"
235 "xor %1, %4, %3 \n\t"
236 "and %0, %0, %4 \n\t"
237 "s32i %0, %2, 0 \n\t"
238 "wsr a15, "__stringify(PS)" \n\t"
239 "rsync \n"
240 : "=&a" (vval), "=a" (mask)
241 : "a" (v), "a" (all_f), "1" (mask)
242 : "a15", "memory"
243 );
244}
245
246extern __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
247{
248 unsigned int vval;
249
250 __asm__ __volatile__(
251 "rsil a15,"__stringify(LOCKLEVEL)"\n\t"
252 "l32i %0, %2, 0 \n\t"
253 "or %0, %0, %1 \n\t"
254 "s32i %0, %2, 0 \n\t"
255 "wsr a15, "__stringify(PS)" \n\t"
256 "rsync \n"
257 : "=&a" (vval)
258 : "a" (mask), "a" (v)
259 : "a15", "memory"
260 );
261}
262
263/* Atomic operations are already serializing */
264#define smp_mb__before_atomic_dec() barrier()
265#define smp_mb__after_atomic_dec() barrier()
266#define smp_mb__before_atomic_inc() barrier()
267#define smp_mb__after_atomic_inc() barrier()
268
269#endif /* __KERNEL__ */
270
271#endif /* _XTENSA_ATOMIC_H */
272
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
new file mode 100644
index 0000000000..d395ef226c
--- /dev/null
+++ b/include/asm-xtensa/bitops.h
@@ -0,0 +1,446 @@
1/*
2 * include/asm-xtensa/bitops.h
3 *
4 * Atomic operations that C can't guarantee us.Useful for resource counting etc.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_BITOPS_H
14#define _XTENSA_BITOPS_H
15
16#ifdef __KERNEL__
17
18#include <asm/processor.h>
19#include <asm/byteorder.h>
20#include <asm/system.h>
21
22#ifdef CONFIG_SMP
23# error SMP not supported on this architecture
24#endif
25
26static __inline__ void set_bit(int nr, volatile void * addr)
27{
28 unsigned long mask = 1 << (nr & 0x1f);
29 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
30 unsigned long flags;
31
32 local_irq_save(flags);
33 *a |= mask;
34 local_irq_restore(flags);
35}
36
37static __inline__ void __set_bit(int nr, volatile unsigned long * addr)
38{
39 unsigned long mask = 1 << (nr & 0x1f);
40 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
41
42 *a |= mask;
43}
44
45static __inline__ void clear_bit(int nr, volatile void * addr)
46{
47 unsigned long mask = 1 << (nr & 0x1f);
48 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
49 unsigned long flags;
50
51 local_irq_save(flags);
52 *a &= ~mask;
53 local_irq_restore(flags);
54}
55
56static __inline__ void __clear_bit(int nr, volatile unsigned long *addr)
57{
58 unsigned long mask = 1 << (nr & 0x1f);
59 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
60
61 *a &= ~mask;
62}
63
64/*
65 * clear_bit() doesn't provide any barrier for the compiler.
66 */
67
68#define smp_mb__before_clear_bit() barrier()
69#define smp_mb__after_clear_bit() barrier()
70
71static __inline__ void change_bit(int nr, volatile void * addr)
72{
73 unsigned long mask = 1 << (nr & 0x1f);
74 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
75 unsigned long flags;
76
77 local_irq_save(flags);
78 *a ^= mask;
79 local_irq_restore(flags);
80}
81
82static __inline__ void __change_bit(int nr, volatile void * addr)
83{
84 unsigned long mask = 1 << (nr & 0x1f);
85 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
86
87 *a ^= mask;
88}
89
90static __inline__ int test_and_set_bit(int nr, volatile void * addr)
91{
92 unsigned long retval;
93 unsigned long mask = 1 << (nr & 0x1f);
94 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
95 unsigned long flags;
96
97 local_irq_save(flags);
98 retval = (mask & *a) != 0;
99 *a |= mask;
100 local_irq_restore(flags);
101
102 return retval;
103}
104
105static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
106{
107 unsigned long retval;
108 unsigned long mask = 1 << (nr & 0x1f);
109 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
110
111 retval = (mask & *a) != 0;
112 *a |= mask;
113
114 return retval;
115}
116
117static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
118{
119 unsigned long retval;
120 unsigned long mask = 1 << (nr & 0x1f);
121 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
122 unsigned long flags;
123
124 local_irq_save(flags);
125 retval = (mask & *a) != 0;
126 *a &= ~mask;
127 local_irq_restore(flags);
128
129 return retval;
130}
131
132static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
133{
134 unsigned long mask = 1 << (nr & 0x1f);
135 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
136 unsigned long old = *a;
137
138 *a = old & ~mask;
139 return (old & mask) != 0;
140}
141
142static __inline__ int test_and_change_bit(int nr, volatile void * addr)
143{
144 unsigned long retval;
145 unsigned long mask = 1 << (nr & 0x1f);
146 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
147 unsigned long flags;
148
149 local_irq_save(flags);
150
151 retval = (mask & *a) != 0;
152 *a ^= mask;
153 local_irq_restore(flags);
154
155 return retval;
156}
157
158/*
159 * non-atomic version; can be reordered
160 */
161
162static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
163{
164 unsigned long mask = 1 << (nr & 0x1f);
165 unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
166 unsigned long old = *a;
167
168 *a = old ^ mask;
169 return (old & mask) != 0;
170}
171
172static __inline__ int test_bit(int nr, const volatile void *addr)
173{
174 return 1UL & (((const volatile unsigned int *)addr)[nr>>5] >> (nr&31));
175}
176
177#if XCHAL_HAVE_NSAU
178
179static __inline__ int __cntlz (unsigned long x)
180{
181 int lz;
182 asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
183 return 31 - lz;
184}
185
186#else
187
188static __inline__ int __cntlz (unsigned long x)
189{
190 unsigned long sum, x1, x2, x4, x8, x16;
191 x1 = x & 0xAAAAAAAA;
192 x2 = x & 0xCCCCCCCC;
193 x4 = x & 0xF0F0F0F0;
194 x8 = x & 0xFF00FF00;
195 x16 = x & 0xFFFF0000;
196 sum = x2 ? 2 : 0;
197 sum += (x16 != 0) * 16;
198 sum += (x8 != 0) * 8;
199 sum += (x4 != 0) * 4;
200 sum += (x1 != 0);
201
202 return sum;
203}
204
205#endif
206
207/*
208 * ffz: Find first zero in word. Undefined if no zero exists.
209 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
210 */
211
212static __inline__ int ffz(unsigned long x)
213{
214 if ((x = ~x) == 0)
215 return 32;
216 return __cntlz(x & -x);
217}
218
219/*
220 * __ffs: Find first bit set in word. Return 0 for bit 0
221 */
222
223static __inline__ int __ffs(unsigned long x)
224{
225 return __cntlz(x & -x);
226}
227
228/*
229 * ffs: Find first bit set in word. This is defined the same way as
230 * the libc and compiler builtin ffs routines, therefore
231 * differs in spirit from the above ffz (man ffs).
232 */
233
234static __inline__ int ffs(unsigned long x)
235{
236 return __cntlz(x & -x) + 1;
237}
238
239/*
240 * fls: Find last (most-significant) bit set in word.
241 * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
242 */
243
244static __inline__ int fls (unsigned int x)
245{
246 return __cntlz(x);
247}
248
249static __inline__ int
250find_next_bit(const unsigned long *addr, int size, int offset)
251{
252 const unsigned long *p = addr + (offset >> 5);
253 unsigned long result = offset & ~31UL;
254 unsigned long tmp;
255
256 if (offset >= size)
257 return size;
258 size -= result;
259 offset &= 31UL;
260 if (offset) {
261 tmp = *p++;
262 tmp &= ~0UL << offset;
263 if (size < 32)
264 goto found_first;
265 if (tmp)
266 goto found_middle;
267 size -= 32;
268 result += 32;
269 }
270 while (size >= 32) {
271 if ((tmp = *p++) != 0)
272 goto found_middle;
273 result += 32;
274 size -= 32;
275 }
276 if (!size)
277 return result;
278 tmp = *p;
279
280found_first:
281 tmp &= ~0UL >> (32 - size);
282 if (tmp == 0UL) /* Are any bits set? */
283 return result + size; /* Nope. */
284found_middle:
285 return result + __ffs(tmp);
286}
287
288/**
289 * find_first_bit - find the first set bit in a memory region
290 * @addr: The address to start the search at
291 * @size: The maximum size to search
292 *
293 * Returns the bit-number of the first set bit, not the number of the byte
294 * containing a bit.
295 */
296
297#define find_first_bit(addr, size) \
298 find_next_bit((addr), (size), 0)
299
300static __inline__ int
301find_next_zero_bit(const unsigned long *addr, int size, int offset)
302{
303 const unsigned long *p = addr + (offset >> 5);
304 unsigned long result = offset & ~31UL;
305 unsigned long tmp;
306
307 if (offset >= size)
308 return size;
309 size -= result;
310 offset &= 31UL;
311 if (offset) {
312 tmp = *p++;
313 tmp |= ~0UL >> (32-offset);
314 if (size < 32)
315 goto found_first;
316 if (~tmp)
317 goto found_middle;
318 size -= 32;
319 result += 32;
320 }
321 while (size & ~31UL) {
322 if (~(tmp = *p++))
323 goto found_middle;
324 result += 32;
325 size -= 32;
326 }
327 if (!size)
328 return result;
329 tmp = *p;
330
331found_first:
332 tmp |= ~0UL << size;
333found_middle:
334 return result + ffz(tmp);
335}
336
337#define find_first_zero_bit(addr, size) \
338 find_next_zero_bit((addr), (size), 0)
339
340#ifdef __XTENSA_EL__
341# define ext2_set_bit(nr,addr) __test_and_set_bit((nr), (addr))
342# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr),(addr))
343# define ext2_clear_bit(nr,addr) __test_and_clear_bit((nr), (addr))
344# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr),(addr))
345# define ext2_test_bit(nr,addr) test_bit((nr), (addr))
346# define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr),(size))
347# define ext2_find_next_zero_bit(addr, size, offset) \
348 find_next_zero_bit((addr), (size), (offset))
349#elif defined(__XTENSA_EB__)
350# define ext2_set_bit(nr,addr) __test_and_set_bit((nr) ^ 0x18, (addr))
351# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr) ^ 0x18, (addr))
352# define ext2_clear_bit(nr,addr) __test_and_clear_bit((nr) ^ 18, (addr))
353# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr)^0x18,(addr))
354# define ext2_test_bit(nr,addr) test_bit((nr) ^ 0x18, (addr))
355# define ext2_find_first_zero_bit(addr, size) \
356 ext2_find_next_zero_bit((addr), (size), 0)
357
358static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
359{
360 unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
361 unsigned long result = offset & ~31UL;
362 unsigned long tmp;
363
364 if (offset >= size)
365 return size;
366 size -= result;
367 offset &= 31UL;
368 if(offset) {
369 /* We hold the little endian value in tmp, but then the
370 * shift is illegal. So we could keep a big endian value
371 * in tmp, like this:
372 *
373 * tmp = __swab32(*(p++));
374 * tmp |= ~0UL >> (32-offset);
375 *
376 * but this would decrease preformance, so we change the
377 * shift:
378 */
379 tmp = *(p++);
380 tmp |= __swab32(~0UL >> (32-offset));
381 if(size < 32)
382 goto found_first;
383 if(~tmp)
384 goto found_middle;
385 size -= 32;
386 result += 32;
387 }
388 while(size & ~31UL) {
389 if(~(tmp = *(p++)))
390 goto found_middle;
391 result += 32;
392 size -= 32;
393 }
394 if(!size)
395 return result;
396 tmp = *p;
397
398found_first:
399 /* tmp is little endian, so we would have to swab the shift,
400 * see above. But then we have to swab tmp below for ffz, so
401 * we might as well do this here.
402 */
403 return result + ffz(__swab32(tmp) | (~0UL << size));
404found_middle:
405 return result + ffz(__swab32(tmp));
406}
407
408#else
409# error processor byte order undefined!
410#endif
411
412
413#define hweight32(x) generic_hweight32(x)
414#define hweight16(x) generic_hweight16(x)
415#define hweight8(x) generic_hweight8(x)
416
417/*
418 * Find the first bit set in a 140-bit bitmap.
419 * The first 100 bits are unlikely to be set.
420 */
421
422static inline int sched_find_first_bit(const unsigned long *b)
423{
424 if (unlikely(b[0]))
425 return __ffs(b[0]);
426 if (unlikely(b[1]))
427 return __ffs(b[1]) + 32;
428 if (unlikely(b[2]))
429 return __ffs(b[2]) + 64;
430 if (b[3])
431 return __ffs(b[3]) + 96;
432 return __ffs(b[4]) + 128;
433}
434
435
436/* Bitmap functions for the minix filesystem. */
437
438#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
439#define minix_set_bit(nr,addr) set_bit(nr,addr)
440#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
441#define minix_test_bit(nr,addr) test_bit(nr,addr)
442#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
443
444#endif /* __KERNEL__ */
445
446#endif /* _XTENSA_BITOPS_H */
diff --git a/include/asm-xtensa/bootparam.h b/include/asm-xtensa/bootparam.h
new file mode 100644
index 0000000000..9983f2c1b7
--- /dev/null
+++ b/include/asm-xtensa/bootparam.h
@@ -0,0 +1,61 @@
1/*
2 * include/asm-xtensa/bootparam.h
3 *
4 * Definition of the Linux/Xtensa boot parameter structure
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 *
12 * (Concept borrowed from the 68K port)
13 */
14
15#ifndef _XTENSA_BOOTPARAM_H
16#define _XTENSA_BOOTPARAM_H
17
18#define BP_VERSION 0x0001
19
20#define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/
21#define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */
22#define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */
23#define BP_TAG_SERIAL_BAUSRATE 0x1004 /* baud rate of current console. */
24#define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */
25
26#define BP_TAG_FIRST 0x7B0B /* first tag with a version number */
27#define BP_TAG_LAST 0x7E0B /* last tag */
28
29#ifndef __ASSEMBLY__
30
31/* All records are aligned to 4 bytes */
32
33typedef struct bp_tag {
34 unsigned short id; /* tag id */
35 unsigned short size; /* size of this record excluding the structure*/
36 unsigned long data[0]; /* data */
37} bp_tag_t;
38
39typedef struct meminfo {
40 unsigned long type;
41 unsigned long start;
42 unsigned long end;
43} meminfo_t;
44
45#define SYSMEM_BANKS_MAX 5
46
47#define MEMORY_TYPE_CONVENTIONAL 0x1000
48#define MEMORY_TYPE_NONE 0x2000
49
50typedef struct sysmem_info {
51 int nr_banks;
52 meminfo_t bank[SYSMEM_BANKS_MAX];
53} sysmem_info_t;
54
55extern sysmem_info_t sysmem;
56
57#endif
58#endif
59
60
61
diff --git a/include/asm-xtensa/bug.h b/include/asm-xtensa/bug.h
new file mode 100644
index 0000000000..56703659b2
--- /dev/null
+++ b/include/asm-xtensa/bug.h
@@ -0,0 +1,41 @@
1/*
2 * include/asm-xtensa/bug.h
3 *
4 * Macros to cause a 'bug' message.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_BUG_H
14#define _XTENSA_BUG_H
15
16#include <linux/stringify.h>
17
18#define ILL __asm__ __volatile__ (".byte 0,0,0\n")
19
20#ifdef CONFIG_KALLSYMS
21# define BUG() do { \
22 printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
23 ILL; \
24} while (0)
25#else
26# define BUG() do { \
27 printk("kernel BUG!\n"); \
28 ILL; \
29} while (0)
30#endif
31
32#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
33#define PAGE_BUG(page) do { BUG(); } while (0)
34#define WARN_ON(condition) do { \
35 if (unlikely((condition)!=0)) { \
36 printk ("Warning in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
37 dump_stack(); \
38 } \
39} while (0)
40
41#endif /* _XTENSA_BUG_H */
diff --git a/include/asm-xtensa/bugs.h b/include/asm-xtensa/bugs.h
new file mode 100644
index 0000000000..c422853201
--- /dev/null
+++ b/include/asm-xtensa/bugs.h
@@ -0,0 +1,22 @@
1/*
2 * include/asm-xtensa/bugs.h
3 *
4 * This is included by init/main.c to check for architecture-dependent bugs.
5 *
6 * Xtensa processors don't have any bugs. :)
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file "COPYING" in the main directory of
10 * this archive for more details.
11 */
12
13#ifndef _XTENSA_BUGS_H
14#define _XTENSA_BUGS_H
15
16#include <asm/processor.h>
17
18static void __init check_bugs(void)
19{
20}
21
22#endif /* _XTENSA_BUGS_H */
diff --git a/include/asm-xtensa/byteorder.h b/include/asm-xtensa/byteorder.h
new file mode 100644
index 0000000000..0b1552569a
--- /dev/null
+++ b/include/asm-xtensa/byteorder.h
@@ -0,0 +1,82 @@
1/*
2 * include/asm-xtensa/byteorder.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_BYTEORDER_H
12#define _XTENSA_BYTEORDER_H
13
14#include <asm/processor.h>
15#include <asm/types.h>
16
17static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
18{
19 __u32 res;
20 /* instruction sequence from Xtensa ISA release 2/2000 */
21 __asm__("ssai 8 \n\t"
22 "srli %0, %1, 16 \n\t"
23 "src %0, %0, %1 \n\t"
24 "src %0, %0, %0 \n\t"
25 "src %0, %1, %0 \n"
26 : "=&a" (res)
27 : "a" (x)
28 );
29 return res;
30}
31
32static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
33{
34 /* Given that 'short' values are signed (i.e., can be negative),
35 * we cannot assume that the upper 16-bits of the register are
36 * zero. We are careful to mask values after shifting.
37 */
38
39 /* There exists an anomaly between xt-gcc and xt-xcc. xt-gcc
40 * inserts an extui instruction after putting this function inline
41 * to ensure that it uses only the least-significant 16 bits of
42 * the result. xt-xcc doesn't use an extui, but assumes the
43 * __asm__ macro follows convention that the upper 16 bits of an
44 * 'unsigned short' result are still zero. This macro doesn't
45 * follow convention; indeed, it leaves garbage in the upport 16
46 * bits of the register.
47
48 * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
49 * types while the return type of the function is a 16-bit type
50 * forces both compilers to insert exactly one extui instruction
51 * (or equivalent) to mask off the upper 16 bits. */
52
53 __u32 res;
54 __u32 tmp;
55
56 __asm__("extui %1, %2, 8, 8\n\t"
57 "slli %0, %2, 8 \n\t"
58 "or %0, %0, %1 \n"
59 : "=&a" (res), "=&a" (tmp)
60 : "a" (x)
61 );
62
63 return res;
64}
65
66#define __arch__swab32(x) ___arch__swab32(x)
67#define __arch__swab16(x) ___arch__swab16(x)
68
69#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
70# define __BYTEORDER_HAS_U64__
71# define __SWAB_64_THRU_32__
72#endif
73
74#ifdef __XTENSA_EL__
75# include <linux/byteorder/little_endian.h>
76#elif defined(__XTENSA_EB__)
77# include <linux/byteorder/big_endian.h>
78#else
79# error processor byte order undefined!
80#endif
81
82#endif /* __ASM_XTENSA_BYTEORDER_H */
diff --git a/include/asm-xtensa/cache.h b/include/asm-xtensa/cache.h
new file mode 100644
index 0000000000..5aae3f1240
--- /dev/null
+++ b/include/asm-xtensa/cache.h
@@ -0,0 +1,32 @@
1/*
2 * include/asm-xtensa/cacheflush.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 * 2 of the License, or (at your option) any later version.
8 *
9 * (C) 2001 - 2005 Tensilica Inc.
10 */
11
12#ifndef _XTENSA_CACHE_H
13#define _XTENSA_CACHE_H
14
15#include <xtensa/config/core.h>
16
17#if XCHAL_ICACHE_SIZE > 0
18# if (XCHAL_ICACHE_SIZE % (XCHAL_ICACHE_LINESIZE*XCHAL_ICACHE_WAYS*4)) != 0
19# error cache configuration outside expected/supported range!
20# endif
21#endif
22
23#if XCHAL_DCACHE_SIZE > 0
24# if (XCHAL_DCACHE_SIZE % (XCHAL_DCACHE_LINESIZE*XCHAL_DCACHE_WAYS*4)) != 0
25# error cache configuration outside expected/supported range!
26# endif
27#endif
28
29#define L1_CACHE_SHIFT XCHAL_CACHE_LINEWIDTH_MAX
30#define L1_CACHE_BYTES XCHAL_CACHE_LINESIZE_MAX
31
32#endif /* _XTENSA_CACHE_H */
diff --git a/include/asm-xtensa/cacheflush.h b/include/asm-xtensa/cacheflush.h
new file mode 100644
index 0000000000..44a36e0878
--- /dev/null
+++ b/include/asm-xtensa/cacheflush.h
@@ -0,0 +1,122 @@
1/*
2 * include/asm-xtensa/cacheflush.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_CACHEFLUSH_H
12#define _XTENSA_CACHEFLUSH_H
13
14#ifdef __KERNEL__
15
16#include <linux/mm.h>
17#include <asm/processor.h>
18#include <asm/page.h>
19
20/*
21 * flush and invalidate data cache, invalidate instruction cache:
22 *
23 * __flush_invalidate_cache_all()
24 * __flush_invalidate_cache_range(from,sze)
25 *
26 * invalidate data or instruction cache:
27 *
28 * __invalidate_icache_all()
29 * __invalidate_icache_page(adr)
30 * __invalidate_dcache_page(adr)
31 * __invalidate_icache_range(from,size)
32 * __invalidate_dcache_range(from,size)
33 *
34 * flush data cache:
35 *
36 * __flush_dcache_page(adr)
37 *
38 * flush and invalidate data cache:
39 *
40 * __flush_invalidate_dcache_all()
41 * __flush_invalidate_dcache_page(adr)
42 * __flush_invalidate_dcache_range(from,size)
43 */
44
45extern void __flush_invalidate_cache_all(void);
46extern void __flush_invalidate_cache_range(unsigned long, unsigned long);
47extern void __flush_invalidate_dcache_all(void);
48extern void __invalidate_icache_all(void);
49
50extern void __invalidate_dcache_page(unsigned long);
51extern void __invalidate_icache_page(unsigned long);
52extern void __invalidate_icache_range(unsigned long, unsigned long);
53extern void __invalidate_dcache_range(unsigned long, unsigned long);
54
55#if XCHAL_DCACHE_IS_WRITEBACK
56extern void __flush_dcache_page(unsigned long);
57extern void __flush_invalidate_dcache_page(unsigned long);
58extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
59#else
60# define __flush_dcache_page(p) do { } while(0)
61# define __flush_invalidate_dcache_page(p) do { } while(0)
62# define __flush_invalidate_dcache_range(p,s) do { } while(0)
63#endif
64
65/*
66 * We have physically tagged caches - nothing to do here -
67 * unless we have cache aliasing.
68 *
69 * Pages can get remapped. Because this might change the 'color' of that page,
70 * we have to flush the cache before the PTE is changed.
71 * (see also Documentation/cachetlb.txt)
72 */
73
74#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
75
76#define flush_cache_all() __flush_invalidate_cache_all();
77#define flush_cache_mm(mm) __flush_invalidate_cache_all();
78
79#define flush_cache_vmap(start,end) __flush_invalidate_cache_all();
80#define flush_cache_vunmap(start,end) __flush_invalidate_cache_all();
81
82extern void flush_dcache_page(struct page*);
83
84extern void flush_cache_range(struct vm_area_struct*, ulong, ulong);
85extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned long);
86
87#else
88
89#define flush_cache_all() do { } while (0)
90#define flush_cache_mm(mm) do { } while (0)
91
92#define flush_cache_vmap(start,end) do { } while (0)
93#define flush_cache_vunmap(start,end) do { } while (0)
94
95#define flush_dcache_page(page) do { } while (0)
96
97#define flush_cache_page(vma,addr,pfn) do { } while (0)
98#define flush_cache_range(vma,start,end) do { } while (0)
99
100#endif
101
102#define flush_icache_range(start,end) \
103 __invalidate_icache_range(start,(end)-(start))
104
105/* This is not required, see Documentation/cachetlb.txt */
106
107#define flush_icache_page(vma,page) do { } while(0)
108
109#define flush_dcache_mmap_lock(mapping) do { } while (0)
110#define flush_dcache_mmap_unlock(mapping) do { } while (0)
111
112
113#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
114 memcpy(dst, src, len)
115
116#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
117 memcpy(dst, src, len)
118
119#endif /* __KERNEL__ */
120
121#endif /* _XTENSA_CACHEFLUSH_H */
122
diff --git a/include/asm-xtensa/checksum.h b/include/asm-xtensa/checksum.h
new file mode 100644
index 0000000000..1a00fad199
--- /dev/null
+++ b/include/asm-xtensa/checksum.h
@@ -0,0 +1,264 @@
1/*
2 * include/asm-xtensa/checksum.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_CHECKSUM_H
12#define _XTENSA_CHECKSUM_H
13
14#include <linux/config.h>
15#include <linux/in6.h>
16#include <xtensa/config/core.h>
17
18/*
19 * computes the checksum of a memory block at buff, length len,
20 * and adds in "sum" (32-bit)
21 *
22 * returns a 32-bit number suitable for feeding into itself
23 * or csum_tcpudp_magic
24 *
25 * this function must be called with even lengths, except
26 * for the last fragment, which may be odd
27 *
28 * it's best to have buff aligned on a 32-bit boundary
29 */
30asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
31
32/*
33 * the same as csum_partial, but copies from src while it
34 * checksums, and handles user-space pointer exceptions correctly, when needed.
35 *
36 * here even more important to align src and dst on a 32-bit (or even
37 * better 64-bit) boundary
38 */
39
40asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
41 int *src_err_ptr, int *dst_err_ptr);
42
43/*
44 * Note: when you get a NULL pointer exception here this means someone
45 * passed in an incorrect kernel address to one of these functions.
46 *
47 * If you use these functions directly please don't forget the
48 * verify_area().
49 */
50extern __inline__
51unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
52 int len, int sum)
53{
54 return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
55}
56
57extern __inline__
58unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
59 int len, int sum, int *err_ptr)
60{
61 return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
62}
63
64/*
65 * These are the old (and unsafe) way of doing checksums, a warning message will be
66 * printed if they are used and an exeption occurs.
67 *
68 * these functions should go away after some time.
69 */
70
71#define csum_partial_copy_fromuser csum_partial_copy
72unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
73
74/*
75 * Fold a partial checksum
76 */
77
78static __inline__ unsigned int csum_fold(unsigned int sum)
79{
80 unsigned int __dummy;
81 __asm__("extui %1, %0, 16, 16\n\t"
82 "extui %0 ,%0, 0, 16\n\t"
83 "add %0, %0, %1\n\t"
84 "slli %1, %0, 16\n\t"
85 "add %0, %0, %1\n\t"
86 "extui %0, %0, 16, 16\n\t"
87 "neg %0, %0\n\t"
88 "addi %0, %0, -1\n\t"
89 "extui %0, %0, 0, 16\n\t"
90 : "=r" (sum), "=&r" (__dummy)
91 : "0" (sum));
92 return sum;
93}
94
95/*
96 * This is a version of ip_compute_csum() optimized for IP headers,
97 * which always checksum on 4 octet boundaries.
98 */
99static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
100{
101 unsigned int sum, tmp, endaddr;
102
103 __asm__ __volatile__(
104 "sub %0, %0, %0\n\t"
105#if XCHAL_HAVE_LOOPS
106 "loopgtz %2, 2f\n\t"
107#else
108 "beqz %2, 2f\n\t"
109 "slli %4, %2, 2\n\t"
110 "add %4, %4, %1\n\t"
111 "0:\t"
112#endif
113 "l32i %3, %1, 0\n\t"
114 "add %0, %0, %3\n\t"
115 "bgeu %0, %3, 1f\n\t"
116 "addi %0, %0, 1\n\t"
117 "1:\t"
118 "addi %1, %1, 4\n\t"
119#if !XCHAL_HAVE_LOOPS
120 "blt %1, %4, 0b\n\t"
121#endif
122 "2:\t"
123 /* Since the input registers which are loaded with iph and ihl
124 are modified, we must also specify them as outputs, or gcc
125 will assume they contain their original values. */
126 : "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp), "=&r" (endaddr)
127 : "1" (iph), "2" (ihl));
128
129 return csum_fold(sum);
130}
131
132static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
133 unsigned long daddr,
134 unsigned short len,
135 unsigned short proto,
136 unsigned int sum)
137{
138
139#ifdef __XTENSA_EL__
140 unsigned long len_proto = (ntohs(len)<<16)+proto*256;
141#elif defined(__XTENSA_EB__)
142 unsigned long len_proto = (proto<<16)+len;
143#else
144# error processor byte order undefined!
145#endif
146 __asm__("add %0, %0, %1\n\t"
147 "bgeu %0, %1, 1f\n\t"
148 "addi %0, %0, 1\n\t"
149 "1:\t"
150 "add %0, %0, %2\n\t"
151 "bgeu %0, %2, 1f\n\t"
152 "addi %0, %0, 1\n\t"
153 "1:\t"
154 "add %0, %0, %3\n\t"
155 "bgeu %0, %3, 1f\n\t"
156 "addi %0, %0, 1\n\t"
157 "1:\t"
158 : "=r" (sum), "=r" (len_proto)
159 : "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum));
160 return sum;
161}
162
163/*
164 * computes the checksum of the TCP/UDP pseudo-header
165 * returns a 16-bit checksum, already complemented
166 */
167static __inline__ unsigned short int csum_tcpudp_magic(unsigned long saddr,
168 unsigned long daddr,
169 unsigned short len,
170 unsigned short proto,
171 unsigned int sum)
172{
173 return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
174}
175
176/*
177 * this routine is used for miscellaneous IP-like checksums, mainly
178 * in icmp.c
179 */
180
181static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
182{
183 return csum_fold (csum_partial(buff, len, 0));
184}
185
186#define _HAVE_ARCH_IPV6_CSUM
187static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
188 struct in6_addr *daddr,
189 __u32 len,
190 unsigned short proto,
191 unsigned int sum)
192{
193 unsigned int __dummy;
194 __asm__("l32i %1, %2, 0\n\t"
195 "add %0, %0, %1\n\t"
196 "bgeu %0, %1, 1f\n\t"
197 "addi %0, %0, 1\n\t"
198 "1:\t"
199 "l32i %1, %2, 4\n\t"
200 "add %0, %0, %1\n\t"
201 "bgeu %0, %1, 1f\n\t"
202 "addi %0, %0, 1\n\t"
203 "1:\t"
204 "l32i %1, %2, 8\n\t"
205 "add %0, %0, %1\n\t"
206 "bgeu %0, %1, 1f\n\t"
207 "addi %0, %0, 1\n\t"
208 "1:\t"
209 "l32i %1, %2, 12\n\t"
210 "add %0, %0, %1\n\t"
211 "bgeu %0, %1, 1f\n\t"
212 "addi %0, %0, 1\n\t"
213 "1:\t"
214 "l32i %1, %3, 0\n\t"
215 "add %0, %0, %1\n\t"
216 "bgeu %0, %1, 1f\n\t"
217 "addi %0, %0, 1\n\t"
218 "1:\t"
219 "l32i %1, %3, 4\n\t"
220 "add %0, %0, %1\n\t"
221 "bgeu %0, %1, 1f\n\t"
222 "addi %0, %0, 1\n\t"
223 "1:\t"
224 "l32i %1, %3, 8\n\t"
225 "add %0, %0, %1\n\t"
226 "bgeu %0, %1, 1f\n\t"
227 "addi %0, %0, 1\n\t"
228 "1:\t"
229 "l32i %1, %3, 12\n\t"
230 "add %0, %0, %1\n\t"
231 "bgeu %0, %1, 1f\n\t"
232 "addi %0, %0, 1\n\t"
233 "1:\t"
234 "add %0, %0, %4\n\t"
235 "bgeu %0, %4, 1f\n\t"
236 "addi %0, %0, 1\n\t"
237 "1:\t"
238 "add %0, %0, %5\n\t"
239 "bgeu %0, %5, 1f\n\t"
240 "addi %0, %0, 1\n\t"
241 "1:\t"
242 : "=r" (sum), "=&r" (__dummy)
243 : "r" (saddr), "r" (daddr),
244 "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
245
246 return csum_fold(sum);
247}
248
249/*
250 * Copy and checksum to user
251 */
252#define HAVE_CSUM_COPY_USER
253static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
254 int len, int sum, int *err_ptr)
255{
256 if (access_ok(VERIFY_WRITE, dst, len))
257 return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
258
259 if (len)
260 *err_ptr = -EFAULT;
261
262 return -1; /* invalid checksum */
263}
264#endif
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h
new file mode 100644
index 0000000000..a91b96dc0e
--- /dev/null
+++ b/include/asm-xtensa/coprocessor.h
@@ -0,0 +1,70 @@
1/*
2 * include/asm-xtensa/cpextra.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2003 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_COPROCESSOR_H
12#define _XTENSA_COPROCESSOR_H
13
14#include <xtensa/config/core.h>
15
16#define XTOFS(last_start,last_size,align) \
17 ((last_start+last_size+align-1) & -align)
18
19#define XTENSA_CP_EXTRA_OFFSET 0
20#define XTENSA_CP_EXTRA_ALIGN XCHAL_EXTRA_SA_ALIGN
21
22#define XTENSA_CPE_CP0_OFFSET \
23 XTOFS(XTENSA_CP_EXTRA_OFFSET, XCHAL_EXTRA_SA_SIZE, XCHAL_CP0_SA_ALIGN)
24#define XTENSA_CPE_CP1_OFFSET \
25 XTOFS(XTENSA_CPE_CP0_OFFSET, XCHAL_CP0_SA_SIZE, XCHAL_CP1_SA_ALIGN)
26#define XTENSA_CPE_CP2_OFFSET \
27 XTOFS(XTENSA_CPE_CP1_OFFSET, XCHAL_CP1_SA_SIZE, XCHAL_CP2_SA_ALIGN)
28#define XTENSA_CPE_CP3_OFFSET \
29 XTOFS(XTENSA_CPE_CP2_OFFSET, XCHAL_CP2_SA_SIZE, XCHAL_CP3_SA_ALIGN)
30#define XTENSA_CPE_CP4_OFFSET \
31 XTOFS(XTENSA_CPE_CP3_OFFSET, XCHAL_CP3_SA_SIZE, XCHAL_CP4_SA_ALIGN)
32#define XTENSA_CPE_CP5_OFFSET \
33 XTOFS(XTENSA_CPE_CP4_OFFSET, XCHAL_CP4_SA_SIZE, XCHAL_CP5_SA_ALIGN)
34#define XTENSA_CPE_CP6_OFFSET \
35 XTOFS(XTENSA_CPE_CP5_OFFSET, XCHAL_CP5_SA_SIZE, XCHAL_CP6_SA_ALIGN)
36#define XTENSA_CPE_CP7_OFFSET \
37 XTOFS(XTENSA_CPE_CP6_OFFSET, XCHAL_CP6_SA_SIZE, XCHAL_CP7_SA_ALIGN)
38#define XTENSA_CP_EXTRA_SIZE \
39 XTOFS(XTENSA_CPE_CP7_OFFSET, XCHAL_CP7_SA_SIZE, 16)
40
41#if XCHAL_CP_NUM > 0
42# ifndef __ASSEMBLY__
43/*
44 * Tasks that own contents of (last user) each coprocessor.
45 * Entries are 0 for not-owned or non-existent coprocessors.
46 * Note: The size of this structure is fixed to 8 bytes in entry.S
47 */
48typedef struct {
49 struct task_struct *owner; /* owner */
50 int offset; /* offset in cpextra space. */
51} coprocessor_info_t;
52# else
53# define COPROCESSOR_INFO_OWNER 0
54# define COPROCESSOR_INFO_OFFSET 4
55# define COPROCESSOR_INFO_SIZE 8
56# endif
57#endif
58
59
60#ifndef __ASSEMBLY__
61# if XCHAL_CP_NUM > 0
62struct task_struct;
63extern void release_coprocessors (struct task_struct*);
64extern void save_coprocessor_registers(void*, int);
65# else
66# define release_coprocessors(task)
67# endif
68#endif
69
70#endif /* _XTENSA_COPROCESSOR_H */
diff --git a/include/asm-xtensa/cpumask.h b/include/asm-xtensa/cpumask.h
new file mode 100644
index 0000000000..ebeede397d
--- /dev/null
+++ b/include/asm-xtensa/cpumask.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/cpumask.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_CPUMASK_H
12#define _XTENSA_CPUMASK_H
13
14#include <asm-generic/cpumask.h>
15
16#endif /* _XTENSA_CPUMASK_H */
diff --git a/include/asm-xtensa/cputime.h b/include/asm-xtensa/cputime.h
new file mode 100644
index 0000000000..a7fb864a50
--- /dev/null
+++ b/include/asm-xtensa/cputime.h
@@ -0,0 +1,6 @@
1#ifndef _XTENSA_CPUTIME_H
2#define _XTENSA_CPUTIME_H
3
4#include <asm-generic/cputime.h>
5
6#endif /* _XTENSA_CPUTIME_H */
diff --git a/include/asm-xtensa/current.h b/include/asm-xtensa/current.h
new file mode 100644
index 0000000000..8d1eb5d786
--- /dev/null
+++ b/include/asm-xtensa/current.h
@@ -0,0 +1,38 @@
1/*
2 * include/asm-xtensa/current.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_CURRENT_H
12#define _XTENSA_CURRENT_H
13
14#ifndef __ASSEMBLY__
15
16#include <linux/thread_info.h>
17
18struct task_struct;
19
20static inline struct task_struct *get_current(void)
21{
22 return current_thread_info()->task;
23}
24
25#define current get_current()
26
27#else
28
29#define CURRENT_SHIFT 13
30
31#define GET_CURRENT(reg,sp) \
32 GET_THREAD_INFO(reg,sp); \
33 l32i reg, reg, TI_TASK \
34
35#endif
36
37
38#endif /* XTENSA_CURRENT_H */
diff --git a/include/asm-xtensa/delay.h b/include/asm-xtensa/delay.h
new file mode 100644
index 0000000000..6359c55e77
--- /dev/null
+++ b/include/asm-xtensa/delay.h
@@ -0,0 +1,50 @@
1/*
2 * include/asm-xtensa/delay.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 *
10 */
11
12#ifndef _XTENSA_DELAY_H
13#define _XTENSA_DELAY_H
14
15#include <linux/config.h>
16#include <asm/processor.h>
17#include <asm/param.h>
18
19extern unsigned long loops_per_jiffy;
20
21extern __inline__ void __delay(unsigned long loops)
22{
23 /* 2 cycles per loop. */
24 __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 1, 1b"
25 : "=r" (loops) : "0" (loops));
26}
27
28static __inline__ u32 xtensa_get_ccount(void)
29{
30 u32 ccount;
31 asm volatile ("rsr %0, 234; # CCOUNT\n" : "=r" (ccount));
32 return ccount;
33}
34
35/* For SMP/NUMA systems, change boot_cpu_data to something like
36 * local_cpu_data->... where local_cpu_data points to the current
37 * cpu. */
38
39static __inline__ void udelay (unsigned long usecs)
40{
41 unsigned long start = xtensa_get_ccount();
42 unsigned long cycles = usecs * (loops_per_jiffy / (1000000UL / HZ));
43
44 /* Note: all variables are unsigned (can wrap around)! */
45 while (((unsigned long)xtensa_get_ccount()) - start < cycles)
46 ;
47}
48
49#endif
50
diff --git a/include/asm-xtensa/div64.h b/include/asm-xtensa/div64.h
new file mode 100644
index 0000000000..c4a1057763
--- /dev/null
+++ b/include/asm-xtensa/div64.h
@@ -0,0 +1,19 @@
1/*
2 * include/asm-xtensa/div64.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_DIV64_H
12#define _XTENSA_DIV64_H
13
14#define do_div(n,base) ({ \
15 int __res = n % ((unsigned int) base); \
16 n /= (unsigned int) base; \
17 __res; })
18
19#endif
diff --git a/include/asm-xtensa/dma-mapping.h b/include/asm-xtensa/dma-mapping.h
new file mode 100644
index 0000000000..e86a206f12
--- /dev/null
+++ b/include/asm-xtensa/dma-mapping.h
@@ -0,0 +1,182 @@
1/*
2 * include/asm-xtensa/dma_mapping.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2003 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_DMA_MAPPING_H
12#define _XTENSA_DMA_MAPPING_H
13
14#include <asm/scatterlist.h>
15#include <asm/cache.h>
16#include <asm/io.h>
17#include <linux/mm.h>
18
19/*
20 * DMA-consistent mapping functions.
21 */
22
23extern void *consistent_alloc(int, size_t, dma_addr_t, unsigned long);
24extern void consistent_free(void*, size_t, dma_addr_t);
25extern void consistent_sync(void*, size_t, int);
26
27#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
28#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
29
30void *dma_alloc_coherent(struct device *dev, size_t size,
31 dma_addr_t *dma_handle, int flag);
32
33void dma_free_coherent(struct device *dev, size_t size,
34 void *vaddr, dma_addr_t dma_handle);
35
36static inline dma_addr_t
37dma_map_single(struct device *dev, void *ptr, size_t size,
38 enum dma_data_direction direction)
39{
40 BUG_ON(direction == DMA_NONE);
41 consistent_sync(ptr, size, direction);
42 return virt_to_phys(ptr);
43}
44
45static inline void
46dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
47 enum dma_data_direction direction)
48{
49 BUG_ON(direction == DMA_NONE);
50}
51
52static inline int
53dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
54 enum dma_data_direction direction)
55{
56 int i;
57
58 BUG_ON(direction == DMA_NONE);
59
60 for (i = 0; i < nents; i++, sg++ ) {
61 BUG_ON(!sg->page);
62
63 sg->dma_address = page_to_phys(sg->page) + sg->offset;
64 consistent_sync(page_address(sg->page) + sg->offset,
65 sg->length, direction);
66 }
67
68 return nents;
69}
70
71static inline dma_addr_t
72dma_map_page(struct device *dev, struct page *page, unsigned long offset,
73 size_t size, enum dma_data_direction direction)
74{
75 BUG_ON(direction == DMA_NONE);
76 return (dma_addr_t)(page_to_pfn(page)) * PAGE_SIZE + offset;
77}
78
79static inline void
80dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
81 enum dma_data_direction direction)
82{
83 BUG_ON(direction == DMA_NONE);
84}
85
86
87static inline void
88dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
89 enum dma_data_direction direction)
90{
91 BUG_ON(direction == DMA_NONE);
92}
93
94static inline void
95dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
96 enum dma_data_direction direction)
97{
98 consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
99}
100
101static inline void
102dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
103 enum dma_data_direction direction)
104{
105 consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
106}
107
108static inline void
109dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
110 unsigned long offset, size_t size,
111 enum dma_data_direction direction)
112{
113
114 consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
115}
116
117static inline void
118dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
119 unsigned long offset, size_t size,
120 enum dma_data_direction direction)
121{
122
123 consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
124}
125static inline void
126dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
127 enum dma_data_direction dir)
128{
129 int i;
130 for (i = 0; i < nelems; i++, sg++)
131 consistent_sync(page_address(sg->page) + sg->offset,
132 sg->length, dir);
133}
134
135static inline void
136dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
137 enum dma_data_direction dir)
138{
139 int i;
140 for (i = 0; i < nelems; i++, sg++)
141 consistent_sync(page_address(sg->page) + sg->offset,
142 sg->length, dir);
143}
144static inline int
145dma_mapping_error(dma_addr_t dma_addr)
146{
147 return 0;
148}
149
150static inline int
151dma_supported(struct device *dev, u64 mask)
152{
153 return 1;
154}
155
156static inline int
157dma_set_mask(struct device *dev, u64 mask)
158{
159 if(!dev->dma_mask || !dma_supported(dev, mask))
160 return -EIO;
161
162 *dev->dma_mask = mask;
163
164 return 0;
165}
166
167static inline int
168dma_get_cache_alignment(void)
169{
170 return L1_CACHE_BYTES;
171}
172
173#define dma_is_consistent(d) (1)
174
175static inline void
176dma_cache_sync(void *vaddr, size_t size,
177 enum dma_data_direction direction)
178{
179 consistent_sync(vaddr, size, direction);
180}
181
182#endif /* _XTENSA_DMA_MAPPING_H */
diff --git a/include/asm-xtensa/dma.h b/include/asm-xtensa/dma.h
new file mode 100644
index 0000000000..1c22b02345
--- /dev/null
+++ b/include/asm-xtensa/dma.h
@@ -0,0 +1,61 @@
1/*
2 * include/asm-xtensa/dma.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2003 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_DMA_H
12#define _XTENSA_DMA_H
13
14#include <linux/config.h>
15#include <asm/io.h> /* need byte IO */
16#include <xtensa/config/core.h>
17
18/*
19 * This is only to be defined if we have PC-like DMA.
20 * By default this is not true on an Xtensa processor,
21 * however on boards with a PCI bus, such functionality
22 * might be emulated externally.
23 *
24 * NOTE: there still exists driver code that assumes
25 * this is defined, eg. drivers/sound/soundcard.c (as of 2.4).
26 */
27#define MAX_DMA_CHANNELS 8
28
29/*
30 * The maximum virtual address to which DMA transfers
31 * can be performed on this platform.
32 *
33 * NOTE: This is board (platform) specific, not processor-specific!
34 *
35 * NOTE: This assumes DMA transfers can only be performed on
36 * the section of physical memory contiguously mapped in virtual
37 * space for the kernel. For the Xtensa architecture, this
38 * means the maximum possible size of this DMA area is
39 * the size of the statically mapped kernel segment
40 * (XCHAL_KSEG_{CACHED,BYPASS}_SIZE), ie. 128 MB.
41 *
42 * NOTE: When the entire KSEG area is DMA capable, we substract
43 * one from the max address so that the virt_to_phys() macro
44 * works correctly on the address (otherwise the address
45 * enters another area, and virt_to_phys() may not return
46 * the value desired).
47 */
48#define MAX_DMA_ADDRESS (PAGE_OFFSET + XCHAL_KSEG_CACHED_SIZE - 1)
49
50/* Reserve and release a DMA channel */
51extern int request_dma(unsigned int dmanr, const char * device_id);
52extern void free_dma(unsigned int dmanr);
53
54#ifdef CONFIG_PCI
55extern int isa_dma_bridge_buggy;
56#else
57#define isa_dma_bridge_buggy (0)
58#endif
59
60
61#endif
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
new file mode 100644
index 0000000000..64f1f53874
--- /dev/null
+++ b/include/asm-xtensa/elf.h
@@ -0,0 +1,222 @@
1/*
2 * include/asm-xtensa/elf.h
3 *
4 * ELF register definitions
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_ELF_H
14#define _XTENSA_ELF_H
15
16#include <asm/ptrace.h>
17#include <asm/coprocessor.h>
18#include <xtensa/config/core.h>
19
20/* Xtensa processor ELF architecture-magic number */
21
22#define EM_XTENSA 94
23#define EM_XTENSA_OLD 0xABC7
24
25/* ELF register definitions. This is needed for core dump support. */
26
27/*
28 * elf_gregset_t contains the application-level state in the following order:
29 * Processor info: config_version, cpuxy
30 * Processor state: pc, ps, exccause, excvaddr, wb, ws,
31 * lbeg, lend, lcount, sar
32 * GP regs: ar0 - arXX
33 */
34
35typedef unsigned long elf_greg_t;
36
37typedef struct {
38 elf_greg_t xchal_config_id0;
39 elf_greg_t xchal_config_id1;
40 elf_greg_t cpux;
41 elf_greg_t cpuy;
42 elf_greg_t pc;
43 elf_greg_t ps;
44 elf_greg_t exccause;
45 elf_greg_t excvaddr;
46 elf_greg_t windowbase;
47 elf_greg_t windowstart;
48 elf_greg_t lbeg;
49 elf_greg_t lend;
50 elf_greg_t lcount;
51 elf_greg_t sar;
52 elf_greg_t syscall;
53 elf_greg_t ar[XCHAL_NUM_AREGS];
54} xtensa_gregset_t;
55
56#define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
57
58typedef elf_greg_t elf_gregset_t[ELF_NGREG];
59
60/*
61 * Compute the size of the coprocessor and extra state layout (register info)
62 * table (in bytes).
63 * This is actually the maximum size of the table, as opposed to the size,
64 * which is available from the _xtensa_reginfo_table_size global variable.
65 *
66 * (See also arch/xtensa/kernel/coprocessor.S)
67 *
68 */
69
70#ifndef XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM
71# define XTENSA_CPE_LTABLE_SIZE 0
72#else
73# define XTENSA_CPE_SEGMENT(num) (num ? (1+num) : 0)
74# define XTENSA_CPE_LTABLE_ENTRIES \
75 ( XTENSA_CPE_SEGMENT(XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM) \
76 + XTENSA_CPE_SEGMENT(XCHAL_CP0_SA_CONTENTS_LIBDB_NUM) \
77 + XTENSA_CPE_SEGMENT(XCHAL_CP1_SA_CONTENTS_LIBDB_NUM) \
78 + XTENSA_CPE_SEGMENT(XCHAL_CP2_SA_CONTENTS_LIBDB_NUM) \
79 + XTENSA_CPE_SEGMENT(XCHAL_CP3_SA_CONTENTS_LIBDB_NUM) \
80 + XTENSA_CPE_SEGMENT(XCHAL_CP4_SA_CONTENTS_LIBDB_NUM) \
81 + XTENSA_CPE_SEGMENT(XCHAL_CP5_SA_CONTENTS_LIBDB_NUM) \
82 + XTENSA_CPE_SEGMENT(XCHAL_CP6_SA_CONTENTS_LIBDB_NUM) \
83 + XTENSA_CPE_SEGMENT(XCHAL_CP7_SA_CONTENTS_LIBDB_NUM) \
84 + 1 /* final entry */ \
85 )
86# define XTENSA_CPE_LTABLE_SIZE (XTENSA_CPE_LTABLE_ENTRIES * 8)
87#endif
88
89
90/*
91 * Instantiations of the elf_fpregset_t type contain, in most
92 * architectures, the floating point (FPU) register set.
93 * For Xtensa, this type is extended to contain all custom state,
94 * ie. coprocessor and "extra" (non-coprocessor) state (including,
95 * for example, TIE-defined states and register files; as well
96 * as other optional processor state).
97 * This includes FPU state if a floating-point coprocessor happens
98 * to have been configured within the Xtensa processor.
99 *
100 * TOTAL_FPREGS_SIZE is the required size (without rounding)
101 * of elf_fpregset_t. It provides space for the following:
102 *
103 * a) 32-bit mask of active coprocessors for this task (similar
104 * to CPENABLE in single-threaded Xtensa processor systems)
105 *
106 * b) table describing the layout of custom states (ie. of
107 * individual registers, etc) within the save areas
108 *
109 * c) save areas for each coprocessor and for non-coprocessor
110 * ("extra") state
111 *
112 * Note that save areas may require up to 16-byte alignment when
113 * accessed by save/restore sequences. We do not need to ensure
114 * such alignment in an elf_fpregset_t structure because custom
115 * state is not directly loaded/stored into it; rather, save area
116 * contents are copied to elf_fpregset_t from the active save areas
117 * (see 'struct task_struct' definition in processor.h for that)
118 * using memcpy(). But we do allow space for such alignment,
119 * to allow optimizations of layout and copying.
120 */
121
122#define TOTAL_FPREGS_SIZE \
123 (4 + XTENSA_CPE_LTABLE_SIZE + XTENSA_CP_EXTRA_SIZE)
124#define ELF_NFPREG \
125 ((TOTAL_FPREGS_SIZE + sizeof(elf_fpreg_t) - 1) / sizeof(elf_fpreg_t))
126
127typedef unsigned int elf_fpreg_t;
128typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
129
130#define ELF_CORE_COPY_REGS(_eregs, _pregs) \
131 xtensa_elf_core_copy_regs (&_eregs, _pregs);
132
133extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *);
134
135/*
136 * This is used to ensure we don't load something for the wrong architecture.
137 */
138
139#define elf_check_arch(x) ( ( (x)->e_machine == EM_XTENSA ) || \
140 ( (x)->e_machine == EM_XTENSA_OLD ) )
141
142/*
143 * These are used to set parameters in the core dumps.
144 */
145
146#ifdef __XTENSA_EL__
147# define ELF_DATA ELFDATA2LSB
148#elif defined(__XTENSA_EB__)
149# define ELF_DATA ELFDATA2MSB
150#else
151# error processor byte order undefined!
152#endif
153
154#define ELF_CLASS ELFCLASS32
155#define ELF_ARCH EM_XTENSA
156
157#define USE_ELF_CORE_DUMP
158#define ELF_EXEC_PAGESIZE PAGE_SIZE
159
160/*
161 * This is the location that an ET_DYN program is loaded if exec'ed. Typical
162 * use of this is to invoke "./ld.so someprog" to test out a new version of
163 * the loader. We need to make sure that it is out of the way of the program
164 * that it will "exec", and that there is sufficient room for the brk.
165 */
166
167#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
168
169/*
170 * This yields a mask that user programs can use to figure out what
171 * instruction set this CPU supports. This could be done in user space,
172 * but it's not easy, and we've already done it here.
173 */
174
175#define ELF_HWCAP (0)
176
177/*
178 * This yields a string that ld.so will use to load implementation
179 * specific libraries for optimization. This is more specific in
180 * intent than poking at uname or /proc/cpuinfo.
181 * For the moment, we have only optimizations for the Intel generations,
182 * but that could change...
183 */
184
185#define ELF_PLATFORM (NULL)
186
187/*
188 * The Xtensa processor ABI says that when the program starts, a2
189 * contains a pointer to a function which might be registered using
190 * `atexit'. This provides a mean for the dynamic linker to call
191 * DT_FINI functions for shared libraries that have been loaded before
192 * the code runs.
193 *
194 * A value of 0 tells we have no such handler.
195 *
196 * We might as well make sure everything else is cleared too (except
197 * for the stack pointer in a1), just to make things more
198 * deterministic. Also, clearing a0 terminates debugger backtraces.
199 */
200
201#define ELF_PLAT_INIT(_r, load_addr) \
202 do { _r->areg[0]=0; /*_r->areg[1]=0;*/ _r->areg[2]=0; _r->areg[3]=0; \
203 _r->areg[4]=0; _r->areg[5]=0; _r->areg[6]=0; _r->areg[7]=0; \
204 _r->areg[8]=0; _r->areg[9]=0; _r->areg[10]=0; _r->areg[11]=0; \
205 _r->areg[12]=0; _r->areg[13]=0; _r->areg[14]=0; _r->areg[15]=0; \
206 } while (0)
207
208#ifdef __KERNEL__
209
210#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
211
212extern void do_copy_regs (xtensa_gregset_t*, struct pt_regs*,
213 struct task_struct*);
214extern void do_restore_regs (xtensa_gregset_t*, struct pt_regs*,
215 struct task_struct*);
216extern void do_save_fpregs (elf_fpregset_t*, struct pt_regs*,
217 struct task_struct*);
218extern int do_restore_fpregs (elf_fpregset_t*, struct pt_regs*,
219 struct task_struct*);
220
221#endif /* __KERNEL__ */
222#endif /* _XTENSA_ELF_H */
diff --git a/include/asm-xtensa/errno.h b/include/asm-xtensa/errno.h
new file mode 100644
index 0000000000..ced5194d27
--- /dev/null
+++ b/include/asm-xtensa/errno.h
@@ -0,0 +1,142 @@
1/*
2 * include/asm-xtensa/errno.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2002 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_ERRNO_H
12#define _XTENSA_ERRNO_H
13
14#define EPERM 1 /* Operation not permitted */
15#define ENOENT 2 /* No such file or directory */
16#define ESRCH 3 /* No such process */
17#define EINTR 4 /* Interrupted system call */
18#define EIO 5 /* I/O error */
19#define ENXIO 6 /* No such device or address */
20#define E2BIG 7 /* Arg list too long */
21#define ENOEXEC 8 /* Exec format error */
22#define EBADF 9 /* Bad file number */
23#define ECHILD 10 /* No child processes */
24#define EAGAIN 11 /* Try again */
25#define ENOMEM 12 /* Out of memory */
26#define EACCES 13 /* Permission denied */
27#define EFAULT 14 /* Bad address */
28#define ENOTBLK 15 /* Block device required */
29#define EBUSY 16 /* Device or resource busy */
30#define EEXIST 17 /* File exists */
31#define EXDEV 18 /* Cross-device link */
32#define ENODEV 19 /* No such device */
33#define ENOTDIR 20 /* Not a directory */
34#define EISDIR 21 /* Is a directory */
35#define EINVAL 22 /* Invalid argument */
36#define ENFILE 23 /* File table overflow */
37#define EMFILE 24 /* Too many open files */
38#define ENOTTY 25 /* Not a typewriter */
39#define ETXTBSY 26 /* Text file busy */
40#define EFBIG 27 /* File too large */
41#define ENOSPC 28 /* No space left on device */
42#define ESPIPE 29 /* Illegal seek */
43#define EROFS 30 /* Read-only file system */
44#define EMLINK 31 /* Too many links */
45#define EPIPE 32 /* Broken pipe */
46#define EDOM 33 /* Math argument out of domain of func */
47#define ERANGE 34 /* Math result not representable */
48#define EDEADLK 35 /* Resource deadlock would occur */
49#define ENAMETOOLONG 36 /* File name too long */
50#define ENOLCK 37 /* No record locks available */
51#define ENOSYS 38 /* Function not implemented */
52#define ENOTEMPTY 39 /* Directory not empty */
53#define ELOOP 40 /* Too many symbolic links encountered */
54#define EWOULDBLOCK EAGAIN /* Operation would block */
55#define ENOMSG 42 /* No message of desired type */
56#define EIDRM 43 /* Identifier removed */
57#define ECHRNG 44 /* Channel number out of range */
58#define EL2NSYNC 45 /* Level 2 not synchronized */
59#define EL3HLT 46 /* Level 3 halted */
60#define EL3RST 47 /* Level 3 reset */
61#define ELNRNG 48 /* Link number out of range */
62#define EUNATCH 49 /* Protocol driver not attached */
63#define ENOCSI 50 /* No CSI structure available */
64#define EL2HLT 51 /* Level 2 halted */
65#define EBADE 52 /* Invalid exchange */
66#define EBADR 53 /* Invalid request descriptor */
67#define EXFULL 54 /* Exchange full */
68#define ENOANO 55 /* No anode */
69#define EBADRQC 56 /* Invalid request code */
70#define EBADSLT 57 /* Invalid slot */
71
72#define EDEADLOCK EDEADLK
73
74#define EBFONT 59 /* Bad font file format */
75#define ENOSTR 60 /* Device not a stream */
76#define ENODATA 61 /* No data available */
77#define ETIME 62 /* Timer expired */
78#define ENOSR 63 /* Out of streams resources */
79#define ENONET 64 /* Machine is not on the network */
80#define ENOPKG 65 /* Package not installed */
81#define EREMOTE 66 /* Object is remote */
82#define ENOLINK 67 /* Link has been severed */
83#define EADV 68 /* Advertise error */
84#define ESRMNT 69 /* Srmount error */
85#define ECOMM 70 /* Communication error on send */
86#define EPROTO 71 /* Protocol error */
87#define EMULTIHOP 72 /* Multihop attempted */
88#define EDOTDOT 73 /* RFS specific error */
89#define EBADMSG 74 /* Not a data message */
90#define EOVERFLOW 75 /* Value too large for defined data type */
91#define ENOTUNIQ 76 /* Name not unique on network */
92#define EBADFD 77 /* File descriptor in bad state */
93#define EREMCHG 78 /* Remote address changed */
94#define ELIBACC 79 /* Can not access a needed shared library */
95#define ELIBBAD 80 /* Accessing a corrupted shared library */
96#define ELIBSCN 81 /* .lib section in a.out corrupted */
97#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
98#define ELIBEXEC 83 /* Cannot exec a shared library directly */
99#define EILSEQ 84 /* Illegal byte sequence */
100#define ERESTART 85 /* Interrupted system call should be restarted */
101#define ESTRPIPE 86 /* Streams pipe error */
102#define EUSERS 87 /* Too many users */
103#define ENOTSOCK 88 /* Socket operation on non-socket */
104#define EDESTADDRREQ 89 /* Destination address required */
105#define EMSGSIZE 90 /* Message too long */
106#define EPROTOTYPE 91 /* Protocol wrong type for socket */
107#define ENOPROTOOPT 92 /* Protocol not available */
108#define EPROTONOSUPPORT 93 /* Protocol not supported */
109#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
110#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
111#define EPFNOSUPPORT 96 /* Protocol family not supported */
112#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
113#define EADDRINUSE 98 /* Address already in use */
114#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
115#define ENETDOWN 100 /* Network is down */
116#define ENETUNREACH 101 /* Network is unreachable */
117#define ENETRESET 102 /* Network dropped connection because of reset */
118#define ECONNABORTED 103 /* Software caused connection abort */
119#define ECONNRESET 104 /* Connection reset by peer */
120#define ENOBUFS 105 /* No buffer space available */
121#define EISCONN 106 /* Transport endpoint is already connected */
122#define ENOTCONN 107 /* Transport endpoint is not connected */
123#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
124#define ETOOMANYREFS 109 /* Too many references: cannot splice */
125#define ETIMEDOUT 110 /* Connection timed out */
126#define ECONNREFUSED 111 /* Connection refused */
127#define EHOSTDOWN 112 /* Host is down */
128#define EHOSTUNREACH 113 /* No route to host */
129#define EALREADY 114 /* Operation already in progress */
130#define EINPROGRESS 115 /* Operation now in progress */
131#define ESTALE 116 /* Stale NFS file handle */
132#define EUCLEAN 117 /* Structure needs cleaning */
133#define ENOTNAM 118 /* Not a XENIX named type file */
134#define ENAVAIL 119 /* No XENIX semaphores available */
135#define EISNAM 120 /* Is a named type file */
136#define EREMOTEIO 121 /* Remote I/O error */
137#define EDQUOT 122 /* Quota exceeded */
138
139#define ENOMEDIUM 123 /* No medium found */
140#define EMEDIUMTYPE 124 /* Wrong medium type */
141
142#endif /* _XTENSA_ERRNO_H */
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h
new file mode 100644
index 0000000000..48876bb727
--- /dev/null
+++ b/include/asm-xtensa/fcntl.h
@@ -0,0 +1,101 @@
1/*
2 * include/asm-xtensa/fcntl.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
9 * Copyright (C) 2001 - 2005 Tensilica Inc.
10 */
11
12#ifndef _XTENSA_FCNTL_H
13#define _XTENSA_FCNTL_H
14
15/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
16 located on an ext2 file system */
17#define O_ACCMODE 0x0003
18#define O_RDONLY 0x0000
19#define O_WRONLY 0x0001
20#define O_RDWR 0x0002
21#define O_APPEND 0x0008
22#define O_SYNC 0x0010
23#define O_NONBLOCK 0x0080
24#define O_CREAT 0x0100 /* not fcntl */
25#define O_TRUNC 0x0200 /* not fcntl */
26#define O_EXCL 0x0400 /* not fcntl */
27#define O_NOCTTY 0x0800 /* not fcntl */
28#define FASYNC 0x1000 /* fcntl, for BSD compatibility */
29#define O_LARGEFILE 0x2000 /* allow large file opens - currently ignored */
30#define O_DIRECT 0x8000 /* direct disk access hint - currently ignored*/
31#define O_DIRECTORY 0x10000 /* must be a directory */
32#define O_NOFOLLOW 0x20000 /* don't follow links */
33#define O_NOATIME 0x100000
34
35#define O_NDELAY O_NONBLOCK
36
37#define F_DUPFD 0 /* dup */
38#define F_GETFD 1 /* get close_on_exec */
39#define F_SETFD 2 /* set/clear close_on_exec */
40#define F_GETFL 3 /* get file->f_flags */
41#define F_SETFL 4 /* set file->f_flags */
42#define F_GETLK 14
43#define F_GETLK64 15
44#define F_SETLK 6
45#define F_SETLKW 7
46#define F_SETLK64 16
47#define F_SETLKW64 17
48
49#define F_SETOWN 24 /* for sockets. */
50#define F_GETOWN 23 /* for sockets. */
51#define F_SETSIG 10 /* for sockets. */
52#define F_GETSIG 11 /* for sockets. */
53
54/* for F_[GET|SET]FL */
55#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
56
57/* for posix fcntl() and lockf() */
58#define F_RDLCK 0
59#define F_WRLCK 1
60#define F_UNLCK 2
61
62/* for old implementation of bsd flock () */
63#define F_EXLCK 4 /* or 3 */
64#define F_SHLCK 8 /* or 4 */
65
66/* for leases */
67#define F_INPROGRESS 16
68
69/* operations for bsd flock(), also used by the kernel implementation */
70#define LOCK_SH 1 /* shared lock */
71#define LOCK_EX 2 /* exclusive lock */
72#define LOCK_NB 4 /* or'd with one of the above to prevent
73 blocking */
74#define LOCK_UN 8 /* remove lock */
75
76#define LOCK_MAND 32 /* This is a mandatory flock ... */
77#define LOCK_READ 64 /* which allows concurrent read operations */
78#define LOCK_WRITE 128 /* which allows concurrent write operations */
79#define LOCK_RW 192 /* which allows concurrent read & write ops */
80
81typedef struct flock {
82 short l_type;
83 short l_whence;
84 __kernel_off_t l_start;
85 __kernel_off_t l_len;
86 long l_sysid;
87 __kernel_pid_t l_pid;
88 long pad[4];
89} flock_t;
90
91struct flock64 {
92 short l_type;
93 short l_whence;
94 __kernel_off_t l_start;
95 __kernel_off_t l_len;
96 pid_t l_pid;
97};
98
99#define F_LINUX_SPECIFIC_BASE 1024
100
101#endif /* _XTENSA_FCNTL_H */
diff --git a/include/asm-xtensa/fixmap.h b/include/asm-xtensa/fixmap.h
new file mode 100644
index 0000000000..4423b8ad49
--- /dev/null
+++ b/include/asm-xtensa/fixmap.h
@@ -0,0 +1,252 @@
1/*
2 * include/asm-xtensa/fixmap.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_FIXMAP_H
12#define _XTENSA_FIXMAP_H
13
14#include <asm/processor.h>
15
16#ifdef CONFIG_MMU
17
18/*
19 * Here we define all the compile-time virtual addresses.
20 */
21
22#if XCHAL_SEG_MAPPABLE_VADDR != 0
23# error "Current port requires virtual user space starting at 0"
24#endif
25#if XCHAL_SEG_MAPPABLE_SIZE < 0x80000000
26# error "Current port requires at least 0x8000000 bytes for user space"
27#endif
28
29/* Verify instruction/data ram/rom and xlmi don't overlay vmalloc space. */
30
31#define __IN_VMALLOC(addr) \
32 (((addr) >= VMALLOC_START) && ((addr) < VMALLOC_END))
33#define __SPAN_VMALLOC(start,end) \
34 (((start) < VMALLOC_START) && ((end) >= VMALLOC_END))
35#define INSIDE_VMALLOC(start,end) \
36 (__IN_VMALLOC((start)) || __IN_VMALLOC(end) || __SPAN_VMALLOC((start),(end)))
37
38#if XCHAL_NUM_INSTROM
39# if XCHAL_NUM_INSTROM == 1
40# if INSIDE_VMALLOC(XCHAL_INSTROM0_VADDR,XCHAL_INSTROM0_VADDR+XCHAL_INSTROM0_SIZE)
41# error vmalloc range conflicts with instrom0
42# endif
43# endif
44# if XCHAL_NUM_INSTROM == 2
45# if INSIDE_VMALLOC(XCHAL_INSTROM1_VADDR,XCHAL_INSTROM1_VADDR+XCHAL_INSTROM1_SIZE)
46# error vmalloc range conflicts with instrom1
47# endif
48# endif
49#endif
50
51#if XCHAL_NUM_INSTRAM
52# if XCHAL_NUM_INSTRAM == 1
53# if INSIDE_VMALLOC(XCHAL_INSTRAM0_VADDR,XCHAL_INSTRAM0_VADDR+XCHAL_INSTRAM0_SIZE)
54# error vmalloc range conflicts with instram0
55# endif
56# endif
57# if XCHAL_NUM_INSTRAM == 2
58# if INSIDE_VMALLOC(XCHAL_INSTRAM1_VADDR,XCHAL_INSTRAM1_VADDR+XCHAL_INSTRAM1_SIZE)
59# error vmalloc range conflicts with instram1
60# endif
61# endif
62#endif
63
64#if XCHAL_NUM_DATAROM
65# if XCHAL_NUM_DATAROM == 1
66# if INSIDE_VMALLOC(XCHAL_DATAROM0_VADDR,XCHAL_DATAROM0_VADDR+XCHAL_DATAROM0_SIZE)
67# error vmalloc range conflicts with datarom0
68# endif
69# endif
70# if XCHAL_NUM_DATAROM == 2
71# if INSIDE_VMALLOC(XCHAL_DATAROM1_VADDR,XCHAL_DATAROM1_VADDR+XCHAL_DATAROM1_SIZE)
72# error vmalloc range conflicts with datarom1
73# endif
74# endif
75#endif
76
77#if XCHAL_NUM_DATARAM
78# if XCHAL_NUM_DATARAM == 1
79# if INSIDE_VMALLOC(XCHAL_DATARAM0_VADDR,XCHAL_DATARAM0_VADDR+XCHAL_DATARAM0_SIZE)
80# error vmalloc range conflicts with dataram0
81# endif
82# endif
83# if XCHAL_NUM_DATARAM == 2
84# if INSIDE_VMALLOC(XCHAL_DATARAM1_VADDR,XCHAL_DATARAM1_VADDR+XCHAL_DATARAM1_SIZE)
85# error vmalloc range conflicts with dataram1
86# endif
87# endif
88#endif
89
90#if XCHAL_NUM_XLMI
91# if XCHAL_NUM_XLMI == 1
92# if INSIDE_VMALLOC(XCHAL_XLMI0_VADDR,XCHAL_XLMI0_VADDR+XCHAL_XLMI0_SIZE)
93# error vmalloc range conflicts with xlmi0
94# endif
95# endif
96# if XCHAL_NUM_XLMI == 2
97# if INSIDE_VMALLOC(XCHAL_XLMI1_VADDR,XCHAL_XLMI1_VADDR+XCHAL_XLMI1_SIZE)
98# error vmalloc range conflicts with xlmi1
99# endif
100# endif
101#endif
102
103#if (XCHAL_NUM_INSTROM > 2) || \
104 (XCHAL_NUM_INSTRAM > 2) || \
105 (XCHAL_NUM_DATARAM > 2) || \
106 (XCHAL_NUM_DATAROM > 2) || \
107 (XCHAL_NUM_XLMI > 2)
108# error Insufficient checks on vmalloc above for more than 2 devices
109#endif
110
111/*
112 * USER_VM_SIZE does not necessarily equal TASK_SIZE. We bumped
113 * TASK_SIZE down to 0x4000000 to simplify the handling of windowed
114 * call instructions (currently limited to a range of 1 GByte). User
115 * tasks may very well reclaim the VM space from 0x40000000 to
116 * 0x7fffffff in the future, so we do not want the kernel becoming
117 * accustomed to having any of its stuff (e.g., page tables) in this
118 * region. This VM region is no-man's land for now.
119 */
120
121#define USER_VM_START XCHAL_SEG_MAPPABLE_VADDR
122#define USER_VM_SIZE 0x80000000
123
124/* Size of page table: */
125
126#define PGTABLE_SIZE_BITS (32 - XCHAL_MMU_MIN_PTE_PAGE_SIZE + 2)
127#define PGTABLE_SIZE (1L << PGTABLE_SIZE_BITS)
128
129/* All kernel-mappable space: */
130
131#define KERNEL_ALLMAP_START (USER_VM_START + USER_VM_SIZE)
132#define KERNEL_ALLMAP_SIZE (XCHAL_SEG_MAPPABLE_SIZE - KERNEL_ALLMAP_START)
133
134/* Carve out page table at start of kernel-mappable area: */
135
136#if KERNEL_ALLMAP_SIZE < PGTABLE_SIZE
137#error "Gimme some space for page table!"
138#endif
139#define PGTABLE_START KERNEL_ALLMAP_START
140
141/* Remaining kernel-mappable space: */
142
143#define KERNEL_MAPPED_START (KERNEL_ALLMAP_START + PGTABLE_SIZE)
144#define KERNEL_MAPPED_SIZE (KERNEL_ALLMAP_SIZE - PGTABLE_SIZE)
145
146#if KERNEL_MAPPED_SIZE < 0x01000000 /* 16 MB is arbitrary for now */
147# error "Shouldn't the kernel have at least *some* mappable space?"
148#endif
149
150#define MAX_LOW_MEMORY XCHAL_KSEG_CACHED_SIZE
151
152#endif
153
154/*
155 * Some constants used elsewhere, but perhaps only in Xtensa header
156 * files, so maybe we can get rid of some and access compile-time HAL
157 * directly...
158 *
159 * Note: We assume that system RAM is located at the very start of the
160 * kernel segments !!
161 */
162#define KERNEL_VM_LOW XCHAL_KSEG_CACHED_VADDR
163#define KERNEL_VM_HIGH XCHAL_KSEG_BYPASS_VADDR
164#define KERNEL_SPACE XCHAL_KSEG_CACHED_VADDR
165
166/*
167 * Returns the physical/virtual addresses of the kernel space
168 * (works with the cached kernel segment only, which is the
169 * one normally used for kernel operation).
170 */
171
172/* PHYSICAL BYPASS CACHED
173 *
174 * bypass vaddr bypass paddr * cached vaddr
175 * cached vaddr cached paddr bypass vaddr *
176 * bypass paddr * bypass vaddr cached vaddr
177 * cached paddr * bypass vaddr cached vaddr
178 * other * * *
179 */
180
181#define PHYSADDR(a) \
182(((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR \
183 && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
184 (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_PADDR : \
185 ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR \
186 && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_SIZE) ? \
187 (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_PADDR : \
188 (unsigned)(a))
189
190#define BYPASS_ADDR(a) \
191(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR \
192 && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
193 (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_VADDR : \
194 ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR \
195 && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ? \
196 (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_BYPASS_VADDR : \
197 ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR \
198 && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_CACHED_SIZE)? \
199 (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_BYPASS_VADDR: \
200 (unsigned)(a))
201
202#define CACHED_ADDR(a) \
203(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR \
204 && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
205 (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_CACHED_VADDR : \
206 ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR \
207 && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ? \
208 (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_VADDR : \
209 ((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR \
210 && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_BYPASS_SIZE) ? \
211 (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_CACHED_VADDR : \
212 (unsigned)(a))
213
214#define PHYSADDR_IO(a) \
215(((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR \
216 && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ? \
217 (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_PADDR : \
218 ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR \
219 && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ? \
220 (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_PADDR : \
221 (unsigned)(a))
222
223#define BYPASS_ADDR_IO(a) \
224(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR \
225 && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ? \
226 (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_VADDR : \
227 ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR \
228 && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ? \
229 (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_BYPASS_VADDR : \
230 ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR \
231 && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ? \
232 (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_BYPASS_VADDR : \
233 (unsigned)(a))
234
235#define CACHED_ADDR_IO(a) \
236(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR \
237 && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ? \
238 (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_CACHED_VADDR : \
239 ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR \
240 && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ? \
241 (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_VADDR : \
242 ((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR \
243 && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ? \
244 (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_CACHED_VADDR : \
245 (unsigned)(a))
246
247#endif /* _XTENSA_ADDRSPACE_H */
248
249
250
251
252
diff --git a/include/asm-xtensa/hardirq.h b/include/asm-xtensa/hardirq.h
new file mode 100644
index 0000000000..e07c76c36b
--- /dev/null
+++ b/include/asm-xtensa/hardirq.h
@@ -0,0 +1,28 @@
1/*
2 * include/asm-xtensa/hardirq.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2002 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_HARDIRQ_H
12#define _XTENSA_HARDIRQ_H
13
14#include <linux/config.h>
15#include <linux/cache.h>
16#include <asm/irq.h>
17
18/* headers.S is sensitive to the offsets of these fields */
19typedef struct {
20 unsigned int __softirq_pending;
21 unsigned int __syscall_count;
22 struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
23 unsigned int __nmi_count; /* arch dependent */
24} ____cacheline_aligned irq_cpustat_t;
25
26#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
27
28#endif /* _XTENSA_HARDIRQ_H */
diff --git a/include/asm-xtensa/hdreg.h b/include/asm-xtensa/hdreg.h
new file mode 100644
index 0000000000..64b80607b8
--- /dev/null
+++ b/include/asm-xtensa/hdreg.h
@@ -0,0 +1,17 @@
1/*
2 * include/asm-xtensa/hdreg.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2002 - 2005 Tensilica Inc.
9 * Copyright (C) 1994-1996 Linus Torvalds & authors
10 */
11
12#ifndef _XTENSA_HDREG_H
13#define _XTENSA_HDREG_H
14
15typedef unsigned int ide_ioreg_t;
16
17#endif
diff --git a/include/asm-xtensa/highmem.h b/include/asm-xtensa/highmem.h
new file mode 100644
index 0000000000..0a046ca5a6
--- /dev/null
+++ b/include/asm-xtensa/highmem.h
@@ -0,0 +1,17 @@
1/*
2 * include/asm-xtensa/highmem.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2003 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_HIGHMEM_H
12#define _XTENSA_HIGHMEM_H
13
14extern void flush_cache_kmaps(void);
15
16#endif
17
diff --git a/include/asm-xtensa/hw_irq.h b/include/asm-xtensa/hw_irq.h
new file mode 100644
index 0000000000..ccf436249e
--- /dev/null
+++ b/include/asm-xtensa/hw_irq.h
@@ -0,0 +1,18 @@
1/*
2 * include/asm-xtensa/hw_irq.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2002 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_HW_IRQ_H
12#define _XTENSA_HW_IRQ_H
13
14static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
15{
16}
17
18#endif
diff --git a/include/asm-xtensa/ide.h b/include/asm-xtensa/ide.h
new file mode 100644
index 0000000000..b523cd4a48
--- /dev/null
+++ b/include/asm-xtensa/ide.h
@@ -0,0 +1,36 @@
1/*
2 * include/asm-xtensa/ide.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1994 - 1996 Linus Torvalds & authors
9 * Copyright (C) 2001 - 2005 Tensilica Inc.
10 */
11
12#ifndef _XTENSA_IDE_H
13#define _XTENSA_IDE_H
14
15#ifdef __KERNEL__
16
17#include <linux/config.h>
18
19#ifndef MAX_HWIFS
20# define MAX_HWIFS 1
21#endif
22
23static __inline__ int ide_default_irq(unsigned long base)
24{
25 /* Unsupported! */
26 return 0;
27}
28
29static __inline__ unsigned long ide_default_io_base(int index)
30{
31 /* Unsupported! */
32 return 0;
33}
34
35#endif /* __KERNEL__ */
36#endif /* _XTENSA_IDE_H */
diff --git a/include/asm-xtensa/io.h b/include/asm-xtensa/io.h
new file mode 100644
index 0000000000..2c471c42ec
--- /dev/null
+++ b/include/asm-xtensa/io.h
@@ -0,0 +1,197 @@
1/*
2 * linux/include/asm-xtensa/io.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_IO_H
12#define _XTENSA_IO_H
13
14#ifdef __KERNEL__
15#include <linux/config.h>
16#include <asm/byteorder.h>
17
18#include <linux/types.h>
19#include <asm/fixmap.h>
20
21#define _IO_BASE 0
22
23
24/*
25 * swap functions to change byte order from little-endian to big-endian and
26 * vice versa.
27 */
28
29static inline unsigned short _swapw (unsigned short v)
30{
31 return (v << 8) | (v >> 8);
32}
33
34static inline unsigned int _swapl (unsigned int v)
35{
36 return (v << 24) | ((v & 0xff00) << 8) | ((v >> 8) & 0xff00) | (v >> 24);
37}
38
39/*
40 * Change virtual addresses to physical addresses and vv.
41 * These are trivial on the 1:1 Linux/Xtensa mapping
42 */
43
44extern inline unsigned long virt_to_phys(volatile void * address)
45{
46 return PHYSADDR((unsigned long)address);
47}
48
49extern inline void * phys_to_virt(unsigned long address)
50{
51 return (void*) CACHED_ADDR(address);
52}
53
54/*
55 * IO bus memory addresses are also 1:1 with the physical address
56 */
57
58extern inline unsigned long virt_to_bus(volatile void * address)
59{
60 return PHYSADDR((unsigned long)address);
61}
62
63extern inline void * bus_to_virt (unsigned long address)
64{
65 return (void *) CACHED_ADDR(address);
66}
67
68/*
69 * Change "struct page" to physical address.
70 */
71
72extern inline void *ioremap(unsigned long offset, unsigned long size)
73{
74 return (void *) CACHED_ADDR_IO(offset);
75}
76
77extern inline void *ioremap_nocache(unsigned long offset, unsigned long size)
78{
79 return (void *) BYPASS_ADDR_IO(offset);
80}
81
82extern inline void iounmap(void *addr)
83{
84}
85
86/*
87 * Generic I/O
88 */
89
90#define readb(addr) \
91 ({ unsigned char __v = (*(volatile unsigned char *)(addr)); __v; })
92#define readw(addr) \
93 ({ unsigned short __v = (*(volatile unsigned short *)(addr)); __v; })
94#define readl(addr) \
95 ({ unsigned int __v = (*(volatile unsigned int *)(addr)); __v; })
96#define writeb(b, addr) (void)((*(volatile unsigned char *)(addr)) = (b))
97#define writew(b, addr) (void)((*(volatile unsigned short *)(addr)) = (b))
98#define writel(b, addr) (void)((*(volatile unsigned int *)(addr)) = (b))
99
100static inline __u8 __raw_readb(const volatile void __iomem *addr)
101{
102 return *(__force volatile __u8 *)(addr);
103}
104static inline __u16 __raw_readw(const volatile void __iomem *addr)
105{
106 return *(__force volatile __u16 *)(addr);
107}
108static inline __u32 __raw_readl(const volatile void __iomem *addr)
109{
110 return *(__force volatile __u32 *)(addr);
111}
112static inline void __raw_writeb(__u8 b, volatile void __iomem *addr)
113{
114 *(__force volatile __u8 *)(addr) = b;
115}
116static inline void __raw_writew(__u16 b, volatile void __iomem *addr)
117{
118 *(__force volatile __u16 *)(addr) = b;
119}
120static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
121{
122 *(__force volatile __u32 *)(addr) = b;
123}
124
125
126
127
128/* These are the definitions for the x86 IO instructions
129 * inb/inw/inl/outb/outw/outl, the "string" versions
130 * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
131 * inb_p/inw_p/...
132 * The macros don't do byte-swapping.
133 */
134
135#define inb(port) readb((u8 *)((port)+_IO_BASE))
136#define outb(val, port) writeb((val),(u8 *)((unsigned long)(port)+_IO_BASE))
137#define inw(port) readw((u16 *)((port)+_IO_BASE))
138#define outw(val, port) writew((val),(u16 *)((unsigned long)(port)+_IO_BASE))
139#define inl(port) readl((u32 *)((port)+_IO_BASE))
140#define outl(val, port) writel((val),(u32 *)((unsigned long)(port)))
141
142#define inb_p(port) inb((port))
143#define outb_p(val, port) outb((val), (port))
144#define inw_p(port) inw((port))
145#define outw_p(val, port) outw((val), (port))
146#define inl_p(port) inl((port))
147#define outl_p(val, port) outl((val), (port))
148
149extern void insb (unsigned long port, void *dst, unsigned long count);
150extern void insw (unsigned long port, void *dst, unsigned long count);
151extern void insl (unsigned long port, void *dst, unsigned long count);
152extern void outsb (unsigned long port, const void *src, unsigned long count);
153extern void outsw (unsigned long port, const void *src, unsigned long count);
154extern void outsl (unsigned long port, const void *src, unsigned long count);
155
156#define IO_SPACE_LIMIT ~0
157
158#define memset_io(a,b,c) memset((void *)(a),(b),(c))
159#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
160#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
161
162/* At this point the Xtensa doesn't provide byte swap instructions */
163
164#ifdef __XTENSA_EB__
165# define in_8(addr) (*(u8*)(addr))
166# define in_le16(addr) _swapw(*(u16*)(addr))
167# define in_le32(addr) _swapl(*(u32*)(addr))
168# define out_8(b, addr) *(u8*)(addr) = (b)
169# define out_le16(b, addr) *(u16*)(addr) = _swapw(b)
170# define out_le32(b, addr) *(u32*)(addr) = _swapl(b)
171#elif defined(__XTENSA_EL__)
172# define in_8(addr) (*(u8*)(addr))
173# define in_le16(addr) (*(u16*)(addr))
174# define in_le32(addr) (*(u32*)(addr))
175# define out_8(b, addr) *(u8*)(addr) = (b)
176# define out_le16(b, addr) *(u16*)(addr) = (b)
177# define out_le32(b, addr) *(u32*)(addr) = (b)
178#else
179# error processor byte order undefined!
180#endif
181
182
183/*
184 * * Convert a physical pointer to a virtual kernel pointer for /dev/mem
185 * * access
186 * */
187#define xlate_dev_mem_ptr(p) __va(p)
188
189/*
190 * * Convert a virtual cached pointer to an uncached pointer
191 * */
192#define xlate_dev_kmem_ptr(p) p
193
194
195#endif /* __KERNEL__ */
196
197#endif /* _XTENSA_IO_H */
diff --git a/include/asm-xtensa/ioctl.h b/include/asm-xtensa/ioctl.h
new file mode 100644
index 0000000000..856c605d62
--- /dev/null
+++ b/include/asm-xtensa/ioctl.h
@@ -0,0 +1,83 @@
1/*
2 * include/asm-xtensa/ioctl.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2003 - 2005 Tensilica Inc.
9 *
10 * Derived from "include/asm-i386/ioctl.h"
11 */
12
13#ifndef _XTENSA_IOCTL_H
14#define _XTENSA_IOCTL_H
15
16
17/* ioctl command encoding: 32 bits total, command in lower 16 bits,
18 * size of the parameter structure in the lower 14 bits of the
19 * upper 16 bits.
20 * Encoding the size of the parameter structure in the ioctl request
21 * is useful for catching programs compiled with old versions
22 * and to avoid overwriting user space outside the user buffer area.
23 * The highest 2 bits are reserved for indicating the ``access mode''.
24 * NOTE: This limits the max parameter size to 16kB -1 !
25 */
26
27/*
28 * The following is for compatibility across the various Linux
29 * platforms. The i386 ioctl numbering scheme doesn't really enforce
30 * a type field. De facto, however, the top 8 bits of the lower 16
31 * bits are indeed used as a type field, so we might just as well make
32 * this explicit here. Please be sure to use the decoding macros
33 * below from now on.
34 */
35#define _IOC_NRBITS 8
36#define _IOC_TYPEBITS 8
37#define _IOC_SIZEBITS 14
38#define _IOC_DIRBITS 2
39
40#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
41#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
42#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
43#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
44
45#define _IOC_NRSHIFT 0
46#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
47#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
48#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
49
50/*
51 * Direction bits.
52 */
53#define _IOC_NONE 0U
54#define _IOC_WRITE 1U
55#define _IOC_READ 2U
56
57#define _IOC(dir,type,nr,size) \
58 (((dir) << _IOC_DIRSHIFT) | \
59 ((type) << _IOC_TYPESHIFT) | \
60 ((nr) << _IOC_NRSHIFT) | \
61 ((size) << _IOC_SIZESHIFT))
62
63/* used to create numbers */
64#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
65#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
66#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
67#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
68
69/* used to decode ioctl numbers.. */
70#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
71#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
72#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
73#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
74
75/* ...and for the drivers/sound files... */
76
77#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
78#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
79#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
80#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
81#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
82
83#endif
diff --git a/include/asm-xtensa/ioctls.h b/include/asm-xtensa/ioctls.h
new file mode 100644
index 0000000000..10c443435c
--- /dev/null
+++ b/include/asm-xtensa/ioctls.h
@@ -0,0 +1,112 @@
1/*
2 * include/asm-xtensa/ioctl.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2003 - 2005 Tensilica Inc.
9 *
10 * Derived from "include/asm-i386/ioctls.h"
11 */
12
13#ifndef _XTENSA_IOCTLS_H
14#define _XTENSA_IOCTLS_H
15
16#include <asm/ioctl.h>
17
18#define FIOCLEX _IO('f', 1)
19#define FIONCLEX _IO('f', 2)
20#define FIOASYNC _IOW('f', 125, int)
21#define FIONBIO _IOW('f', 126, int)
22#define FIONREAD _IOR('f', 127, int)
23#define TIOCINQ FIONREAD
24#define FIOQSIZE _IOR('f', 128, loff_t)
25
26#define TCGETS 0x5401
27#define TCSETS 0x5402
28#define TCSETSW 0x5403
29#define TCSETSF 0x5404
30
31#define TCGETA _IOR('t', 23, struct termio)
32#define TCSETA _IOW('t', 24, struct termio)
33#define TCSETAW _IOW('t', 25, struct termio)
34#define TCSETAF _IOW('t', 28, struct termio)
35
36#define TCSBRK _IO('t', 29)
37#define TCXONC _IO('t', 30)
38#define TCFLSH _IO('t', 31)
39
40#define TIOCSWINSZ _IOW('t', 103, struct winsize)
41#define TIOCGWINSZ _IOR('t', 104, struct winsize)
42#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
43#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
44#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
45
46#define TIOCSPGRP _IOW('t', 118, int)
47#define TIOCGPGRP _IOR('t', 119, int)
48
49#define TIOCEXCL _IO('T', 12)
50#define TIOCNXCL _IO('T', 13)
51#define TIOCSCTTY _IO('T', 14)
52
53#define TIOCSTI _IOW('T', 18, char)
54#define TIOCMGET _IOR('T', 21, unsigned int)
55#define TIOCMBIS _IOW('T', 22, unsigned int)
56#define TIOCMBIC _IOW('T', 23, unsigned int)
57#define TIOCMSET _IOW('T', 24, unsigned int)
58# define TIOCM_LE 0x001
59# define TIOCM_DTR 0x002
60# define TIOCM_RTS 0x004
61# define TIOCM_ST 0x008
62# define TIOCM_SR 0x010
63# define TIOCM_CTS 0x020
64# define TIOCM_CAR 0x040
65# define TIOCM_RNG 0x080
66# define TIOCM_DSR 0x100
67# define TIOCM_CD TIOCM_CAR
68# define TIOCM_RI TIOCM_RNG
69
70#define TIOCGSOFTCAR _IOR('T', 25, unsigned int)
71#define TIOCSSOFTCAR _IOW('T', 26, unsigned int)
72#define TIOCLINUX _IOW('T', 28, char)
73#define TIOCCONS _IO('T', 29)
74#define TIOCGSERIAL _IOR('T', 30, struct serial_struct)
75#define TIOCSSERIAL _IOW('T', 31, struct serial_struct)
76#define TIOCPKT _IOW('T', 32, int)
77# define TIOCPKT_DATA 0
78# define TIOCPKT_FLUSHREAD 1
79# define TIOCPKT_FLUSHWRITE 2
80# define TIOCPKT_STOP 4
81# define TIOCPKT_START 8
82# define TIOCPKT_NOSTOP 16
83# define TIOCPKT_DOSTOP 32
84
85
86#define TIOCNOTTY _IO('T', 34)
87#define TIOCSETD _IOW('T', 35, int)
88#define TIOCGETD _IOR('T', 36, int)
89#define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/
90#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/
91#define TIOCSBRK _IO('T', 39) /* BSD compatibility */
92#define TIOCCBRK _IO('T', 40) /* BSD compatibility */
93#define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/
94#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
95#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
96
97#define TIOCSERCONFIG _IO('T', 83)
98#define TIOCSERGWILD _IOR('T', 84, int)
99#define TIOCSERSWILD _IOW('T', 85, int)
100#define TIOCGLCKTRMIOS 0x5456
101#define TIOCSLCKTRMIOS 0x5457
102#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
103#define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */
104 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
105# define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
106#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config */
107#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
108
109#define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */
110#define TIOCGICOUNT _IOR('T', 93, struct async_icount) /* read serial port inline interrupt counts */
111
112#endif /* _XTENSA_IOCTLS_H */
diff --git a/include/asm-xtensa/ipc.h b/include/asm-xtensa/ipc.h
new file mode 100644
index 0000000000..d37bdb4d4c
--- /dev/null
+++ b/include/asm-xtensa/ipc.h
@@ -0,0 +1,34 @@
1/*
2 * include/asm-xtensa/ipc.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_IPC_H
12#define _XTENSA_IPC_H
13
14struct ipc_kludge {
15 struct msgbuf __user *msgp;
16 long msgtyp;
17};
18
19#define SEMOP 1
20#define SEMGET 2
21#define SEMCTL 3
22#define SEMTIMEDOP 4
23#define MSGSND 11
24#define MSGRCV 12
25#define MSGGET 13
26#define MSGCTL 14
27#define SHMAT 21
28#define SHMDT 22
29#define SHMGET 23
30#define SHMCTL 24
31
32#define IPCCALL(version,op) ((version)<<16 | (op))
33
34#endif /* _XTENSA_IPC_H */
diff --git a/include/asm-xtensa/ipcbuf.h b/include/asm-xtensa/ipcbuf.h
new file mode 100644
index 0000000000..c33aa6a421
--- /dev/null
+++ b/include/asm-xtensa/ipcbuf.h
@@ -0,0 +1,37 @@
1/*
2 * include/asm-xtensa/ipcbuf.h
3 *
4 * The ipc64_perm structure for the Xtensa architecture.
5 * Note extra padding because this structure is passed back and forth
6 * between kernel and user space.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_IPCBUF_H
12#define _XTENSA_IPCBUF_H
13
14/*
15 * Pad space is left for:
16 * - 32-bit mode_t and seq
17 * - 2 miscellaneous 32-bit values
18 *
19 * This file is subject to the terms and conditions of the GNU General
20 * Public License. See the file "COPYING" in the main directory of
21 * this archive for more details.
22 */
23
24struct ipc64_perm
25{
26 __kernel_key_t key;
27 __kernel_uid32_t uid;
28 __kernel_gid32_t gid;
29 __kernel_uid32_t cuid;
30 __kernel_gid32_t cgid;
31 __kernel_mode_t mode;
32 unsigned long seq;
33 unsigned long __unused1;
34 unsigned long __unused2;
35};
36
37#endif /* _XTENSA_IPCBUF_H */
diff --git a/include/asm-xtensa/irq.h b/include/asm-xtensa/irq.h
new file mode 100644
index 0000000000..d984e95593
--- /dev/null
+++ b/include/asm-xtensa/irq.h
@@ -0,0 +1,37 @@
1/*
2 * include/asm-xtensa/irq.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_IRQ_H
12#define _XTENSA_IRQ_H
13
14#include <linux/config.h>
15#include <asm/platform/hardware.h>
16
17#include <xtensa/config/core.h>
18
19#ifndef PLATFORM_NR_IRQS
20# define PLATFORM_NR_IRQS 0
21#endif
22#define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
23#define NR_IRQS (XTENSA_NR_IRQS + PLATFORM_NR_IRQS)
24
25static __inline__ int irq_canonicalize(int irq)
26{
27 return (irq);
28}
29
30struct irqaction;
31#if 0 // FIXME
32extern void disable_irq_nosync(unsigned int);
33extern void disable_irq(unsigned int);
34extern void enable_irq(unsigned int);
35#endif
36
37#endif /* _XTENSA_IRQ_H */
diff --git a/include/asm-xtensa/kmap_types.h b/include/asm-xtensa/kmap_types.h
new file mode 100644
index 0000000000..9e822d2e3b
--- /dev/null
+++ b/include/asm-xtensa/kmap_types.h
@@ -0,0 +1,31 @@
1/*
2 * include/asm-xtensa/kmap_types.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_KMAP_TYPES_H
12#define _XTENSA_KMAP_TYPES_H
13
14enum km_type {
15 KM_BOUNCE_READ,
16 KM_SKB_SUNRPC_DATA,
17 KM_SKB_DATA_SOFTIRQ,
18 KM_USER0,
19 KM_USER1,
20 KM_BIO_SRC_IRQ,
21 KM_BIO_DST_IRQ,
22 KM_PTE0,
23 KM_PTE1,
24 KM_IRQ0,
25 KM_IRQ1,
26 KM_SOFTIRQ0,
27 KM_SOFTIRQ1,
28 KM_TYPE_NR
29};
30
31#endif /* _XTENSA_KMAP_TYPES_H */
diff --git a/include/asm-xtensa/linkage.h b/include/asm-xtensa/linkage.h
new file mode 100644
index 0000000000..bf2128a99d
--- /dev/null
+++ b/include/asm-xtensa/linkage.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/linkage.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_LINKAGE_H
12#define _XTENSA_LINKAGE_H
13
14/* Nothing to do here ... */
15
16#endif /* _XTENSA_LINKAGE_H */
diff --git a/include/asm-xtensa/local.h b/include/asm-xtensa/local.h
new file mode 100644
index 0000000000..48723e550d
--- /dev/null
+++ b/include/asm-xtensa/local.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/local.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_LOCAL_H
12#define _XTENSA_LOCAL_H
13
14#include <asm-generic/local.h>
15
16#endif /* _XTENSA_LOCAL_H */
diff --git a/include/asm-xtensa/mman.h b/include/asm-xtensa/mman.h
new file mode 100644
index 0000000000..9a95a45df9
--- /dev/null
+++ b/include/asm-xtensa/mman.h
@@ -0,0 +1,80 @@
1/*
2 * include/asm-xtensa/mman.h
3 *
4 * Xtensa Processor memory-manager definitions
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 1995 by Ralf Baechle
11 * Copyright (C) 2001 - 2005 Tensilica Inc.
12 */
13
14#ifndef _XTENSA_MMAN_H
15#define _XTENSA_MMAN_H
16
17/*
18 * Protections are chosen from these bits, OR'd together. The
19 * implementation does not necessarily support PROT_EXEC or PROT_WRITE
20 * without PROT_READ. The only guarantees are that no writing will be
21 * allowed without PROT_WRITE and no access will be allowed for PROT_NONE.
22 */
23
24#define PROT_NONE 0x0 /* page can not be accessed */
25#define PROT_READ 0x1 /* page can be read */
26#define PROT_WRITE 0x2 /* page can be written */
27#define PROT_EXEC 0x4 /* page can be executed */
28
29#define PROT_SEM 0x10 /* page may be used for atomic ops */
30#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
31#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end fo growsup vma */
32
33/*
34 * Flags for mmap
35 */
36#define MAP_SHARED 0x001 /* Share changes */
37#define MAP_PRIVATE 0x002 /* Changes are private */
38#define MAP_TYPE 0x00f /* Mask for type of mapping */
39#define MAP_FIXED 0x010 /* Interpret addr exactly */
40
41/* not used by linux, but here to make sure we don't clash with ABI defines */
42#define MAP_RENAME 0x020 /* Assign page to file */
43#define MAP_AUTOGROW 0x040 /* File may grow by writing */
44#define MAP_LOCAL 0x080 /* Copy on fork/sproc */
45#define MAP_AUTORSRV 0x100 /* Logical swap reserved on demand */
46
47/* These are linux-specific */
48#define MAP_NORESERVE 0x0400 /* don't check for reservations */
49#define MAP_ANONYMOUS 0x0800 /* don't use a file */
50#define MAP_GROWSDOWN 0x1000 /* stack-like segment */
51#define MAP_DENYWRITE 0x2000 /* ETXTBSY */
52#define MAP_EXECUTABLE 0x4000 /* mark it as an executable */
53#define MAP_LOCKED 0x8000 /* pages are locked */
54#define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */
55#define MAP_NONBLOCK 0x20000 /* do not block on IO */
56
57/*
58 * Flags for msync
59 */
60#define MS_ASYNC 0x0001 /* sync memory asynchronously */
61#define MS_INVALIDATE 0x0002 /* invalidate mappings & caches */
62#define MS_SYNC 0x0004 /* synchronous memory sync */
63
64/*
65 * Flags for mlockall
66 */
67#define MCL_CURRENT 1 /* lock all current mappings */
68#define MCL_FUTURE 2 /* lock all future mappings */
69
70#define MADV_NORMAL 0x0 /* default page-in behavior */
71#define MADV_RANDOM 0x1 /* page-in minimum required */
72#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
73#define MADV_WILLNEED 0x3 /* pre-fault pages */
74#define MADV_DONTNEED 0x4 /* discard these pages */
75
76/* compatibility flags */
77#define MAP_ANON MAP_ANONYMOUS
78#define MAP_FILE 0
79
80#endif /* _XTENSA_MMAN_H */
diff --git a/include/asm-xtensa/mmu.h b/include/asm-xtensa/mmu.h
new file mode 100644
index 0000000000..44c5bb04c5
--- /dev/null
+++ b/include/asm-xtensa/mmu.h
@@ -0,0 +1,17 @@
1/*
2 * include/asm-xtensa/mmu.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_MMU_H
12#define _XTENSA_MMU_H
13
14/* Default "unsigned long" context */
15typedef unsigned long mm_context_t;
16
17#endif /* _XTENSA_MMU_H */
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
new file mode 100644
index 0000000000..1b0801548c
--- /dev/null
+++ b/include/asm-xtensa/mmu_context.h
@@ -0,0 +1,330 @@
1/*
2 * include/asm-xtensa/mmu_context.h
3 *
4 * Switch an MMU context.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_MMU_CONTEXT_H
14#define _XTENSA_MMU_CONTEXT_H
15
16#include <linux/config.h>
17#include <linux/stringify.h>
18
19#include <asm/pgtable.h>
20#include <asm/mmu_context.h>
21#include <asm/cacheflush.h>
22#include <asm/tlbflush.h>
23
24/*
25 * Linux was ported to Xtensa assuming all auto-refill ways in set 0
26 * had the same properties (a very likely assumption). Multiple sets
27 * of auto-refill ways will still work properly, but not as optimally
28 * as the Xtensa designer may have assumed.
29 *
30 * We make this case a hard #error, killing the kernel build, to alert
31 * the developer to this condition (which is more likely an error).
32 * You super-duper clever developers can change it to a warning or
33 * remove it altogether if you think you know what you're doing. :)
34 */
35
36#if (XCHAL_HAVE_TLBS != 1)
37# error "Linux must have an MMU!"
38#endif
39
40#if ((XCHAL_ITLB_ARF_WAYS == 0) || (XCHAL_DTLB_ARF_WAYS == 0))
41# error "MMU must have auto-refill ways"
42#endif
43
44#if ((XCHAL_ITLB_ARF_SETS != 1) || (XCHAL_DTLB_ARF_SETS != 1))
45# error Linux may not use all auto-refill ways as efficiently as you think
46#endif
47
48#if (XCHAL_MMU_MAX_PTE_PAGE_SIZE != XCHAL_MMU_MIN_PTE_PAGE_SIZE)
49# error Only one page size allowed!
50#endif
51
52extern unsigned long asid_cache;
53extern pgd_t *current_pgd;
54
55/*
56 * Define the number of entries per auto-refill way in set 0 of both I and D
57 * TLBs. We deal only with set 0 here (an assumption further explained in
58 * assertions.h). Also, define the total number of ARF entries in both TLBs.
59 */
60
61#define ITLB_ENTRIES_PER_ARF_WAY (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES))
62#define DTLB_ENTRIES_PER_ARF_WAY (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES))
63
64#define ITLB_ENTRIES \
65 (ITLB_ENTRIES_PER_ARF_WAY * (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,WAYS)))
66#define DTLB_ENTRIES \
67 (DTLB_ENTRIES_PER_ARF_WAY * (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,WAYS)))
68
69
70/*
71 * SMALLEST_NTLB_ENTRIES is the smaller of ITLB_ENTRIES and DTLB_ENTRIES.
72 * In practice, they are probably equal. This macro simplifies function
73 * flush_tlb_range().
74 */
75
76#if (DTLB_ENTRIES < ITLB_ENTRIES)
77# define SMALLEST_NTLB_ENTRIES DTLB_ENTRIES
78#else
79# define SMALLEST_NTLB_ENTRIES ITLB_ENTRIES
80#endif
81
82
83/*
84 * asid_cache tracks only the ASID[USER_RING] field of the RASID special
85 * register, which is the current user-task asid allocation value.
86 * mm->context has the same meaning. When it comes time to write the
87 * asid_cache or mm->context values to the RASID special register, we first
88 * shift the value left by 8, then insert the value.
89 * ASID[0] always contains the kernel's asid value, and we reserve three
90 * other asid values that we never assign to user tasks.
91 */
92
93#define ASID_INC 0x1
94#define ASID_MASK ((1 << XCHAL_MMU_ASID_BITS) - 1)
95
96/*
97 * XCHAL_MMU_ASID_INVALID is a configurable Xtensa processor constant
98 * indicating invalid address space. XCHAL_MMU_ASID_KERNEL is a configurable
99 * Xtensa processor constant indicating the kernel address space. They can
100 * be arbitrary values.
101 *
102 * We identify three more unique, reserved ASID values to use in the unused
103 * ring positions. No other user process will be assigned these reserved
104 * ASID values.
105 *
106 * For example, given that
107 *
108 * XCHAL_MMU_ASID_INVALID == 0
109 * XCHAL_MMU_ASID_KERNEL == 1
110 *
111 * the following maze of #if statements would generate
112 *
113 * ASID_RESERVED_1 == 2
114 * ASID_RESERVED_2 == 3
115 * ASID_RESERVED_3 == 4
116 * ASID_FIRST_NONRESERVED == 5
117 */
118
119#if (XCHAL_MMU_ASID_INVALID != XCHAL_MMU_ASID_KERNEL + 1)
120# define ASID_RESERVED_1 ((XCHAL_MMU_ASID_KERNEL + 1) & ASID_MASK)
121#else
122# define ASID_RESERVED_1 ((XCHAL_MMU_ASID_KERNEL + 2) & ASID_MASK)
123#endif
124
125#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_1 + 1)
126# define ASID_RESERVED_2 ((ASID_RESERVED_1 + 1) & ASID_MASK)
127#else
128# define ASID_RESERVED_2 ((ASID_RESERVED_1 + 2) & ASID_MASK)
129#endif
130
131#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_2 + 1)
132# define ASID_RESERVED_3 ((ASID_RESERVED_2 + 1) & ASID_MASK)
133#else
134# define ASID_RESERVED_3 ((ASID_RESERVED_2 + 2) & ASID_MASK)
135#endif
136
137#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_3 + 1)
138# define ASID_FIRST_NONRESERVED ((ASID_RESERVED_3 + 1) & ASID_MASK)
139#else
140# define ASID_FIRST_NONRESERVED ((ASID_RESERVED_3 + 2) & ASID_MASK)
141#endif
142
143#define ASID_ALL_RESERVED ( ((ASID_RESERVED_1) << 24) + \
144 ((ASID_RESERVED_2) << 16) + \
145 ((ASID_RESERVED_3) << 8) + \
146 ((XCHAL_MMU_ASID_KERNEL)) )
147
148
149/*
150 * NO_CONTEXT is the invalid ASID value that we don't ever assign to
151 * any user or kernel context. NO_CONTEXT is a better mnemonic than
152 * XCHAL_MMU_ASID_INVALID, so we use it in code instead.
153 */
154
155#define NO_CONTEXT XCHAL_MMU_ASID_INVALID
156
157#if (KERNEL_RING != 0)
158# error The KERNEL_RING really should be zero.
159#endif
160
161#if (USER_RING >= XCHAL_MMU_RINGS)
162# error USER_RING cannot be greater than the highest numbered ring.
163#endif
164
165#if (USER_RING == KERNEL_RING)
166# error The user and kernel rings really should not be equal.
167#endif
168
169#if (USER_RING == 1)
170#define ASID_INSERT(x) ( ((ASID_RESERVED_1) << 24) + \
171 ((ASID_RESERVED_2) << 16) + \
172 (((x) & (ASID_MASK)) << 8) + \
173 ((XCHAL_MMU_ASID_KERNEL)) )
174
175#elif (USER_RING == 2)
176#define ASID_INSERT(x) ( ((ASID_RESERVED_1) << 24) + \
177 (((x) & (ASID_MASK)) << 16) + \
178 ((ASID_RESERVED_2) << 8) + \
179 ((XCHAL_MMU_ASID_KERNEL)) )
180
181#elif (USER_RING == 3)
182#define ASID_INSERT(x) ( (((x) & (ASID_MASK)) << 24) + \
183 ((ASID_RESERVED_1) << 16) + \
184 ((ASID_RESERVED_2) << 8) + \
185 ((XCHAL_MMU_ASID_KERNEL)) )
186
187#else
188#error Goofy value for USER_RING
189
190#endif /* USER_RING == 1 */
191
192
193/*
194 * All unused by hardware upper bits will be considered
195 * as a software asid extension.
196 */
197
198#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
199#define ASID_FIRST_VERSION \
200 ((unsigned long)(~ASID_VERSION_MASK) + 1 + ASID_FIRST_NONRESERVED)
201
202extern inline void set_rasid_register (unsigned long val)
203{
204 __asm__ __volatile__ (" wsr %0, "__stringify(RASID)"\n\t"
205 " isync\n" : : "a" (val));
206}
207
208extern inline unsigned long get_rasid_register (void)
209{
210 unsigned long tmp;
211 __asm__ __volatile__ (" rsr %0, "__stringify(RASID)"\n\t" : "=a" (tmp));
212 return tmp;
213}
214
215
216#if ((XCHAL_MMU_ASID_INVALID == 0) && (XCHAL_MMU_ASID_KERNEL == 1))
217
218extern inline void
219get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
220{
221 extern void flush_tlb_all(void);
222 if (! ((asid += ASID_INC) & ASID_MASK) ) {
223 flush_tlb_all(); /* start new asid cycle */
224 if (!asid) /* fix version if needed */
225 asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
226 asid += ASID_FIRST_NONRESERVED;
227 }
228 mm->context = asid_cache = asid;
229}
230
231#else
232#warning ASID_{INVALID,KERNEL} values impose non-optimal get_new_mmu_context implementation
233
234/* XCHAL_MMU_ASID_INVALID == 0 and XCHAL_MMU_ASID_KERNEL ==1 are
235 really the best, but if you insist... */
236
237extern inline int validate_asid (unsigned long asid)
238{
239 switch (asid) {
240 case XCHAL_MMU_ASID_INVALID:
241 case XCHAL_MMU_ASID_KERNEL:
242 case ASID_RESERVED_1:
243 case ASID_RESERVED_2:
244 case ASID_RESERVED_3:
245 return 0; /* can't use these values as ASIDs */
246 }
247 return 1; /* valid */
248}
249
250extern inline void
251get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
252{
253 extern void flush_tlb_all(void);
254 while (1) {
255 asid += ASID_INC;
256 if ( ! (asid & ASID_MASK) ) {
257 flush_tlb_all(); /* start new asid cycle */
258 if (!asid) /* fix version if needed */
259 asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
260 asid += ASID_FIRST_NONRESERVED;
261 break; /* no need to validate here */
262 }
263 if (validate_asid (asid & ASID_MASK))
264 break;
265 }
266 mm->context = asid_cache = asid;
267}
268
269#endif
270
271
272/*
273 * Initialize the context related info for a new mm_struct
274 * instance.
275 */
276
277extern inline int
278init_new_context(struct task_struct *tsk, struct mm_struct *mm)
279{
280 mm->context = NO_CONTEXT;
281 return 0;
282}
283
284extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
285 struct task_struct *tsk)
286{
287 unsigned long asid = asid_cache;
288
289 /* Check if our ASID is of an older version and thus invalid */
290
291 if ((next->context ^ asid) & ASID_VERSION_MASK)
292 get_new_mmu_context(next, asid);
293
294 set_rasid_register (ASID_INSERT(next->context));
295 invalidate_page_directory();
296}
297
298#define deactivate_mm(tsk, mm) do { } while(0)
299
300/*
301 * Destroy context related info for an mm_struct that is about
302 * to be put to rest.
303 */
304extern inline void destroy_context(struct mm_struct *mm)
305{
306 /* Nothing to do. */
307}
308
309/*
310 * After we have set current->mm to a new value, this activates
311 * the context for the new mm so we see the new mappings.
312 */
313extern inline void
314activate_mm(struct mm_struct *prev, struct mm_struct *next)
315{
316 /* Unconditionally get a new ASID. */
317
318 get_new_mmu_context(next, asid_cache);
319 set_rasid_register (ASID_INSERT(next->context));
320 invalidate_page_directory();
321}
322
323
324static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
325{
326 /* Nothing to do. */
327
328}
329
330#endif /* _XTENSA_MMU_CONTEXT_H */
diff --git a/include/asm-xtensa/module.h b/include/asm-xtensa/module.h
new file mode 100644
index 0000000000..ffb25bfdf6
--- /dev/null
+++ b/include/asm-xtensa/module.h
@@ -0,0 +1,25 @@
1/*
2 * include/asm-xtensa/module.h
3 *
4 * This file contains the module code specific to the Xtensa architecture.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_MODULE_H
14#define _XTENSA_MODULE_H
15
16struct mod_arch_specific
17{
18 /* Module support is not completely implemented. */
19};
20
21#define Elf_Shdr Elf32_Shdr
22#define Elf_Sym Elf32_Sym
23#define Elf_Ehdr Elf32_Ehdr
24
25#endif /* _XTENSA_MODULE_H */
diff --git a/include/asm-xtensa/msgbuf.h b/include/asm-xtensa/msgbuf.h
new file mode 100644
index 0000000000..693c967552
--- /dev/null
+++ b/include/asm-xtensa/msgbuf.h
@@ -0,0 +1,48 @@
1/*
2 * include/asm-xtensa/msgbuf.h
3 *
4 * The msqid64_ds structure for the Xtensa architecture.
5 * Note extra padding because this structure is passed back and forth
6 * between kernel and user space.
7 *
8 * Pad space is left for:
9 * - 64-bit time_t to solve y2038 problem
10 * - 2 miscellaneous 32-bit values
11 *
12 * This file is subject to the terms and conditions of the GNU General
13 * Public License. See the file "COPYING" in the main directory of
14 * this archive for more details.
15 */
16
17#ifndef _XTENSA_MSGBUF_H
18#define _XTENSA_MSGBUF_H
19
20struct msqid64_ds {
21 struct ipc64_perm msg_perm;
22#ifdef __XTENSA_EB__
23 unsigned int __unused1;
24 __kernel_time_t msg_stime; /* last msgsnd time */
25 unsigned int __unused2;
26 __kernel_time_t msg_rtime; /* last msgrcv time */
27 unsigned int __unused3;
28 __kernel_time_t msg_ctime; /* last change time */
29#elif defined(__XTENSA_EL__)
30 __kernel_time_t msg_stime; /* last msgsnd time */
31 unsigned int __unused1;
32 __kernel_time_t msg_rtime; /* last msgrcv time */
33 unsigned int __unused2;
34 __kernel_time_t msg_ctime; /* last change time */
35 unsigned int __unused3;
36#else
37# error processor byte order undefined!
38#endif
39 unsigned long msg_cbytes; /* current number of bytes on queue */
40 unsigned long msg_qnum; /* number of messages in queue */
41 unsigned long msg_qbytes; /* max number of bytes on queue */
42 __kernel_pid_t msg_lspid; /* pid of last msgsnd */
43 __kernel_pid_t msg_lrpid; /* last receive pid */
44 unsigned long __unused4;
45 unsigned long __unused5;
46};
47
48#endif /* _XTENSA_MSGBUF_H */
diff --git a/include/asm-xtensa/namei.h b/include/asm-xtensa/namei.h
new file mode 100644
index 0000000000..3fdff039d2
--- /dev/null
+++ b/include/asm-xtensa/namei.h
@@ -0,0 +1,26 @@
1/*
2 * include/asm-xtensa/namei.h
3 *
4 * Included from linux/fs/namei.c
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_NAMEI_H
14#define _XTENSA_NAMEI_H
15
16#ifdef __KERNEL__
17
18/* This dummy routine maybe changed to something useful
19 * for /usr/gnemul/ emulation stuff.
20 * Look at asm-sparc/namei.h for details.
21 */
22
23#define __emul_prefix() NULL
24
25#endif /* __KERNEL__ */
26#endif /* _XTENSA_NAMEI_H */
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
new file mode 100644
index 0000000000..b495e5b5a9
--- /dev/null
+++ b/include/asm-xtensa/page.h
@@ -0,0 +1,133 @@
1/*
2 * linux/include/asm-xtensa/page.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version2 as
6 * published by the Free Software Foundation.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PAGE_H
12#define _XTENSA_PAGE_H
13
14#ifdef __KERNEL__
15
16#include <asm/processor.h>
17#include <linux/config.h>
18
19/*
20 * PAGE_SHIFT determines the page size
21 * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
22 */
23
24#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE
25#define PAGE_SIZE (1 << PAGE_SHIFT)
26#define PAGE_MASK (~(PAGE_SIZE-1))
27#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
28
29#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
30#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
31
32#ifdef __ASSEMBLY__
33
34#define __pgprot(x) (x)
35
36#else
37
38/*
39 * These are used to make use of C type-checking..
40 */
41
42typedef struct { unsigned long pte; } pte_t; /* page table entry */
43typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */
44typedef struct { unsigned long pgprot; } pgprot_t;
45
46#define pte_val(x) ((x).pte)
47#define pgd_val(x) ((x).pgd)
48#define pgprot_val(x) ((x).pgprot)
49
50#define __pte(x) ((pte_t) { (x) } )
51#define __pgd(x) ((pgd_t) { (x) } )
52#define __pgprot(x) ((pgprot_t) { (x) } )
53
54/*
55 * Pure 2^n version of get_order
56 */
57
58extern __inline__ int get_order(unsigned long size)
59{
60 int order;
61#ifndef XCHAL_HAVE_NSU
62 unsigned long x1, x2, x4, x8, x16;
63
64 size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
65 x1 = size & 0xAAAAAAAA;
66 x2 = size & 0xCCCCCCCC;
67 x4 = size & 0xF0F0F0F0;
68 x8 = size & 0xFF00FF00;
69 x16 = size & 0xFFFF0000;
70 order = x2 ? 2 : 0;
71 order += (x16 != 0) * 16;
72 order += (x8 != 0) * 8;
73 order += (x4 != 0) * 4;
74 order += (x1 != 0);
75
76 return order;
77#else
78 size = (size - 1) >> PAGE_SHIFT;
79 asm ("nsau %0, %1" : "=r" (order) : "r" (size));
80 return 32 - order;
81#endif
82}
83
84
85struct page;
86extern void clear_page(void *page);
87extern void copy_page(void *to, void *from);
88
89/*
90 * If we have cache aliasing and writeback caches, we might have to do
91 * some extra work
92 */
93
94#if (DCACHE_WAY_SIZE > PAGE_SIZE)
95void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
96void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
97#else
98# define clear_user_page(page,vaddr,pg) clear_page(page)
99# define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
100#endif
101
102/*
103 * This handles the memory map. We handle pages at
104 * XCHAL_KSEG_CACHED_VADDR for kernels with 32 bit address space.
105 * These macros are for conversion of kernel address, not user
106 * addresses.
107 */
108
109#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
110#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
111#define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr)
112#ifndef CONFIG_DISCONTIGMEM
113# define pfn_to_page(pfn) (mem_map + (pfn))
114# define page_to_pfn(page) ((unsigned long)((page) - mem_map))
115#else
116# error CONFIG_DISCONTIGMEM not supported
117#endif
118
119#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
120#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
121#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
122#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
123
124#define WANT_PAGE_VIRTUAL
125
126
127#endif /* __ASSEMBLY__ */
128
129#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
130 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
131
132#endif /* __KERNEL__ */
133#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/page.h.n b/include/asm-xtensa/page.h.n
new file mode 100644
index 0000000000..546cc6624f
--- /dev/null
+++ b/include/asm-xtensa/page.h.n
@@ -0,0 +1,135 @@
1/*
2 * linux/include/asm-xtensa/page.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version2 as
6 * published by the Free Software Foundation.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PAGE_H
12#define _XTENSA_PAGE_H
13
14#ifdef __KERNEL__
15
16#include <asm/processor.h>
17#include <linux/config.h>
18
19/*
20 * PAGE_SHIFT determines the page size
21 * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
22 */
23#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE
24#define PAGE_SIZE (1 << PAGE_SHIFT)
25#define PAGE_MASK (~(PAGE_SIZE-1))
26#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
27
28#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
29#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
30
31#ifdef __ASSEMBLY__
32
33#define __pgprot(x) (x)
34
35#else
36
37
38/*
39 * These are used to make use of C type-checking..
40 */
41typedef struct { unsigned long pte; } pte_t; /* page table entry */
42typedef struct { unsigned long pmd; } pmd_t; /* PMD table entry */
43typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */
44typedef struct { unsigned long pgprot; } pgprot_t;
45
46#define pte_val(x) ((x).pte)
47#define pmd_val(x) ((x).pmd)
48#define pgd_val(x) ((x).pgd)
49#define pgprot_val(x) ((x).pgprot)
50
51#define __pte(x) ((pte_t) { (x) } )
52#define __pmd(x) ((pmd_t) { (x) } )
53#define __pgd(x) ((pgd_t) { (x) } )
54#define __pgprot(x) ((pgprot_t) { (x) } )
55
56/*
57 * Pure 2^n version of get_order
58 */
59extern __inline__ int get_order(unsigned long size)
60{
61 int order;
62#ifndef XCHAL_HAVE_NSU
63 unsigned long x1, x2, x4, x8, x16;
64
65 size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
66 x1 = size & 0xAAAAAAAA;
67 x2 = size & 0xCCCCCCCC;
68 x4 = size & 0xF0F0F0F0;
69 x8 = size & 0xFF00FF00;
70 x16 = size & 0xFFFF0000;
71 order = x2 ? 2 : 0;
72 order += (x16 != 0) * 16;
73 order += (x8 != 0) * 8;
74 order += (x4 != 0) * 4;
75 order += (x1 != 0);
76
77 return order;
78#else
79 size = (size - 1) >> PAGE_SHIFT;
80 asm ("nsau %0, %1" : "=r" (order) : "r" (size));
81 return 32 - order;
82#endif
83}
84
85
86struct page;
87extern void clear_page(void *page);
88extern void copy_page(void *to, void *from);
89
90/*
91 * If we have cache aliasing and writeback caches, we might have to do
92 * some extra work
93 */
94
95#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
96void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
97void copy_user_page(void *to, void* from, unsigned long vaddr, struct page* page);
98#else
99# define clear_user_page(page,vaddr,pg) clear_page(page)
100# define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
101#endif
102
103
104/*
105 * This handles the memory map. We handle pages at
106 * XCHAL_KSEG_CACHED_VADDR for kernels with 32 bit address space.
107 * These macros are for conversion of kernel address, not user
108 * addresses.
109 */
110
111#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
112#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
113#define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr)
114#ifndef CONFIG_DISCONTIGMEM
115# define pfn_to_page(pfn) (mem_map + (pfn))
116# define page_to_pfn(page) ((unsigned long)((page) - mem_map))
117#else
118# error CONFIG_DISCONTIGMEM not supported
119#endif
120
121#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
122#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
123#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
124#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
125
126#define WANT_PAGE_VIRTUAL
127
128
129#endif /* __ASSEMBLY__ */
130
131#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
132 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
133
134#endif /* __KERNEL__ */
135#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h
new file mode 100644
index 0000000000..c0eec8260b
--- /dev/null
+++ b/include/asm-xtensa/param.h
@@ -0,0 +1,34 @@
1/*
2 * include/asm-xtensa/param.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PARAM_H
12#define _XTENSA_PARAM_H
13
14#include <xtensa/config/core.h>
15
16#ifdef __KERNEL__
17# define HZ 100 /* internal timer frequency */
18# define USER_HZ 100 /* for user interfaces in "ticks" */
19# define CLOCKS_PER_SEC (USER_HZ) /* frequnzy at which times() counts */
20#endif
21
22#define EXEC_PAGESIZE (1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE)
23
24#ifndef NGROUPS
25#define NGROUPS 32
26#endif
27
28#ifndef NOGROUP
29#define NOGROUP (-1)
30#endif
31
32#define MAXHOSTNAMELEN 64 /* max length of hostname */
33
34#endif /* _XTENSA_PARAM_H */
diff --git a/include/asm-xtensa/pci-bridge.h b/include/asm-xtensa/pci-bridge.h
new file mode 100644
index 0000000000..00fcbd7c53
--- /dev/null
+++ b/include/asm-xtensa/pci-bridge.h
@@ -0,0 +1,88 @@
1/*
2 * include/asm-xtensa/pci-bridge.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PCI_BRIDGE_H
12#define _XTENSA_PCI_BRIDGE_H
13
14#ifdef __KERNEL__
15
16struct device_node;
17struct pci_controller;
18
19/*
20 * pciauto_bus_scan() enumerates the pci space.
21 */
22
23extern int pciauto_bus_scan(struct pci_controller *, int);
24
25struct pci_space {
26 unsigned long start;
27 unsigned long end;
28 unsigned long base;
29};
30
31/*
32 * Structure of a PCI controller (host bridge)
33 */
34
35struct pci_controller {
36 int index; /* used for pci_controller_num */
37 struct pci_controller *next;
38 struct pci_bus *bus;
39 void *arch_data;
40
41 int first_busno;
42 int last_busno;
43
44 struct pci_ops *ops;
45 volatile unsigned int *cfg_addr;
46 volatile unsigned char *cfg_data;
47
48 /* Currently, we limit ourselves to 1 IO range and 3 mem
49 * ranges since the common pci_bus structure can't handle more
50 */
51 struct resource io_resource;
52 struct resource mem_resources[3];
53 int mem_resource_count;
54
55 /* Host bridge I/O and Memory space
56 * Used for BAR placement algorithms
57 */
58 struct pci_space io_space;
59 struct pci_space mem_space;
60
61 /* Return the interrupt number fo a device. */
62 int (*map_irq)(struct pci_dev*, u8, u8);
63
64};
65
66static inline void pcibios_init_resource(struct resource *res,
67 unsigned long start, unsigned long end, int flags, char *name)
68{
69 res->start = start;
70 res->end = end;
71 res->flags = flags;
72 res->name = name;
73 res->parent = NULL;
74 res->sibling = NULL;
75 res->child = NULL;
76}
77
78
79/* These are used for config access before all the PCI probing has been done. */
80int early_read_config_byte(struct pci_controller*, int, int, int, u8*);
81int early_read_config_word(struct pci_controller*, int, int, int, u16*);
82int early_read_config_dword(struct pci_controller*, int, int, int, u32*);
83int early_write_config_byte(struct pci_controller*, int, int, int, u8);
84int early_write_config_word(struct pci_controller*, int, int, int, u16);
85int early_write_config_dword(struct pci_controller*, int, int, int, u32);
86
87#endif /* __KERNEL__ */
88#endif /* _XTENSA_PCI_BRIDGE_H */
diff --git a/include/asm-xtensa/pci.h b/include/asm-xtensa/pci.h
new file mode 100644
index 0000000000..6817742301
--- /dev/null
+++ b/include/asm-xtensa/pci.h
@@ -0,0 +1,89 @@
1/*
2 * linux/include/asm-xtensa/pci.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PCI_H
12#define _XTENSA_PCI_H
13
14#ifdef __KERNEL__
15
16/* Can be used to override the logic in pci_scan_bus for skipping
17 * already-configured bus numbers - to be used for buggy BIOSes
18 * or architectures with incomplete PCI setup by the loader
19 */
20
21#define pcibios_assign_all_busses() 0
22
23extern struct pci_controller* pcibios_alloc_controller(void);
24
25extern inline void pcibios_set_master(struct pci_dev *dev)
26{
27 /* No special bus mastering setup handling */
28}
29
30extern inline void pcibios_penalize_isa_irq(int irq)
31{
32 /* We don't do dynamic PCI IRQ allocation */
33}
34
35/* Assume some values. (We should revise them, if necessary) */
36
37#define PCIBIOS_MIN_IO 0x2000
38#define PCIBIOS_MIN_MEM 0x10000000
39
40/* Dynamic DMA mapping stuff.
41 * Xtensa has everything mapped statically like x86.
42 */
43
44#include <linux/types.h>
45#include <linux/slab.h>
46#include <asm/scatterlist.h>
47#include <linux/string.h>
48#include <asm/io.h>
49
50struct pci_dev;
51
52/* The PCI address space does equal the physical memory address space.
53 * The networking and block device layers use this boolean for bounce buffer
54 * decisions.
55 */
56
57#define PCI_DMA_BUS_IS_PHYS (1)
58
59/* pci_unmap_{page,single} is a no-op, so */
60#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
61#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
62#define pci_unmap_addr(PTR, ADDR_NAME) (0)
63#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
64#define pci_ubnmap_len(PTR, LEN_NAME) (0)
65#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
66
67/* We cannot access memory above 4GB */
68#define pci_dac_dma_supported(pci_dev, mask) (0)
69
70/* Map a range of PCI memory or I/O space for a device into user space */
71int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
72 enum pci_mmap_state mmap_state, int write_combine);
73
74/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
75#define HAVE_PCI_MMAP 1
76
77static inline void pcibios_add_platform_entries(struct pci_dev *dev)
78{
79}
80
81#endif /* __KERNEL__ */
82
83/* Implement the pci_ DMA API in terms of the generic device dma_ one */
84#include <asm-generic/pci-dma-compat.h>
85
86/* Generic PCI */
87#include <asm-generic/pci.h>
88
89#endif /* _XTENSA_PCI_H */
diff --git a/include/asm-xtensa/percpu.h b/include/asm-xtensa/percpu.h
new file mode 100644
index 0000000000..6d2bc2ada9
--- /dev/null
+++ b/include/asm-xtensa/percpu.h
@@ -0,0 +1,16 @@
1/*
2 * linux/include/asm-xtensa/percpu.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PERCPU__
12#define _XTENSA_PERCPU__
13
14#include <asm-generic/percpu.h>
15
16#endif /* _XTENSA_PERCPU__ */
diff --git a/include/asm-xtensa/pgalloc.h b/include/asm-xtensa/pgalloc.h
new file mode 100644
index 0000000000..734a8d0603
--- /dev/null
+++ b/include/asm-xtensa/pgalloc.h
@@ -0,0 +1,116 @@
1/*
2 * linux/include/asm-xtensa/pgalloc.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Copyright (C) 2001-2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PGALLOC_H
12#define _XTENSA_PGALLOC_H
13
14#ifdef __KERNEL__
15
16#include <linux/config.h>
17#include <linux/threads.h>
18#include <linux/highmem.h>
19#include <asm/processor.h>
20#include <asm/cacheflush.h>
21
22
23/* Cache aliasing:
24 *
25 * If the cache size for one way is greater than the page size, we have to
26 * deal with cache aliasing. The cache index is wider than the page size:
27 *
28 * |cache |
29 * |pgnum |page| virtual address
30 * |xxxxxX|zzzz|
31 * | | |
32 * \ / | |
33 * trans.| |
34 * / \ | |
35 * |yyyyyY|zzzz| physical address
36 *
37 * When the page number is translated to the physical page address, the lowest
38 * bit(s) (X) that are also part of the cache index are also translated (Y).
39 * If this translation changes this bit (X), the cache index is also afected,
40 * thus resulting in a different cache line than before.
41 * The kernel does not provide a mechanism to ensure that the page color
42 * (represented by this bit) remains the same when allocated or when pages
43 * are remapped. When user pages are mapped into kernel space, the color of
44 * the page might also change.
45 *
46 * We use the address space VMALLOC_END ... VMALLOC_END + DCACHE_WAY_SIZE * 2
47 * to temporarily map a patch so we can match the color.
48 */
49
50#if (DCACHE_WAY_SIZE > PAGE_SIZE)
51# define PAGE_COLOR_MASK (PAGE_MASK & (DCACHE_WAY_SIZE-1))
52# define PAGE_COLOR(a) \
53 (((unsigned long)(a)&PAGE_COLOR_MASK) >> PAGE_SHIFT)
54# define PAGE_COLOR_EQ(a,b) \
55 ((((unsigned long)(a) ^ (unsigned long)(b)) & PAGE_COLOR_MASK) == 0)
56# define PAGE_COLOR_MAP0(v) \
57 (VMALLOC_END + ((unsigned long)(v) & PAGE_COLOR_MASK))
58# define PAGE_COLOR_MAP1(v) \
59 (VMALLOC_END + ((unsigned long)(v) & PAGE_COLOR_MASK) + DCACHE_WAY_SIZE)
60#endif
61
62/*
63 * Allocating and freeing a pmd is trivial: the 1-entry pmd is
64 * inside the pgd, so has no extra memory associated with it.
65 */
66
67#define pgd_free(pgd) free_page((unsigned long)(pgd))
68
69#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
70
71static inline void
72pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *pte)
73{
74 pmd_val(*(pmdp)) = (unsigned long)(pte);
75 __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
76}
77
78static inline void
79pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *page)
80{
81 pmd_val(*(pmdp)) = (unsigned long)page_to_virt(page);
82 __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
83}
84
85
86
87#else
88
89# define pmd_populate_kernel(mm, pmdp, pte) \
90 (pmd_val(*(pmdp)) = (unsigned long)(pte))
91# define pmd_populate(mm, pmdp, page) \
92 (pmd_val(*(pmdp)) = (unsigned long)page_to_virt(page))
93
94#endif
95
96static inline pgd_t*
97pgd_alloc(struct mm_struct *mm)
98{
99 pgd_t *pgd;
100
101 pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, PGD_ORDER);
102
103 if (likely(pgd != NULL))
104 __flush_dcache_page((unsigned long)pgd);
105
106 return pgd;
107}
108
109extern pte_t* pte_alloc_one_kernel(struct mm_struct* mm, unsigned long addr);
110extern struct page* pte_alloc_one(struct mm_struct* mm, unsigned long addr);
111
112#define pte_free_kernel(pte) free_page((unsigned long)pte)
113#define pte_free(pte) __free_page(pte)
114
115#endif /* __KERNEL__ */
116#endif /* _XTENSA_PGALLOC_H */
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
new file mode 100644
index 0000000000..0bb6416ae2
--- /dev/null
+++ b/include/asm-xtensa/pgtable.h
@@ -0,0 +1,468 @@
1/*
2 * linux/include/asm-xtensa/page.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version2 as
6 * published by the Free Software Foundation.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PGTABLE_H
12#define _XTENSA_PGTABLE_H
13
14#include <asm-generic/pgtable-nopmd.h>
15#include <asm/page.h>
16
17/* Assertions. */
18
19#ifdef CONFIG_MMU
20
21
22#if (XCHAL_MMU_RINGS < 2)
23# error Linux build assumes at least 2 ring levels.
24#endif
25
26#if (XCHAL_MMU_CA_BITS != 4)
27# error We assume exactly four bits for CA.
28#endif
29
30#if (XCHAL_MMU_SR_BITS != 0)
31# error We have no room for SR bits.
32#endif
33
34/*
35 * Use the first min-wired way for mapping page-table pages.
36 * Page coloring requires a second min-wired way.
37 */
38
39#if (XCHAL_DTLB_MINWIRED_SETS == 0)
40# error Need a min-wired way for mapping page-table pages
41#endif
42
43#define DTLB_WAY_PGTABLE XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAY)
44
45#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
46# if XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAYS) >= 2
47# define DTLB_WAY_DCACHE_ALIAS0 (DTLB_WAY_PGTABLE + 1)
48# define DTLB_WAY_DCACHE_ALIAS1 (DTLB_WAY_PGTABLE + 2)
49# else
50# error Page coloring requires its own wired dtlb way!
51# endif
52#endif
53
54#endif /* CONFIG_MMU */
55
56/*
57 * We only use two ring levels, user and kernel space.
58 */
59
60#define USER_RING 1 /* user ring level */
61#define KERNEL_RING 0 /* kernel ring level */
62
63/*
64 * The Xtensa architecture port of Linux has a two-level page table system,
65 * i.e. the logical three-level Linux page table layout are folded.
66 * Each task has the following memory page tables:
67 *
68 * PGD table (page directory), ie. 3rd-level page table:
69 * One page (4 kB) of 1024 (PTRS_PER_PGD) pointers to PTE tables
70 * (Architectures that don't have the PMD folded point to the PMD tables)
71 *
72 * The pointer to the PGD table for a given task can be retrieved from
73 * the task structure (struct task_struct*) t, e.g. current():
74 * (t->mm ? t->mm : t->active_mm)->pgd
75 *
76 * PMD tables (page middle-directory), ie. 2nd-level page tables:
77 * Absent for the Xtensa architecture (folded, PTRS_PER_PMD == 1).
78 *
79 * PTE tables (page table entry), ie. 1st-level page tables:
80 * One page (4 kB) of 1024 (PTRS_PER_PTE) PTEs with a special PTE
81 * invalid_pte_table for absent mappings.
82 *
83 * The individual pages are 4 kB big with special pages for the empty_zero_page.
84 */
85#define PGDIR_SHIFT 22
86#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
87#define PGDIR_MASK (~(PGDIR_SIZE-1))
88
89/*
90 * Entries per page directory level: we use two-level, so
91 * we don't really have any PMD directory physically.
92 */
93#define PTRS_PER_PTE 1024
94#define PTRS_PER_PTE_SHIFT 10
95#define PTRS_PER_PMD 1
96#define PTRS_PER_PGD 1024
97#define PGD_ORDER 0
98#define PMD_ORDER 0
99#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
100#define FIRST_USER_ADDRESS XCHAL_SEG_MAPPABLE_VADDR
101#define FIRST_USER_PGD_NR (FIRST_USER_ADDRESS >> PGDIR_SHIFT)
102
103/* virtual memory area. We keep a distance to other memory regions to be
104 * on the safe side. We also use this area for cache aliasing.
105 */
106
107// FIXME: virtual memory area must be configuration-dependent
108
109#define VMALLOC_START 0xC0000000
110#define VMALLOC_END 0xC7FF0000
111
112/* Xtensa Linux config PTE layout (when present):
113 * 31-12: PPN
114 * 11-6: Software
115 * 5-4: RING
116 * 3-0: CA
117 *
118 * Similar to the Alpha and MIPS ports, we need to keep track of the ref
119 * and mod bits in software. We have a software "you can read
120 * from this page" bit, and a hardware one which actually lets the
121 * process read from the page. On the same token we have a software
122 * writable bit and the real hardware one which actually lets the
123 * process write to the page.
124 *
125 * See further below for PTE layout for swapped-out pages.
126 */
127
128#define _PAGE_VALID (1<<0) /* hardware: page is accessible */
129#define _PAGE_WRENABLE (1<<1) /* hardware: page is writable */
130
131/* None of these cache modes include MP coherency: */
132#define _PAGE_NO_CACHE (0<<2) /* bypass, non-speculative */
133#if XCHAL_DCACHE_IS_WRITEBACK
134# define _PAGE_WRITEBACK (1<<2) /* write back */
135# define _PAGE_WRITETHRU (2<<2) /* write through */
136#else
137# define _PAGE_WRITEBACK (1<<2) /* assume write through */
138# define _PAGE_WRITETHRU (1<<2)
139#endif
140#define _PAGE_NOALLOC (3<<2) /* don't allocate cache,if not cached */
141#define _CACHE_MASK (3<<2)
142
143#define _PAGE_USER (1<<4) /* user access (ring=1) */
144#define _PAGE_KERNEL (0<<4) /* kernel access (ring=0) */
145
146/* Software */
147#define _PAGE_RW (1<<6) /* software: page writable */
148#define _PAGE_DIRTY (1<<7) /* software: page dirty */
149#define _PAGE_ACCESSED (1<<8) /* software: page accessed (read) */
150#define _PAGE_FILE (1<<9) /* nonlinear file mapping*/
151
152#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _CACHE_MASK | _PAGE_DIRTY)
153#define _PAGE_PRESENT ( _PAGE_VALID | _PAGE_WRITEBACK | _PAGE_ACCESSED)
154
155#ifdef CONFIG_MMU
156
157# define PAGE_NONE __pgprot(_PAGE_PRESENT)
158# define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_RW)
159# define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER)
160# define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER)
161# define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_KERNEL | _PAGE_WRENABLE)
162# define PAGE_INVALID __pgprot(_PAGE_USER)
163
164# if (DCACHE_WAY_SIZE > PAGE_SIZE)
165# define PAGE_DIRECTORY __pgprot(_PAGE_VALID | _PAGE_ACCESSED | _PAGE_KERNEL)
166# else
167# define PAGE_DIRECTORY __pgprot(_PAGE_PRESENT | _PAGE_KERNEL)
168# endif
169
170#else /* no mmu */
171
172# define PAGE_NONE __pgprot(0)
173# define PAGE_SHARED __pgprot(0)
174# define PAGE_COPY __pgprot(0)
175# define PAGE_READONLY __pgprot(0)
176# define PAGE_KERNEL __pgprot(0)
177
178#endif
179
180/*
181 * On certain configurations of Xtensa MMUs (eg. the initial Linux config),
182 * the MMU can't do page protection for execute, and considers that the same as
183 * read. Also, write permissions may imply read permissions.
184 * What follows is the closest we can get by reasonable means..
185 * See linux/mm/mmap.c for protection_map[] array that uses these definitions.
186 */
187#define __P000 PAGE_NONE /* private --- */
188#define __P001 PAGE_READONLY /* private --r */
189#define __P010 PAGE_COPY /* private -w- */
190#define __P011 PAGE_COPY /* private -wr */
191#define __P100 PAGE_READONLY /* private x-- */
192#define __P101 PAGE_READONLY /* private x-r */
193#define __P110 PAGE_COPY /* private xw- */
194#define __P111 PAGE_COPY /* private xwr */
195
196#define __S000 PAGE_NONE /* shared --- */
197#define __S001 PAGE_READONLY /* shared --r */
198#define __S010 PAGE_SHARED /* shared -w- */
199#define __S011 PAGE_SHARED /* shared -wr */
200#define __S100 PAGE_READONLY /* shared x-- */
201#define __S101 PAGE_READONLY /* shared x-r */
202#define __S110 PAGE_SHARED /* shared xw- */
203#define __S111 PAGE_SHARED /* shared xwr */
204
205#ifndef __ASSEMBLY__
206
207#define pte_ERROR(e) \
208 printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
209#define pgd_ERROR(e) \
210 printk("%s:%d: bad pgd entry %08lx.\n", __FILE__, __LINE__, pgd_val(e))
211
212extern unsigned long empty_zero_page[1024];
213
214#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
215
216extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)];
217
218/*
219 * The pmd contains the kernel virtual address of the pte page.
220 */
221#define pmd_page_kernel(pmd) ((unsigned long)(pmd_val(pmd) & PAGE_MASK))
222#define pmd_page(pmd) virt_to_page(pmd_val(pmd))
223
224/*
225 * The following only work if pte_present() is true.
226 */
227#define pte_none(pte) (!(pte_val(pte) ^ _PAGE_USER))
228#define pte_present(pte) (pte_val(pte) & _PAGE_VALID)
229#define pte_clear(mm,addr,ptep) \
230 do { update_pte(ptep, __pte(_PAGE_USER)); } while(0)
231
232#define pmd_none(pmd) (!pmd_val(pmd))
233#define pmd_present(pmd) (pmd_val(pmd) & PAGE_MASK)
234#define pmd_clear(pmdp) do { set_pmd(pmdp, __pmd(0)); } while (0)
235#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK)
236
237/* Note: We use the _PAGE_USER bit to indicate write-protect kernel memory */
238
239static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
240static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
241static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
242static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
243static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
244static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_RW | _PAGE_WRENABLE); return pte; }
245static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
246static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
247static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
248static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
249static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
250static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
251static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; }
252
253/*
254 * Conversion functions: convert a page and protection to a page entry,
255 * and a page entry and page directory to the page they refer to.
256 */
257#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
258#define pte_same(a,b) (pte_val(a) == pte_val(b))
259#define pte_page(x) pfn_to_page(pte_pfn(x))
260#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
261#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
262
263extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
264{
265 return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
266}
267
268/*
269 * Certain architectures need to do special things when pte's
270 * within a page table are directly modified. Thus, the following
271 * hook is made available.
272 */
273static inline void update_pte(pte_t *ptep, pte_t pteval)
274{
275 *ptep = pteval;
276#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
277 __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (ptep));
278#endif
279}
280
281extern inline void
282set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)
283{
284 update_pte(ptep, pteval);
285}
286
287
288extern inline void
289set_pmd(pmd_t *pmdp, pmd_t pmdval)
290{
291 *pmdp = pmdval;
292#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
293 __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
294#endif
295}
296
297
298static inline int
299ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr,
300 pte_t *ptep)
301{
302 pte_t pte = *ptep;
303 if (!pte_young(pte))
304 return 0;
305 update_pte(ptep, pte_mkold(pte));
306 return 1;
307}
308
309static inline int
310ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr,
311 pte_t *ptep)
312{
313 pte_t pte = *ptep;
314 if (!pte_dirty(pte))
315 return 0;
316 update_pte(ptep, pte_mkclean(pte));
317 return 1;
318}
319
320static inline pte_t
321ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
322{
323 pte_t pte = *ptep;
324 pte_clear(mm, addr, ptep);
325 return pte;
326}
327
328static inline void
329ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
330{
331 pte_t pte = *ptep;
332 update_pte(ptep, pte_wrprotect(pte));
333}
334
335/* to find an entry in a kernel page-table-directory */
336#define pgd_offset_k(address) pgd_offset(&init_mm, address)
337
338/* to find an entry in a page-table-directory */
339#define pgd_offset(mm,address) ((mm)->pgd + pgd_index(address))
340
341#define pgd_index(address) ((address) >> PGDIR_SHIFT)
342
343/* Find an entry in the second-level page table.. */
344#define pmd_offset(dir,address) ((pmd_t*)(dir))
345
346/* Find an entry in the third-level page table.. */
347#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
348#define pte_offset_kernel(dir,addr) \
349 ((pte_t*) pmd_page_kernel(*(dir)) + pte_index(addr))
350#define pte_offset_map(dir,addr) pte_offset_kernel((dir),(addr))
351#define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir),(addr))
352
353#define pte_unmap(pte) do { } while (0)
354#define pte_unmap_nested(pte) do { } while (0)
355
356
357/*
358 * Encode and decode a swap entry.
359 * Each PTE in a process VM's page table is either:
360 * "present" -- valid and not swapped out, protection bits are meaningful;
361 * "not present" -- which further subdivides in these two cases:
362 * "none" -- no mapping at all; identified by pte_none(), set by pte_clear(
363 * "swapped out" -- the page is swapped out, and the SWP macros below
364 * are used to store swap file info in the PTE itself.
365 *
366 * In the Xtensa processor MMU, any PTE entries in user space (or anywhere
367 * in virtual memory that can map differently across address spaces)
368 * must have a correct ring value that represents the RASID field that
369 * is changed when switching address spaces. Eg. such PTE entries cannot
370 * be set to ring zero, because that can cause a (global) kernel ASID
371 * entry to be created in the TLBs (even with invalid cache attribute),
372 * potentially causing a multihit exception when going back to another
373 * address space that mapped the same virtual address at another ring.
374 *
375 * SO: we avoid using ring bits (_PAGE_RING_MASK) in "not present" PTEs.
376 * We also avoid using the _PAGE_VALID bit which must be zero for non-present
377 * pages.
378 *
379 * We end up with the following available bits: 1..3 and 7..31.
380 * We don't bother with 1..3 for now (we can use them later if needed),
381 * and chose to allocate 6 bits for SWP_TYPE and the remaining 19 bits
382 * for SWP_OFFSET. At least 5 bits are needed for SWP_TYPE, because it
383 * is currently implemented as an index into swap_info[MAX_SWAPFILES]
384 * and MAX_SWAPFILES is currently defined as 32 in <linux/swap.h>.
385 * However, for some reason all other architectures in the 2.4 kernel
386 * reserve either 6, 7, or 8 bits so I'll not detract from that for now. :)
387 * SWP_OFFSET is an offset into the swap file in page-size units, so
388 * with 4 kB pages, 19 bits supports a maximum swap file size of 2 GB.
389 *
390 * FIXME: 2 GB isn't very big. Other bits can be used to allow
391 * larger swap sizes. In the meantime, it appears relatively easy to get
392 * around the 2 GB limitation by simply using multiple swap files.
393 */
394
395#define __swp_type(entry) (((entry).val >> 7) & 0x3f)
396#define __swp_offset(entry) ((entry).val >> 13)
397#define __swp_entry(type,offs) ((swp_entry_t) {((type) << 7) | ((offs) << 13)})
398#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
399#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
400
401#define PTE_FILE_MAX_BITS 29
402#define pte_to_pgoff(pte) (pte_val(pte) >> 3)
403#define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE })
404
405
406#endif /* !defined (__ASSEMBLY__) */
407
408
409#ifdef __ASSEMBLY__
410
411/* Assembly macro _PGD_INDEX is the same as C pgd_index(unsigned long),
412 * _PGD_OFFSET as C pgd_offset(struct mm_struct*, unsigned long),
413 * _PMD_OFFSET as C pmd_offset(pgd_t*, unsigned long)
414 * _PTE_OFFSET as C pte_offset(pmd_t*, unsigned long)
415 *
416 * Note: We require an additional temporary register which can be the same as
417 * the register that holds the address.
418 *
419 * ((pte_t*) ((unsigned long)(pmd_val(*pmd) & PAGE_MASK)) + pte_index(addr))
420 *
421 */
422#define _PGD_INDEX(rt,rs) extui rt, rs, PGDIR_SHIFT, 32-PGDIR_SHIFT
423#define _PTE_INDEX(rt,rs) extui rt, rs, PAGE_SHIFT, PTRS_PER_PTE_SHIFT
424
425#define _PGD_OFFSET(mm,adr,tmp) l32i mm, mm, MM_PGD; \
426 _PGD_INDEX(tmp, adr); \
427 addx4 mm, tmp, mm
428
429#define _PTE_OFFSET(pmd,adr,tmp) _PTE_INDEX(tmp, adr); \
430 srli pmd, pmd, PAGE_SHIFT; \
431 slli pmd, pmd, PAGE_SHIFT; \
432 addx4 pmd, tmp, pmd
433
434#else
435
436extern void paging_init(void);
437
438#define kern_addr_valid(addr) (1)
439
440extern void update_mmu_cache(struct vm_area_struct * vma,
441 unsigned long address, pte_t pte);
442
443/*
444 * remap a physical address `phys' of size `size' with page protection `prot'
445 * into virtual address `from'
446 */
447#define io_remap_page_range(vma,from,phys,size,prot) \
448 remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
449
450
451/* No page table caches to init */
452
453#define pgtable_cache_init() do { } while (0)
454
455typedef pte_t *pte_addr_t;
456
457#endif /* !defined (__ASSEMBLY__) */
458
459#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
460#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
461#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
462#define __HAVE_ARCH_PTEP_SET_WRPROTECT
463#define __HAVE_ARCH_PTEP_MKDIRTY
464#define __HAVE_ARCH_PTE_SAME
465
466#include <asm-generic/pgtable.h>
467
468#endif /* _XTENSA_PGTABLE_H */
diff --git a/include/asm-xtensa/platform-iss/hardware.h b/include/asm-xtensa/platform-iss/hardware.h
new file mode 100644
index 0000000000..22240f0018
--- /dev/null
+++ b/include/asm-xtensa/platform-iss/hardware.h
@@ -0,0 +1,29 @@
1/*
2 * include/asm-xtensa/platform-iss/hardware.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 Tensilica Inc.
9 */
10
11/*
12 * This file contains the default configuration of ISS.
13 */
14
15#ifndef __ASM_XTENSA_ISS_HARDWARE
16#define __ASM_XTENSA_ISS_HARDWARE
17
18/*
19 * Memory configuration.
20 */
21
22#define PLATFORM_DEFAULT_MEM_START XSHAL_RAM_PADDR
23#define PLATFORM_DEFAULT_MEM_SIZE XSHAL_RAM_VSIZE
24
25/*
26 * Interrupt configuration.
27 */
28
29#endif /* __ASM_XTENSA_ISS_HARDWARE */
diff --git a/include/asm-xtensa/platform.h b/include/asm-xtensa/platform.h
new file mode 100644
index 0000000000..36163894bc
--- /dev/null
+++ b/include/asm-xtensa/platform.h
@@ -0,0 +1,92 @@
1/*
2 * include/asm-xtensa/platform.h
3 *
4 * Platform specific functions
5 *
6 * This file is subject to the terms and conditions of the GNU General
7 * Public License. See the file "COPYING" in the main directory of
8 * this archive for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_PLATFORM_H
14#define _XTENSA_PLATFORM_H
15
16#include <linux/config.h>
17#include <linux/types.h>
18#include <linux/pci.h>
19
20#include <asm/bootparam.h>
21
22/*
23 * platform_init is called before the mmu is initialized to give the
24 * platform a early hook-up. bp_tag_t is a list of configuration tags
25 * passed from the boot-loader.
26 */
27extern void platform_init(bp_tag_t*);
28
29/*
30 * platform_setup is called from setup_arch with a pointer to the command-line
31 * string.
32 */
33extern void platform_setup (char **);
34
35/*
36 * platform_init_irq is called from init_IRQ.
37 */
38extern void platform_init_irq (void);
39
40/*
41 * platform_restart is called to restart the system.
42 */
43extern void platform_restart (void);
44
45/*
46 * platform_halt is called to stop the system and halt.
47 */
48extern void platform_halt (void);
49
50/*
51 * platform_power_off is called to stop the system and power it off.
52 */
53extern void platform_power_off (void);
54
55/*
56 * platform_idle is called from the idle function.
57 */
58extern void platform_idle (void);
59
60/*
61 * platform_heartbeat is called every HZ
62 */
63extern void platform_heartbeat (void);
64
65/*
66 * platform_pcibios_init is called to allow the platform to setup the pci bus.
67 */
68extern void platform_pcibios_init (void);
69
70/*
71 * platform_pcibios_fixup allows to modify the PCI configuration.
72 */
73extern int platform_pcibios_fixup (void);
74
75/*
76 * platform_calibrate_ccount calibrates cpu clock freq (CONFIG_XTENSA_CALIBRATE)
77 */
78extern void platform_calibrate_ccount (void);
79
80/*
81 * platform_get_rtc_time returns RTC seconds (returns 0 for no error)
82 */
83extern int platform_get_rtc_time(time_t*);
84
85/*
86 * platform_set_rtc_time set RTC seconds (returns 0 for no error)
87 */
88extern int platform_set_rtc_time(time_t);
89
90
91#endif /* _XTENSA_PLATFORM_H */
92
diff --git a/include/asm-xtensa/poll.h b/include/asm-xtensa/poll.h
new file mode 100644
index 0000000000..dffe447534
--- /dev/null
+++ b/include/asm-xtensa/poll.h
@@ -0,0 +1,37 @@
1/*
2 * include/asm-xtensa/poll.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_POLL_H
12#define _XTENSA_POLL_H
13
14
15#define POLLIN 0x0001
16#define POLLPRI 0x0002
17#define POLLOUT 0x0004
18
19#define POLLERR 0x0008
20#define POLLHUP 0x0010
21#define POLLNVAL 0x0020
22
23#define POLLRDNORM 0x0040
24#define POLLRDBAND 0x0080
25#define POLLWRNORM POLLOUT
26#define POLLWRBAND 0x0100
27
28#define POLLMSG 0x0400
29#define POLLREMOVE 0x0800
30
31struct pollfd {
32 int fd;
33 short events;
34 short revents;
35};
36
37#endif /* _XTENSA_POLL_H */
diff --git a/include/asm-xtensa/posix_types.h b/include/asm-xtensa/posix_types.h
new file mode 100644
index 0000000000..2c816b0e77
--- /dev/null
+++ b/include/asm-xtensa/posix_types.h
@@ -0,0 +1,123 @@
1/*
2 * include/asm-xtensa/posix_types.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Largely copied from include/asm-ppc/posix_types.h
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_POSIX_TYPES_H
14#define _XTENSA_POSIX_TYPES_H
15
16/*
17 * This file is generally used by user-level software, so you need to
18 * be a little careful about namespace pollution etc. Also, we cannot
19 * assume GCC is being used.
20 */
21
22typedef unsigned long __kernel_ino_t;
23typedef unsigned int __kernel_mode_t;
24typedef unsigned short __kernel_nlink_t;
25typedef long __kernel_off_t;
26typedef int __kernel_pid_t;
27typedef unsigned short __kernel_ipc_pid_t;
28typedef unsigned int __kernel_uid_t;
29typedef unsigned int __kernel_gid_t;
30typedef unsigned int __kernel_size_t;
31typedef int __kernel_ssize_t;
32typedef long __kernel_ptrdiff_t;
33typedef long __kernel_time_t;
34typedef long __kernel_suseconds_t;
35typedef long __kernel_clock_t;
36typedef int __kernel_timer_t;
37typedef int __kernel_clockid_t;
38typedef int __kernel_daddr_t;
39typedef char * __kernel_caddr_t;
40typedef unsigned short __kernel_uid16_t;
41typedef unsigned short __kernel_gid16_t;
42typedef unsigned int __kernel_uid32_t;
43typedef unsigned int __kernel_gid32_t;
44
45typedef unsigned short __kernel_old_uid_t;
46typedef unsigned short __kernel_old_gid_t;
47typedef unsigned short __kernel_old_dev_t;
48
49#ifdef __GNUC__
50typedef long long __kernel_loff_t;
51#endif
52
53typedef struct {
54 int val[2];
55} __kernel_fsid_t;
56
57#ifndef __GNUC__
58
59#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
60#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
61#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
62#define __FD_ZERO(set) \
63 ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
64
65#else /* __GNUC__ */
66
67#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
68 || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
69/* With GNU C, use inline functions instead so args are evaluated only once: */
70
71#undef __FD_SET
72static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
73{
74 unsigned long _tmp = fd / __NFDBITS;
75 unsigned long _rem = fd % __NFDBITS;
76 fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
77}
78
79#undef __FD_CLR
80static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
81{
82 unsigned long _tmp = fd / __NFDBITS;
83 unsigned long _rem = fd % __NFDBITS;
84 fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
85}
86
87#undef __FD_ISSET
88static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
89{
90 unsigned long _tmp = fd / __NFDBITS;
91 unsigned long _rem = fd % __NFDBITS;
92 return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
93}
94
95/*
96 * This will unroll the loop for the normal constant case (8 ints,
97 * for a 256-bit fd_set)
98 */
99#undef __FD_ZERO
100static __inline__ void __FD_ZERO(__kernel_fd_set *p)
101{
102 unsigned int *tmp = (unsigned int *)p->fds_bits;
103 int i;
104
105 if (__builtin_constant_p(__FDSET_LONGS)) {
106 switch (__FDSET_LONGS) {
107 case 8:
108 tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
109 tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
110 return;
111 }
112 }
113 i = __FDSET_LONGS;
114 while (i) {
115 i--;
116 *tmp = 0;
117 tmp++;
118 }
119}
120
121#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
122#endif /* __GNUC__ */
123#endif /* _XTENSA_POSIX_TYPES_H */
diff --git a/include/asm-xtensa/processor.h b/include/asm-xtensa/processor.h
new file mode 100644
index 0000000000..9cab5e4298
--- /dev/null
+++ b/include/asm-xtensa/processor.h
@@ -0,0 +1,205 @@
1/*
2 * include/asm-xtensa/processor.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PROCESSOR_H
12#define _XTENSA_PROCESSOR_H
13
14#ifdef __ASSEMBLY__
15#define _ASMLANGUAGE
16#endif
17
18#include <xtensa/config/core.h>
19#include <xtensa/config/specreg.h>
20#include <xtensa/config/tie.h>
21#include <xtensa/config/system.h>
22
23#include <asm/ptrace.h>
24#include <asm/types.h>
25#include <asm/coprocessor.h>
26
27/* Assertions. */
28
29#if (XCHAL_HAVE_WINDOWED != 1)
30#error Linux requires the Xtensa Windowed Registers Option.
31#endif
32
33/*
34 * User space process size: 1 GB.
35 * Windowed call ABI requires caller and callee to be located within the same
36 * 1 GB region. The C compiler places trampoline code on the stack for sources
37 * that take the address of a nested C function (a feature used by glibc), so
38 * the 1 GB requirement applies to the stack as well.
39 */
40
41#define TASK_SIZE 0x40000000
42
43/*
44 * General exception cause assigned to debug exceptions. Debug exceptions go
45 * to their own vector, rather than the general exception vectors (user,
46 * kernel, double); and their specific causes are reported via DEBUGCAUSE
47 * rather than EXCCAUSE. However it is sometimes convenient to redirect debug
48 * exceptions to the general exception mechanism. To do this, an otherwise
49 * unused EXCCAUSE value was assigned to debug exceptions for this purpose.
50 */
51
52#define EXCCAUSE_MAPPED_DEBUG 63
53
54/*
55 * We use DEPC also as a flag to distinguish between double and regular
56 * exceptions. For performance reasons, DEPC might contain the value of
57 * EXCCAUSE for regular exceptions, so we use this definition to mark a
58 * valid double exception address.
59 * (Note: We use it in bgeui, so it should be 64, 128, or 256)
60 */
61
62#define VALID_DOUBLE_EXCEPTION_ADDRESS 64
63
64/* LOCKLEVEL defines the interrupt level that masks all
65 * general-purpose interrupts.
66 */
67#define LOCKLEVEL 1
68
69/* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
70 * registers
71 */
72#define WSBITS (XCHAL_NUM_AREGS / 4) /* width of WINDOWSTART in bits */
73#define WBBITS (XCHAL_NUM_AREGS_LOG2 - 2) /* width of WINDOWBASE in bits */
74
75#ifndef __ASSEMBLY__
76
77/* Build a valid return address for the specified call winsize.
78 * winsize must be 1 (call4), 2 (call8), or 3 (call12)
79 */
80#define MAKE_RA_FOR_CALL(ra,ws) (((ra) & 0x3fffffff) | (ws) << 30)
81
82/* Convert return address to a valid pc
83 * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
84 */
85#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
86
87typedef struct {
88 unsigned long seg;
89} mm_segment_t;
90
91struct thread_struct {
92
93 /* kernel's return address and stack pointer for context switching */
94 unsigned long ra; /* kernel's a0: return address and window call size */
95 unsigned long sp; /* kernel's a1: stack pointer */
96
97 mm_segment_t current_ds; /* see uaccess.h for example uses */
98
99 /* struct xtensa_cpuinfo info; */
100
101 unsigned long bad_vaddr; /* last user fault */
102 unsigned long bad_uaddr; /* last kernel fault accessing user space */
103 unsigned long error_code;
104
105 unsigned long ibreak[XCHAL_NUM_IBREAK];
106 unsigned long dbreaka[XCHAL_NUM_DBREAK];
107 unsigned long dbreakc[XCHAL_NUM_DBREAK];
108
109 /* Allocate storage for extra state and coprocessor state. */
110 unsigned char cp_save[XTENSA_CP_EXTRA_SIZE]
111 __attribute__ ((aligned(XTENSA_CP_EXTRA_ALIGN)));
112
113 /* Make structure 16 bytes aligned. */
114 int align[0] __attribute__ ((aligned(16)));
115};
116
117
118/*
119 * Default implementation of macro that returns current
120 * instruction pointer ("program counter").
121 */
122#define current_text_addr() ({ __label__ _l; _l: &&_l;})
123
124
125/* This decides where the kernel will search for a free chunk of vm
126 * space during mmap's.
127 */
128#define TASK_UNMAPPED_BASE (TASK_SIZE / 2)
129
130#define INIT_THREAD \
131{ \
132 ra: 0, \
133 sp: sizeof(init_stack) + (long) &init_stack, \
134 current_ds: {0}, \
135 /*info: {0}, */ \
136 bad_vaddr: 0, \
137 bad_uaddr: 0, \
138 error_code: 0, \
139}
140
141
142/*
143 * Do necessary setup to start up a newly executed thread.
144 * Note: We set-up ps as if we did a call4 to the new pc.
145 * set_thread_state in signal.c depends on it.
146 */
147#define USER_PS_VALUE ( (1 << XCHAL_PS_WOE_SHIFT) + \
148 (1 << XCHAL_PS_CALLINC_SHIFT) + \
149 (USER_RING << XCHAL_PS_RING_SHIFT) + \
150 (1 << XCHAL_PS_PROGSTACK_SHIFT) + \
151 (1 << XCHAL_PS_EXCM_SHIFT) )
152
153/* Clearing a0 terminates the backtrace. */
154#define start_thread(regs, new_pc, new_sp) \
155 regs->pc = new_pc; \
156 regs->ps = USER_PS_VALUE; \
157 regs->areg[1] = new_sp; \
158 regs->areg[0] = 0; \
159 regs->wmask = 1; \
160 regs->depc = 0; \
161 regs->windowbase = 0; \
162 regs->windowstart = 1;
163
164/* Forward declaration */
165struct task_struct;
166struct mm_struct;
167
168// FIXME: do we need release_thread for CP??
169/* Free all resources held by a thread. */
170#define release_thread(thread) do { } while(0)
171
172// FIXME: do we need prepare_to_copy (lazy status) for CP??
173/* Prepare to copy thread state - unlazy all lazy status */
174#define prepare_to_copy(tsk) do { } while (0)
175
176/*
177 * create a kernel thread without removing it from tasklists
178 */
179extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
180
181/* Copy and release all segment info associated with a VM */
182
183#define copy_segments(p, mm) do { } while(0)
184#define release_segments(mm) do { } while(0)
185#define forget_segments() do { } while (0)
186
187#define thread_saved_pc(tsk) (xtensa_pt_regs(tsk)->pc)
188
189extern unsigned long get_wchan(struct task_struct *p);
190
191#define KSTK_EIP(tsk) (xtensa_pt_regs(tsk)->pc)
192#define KSTK_ESP(tsk) (xtensa_pt_regs(tsk)->areg[1])
193
194#define cpu_relax() do { } while (0)
195
196/* Special register access. */
197
198#define WSR(v,sr) __asm__ __volatile__ ("wsr %0,"__stringify(sr) :: "a"(v));
199#define RSR(v,sr) __asm__ __volatile__ ("rsr %0,"__stringify(sr) : "=a"(v));
200
201#define set_sr(x,sr) ({unsigned int v=(unsigned int)x; WSR(v,sr);})
202#define get_sr(sr) ({unsigned int v; RSR(v,sr); v; })
203
204#endif /* __ASSEMBLY__ */
205#endif /* _XTENSA_PROCESSOR_H */
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
new file mode 100644
index 0000000000..2848a5ff83
--- /dev/null
+++ b/include/asm-xtensa/ptrace.h
@@ -0,0 +1,135 @@
1/*
2 * include/asm-xtensa/ptrace.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_PTRACE_H
12#define _XTENSA_PTRACE_H
13
14#include <xtensa/config/core.h>
15
16/*
17 * Kernel stack
18 *
19 * +-----------------------+ -------- STACK_SIZE
20 * | register file | |
21 * +-----------------------+ |
22 * | struct pt_regs | |
23 * +-----------------------+ | ------ PT_REGS_OFFSET
24 * double : 16 bytes spill area : | ^
25 * excetion :- - - - - - - - - - - -: | |
26 * frame : struct pt_regs : | |
27 * :- - - - - - - - - - - -: | |
28 * | | | |
29 * | memory stack | | |
30 * | | | |
31 * ~ ~ ~ ~
32 * ~ ~ ~ ~
33 * | | | |
34 * | | | |
35 * +-----------------------+ | | --- STACK_BIAS
36 * | struct task_struct | | | ^
37 * current --> +-----------------------+ | | |
38 * | struct thread_info | | | |
39 * +-----------------------+ --------
40 */
41
42#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
43
44/* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */
45
46#define EXC_TABLE_KSTK 0x004 /* Kernel Stack */
47#define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */
48#define EXC_TABLE_FIXUP 0x00c /* Fixup handler */
49#define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */
50#define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */
51#define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */
52#define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */
53#define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */
54#define EXC_TABLE_SIZE 0x400
55
56/* Registers used by strace */
57
58#define REG_A_BASE 0xfc000000
59#define REG_AR_BASE 0x04000000
60#define REG_PC 0x14000000
61#define REG_PS 0x080000e6
62#define REG_WB 0x08000048
63#define REG_WS 0x08000049
64#define REG_LBEG 0x08000000
65#define REG_LEND 0x08000001
66#define REG_LCOUNT 0x08000002
67#define REG_SAR 0x08000003
68#define REG_DEPC 0x080000c0
69#define REG_EXCCAUSE 0x080000e8
70#define REG_EXCVADDR 0x080000ee
71#define SYSCALL_NR 0x1
72
73#define AR_REGNO_TO_A_REGNO(ar, wb) (ar - wb*4) & ~(XCHAL_NUM_AREGS - 1)
74
75/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
76
77#define PTRACE_GETREGS 12
78#define PTRACE_SETREGS 13
79#define PTRACE_GETFPREGS 14
80#define PTRACE_SETFPREGS 15
81#define PTRACE_GETFPREGSIZE 18
82
83#ifndef __ASSEMBLY__
84
85/*
86 * This struct defines the way the registers are stored on the
87 * kernel stack during a system call or other kernel entry.
88 */
89struct pt_regs {
90 unsigned long pc; /* 4 */
91 unsigned long ps; /* 8 */
92 unsigned long depc; /* 12 */
93 unsigned long exccause; /* 16 */
94 unsigned long excvaddr; /* 20 */
95 unsigned long debugcause; /* 24 */
96 unsigned long wmask; /* 28 */
97 unsigned long lbeg; /* 32 */
98 unsigned long lend; /* 36 */
99 unsigned long lcount; /* 40 */
100 unsigned long sar; /* 44 */
101 unsigned long windowbase; /* 48 */
102 unsigned long windowstart; /* 52 */
103 unsigned long syscall; /* 56 */
104 int reserved[2]; /* 64 */
105
106 /* Make sure the areg field is 16 bytes aligned. */
107 int align[0] __attribute__ ((aligned(16)));
108
109 /* current register frame.
110 * Note: The ESF for kernel exceptions ends after 16 registers!
111 */
112 unsigned long areg[16]; /* 128 (64) */
113};
114
115#ifdef __KERNEL__
116# define xtensa_pt_regs(tsk) ((struct pt_regs*) \
117 (((long)(tsk)->thread_info + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4)) - 1)
118# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
119# define instruction_pointer(regs) ((regs)->pc)
120extern void show_regs(struct pt_regs *);
121
122# ifndef CONFIG_SMP
123# define profile_pc(regs) instruction_pointer(regs)
124# endif
125#endif /* __KERNEL__ */
126
127#else /* __ASSEMBLY__ */
128
129#ifdef __KERNEL__
130# include <asm/offsets.h>
131#define PT_REGS_OFFSET (KERNEL_STACK_SIZE - PT_USER_SIZE)
132#endif
133
134#endif /* !__ASSEMBLY__ */
135#endif /* _XTENSA_PTRACE_H */
diff --git a/include/asm-xtensa/resource.h b/include/asm-xtensa/resource.h
new file mode 100644
index 0000000000..17b5ab3117
--- /dev/null
+++ b/include/asm-xtensa/resource.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/resource.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_RESOURCE_H
12#define _XTENSA_RESOURCE_H
13
14#include <asm-generic/resource.h>
15
16#endif /* _XTENSA_RESOURCE_H */
diff --git a/include/asm-xtensa/rmap.h b/include/asm-xtensa/rmap.h
new file mode 100644
index 0000000000..649588b7e9
--- /dev/null
+++ b/include/asm-xtensa/rmap.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/rmap.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_RMAP_H
12#define _XTENSA_RMAP_H
13
14#include <asm-generic/rmap.h>
15
16#endif
diff --git a/include/asm-xtensa/rwsem.h b/include/asm-xtensa/rwsem.h
new file mode 100644
index 0000000000..3c02b0e033
--- /dev/null
+++ b/include/asm-xtensa/rwsem.h
@@ -0,0 +1,175 @@
1/*
2 * include/asm-xtensa/rwsem.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Largely copied from include/asm-ppc/rwsem.h
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_RWSEM_H
14#define _XTENSA_RWSEM_H
15
16#include <linux/list.h>
17#include <linux/spinlock.h>
18#include <asm/atomic.h>
19#include <asm/system.h>
20
21/*
22 * the semaphore definition
23 */
24struct rw_semaphore {
25 signed long count;
26#define RWSEM_UNLOCKED_VALUE 0x00000000
27#define RWSEM_ACTIVE_BIAS 0x00000001
28#define RWSEM_ACTIVE_MASK 0x0000ffff
29#define RWSEM_WAITING_BIAS (-0x00010000)
30#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
31#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
32 spinlock_t wait_lock;
33 struct list_head wait_list;
34#if RWSEM_DEBUG
35 int debug;
36#endif
37};
38
39/*
40 * initialisation
41 */
42#if RWSEM_DEBUG
43#define __RWSEM_DEBUG_INIT , 0
44#else
45#define __RWSEM_DEBUG_INIT /* */
46#endif
47
48#define __RWSEM_INITIALIZER(name) \
49 { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
50 LIST_HEAD_INIT((name).wait_list) \
51 __RWSEM_DEBUG_INIT }
52
53#define DECLARE_RWSEM(name) \
54 struct rw_semaphore name = __RWSEM_INITIALIZER(name)
55
56extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
57extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
58extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
59extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
60
61static inline void init_rwsem(struct rw_semaphore *sem)
62{
63 sem->count = RWSEM_UNLOCKED_VALUE;
64 spin_lock_init(&sem->wait_lock);
65 INIT_LIST_HEAD(&sem->wait_list);
66#if RWSEM_DEBUG
67 sem->debug = 0;
68#endif
69}
70
71/*
72 * lock for reading
73 */
74static inline void __down_read(struct rw_semaphore *sem)
75{
76 if (atomic_add_return(1,(atomic_t *)(&sem->count)) > 0)
77 smp_wmb();
78 else
79 rwsem_down_read_failed(sem);
80}
81
82static inline int __down_read_trylock(struct rw_semaphore *sem)
83{
84 int tmp;
85
86 while ((tmp = sem->count) >= 0) {
87 if (tmp == cmpxchg(&sem->count, tmp,
88 tmp + RWSEM_ACTIVE_READ_BIAS)) {
89 smp_wmb();
90 return 1;
91 }
92 }
93 return 0;
94}
95
96/*
97 * lock for writing
98 */
99static inline void __down_write(struct rw_semaphore *sem)
100{
101 int tmp;
102
103 tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
104 (atomic_t *)(&sem->count));
105 if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
106 smp_wmb();
107 else
108 rwsem_down_write_failed(sem);
109}
110
111static inline int __down_write_trylock(struct rw_semaphore *sem)
112{
113 int tmp;
114
115 tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
116 RWSEM_ACTIVE_WRITE_BIAS);
117 smp_wmb();
118 return tmp == RWSEM_UNLOCKED_VALUE;
119}
120
121/*
122 * unlock after reading
123 */
124static inline void __up_read(struct rw_semaphore *sem)
125{
126 int tmp;
127
128 smp_wmb();
129 tmp = atomic_sub_return(1,(atomic_t *)(&sem->count));
130 if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
131 rwsem_wake(sem);
132}
133
134/*
135 * unlock after writing
136 */
137static inline void __up_write(struct rw_semaphore *sem)
138{
139 smp_wmb();
140 if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
141 (atomic_t *)(&sem->count)) < 0)
142 rwsem_wake(sem);
143}
144
145/*
146 * implement atomic add functionality
147 */
148static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
149{
150 atomic_add(delta, (atomic_t *)(&sem->count));
151}
152
153/*
154 * downgrade write lock to read lock
155 */
156static inline void __downgrade_write(struct rw_semaphore *sem)
157{
158 int tmp;
159
160 smp_wmb();
161 tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
162 if (tmp < 0)
163 rwsem_downgrade_wake(sem);
164}
165
166/*
167 * implement exchange and add functionality
168 */
169static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
170{
171 smp_mb();
172 return atomic_add_return(delta, (atomic_t *)(&sem->count));
173}
174
175#endif /* _XTENSA_RWSEM_XADD_H */
diff --git a/include/asm-xtensa/scatterlist.h b/include/asm-xtensa/scatterlist.h
new file mode 100644
index 0000000000..38a2b9acd6
--- /dev/null
+++ b/include/asm-xtensa/scatterlist.h
@@ -0,0 +1,34 @@
1/*
2 * include/asm-xtensa/scatterlist.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SCATTERLIST_H
12#define _XTENSA_SCATTERLIST_H
13
14struct scatterlist {
15 struct page *page;
16 unsigned int offset;
17 dma_addr_t dma_address;
18 unsigned int length;
19};
20
21/*
22 * These macros should be used after a pci_map_sg call has been done
23 * to get bus addresses of each of the SG entries and their lengths.
24 * You should only work with the number of sg entries pci_map_sg
25 * returns, or alternatively stop on the first sg_dma_len(sg) which
26 * is 0.
27 */
28#define sg_dma_address(sg) ((sg)->dma_address)
29#define sg_dma_len(sg) ((sg)->length)
30
31
32#define ISA_DMA_THRESHOLD (~0UL)
33
34#endif /* _XTENSA_SCATTERLIST_H */
diff --git a/include/asm-xtensa/sections.h b/include/asm-xtensa/sections.h
new file mode 100644
index 0000000000..40b5191b55
--- /dev/null
+++ b/include/asm-xtensa/sections.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/sections.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SECTIONS_H
12#define _XTENSA_SECTIONS_H
13
14#include <asm-generic/sections.h>
15
16#endif /* _XTENSA_SECTIONS_H */
diff --git a/include/asm-xtensa/segment.h b/include/asm-xtensa/segment.h
new file mode 100644
index 0000000000..a2eb547a1a
--- /dev/null
+++ b/include/asm-xtensa/segment.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/segment.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SEGMENT_H
12#define _XTENSA_SEGMENT_H
13
14#include <asm/uaccess.h>
15
16#endif /* _XTENSA_SEGEMENT_H */
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
new file mode 100644
index 0000000000..c8a7574a9a
--- /dev/null
+++ b/include/asm-xtensa/semaphore.h
@@ -0,0 +1,129 @@
1/*
2 * linux/include/asm-xtensa/semaphore.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SEMAPHORE_H
12#define _XTENSA_SEMAPHORE_H
13
14#include <asm/atomic.h>
15#include <asm/system.h>
16#include <linux/wait.h>
17#include <linux/rwsem.h>
18
19struct semaphore {
20 atomic_t count;
21 int sleepers;
22 wait_queue_head_t wait;
23#if WAITQUEUE_DEBUG
24 long __magic;
25#endif
26};
27
28#if WAITQUEUE_DEBUG
29# define __SEM_DEBUG_INIT(name) \
30 , (int)&(name).__magic
31#else
32# define __SEM_DEBUG_INIT(name)
33#endif
34
35#define __SEMAPHORE_INITIALIZER(name,count) \
36 { ATOMIC_INIT(count), \
37 0, \
38 __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
39 __SEM_DEBUG_INIT(name) }
40
41#define __MUTEX_INITIALIZER(name) \
42 __SEMAPHORE_INITIALIZER(name, 1)
43
44#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
45 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
46
47#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
48#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
49
50extern inline void sema_init (struct semaphore *sem, int val)
51{
52/*
53 * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
54 *
55 * i'd rather use the more flexible initialization above, but sadly
56 * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
57 */
58 atomic_set(&sem->count, val);
59 init_waitqueue_head(&sem->wait);
60#if WAITQUEUE_DEBUG
61 sem->__magic = (int)&sem->__magic;
62#endif
63}
64
65static inline void init_MUTEX (struct semaphore *sem)
66{
67 sema_init(sem, 1);
68}
69
70static inline void init_MUTEX_LOCKED (struct semaphore *sem)
71{
72 sema_init(sem, 0);
73}
74
75asmlinkage void __down(struct semaphore * sem);
76asmlinkage int __down_interruptible(struct semaphore * sem);
77asmlinkage int __down_trylock(struct semaphore * sem);
78asmlinkage void __up(struct semaphore * sem);
79
80extern spinlock_t semaphore_wake_lock;
81
82extern __inline__ void down(struct semaphore * sem)
83{
84#if WAITQUEUE_DEBUG
85 CHECK_MAGIC(sem->__magic);
86#endif
87
88 if (atomic_sub_return(1, &sem->count) < 0)
89 __down(sem);
90}
91
92extern __inline__ int down_interruptible(struct semaphore * sem)
93{
94 int ret = 0;
95#if WAITQUEUE_DEBUG
96 CHECK_MAGIC(sem->__magic);
97#endif
98
99 if (atomic_sub_return(1, &sem->count) < 0)
100 ret = __down_interruptible(sem);
101 return ret;
102}
103
104extern __inline__ int down_trylock(struct semaphore * sem)
105{
106 int ret = 0;
107#if WAITQUEUE_DEBUG
108 CHECK_MAGIC(sem->__magic);
109#endif
110
111 if (atomic_sub_return(1, &sem->count) < 0)
112 ret = __down_trylock(sem);
113 return ret;
114}
115
116/*
117 * Note! This is subtle. We jump to wake people up only if
118 * the semaphore was negative (== somebody was waiting on it).
119 */
120extern __inline__ void up(struct semaphore * sem)
121{
122#if WAITQUEUE_DEBUG
123 CHECK_MAGIC(sem->__magic);
124#endif
125 if (atomic_add_return(1, &sem->count) <= 0)
126 __up(sem);
127}
128
129#endif /* _XTENSA_SEMAPHORE_H */
diff --git a/include/asm-xtensa/sembuf.h b/include/asm-xtensa/sembuf.h
new file mode 100644
index 0000000000..2d26c47666
--- /dev/null
+++ b/include/asm-xtensa/sembuf.h
@@ -0,0 +1,44 @@
1/*
2 * include/asm-xtensa/sembuf.h
3 *
4 * The semid64_ds structure for Xtensa architecture.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 *
12 * Note extra padding because this structure is passed back and forth
13 * between kernel and user space.
14 *
15 * Pad space is left for:
16 * - 64-bit time_t to solve y2038 problem
17 * - 2 miscellaneous 32-bit values
18 *
19 */
20
21#ifndef _XTENSA_SEMBUF_H
22#define _XTENSA_SEMBUF_H
23
24#include <asm/byteorder.h>
25
26struct semid64_ds {
27 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
28#if XCHAL_HAVE_LE
29 __kernel_time_t sem_otime; /* last semop time */
30 unsigned long __unused1;
31 __kernel_time_t sem_ctime; /* last change time */
32 unsigned long __unused2;
33#else
34 unsigned long __unused1;
35 __kernel_time_t sem_otime; /* last semop time */
36 unsigned long __unused2;
37 __kernel_time_t sem_ctime; /* last change time */
38#endif
39 unsigned long sem_nsems; /* no. of semaphores in array */
40 unsigned long __unused3;
41 unsigned long __unused4;
42};
43
44#endif /* __ASM_XTENSA_SEMBUF_H */
diff --git a/include/asm-xtensa/serial.h b/include/asm-xtensa/serial.h
new file mode 100644
index 0000000000..ec04114fcf
--- /dev/null
+++ b/include/asm-xtensa/serial.h
@@ -0,0 +1,18 @@
1/*
2 * include/asm-xtensa/serial.h
3 *
4 * Configuration details for 8250, 16450, 16550, etc. serial ports
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_SERIAL_H
14#define _XTENSA_SERIAL_H
15
16#include <asm/platform/serial.h>
17
18#endif /* _XTENSA_SERIAL_H */
diff --git a/include/asm-xtensa/setup.h b/include/asm-xtensa/setup.h
new file mode 100644
index 0000000000..e3636520d8
--- /dev/null
+++ b/include/asm-xtensa/setup.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/setup.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SETUP_H
12#define _XTENSA_SETUP_H
13
14#define COMMAND_LINE_SIZE 256
15
16#endif
diff --git a/include/asm-xtensa/shmbuf.h b/include/asm-xtensa/shmbuf.h
new file mode 100644
index 0000000000..a30b81a4b9
--- /dev/null
+++ b/include/asm-xtensa/shmbuf.h
@@ -0,0 +1,50 @@
1/*
2 * include/asm-xtensa/shmbuf.h
3 *
4 * The shmid64_ds structure for Xtensa architecture.
5 * Note extra padding because this structure is passed back and forth
6 * between kernel and user space.
7 *
8 * Pad space is left for:
9 * - 64-bit time_t to solve y2038 problem
10 * - 2 miscellaneous 32-bit values
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file "COPYING" in the main directory of this archive
14 * for more details.
15 *
16 * Copyright (C) 2001 - 2005 Tensilica Inc.
17 */
18
19#ifndef _XTENSA_SHMBUF_H
20#define _XTENSA_SHMBUF_H
21
22struct shmid64_ds {
23 struct ipc64_perm shm_perm; /* operation perms */
24 size_t shm_segsz; /* size of segment (bytes) */
25 __kernel_time_t shm_atime; /* last attach time */
26 unsigned long __unused1;
27 __kernel_time_t shm_dtime; /* last detach time */
28 unsigned long __unused2;
29 __kernel_time_t shm_ctime; /* last change time */
30 unsigned long __unused3;
31 __kernel_pid_t shm_cpid; /* pid of creator */
32 __kernel_pid_t shm_lpid; /* pid of last operator */
33 unsigned long shm_nattch; /* no. of current attaches */
34 unsigned long __unused4;
35 unsigned long __unused5;
36};
37
38struct shminfo64 {
39 unsigned long shmmax;
40 unsigned long shmmin;
41 unsigned long shmmni;
42 unsigned long shmseg;
43 unsigned long shmall;
44 unsigned long __unused1;
45 unsigned long __unused2;
46 unsigned long __unused3;
47 unsigned long __unused4;
48};
49
50#endif /* _XTENSA_SHMBUF_H */
diff --git a/include/asm-xtensa/shmparam.h b/include/asm-xtensa/shmparam.h
new file mode 100644
index 0000000000..d3b65bfa71
--- /dev/null
+++ b/include/asm-xtensa/shmparam.h
@@ -0,0 +1,23 @@
1/*
2 * include/asm-xtensa/shmparam.h
3 *
4 * This file is subject to the terms and conditions of the GNU General
5 * Public License. See the file "COPYING" in the main directory of
6 * this archive for more details.
7 */
8
9#ifndef _XTENSA_SHMPARAM_H
10#define _XTENSA_SHMPARAM_H
11
12#include <asm/processor.h>
13
14/*
15 * Xtensa can have variable size caches, and if
16 * the size of single way is larger than the page size,
17 * then we have to start worrying about cache aliasing
18 * problems.
19 */
20
21#define SHMLBA ((PAGE_SIZE > DCACHE_WAY_SIZE)? PAGE_SIZE : DCACHE_WAY_SIZE)
22
23#endif /* _XTENSA_SHMPARAM_H */
diff --git a/include/asm-xtensa/sigcontext.h b/include/asm-xtensa/sigcontext.h
new file mode 100644
index 0000000000..a751772914
--- /dev/null
+++ b/include/asm-xtensa/sigcontext.h
@@ -0,0 +1,44 @@
1/*
2 * include/asm-xtensa/sigcontext.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2003 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SIGCONTEXT_H
12#define _XTENSA_SIGCONTEXT_H
13
14#define _ASMLANGUAGE
15#include <asm/processor.h>
16#include <asm/coprocessor.h>
17
18
19struct _cpstate {
20 unsigned char _cpstate[XTENSA_CP_EXTRA_SIZE];
21} __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
22
23
24struct sigcontext {
25 unsigned long oldmask;
26
27 /* CPU registers */
28 unsigned long sc_pc;
29 unsigned long sc_ps;
30 unsigned long sc_wmask;
31 unsigned long sc_windowbase;
32 unsigned long sc_windowstart;
33 unsigned long sc_lbeg;
34 unsigned long sc_lend;
35 unsigned long sc_lcount;
36 unsigned long sc_sar;
37 unsigned long sc_depc;
38 unsigned long sc_dareg0;
39 unsigned long sc_treg[4];
40 unsigned long sc_areg[XCHAL_NUM_AREGS];
41 struct _cpstate *sc_cpstate;
42};
43
44#endif /* __ASM_XTENSA_SIGCONTEXT_H */
diff --git a/include/asm-xtensa/siginfo.h b/include/asm-xtensa/siginfo.h
new file mode 100644
index 0000000000..44f0ae77b5
--- /dev/null
+++ b/include/asm-xtensa/siginfo.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/processor.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SIGINFO_H
12#define _XTENSA_SIGINFO_H
13
14#include <asm-generic/siginfo.h>
15
16#endif /* _XTENSA_SIGINFO_H */
diff --git a/include/asm-xtensa/signal.h b/include/asm-xtensa/signal.h
new file mode 100644
index 0000000000..5d6fc9cdf5
--- /dev/null
+++ b/include/asm-xtensa/signal.h
@@ -0,0 +1,187 @@
1/*
2 * include/asm-xtensa/signal.h
3 *
4 * Swiped from SH.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_SIGNAL_H
14#define _XTENSA_SIGNAL_H
15
16
17#define _NSIG 64
18#define _NSIG_BPW 32
19#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
20
21#ifndef __ASSEMBLY__
22
23#include <linux/types.h>
24
25/* Avoid too many header ordering problems. */
26struct siginfo;
27typedef unsigned long old_sigset_t; /* at least 32 bits */
28typedef struct {
29 unsigned long sig[_NSIG_WORDS];
30} sigset_t;
31
32#endif
33
34#define SIGHUP 1
35#define SIGINT 2
36#define SIGQUIT 3
37#define SIGILL 4
38#define SIGTRAP 5
39#define SIGABRT 6
40#define SIGIOT 6
41#define SIGBUS 7
42#define SIGFPE 8
43#define SIGKILL 9
44#define SIGUSR1 10
45#define SIGSEGV 11
46#define SIGUSR2 12
47#define SIGPIPE 13
48#define SIGALRM 14
49#define SIGTERM 15
50#define SIGSTKFLT 16
51#define SIGCHLD 17
52#define SIGCONT 18
53#define SIGSTOP 19
54#define SIGTSTP 20
55#define SIGTTIN 21
56#define SIGTTOU 22
57#define SIGURG 23
58#define SIGXCPU 24
59#define SIGXFSZ 25
60#define SIGVTALRM 26
61#define SIGPROF 27
62#define SIGWINCH 28
63#define SIGIO 29
64#define SIGPOLL SIGIO
65/* #define SIGLOST 29 */
66#define SIGPWR 30
67#define SIGSYS 31
68#define SIGUNUSED 31
69
70/* These should not be considered constants from userland. */
71#define SIGRTMIN 32
72#define SIGRTMAX (_NSIG-1)
73
74/*
75 * SA_FLAGS values:
76 *
77 * SA_ONSTACK indicates that a registered stack_t will be used.
78 * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
79 * SA_RESTART flag to get restarting signals (which were the default long ago)
80 * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
81 * SA_RESETHAND clears the handler when the signal is delivered.
82 * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
83 * SA_NODEFER prevents the current signal from being masked in the handler.
84 *
85 * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
86 * Unix names RESETHAND and NODEFER respectively.
87 */
88#define SA_NOCLDSTOP 0x00000001
89#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
90#define SA_SIGINFO 0x00000004
91#define SA_ONSTACK 0x08000000
92#define SA_RESTART 0x10000000
93#define SA_NODEFER 0x40000000
94#define SA_RESETHAND 0x80000000
95
96#define SA_NOMASK SA_NODEFER
97#define SA_ONESHOT SA_RESETHAND
98#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
99
100#define SA_RESTORER 0x04000000
101
102/*
103 * sigaltstack controls
104 */
105#define SS_ONSTACK 1
106#define SS_DISABLE 2
107
108#define MINSIGSTKSZ 2048
109#define SIGSTKSZ 8192
110
111#ifndef __ASSEMBLY__
112#ifdef __KERNEL__
113
114/*
115 * These values of sa_flags are used only by the kernel as part of the
116 * irq handling routines.
117 *
118 * SA_INTERRUPT is also used by the irq handling routines.
119 * SA_SHIRQ is for shared interrupt support on PCI and EISA.
120 */
121#define SA_PROBE SA_ONESHOT
122#define SA_SAMPLE_RANDOM SA_RESTART
123#define SA_SHIRQ 0x04000000
124#endif
125
126#define SIG_BLOCK 0 /* for blocking signals */
127#define SIG_UNBLOCK 1 /* for unblocking signals */
128#define SIG_SETMASK 2 /* for setting the signal mask */
129
130/* Type of a signal handler. */
131typedef void (*__sighandler_t)(int);
132
133#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
134#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
135#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
136
137#ifdef __KERNEL__
138struct old_sigaction {
139 __sighandler_t sa_handler;
140 old_sigset_t sa_mask;
141 unsigned long sa_flags;
142 void (*sa_restorer)(void);
143};
144
145struct sigaction {
146 __sighandler_t sa_handler;
147 unsigned long sa_flags;
148 void (*sa_restorer)(void);
149 sigset_t sa_mask; /* mask last for extensibility */
150};
151
152struct k_sigaction {
153 struct sigaction sa;
154};
155
156#else
157
158/* Here we must cater to libcs that poke about in kernel headers. */
159
160struct sigaction {
161 union {
162 __sighandler_t _sa_handler;
163 void (*_sa_sigaction)(int, struct siginfo *, void *);
164 } _u;
165 sigset_t sa_mask;
166 unsigned long sa_flags;
167 void (*sa_restorer)(void);
168};
169
170#define sa_handler _u._sa_handler
171#define sa_sigaction _u._sa_sigaction
172
173#endif /* __KERNEL__ */
174
175typedef struct sigaltstack {
176 void *ss_sp;
177 int ss_flags;
178 size_t ss_size;
179} stack_t;
180
181#ifdef __KERNEL__
182#include <asm/sigcontext.h>
183#define ptrace_signal_deliver(regs, cookie) do { } while (0)
184
185#endif /* __KERNEL__ */
186#endif /* __ASSEMBLY__ */
187#endif /* _XTENSA_SIGNAL_H */
diff --git a/include/asm-xtensa/smp.h b/include/asm-xtensa/smp.h
new file mode 100644
index 0000000000..83c569e3bd
--- /dev/null
+++ b/include/asm-xtensa/smp.h
@@ -0,0 +1,27 @@
1/*
2 * include/asm-xtensa/smp.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SMP_H
12#define _XTENSA_SMP_H
13
14extern struct xtensa_cpuinfo boot_cpu_data;
15
16#define cpu_data (&boot_cpu_data)
17#define current_cpu_data boot_cpu_data
18
19struct xtensa_cpuinfo {
20 unsigned long *pgd_cache;
21 unsigned long *pte_cache;
22 unsigned long pgtable_cache_sz;
23};
24
25#define cpu_logical_map(cpu) (cpu)
26
27#endif /* _XTENSA_SMP_H */
diff --git a/include/asm-xtensa/socket.h b/include/asm-xtensa/socket.h
new file mode 100644
index 0000000000..daccd05a14
--- /dev/null
+++ b/include/asm-xtensa/socket.h
@@ -0,0 +1,61 @@
1/*
2 * include/asm-xtensa/socket.h
3 *
4 * Copied from i386.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#ifndef _XTENSA_SOCKET_H
12#define _XTENSA_SOCKET_H
13
14#include <asm/sockios.h>
15
16/* For setsockoptions(2) */
17#define SOL_SOCKET 1
18
19#define SO_DEBUG 1
20#define SO_REUSEADDR 2
21#define SO_TYPE 3
22#define SO_ERROR 4
23#define SO_DONTROUTE 5
24#define SO_BROADCAST 6
25#define SO_SNDBUF 7
26#define SO_RCVBUF 8
27#define SO_KEEPALIVE 9
28#define SO_OOBINLINE 10
29#define SO_NO_CHECK 11
30#define SO_PRIORITY 12
31#define SO_LINGER 13
32#define SO_BSDCOMPAT 14
33/* To add :#define SO_REUSEPORT 15 */
34#define SO_PASSCRED 16
35#define SO_PEERCRED 17
36#define SO_RCVLOWAT 18
37#define SO_SNDLOWAT 19
38#define SO_RCVTIMEO 20
39#define SO_SNDTIMEO 21
40
41/* Security levels - as per NRL IPv6 - don't actually do anything */
42
43#define SO_SECURITY_AUTHENTICATION 22
44#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
45#define SO_SECURITY_ENCRYPTION_NETWORK 24
46
47#define SO_BINDTODEVICE 25
48
49/* Socket filtering */
50
51#define SO_ATTACH_FILTER 26
52#define SO_DETACH_FILTER 27
53
54#define SO_PEERNAME 28
55#define SO_TIMESTAMP 29
56#define SCM_TIMESTAMP SO_TIMESTAMP
57
58#define SO_ACCEPTCONN 30
59#define SO_PEERSEC 31
60
61#endif /* _XTENSA_SOCKET_H */
diff --git a/include/asm-xtensa/sockios.h b/include/asm-xtensa/sockios.h
new file mode 100644
index 0000000000..20d2ba10ec
--- /dev/null
+++ b/include/asm-xtensa/sockios.h
@@ -0,0 +1,30 @@
1/*
2 * include/asm-xtensa/sockios.h
3 *
4 * Socket-level I/O control calls. Copied from MIPS.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 1995 by Ralf Baechle
11 * Copyright (C) 2001 Tensilica Inc.
12 */
13
14#ifndef _XTENSA_SOCKIOS_H
15#define _XTENSA_SOCKIOS_H
16
17#include <asm/ioctl.h>
18
19/* Socket-level I/O control calls. */
20
21#define FIOGETOWN _IOR('f', 123, int)
22#define FIOSETOWN _IOW('f', 124, int)
23
24#define SIOCATMARK _IOR('s', 7, int)
25#define SIOCSPGRP _IOW('s', 8, pid_t)
26#define SIOCGPGRP _IOR('s', 9, pid_t)
27
28#define SIOCGSTAMP 0x8906 /* Get stamp - linux-specific */
29
30#endif /* _XTENSA_SOCKIOS_H */
diff --git a/include/asm-xtensa/spinlock.h b/include/asm-xtensa/spinlock.h
new file mode 100644
index 0000000000..8ff2364958
--- /dev/null
+++ b/include/asm-xtensa/spinlock.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/spinlock.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SPINLOCK_H
12#define _XTENSA_SPINLOCK_H
13
14#include <linux/spinlock.h>
15
16#endif /* _XTENSA_SPINLOCK_H */
diff --git a/include/asm-xtensa/stat.h b/include/asm-xtensa/stat.h
new file mode 100644
index 0000000000..2f4662ff6c
--- /dev/null
+++ b/include/asm-xtensa/stat.h
@@ -0,0 +1,105 @@
1/*
2 * include/asm-xtensa/stat.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_STAT_H
12#define _XTENSA_STAT_H
13
14#include <linux/types.h>
15
16struct __old_kernel_stat {
17 unsigned short st_dev;
18 unsigned short st_ino;
19 unsigned short st_mode;
20 unsigned short st_nlink;
21 unsigned short st_uid;
22 unsigned short st_gid;
23 unsigned short st_rdev;
24 unsigned long st_size;
25 unsigned long st_atime;
26 unsigned long st_mtime;
27 unsigned long st_ctime;
28};
29
30#define STAT_HAVE_NSEC 1
31
32struct stat {
33 unsigned short st_dev;
34 unsigned short __pad1;
35 unsigned long st_ino;
36 unsigned short st_mode;
37 unsigned short st_nlink;
38 unsigned short st_uid;
39 unsigned short st_gid;
40 unsigned short st_rdev;
41 unsigned short __pad2;
42 unsigned long st_size;
43 unsigned long st_blksize;
44 unsigned long st_blocks;
45 unsigned long st_atime;
46 unsigned long st_atime_nsec;
47 unsigned long st_mtime;
48 unsigned long st_mtime_nsec;
49 unsigned long st_ctime;
50 unsigned long st_ctime_nsec;
51 unsigned long __unused4;
52 unsigned long __unused5;
53};
54
55/* This matches struct stat64 in glibc-2.2.3. */
56
57struct stat64 {
58#ifdef __XTENSA_EL__
59 unsigned short st_dev; /* Device */
60 unsigned char __pad0[10];
61#else
62 unsigned char __pad0[6];
63 unsigned short st_dev;
64 unsigned char __pad1[2];
65#endif
66
67#define STAT64_HAS_BROKEN_ST_INO 1
68 unsigned long __st_ino; /* 32bit file serial number. */
69
70 unsigned int st_mode; /* File mode. */
71 unsigned int st_nlink; /* Link count. */
72 unsigned int st_uid; /* User ID of the file's owner. */
73 unsigned int st_gid; /* Group ID of the file's group. */
74
75#ifdef __XTENSA_EL__
76 unsigned short st_rdev; /* Device number, if device. */
77 unsigned char __pad3[10];
78#else
79 unsigned char __pad2[6];
80 unsigned short st_rdev;
81 unsigned char __pad3[2];
82#endif
83
84 long long int st_size; /* Size of file, in bytes. */
85 long int st_blksize; /* Optimal block size for I/O. */
86
87#ifdef __XTENSA_EL__
88 unsigned long st_blocks; /* Number 512-byte blocks allocated. */
89 unsigned long __pad4;
90#else
91 unsigned long __pad4;
92 unsigned long st_blocks;
93#endif
94
95 unsigned long __pad5;
96 long int st_atime; /* Time of last access. */
97 unsigned long st_atime_nsec;
98 long int st_mtime; /* Time of last modification. */
99 unsigned long st_mtime_nsec;
100 long int st_ctime; /* Time of last status change. */
101 unsigned long st_ctime_nsec;
102 unsigned long long int st_ino; /* File serial number. */
103};
104
105#endif /* _XTENSA_STAT_H */
diff --git a/include/asm-xtensa/statfs.h b/include/asm-xtensa/statfs.h
new file mode 100644
index 0000000000..9c3d1a2131
--- /dev/null
+++ b/include/asm-xtensa/statfs.h
@@ -0,0 +1,17 @@
1/*
2 * include/asm-xtensa/statfs.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_STATFS_H
12#define _XTENSA_STATFS_H
13
14#include <asm-generic/statfs.h>
15
16#endif /* _XTENSA_STATFS_H */
17
diff --git a/include/asm-xtensa/string.h b/include/asm-xtensa/string.h
new file mode 100644
index 0000000000..3f81b27d98
--- /dev/null
+++ b/include/asm-xtensa/string.h
@@ -0,0 +1,124 @@
1/*
2 * include/asm-xtensa/string.h
3 *
4 * These trivial string functions are considered part of the public domain.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13/* We should optimize these. See arch/xtensa/lib/strncpy_user.S */
14
15#ifndef _XTENSA_STRING_H
16#define _XTENSA_STRING_H
17
18#define __HAVE_ARCH_STRCPY
19extern __inline__ char *strcpy(char *__dest, const char *__src)
20{
21 register char *__xdest = __dest;
22 unsigned long __dummy;
23
24 __asm__ __volatile__("1:\n\t"
25 "l8ui %2, %1, 0\n\t"
26 "s8i %2, %0, 0\n\t"
27 "addi %1, %1, 1\n\t"
28 "addi %0, %0, 1\n\t"
29 "bnez %2, 1b\n\t"
30 : "=r" (__dest), "=r" (__src), "=&r" (__dummy)
31 : "0" (__dest), "1" (__src)
32 : "memory");
33
34 return __xdest;
35}
36
37#define __HAVE_ARCH_STRNCPY
38extern __inline__ char *strncpy(char *__dest, const char *__src, size_t __n)
39{
40 register char *__xdest = __dest;
41 unsigned long __dummy;
42
43 if (__n == 0)
44 return __xdest;
45
46 __asm__ __volatile__(
47 "1:\n\t"
48 "l8ui %2, %1, 0\n\t"
49 "s8i %2, %0, 0\n\t"
50 "addi %1, %1, 1\n\t"
51 "addi %0, %0, 1\n\t"
52 "beqz %2, 2f\n\t"
53 "bne %1, %5, 1b\n"
54 "2:"
55 : "=r" (__dest), "=r" (__src), "=&r" (__dummy)
56 : "0" (__dest), "1" (__src), "r" (__src+__n)
57 : "memory");
58
59 return __xdest;
60}
61
62#define __HAVE_ARCH_STRCMP
63extern __inline__ int strcmp(const char *__cs, const char *__ct)
64{
65 register int __res;
66 unsigned long __dummy;
67
68 __asm__ __volatile__(
69 "1:\n\t"
70 "l8ui %3, %1, 0\n\t"
71 "addi %1, %1, 1\n\t"
72 "l8ui %2, %0, 0\n\t"
73 "addi %0, %0, 1\n\t"
74 "beqz %2, 2f\n\t"
75 "beq %2, %3, 1b\n"
76 "2:\n\t"
77 "sub %2, %3, %2"
78 : "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&r" (__dummy)
79 : "0" (__cs), "1" (__ct));
80
81 return __res;
82}
83
84#define __HAVE_ARCH_STRNCMP
85extern __inline__ int strncmp(const char *__cs, const char *__ct, size_t __n)
86{
87 register int __res;
88 unsigned long __dummy;
89
90 __asm__ __volatile__(
91 "mov %2, %3\n"
92 "1:\n\t"
93 "beq %0, %6, 2f\n\t"
94 "l8ui %3, %1, 0\n\t"
95 "addi %1, %1, 1\n\t"
96 "l8ui %2, %0, 0\n\t"
97 "addi %0, %0, 1\n\t"
98 "beqz %2, 2f\n\t"
99 "beqz %3, 2f\n\t"
100 "beq %2, %3, 1b\n"
101 "2:\n\t"
102 "sub %2, %3, %2"
103 : "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&r" (__dummy)
104 : "0" (__cs), "1" (__ct), "r" (__cs+__n));
105
106 return __res;
107}
108
109#define __HAVE_ARCH_MEMSET
110extern void *memset(void *__s, int __c, size_t __count);
111
112#define __HAVE_ARCH_MEMCPY
113extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
114
115#define __HAVE_ARCH_MEMMOVE
116extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
117
118/* Don't build bcopy at all ... */
119#define __HAVE_ARCH_BCOPY
120
121#define __HAVE_ARCH_MEMSCAN
122#define memscan memchr
123
124#endif /* _XTENSA_STRING_H */
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
new file mode 100644
index 0000000000..690fe325e6
--- /dev/null
+++ b/include/asm-xtensa/system.h
@@ -0,0 +1,252 @@
1/*
2 * include/asm-xtensa/system.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_SYSTEM_H
12#define _XTENSA_SYSTEM_H
13
14#include <linux/config.h>
15#include <linux/stringify.h>
16
17#include <asm/processor.h>
18
19/* interrupt control */
20
21#define local_save_flags(x) \
22 __asm__ __volatile__ ("rsr %0,"__stringify(PS) : "=a" (x));
23#define local_irq_restore(x) do { \
24 __asm__ __volatile__ ("wsr %0, "__stringify(PS)" ; rsync" \
25 :: "a" (x) : "memory"); } while(0);
26#define local_irq_save(x) do { \
27 __asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL) \
28 : "=a" (x) :: "memory");} while(0);
29
30static inline void local_irq_disable(void)
31{
32 unsigned long flags;
33 __asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL)
34 : "=a" (flags) :: "memory");
35}
36static inline void local_irq_enable(void)
37{
38 unsigned long flags;
39 __asm__ __volatile__ ("rsil %0, 0" : "=a" (flags) :: "memory");
40
41}
42
43static inline int irqs_disabled(void)
44{
45 unsigned long flags;
46 local_save_flags(flags);
47 return flags & 0xf;
48}
49
50#define RSR_CPENABLE(x) do { \
51 __asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \
52 } while(0);
53#define WSR_CPENABLE(x) do { \
54 __asm__ __volatile__("wsr %0," __stringify(CPENABLE)";rsync" \
55 :: "a" (x));} while(0);
56
57#define clear_cpenable() __clear_cpenable()
58
59extern __inline__ void __clear_cpenable(void)
60{
61#if XCHAL_HAVE_CP
62 unsigned long i = 0;
63 WSR_CPENABLE(i);
64#endif
65}
66
67extern __inline__ void enable_coprocessor(int i)
68{
69#if XCHAL_HAVE_CP
70 int cp;
71 RSR_CPENABLE(cp);
72 cp |= 1 << i;
73 WSR_CPENABLE(cp);
74#endif
75}
76
77extern __inline__ void disable_coprocessor(int i)
78{
79#if XCHAL_HAVE_CP
80 int cp;
81 RSR_CPENABLE(cp);
82 cp &= ~(1 << i);
83 WSR_CPENABLE(cp);
84#endif
85}
86
87#define smp_read_barrier_depends() do { } while(0)
88#define read_barrier_depends() do { } while(0)
89
90#define mb() barrier()
91#define rmb() mb()
92#define wmb() mb()
93
94#ifdef CONFIG_SMP
95#error smp_* not defined
96#else
97#define smp_mb() barrier()
98#define smp_rmb() barrier()
99#define smp_wmb() barrier()
100#endif
101
102#define set_mb(var, value) do { var = value; mb(); } while (0)
103#define set_wmb(var, value) do { var = value; wmb(); } while (0)
104
105#if !defined (__ASSEMBLY__)
106
107/* * switch_to(n) should switch tasks to task nr n, first
108 * checking that n isn't the current task, in which case it does nothing.
109 */
110extern void *_switch_to(void *last, void *next);
111
112#endif /* __ASSEMBLY__ */
113
114#define prepare_to_switch() do { } while(0)
115
116#define switch_to(prev,next,last) \
117do { \
118 clear_cpenable(); \
119 (last) = _switch_to(prev, next); \
120} while(0)
121
122/*
123 * cmpxchg
124 */
125
126extern __inline__ unsigned long
127__cmpxchg_u32(volatile int *p, int old, int new)
128{
129 __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t"
130 "l32i %0, %1, 0 \n\t"
131 "bne %0, %2, 1f \n\t"
132 "s32i %3, %1, 0 \n\t"
133 "1: \n\t"
134 "wsr a15, "__stringify(PS)" \n\t"
135 "rsync \n\t"
136 : "=&a" (old)
137 : "a" (p), "a" (old), "r" (new)
138 : "a15", "memory");
139 return old;
140}
141/* This function doesn't exist, so you'll get a linker error
142 * if something tries to do an invalid cmpxchg(). */
143
144extern void __cmpxchg_called_with_bad_pointer(void);
145
146static __inline__ unsigned long
147__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
148{
149 switch (size) {
150 case 4: return __cmpxchg_u32(ptr, old, new);
151 default: __cmpxchg_called_with_bad_pointer();
152 return old;
153 }
154}
155
156#define cmpxchg(ptr,o,n) \
157 ({ __typeof__(*(ptr)) _o_ = (o); \
158 __typeof__(*(ptr)) _n_ = (n); \
159 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
160 (unsigned long)_n_, sizeof (*(ptr))); \
161 })
162
163
164
165
166/*
167 * xchg_u32
168 *
169 * Note that a15 is used here because the register allocation
170 * done by the compiler is not guaranteed and a window overflow
171 * may not occur between the rsil and wsr instructions. By using
172 * a15 in the rsil, the machine is guaranteed to be in a state
173 * where no register reference will cause an overflow.
174 */
175
176extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
177{
178 unsigned long tmp;
179 __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t"
180 "l32i %0, %1, 0 \n\t"
181 "s32i %2, %1, 0 \n\t"
182 "wsr a15, "__stringify(PS)" \n\t"
183 "rsync \n\t"
184 : "=&a" (tmp)
185 : "a" (m), "a" (val)
186 : "a15", "memory");
187 return tmp;
188}
189
190#define tas(ptr) (xchg((ptr),1))
191
192#if ( __XCC__ == 1 )
193
194/* xt-xcc processes __inline__ differently than xt-gcc and decides to
195 * insert an out-of-line copy of function __xchg. This presents the
196 * unresolved symbol at link time of __xchg_called_with_bad_pointer,
197 * even though such a function would never be called at run-time.
198 * xt-gcc always inlines __xchg, and optimizes away the undefined
199 * bad_pointer function.
200 */
201
202#define xchg(ptr,x) xchg_u32(ptr,x)
203
204#else /* assume xt-gcc */
205
206#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
207
208/*
209 * This only works if the compiler isn't horribly bad at optimizing.
210 * gcc-2.5.8 reportedly can't handle this, but I define that one to
211 * be dead anyway.
212 */
213
214extern void __xchg_called_with_bad_pointer(void);
215
216static __inline__ unsigned long
217__xchg(unsigned long x, volatile void * ptr, int size)
218{
219 switch (size) {
220 case 4:
221 return xchg_u32(ptr, x);
222 }
223 __xchg_called_with_bad_pointer();
224 return x;
225}
226
227#endif
228
229extern void set_except_vector(int n, void *addr);
230
231static inline void spill_registers(void)
232{
233 unsigned int a0, ps;
234
235 __asm__ __volatile__ (
236 "movi a14," __stringify (PS_EXCM_MASK) " | 1\n\t"
237 "mov a12, a0\n\t"
238 "rsr a13," __stringify(SAR) "\n\t"
239 "xsr a14," __stringify(PS) "\n\t"
240 "movi a0, _spill_registers\n\t"
241 "rsync\n\t"
242 "callx0 a0\n\t"
243 "mov a0, a12\n\t"
244 "wsr a13," __stringify(SAR) "\n\t"
245 "wsr a14," __stringify(PS) "\n\t"
246 :: "a" (&a0), "a" (&ps)
247 : "a2", "a3", "a12", "a13", "a14", "a15", "memory");
248}
249
250#define arch_align_stack(x) (x)
251
252#endif /* _XTENSA_SYSTEM_H */
diff --git a/include/asm-xtensa/termbits.h b/include/asm-xtensa/termbits.h
new file mode 100644
index 0000000000..c780593ff5
--- /dev/null
+++ b/include/asm-xtensa/termbits.h
@@ -0,0 +1,194 @@
1/*
2 * include/asm-xtensa/termbits.h
3 *
4 * Copied from SH.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_TERMBITS_H
14#define _XTENSA_TERMBITS_H
15
16
17#include <linux/posix_types.h>
18
19typedef unsigned char cc_t;
20typedef unsigned int speed_t;
21typedef unsigned int tcflag_t;
22
23#define NCCS 19
24struct termios {
25 tcflag_t c_iflag; /* input mode flags */
26 tcflag_t c_oflag; /* output mode flags */
27 tcflag_t c_cflag; /* control mode flags */
28 tcflag_t c_lflag; /* local mode flags */
29 cc_t c_line; /* line discipline */
30 cc_t c_cc[NCCS]; /* control characters */
31};
32
33/* c_cc characters */
34
35#define VINTR 0
36#define VQUIT 1
37#define VERASE 2
38#define VKILL 3
39#define VEOF 4
40#define VTIME 5
41#define VMIN 6
42#define VSWTC 7
43#define VSTART 8
44#define VSTOP 9
45#define VSUSP 10
46#define VEOL 11
47#define VREPRINT 12
48#define VDISCARD 13
49#define VWERASE 14
50#define VLNEXT 15
51#define VEOL2 16
52
53/* c_iflag bits */
54
55#define IGNBRK 0000001
56#define BRKINT 0000002
57#define IGNPAR 0000004
58#define PARMRK 0000010
59#define INPCK 0000020
60#define ISTRIP 0000040
61#define INLCR 0000100
62#define IGNCR 0000200
63#define ICRNL 0000400
64#define IUCLC 0001000
65#define IXON 0002000
66#define IXANY 0004000
67#define IXOFF 0010000
68#define IMAXBEL 0020000
69#define IUTF8 0040000
70
71/* c_oflag bits */
72
73#define OPOST 0000001
74#define OLCUC 0000002
75#define ONLCR 0000004
76#define OCRNL 0000010
77#define ONOCR 0000020
78#define ONLRET 0000040
79#define OFILL 0000100
80#define OFDEL 0000200
81#define NLDLY 0000400
82#define NL0 0000000
83#define NL1 0000400
84#define CRDLY 0003000
85#define CR0 0000000
86#define CR1 0001000
87#define CR2 0002000
88#define CR3 0003000
89#define TABDLY 0014000
90#define TAB0 0000000
91#define TAB1 0004000
92#define TAB2 0010000
93#define TAB3 0014000
94#define XTABS 0014000
95#define BSDLY 0020000
96#define BS0 0000000
97#define BS1 0020000
98#define VTDLY 0040000
99#define VT0 0000000
100#define VT1 0040000
101#define FFDLY 0100000
102#define FF0 0000000
103#define FF1 0100000
104
105/* c_cflag bit meaning */
106
107#define CBAUD 0010017
108#define B0 0000000 /* hang up */
109#define B50 0000001
110#define B75 0000002
111#define B110 0000003
112#define B134 0000004
113#define B150 0000005
114#define B200 0000006
115#define B300 0000007
116#define B600 0000010
117#define B1200 0000011
118#define B1800 0000012
119#define B2400 0000013
120#define B4800 0000014
121#define B9600 0000015
122#define B19200 0000016
123#define B38400 0000017
124#define EXTA B19200
125#define EXTB B38400
126#define CSIZE 0000060
127#define CS5 0000000
128#define CS6 0000020
129#define CS7 0000040
130#define CS8 0000060
131#define CSTOPB 0000100
132#define CREAD 0000200
133#define PARENB 0000400
134#define PARODD 0001000
135#define HUPCL 0002000
136#define CLOCAL 0004000
137#define CBAUDEX 0010000
138#define B57600 0010001
139#define B115200 0010002
140#define B230400 0010003
141#define B460800 0010004
142#define B500000 0010005
143#define B576000 0010006
144#define B921600 0010007
145#define B1000000 0010010
146#define B1152000 0010011
147#define B1500000 0010012
148#define B2000000 0010013
149#define B2500000 0010014
150#define B3000000 0010015
151#define B3500000 0010016
152#define B4000000 0010017
153#define CIBAUD 002003600000 /* input baud rate (not used) */
154#define CMSPAR 010000000000 /* mark or space (stick) parity */
155#define CRTSCTS 020000000000 /* flow control */
156
157/* c_lflag bits */
158
159#define ISIG 0000001
160#define ICANON 0000002
161#define XCASE 0000004
162#define ECHO 0000010
163#define ECHOE 0000020
164#define ECHOK 0000040
165#define ECHONL 0000100
166#define NOFLSH 0000200
167#define TOSTOP 0000400
168#define ECHOCTL 0001000
169#define ECHOPRT 0002000
170#define ECHOKE 0004000
171#define FLUSHO 0010000
172#define PENDIN 0040000
173#define IEXTEN 0100000
174
175/* tcflow() and TCXONC use these */
176
177#define TCOOFF 0
178#define TCOON 1
179#define TCIOFF 2
180#define TCION 3
181
182/* tcflush() and TCFLSH use these */
183
184#define TCIFLUSH 0
185#define TCOFLUSH 1
186#define TCIOFLUSH 2
187
188/* tcsetattr uses these */
189
190#define TCSANOW 0
191#define TCSADRAIN 1
192#define TCSAFLUSH 2
193
194#endif /* _XTENSA_TERMBITS_H */
diff --git a/include/asm-xtensa/termios.h b/include/asm-xtensa/termios.h
new file mode 100644
index 0000000000..83c6aed1d1
--- /dev/null
+++ b/include/asm-xtensa/termios.h
@@ -0,0 +1,122 @@
1/*
2 * include/asm-xtensa/termios.h
3 *
4 * Copied from SH.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_TERMIOS_H
14#define _XTENSA_TERMIOS_H
15
16#include <asm/termbits.h>
17#include <asm/ioctls.h>
18
19struct winsize {
20 unsigned short ws_row;
21 unsigned short ws_col;
22 unsigned short ws_xpixel;
23 unsigned short ws_ypixel;
24};
25
26#define NCC 8
27struct termio {
28 unsigned short c_iflag; /* input mode flags */
29 unsigned short c_oflag; /* output mode flags */
30 unsigned short c_cflag; /* control mode flags */
31 unsigned short c_lflag; /* local mode flags */
32 unsigned char c_line; /* line discipline */
33 unsigned char c_cc[NCC]; /* control characters */
34};
35
36/* Modem lines */
37
38#define TIOCM_LE 0x001
39#define TIOCM_DTR 0x002
40#define TIOCM_RTS 0x004
41#define TIOCM_ST 0x008
42#define TIOCM_SR 0x010
43#define TIOCM_CTS 0x020
44#define TIOCM_CAR 0x040
45#define TIOCM_RNG 0x080
46#define TIOCM_DSR 0x100
47#define TIOCM_CD TIOCM_CAR
48#define TIOCM_RI TIOCM_RNG
49#define TIOCM_OUT1 0x2000
50#define TIOCM_OUT2 0x4000
51#define TIOCM_LOOP 0x8000
52
53/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
54
55/* Line disciplines */
56
57#define N_TTY 0
58#define N_SLIP 1
59#define N_MOUSE 2
60#define N_PPP 3
61#define N_STRIP 4
62#define N_AX25 5
63#define N_X25 6 /* X.25 async */
64#define N_6PACK 7
65#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
66#define N_R3964 9 /* Reserved for Simatic R3964 module */
67#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
68#define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */
69#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
70#define N_HDLC 13 /* synchronous HDLC */
71#define N_SYNC_PPP 14
72#define N_HCI 15 /* Bluetooth HCI UART */
73
74#ifdef __KERNEL__
75
76/* intr=^C quit=^\ erase=del kill=^U
77 eof=^D vtime=\0 vmin=\1 sxtc=\0
78 start=^Q stop=^S susp=^Z eol=\0
79 reprint=^R discard=^U werase=^W lnext=^V
80 eol2=\0
81*/
82#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
83
84/*
85 * Translate a "termio" structure into a "termios". Ugh.
86 */
87
88#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
89 unsigned short __tmp; \
90 get_user(__tmp,&(termio)->x); \
91 *(unsigned short *) &(termios)->x = __tmp; \
92}
93
94#define user_termio_to_kernel_termios(termios, termio) \
95({ \
96 SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
97 SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
98 SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
99 SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
100 copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
101})
102
103/*
104 * Translate a "termios" structure into a "termio". Ugh.
105 */
106
107#define kernel_termios_to_user_termio(termio, termios) \
108({ \
109 put_user((termios)->c_iflag, &(termio)->c_iflag); \
110 put_user((termios)->c_oflag, &(termio)->c_oflag); \
111 put_user((termios)->c_cflag, &(termio)->c_cflag); \
112 put_user((termios)->c_lflag, &(termio)->c_lflag); \
113 put_user((termios)->c_line, &(termio)->c_line); \
114 copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
115})
116
117#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
118#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
119
120#endif /* __KERNEL__ */
121
122#endif /* _XTENSA_TERMIOS_H */
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h
new file mode 100644
index 0000000000..af208d41fd
--- /dev/null
+++ b/include/asm-xtensa/thread_info.h
@@ -0,0 +1,146 @@
1/*
2 * include/asm-xtensa/thread_info.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_THREAD_INFO_H
12#define _XTENSA_THREAD_INFO_H
13
14#ifdef __KERNEL__
15
16#ifndef __ASSEMBLY__
17# include <asm/processor.h>
18#endif
19
20/*
21 * low level task data that entry.S needs immediate access to
22 * - this struct should fit entirely inside of one cache line
23 * - this struct shares the supervisor stack pages
24 * - if the contents of this structure are changed, the assembly constants
25 * must also be changed
26 */
27
28#ifndef __ASSEMBLY__
29
30struct thread_info {
31 struct task_struct *task; /* main task structure */
32 struct exec_domain *exec_domain; /* execution domain */
33 unsigned long flags; /* low level flags */
34 unsigned long status; /* thread-synchronous flags */
35 __u32 cpu; /* current CPU */
36 __s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
37
38 mm_segment_t addr_limit; /* thread address space */
39 struct restart_block restart_block;
40
41
42};
43
44#else /* !__ASSEMBLY__ */
45
46/* offsets into the thread_info struct for assembly code access */
47#define TI_TASK 0x00000000
48#define TI_EXEC_DOMAIN 0x00000004
49#define TI_FLAGS 0x00000008
50#define TI_STATUS 0x0000000C
51#define TI_CPU 0x00000010
52#define TI_PRE_COUNT 0x00000014
53#define TI_ADDR_LIMIT 0x00000018
54#define TI_RESTART_BLOCK 0x000001C
55
56#endif
57
58#define PREEMPT_ACTIVE 0x10000000
59
60/*
61 * macros/functions for gaining access to the thread information structure
62 *
63 * preempt_count needs to be 1 initially, until the scheduler is functional.
64 */
65
66#ifndef __ASSEMBLY__
67
68#define INIT_THREAD_INFO(tsk) \
69{ \
70 .task = &tsk, \
71 .exec_domain = &default_exec_domain, \
72 .flags = 0, \
73 .cpu = 0, \
74 .preempt_count = 1, \
75 .addr_limit = KERNEL_DS, \
76 .restart_block = { \
77 .fn = do_no_restart_syscall, \
78 }, \
79}
80
81#define init_thread_info (init_thread_union.thread_info)
82#define init_stack (init_thread_union.stack)
83
84/* how to get the thread information struct from C */
85static inline struct thread_info *current_thread_info(void)
86{
87 struct thread_info *ti;
88 __asm__("extui %0,a1,0,13\n\t"
89 "xor %0, a1, %0" : "=&r" (ti) : );
90 return ti;
91}
92
93/* thread information allocation */
94#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
95#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
96#define get_thread_info(ti) get_task_struct((ti)->task)
97#define put_thread_info(ti) put_task_struct((ti)->task)
98
99#else /* !__ASSEMBLY__ */
100
101/* how to get the thread information struct from ASM */
102#define GET_THREAD_INFO(reg,sp) \
103 extui reg, sp, 0, 13; \
104 xor reg, sp, reg
105#endif
106
107
108/*
109 * thread information flags
110 * - these are process state flags that various assembly files may need to access
111 * - pending work-to-be-done flags are in LSW
112 * - other flags in MSW
113 */
114#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
115#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
116#define TIF_SIGPENDING 2 /* signal pending */
117#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
118#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
119#define TIF_IRET 5 /* return with iret */
120#define TIF_MEMDIE 6
121#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
122
123#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
124#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
125#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
126#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
127#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
128#define _TIF_IRET (1<<TIF_IRET)
129#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
130
131#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
132#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
133
134/*
135 * Thread-synchronous status.
136 *
137 * This is different from the flags in that nobody else
138 * ever touches our thread-synchronous status, so we don't
139 * have to worry about atomic accesses.
140 */
141#define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */
142
143#define THREAD_SIZE 8192 //(2*PAGE_SIZE)
144
145#endif /* __KERNEL__ */
146#endif /* _XTENSA_THREAD_INFO */
diff --git a/include/asm-xtensa/timex.h b/include/asm-xtensa/timex.h
new file mode 100644
index 0000000000..d14a3755a1
--- /dev/null
+++ b/include/asm-xtensa/timex.h
@@ -0,0 +1,94 @@
1/*
2 * include/asm-xtensa/timex.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_TIMEX_H
12#define _XTENSA_TIMEX_H
13
14#ifdef __KERNEL__
15
16#include <asm/processor.h>
17#include <linux/stringify.h>
18
19#if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
20# define LINUX_TIMER 0
21#elif XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) == 1
22# define LINUX_TIMER 1
23#elif XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) == 1
24# define LINUX_TIMER 2
25#else
26# error "Bad timer number for Linux configurations!"
27#endif
28
29#define LINUX_TIMER_INT XCHAL_TIMER_INTERRUPT(LINUX_TIMER)
30#define LINUX_TIMER_MASK (1L << LINUX_TIMER_INT)
31
32#define CLOCK_TICK_RATE 1193180 /* (everyone is using this value) */
33#define CLOCK_TICK_FACTOR 20 /* Factor of both 10^6 and CLOCK_TICK_RATE */
34#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
35 (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
36 << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
37
38#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
39extern unsigned long ccount_per_jiffy;
40extern unsigned long ccount_nsec;
41#define CCOUNT_PER_JIFFY ccount_per_jiffy
42#define CCOUNT_NSEC ccount_nsec
43#else
44#define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ))
45#define CCOUNT_NSEC (1000000000UL / CONFIG_XTENSA_CPU_CLOCK)
46#endif
47
48
49typedef unsigned long long cycles_t;
50
51/*
52 * Only used for SMP.
53 */
54
55extern cycles_t cacheflush_time;
56
57#define get_cycles() (0)
58
59
60/*
61 * Register access.
62 */
63
64#define WSR_CCOUNT(r) __asm__("wsr %0,"__stringify(CCOUNT) :: "a" (r))
65#define RSR_CCOUNT(r) __asm__("rsr %0,"__stringify(CCOUNT) : "=a" (r))
66#define WSR_CCOMPARE(x,r) __asm__("wsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) :: "a"(r))
67#define RSR_CCOMPARE(x,r) __asm__("rsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) : "=a"(r))
68
69static inline unsigned long get_ccount (void)
70{
71 unsigned long ccount;
72 RSR_CCOUNT(ccount);
73 return ccount;
74}
75
76static inline void set_ccount (unsigned long ccount)
77{
78 WSR_CCOUNT(ccount);
79}
80
81static inline unsigned long get_linux_timer (void)
82{
83 unsigned ccompare;
84 RSR_CCOMPARE(LINUX_TIMER, ccompare);
85 return ccompare;
86}
87
88static inline void set_linux_timer (unsigned long ccompare)
89{
90 WSR_CCOMPARE(LINUX_TIMER, ccompare);
91}
92
93#endif /* __KERNEL__ */
94#endif /* _XTENSA_TIMEX_H */
diff --git a/include/asm-xtensa/tlb.h b/include/asm-xtensa/tlb.h
new file mode 100644
index 0000000000..4562b2dcfb
--- /dev/null
+++ b/include/asm-xtensa/tlb.h
@@ -0,0 +1,25 @@
1/*
2 * include/asm-xtensa/tlb.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_TLB_H
12#define _XTENSA_TLB_H
13
14#define tlb_start_vma(tlb,vma) do { } while (0)
15#define tlb_end_vma(tlb,vma) do { } while (0)
16#define __tlb_remove_tlb_entry(tlb,pte,addr) do { } while (0)
17
18#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
19
20#include <asm-generic/tlb.h>
21#include <asm/page.h>
22
23#define __pte_free_tlb(tlb,pte) pte_free(pte)
24
25#endif /* _XTENSA_TLB_H */
diff --git a/include/asm-xtensa/tlbflush.h b/include/asm-xtensa/tlbflush.h
new file mode 100644
index 0000000000..23bfe9db45
--- /dev/null
+++ b/include/asm-xtensa/tlbflush.h
@@ -0,0 +1,200 @@
1/*
2 * include/asm-xtensa/tlbflush.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_TLBFLUSH_H
12#define _XTENSA_TLBFLUSH_H
13
14#define DEBUG_TLB
15
16#ifdef __KERNEL__
17
18#include <asm/processor.h>
19#include <linux/stringify.h>
20
21/* TLB flushing:
22 *
23 * - flush_tlb_all() flushes all processes TLB entries
24 * - flush_tlb_mm(mm) flushes the specified mm context TLB entries
25 * - flush_tlb_page(mm, vmaddr) flushes a single page
26 * - flush_tlb_range(mm, start, end) flushes a range of pages
27 */
28
29extern void flush_tlb_all(void);
30extern void flush_tlb_mm(struct mm_struct*);
31extern void flush_tlb_page(struct vm_area_struct*,unsigned long);
32extern void flush_tlb_range(struct vm_area_struct*,unsigned long,unsigned long);
33
34#define flush_tlb_kernel_range(start,end) flush_tlb_all()
35
36
37/* This is calld in munmap when we have freed up some page-table pages.
38 * We don't need to do anything here, there's nothing special about our
39 * page-table pages.
40 */
41
42extern inline void flush_tlb_pgtables(struct mm_struct *mm,
43 unsigned long start, unsigned long end)
44{
45}
46
47/* TLB operations. */
48
49#define ITLB_WAYS_LOG2 XCHAL_ITLB_WAY_BITS
50#define DTLB_WAYS_LOG2 XCHAL_DTLB_WAY_BITS
51#define ITLB_PROBE_SUCCESS (1 << ITLB_WAYS_LOG2)
52#define DTLB_PROBE_SUCCESS (1 << DTLB_WAYS_LOG2)
53
54extern inline unsigned long itlb_probe(unsigned long addr)
55{
56 unsigned long tmp;
57 __asm__ __volatile__("pitlb %0, %1\n\t" : "=a" (tmp) : "a" (addr));
58 return tmp;
59}
60
61extern inline unsigned long dtlb_probe(unsigned long addr)
62{
63 unsigned long tmp;
64 __asm__ __volatile__("pdtlb %0, %1\n\t" : "=a" (tmp) : "a" (addr));
65 return tmp;
66}
67
68extern inline void invalidate_itlb_entry (unsigned long probe)
69{
70 __asm__ __volatile__("iitlb %0; isync\n\t" : : "a" (probe));
71}
72
73extern inline void invalidate_dtlb_entry (unsigned long probe)
74{
75 __asm__ __volatile__("idtlb %0; dsync\n\t" : : "a" (probe));
76}
77
78/* Use the .._no_isync functions with caution. Generally, these are
79 * handy for bulk invalidates followed by a single 'isync'. The
80 * caller must follow up with an 'isync', which can be relatively
81 * expensive on some Xtensa implementations.
82 */
83extern inline void invalidate_itlb_entry_no_isync (unsigned entry)
84{
85 /* Caller must follow up with 'isync'. */
86 __asm__ __volatile__ ("iitlb %0\n" : : "a" (entry) );
87}
88
89extern inline void invalidate_dtlb_entry_no_isync (unsigned entry)
90{
91 /* Caller must follow up with 'isync'. */
92 __asm__ __volatile__ ("idtlb %0\n" : : "a" (entry) );
93}
94
95extern inline void set_itlbcfg_register (unsigned long val)
96{
97 __asm__ __volatile__("wsr %0, "__stringify(ITLBCFG)"\n\t" "isync\n\t"
98 : : "a" (val));
99}
100
101extern inline void set_dtlbcfg_register (unsigned long val)
102{
103 __asm__ __volatile__("wsr %0, "__stringify(DTLBCFG)"; dsync\n\t"
104 : : "a" (val));
105}
106
107extern inline void set_ptevaddr_register (unsigned long val)
108{
109 __asm__ __volatile__(" wsr %0, "__stringify(PTEVADDR)"; isync\n"
110 : : "a" (val));
111}
112
113extern inline unsigned long read_ptevaddr_register (void)
114{
115 unsigned long tmp;
116 __asm__ __volatile__("rsr %0, "__stringify(PTEVADDR)"\n\t" : "=a" (tmp));
117 return tmp;
118}
119
120extern inline void write_dtlb_entry (pte_t entry, int way)
121{
122 __asm__ __volatile__("wdtlb %1, %0; dsync\n\t"
123 : : "r" (way), "r" (entry) );
124}
125
126extern inline void write_itlb_entry (pte_t entry, int way)
127{
128 __asm__ __volatile__("witlb %1, %0; isync\n\t"
129 : : "r" (way), "r" (entry) );
130}
131
132extern inline void invalidate_page_directory (void)
133{
134 invalidate_dtlb_entry (DTLB_WAY_PGTABLE);
135}
136
137extern inline void invalidate_itlb_mapping (unsigned address)
138{
139 unsigned long tlb_entry;
140 while ((tlb_entry = itlb_probe (address)) & ITLB_PROBE_SUCCESS)
141 invalidate_itlb_entry (tlb_entry);
142}
143
144extern inline void invalidate_dtlb_mapping (unsigned address)
145{
146 unsigned long tlb_entry;
147 while ((tlb_entry = dtlb_probe (address)) & DTLB_PROBE_SUCCESS)
148 invalidate_dtlb_entry (tlb_entry);
149}
150
151#define check_pgt_cache() do { } while (0)
152
153
154#ifdef DEBUG_TLB
155
156/* DO NOT USE THESE FUNCTIONS. These instructions aren't part of the Xtensa
157 * ISA and exist only for test purposes..
158 * You may find it helpful for MMU debugging, however.
159 *
160 * 'at' is the unmodified input register
161 * 'as' is the output register, as follows (specific to the Linux config):
162 *
163 * as[31..12] contain the virtual address
164 * as[11..08] are meaningless
165 * as[07..00] contain the asid
166 */
167
168extern inline unsigned long read_dtlb_virtual (int way)
169{
170 unsigned long tmp;
171 __asm__ __volatile__("rdtlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way));
172 return tmp;
173}
174
175extern inline unsigned long read_dtlb_translation (int way)
176{
177 unsigned long tmp;
178 __asm__ __volatile__("rdtlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way));
179 return tmp;
180}
181
182extern inline unsigned long read_itlb_virtual (int way)
183{
184 unsigned long tmp;
185 __asm__ __volatile__("ritlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way));
186 return tmp;
187}
188
189extern inline unsigned long read_itlb_translation (int way)
190{
191 unsigned long tmp;
192 __asm__ __volatile__("ritlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way));
193 return tmp;
194}
195
196#endif /* DEBUG_TLB */
197
198
199#endif /* __KERNEL__ */
200#endif /* _XTENSA_PGALLOC_H */
diff --git a/include/asm-xtensa/topology.h b/include/asm-xtensa/topology.h
new file mode 100644
index 0000000000..7309e38a0c
--- /dev/null
+++ b/include/asm-xtensa/topology.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/topology.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_TOPOLOGY_H
12#define _XTENSA_TOPOLOGY_H
13
14#include <asm-generic/topology.h>
15
16#endif /* _XTENSA_TOPOLOGY_H */
diff --git a/include/asm-xtensa/types.h b/include/asm-xtensa/types.h
new file mode 100644
index 0000000000..ebac004698
--- /dev/null
+++ b/include/asm-xtensa/types.h
@@ -0,0 +1,66 @@
1/*
2 * include/asm-xtensa/types.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_TYPES_H
12#define _XTENSA_TYPES_H
13
14#ifndef __ASSEMBLY__
15
16typedef unsigned short umode_t;
17
18/*
19 * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
20 * header files exported to user space
21 */
22
23typedef __signed__ char __s8;
24typedef unsigned char __u8;
25
26typedef __signed__ short __s16;
27typedef unsigned short __u16;
28
29typedef __signed__ int __s32;
30typedef unsigned int __u32;
31
32#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
33typedef __signed__ long long __s64;
34typedef unsigned long long __u64;
35#endif
36
37/*
38 * These aren't exported outside the kernel to avoid name space clashes
39 */
40#ifdef __KERNEL__
41
42typedef __signed__ char s8;
43typedef unsigned char u8;
44
45typedef __signed__ short s16;
46typedef unsigned short u16;
47
48typedef __signed__ int s32;
49typedef unsigned int u32;
50
51typedef __signed__ long long s64;
52typedef unsigned long long u64;
53
54
55#define BITS_PER_LONG 32
56
57/* Dma addresses are 32-bits wide. */
58
59typedef u32 dma_addr_t;
60
61typedef unsigned int kmem_bufctl_t;
62
63#endif /* __KERNEL__ */
64#endif
65
66#endif /* _XTENSA_TYPES_H */
diff --git a/include/asm-xtensa/uaccess.h b/include/asm-xtensa/uaccess.h
new file mode 100644
index 0000000000..35576b25c7
--- /dev/null
+++ b/include/asm-xtensa/uaccess.h
@@ -0,0 +1,532 @@
1/*
2 * include/asm-xtensa/uaccess.h
3 *
4 * User space memory access functions
5 *
6 * These routines provide basic accessing functions to the user memory
7 * space for the kernel. This header file provides fuctions such as:
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 *
13 * Copyright (C) 2001 - 2005 Tensilica Inc.
14 */
15
16#ifndef _XTENSA_UACCESS_H
17#define _XTENSA_UACCESS_H
18
19#include <linux/errno.h>
20
21#define VERIFY_READ 0
22#define VERIFY_WRITE 1
23
24#ifdef __ASSEMBLY__
25
26#define _ASMLANGUAGE
27#include <asm/current.h>
28#include <asm/offsets.h>
29#include <asm/processor.h>
30
31/*
32 * These assembly macros mirror the C macros that follow below. They
33 * should always have identical functionality. See
34 * arch/xtensa/kernel/sys.S for usage.
35 */
36
37#define KERNEL_DS 0
38#define USER_DS 1
39
40#define get_ds (KERNEL_DS)
41
42/*
43 * get_fs reads current->thread.current_ds into a register.
44 * On Entry:
45 * <ad> anything
46 * <sp> stack
47 * On Exit:
48 * <ad> contains current->thread.current_ds
49 */
50 .macro get_fs ad, sp
51 GET_CURRENT(\ad,\sp)
52 l32i \ad, \ad, THREAD_CURRENT_DS
53 .endm
54
55/*
56 * set_fs sets current->thread.current_ds to some value.
57 * On Entry:
58 * <at> anything (temp register)
59 * <av> value to write
60 * <sp> stack
61 * On Exit:
62 * <at> destroyed (actually, current)
63 * <av> preserved, value to write
64 */
65 .macro set_fs at, av, sp
66 GET_CURRENT(\at,\sp)
67 s32i \av, \at, THREAD_CURRENT_DS
68 .endm
69
70/*
71 * kernel_ok determines whether we should bypass addr/size checking.
72 * See the equivalent C-macro version below for clarity.
73 * On success, kernel_ok branches to a label indicated by parameter
74 * <success>. This implies that the macro falls through to the next
75 * insruction on an error.
76 *
77 * Note that while this macro can be used independently, we designed
78 * in for optimal use in the access_ok macro below (i.e., we fall
79 * through on error).
80 *
81 * On Entry:
82 * <at> anything (temp register)
83 * <success> label to branch to on success; implies
84 * fall-through macro on error
85 * <sp> stack pointer
86 * On Exit:
87 * <at> destroyed (actually, current->thread.current_ds)
88 */
89
90#if ((KERNEL_DS != 0) || (USER_DS == 0))
91# error Assembly macro kernel_ok fails
92#endif
93 .macro kernel_ok at, sp, success
94 get_fs \at, \sp
95 beqz \at, \success
96 .endm
97
98/*
99 * user_ok determines whether the access to user-space memory is allowed.
100 * See the equivalent C-macro version below for clarity.
101 *
102 * On error, user_ok branches to a label indicated by parameter
103 * <error>. This implies that the macro falls through to the next
104 * instruction on success.
105 *
106 * Note that while this macro can be used independently, we designed
107 * in for optimal use in the access_ok macro below (i.e., we fall
108 * through on success).
109 *
110 * On Entry:
111 * <aa> register containing memory address
112 * <as> register containing memory size
113 * <at> temp register
114 * <error> label to branch to on error; implies fall-through
115 * macro on success
116 * On Exit:
117 * <aa> preserved
118 * <as> preserved
119 * <at> destroyed (actually, (TASK_SIZE + 1 - size))
120 */
121 .macro user_ok aa, as, at, error
122 movi \at, (TASK_SIZE+1)
123 bgeu \as, \at, \error
124 sub \at, \at, \as
125 bgeu \aa, \at, \error
126 .endm
127
128/*
129 * access_ok determines whether a memory access is allowed. See the
130 * equivalent C-macro version below for clarity.
131 *
132 * On error, access_ok branches to a label indicated by parameter
133 * <error>. This implies that the macro falls through to the next
134 * instruction on success.
135 *
136 * Note that we assume success is the common case, and we optimize the
137 * branch fall-through case on success.
138 *
139 * On Entry:
140 * <aa> register containing memory address
141 * <as> register containing memory size
142 * <at> temp register
143 * <sp>
144 * <error> label to branch to on error; implies fall-through
145 * macro on success
146 * On Exit:
147 * <aa> preserved
148 * <as> preserved
149 * <at> destroyed
150 */
151 .macro access_ok aa, as, at, sp, error
152 kernel_ok \at, \sp, .Laccess_ok_\@
153 user_ok \aa, \as, \at, \error
154.Laccess_ok_\@:
155 .endm
156
157/*
158 * verify_area determines whether a memory access is allowed. It's
159 * mostly an unnecessary wrapper for access_ok, but we provide it as a
160 * duplicate of the verify_area() C inline function below. See the
161 * equivalent C version below for clarity.
162 *
163 * On error, verify_area branches to a label indicated by parameter
164 * <error>. This implies that the macro falls through to the next
165 * instruction on success.
166 *
167 * Note that we assume success is the common case, and we optimize the
168 * branch fall-through case on success.
169 *
170 * On Entry:
171 * <aa> register containing memory address
172 * <as> register containing memory size
173 * <at> temp register
174 * <error> label to branch to on error; implies fall-through
175 * macro on success
176 * On Exit:
177 * <aa> preserved
178 * <as> preserved
179 * <at> destroyed
180 */
181 .macro verify_area aa, as, at, sp, error
182 access_ok \at, \aa, \as, \sp, \error
183 .endm
184
185
186#else /* __ASSEMBLY__ not defined */
187
188#include <linux/sched.h>
189#include <asm/types.h>
190
191/*
192 * The fs value determines whether argument validity checking should
193 * be performed or not. If get_fs() == USER_DS, checking is
194 * performed, with get_fs() == KERNEL_DS, checking is bypassed.
195 *
196 * For historical reasons (Data Segment Register?), these macros are
197 * grossly misnamed.
198 */
199
200#define KERNEL_DS ((mm_segment_t) { 0 })
201#define USER_DS ((mm_segment_t) { 1 })
202
203#define get_ds() (KERNEL_DS)
204#define get_fs() (current->thread.current_ds)
205#define set_fs(val) (current->thread.current_ds = (val))
206
207#define segment_eq(a,b) ((a).seg == (b).seg)
208
209#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
210#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
211#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
212#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
213
214extern inline int verify_area(int type, const void * addr, unsigned long size)
215{
216 return access_ok(type,addr,size) ? 0 : -EFAULT;
217}
218
219/*
220 * These are the main single-value transfer routines. They
221 * automatically use the right size if we just have the right pointer
222 * type.
223 *
224 * This gets kind of ugly. We want to return _two_ values in
225 * "get_user()" and yet we don't want to do any pointers, because that
226 * is too much of a performance impact. Thus we have a few rather ugly
227 * macros here, and hide all the uglyness from the user.
228 *
229 * Careful to not
230 * (a) re-use the arguments for side effects (sizeof is ok)
231 * (b) require any knowledge of processes at this stage
232 */
233#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr)))
234#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)))
235
236/*
237 * The "__xxx" versions of the user access functions are versions that
238 * do not verify the address space, that must have been done previously
239 * with a separate "access_ok()" call (this is used when we do multiple
240 * accesses to the same area of user memory).
241 */
242#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
243#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
244
245
246extern long __put_user_bad(void);
247
248#define __put_user_nocheck(x,ptr,size) \
249({ \
250 long __pu_err; \
251 __put_user_size((x),(ptr),(size),__pu_err); \
252 __pu_err; \
253})
254
255#define __put_user_check(x,ptr,size) \
256({ \
257 long __pu_err = -EFAULT; \
258 __typeof__(*(ptr)) *__pu_addr = (ptr); \
259 if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
260 __put_user_size((x),__pu_addr,(size),__pu_err); \
261 __pu_err; \
262})
263
264#define __put_user_size(x,ptr,size,retval) \
265do { \
266 retval = 0; \
267 switch (size) { \
268 case 1: __put_user_asm(x,ptr,retval,1,"s8i"); break; \
269 case 2: __put_user_asm(x,ptr,retval,2,"s16i"); break; \
270 case 4: __put_user_asm(x,ptr,retval,4,"s32i"); break; \
271 case 8: { \
272 __typeof__(*ptr) __v64 = x; \
273 retval = __copy_to_user(ptr,&__v64,8); \
274 break; \
275 } \
276 default: __put_user_bad(); \
277 } \
278} while (0)
279
280
281/*
282 * Consider a case of a user single load/store would cause both an
283 * unaligned exception and an MMU-related exception (unaligned
284 * exceptions happen first):
285 *
286 * User code passes a bad variable ptr to a system call.
287 * Kernel tries to access the variable.
288 * Unaligned exception occurs.
289 * Unaligned exception handler tries to make aligned accesses.
290 * Double exception occurs for MMU-related cause (e.g., page not mapped).
291 * do_page_fault() thinks the fault address belongs to the kernel, not the
292 * user, and panics.
293 *
294 * The kernel currently prohibits user unaligned accesses. We use the
295 * __check_align_* macros to check for unaligned addresses before
296 * accessing user space so we don't crash the kernel. Both
297 * __put_user_asm and __get_user_asm use these alignment macros, so
298 * macro-specific labels such as 0f, 1f, %0, %2, and %3 must stay in
299 * sync.
300 */
301
302#define __check_align_1 ""
303
304#define __check_align_2 \
305 " _bbci.l %2, 0, 1f \n" \
306 " movi %0, %3 \n" \
307 " _j 2f \n"
308
309#define __check_align_4 \
310 " _bbsi.l %2, 0, 0f \n" \
311 " _bbci.l %2, 1, 1f \n" \
312 "0: movi %0, %3 \n" \
313 " _j 2f \n"
314
315
316/*
317 * We don't tell gcc that we are accessing memory, but this is OK
318 * because we do not write to any memory gcc knows about, so there
319 * are no aliasing issues.
320 *
321 * WARNING: If you modify this macro at all, verify that the
322 * __check_align_* macros still work.
323 */
324#define __put_user_asm(x, addr, err, align, insn) \
325 __asm__ __volatile__( \
326 __check_align_##align \
327 "1: "insn" %1, %2, 0 \n" \
328 "2: \n" \
329 " .section .fixup,\"ax\" \n" \
330 " .align 4 \n" \
331 "4: \n" \
332 " .long 2b \n" \
333 "5: \n" \
334 " l32r %2, 4b \n" \
335 " movi %0, %3 \n" \
336 " jx %2 \n" \
337 " .previous \n" \
338 " .section __ex_table,\"a\" \n" \
339 " .long 1b, 5b \n" \
340 " .previous" \
341 :"=r" (err) \
342 :"r" ((int)(x)), "r" (addr), "i" (-EFAULT), "0" (err))
343
344#define __get_user_nocheck(x,ptr,size) \
345({ \
346 long __gu_err, __gu_val; \
347 __get_user_size(__gu_val,(ptr),(size),__gu_err); \
348 (x) = (__typeof__(*(ptr)))__gu_val; \
349 __gu_err; \
350})
351
352#define __get_user_check(x,ptr,size) \
353({ \
354 long __gu_err = -EFAULT, __gu_val = 0; \
355 const __typeof__(*(ptr)) *__gu_addr = (ptr); \
356 if (access_ok(VERIFY_READ,__gu_addr,size)) \
357 __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
358 (x) = (__typeof__(*(ptr)))__gu_val; \
359 __gu_err; \
360})
361
362extern long __get_user_bad(void);
363
364#define __get_user_size(x,ptr,size,retval) \
365do { \
366 retval = 0; \
367 switch (size) { \
368 case 1: __get_user_asm(x,ptr,retval,1,"l8ui"); break; \
369 case 2: __get_user_asm(x,ptr,retval,2,"l16ui"); break; \
370 case 4: __get_user_asm(x,ptr,retval,4,"l32i"); break; \
371 case 8: retval = __copy_from_user(&x,ptr,8); break; \
372 default: (x) = __get_user_bad(); \
373 } \
374} while (0)
375
376
377/*
378 * WARNING: If you modify this macro at all, verify that the
379 * __check_align_* macros still work.
380 */
381#define __get_user_asm(x, addr, err, align, insn) \
382 __asm__ __volatile__( \
383 __check_align_##align \
384 "1: "insn" %1, %2, 0 \n" \
385 "2: \n" \
386 " .section .fixup,\"ax\" \n" \
387 " .align 4 \n" \
388 "4: \n" \
389 " .long 2b \n" \
390 "5: \n" \
391 " l32r %2, 4b \n" \
392 " movi %1, 0 \n" \
393 " movi %0, %3 \n" \
394 " jx %2 \n" \
395 " .previous \n" \
396 " .section __ex_table,\"a\" \n" \
397 " .long 1b, 5b \n" \
398 " .previous" \
399 :"=r" (err), "=r" (x) \
400 :"r" (addr), "i" (-EFAULT), "0" (err))
401
402
403/*
404 * Copy to/from user space
405 */
406
407/*
408 * We use a generic, arbitrary-sized copy subroutine. The Xtensa
409 * architecture would cause heavy code bloat if we tried to inline
410 * these functions and provide __constant_copy_* equivalents like the
411 * i386 versions. __xtensa_copy_user is quite efficient. See the
412 * .fixup section of __xtensa_copy_user for a discussion on the
413 * X_zeroing equivalents for Xtensa.
414 */
415
416extern unsigned __xtensa_copy_user(void *to, const void *from, unsigned n);
417#define __copy_user(to,from,size) __xtensa_copy_user(to,from,size)
418
419
420static inline unsigned long
421__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
422{
423 return __copy_user(to,from,n);
424}
425
426static inline unsigned long
427__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
428{
429 return __copy_user(to,from,n);
430}
431
432static inline unsigned long
433__generic_copy_to_user(void *to, const void *from, unsigned long n)
434{
435 prefetch(from);
436 if (access_ok(VERIFY_WRITE, to, n))
437 return __copy_user(to,from,n);
438 return n;
439}
440
441static inline unsigned long
442__generic_copy_from_user(void *to, const void *from, unsigned long n)
443{
444 prefetchw(to);
445 if (access_ok(VERIFY_READ, from, n))
446 return __copy_user(to,from,n);
447 else
448 memset(to, 0, n);
449 return n;
450}
451
452#define copy_to_user(to,from,n) __generic_copy_to_user((to),(from),(n))
453#define copy_from_user(to,from,n) __generic_copy_from_user((to),(from),(n))
454#define __copy_to_user(to,from,n) __generic_copy_to_user_nocheck((to),(from),(n))
455#define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
456#define __copy_to_user_inatomic __copy_to_user
457#define __copy_from_user_inatomic __copy_from_user
458
459
460/*
461 * We need to return the number of bytes not cleared. Our memset()
462 * returns zero if a problem occurs while accessing user-space memory.
463 * In that event, return no memory cleared. Otherwise, zero for
464 * success.
465 */
466
467extern inline unsigned long
468__xtensa_clear_user(void *addr, unsigned long size)
469{
470 if ( ! memset(addr, 0, size) )
471 return size;
472 return 0;
473}
474
475extern inline unsigned long
476clear_user(void *addr, unsigned long size)
477{
478 if (access_ok(VERIFY_WRITE, addr, size))
479 return __xtensa_clear_user(addr, size);
480 return size ? -EFAULT : 0;
481}
482
483#define __clear_user __xtensa_clear_user
484
485
486extern long __strncpy_user(char *, const char *, long);
487#define __strncpy_from_user __strncpy_user
488
489extern inline long
490strncpy_from_user(char *dst, const char *src, long count)
491{
492 if (access_ok(VERIFY_READ, src, 1))
493 return __strncpy_from_user(dst, src, count);
494 return -EFAULT;
495}
496
497
498#define strlen_user(str) strnlen_user((str), TASK_SIZE - 1)
499
500/*
501 * Return the size of a string (including the ending 0!)
502 */
503extern long __strnlen_user(const char *, long);
504
505extern inline long strnlen_user(const char *str, long len)
506{
507 unsigned long top = __kernel_ok ? ~0UL : TASK_SIZE - 1;
508
509 if ((unsigned long)str > top)
510 return 0;
511 return __strnlen_user(str, len);
512}
513
514
515struct exception_table_entry
516{
517 unsigned long insn, fixup;
518};
519
520/* Returns 0 if exception not found and fixup.unit otherwise. */
521
522extern unsigned long search_exception_table(unsigned long addr);
523extern void sort_exception_table(void);
524
525/* Returns the new pc */
526#define fixup_exception(map_reg, fixup_unit, pc) \
527({ \
528 fixup_unit; \
529})
530
531#endif /* __ASSEMBLY__ */
532#endif /* _XTENSA_UACCESS_H */
diff --git a/include/asm-xtensa/ucontext.h b/include/asm-xtensa/ucontext.h
new file mode 100644
index 0000000000..94c94ed3e0
--- /dev/null
+++ b/include/asm-xtensa/ucontext.h
@@ -0,0 +1,22 @@
1/*
2 * include/asm-xtensa/ucontext.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_UCONTEXT_H
12#define _XTENSA_UCONTEXT_H
13
14struct ucontext {
15 unsigned long uc_flags;
16 struct ucontext *uc_link;
17 stack_t uc_stack;
18 struct sigcontext uc_mcontext;
19 sigset_t uc_sigmask; /* mask last for extensibility */
20};
21
22#endif /* _XTENSA_UCONTEXT_H */
diff --git a/include/asm-xtensa/unaligned.h b/include/asm-xtensa/unaligned.h
new file mode 100644
index 0000000000..28220890d0
--- /dev/null
+++ b/include/asm-xtensa/unaligned.h
@@ -0,0 +1,28 @@
1/*
2 * include/asm-xtensa/unaligned.h
3 *
4 * Xtensa doesn't handle unaligned accesses efficiently.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_UNALIGNED_H
14#define _XTENSA_UNALIGNED_H
15
16#include <linux/string.h>
17
18/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
19
20#define get_unaligned(ptr) \
21 ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
22
23#define put_unaligned(val, ptr) \
24 ({ __typeof__(*(ptr)) __tmp = (val); \
25 memmove((ptr), &__tmp, sizeof(*(ptr))); \
26 (void)0; })
27
28#endif /* _XTENSA_UNALIGNED_H */
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h
new file mode 100644
index 0000000000..64c64dd83b
--- /dev/null
+++ b/include/asm-xtensa/unistd.h
@@ -0,0 +1,537 @@
1/*
2 * include/asm-xtensa/unistd.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_UNISTD_H
12#define _XTENSA_UNISTD_H
13
14#include <linux/linkage.h>
15
16//#define __NR_setup 0 /* used only by init, to get system going */
17#define __NR_spill 0
18#define __NR_exit 1
19#define __NR_fork 2
20#define __NR_read 3
21#define __NR_write 4
22#define __NR_open 5
23#define __NR_close 6
24#define __NR_waitpid 7
25#define __NR_creat 8
26#define __NR_link 9
27#define __NR_unlink 10
28#define __NR_execve 11
29#define __NR_chdir 12
30#define __NR_time 13
31#define __NR_mknod 14
32#define __NR_chmod 15
33#define __NR_lchown 16
34#define __NR_break 17
35#define __NR_oldstat 18
36#define __NR_lseek 19
37#define __NR_getpid 20
38#define __NR_mount 21
39#define __NR_oldumount 22
40#define __NR_setuid 23
41#define __NR_getuid 24
42#define __NR_stime 25
43#define __NR_ptrace 26
44#define __NR_alarm 27
45#define __NR_oldfstat 28
46#define __NR_pause 29
47#define __NR_utime 30
48#define __NR_stty 31
49#define __NR_gtty 32
50#define __NR_access 33
51#define __NR_nice 34
52#define __NR_ftime 35
53#define __NR_sync 36
54#define __NR_kill 37
55#define __NR_rename 38
56#define __NR_mkdir 39
57#define __NR_rmdir 40
58#define __NR_dup 41
59#define __NR_pipe 42
60#define __NR_times 43
61#define __NR_prof 44
62#define __NR_brk 45
63#define __NR_setgid 46
64#define __NR_getgid 47
65#define __NR_signal 48
66#define __NR_geteuid 49
67#define __NR_getegid 50
68#define __NR_acct 51
69#define __NR_umount 52
70#define __NR_lock 53
71#define __NR_ioctl 54
72#define __NR_fcntl 55
73#define __NR_mpx 56
74#define __NR_setpgid 57
75#define __NR_ulimit 58
76#define __NR_oldolduname 59
77#define __NR_umask 60
78#define __NR_chroot 61
79#define __NR_ustat 62
80#define __NR_dup2 63
81#define __NR_getppid 64
82#define __NR_getpgrp 65
83#define __NR_setsid 66
84#define __NR_sigaction 67
85#define __NR_sgetmask 68
86#define __NR_ssetmask 69
87#define __NR_setreuid 70
88#define __NR_setregid 71
89#define __NR_sigsuspend 72
90#define __NR_sigpending 73
91#define __NR_sethostname 74
92#define __NR_setrlimit 75
93#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
94#define __NR_getrusage 77
95#define __NR_gettimeofday 78
96#define __NR_settimeofday 79
97#define __NR_getgroups 80
98#define __NR_setgroups 81
99#define __NR_select 82
100#define __NR_symlink 83
101#define __NR_oldlstat 84
102#define __NR_readlink 85
103#define __NR_uselib 86
104#define __NR_swapon 87
105#define __NR_reboot 88
106#define __NR_readdir 89
107#define __NR_mmap 90
108#define __NR_munmap 91
109#define __NR_truncate 92
110#define __NR_ftruncate 93
111#define __NR_fchmod 94
112#define __NR_fchown 95
113#define __NR_getpriority 96
114#define __NR_setpriority 97
115#define __NR_profil 98
116#define __NR_statfs 99
117#define __NR_fstatfs 100
118#define __NR_ioperm 101
119#define __NR_socketcall 102
120#define __NR_syslog 103
121#define __NR_setitimer 104
122#define __NR_getitimer 105
123#define __NR_stat 106
124#define __NR_lstat 107
125#define __NR_fstat 108
126#define __NR_olduname 109
127#define __NR_iopl 110
128#define __NR_vhangup 111
129#define __NR_idle 112
130#define __NR_vm86 113
131#define __NR_wait4 114
132#define __NR_swapoff 115
133#define __NR_sysinfo 116
134#define __NR_ipc 117
135#define __NR_fsync 118
136#define __NR_sigreturn 119
137#define __NR_clone 120
138#define __NR_setdomainname 121
139#define __NR_uname 122
140#define __NR_modify_ldt 123
141#define __NR_adjtimex 124
142#define __NR_mprotect 125
143#define __NR_sigprocmask 126
144#define __NR_create_module 127
145#define __NR_init_module 128
146#define __NR_delete_module 129
147#define __NR_get_kernel_syms 130
148#define __NR_quotactl 131
149#define __NR_getpgid 132
150#define __NR_fchdir 133
151#define __NR_bdflush 134
152#define __NR_sysfs 135
153#define __NR_personality 136
154#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
155#define __NR_setfsuid 138
156#define __NR_setfsgid 139
157#define __NR__llseek 140
158#define __NR_getdents 141
159#define __NR__newselect 142
160#define __NR_flock 143
161#define __NR_msync 144
162#define __NR_readv 145
163#define __NR_writev 146
164#define __NR_cacheflush 147
165#define __NR_cachectl 148
166#define __NR_sysxtensa 149
167#define __NR_sysdummy 150
168#define __NR_getsid 151
169#define __NR_fdatasync 152
170#define __NR__sysctl 153
171#define __NR_mlock 154
172#define __NR_munlock 155
173#define __NR_mlockall 156
174#define __NR_munlockall 157
175#define __NR_sched_setparam 158
176#define __NR_sched_getparam 159
177#define __NR_sched_setscheduler 160
178#define __NR_sched_getscheduler 161
179#define __NR_sched_yield 162
180#define __NR_sched_get_priority_max 163
181#define __NR_sched_get_priority_min 164
182#define __NR_sched_rr_get_interval 165
183#define __NR_nanosleep 166
184#define __NR_mremap 167
185#define __NR_accept 168
186#define __NR_bind 169
187#define __NR_connect 170
188#define __NR_getpeername 171
189#define __NR_getsockname 172
190#define __NR_getsockopt 173
191#define __NR_listen 174
192#define __NR_recv 175
193#define __NR_recvfrom 176
194#define __NR_recvmsg 177
195#define __NR_send 178
196#define __NR_sendmsg 179
197#define __NR_sendto 180
198#define __NR_setsockopt 181
199#define __NR_shutdown 182
200#define __NR_socket 183
201#define __NR_socketpair 184
202#define __NR_setresuid 185
203#define __NR_getresuid 186
204#define __NR_query_module 187
205#define __NR_poll 188
206#define __NR_nfsservctl 189
207#define __NR_setresgid 190
208#define __NR_getresgid 191
209#define __NR_prctl 192
210#define __NR_rt_sigreturn 193
211#define __NR_rt_sigaction 194
212#define __NR_rt_sigprocmask 195
213#define __NR_rt_sigpending 196
214#define __NR_rt_sigtimedwait 197
215#define __NR_rt_sigqueueinfo 198
216#define __NR_rt_sigsuspend 199
217#define __NR_pread 200
218#define __NR_pwrite 201
219#define __NR_chown 202
220#define __NR_getcwd 203
221#define __NR_capget 204
222#define __NR_capset 205
223#define __NR_sigaltstack 206
224#define __NR_sendfile 207
225#define __NR_streams1 208 /* some people actually want it */
226#define __NR_streams2 209 /* some people actually want it */
227#define __NR_mmap2 210
228#define __NR_truncate64 211
229#define __NR_ftruncate64 212
230#define __NR_stat64 213
231#define __NR_lstat64 214
232#define __NR_fstat64 215
233#define __NR_pivot_root 216
234#define __NR_mincore 217
235#define __NR_madvise 218
236#define __NR_getdents64 219
237#define __NR_vfork 220
238
239/* Keep this last; should always equal the last valid call number. */
240#define __NR_Linux_syscalls 220
241
242/* user-visible error numbers are in the range -1 - -125: see
243 * <asm-xtensa/errno.h> */
244
245#define SYSXTENSA_RESERVED 0 /* don't use this */
246#define SYSXTENSA_ATOMIC_SET 1 /* set variable */
247#define SYSXTENSA_ATOMIC_EXG_ADD 2 /* exchange memory and add */
248#define SYSXTENSA_ATOMIC_ADD 3 /* add to memory */
249#define SYSXTENSA_ATOMIC_CMP_SWP 4 /* compare and swap */
250
251#define SYSXTENSA_COUNT 5 /* count of syscall0 functions*/
252
253#ifdef __KERNEL__
254#define __syscall_return(type, res) return ((type)(res))
255#else
256#define __syscall_return(type, res) \
257do { \
258 if ((unsigned long)(res) >= (unsigned long)(-125)) { \
259 /* Avoid using "res" which is declared to be in register r2; \
260 * errno might expand to a function call and clobber it. */ \
261 int __err = -(res); \
262 errno = __err; \
263 res = -1; \
264 } \
265 return (type) (res); \
266} while (0)
267#endif
268
269
270/* Tensilica's xt-xcc compiler is much more agressive at code
271 * optimization than gcc. Multiple __asm__ statements are
272 * insufficient for xt-xcc because subsequent optimization passes
273 * (beyond the front-end that knows of __asm__ statements and other
274 * such GNU Extensions to C) can modify the register selection for
275 * containment of C variables.
276 *
277 * xt-xcc cannot modify the contents of a single __asm__ statement, so
278 * we create single-asm versions of the syscall macros that are
279 * suitable and optimal for both xt-xcc and gcc.
280 *
281 * Linux takes system-call arguments in registers. The following
282 * design is optimized for user-land apps (e.g., glibc) which
283 * typically have a function wrapper around the "syscall" assembly
284 * instruction. It satisfies the Xtensa ABI while minizing argument
285 * shifting.
286 *
287 * The Xtensa ABI and software conventions require the system-call
288 * number in a2. If an argument exists in a2, we move it to the next
289 * available register. Note that for improved efficiency, we do NOT
290 * shift all parameters down one register to maintain the original
291 * order.
292 *
293 * At best case (zero arguments), we just write the syscall number to
294 * a2. At worst case (1 to 6 arguments), we move the argument in a2
295 * to the next available register, then write the syscall number to
296 * a2.
297 *
298 * For clarity, the following truth table enumerates all possibilities.
299 *
300 * arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5
301 * --------- -------------- ----------------------------------
302 * 0 a2
303 * 1 a2 a3
304 * 2 a2 a4, a3
305 * 3 a2 a5, a3, a4
306 * 4 a2 a6, a3, a4, a5
307 * 5 a2 a7, a3, a4, a5, a6
308 * 6 a2 a8, a3, a4, a5, a6, a7
309 */
310
311#define _syscall0(type,name) \
312type name(void) \
313{ \
314long __res; \
315__asm__ __volatile__ ( \
316 " movi a2, %1 \n" \
317 " syscall \n" \
318 " mov %0, a2 \n" \
319 : "=a" (__res) \
320 : "i" (__NR_##name) \
321 : "a2" \
322 ); \
323__syscall_return(type,__res); \
324}
325
326#define _syscall1(type,name,type0,arg0) \
327type name(type0 arg0) \
328{ \
329long __res; \
330__asm__ __volatile__ ( \
331 " mov a3, %2 \n" \
332 " movi a2, %1 \n" \
333 " syscall \n" \
334 " mov %0, a2 \n" \
335 : "=a" (__res) \
336 : "i" (__NR_##name), "a" (arg0) \
337 : "a2", "a3" \
338 ); \
339__syscall_return(type,__res); \
340}
341
342#define _syscall2(type,name,type0,arg0,type1,arg1) \
343type name(type0 arg0,type1 arg1) \
344{ \
345long __res; \
346__asm__ __volatile__ ( \
347 " mov a4, %2 \n" \
348 " mov a3, %3 \n" \
349 " movi a2, %1 \n" \
350 " syscall \n" \
351 " mov %0, a2 \n" \
352 : "=a" (__res) \
353 : "i" (__NR_##name), "a" (arg0), "a" (arg1) \
354 : "a2", "a3", "a4" \
355 ); \
356__syscall_return(type,__res); \
357}
358
359#define _syscall3(type,name,type0,arg0,type1,arg1,type2,arg2) \
360type name(type0 arg0,type1 arg1,type2 arg2) \
361{ \
362long __res; \
363__asm__ __volatile__ ( \
364 " mov a5, %2 \n" \
365 " mov a4, %4 \n" \
366 " mov a3, %3 \n" \
367 " movi a2, %1 \n" \
368 " syscall \n" \
369 " mov %0, a2 \n" \
370 : "=a" (__res) \
371 : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2) \
372 : "a2", "a3", "a4", "a5" \
373 ); \
374__syscall_return(type,__res); \
375}
376
377#define _syscall4(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3) \
378type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3) \
379{ \
380long __res; \
381__asm__ __volatile__ ( \
382 " mov a6, %2 \n" \
383 " mov a5, %5 \n" \
384 " mov a4, %4 \n" \
385 " mov a3, %3 \n" \
386 " movi a2, %1 \n" \
387 " syscall \n" \
388 " mov %0, a2 \n" \
389 : "=a" (__res) \
390 : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), "a" (arg3) \
391 : "a2", "a3", "a4", "a5", "a6" \
392 ); \
393__syscall_return(type,__res); \
394}
395
396/* Note that we save and restore the a7 frame pointer.
397 * Including a7 in the clobber list doesn't do what you'd expect.
398 */
399#define _syscall5(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
400type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
401{ \
402long __res; \
403__asm__ __volatile__ ( \
404 " mov a9, a7 \n" \
405 " mov a7, %2 \n" \
406 " mov a6, %6 \n" \
407 " mov a5, %5 \n" \
408 " mov a4, %4 \n" \
409 " mov a3, %3 \n" \
410 " movi a2, %1 \n" \
411 " syscall \n" \
412 " mov a7, a9 \n" \
413 " mov %0, a2 \n" \
414 : "=a" (__res) \
415 : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \
416 "a" (arg3), "a" (arg4) \
417 : "a2", "a3", "a4", "a5", "a6", "a9" \
418 ); \
419__syscall_return(type,__res); \
420}
421
422/* Note that we save and restore the a7 frame pointer.
423 * Including a7 in the clobber list doesn't do what you'd expect.
424 */
425#define _syscall6(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
426type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
427{ \
428long __res; \
429__asm__ __volatile__ ( \
430 " mov a9, a7 \n" \
431 " mov a8, %2 \n" \
432 " mov a7, %7 \n" \
433 " mov a6, %6 \n" \
434 " mov a5, %5 \n" \
435 " mov a4, %4 \n" \
436 " mov a3, %3 \n" \
437 " movi a2, %1 \n" \
438 " syscall \n" \
439 " mov a7, a9 \n" \
440 " mov %0, a2 \n" \
441 : "=a" (__res) \
442 : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \
443 "a" (arg3), "a" (arg4), "a" (arg5) \
444 : "a2", "a3", "a4", "a5", "a6", "a8", "a9" \
445 ); \
446__syscall_return(type,__res); \
447}
448
449
450#ifdef __KERNEL_SYSCALLS__
451
452#include <linux/compiler.h>
453#include <linux/types.h>
454#include <linux/syscalls.h>
455
456/*
457 * we need this inline - forking from kernel space will result
458 * in NO COPY ON WRITE (!!!), until an execve is executed. This
459 * is no problem, but for the stack. This is handled by not letting
460 * main() use the stack at all after fork(). Thus, no function
461 * calls - which means inline code for fork too, as otherwise we
462 * would use the stack upon exit from 'fork()'.
463 *
464 * Actually only pause and fork are needed inline, so that there
465 * won't be any messing with the stack from main(), but we define
466 * some others too.
467 */
468
469#define __NR__exit __NR_exit
470
471static __inline__ _syscall0(int,pause)
472//static __inline__ _syscall1(int,setup,int,magic) FIXME
473static __inline__ _syscall0(int,sync)
474static __inline__ _syscall0(pid_t,setsid)
475static __inline__ _syscall3(int,write,int,fd,const char *,buf,off_t,count)
476static __inline__ _syscall3(int,read,int,fd,char *,buf,off_t,count)
477static __inline__ _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
478static __inline__ _syscall1(int,dup,int,fd)
479static __inline__ _syscall3(int,execve,const char*,file,char**,argv,char**,envp)
480static __inline__ _syscall3(int,open,const char *,file,int,flag,int,mode)
481static __inline__ _syscall1(int,close,int,fd)
482static __inline__ _syscall1(int,_exit,int,exitcode)
483static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
484static __inline__ _syscall1(int,delete_module,const char *,name)
485
486struct stat;
487static __inline__ _syscall2(int,fstat,int,fd,struct stat *,buf)
488static __inline__ _syscall0(pid_t,getpid)
489static __inline__ _syscall2(int,kill,int,pid,int,sig)
490static __inline__ _syscall2(int,stat,const char *, path,struct stat *,buf)
491static __inline__ _syscall1(int,unlink,char *,pathname)
492
493
494
495extern pid_t waitpid(int, int*, int );
496static __inline__ pid_t wait(int * wait_stat)
497{
498 return waitpid(-1,wait_stat,0);
499}
500#endif
501
502/*
503 * "Conditional" syscalls
504 *
505 * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
506 * but it doesn't work on all toolchains, so we just do it by hand
507 */
508#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
509
510#ifdef __KERNEL__
511#define __ARCH_WANT_IPC_PARSE_VERSION
512#define __ARCH_WANT_OLD_READDIR
513#define __ARCH_WANT_OLD_STAT
514#define __ARCH_WANT_STAT64
515#define __ARCH_WANT_SYS_ALARM
516#define __ARCH_WANT_SYS_GETHOSTNAME
517#define __ARCH_WANT_SYS_PAUSE
518#define __ARCH_WANT_SYS_SGETMASK
519#define __ARCH_WANT_SYS_SIGNAL
520#define __ARCH_WANT_SYS_TIME
521#define __ARCH_WANT_SYS_UTIME
522#define __ARCH_WANT_SYS_WAITPID
523#define __ARCH_WANT_SYS_SOCKETCALL
524#define __ARCH_WANT_SYS_FADVISE64
525#define __ARCH_WANT_SYS_GETPGRP
526#define __ARCH_WANT_SYS_LLSEEK
527#define __ARCH_WANT_SYS_NICE
528#define __ARCH_WANT_SYS_OLD_GETRLIMIT
529#define __ARCH_WANT_SYS_OLDUMOUNT
530#define __ARCH_WANT_SYS_SIGPENDING
531#define __ARCH_WANT_SYS_SIGPROCMASK
532#define __ARCH_WANT_SYS_RT_SIGACTION
533#endif
534
535
536
537#endif /* _XTENSA_UNISTD_H */
diff --git a/include/asm-xtensa/user.h b/include/asm-xtensa/user.h
new file mode 100644
index 0000000000..2c3ed23354
--- /dev/null
+++ b/include/asm-xtensa/user.h
@@ -0,0 +1,20 @@
1/*
2 * include/asm-xtensa/user.h
3 *
4 * Xtensa Processor version.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc.
11 */
12
13#ifndef _XTENSA_USER_H
14#define _XTENSA_USER_H
15
16/* This file usually defines a 'struct user' structure. However, it it only
17 * used for a.out file, which are not supported on Xtensa.
18 */
19
20#endif /* _XTENSA_USER_H */
diff --git a/include/asm-xtensa/vga.h b/include/asm-xtensa/vga.h
new file mode 100644
index 0000000000..23d82f6acb
--- /dev/null
+++ b/include/asm-xtensa/vga.h
@@ -0,0 +1,19 @@
1/*
2 * include/asm-xtensa/vga.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_VGA_H
12#define _XTENSA_VGA_H
13
14#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
15
16#define vga_readb(x) (*(x))
17#define vga_writeb(x,y) (*(y) = (x))
18
19#endif
diff --git a/include/asm-xtensa/xor.h b/include/asm-xtensa/xor.h
new file mode 100644
index 0000000000..e7b1f08399
--- /dev/null
+++ b/include/asm-xtensa/xor.h
@@ -0,0 +1,16 @@
1/*
2 * include/asm-xtensa/xor.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc.
9 */
10
11#ifndef _XTENSA_XOR_H
12#define _XTENSA_XOR_H
13
14#include <asm-generic/xor.h>
15
16#endif
diff --git a/include/asm-xtensa/xtensa/cacheasm.h b/include/asm-xtensa/xtensa/cacheasm.h
new file mode 100644
index 0000000000..0cdbb0bf18
--- /dev/null
+++ b/include/asm-xtensa/xtensa/cacheasm.h
@@ -0,0 +1,708 @@
1#ifndef XTENSA_CACHEASM_H
2#define XTENSA_CACHEASM_H
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * include/asm-xtensa/xtensa/cacheasm.h -- assembler-specific cache
8 * related definitions that depend on CORE configuration.
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file "COPYING" in the main directory of this archive
12 * for more details.
13 *
14 * Copyright (C) 2002 Tensilica Inc.
15 */
16
17
18#include <xtensa/coreasm.h>
19
20
21/*
22 * This header file defines assembler macros of the form:
23 * <x>cache_<func>
24 * where <x> is 'i' or 'd' for instruction and data caches,
25 * and <func> indicates the function of the macro.
26 *
27 * The following functions <func> are defined,
28 * and apply only to the specified cache (I or D):
29 *
30 * reset
31 * Resets the cache.
32 *
33 * sync
34 * Makes sure any previous cache instructions have been completed;
35 * ie. makes sure any previous cache control operations
36 * have had full effect and been synchronized to memory.
37 * Eg. any invalidate completed [so as not to generate a hit],
38 * any writebacks or other pipelined writes written to memory, etc.
39 *
40 * invalidate_line (single cache line)
41 * invalidate_region (specified memory range)
42 * invalidate_all (entire cache)
43 * Invalidates all cache entries that cache
44 * data from the specified memory range.
45 * NOTE: locked entries are not invalidated.
46 *
47 * writeback_line (single cache line)
48 * writeback_region (specified memory range)
49 * writeback_all (entire cache)
50 * Writes back to memory all dirty cache entries
51 * that cache data from the specified memory range,
52 * and marks these entries as clean.
53 * NOTE: on some future implementations, this might
54 * also invalidate.
55 * NOTE: locked entries are written back, but never invalidated.
56 * NOTE: instruction caches never implement writeback.
57 *
58 * writeback_inv_line (single cache line)
59 * writeback_inv_region (specified memory range)
60 * writeback_inv_all (entire cache)
61 * Writes back to memory all dirty cache entries
62 * that cache data from the specified memory range,
63 * and invalidates these entries (including all clean
64 * cache entries that cache data from that range).
65 * NOTE: locked entries are written back but not invalidated.
66 * NOTE: instruction caches never implement writeback.
67 *
68 * lock_line (single cache line)
69 * lock_region (specified memory range)
70 * Prefetch and lock the specified memory range into cache.
71 * NOTE: if any part of the specified memory range cannot
72 * be locked, a ??? exception occurs. These macros don't
73 * do anything special (yet anyway) to handle this situation.
74 *
75 * unlock_line (single cache line)
76 * unlock_region (specified memory range)
77 * unlock_all (entire cache)
78 * Unlock cache entries that cache the specified memory range.
79 * Entries not already locked are unaffected.
80 */
81
82
83
84/*************************** GENERIC -- ALL CACHES ***************************/
85
86
87/*
88 * The following macros assume the following cache size/parameter limits
89 * in the current Xtensa core implementation:
90 * cache size: 1024 bytes minimum
91 * line size: 16 - 64 bytes
92 * way count: 1 - 4
93 *
94 * Minimum entries per way (ie. per associativity) = 1024 / 64 / 4 = 4
95 * Hence the assumption that each loop can execute four cache instructions.
96 *
97 * Correspondingly, the offset range of instructions is assumed able to cover
98 * four lines, ie. offsets {0,1,2,3} * line_size are assumed valid for
99 * both hit and indexed cache instructions. Ie. these offsets are all
100 * valid: 0, 16, 32, 48, 64, 96, 128, 192 (for line sizes 16, 32, 64).
101 * This is true of all original cache instructions
102 * (dhi, ihi, dhwb, dhwbi, dii, iii) which have offsets
103 * of 0 to 1020 in multiples of 4 (ie. 8 bits shifted by 2).
104 * This is also true of subsequent cache instructions
105 * (dhu, ihu, diu, iiu, diwb, diwbi, dpfl, ipfl) which have offsets
106 * of 0 to 240 in multiples of 16 (ie. 4 bits shifted by 4).
107 *
108 * (Maximum cache size, currently 32k, doesn't affect the following macros.
109 * Cache ways > MMU min page size cause aliasing but that's another matter.)
110 */
111
112
113
114/*
115 * Macro to apply an 'indexed' cache instruction to the entire cache.
116 *
117 * Parameters:
118 * cainst instruction/ that takes an address register parameter
119 * and an offset parameter (in range 0 .. 3*linesize).
120 * size size of cache in bytes
121 * linesize size of cache line in bytes
122 * assoc_or1 number of associativities (ways/sets) in cache
123 * if all sets affected by cainst,
124 * or 1 if only one set (or not all sets) of the cache
125 * is affected by cainst (eg. DIWB or DIWBI [not yet ISA defined]).
126 * aa, ab unique address registers (temporaries)
127 */
128
129 .macro cache_index_all cainst, size, linesize, assoc_or1, aa, ab
130
131 // Sanity-check on cache parameters:
132 .ifne (\size % (\linesize * \assoc_or1 * 4))
133 .err // cache configuration outside expected/supported range!
134 .endif
135
136 // \size byte cache, \linesize byte lines, \assoc_or1 way(s) affected by each \cainst.
137 movi \aa, (\size / (\linesize * \assoc_or1 * 4))
138 // Possible improvement: need only loop if \aa > 1 ;
139 // however that particular condition is highly unlikely.
140 movi \ab, 0 // to iterate over cache
141 floop \aa, cachex\@
142 \cainst \ab, 0*\linesize
143 \cainst \ab, 1*\linesize
144 \cainst \ab, 2*\linesize
145 \cainst \ab, 3*\linesize
146 addi \ab, \ab, 4*\linesize // move to next line
147 floopend \aa, cachex\@
148
149 .endm
150
151
152/*
153 * Macro to apply a 'hit' cache instruction to a memory region,
154 * ie. to any cache entries that cache a specified portion (region) of memory.
155 * Takes care of the unaligned cases, ie. may apply to one
156 * more cache line than $asize / lineSize if $aaddr is not aligned.
157 *
158 *
159 * Parameters are:
160 * cainst instruction/macro that takes an address register parameter
161 * and an offset parameter (currently always zero)
162 * and generates a cache instruction (eg. "dhi", "dhwb", "ihi", etc.)
163 * linesize_log2 log2(size of cache line in bytes)
164 * addr register containing start address of region (clobbered)
165 * asize register containing size of the region in bytes (clobbered)
166 * askew unique register used as temporary
167 *
168 * !?!?! 2DO: optimization: iterate max(cache_size and \asize) / linesize
169 */
170
171 .macro cache_hit_region cainst, linesize_log2, addr, asize, askew
172
173 // Make \asize the number of iterations:
174 extui \askew, \addr, 0, \linesize_log2 // get unalignment amount of \addr
175 add \asize, \asize, \askew // ... and add it to \asize
176 addi \asize, \asize, (1 << \linesize_log2) - 1 // round up!
177 srli \asize, \asize, \linesize_log2
178
179 // Iterate over region:
180 floopnez \asize, cacheh\@
181 \cainst \addr, 0
182 addi \addr, \addr, (1 << \linesize_log2) // move to next line
183 floopend \asize, cacheh\@
184
185 .endm
186
187
188
189
190
191/*************************** INSTRUCTION CACHE ***************************/
192
193
194/*
195 * Reset/initialize the instruction cache by simply invalidating it:
196 * (need to unlock first also, if cache locking implemented):
197 *
198 * Parameters:
199 * aa, ab unique address registers (temporaries)
200 */
201 .macro icache_reset aa, ab
202 icache_unlock_all \aa, \ab
203 icache_invalidate_all \aa, \ab
204 .endm
205
206
207/*
208 * Synchronize after an instruction cache operation,
209 * to be sure everything is in sync with memory as to be
210 * expected following any previous instruction cache control operations.
211 *
212 * Parameters are:
213 * ar an address register (temporary) (currently unused, but may be used in future)
214 */
215 .macro icache_sync ar
216#if XCHAL_ICACHE_SIZE > 0
217 isync
218#endif
219 .endm
220
221
222
223/*
224 * Invalidate a single line of the instruction cache.
225 * Parameters are:
226 * ar address register that contains (virtual) address to invalidate
227 * (may get clobbered in a future implementation, but not currently)
228 * offset (optional) offset to add to \ar to compute effective address to invalidate
229 * (note: some number of lsbits are ignored)
230 */
231 .macro icache_invalidate_line ar, offset
232#if XCHAL_ICACHE_SIZE > 0
233 ihi \ar, \offset // invalidate icache line
234 /*
235 * NOTE: in some version of the silicon [!!!SHOULD HAVE BEEN DOCUMENTED!!!]
236 * 'ihi' doesn't work, so it had been replaced with 'iii'
237 * (which would just invalidate more than it should,
238 * which should be okay other than the performance hit
239 * because cache locking did not exist in that version,
240 * unless user somehow relies on something being cached).
241 * [WHAT VERSION IS IT!!?!?
242 * IS THERE ANY WAY TO TEST FOR THAT HERE, TO OUTPUT 'III' ONLY IF NEEDED!?!?].
243 *
244 * iii \ar, \offset
245 */
246 icache_sync \ar
247#endif
248 .endm
249
250
251
252
253/*
254 * Invalidate instruction cache entries that cache a specified portion of memory.
255 * Parameters are:
256 * astart start address (register gets clobbered)
257 * asize size of the region in bytes (register gets clobbered)
258 * ac unique register used as temporary
259 */
260 .macro icache_invalidate_region astart, asize, ac
261#if XCHAL_ICACHE_SIZE > 0
262 // Instruction cache region invalidation:
263 cache_hit_region ihi, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
264 icache_sync \ac
265 // End of instruction cache region invalidation
266#endif
267 .endm
268
269
270
271/*
272 * Invalidate entire instruction cache.
273 *
274 * Parameters:
275 * aa, ab unique address registers (temporaries)
276 */
277 .macro icache_invalidate_all aa, ab
278#if XCHAL_ICACHE_SIZE > 0
279 // Instruction cache invalidation:
280 cache_index_all iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, XCHAL_ICACHE_WAYS, \aa, \ab
281 icache_sync \aa
282 // End of instruction cache invalidation
283#endif
284 .endm
285
286
287
288/*
289 * Lock (prefetch & lock) a single line of the instruction cache.
290 *
291 * Parameters are:
292 * ar address register that contains (virtual) address to lock
293 * (may get clobbered in a future implementation, but not currently)
294 * offset offset to add to \ar to compute effective address to lock
295 * (note: some number of lsbits are ignored)
296 */
297 .macro icache_lock_line ar, offset
298#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
299 ipfl \ar, \offset /* prefetch and lock icache line */
300 icache_sync \ar
301#endif
302 .endm
303
304
305
306/*
307 * Lock (prefetch & lock) a specified portion of memory into the instruction cache.
308 * Parameters are:
309 * astart start address (register gets clobbered)
310 * asize size of the region in bytes (register gets clobbered)
311 * ac unique register used as temporary
312 */
313 .macro icache_lock_region astart, asize, ac
314#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
315 // Instruction cache region lock:
316 cache_hit_region ipfl, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
317 icache_sync \ac
318 // End of instruction cache region lock
319#endif
320 .endm
321
322
323
324/*
325 * Unlock a single line of the instruction cache.
326 *
327 * Parameters are:
328 * ar address register that contains (virtual) address to unlock
329 * (may get clobbered in a future implementation, but not currently)
330 * offset offset to add to \ar to compute effective address to unlock
331 * (note: some number of lsbits are ignored)
332 */
333 .macro icache_unlock_line ar, offset
334#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
335 ihu \ar, \offset /* unlock icache line */
336 icache_sync \ar
337#endif
338 .endm
339
340
341
342/*
343 * Unlock a specified portion of memory from the instruction cache.
344 * Parameters are:
345 * astart start address (register gets clobbered)
346 * asize size of the region in bytes (register gets clobbered)
347 * ac unique register used as temporary
348 */
349 .macro icache_unlock_region astart, asize, ac
350#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
351 // Instruction cache region unlock:
352 cache_hit_region ihu, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
353 icache_sync \ac
354 // End of instruction cache region unlock
355#endif
356 .endm
357
358
359
360/*
361 * Unlock entire instruction cache.
362 *
363 * Parameters:
364 * aa, ab unique address registers (temporaries)
365 */
366 .macro icache_unlock_all aa, ab
367#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
368 // Instruction cache unlock:
369 cache_index_all iiu, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, 1, \aa, \ab
370 icache_sync \aa
371 // End of instruction cache unlock
372#endif
373 .endm
374
375
376
377
378
379/*************************** DATA CACHE ***************************/
380
381
382
383/*
384 * Reset/initialize the data cache by simply invalidating it
385 * (need to unlock first also, if cache locking implemented):
386 *
387 * Parameters:
388 * aa, ab unique address registers (temporaries)
389 */
390 .macro dcache_reset aa, ab
391 dcache_unlock_all \aa, \ab
392 dcache_invalidate_all \aa, \ab
393 .endm
394
395
396
397
398/*
399 * Synchronize after a data cache operation,
400 * to be sure everything is in sync with memory as to be
401 * expected following any previous data cache control operations.
402 *
403 * Parameters are:
404 * ar an address register (temporary) (currently unused, but may be used in future)
405 */
406 .macro dcache_sync ar
407#if XCHAL_DCACHE_SIZE > 0
408 // This previous sequence errs on the conservative side (too much so); a DSYNC should be sufficient:
409 //memw // synchronize data cache changes relative to subsequent memory accesses
410 //isync // be conservative and ISYNC as well (just to be sure)
411
412 dsync
413#endif
414 .endm
415
416
417
418/*
419 * Synchronize after a data store operation,
420 * to be sure the stored data is completely off the processor
421 * (and assuming there is no buffering outside the processor,
422 * that the data is in memory). This may be required to
423 * ensure that the processor's write buffers are emptied.
424 * A MEMW followed by a read guarantees this, by definition.
425 * We also try to make sure the read itself completes.
426 *
427 * Parameters are:
428 * ar an address register (temporary)
429 */
430 .macro write_sync ar
431 memw // ensure previous memory accesses are complete prior to subsequent memory accesses
432 l32i \ar, sp, 0 // completing this read ensures any previous write has completed, because of MEMW
433 //slot
434 add \ar, \ar, \ar // use the result of the read to help ensure the read completes (in future architectures)
435 .endm
436
437
438/*
439 * Invalidate a single line of the data cache.
440 * Parameters are:
441 * ar address register that contains (virtual) address to invalidate
442 * (may get clobbered in a future implementation, but not currently)
443 * offset (optional) offset to add to \ar to compute effective address to invalidate
444 * (note: some number of lsbits are ignored)
445 */
446 .macro dcache_invalidate_line ar, offset
447#if XCHAL_DCACHE_SIZE > 0
448 dhi \ar, \offset
449 dcache_sync \ar
450#endif
451 .endm
452
453
454
455
456
457/*
458 * Invalidate data cache entries that cache a specified portion of memory.
459 * Parameters are:
460 * astart start address (register gets clobbered)
461 * asize size of the region in bytes (register gets clobbered)
462 * ac unique register used as temporary
463 */
464 .macro dcache_invalidate_region astart, asize, ac
465#if XCHAL_DCACHE_SIZE > 0
466 // Data cache region invalidation:
467 cache_hit_region dhi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
468 dcache_sync \ac
469 // End of data cache region invalidation
470#endif
471 .endm
472
473
474
475#if 0
476/*
477 * This is a work-around for a bug in SiChip1 (???).
478 * There should be a proper mechanism for not outputting
479 * these instructions when not needed.
480 * To enable work-around, uncomment this and replace 'dii'
481 * with 'dii_s1' everywhere, eg. in dcache_invalidate_all
482 * macro below.
483 */
484 .macro dii_s1 ar, offset
485 dii \ar, \offset
486 or \ar, \ar, \ar
487 or \ar, \ar, \ar
488 or \ar, \ar, \ar
489 or \ar, \ar, \ar
490 .endm
491#endif
492
493
494/*
495 * Invalidate entire data cache.
496 *
497 * Parameters:
498 * aa, ab unique address registers (temporaries)
499 */
500 .macro dcache_invalidate_all aa, ab
501#if XCHAL_DCACHE_SIZE > 0
502 // Data cache invalidation:
503 cache_index_all dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, XCHAL_DCACHE_WAYS, \aa, \ab
504 dcache_sync \aa
505 // End of data cache invalidation
506#endif
507 .endm
508
509
510
511/*
512 * Writeback a single line of the data cache.
513 * Parameters are:
514 * ar address register that contains (virtual) address to writeback
515 * (may get clobbered in a future implementation, but not currently)
516 * offset offset to add to \ar to compute effective address to writeback
517 * (note: some number of lsbits are ignored)
518 */
519 .macro dcache_writeback_line ar, offset
520#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
521 dhwb \ar, \offset
522 dcache_sync \ar
523#endif
524 .endm
525
526
527
528/*
529 * Writeback dirty data cache entries that cache a specified portion of memory.
530 * Parameters are:
531 * astart start address (register gets clobbered)
532 * asize size of the region in bytes (register gets clobbered)
533 * ac unique register used as temporary
534 */
535 .macro dcache_writeback_region astart, asize, ac
536#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
537 // Data cache region writeback:
538 cache_hit_region dhwb, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
539 dcache_sync \ac
540 // End of data cache region writeback
541#endif
542 .endm
543
544
545
546/*
547 * Writeback entire data cache.
548 * Parameters:
549 * aa, ab unique address registers (temporaries)
550 */
551 .macro dcache_writeback_all aa, ab
552#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
553 // Data cache writeback:
554 cache_index_all diwb, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
555 dcache_sync \aa
556 // End of data cache writeback
557#endif
558 .endm
559
560
561
562/*
563 * Writeback and invalidate a single line of the data cache.
564 * Parameters are:
565 * ar address register that contains (virtual) address to writeback and invalidate
566 * (may get clobbered in a future implementation, but not currently)
567 * offset offset to add to \ar to compute effective address to writeback and invalidate
568 * (note: some number of lsbits are ignored)
569 */
570 .macro dcache_writeback_inv_line ar, offset
571#if XCHAL_DCACHE_SIZE > 0
572 dhwbi \ar, \offset /* writeback and invalidate dcache line */
573 dcache_sync \ar
574#endif
575 .endm
576
577
578
579/*
580 * Writeback and invalidate data cache entries that cache a specified portion of memory.
581 * Parameters are:
582 * astart start address (register gets clobbered)
583 * asize size of the region in bytes (register gets clobbered)
584 * ac unique register used as temporary
585 */
586 .macro dcache_writeback_inv_region astart, asize, ac
587#if XCHAL_DCACHE_SIZE > 0
588 // Data cache region writeback and invalidate:
589 cache_hit_region dhwbi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
590 dcache_sync \ac
591 // End of data cache region writeback and invalidate
592#endif
593 .endm
594
595
596
597/*
598 * Writeback and invalidate entire data cache.
599 * Parameters:
600 * aa, ab unique address registers (temporaries)
601 */
602 .macro dcache_writeback_inv_all aa, ab
603#if XCHAL_DCACHE_SIZE > 0
604 // Data cache writeback and invalidate:
605#if XCHAL_DCACHE_IS_WRITEBACK
606 cache_index_all diwbi, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
607 dcache_sync \aa
608#else /*writeback*/
609 // Data cache does not support writeback, so just invalidate: */
610 dcache_invalidate_all \aa, \ab
611#endif /*writeback*/
612 // End of data cache writeback and invalidate
613#endif
614 .endm
615
616
617
618
619/*
620 * Lock (prefetch & lock) a single line of the data cache.
621 *
622 * Parameters are:
623 * ar address register that contains (virtual) address to lock
624 * (may get clobbered in a future implementation, but not currently)
625 * offset offset to add to \ar to compute effective address to lock
626 * (note: some number of lsbits are ignored)
627 */
628 .macro dcache_lock_line ar, offset
629#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
630 dpfl \ar, \offset /* prefetch and lock dcache line */
631 dcache_sync \ar
632#endif
633 .endm
634
635
636
637/*
638 * Lock (prefetch & lock) a specified portion of memory into the data cache.
639 * Parameters are:
640 * astart start address (register gets clobbered)
641 * asize size of the region in bytes (register gets clobbered)
642 * ac unique register used as temporary
643 */
644 .macro dcache_lock_region astart, asize, ac
645#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
646 // Data cache region lock:
647 cache_hit_region dpfl, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
648 dcache_sync \ac
649 // End of data cache region lock
650#endif
651 .endm
652
653
654
655/*
656 * Unlock a single line of the data cache.
657 *
658 * Parameters are:
659 * ar address register that contains (virtual) address to unlock
660 * (may get clobbered in a future implementation, but not currently)
661 * offset offset to add to \ar to compute effective address to unlock
662 * (note: some number of lsbits are ignored)
663 */
664 .macro dcache_unlock_line ar, offset
665#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
666 dhu \ar, \offset /* unlock dcache line */
667 dcache_sync \ar
668#endif
669 .endm
670
671
672
673/*
674 * Unlock a specified portion of memory from the data cache.
675 * Parameters are:
676 * astart start address (register gets clobbered)
677 * asize size of the region in bytes (register gets clobbered)
678 * ac unique register used as temporary
679 */
680 .macro dcache_unlock_region astart, asize, ac
681#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
682 // Data cache region unlock:
683 cache_hit_region dhu, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
684 dcache_sync \ac
685 // End of data cache region unlock
686#endif
687 .endm
688
689
690
691/*
692 * Unlock entire data cache.
693 *
694 * Parameters:
695 * aa, ab unique address registers (temporaries)
696 */
697 .macro dcache_unlock_all aa, ab
698#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
699 // Data cache unlock:
700 cache_index_all diu, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
701 dcache_sync \aa
702 // End of data cache unlock
703#endif
704 .endm
705
706
707#endif /*XTENSA_CACHEASM_H*/
708
diff --git a/include/asm-xtensa/xtensa/cacheattrasm.h b/include/asm-xtensa/xtensa/cacheattrasm.h
new file mode 100644
index 0000000000..1c3e117b35
--- /dev/null
+++ b/include/asm-xtensa/xtensa/cacheattrasm.h
@@ -0,0 +1,432 @@
1#ifndef XTENSA_CACHEATTRASM_H
2#define XTENSA_CACHEATTRASM_H
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * include/asm-xtensa/xtensa/cacheattrasm.h -- assembler-specific
8 * CACHEATTR register related definitions that depend on CORE
9 * configuration.
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
13 * for more details.
14 *
15 * Copyright (C) 2002 Tensilica Inc.
16 */
17
18
19#include <xtensa/coreasm.h>
20
21
22/*
23 * This header file defines assembler macros of the form:
24 * <x>cacheattr_<func>
25 * where:
26 * <x> is 'i', 'd' or absent for instruction, data
27 * or both caches; and
28 * <func> indicates the function of the macro.
29 *
30 * The following functions are defined:
31 *
32 * icacheattr_get
33 * Reads I-cache CACHEATTR into a2 (clobbers a3-a5).
34 *
35 * dcacheattr_get
36 * Reads D-cache CACHEATTR into a2 (clobbers a3-a5).
37 * (Note: for configs with a real CACHEATTR register, the
38 * above two macros are identical.)
39 *
40 * cacheattr_set
41 * Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered).
42 * Works even when changing one's own code's attributes.
43 *
44 * icacheattr_is_enabled label
45 * Branches to \label if I-cache appears to have been enabled
46 * (eg. if CACHEATTR contains a cache-enabled attribute).
47 * (clobbers a2-a5,SAR)
48 *
49 * dcacheattr_is_enabled label
50 * Branches to \label if D-cache appears to have been enabled
51 * (eg. if CACHEATTR contains a cache-enabled attribute).
52 * (clobbers a2-a5,SAR)
53 *
54 * cacheattr_is_enabled label
55 * Branches to \label if either I-cache or D-cache appears to have been enabled
56 * (eg. if CACHEATTR contains a cache-enabled attribute).
57 * (clobbers a2-a5,SAR)
58 *
59 * The following macros are only defined under certain conditions:
60 *
61 * icacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
62 * Writes I-cache CACHEATTR from a2 (a3-a8 clobbered).
63 *
64 * dcacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
65 * Writes D-cache CACHEATTR from a2 (a3-a8 clobbered).
66 */
67
68
69
70/*************************** GENERIC -- ALL CACHES ***************************/
71
72/*
73 * _cacheattr_get
74 *
75 * (Internal macro.)
76 * Returns value of CACHEATTR register (or closest equivalent) in a2.
77 *
78 * Entry:
79 * (none)
80 * Exit:
81 * a2 value read from CACHEATTR
82 * a3-a5 clobbered (temporaries)
83 */
84 .macro _cacheattr_get tlb
85#if XCHAL_HAVE_CACHEATTR
86 rsr a2, CACHEATTR
87#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
88 // We have a config that "mimics" CACHEATTR using a simplified
89 // "MMU" composed of a single statically-mapped way.
90 // DTLB and ITLB are independent, so there's no single
91 // cache attribute that can describe both. So for now
92 // just return the DTLB state.
93 movi a5, 0xE0000000
94 movi a2, 0
95 movi a3, 0
961: add a3, a3, a5 // next segment
97 r&tlb&1 a4, a3 // get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0
98 dsync // interlock???
99 slli a2, a2, 4
100 extui a4, a4, 0, 4 // extract CA
101 or a2, a2, a4
102 bnez a3, 1b
103#else
104 // This macro isn't applicable to arbitrary MMU configurations.
105 // Just return zero.
106 movi a2, 0
107#endif
108 .endm
109
110 .macro icacheattr_get
111 _cacheattr_get itlb
112 .endm
113
114 .macro dcacheattr_get
115 _cacheattr_get dtlb
116 .endm
117
118
119#define XCHAL_CACHEATTR_ALL_BYPASS 0x22222222 /* default (powerup/reset) value of CACHEATTR, all BYPASS
120 mode (ie. disabled/bypassed caches) */
121
122#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
123
124#define XCHAL_FCA_ENAMASK 0x001A /* bitmap of fetch attributes that require enabled icache */
125#define XCHAL_LCA_ENAMASK 0x0003 /* bitmap of load attributes that require enabled dcache */
126#define XCHAL_SCA_ENAMASK 0x0003 /* bitmap of store attributes that require enabled dcache */
127#define XCHAL_LSCA_ENAMASK (XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK) /* l/s attrs requiring enabled dcache */
128#define XCHAL_ALLCA_ENAMASK (XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK) /* all attrs requiring enabled caches */
129
130/*
131 * _cacheattr_is_enabled
132 *
133 * (Internal macro.)
134 * Branches to \label if CACHEATTR in a2 indicates an enabled
135 * cache, using mask in a3.
136 *
137 * Parameters:
138 * label where to branch to if cache is enabled
139 * Entry:
140 * a2 contains CACHEATTR value used to determine whether
141 * caches are enabled
142 * a3 16-bit constant where each bit correspond to
143 * one of the 16 possible CA values (in a CACHEATTR mask);
144 * CA values that indicate the cache is enabled
145 * have their corresponding bit set in this mask
146 * (eg. use XCHAL_xCA_ENAMASK , above)
147 * Exit:
148 * a2,a4,a5 clobbered
149 * SAR clobbered
150 */
151 .macro _cacheattr_is_enabled label
152 movi a4, 8 // loop 8 times
153.Lcaife\@:
154 extui a5, a2, 0, 4 // get CA nibble
155 ssr a5 // index into mask according to CA...
156 srl a5, a3 // ...and get CA's mask bit in a5 bit 0
157 bbsi.l a5, 0, \label // if CA indicates cache enabled, jump to label
158 srli a2, a2, 4 // next nibble
159 addi a4, a4, -1
160 bnez a4, .Lcaife\@ // loop for each nibble
161 .endm
162
163#else /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
164 .macro _cacheattr_is_enabled label
165 j \label // macro not applicable, assume caches always enabled
166 .endm
167#endif /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
168
169
170
171/*
172 * icacheattr_is_enabled
173 *
174 * Branches to \label if I-cache is enabled.
175 *
176 * Parameters:
177 * label where to branch to if icache is enabled
178 * Entry:
179 * (none)
180 * Exit:
181 * a2-a5, SAR clobbered (temporaries)
182 */
183 .macro icacheattr_is_enabled label
184#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
185 icacheattr_get
186 movi a3, XCHAL_FCA_ENAMASK
187#endif
188 _cacheattr_is_enabled \label
189 .endm
190
191/*
192 * dcacheattr_is_enabled
193 *
194 * Branches to \label if D-cache is enabled.
195 *
196 * Parameters:
197 * label where to branch to if dcache is enabled
198 * Entry:
199 * (none)
200 * Exit:
201 * a2-a5, SAR clobbered (temporaries)
202 */
203 .macro dcacheattr_is_enabled label
204#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
205 dcacheattr_get
206 movi a3, XCHAL_LSCA_ENAMASK
207#endif
208 _cacheattr_is_enabled \label
209 .endm
210
211/*
212 * cacheattr_is_enabled
213 *
214 * Branches to \label if either I-cache or D-cache is enabled.
215 *
216 * Parameters:
217 * label where to branch to if a cache is enabled
218 * Entry:
219 * (none)
220 * Exit:
221 * a2-a5, SAR clobbered (temporaries)
222 */
223 .macro cacheattr_is_enabled label
224#if XCHAL_HAVE_CACHEATTR
225 rsr a2, CACHEATTR
226 movi a3, XCHAL_ALLCA_ENAMASK
227#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
228 icacheattr_get
229 movi a3, XCHAL_FCA_ENAMASK
230 _cacheattr_is_enabled \label
231 dcacheattr_get
232 movi a3, XCHAL_LSCA_ENAMASK
233#endif
234 _cacheattr_is_enabled \label
235 .endm
236
237
238
239/*
240 * The ISA does not have a defined way to change the
241 * instruction cache attributes of the running code,
242 * ie. of the memory area that encloses the current PC.
243 * However, each micro-architecture (or class of
244 * configurations within a micro-architecture)
245 * provides a way to deal with this issue.
246 *
247 * Here are a few macros used to implement the relevant
248 * approach taken.
249 */
250
251#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
252 // We have a config that "mimics" CACHEATTR using a simplified
253 // "MMU" composed of a single statically-mapped way.
254
255/*
256 * icacheattr_set
257 *
258 * Entry:
259 * a2 cacheattr value to set
260 * Exit:
261 * a2 unchanged
262 * a3-a8 clobbered (temporaries)
263 */
264 .macro icacheattr_set
265
266 movi a5, 0xE0000000 // mask of upper 3 bits
267 movi a6, 3f // PC where ITLB is set
268 movi a3, 0 // start at region 0 (0 .. 7)
269 and a6, a6, a5 // upper 3 bits of local PC area
270 mov a7, a2 // copy a2 so it doesn't get clobbered
271 j 3f
272
273# if XCHAL_HAVE_XLT_CACHEATTR
274 // Can do translations, use generic method:
2751: sub a6, a3, a5 // address of some other segment
276 ritlb1 a8, a6 // save its PPN+CA
277 dsync // interlock??
278 witlb a4, a6 // make it translate to this code area
279 movi a6, 5f // where to jump into it
280 isync
281 sub a6, a6, a5 // adjust jump address within that other segment
282 jx a6
283
284 // Note that in the following code snippet, which runs at a different virtual
285 // address than it is assembled for, we avoid using literals (eg. via movi/l32r)
286 // just in case literals end up in a different 512 MB segment, and we avoid
287 // instructions that rely on the current PC being what is expected.
288 //
289 .align 4
290 _j 6f // this is at label '5' minus 4 bytes
291 .align 4
2925: witlb a4, a3 // we're in other segment, now can write previous segment's CA
293 isync
294 add a6, a6, a5 // back to previous segment
295 addi a6, a6, -4 // next jump label
296 jx a6
297
2986: sub a6, a3, a5 // address of some other segment
299 witlb a8, a6 // restore PPN+CA of other segment
300 mov a6, a3 // restore a6
301 isync
302# else /* XCHAL_HAVE_XLT_CACHEATTR */
303 // Use micro-architecture specific method.
304 // The following 4-instruction sequence is aligned such that
305 // it all fits within a single I-cache line. Sixteen byte
306 // alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE
307 // actually causes problems because that can be greater than
308 // the alignment of the reset vector, where this macro is often
309 // invoked, which would cause the linker to align the reset
310 // vector code away from the reset vector!!).
311 .align 16 /*XCHAL_ICACHE_LINESIZE*/
3121: _witlb a4, a3 // write wired PTE (CA, no PPN) of 512MB segment to ITLB
313 _isync
314 nop
315 nop
316# endif /* XCHAL_HAVE_XLT_CACHEATTR */
317 beq a3, a5, 4f // done?
318
319 // Note that in the WITLB loop, we don't do any load/stores
320 // (may not be an issue here, but it is important in the DTLB case).
3212: srli a7, a7, 4 // next CA
322 sub a3, a3, a5 // next segment (add 0x20000000)
3233:
324# if XCHAL_HAVE_XLT_CACHEATTR /* if have translation, preserve it */
325 ritlb1 a8, a3 // get current PPN+CA of segment
326 dsync // interlock???
327 extui a4, a7, 0, 4 // extract CA to set
328 srli a8, a8, 4 // clear CA but keep PPN ...
329 slli a8, a8, 4 // ...
330 add a4, a4, a8 // combine new CA with PPN to preserve
331# else
332 extui a4, a7, 0, 4 // extract CA
333# endif
334 beq a3, a6, 1b // current PC's region? if so, do it in a safe way
335 witlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to ITLB
336 bne a3, a5, 2b
337 isync // make sure all ifetch changes take effect
3384:
339 .endm // icacheattr_set
340
341
342/*
343 * dcacheattr_set
344 *
345 * Entry:
346 * a2 cacheattr value to set
347 * Exit:
348 * a2 unchanged
349 * a3-a8 clobbered (temporaries)
350 */
351
352 .macro dcacheattr_set
353
354 movi a5, 0xE0000000 // mask of upper 3 bits
355 movi a3, 0 // start at region 0 (0 .. 7)
356 mov a7, a2 // copy a2 so it doesn't get clobbered
357 j 3f
358 // Note that in the WDTLB loop, we don't do any load/stores
359 // (including implicit l32r via movi) because it isn't safe.
3602: srli a7, a7, 4 // next CA
361 sub a3, a3, a5 // next segment (add 0x20000000)
3623:
363# if XCHAL_HAVE_XLT_CACHEATTR /* if have translation, preserve it */
364 rdtlb1 a8, a3 // get current PPN+CA of segment
365 dsync // interlock???
366 extui a4, a7, 0, 4 // extract CA to set
367 srli a8, a8, 4 // clear CA but keep PPN ...
368 slli a8, a8, 4 // ...
369 add a4, a4, a8 // combine new CA with PPN to preserve
370# else
371 extui a4, a7, 0, 4 // extract CA to set
372# endif
373 wdtlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to DTLB
374 bne a3, a5, 2b
375 dsync // make sure all data path changes take effect
376 .endm // dcacheattr_set
377
378#endif /* XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
379
380
381
382/*
383 * cacheattr_set
384 *
385 * Macro that sets the current CACHEATTR safely
386 * (both i and d) according to the current contents of a2.
387 * It works even when changing the cache attributes of
388 * the currently running code.
389 *
390 * Entry:
391 * a2 cacheattr value to set
392 * Exit:
393 * a2 unchanged
394 * a3-a8 clobbered (temporaries)
395 */
396 .macro cacheattr_set
397
398#if XCHAL_HAVE_CACHEATTR
399# if XCHAL_ICACHE_LINESIZE < 4
400 // No i-cache, so can always safely write to CACHEATTR:
401 wsr a2, CACHEATTR
402# else
403 // The Athens micro-architecture, when using the old
404 // exception architecture option (ie. with the CACHEATTR register)
405 // allows changing the cache attributes of the running code
406 // using the following exact sequence aligned to be within
407 // an instruction cache line. (NOTE: using XCHAL_ICACHE_LINESIZE
408 // alignment actually causes problems because that can be greater
409 // than the alignment of the reset vector, where this macro is often
410 // invoked, which would cause the linker to align the reset
411 // vector code away from the reset vector!!).
412 j 1f
413 .align 16 /*XCHAL_ICACHE_LINESIZE*/ // align to within an I-cache line
4141: _wsr a2, CACHEATTR
415 _isync
416 nop
417 nop
418# endif
419#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
420 // DTLB and ITLB are independent, but to keep semantics
421 // of this macro we simply write to both.
422 icacheattr_set
423 dcacheattr_set
424#else
425 // This macro isn't applicable to arbitrary MMU configurations.
426 // Do nothing in this case.
427#endif
428 .endm
429
430
431#endif /*XTENSA_CACHEATTRASM_H*/
432
diff --git a/include/asm-xtensa/xtensa/config-linux_be/core.h b/include/asm-xtensa/xtensa/config-linux_be/core.h
new file mode 100644
index 0000000000..d54fe5eb10
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/core.h
@@ -0,0 +1,1270 @@
1/*
2 * xtensa/config/core.h -- HAL definitions that are dependent on CORE configuration
3 *
4 * This header file is sometimes referred to as the "compile-time HAL" or CHAL.
5 * It was generated for a specific Xtensa processor configuration.
6 *
7 * Source for configuration-independent binaries (which link in a
8 * configuration-specific HAL library) must NEVER include this file.
9 * It is perfectly normal, however, for the HAL source itself to include this file.
10 */
11
12/*
13 * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of version 2.1 of the GNU Lesser General Public
17 * License as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it would be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 *
23 * Further, this software is distributed without any warranty that it is
24 * free of the rightful claim of any third person regarding infringement
25 * or the like. Any license provided herein, whether implied or
26 * otherwise, applies only to this software file. Patent licenses, if
27 * any, provided herein do not apply to combinations of this program with
28 * other software, or any other product whatsoever.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this program; if not, write the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
33 * USA.
34 */
35
36
37#ifndef XTENSA_CONFIG_CORE_H
38#define XTENSA_CONFIG_CORE_H
39
40#include <xtensa/hal.h>
41
42
43/*----------------------------------------------------------------------
44 GENERAL
45 ----------------------------------------------------------------------*/
46
47/*
48 * Separators for macros that expand into arrays.
49 * These can be predefined by files that #include this one,
50 * when different separators are required.
51 */
52/* Element separator for macros that expand into 1-dimensional arrays: */
53#ifndef XCHAL_SEP
54#define XCHAL_SEP ,
55#endif
56/* Array separator for macros that expand into 2-dimensional arrays: */
57#ifndef XCHAL_SEP2
58#define XCHAL_SEP2 },{
59#endif
60
61
62/*----------------------------------------------------------------------
63 ENDIANNESS
64 ----------------------------------------------------------------------*/
65
66#define XCHAL_HAVE_BE 1
67#define XCHAL_HAVE_LE 0
68#define XCHAL_MEMORY_ORDER XTHAL_BIGENDIAN
69
70
71/*----------------------------------------------------------------------
72 REGISTER WINDOWS
73 ----------------------------------------------------------------------*/
74
75#define XCHAL_HAVE_WINDOWED 1 /* 1 if windowed registers option configured, 0 otherwise */
76#define XCHAL_NUM_AREGS 64 /* number of physical address regs */
77#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */
78
79
80/*----------------------------------------------------------------------
81 ADDRESS ALIGNMENT
82 ----------------------------------------------------------------------*/
83
84/* These apply to a selected set of core load and store instructions only (see ISA): */
85#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* 1 if unaligned loads cause an exception, 0 otherwise */
86#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* 1 if unaligned stores cause an exception, 0 otherwise */
87
88
89/*----------------------------------------------------------------------
90 INTERRUPTS
91 ----------------------------------------------------------------------*/
92
93#define XCHAL_HAVE_INTERRUPTS 1 /* 1 if interrupt option configured, 0 otherwise */
94#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* 1 if high-priority interrupt option configured, 0 otherwise */
95#define XCHAL_HAVE_HIGHLEVEL_INTERRUPTS XCHAL_HAVE_HIGHPRI_INTERRUPTS
96#define XCHAL_HAVE_NMI 0 /* 1 if NMI option configured, 0 otherwise */
97#define XCHAL_NUM_INTERRUPTS 17 /* number of interrupts */
98#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* number of bits to hold an interrupt number: roundup(log2(number of interrupts)) */
99#define XCHAL_NUM_EXTINTERRUPTS 10 /* number of external interrupts */
100#define XCHAL_NUM_INTLEVELS 4 /* number of interrupt levels (not including level zero!) */
101#define XCHAL_NUM_LOWPRI_LEVELS 1 /* number of low-priority interrupt levels (always 1) */
102#define XCHAL_FIRST_HIGHPRI_LEVEL (XCHAL_NUM_LOWPRI_LEVELS+1) /* level of first high-priority interrupt (always 2) */
103#define XCHAL_EXCM_LEVEL 1 /* level of interrupts masked by PS.EXCM (XEA2 only; always 1 in T10xx);
104 for XEA1, where there is no PS.EXCM, this is always 1;
105 interrupts at levels FIRST_HIGHPRI <= n <= EXCM_LEVEL, if any,
106 are termed "medium priority" interrupts (post T10xx only) */
107/* Note: 1 <= LOWPRI_LEVELS <= EXCM_LEVEL < DEBUGLEVEL <= NUM_INTLEVELS < NMILEVEL <= 15 */
108
109/* Masks of interrupts at each interrupt level: */
110#define XCHAL_INTLEVEL0_MASK 0x00000000
111#define XCHAL_INTLEVEL1_MASK 0x000064F9
112#define XCHAL_INTLEVEL2_MASK 0x00008902
113#define XCHAL_INTLEVEL3_MASK 0x00011204
114#define XCHAL_INTLEVEL4_MASK 0x00000000
115#define XCHAL_INTLEVEL5_MASK 0x00000000
116#define XCHAL_INTLEVEL6_MASK 0x00000000
117#define XCHAL_INTLEVEL7_MASK 0x00000000
118#define XCHAL_INTLEVEL8_MASK 0x00000000
119#define XCHAL_INTLEVEL9_MASK 0x00000000
120#define XCHAL_INTLEVEL10_MASK 0x00000000
121#define XCHAL_INTLEVEL11_MASK 0x00000000
122#define XCHAL_INTLEVEL12_MASK 0x00000000
123#define XCHAL_INTLEVEL13_MASK 0x00000000
124#define XCHAL_INTLEVEL14_MASK 0x00000000
125#define XCHAL_INTLEVEL15_MASK 0x00000000
126/* As an array of entries (eg. for C constant arrays): */
127#define XCHAL_INTLEVEL_MASKS 0x00000000 XCHAL_SEP \
128 0x000064F9 XCHAL_SEP \
129 0x00008902 XCHAL_SEP \
130 0x00011204 XCHAL_SEP \
131 0x00000000 XCHAL_SEP \
132 0x00000000 XCHAL_SEP \
133 0x00000000 XCHAL_SEP \
134 0x00000000 XCHAL_SEP \
135 0x00000000 XCHAL_SEP \
136 0x00000000 XCHAL_SEP \
137 0x00000000 XCHAL_SEP \
138 0x00000000 XCHAL_SEP \
139 0x00000000 XCHAL_SEP \
140 0x00000000 XCHAL_SEP \
141 0x00000000 XCHAL_SEP \
142 0x00000000
143
144/* Masks of interrupts at each range 1..n of interrupt levels: */
145#define XCHAL_INTLEVEL0_ANDBELOW_MASK 0x00000000
146#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000064F9
147#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x0000EDFB
148#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x0001FFFF
149#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x0001FFFF
150#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x0001FFFF
151#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x0001FFFF
152#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x0001FFFF
153#define XCHAL_INTLEVEL8_ANDBELOW_MASK 0x0001FFFF
154#define XCHAL_INTLEVEL9_ANDBELOW_MASK 0x0001FFFF
155#define XCHAL_INTLEVEL10_ANDBELOW_MASK 0x0001FFFF
156#define XCHAL_INTLEVEL11_ANDBELOW_MASK 0x0001FFFF
157#define XCHAL_INTLEVEL12_ANDBELOW_MASK 0x0001FFFF
158#define XCHAL_INTLEVEL13_ANDBELOW_MASK 0x0001FFFF
159#define XCHAL_INTLEVEL14_ANDBELOW_MASK 0x0001FFFF
160#define XCHAL_INTLEVEL15_ANDBELOW_MASK 0x0001FFFF
161#define XCHAL_LOWPRI_MASK XCHAL_INTLEVEL1_ANDBELOW_MASK /* mask of all low-priority interrupts */
162#define XCHAL_EXCM_MASK XCHAL_INTLEVEL1_ANDBELOW_MASK /* mask of all interrupts masked by PS.EXCM (or CEXCM) */
163/* As an array of entries (eg. for C constant arrays): */
164#define XCHAL_INTLEVEL_ANDBELOW_MASKS 0x00000000 XCHAL_SEP \
165 0x000064F9 XCHAL_SEP \
166 0x0000EDFB XCHAL_SEP \
167 0x0001FFFF XCHAL_SEP \
168 0x0001FFFF XCHAL_SEP \
169 0x0001FFFF XCHAL_SEP \
170 0x0001FFFF XCHAL_SEP \
171 0x0001FFFF XCHAL_SEP \
172 0x0001FFFF XCHAL_SEP \
173 0x0001FFFF XCHAL_SEP \
174 0x0001FFFF XCHAL_SEP \
175 0x0001FFFF XCHAL_SEP \
176 0x0001FFFF XCHAL_SEP \
177 0x0001FFFF XCHAL_SEP \
178 0x0001FFFF XCHAL_SEP \
179 0x0001FFFF
180
181/* Interrupt numbers for each interrupt level at which only one interrupt was configured: */
182/*#define XCHAL_INTLEVEL1_NUM ...more than one interrupt at this level...*/
183/*#define XCHAL_INTLEVEL2_NUM ...more than one interrupt at this level...*/
184/*#define XCHAL_INTLEVEL3_NUM ...more than one interrupt at this level...*/
185
186/* Level of each interrupt: */
187#define XCHAL_INT0_LEVEL 1
188#define XCHAL_INT1_LEVEL 2
189#define XCHAL_INT2_LEVEL 3
190#define XCHAL_INT3_LEVEL 1
191#define XCHAL_INT4_LEVEL 1
192#define XCHAL_INT5_LEVEL 1
193#define XCHAL_INT6_LEVEL 1
194#define XCHAL_INT7_LEVEL 1
195#define XCHAL_INT8_LEVEL 2
196#define XCHAL_INT9_LEVEL 3
197#define XCHAL_INT10_LEVEL 1
198#define XCHAL_INT11_LEVEL 2
199#define XCHAL_INT12_LEVEL 3
200#define XCHAL_INT13_LEVEL 1
201#define XCHAL_INT14_LEVEL 1
202#define XCHAL_INT15_LEVEL 2
203#define XCHAL_INT16_LEVEL 3
204#define XCHAL_INT17_LEVEL 0
205#define XCHAL_INT18_LEVEL 0
206#define XCHAL_INT19_LEVEL 0
207#define XCHAL_INT20_LEVEL 0
208#define XCHAL_INT21_LEVEL 0
209#define XCHAL_INT22_LEVEL 0
210#define XCHAL_INT23_LEVEL 0
211#define XCHAL_INT24_LEVEL 0
212#define XCHAL_INT25_LEVEL 0
213#define XCHAL_INT26_LEVEL 0
214#define XCHAL_INT27_LEVEL 0
215#define XCHAL_INT28_LEVEL 0
216#define XCHAL_INT29_LEVEL 0
217#define XCHAL_INT30_LEVEL 0
218#define XCHAL_INT31_LEVEL 0
219/* As an array of entries (eg. for C constant arrays): */
220#define XCHAL_INT_LEVELS 1 XCHAL_SEP \
221 2 XCHAL_SEP \
222 3 XCHAL_SEP \
223 1 XCHAL_SEP \
224 1 XCHAL_SEP \
225 1 XCHAL_SEP \
226 1 XCHAL_SEP \
227 1 XCHAL_SEP \
228 2 XCHAL_SEP \
229 3 XCHAL_SEP \
230 1 XCHAL_SEP \
231 2 XCHAL_SEP \
232 3 XCHAL_SEP \
233 1 XCHAL_SEP \
234 1 XCHAL_SEP \
235 2 XCHAL_SEP \
236 3 XCHAL_SEP \
237 0 XCHAL_SEP \
238 0 XCHAL_SEP \
239 0 XCHAL_SEP \
240 0 XCHAL_SEP \
241 0 XCHAL_SEP \
242 0 XCHAL_SEP \
243 0 XCHAL_SEP \
244 0 XCHAL_SEP \
245 0 XCHAL_SEP \
246 0 XCHAL_SEP \
247 0 XCHAL_SEP \
248 0 XCHAL_SEP \
249 0 XCHAL_SEP \
250 0 XCHAL_SEP \
251 0
252
253/* Type of each interrupt: */
254#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
255#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
256#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
257#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
258#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
259#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
260#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
261#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_EDGE
262#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_EDGE
263#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_EDGE
264#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER
265#define XCHAL_INT11_TYPE XTHAL_INTTYPE_TIMER
266#define XCHAL_INT12_TYPE XTHAL_INTTYPE_TIMER
267#define XCHAL_INT13_TYPE XTHAL_INTTYPE_SOFTWARE
268#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE
269#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE
270#define XCHAL_INT16_TYPE XTHAL_INTTYPE_SOFTWARE
271#define XCHAL_INT17_TYPE XTHAL_INTTYPE_UNCONFIGURED
272#define XCHAL_INT18_TYPE XTHAL_INTTYPE_UNCONFIGURED
273#define XCHAL_INT19_TYPE XTHAL_INTTYPE_UNCONFIGURED
274#define XCHAL_INT20_TYPE XTHAL_INTTYPE_UNCONFIGURED
275#define XCHAL_INT21_TYPE XTHAL_INTTYPE_UNCONFIGURED
276#define XCHAL_INT22_TYPE XTHAL_INTTYPE_UNCONFIGURED
277#define XCHAL_INT23_TYPE XTHAL_INTTYPE_UNCONFIGURED
278#define XCHAL_INT24_TYPE XTHAL_INTTYPE_UNCONFIGURED
279#define XCHAL_INT25_TYPE XTHAL_INTTYPE_UNCONFIGURED
280#define XCHAL_INT26_TYPE XTHAL_INTTYPE_UNCONFIGURED
281#define XCHAL_INT27_TYPE XTHAL_INTTYPE_UNCONFIGURED
282#define XCHAL_INT28_TYPE XTHAL_INTTYPE_UNCONFIGURED
283#define XCHAL_INT29_TYPE XTHAL_INTTYPE_UNCONFIGURED
284#define XCHAL_INT30_TYPE XTHAL_INTTYPE_UNCONFIGURED
285#define XCHAL_INT31_TYPE XTHAL_INTTYPE_UNCONFIGURED
286/* As an array of entries (eg. for C constant arrays): */
287#define XCHAL_INT_TYPES XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
288 XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
289 XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
290 XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
291 XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
292 XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
293 XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
294 XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
295 XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
296 XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
297 XTHAL_INTTYPE_TIMER XCHAL_SEP \
298 XTHAL_INTTYPE_TIMER XCHAL_SEP \
299 XTHAL_INTTYPE_TIMER XCHAL_SEP \
300 XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
301 XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
302 XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
303 XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
304 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
305 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
306 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
307 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
308 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
309 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
310 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
311 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
312 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
313 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
314 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
315 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
316 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
317 XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
318 XTHAL_INTTYPE_UNCONFIGURED
319
320/* Masks of interrupts for each type of interrupt: */
321#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFE0000
322#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0001E000
323#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000380
324#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000007F
325#define XCHAL_INTTYPE_MASK_TIMER 0x00001C00
326#define XCHAL_INTTYPE_MASK_NMI 0x00000000
327/* As an array of entries (eg. for C constant arrays): */
328#define XCHAL_INTTYPE_MASKS 0xFFFE0000 XCHAL_SEP \
329 0x0001E000 XCHAL_SEP \
330 0x00000380 XCHAL_SEP \
331 0x0000007F XCHAL_SEP \
332 0x00001C00 XCHAL_SEP \
333 0x00000000
334
335/* Interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3), -1 if unassigned */
336#define XCHAL_TIMER0_INTERRUPT 10
337#define XCHAL_TIMER1_INTERRUPT 11
338#define XCHAL_TIMER2_INTERRUPT 12
339#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED
340/* As an array of entries (eg. for C constant arrays): */
341#define XCHAL_TIMER_INTERRUPTS 10 XCHAL_SEP \
342 11 XCHAL_SEP \
343 12 XCHAL_SEP \
344 XTHAL_TIMER_UNCONFIGURED
345
346/* Indexing macros: */
347#define _XCHAL_INTLEVEL_MASK(n) XCHAL_INTLEVEL ## n ## _MASK
348#define XCHAL_INTLEVEL_MASK(n) _XCHAL_INTLEVEL_MASK(n) /* n = 0 .. 15 */
349#define _XCHAL_INTLEVEL_ANDBELOWMASK(n) XCHAL_INTLEVEL ## n ## _ANDBELOW_MASK
350#define XCHAL_INTLEVEL_ANDBELOW_MASK(n) _XCHAL_INTLEVEL_ANDBELOWMASK(n) /* n = 0 .. 15 */
351#define _XCHAL_INT_LEVEL(n) XCHAL_INT ## n ## _LEVEL
352#define XCHAL_INT_LEVEL(n) _XCHAL_INT_LEVEL(n) /* n = 0 .. 31 */
353#define _XCHAL_INT_TYPE(n) XCHAL_INT ## n ## _TYPE
354#define XCHAL_INT_TYPE(n) _XCHAL_INT_TYPE(n) /* n = 0 .. 31 */
355#define _XCHAL_TIMER_INTERRUPT(n) XCHAL_TIMER ## n ## _INTERRUPT
356#define XCHAL_TIMER_INTERRUPT(n) _XCHAL_TIMER_INTERRUPT(n) /* n = 0 .. 3 */
357
358
359
360/*
361 * External interrupt vectors/levels.
362 * These macros describe how Xtensa processor interrupt numbers
363 * (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
364 * map to external BInterrupt<n> pins, for those interrupts
365 * configured as external (level-triggered, edge-triggered, or NMI).
366 * See the Xtensa processor databook for more details.
367 */
368
369/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */
370#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */
371#define XCHAL_EXTINT1_NUM 1 /* (intlevel 2) */
372#define XCHAL_EXTINT2_NUM 2 /* (intlevel 3) */
373#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */
374#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */
375#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */
376#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */
377#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */
378#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */
379#define XCHAL_EXTINT9_NUM 9 /* (intlevel 3) */
380
381/* Corresponding interrupt masks: */
382#define XCHAL_EXTINT0_MASK 0x00000001
383#define XCHAL_EXTINT1_MASK 0x00000002
384#define XCHAL_EXTINT2_MASK 0x00000004
385#define XCHAL_EXTINT3_MASK 0x00000008
386#define XCHAL_EXTINT4_MASK 0x00000010
387#define XCHAL_EXTINT5_MASK 0x00000020
388#define XCHAL_EXTINT6_MASK 0x00000040
389#define XCHAL_EXTINT7_MASK 0x00000080
390#define XCHAL_EXTINT8_MASK 0x00000100
391#define XCHAL_EXTINT9_MASK 0x00000200
392
393/* Core config interrupt levels mapped to each external interrupt: */
394#define XCHAL_EXTINT0_LEVEL 1 /* (int number 0) */
395#define XCHAL_EXTINT1_LEVEL 2 /* (int number 1) */
396#define XCHAL_EXTINT2_LEVEL 3 /* (int number 2) */
397#define XCHAL_EXTINT3_LEVEL 1 /* (int number 3) */
398#define XCHAL_EXTINT4_LEVEL 1 /* (int number 4) */
399#define XCHAL_EXTINT5_LEVEL 1 /* (int number 5) */
400#define XCHAL_EXTINT6_LEVEL 1 /* (int number 6) */
401#define XCHAL_EXTINT7_LEVEL 1 /* (int number 7) */
402#define XCHAL_EXTINT8_LEVEL 2 /* (int number 8) */
403#define XCHAL_EXTINT9_LEVEL 3 /* (int number 9) */
404
405
406/*----------------------------------------------------------------------
407 EXCEPTIONS and VECTORS
408 ----------------------------------------------------------------------*/
409
410#define XCHAL_HAVE_EXCEPTIONS 1 /* 1 if exception option configured, 0 otherwise */
411
412#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture number: 1 for XEA1 (old), 2 for XEA2 (new) */
413#define XCHAL_HAVE_XEA1 0 /* 1 if XEA1, 0 otherwise */
414#define XCHAL_HAVE_XEA2 1 /* 1 if XEA2, 0 otherwise */
415/* For backward compatibility ONLY -- DO NOT USE (will be removed in future release): */
416#define XCHAL_HAVE_OLD_EXC_ARCH XCHAL_HAVE_XEA1 /* (DEPRECATED) 1 if old exception architecture (XEA1), 0 otherwise (eg. XEA2) */
417#define XCHAL_HAVE_EXCM XCHAL_HAVE_XEA2 /* (DEPRECATED) 1 if PS.EXCM bit exists (currently equals XCHAL_HAVE_TLBS) */
418
419#define XCHAL_RESET_VECTOR_VADDR 0xFE000020
420#define XCHAL_RESET_VECTOR_PADDR 0xFE000020
421#define XCHAL_USER_VECTOR_VADDR 0xD0000220
422#define XCHAL_PROGRAMEXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR /* for backward compatibility */
423#define XCHAL_USEREXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR /* for backward compatibility */
424#define XCHAL_USER_VECTOR_PADDR 0x00000220
425#define XCHAL_PROGRAMEXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR /* for backward compatibility */
426#define XCHAL_USEREXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR /* for backward compatibility */
427#define XCHAL_KERNEL_VECTOR_VADDR 0xD0000200
428#define XCHAL_STACKEDEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR /* for backward compatibility */
429#define XCHAL_KERNELEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR /* for backward compatibility */
430#define XCHAL_KERNEL_VECTOR_PADDR 0x00000200
431#define XCHAL_STACKEDEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR /* for backward compatibility */
432#define XCHAL_KERNELEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR /* for backward compatibility */
433#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xD0000290
434#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x00000290
435#define XCHAL_WINDOW_VECTORS_VADDR 0xD0000000
436#define XCHAL_WINDOW_VECTORS_PADDR 0x00000000
437#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xD0000240
438#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00000240
439#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xD0000250
440#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x00000250
441#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xFE000520
442#define XCHAL_INTLEVEL4_VECTOR_PADDR 0xFE000520
443#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR
444#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL4_VECTOR_PADDR
445
446/* Indexing macros: */
447#define _XCHAL_INTLEVEL_VECTOR_VADDR(n) XCHAL_INTLEVEL ## n ## _VECTOR_VADDR
448#define XCHAL_INTLEVEL_VECTOR_VADDR(n) _XCHAL_INTLEVEL_VECTOR_VADDR(n) /* n = 0 .. 15 */
449
450/*
451 * General Exception Causes
452 * (values of EXCCAUSE special register set by general exceptions,
453 * which vector to the user, kernel, or double-exception vectors):
454 */
455#define XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION 0 /* Illegal Instruction (IllegalInstruction) */
456#define XCHAL_EXCCAUSE_SYSTEM_CALL 1 /* System Call (SystemCall) */
457#define XCHAL_EXCCAUSE_INSTRUCTION_FETCH_ERROR 2 /* Instruction Fetch Error (InstructionFetchError) */
458#define XCHAL_EXCCAUSE_LOAD_STORE_ERROR 3 /* Load Store Error (LoadStoreError) */
459#define XCHAL_EXCCAUSE_LEVEL1_INTERRUPT 4 /* Level 1 Interrupt (Level1Interrupt) */
460#define XCHAL_EXCCAUSE_ALLOCA 5 /* Stack Extension Assist (Alloca) */
461#define XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO 6 /* Integer Divide by Zero (IntegerDivideByZero) */
462#define XCHAL_EXCCAUSE_SPECULATION 7 /* Speculation (Speculation) */
463#define XCHAL_EXCCAUSE_PRIVILEGED 8 /* Privileged Instruction (Privileged) */
464#define XCHAL_EXCCAUSE_UNALIGNED 9 /* Unaligned Load Store (Unaligned) */
465#define XCHAL_EXCCAUSE_ITLB_MISS 16 /* ITlb Miss Exception (ITlbMiss) */
466#define XCHAL_EXCCAUSE_ITLB_MULTIHIT 17 /* ITlb Mutltihit Exception (ITlbMultihit) */
467#define XCHAL_EXCCAUSE_ITLB_PRIVILEGE 18 /* ITlb Privilege Exception (ITlbPrivilege) */
468#define XCHAL_EXCCAUSE_ITLB_SIZE_RESTRICTION 19 /* ITlb Size Restriction Exception (ITlbSizeRestriction) */
469#define XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE 20 /* Fetch Cache Attribute Exception (FetchCacheAttribute) */
470#define XCHAL_EXCCAUSE_DTLB_MISS 24 /* DTlb Miss Exception (DTlbMiss) */
471#define XCHAL_EXCCAUSE_DTLB_MULTIHIT 25 /* DTlb Multihit Exception (DTlbMultihit) */
472#define XCHAL_EXCCAUSE_DTLB_PRIVILEGE 26 /* DTlb Privilege Exception (DTlbPrivilege) */
473#define XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION 27 /* DTlb Size Restriction Exception (DTlbSizeRestriction) */
474#define XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE 28 /* Load Cache Attribute Exception (LoadCacheAttribute) */
475#define XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE 29 /* Store Cache Attribute Exception (StoreCacheAttribute) */
476#define XCHAL_EXCCAUSE_FLOATING_POINT 40 /* Floating Point Exception (FloatingPoint) */
477
478
479
480/*----------------------------------------------------------------------
481 TIMERS
482 ----------------------------------------------------------------------*/
483
484#define XCHAL_HAVE_CCOUNT 1 /* 1 if have CCOUNT, 0 otherwise */
485/*#define XCHAL_HAVE_TIMERS XCHAL_HAVE_CCOUNT*/
486#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */
487
488
489
490/*----------------------------------------------------------------------
491 DEBUG
492 ----------------------------------------------------------------------*/
493
494#define XCHAL_HAVE_DEBUG 1 /* 1 if debug option configured, 0 otherwise */
495#define XCHAL_HAVE_OCD 1 /* 1 if OnChipDebug option configured, 0 otherwise */
496#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */
497#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */
498#define XCHAL_DEBUGLEVEL 4 /* debug interrupt level */
499/*DebugExternalInterrupt 0 0|1*/
500/*DebugUseDIRArray 0 0|1*/
501
502
503
504
505/*----------------------------------------------------------------------
506 COPROCESSORS and EXTRA STATE
507 ----------------------------------------------------------------------*/
508
509#define XCHAL_HAVE_CP 0 /* 1 if coprocessor option configured (CPENABLE present) */
510#define XCHAL_CP_MAXCFG 0 /* max allowed cp id plus one (per cfg) */
511
512#include <xtensa/config/tie.h>
513
514
515
516
517/*----------------------------------------------------------------------
518 INTERNAL I/D RAM/ROMs and XLMI
519 ----------------------------------------------------------------------*/
520
521#define XCHAL_NUM_INSTROM 0 /* number of core instruction ROMs configured */
522#define XCHAL_NUM_INSTRAM 0 /* number of core instruction RAMs configured */
523#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs configured */
524#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs configured */
525#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports configured */
526#define XCHAL_NUM_IROM XCHAL_NUM_INSTROM /* (DEPRECATED) */
527#define XCHAL_NUM_IRAM XCHAL_NUM_INSTRAM /* (DEPRECATED) */
528#define XCHAL_NUM_DROM XCHAL_NUM_DATAROM /* (DEPRECATED) */
529#define XCHAL_NUM_DRAM XCHAL_NUM_DATARAM /* (DEPRECATED) */
530
531
532
533/*----------------------------------------------------------------------
534 CACHE
535 ----------------------------------------------------------------------*/
536
537/* Size of the cache lines in log2(bytes): */
538#define XCHAL_ICACHE_LINEWIDTH 4
539#define XCHAL_DCACHE_LINEWIDTH 4
540/* Size of the cache lines in bytes: */
541#define XCHAL_ICACHE_LINESIZE 16
542#define XCHAL_DCACHE_LINESIZE 16
543/* Max for both I-cache and D-cache (used for general alignment): */
544#define XCHAL_CACHE_LINEWIDTH_MAX 4
545#define XCHAL_CACHE_LINESIZE_MAX 16
546
547/* Number of cache sets in log2(lines per way): */
548#define XCHAL_ICACHE_SETWIDTH 8
549#define XCHAL_DCACHE_SETWIDTH 8
550/* Max for both I-cache and D-cache (used for general cache-coherency page alignment): */
551#define XCHAL_CACHE_SETWIDTH_MAX 8
552#define XCHAL_CACHE_SETSIZE_MAX 256
553
554/* Cache set associativity (number of ways): */
555#define XCHAL_ICACHE_WAYS 2
556#define XCHAL_DCACHE_WAYS 2
557
558/* Size of the caches in bytes (ways * 2^(linewidth + setwidth)): */
559#define XCHAL_ICACHE_SIZE 8192
560#define XCHAL_DCACHE_SIZE 8192
561
562/* Cache features: */
563#define XCHAL_DCACHE_IS_WRITEBACK 0
564/* Whether cache locking feature is available: */
565#define XCHAL_ICACHE_LINE_LOCKABLE 0
566#define XCHAL_DCACHE_LINE_LOCKABLE 0
567
568/* Number of (encoded) cache attribute bits: */
569#define XCHAL_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */
570/* (The number of access mode bits (decoded cache attribute bits) is defined by the architecture; see xtensa/hal.h?) */
571
572
573/* Cache Attribute encodings -- lists of access modes for each cache attribute: */
574#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \
575 XTHAL_FAM_BYPASS XCHAL_SEP \
576 XTHAL_FAM_EXCEPTION XCHAL_SEP \
577 XTHAL_FAM_BYPASS XCHAL_SEP \
578 XTHAL_FAM_EXCEPTION XCHAL_SEP \
579 XTHAL_FAM_CACHED XCHAL_SEP \
580 XTHAL_FAM_EXCEPTION XCHAL_SEP \
581 XTHAL_FAM_CACHED XCHAL_SEP \
582 XTHAL_FAM_EXCEPTION XCHAL_SEP \
583 XTHAL_FAM_CACHED XCHAL_SEP \
584 XTHAL_FAM_EXCEPTION XCHAL_SEP \
585 XTHAL_FAM_CACHED XCHAL_SEP \
586 XTHAL_FAM_EXCEPTION XCHAL_SEP \
587 XTHAL_FAM_EXCEPTION XCHAL_SEP \
588 XTHAL_FAM_EXCEPTION XCHAL_SEP \
589 XTHAL_FAM_EXCEPTION
590#define XCHAL_LCA_LIST XTHAL_LAM_EXCEPTION XCHAL_SEP \
591 XTHAL_LAM_BYPASSG XCHAL_SEP \
592 XTHAL_LAM_EXCEPTION XCHAL_SEP \
593 XTHAL_LAM_BYPASSG XCHAL_SEP \
594 XTHAL_LAM_EXCEPTION XCHAL_SEP \
595 XTHAL_LAM_CACHED XCHAL_SEP \
596 XTHAL_LAM_EXCEPTION XCHAL_SEP \
597 XTHAL_LAM_CACHED XCHAL_SEP \
598 XTHAL_LAM_EXCEPTION XCHAL_SEP \
599 XTHAL_LAM_NACACHED XCHAL_SEP \
600 XTHAL_LAM_EXCEPTION XCHAL_SEP \
601 XTHAL_LAM_NACACHED XCHAL_SEP \
602 XTHAL_LAM_EXCEPTION XCHAL_SEP \
603 XTHAL_LAM_ISOLATE XCHAL_SEP \
604 XTHAL_LAM_EXCEPTION XCHAL_SEP \
605 XTHAL_LAM_CACHED
606#define XCHAL_SCA_LIST XTHAL_SAM_EXCEPTION XCHAL_SEP \
607 XTHAL_SAM_EXCEPTION XCHAL_SEP \
608 XTHAL_SAM_EXCEPTION XCHAL_SEP \
609 XTHAL_SAM_BYPASS XCHAL_SEP \
610 XTHAL_SAM_EXCEPTION XCHAL_SEP \
611 XTHAL_SAM_EXCEPTION XCHAL_SEP \
612 XTHAL_SAM_EXCEPTION XCHAL_SEP \
613 XTHAL_SAM_WRITETHRU XCHAL_SEP \
614 XTHAL_SAM_EXCEPTION XCHAL_SEP \
615 XTHAL_SAM_EXCEPTION XCHAL_SEP \
616 XTHAL_SAM_EXCEPTION XCHAL_SEP \
617 XTHAL_SAM_WRITETHRU XCHAL_SEP \
618 XTHAL_SAM_EXCEPTION XCHAL_SEP \
619 XTHAL_SAM_ISOLATE XCHAL_SEP \
620 XTHAL_SAM_EXCEPTION XCHAL_SEP \
621 XTHAL_SAM_WRITETHRU
622
623/* Test:
624 read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
625 read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
626 all: 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
627 fault: 0 + 2 + 4 + 6 + 8 + 10 + 12 + 14
628 r/w/x cached:
629 r/w/x dcached:
630 I-bypass: 1 + 3
631
632 load guard bit set: 1 + 3
633 load guard bit clr: 0 + 2 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
634 hit-cache r/w/x: 7 + 11
635
636 fams: 5
637 fams: 0 / 6 / 18 / 1 / 2
638 fams: Bypass / Isolate / Cached / Exception / NACached
639
640 MMU okay: yes
641*/
642
643
644/*----------------------------------------------------------------------
645 MMU
646 ----------------------------------------------------------------------*/
647
648/*
649 * General notes on MMU parameters.
650 *
651 * Terminology:
652 * ASID = address-space ID (acts as an "extension" of virtual addresses)
653 * VPN = virtual page number
654 * PPN = physical page number
655 * CA = encoded cache attribute (access modes)
656 * TLB = translation look-aside buffer (term is stretched somewhat here)
657 * I = instruction (fetch accesses)
658 * D = data (load and store accesses)
659 * way = each TLB (ITLB and DTLB) consists of a number of "ways"
660 * that simultaneously match the virtual address of an access;
661 * a TLB successfully translates a virtual address if exactly
662 * one way matches the vaddr; if none match, it is a miss;
663 * if multiple match, one gets a "multihit" exception;
664 * each way can be independently configured in terms of number of
665 * entries, page sizes, which fields are writable or constant, etc.
666 * set = group of contiguous ways with exactly identical parameters
667 * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE
668 * from the page table and storing it in one of the auto-refill ways;
669 * if this PTE load also misses, a miss exception is posted for s/w.
670 * min-wired = a "min-wired" way can be used to map a single (minimum-sized)
671 * page arbitrarily under program control; it has a single entry,
672 * is non-auto-refill (some other way(s) must be auto-refill),
673 * all its fields (VPN, PPN, ASID, CA) are all writable, and it
674 * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current
675 * restriction is that this be the only page size it supports).
676 *
677 * TLB way entries are virtually indexed.
678 * TLB ways that support multiple page sizes:
679 * - must have all writable VPN and PPN fields;
680 * - can only use one page size at any given time (eg. setup at startup),
681 * selected by the respective ITLBCFG or DTLBCFG special register,
682 * whose bits n*4+3 .. n*4 index the list of page sizes for way n
683 * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n);
684 * this list may be sparse for auto-refill ways because auto-refill
685 * ways have independent lists of supported page sizes sharing a
686 * common encoding with PTE entries; the encoding is the index into
687 * this list; unsupported sizes for a given way are zero in the list;
688 * selecting unsupported sizes results in undefined hardware behaviour;
689 * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition).
690 */
691
692#define XCHAL_HAVE_CACHEATTR 0 /* 1 if CACHEATTR register present, 0 if TLBs present instead */
693#define XCHAL_HAVE_TLBS 1 /* 1 if TLBs present, 0 if CACHEATTR present instead */
694#define XCHAL_HAVE_MMU XCHAL_HAVE_TLBS /* (DEPRECATED; use XCHAL_HAVE_TLBS instead; will be removed in future release) */
695#define XCHAL_HAVE_SPANNING_WAY 0 /* 1 if single way maps entire virtual address space in I+D */
696#define XCHAL_HAVE_IDENTITY_MAP 0 /* 1 if virtual addr == physical addr always, 0 otherwise */
697#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* 1 if have MMU that mimics a CACHEATTR config (CaMMU) */
698#define XCHAL_HAVE_XLT_CACHEATTR 0 /* 1 if have MMU that mimics a CACHEATTR config, but with translation (CaXltMMU) */
699
700#define XCHAL_MMU_ASID_BITS 8 /* number of bits in ASIDs (address space IDs) */
701#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */
702#define XCHAL_MMU_ASID_KERNEL 1 /* ASID value indicating kernel (ring 0) address space */
703#define XCHAL_MMU_RINGS 4 /* number of rings supported (1..4) */
704#define XCHAL_MMU_RING_BITS 2 /* number of bits needed to hold ring number */
705#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */
706#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */
707#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 12 /* max page size in a PTE structure (log2) */
708#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 12 /* min page size in a PTE structure (log2) */
709
710
711/*** Instruction TLB: ***/
712
713#define XCHAL_ITLB_WAY_BITS 3 /* number of bits holding the ways */
714#define XCHAL_ITLB_WAYS 7 /* number of ways (n-way set-associative TLB) */
715#define XCHAL_ITLB_ARF_WAYS 4 /* number of auto-refill ways */
716#define XCHAL_ITLB_SETS 4 /* number of sets (groups of ways with identical settings) */
717
718/* Way set to which each way belongs: */
719#define XCHAL_ITLB_WAY0_SET 0
720#define XCHAL_ITLB_WAY1_SET 0
721#define XCHAL_ITLB_WAY2_SET 0
722#define XCHAL_ITLB_WAY3_SET 0
723#define XCHAL_ITLB_WAY4_SET 1
724#define XCHAL_ITLB_WAY5_SET 2
725#define XCHAL_ITLB_WAY6_SET 3
726
727/* Ways sets that are used by hardware auto-refill (ARF): */
728#define XCHAL_ITLB_ARF_SETS 1 /* number of auto-refill sets */
729#define XCHAL_ITLB_ARF_SET0 0 /* index of n'th auto-refill set */
730
731/* Way sets that are "min-wired" (see terminology comment above): */
732#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */
733
734
735/* ITLB way set 0 (group of ways 0 thru 3): */
736#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */
737#define XCHAL_ITLB_SET0_WAYS 4 /* number of (contiguous) ways in this way set */
738#define XCHAL_ITLB_SET0_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
739#define XCHAL_ITLB_SET0_ENTRIES 4 /* number of entries in this way (always a power of 2) */
740#define XCHAL_ITLB_SET0_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
741#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */
742#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */
743#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
744#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
745#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
746 2^PAGESZ_BITS entries in list, unsupported entries are zero */
747#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
748#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
749#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
750#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
751#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
752#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
753#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
754#define XCHAL_ITLB_SET0_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
755
756/* ITLB way set 1 (group of ways 4 thru 4): */
757#define XCHAL_ITLB_SET1_WAY 4 /* index of first way in this way set */
758#define XCHAL_ITLB_SET1_WAYS 1 /* number of (contiguous) ways in this way set */
759#define XCHAL_ITLB_SET1_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
760#define XCHAL_ITLB_SET1_ENTRIES 4 /* number of entries in this way (always a power of 2) */
761#define XCHAL_ITLB_SET1_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
762#define XCHAL_ITLB_SET1_PAGESIZES 4 /* number of supported page sizes in this way */
763#define XCHAL_ITLB_SET1_PAGESZ_BITS 2 /* number of bits to encode the page size */
764#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MIN 20 /* log2(minimum supported page size) */
765#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MAX 26 /* log2(maximum supported page size) */
766#define XCHAL_ITLB_SET1_PAGESZ_LOG2_LIST 20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26 /* list of log2(page size)s, separated by XCHAL_SEP;
767 2^PAGESZ_BITS entries in list, unsupported entries are zero */
768#define XCHAL_ITLB_SET1_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
769#define XCHAL_ITLB_SET1_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
770#define XCHAL_ITLB_SET1_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
771#define XCHAL_ITLB_SET1_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
772#define XCHAL_ITLB_SET1_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
773#define XCHAL_ITLB_SET1_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
774#define XCHAL_ITLB_SET1_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
775#define XCHAL_ITLB_SET1_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
776
777/* ITLB way set 2 (group of ways 5 thru 5): */
778#define XCHAL_ITLB_SET2_WAY 5 /* index of first way in this way set */
779#define XCHAL_ITLB_SET2_WAYS 1 /* number of (contiguous) ways in this way set */
780#define XCHAL_ITLB_SET2_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
781#define XCHAL_ITLB_SET2_ENTRIES 2 /* number of entries in this way (always a power of 2) */
782#define XCHAL_ITLB_SET2_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
783#define XCHAL_ITLB_SET2_PAGESIZES 1 /* number of supported page sizes in this way */
784#define XCHAL_ITLB_SET2_PAGESZ_BITS 0 /* number of bits to encode the page size */
785#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MIN 27 /* log2(minimum supported page size) */
786#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MAX 27 /* log2(maximum supported page size) */
787#define XCHAL_ITLB_SET2_PAGESZ_LOG2_LIST 27 /* list of log2(page size)s, separated by XCHAL_SEP;
788 2^PAGESZ_BITS entries in list, unsupported entries are zero */
789#define XCHAL_ITLB_SET2_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
790#define XCHAL_ITLB_SET2_VPN_CONSTMASK 0xF0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
791#define XCHAL_ITLB_SET2_PPN_CONSTMASK 0xF8000000 /* constant PPN bits, including entry index bits; 0 if all writable */
792#define XCHAL_ITLB_SET2_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
793#define XCHAL_ITLB_SET2_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
794#define XCHAL_ITLB_SET2_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
795#define XCHAL_ITLB_SET2_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
796#define XCHAL_ITLB_SET2_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
797/* Constant ASID values for each entry of ITLB way set 2 (because ASID_CONSTMASK is non-zero): */
798#define XCHAL_ITLB_SET2_E0_ASID_CONST 0x01
799#define XCHAL_ITLB_SET2_E1_ASID_CONST 0x01
800/* Constant VPN values for each entry of ITLB way set 2 (because VPN_CONSTMASK is non-zero): */
801#define XCHAL_ITLB_SET2_E0_VPN_CONST 0xD0000000
802#define XCHAL_ITLB_SET2_E1_VPN_CONST 0xD8000000
803/* Constant PPN values for each entry of ITLB way set 2 (because PPN_CONSTMASK is non-zero): */
804#define XCHAL_ITLB_SET2_E0_PPN_CONST 0x00000000
805#define XCHAL_ITLB_SET2_E1_PPN_CONST 0x00000000
806/* Constant CA values for each entry of ITLB way set 2 (because CA_CONSTMASK is non-zero): */
807#define XCHAL_ITLB_SET2_E0_CA_CONST 0x07
808#define XCHAL_ITLB_SET2_E1_CA_CONST 0x03
809
810/* ITLB way set 3 (group of ways 6 thru 6): */
811#define XCHAL_ITLB_SET3_WAY 6 /* index of first way in this way set */
812#define XCHAL_ITLB_SET3_WAYS 1 /* number of (contiguous) ways in this way set */
813#define XCHAL_ITLB_SET3_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
814#define XCHAL_ITLB_SET3_ENTRIES 2 /* number of entries in this way (always a power of 2) */
815#define XCHAL_ITLB_SET3_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
816#define XCHAL_ITLB_SET3_PAGESIZES 1 /* number of supported page sizes in this way */
817#define XCHAL_ITLB_SET3_PAGESZ_BITS 0 /* number of bits to encode the page size */
818#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MIN 28 /* log2(minimum supported page size) */
819#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MAX 28 /* log2(maximum supported page size) */
820#define XCHAL_ITLB_SET3_PAGESZ_LOG2_LIST 28 /* list of log2(page size)s, separated by XCHAL_SEP;
821 2^PAGESZ_BITS entries in list, unsupported entries are zero */
822#define XCHAL_ITLB_SET3_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
823#define XCHAL_ITLB_SET3_VPN_CONSTMASK 0xE0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
824#define XCHAL_ITLB_SET3_PPN_CONSTMASK 0xF0000000 /* constant PPN bits, including entry index bits; 0 if all writable */
825#define XCHAL_ITLB_SET3_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
826#define XCHAL_ITLB_SET3_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
827#define XCHAL_ITLB_SET3_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
828#define XCHAL_ITLB_SET3_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
829#define XCHAL_ITLB_SET3_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
830/* Constant ASID values for each entry of ITLB way set 3 (because ASID_CONSTMASK is non-zero): */
831#define XCHAL_ITLB_SET3_E0_ASID_CONST 0x01
832#define XCHAL_ITLB_SET3_E1_ASID_CONST 0x01
833/* Constant VPN values for each entry of ITLB way set 3 (because VPN_CONSTMASK is non-zero): */
834#define XCHAL_ITLB_SET3_E0_VPN_CONST 0xE0000000
835#define XCHAL_ITLB_SET3_E1_VPN_CONST 0xF0000000
836/* Constant PPN values for each entry of ITLB way set 3 (because PPN_CONSTMASK is non-zero): */
837#define XCHAL_ITLB_SET3_E0_PPN_CONST 0xF0000000
838#define XCHAL_ITLB_SET3_E1_PPN_CONST 0xF0000000
839/* Constant CA values for each entry of ITLB way set 3 (because CA_CONSTMASK is non-zero): */
840#define XCHAL_ITLB_SET3_E0_CA_CONST 0x07
841#define XCHAL_ITLB_SET3_E1_CA_CONST 0x03
842
843/* Indexing macros: */
844#define _XCHAL_ITLB_SET(n,_what) XCHAL_ITLB_SET ## n ## _what
845#define XCHAL_ITLB_SET(n,what) _XCHAL_ITLB_SET(n, _ ## what )
846#define _XCHAL_ITLB_SET_E(n,i,_what) XCHAL_ITLB_SET ## n ## _E ## i ## _what
847#define XCHAL_ITLB_SET_E(n,i,what) _XCHAL_ITLB_SET_E(n,i, _ ## what )
848/*
849 * Example use: XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES)
850 * to get the value of XCHAL_ITLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
851 */
852
853
854/*** Data TLB: ***/
855
856#define XCHAL_DTLB_WAY_BITS 4 /* number of bits holding the ways */
857#define XCHAL_DTLB_WAYS 10 /* number of ways (n-way set-associative TLB) */
858#define XCHAL_DTLB_ARF_WAYS 4 /* number of auto-refill ways */
859#define XCHAL_DTLB_SETS 5 /* number of sets (groups of ways with identical settings) */
860
861/* Way set to which each way belongs: */
862#define XCHAL_DTLB_WAY0_SET 0
863#define XCHAL_DTLB_WAY1_SET 0
864#define XCHAL_DTLB_WAY2_SET 0
865#define XCHAL_DTLB_WAY3_SET 0
866#define XCHAL_DTLB_WAY4_SET 1
867#define XCHAL_DTLB_WAY5_SET 2
868#define XCHAL_DTLB_WAY6_SET 3
869#define XCHAL_DTLB_WAY7_SET 4
870#define XCHAL_DTLB_WAY8_SET 4
871#define XCHAL_DTLB_WAY9_SET 4
872
873/* Ways sets that are used by hardware auto-refill (ARF): */
874#define XCHAL_DTLB_ARF_SETS 1 /* number of auto-refill sets */
875#define XCHAL_DTLB_ARF_SET0 0 /* index of n'th auto-refill set */
876
877/* Way sets that are "min-wired" (see terminology comment above): */
878#define XCHAL_DTLB_MINWIRED_SETS 1 /* number of "min-wired" sets */
879#define XCHAL_DTLB_MINWIRED_SET0 4 /* index of n'th "min-wired" set */
880
881
882/* DTLB way set 0 (group of ways 0 thru 3): */
883#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */
884#define XCHAL_DTLB_SET0_WAYS 4 /* number of (contiguous) ways in this way set */
885#define XCHAL_DTLB_SET0_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
886#define XCHAL_DTLB_SET0_ENTRIES 4 /* number of entries in this way (always a power of 2) */
887#define XCHAL_DTLB_SET0_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
888#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */
889#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */
890#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
891#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
892#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
893 2^PAGESZ_BITS entries in list, unsupported entries are zero */
894#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
895#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
896#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
897#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
898#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
899#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
900#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
901#define XCHAL_DTLB_SET0_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
902
903/* DTLB way set 1 (group of ways 4 thru 4): */
904#define XCHAL_DTLB_SET1_WAY 4 /* index of first way in this way set */
905#define XCHAL_DTLB_SET1_WAYS 1 /* number of (contiguous) ways in this way set */
906#define XCHAL_DTLB_SET1_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
907#define XCHAL_DTLB_SET1_ENTRIES 4 /* number of entries in this way (always a power of 2) */
908#define XCHAL_DTLB_SET1_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
909#define XCHAL_DTLB_SET1_PAGESIZES 4 /* number of supported page sizes in this way */
910#define XCHAL_DTLB_SET1_PAGESZ_BITS 2 /* number of bits to encode the page size */
911#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MIN 20 /* log2(minimum supported page size) */
912#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MAX 26 /* log2(maximum supported page size) */
913#define XCHAL_DTLB_SET1_PAGESZ_LOG2_LIST 20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26 /* list of log2(page size)s, separated by XCHAL_SEP;
914 2^PAGESZ_BITS entries in list, unsupported entries are zero */
915#define XCHAL_DTLB_SET1_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
916#define XCHAL_DTLB_SET1_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
917#define XCHAL_DTLB_SET1_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
918#define XCHAL_DTLB_SET1_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
919#define XCHAL_DTLB_SET1_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
920#define XCHAL_DTLB_SET1_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
921#define XCHAL_DTLB_SET1_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
922#define XCHAL_DTLB_SET1_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
923
924/* DTLB way set 2 (group of ways 5 thru 5): */
925#define XCHAL_DTLB_SET2_WAY 5 /* index of first way in this way set */
926#define XCHAL_DTLB_SET2_WAYS 1 /* number of (contiguous) ways in this way set */
927#define XCHAL_DTLB_SET2_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
928#define XCHAL_DTLB_SET2_ENTRIES 2 /* number of entries in this way (always a power of 2) */
929#define XCHAL_DTLB_SET2_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
930#define XCHAL_DTLB_SET2_PAGESIZES 1 /* number of supported page sizes in this way */
931#define XCHAL_DTLB_SET2_PAGESZ_BITS 0 /* number of bits to encode the page size */
932#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MIN 27 /* log2(minimum supported page size) */
933#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MAX 27 /* log2(maximum supported page size) */
934#define XCHAL_DTLB_SET2_PAGESZ_LOG2_LIST 27 /* list of log2(page size)s, separated by XCHAL_SEP;
935 2^PAGESZ_BITS entries in list, unsupported entries are zero */
936#define XCHAL_DTLB_SET2_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
937#define XCHAL_DTLB_SET2_VPN_CONSTMASK 0xF0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
938#define XCHAL_DTLB_SET2_PPN_CONSTMASK 0xF8000000 /* constant PPN bits, including entry index bits; 0 if all writable */
939#define XCHAL_DTLB_SET2_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
940#define XCHAL_DTLB_SET2_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
941#define XCHAL_DTLB_SET2_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
942#define XCHAL_DTLB_SET2_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
943#define XCHAL_DTLB_SET2_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
944/* Constant ASID values for each entry of DTLB way set 2 (because ASID_CONSTMASK is non-zero): */
945#define XCHAL_DTLB_SET2_E0_ASID_CONST 0x01
946#define XCHAL_DTLB_SET2_E1_ASID_CONST 0x01
947/* Constant VPN values for each entry of DTLB way set 2 (because VPN_CONSTMASK is non-zero): */
948#define XCHAL_DTLB_SET2_E0_VPN_CONST 0xD0000000
949#define XCHAL_DTLB_SET2_E1_VPN_CONST 0xD8000000
950/* Constant PPN values for each entry of DTLB way set 2 (because PPN_CONSTMASK is non-zero): */
951#define XCHAL_DTLB_SET2_E0_PPN_CONST 0x00000000
952#define XCHAL_DTLB_SET2_E1_PPN_CONST 0x00000000
953/* Constant CA values for each entry of DTLB way set 2 (because CA_CONSTMASK is non-zero): */
954#define XCHAL_DTLB_SET2_E0_CA_CONST 0x07
955#define XCHAL_DTLB_SET2_E1_CA_CONST 0x03
956
957/* DTLB way set 3 (group of ways 6 thru 6): */
958#define XCHAL_DTLB_SET3_WAY 6 /* index of first way in this way set */
959#define XCHAL_DTLB_SET3_WAYS 1 /* number of (contiguous) ways in this way set */
960#define XCHAL_DTLB_SET3_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
961#define XCHAL_DTLB_SET3_ENTRIES 2 /* number of entries in this way (always a power of 2) */
962#define XCHAL_DTLB_SET3_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
963#define XCHAL_DTLB_SET3_PAGESIZES 1 /* number of supported page sizes in this way */
964#define XCHAL_DTLB_SET3_PAGESZ_BITS 0 /* number of bits to encode the page size */
965#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MIN 28 /* log2(minimum supported page size) */
966#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MAX 28 /* log2(maximum supported page size) */
967#define XCHAL_DTLB_SET3_PAGESZ_LOG2_LIST 28 /* list of log2(page size)s, separated by XCHAL_SEP;
968 2^PAGESZ_BITS entries in list, unsupported entries are zero */
969#define XCHAL_DTLB_SET3_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
970#define XCHAL_DTLB_SET3_VPN_CONSTMASK 0xE0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
971#define XCHAL_DTLB_SET3_PPN_CONSTMASK 0xF0000000 /* constant PPN bits, including entry index bits; 0 if all writable */
972#define XCHAL_DTLB_SET3_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
973#define XCHAL_DTLB_SET3_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
974#define XCHAL_DTLB_SET3_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
975#define XCHAL_DTLB_SET3_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
976#define XCHAL_DTLB_SET3_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
977/* Constant ASID values for each entry of DTLB way set 3 (because ASID_CONSTMASK is non-zero): */
978#define XCHAL_DTLB_SET3_E0_ASID_CONST 0x01
979#define XCHAL_DTLB_SET3_E1_ASID_CONST 0x01
980/* Constant VPN values for each entry of DTLB way set 3 (because VPN_CONSTMASK is non-zero): */
981#define XCHAL_DTLB_SET3_E0_VPN_CONST 0xE0000000
982#define XCHAL_DTLB_SET3_E1_VPN_CONST 0xF0000000
983/* Constant PPN values for each entry of DTLB way set 3 (because PPN_CONSTMASK is non-zero): */
984#define XCHAL_DTLB_SET3_E0_PPN_CONST 0xF0000000
985#define XCHAL_DTLB_SET3_E1_PPN_CONST 0xF0000000
986/* Constant CA values for each entry of DTLB way set 3 (because CA_CONSTMASK is non-zero): */
987#define XCHAL_DTLB_SET3_E0_CA_CONST 0x07
988#define XCHAL_DTLB_SET3_E1_CA_CONST 0x03
989
990/* DTLB way set 4 (group of ways 7 thru 9): */
991#define XCHAL_DTLB_SET4_WAY 7 /* index of first way in this way set */
992#define XCHAL_DTLB_SET4_WAYS 3 /* number of (contiguous) ways in this way set */
993#define XCHAL_DTLB_SET4_ENTRIES_LOG2 0 /* log2(number of entries in this way) */
994#define XCHAL_DTLB_SET4_ENTRIES 1 /* number of entries in this way (always a power of 2) */
995#define XCHAL_DTLB_SET4_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
996#define XCHAL_DTLB_SET4_PAGESIZES 1 /* number of supported page sizes in this way */
997#define XCHAL_DTLB_SET4_PAGESZ_BITS 0 /* number of bits to encode the page size */
998#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
999#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
1000#define XCHAL_DTLB_SET4_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
1001 2^PAGESZ_BITS entries in list, unsupported entries are zero */
1002#define XCHAL_DTLB_SET4_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
1003#define XCHAL_DTLB_SET4_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
1004#define XCHAL_DTLB_SET4_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
1005#define XCHAL_DTLB_SET4_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
1006#define XCHAL_DTLB_SET4_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
1007#define XCHAL_DTLB_SET4_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
1008#define XCHAL_DTLB_SET4_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
1009#define XCHAL_DTLB_SET4_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
1010
1011/* Indexing macros: */
1012#define _XCHAL_DTLB_SET(n,_what) XCHAL_DTLB_SET ## n ## _what
1013#define XCHAL_DTLB_SET(n,what) _XCHAL_DTLB_SET(n, _ ## what )
1014#define _XCHAL_DTLB_SET_E(n,i,_what) XCHAL_DTLB_SET ## n ## _E ## i ## _what
1015#define XCHAL_DTLB_SET_E(n,i,what) _XCHAL_DTLB_SET_E(n,i, _ ## what )
1016/*
1017 * Example use: XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES)
1018 * to get the value of XCHAL_DTLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
1019 */
1020
1021
1022/*
1023 * Determine whether we have a full MMU (with Page Table and Protection)
1024 * usable for an MMU-based OS:
1025 */
1026#if XCHAL_HAVE_TLBS && !XCHAL_HAVE_SPANNING_WAY && XCHAL_ITLB_ARF_WAYS > 0 && XCHAL_DTLB_ARF_WAYS > 0 && XCHAL_MMU_RINGS >= 2
1027# define XCHAL_HAVE_PTP_MMU 1 /* have full MMU (with page table [autorefill] and protection) */
1028#else
1029# define XCHAL_HAVE_PTP_MMU 0 /* don't have full MMU */
1030#endif
1031
1032/*
1033 * For full MMUs, report kernel RAM segment and kernel I/O segment static page mappings:
1034 */
1035#if XCHAL_HAVE_PTP_MMU
1036#define XCHAL_KSEG_CACHED_VADDR 0xD0000000 /* virt.addr of kernel RAM cached static map */
1037#define XCHAL_KSEG_CACHED_PADDR 0x00000000 /* phys.addr of kseg_cached */
1038#define XCHAL_KSEG_CACHED_SIZE 0x08000000 /* size in bytes of kseg_cached (assumed power of 2!!!) */
1039#define XCHAL_KSEG_BYPASS_VADDR 0xD8000000 /* virt.addr of kernel RAM bypass (uncached) static map */
1040#define XCHAL_KSEG_BYPASS_PADDR 0x00000000 /* phys.addr of kseg_bypass */
1041#define XCHAL_KSEG_BYPASS_SIZE 0x08000000 /* size in bytes of kseg_bypass (assumed power of 2!!!) */
1042
1043#define XCHAL_KIO_CACHED_VADDR 0xE0000000 /* virt.addr of kernel I/O cached static map */
1044#define XCHAL_KIO_CACHED_PADDR 0xF0000000 /* phys.addr of kio_cached */
1045#define XCHAL_KIO_CACHED_SIZE 0x10000000 /* size in bytes of kio_cached (assumed power of 2!!!) */
1046#define XCHAL_KIO_BYPASS_VADDR 0xF0000000 /* virt.addr of kernel I/O bypass (uncached) static map */
1047#define XCHAL_KIO_BYPASS_PADDR 0xF0000000 /* phys.addr of kio_bypass */
1048#define XCHAL_KIO_BYPASS_SIZE 0x10000000 /* size in bytes of kio_bypass (assumed power of 2!!!) */
1049
1050#define XCHAL_SEG_MAPPABLE_VADDR 0x00000000 /* start of largest non-static-mapped virtual addr area */
1051#define XCHAL_SEG_MAPPABLE_SIZE 0xD0000000 /* size in bytes of " */
1052/* define XCHAL_SEG_MAPPABLE2_xxx if more areas present, sorted in order of descending size. */
1053#endif
1054
1055
1056/*----------------------------------------------------------------------
1057 MISC
1058 ----------------------------------------------------------------------*/
1059
1060#define XCHAL_NUM_WRITEBUFFER_ENTRIES 4 /* number of write buffer entries */
1061
1062#define XCHAL_CORE_ID "linux_be" /* configuration's alphanumeric core identifier
1063 (CoreID) set in the Xtensa Processor Generator */
1064
1065#define XCHAL_BUILD_UNIQUE_ID 0x00003256 /* software build-unique ID (22-bit) */
1066
1067/* These definitions describe the hardware targeted by this software: */
1068#define XCHAL_HW_CONFIGID0 0xC103D1FF /* config ID reg 0 value (upper 32 of 64 bits) */
1069#define XCHAL_HW_CONFIGID1 0x00803256 /* config ID reg 1 value (lower 32 of 64 bits) */
1070#define XCHAL_CONFIGID0 XCHAL_HW_CONFIGID0 /* for backward compatibility only -- don't use! */
1071#define XCHAL_CONFIGID1 XCHAL_HW_CONFIGID1 /* for backward compatibility only -- don't use! */
1072#define XCHAL_HW_RELEASE_MAJOR 1050 /* major release of targeted hardware */
1073#define XCHAL_HW_RELEASE_MINOR 1 /* minor release of targeted hardware */
1074#define XCHAL_HW_RELEASE_NAME "T1050.1" /* full release name of targeted hardware */
1075#define XTHAL_HW_REL_T1050 1
1076#define XTHAL_HW_REL_T1050_1 1
1077#define XCHAL_HW_CONFIGID_RELIABLE 1
1078
1079
1080/*
1081 * Miscellaneous special register fields:
1082 */
1083
1084
1085/* DBREAKC (special register number 160): */
1086#define XCHAL_DBREAKC_VALIDMASK 0xC000003F /* bits of DBREAKC that are defined */
1087/* MASK field: */
1088#define XCHAL_DBREAKC_MASK_BITS 6 /* number of bits in MASK field */
1089#define XCHAL_DBREAKC_MASK_NUM 64 /* max number of possible causes (2^bits) */
1090#define XCHAL_DBREAKC_MASK_SHIFT 0 /* position of MASK bits in DBREAKC, starting from lsbit */
1091#define XCHAL_DBREAKC_MASK_MASK 0x0000003F /* mask of bits in MASK field of DBREAKC */
1092/* LOADBREAK field: */
1093#define XCHAL_DBREAKC_LOADBREAK_BITS 1 /* number of bits in LOADBREAK field */
1094#define XCHAL_DBREAKC_LOADBREAK_NUM 2 /* max number of possible causes (2^bits) */
1095#define XCHAL_DBREAKC_LOADBREAK_SHIFT 30 /* position of LOADBREAK bits in DBREAKC, starting from lsbit */
1096#define XCHAL_DBREAKC_LOADBREAK_MASK 0x40000000 /* mask of bits in LOADBREAK field of DBREAKC */
1097/* STOREBREAK field: */
1098#define XCHAL_DBREAKC_STOREBREAK_BITS 1 /* number of bits in STOREBREAK field */
1099#define XCHAL_DBREAKC_STOREBREAK_NUM 2 /* max number of possible causes (2^bits) */
1100#define XCHAL_DBREAKC_STOREBREAK_SHIFT 31 /* position of STOREBREAK bits in DBREAKC, starting from lsbit */
1101#define XCHAL_DBREAKC_STOREBREAK_MASK 0x80000000 /* mask of bits in STOREBREAK field of DBREAKC */
1102
1103/* PS (special register number 230): */
1104#define XCHAL_PS_VALIDMASK 0x00070FFF /* bits of PS that are defined */
1105/* INTLEVEL field: */
1106#define XCHAL_PS_INTLEVEL_BITS 4 /* number of bits in INTLEVEL field */
1107#define XCHAL_PS_INTLEVEL_NUM 16 /* max number of possible causes (2^bits) */
1108#define XCHAL_PS_INTLEVEL_SHIFT 0 /* position of INTLEVEL bits in PS, starting from lsbit */
1109#define XCHAL_PS_INTLEVEL_MASK 0x0000000F /* mask of bits in INTLEVEL field of PS */
1110/* EXCM field: */
1111#define XCHAL_PS_EXCM_BITS 1 /* number of bits in EXCM field */
1112#define XCHAL_PS_EXCM_NUM 2 /* max number of possible causes (2^bits) */
1113#define XCHAL_PS_EXCM_SHIFT 4 /* position of EXCM bits in PS, starting from lsbit */
1114#define XCHAL_PS_EXCM_MASK 0x00000010 /* mask of bits in EXCM field of PS */
1115/* PROGSTACK field: */
1116#define XCHAL_PS_PROGSTACK_BITS 1 /* number of bits in PROGSTACK field */
1117#define XCHAL_PS_PROGSTACK_NUM 2 /* max number of possible causes (2^bits) */
1118#define XCHAL_PS_PROGSTACK_SHIFT 5 /* position of PROGSTACK bits in PS, starting from lsbit */
1119#define XCHAL_PS_PROGSTACK_MASK 0x00000020 /* mask of bits in PROGSTACK field of PS */
1120/* RING field: */
1121#define XCHAL_PS_RING_BITS 2 /* number of bits in RING field */
1122#define XCHAL_PS_RING_NUM 4 /* max number of possible causes (2^bits) */
1123#define XCHAL_PS_RING_SHIFT 6 /* position of RING bits in PS, starting from lsbit */
1124#define XCHAL_PS_RING_MASK 0x000000C0 /* mask of bits in RING field of PS */
1125/* OWB field: */
1126#define XCHAL_PS_OWB_BITS 4 /* number of bits in OWB field */
1127#define XCHAL_PS_OWB_NUM 16 /* max number of possible causes (2^bits) */
1128#define XCHAL_PS_OWB_SHIFT 8 /* position of OWB bits in PS, starting from lsbit */
1129#define XCHAL_PS_OWB_MASK 0x00000F00 /* mask of bits in OWB field of PS */
1130/* CALLINC field: */
1131#define XCHAL_PS_CALLINC_BITS 2 /* number of bits in CALLINC field */
1132#define XCHAL_PS_CALLINC_NUM 4 /* max number of possible causes (2^bits) */
1133#define XCHAL_PS_CALLINC_SHIFT 16 /* position of CALLINC bits in PS, starting from lsbit */
1134#define XCHAL_PS_CALLINC_MASK 0x00030000 /* mask of bits in CALLINC field of PS */
1135/* WOE field: */
1136#define XCHAL_PS_WOE_BITS 1 /* number of bits in WOE field */
1137#define XCHAL_PS_WOE_NUM 2 /* max number of possible causes (2^bits) */
1138#define XCHAL_PS_WOE_SHIFT 18 /* position of WOE bits in PS, starting from lsbit */
1139#define XCHAL_PS_WOE_MASK 0x00040000 /* mask of bits in WOE field of PS */
1140
1141/* EXCCAUSE (special register number 232): */
1142#define XCHAL_EXCCAUSE_VALIDMASK 0x0000003F /* bits of EXCCAUSE that are defined */
1143/* EXCCAUSE field: */
1144#define XCHAL_EXCCAUSE_BITS 6 /* number of bits in EXCCAUSE register */
1145#define XCHAL_EXCCAUSE_NUM 64 /* max number of possible causes (2^bits) */
1146#define XCHAL_EXCCAUSE_SHIFT 0 /* position of EXCCAUSE bits in register, starting from lsbit */
1147#define XCHAL_EXCCAUSE_MASK 0x0000003F /* mask of bits in EXCCAUSE register */
1148
1149/* DEBUGCAUSE (special register number 233): */
1150#define XCHAL_DEBUGCAUSE_VALIDMASK 0x0000003F /* bits of DEBUGCAUSE that are defined */
1151/* ICOUNT field: */
1152#define XCHAL_DEBUGCAUSE_ICOUNT_BITS 1 /* number of bits in ICOUNT field */
1153#define XCHAL_DEBUGCAUSE_ICOUNT_NUM 2 /* max number of possible causes (2^bits) */
1154#define XCHAL_DEBUGCAUSE_ICOUNT_SHIFT 0 /* position of ICOUNT bits in DEBUGCAUSE, starting from lsbit */
1155#define XCHAL_DEBUGCAUSE_ICOUNT_MASK 0x00000001 /* mask of bits in ICOUNT field of DEBUGCAUSE */
1156/* IBREAK field: */
1157#define XCHAL_DEBUGCAUSE_IBREAK_BITS 1 /* number of bits in IBREAK field */
1158#define XCHAL_DEBUGCAUSE_IBREAK_NUM 2 /* max number of possible causes (2^bits) */
1159#define XCHAL_DEBUGCAUSE_IBREAK_SHIFT 1 /* position of IBREAK bits in DEBUGCAUSE, starting from lsbit */
1160#define XCHAL_DEBUGCAUSE_IBREAK_MASK 0x00000002 /* mask of bits in IBREAK field of DEBUGCAUSE */
1161/* DBREAK field: */
1162#define XCHAL_DEBUGCAUSE_DBREAK_BITS 1 /* number of bits in DBREAK field */
1163#define XCHAL_DEBUGCAUSE_DBREAK_NUM 2 /* max number of possible causes (2^bits) */
1164#define XCHAL_DEBUGCAUSE_DBREAK_SHIFT 2 /* position of DBREAK bits in DEBUGCAUSE, starting from lsbit */
1165#define XCHAL_DEBUGCAUSE_DBREAK_MASK 0x00000004 /* mask of bits in DBREAK field of DEBUGCAUSE */
1166/* BREAK field: */
1167#define XCHAL_DEBUGCAUSE_BREAK_BITS 1 /* number of bits in BREAK field */
1168#define XCHAL_DEBUGCAUSE_BREAK_NUM 2 /* max number of possible causes (2^bits) */
1169#define XCHAL_DEBUGCAUSE_BREAK_SHIFT 3 /* position of BREAK bits in DEBUGCAUSE, starting from lsbit */
1170#define XCHAL_DEBUGCAUSE_BREAK_MASK 0x00000008 /* mask of bits in BREAK field of DEBUGCAUSE */
1171/* BREAKN field: */
1172#define XCHAL_DEBUGCAUSE_BREAKN_BITS 1 /* number of bits in BREAKN field */
1173#define XCHAL_DEBUGCAUSE_BREAKN_NUM 2 /* max number of possible causes (2^bits) */
1174#define XCHAL_DEBUGCAUSE_BREAKN_SHIFT 4 /* position of BREAKN bits in DEBUGCAUSE, starting from lsbit */
1175#define XCHAL_DEBUGCAUSE_BREAKN_MASK 0x00000010 /* mask of bits in BREAKN field of DEBUGCAUSE */
1176/* DEBUGINT field: */
1177#define XCHAL_DEBUGCAUSE_DEBUGINT_BITS 1 /* number of bits in DEBUGINT field */
1178#define XCHAL_DEBUGCAUSE_DEBUGINT_NUM 2 /* max number of possible causes (2^bits) */
1179#define XCHAL_DEBUGCAUSE_DEBUGINT_SHIFT 5 /* position of DEBUGINT bits in DEBUGCAUSE, starting from lsbit */
1180#define XCHAL_DEBUGCAUSE_DEBUGINT_MASK 0x00000020 /* mask of bits in DEBUGINT field of DEBUGCAUSE */
1181
1182
1183
1184/*----------------------------------------------------------------------
1185 ISA
1186 ----------------------------------------------------------------------*/
1187
1188#define XCHAL_HAVE_DENSITY 1 /* 1 if density option configured, 0 otherwise */
1189#define XCHAL_HAVE_LOOPS 1 /* 1 if zero-overhead loops option configured, 0 otherwise */
1190/* Misc instructions: */
1191#define XCHAL_HAVE_NSA 0 /* 1 if NSA/NSAU instructions option configured, 0 otherwise */
1192#define XCHAL_HAVE_MINMAX 0 /* 1 if MIN/MAX instructions option configured, 0 otherwise */
1193#define XCHAL_HAVE_SEXT 0 /* 1 if sign-extend instruction option configured, 0 otherwise */
1194#define XCHAL_HAVE_CLAMPS 0 /* 1 if CLAMPS instruction option configured, 0 otherwise */
1195#define XCHAL_HAVE_MAC16 0 /* 1 if MAC16 option configured, 0 otherwise */
1196#define XCHAL_HAVE_MUL16 0 /* 1 if 16-bit integer multiply option configured, 0 otherwise */
1197/*#define XCHAL_HAVE_POPC 0*/ /* 1 if CRC instruction option configured, 0 otherwise */
1198/*#define XCHAL_HAVE_CRC 0*/ /* 1 if POPC instruction option configured, 0 otherwise */
1199
1200#define XCHAL_HAVE_SPECULATION 0 /* 1 if speculation option configured, 0 otherwise */
1201/*#define XCHAL_HAVE_MP_SYNC 0*/ /* 1 if multiprocessor sync. option configured, 0 otherwise */
1202#define XCHAL_HAVE_PRID 0 /* 1 if processor ID register configured, 0 otherwise */
1203
1204#define XCHAL_NUM_MISC_REGS 2 /* number of miscellaneous registers (0..4) */
1205
1206/* These relate a bit more to TIE: */
1207#define XCHAL_HAVE_BOOLEANS 0 /* 1 if booleans option configured, 0 otherwise */
1208#define XCHAL_HAVE_MUL32 0 /* 1 if 32-bit integer multiply option configured, 0 otherwise */
1209#define XCHAL_HAVE_MUL32_HIGH 0 /* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
1210#define XCHAL_HAVE_FP 0 /* 1 if floating point option configured, 0 otherwise */
1211
1212
1213/*----------------------------------------------------------------------
1214 DERIVED
1215 ----------------------------------------------------------------------*/
1216
1217#if XCHAL_HAVE_BE
1218#define XCHAL_INST_ILLN 0xD60F /* 2-byte illegal instruction, msb-first */
1219#define XCHAL_INST_ILLN_BYTE0 0xD6 /* 2-byte illegal instruction, 1st byte */
1220#define XCHAL_INST_ILLN_BYTE1 0x0F /* 2-byte illegal instruction, 2nd byte */
1221#else
1222#define XCHAL_INST_ILLN 0xF06D /* 2-byte illegal instruction, lsb-first */
1223#define XCHAL_INST_ILLN_BYTE0 0x6D /* 2-byte illegal instruction, 1st byte */
1224#define XCHAL_INST_ILLN_BYTE1 0xF0 /* 2-byte illegal instruction, 2nd byte */
1225#endif
1226/* Belongs in xtensa/hal.h: */
1227#define XTHAL_INST_ILL 0x000000 /* 3-byte illegal instruction */
1228
1229
1230/*
1231 * Because information as to exactly which hardware release is targeted
1232 * by a given software build is not always available, compile-time HAL
1233 * Hardware-Release "_AT" macros are fuzzy (return 0, 1, or XCHAL_MAYBE):
1234 */
1235#ifndef XCHAL_HW_RELEASE_MAJOR
1236# define XCHAL_HW_CONFIGID_RELIABLE 0
1237#endif
1238#if XCHAL_HW_CONFIGID_RELIABLE
1239# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) (XTHAL_REL_LE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
1240# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) (XTHAL_REL_GE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
1241# define XCHAL_HW_RELEASE_AT(major,minor) (XTHAL_REL_EQ( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
1242# define XCHAL_HW_RELEASE_MAJOR_AT(major) ((XCHAL_HW_RELEASE_MAJOR == (major)) ? 1 : 0)
1243#else
1244# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) ( ((major) < 1040 && XCHAL_HAVE_XEA2) ? 0 \
1245 : ((major) > 1050 && XCHAL_HAVE_XEA1) ? 1 \
1246 : XTHAL_MAYBE )
1247# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) ( ((major) >= 2000 && XCHAL_HAVE_XEA1) ? 0 \
1248 : (XTHAL_REL_LE(major,minor, 1040,0) && XCHAL_HAVE_XEA2) ? 1 \
1249 : XTHAL_MAYBE )
1250# define XCHAL_HW_RELEASE_AT(major,minor) ( (((major) < 1040 && XCHAL_HAVE_XEA2) || \
1251 ((major) >= 2000 && XCHAL_HAVE_XEA1)) ? 0 : XTHAL_MAYBE)
1252# define XCHAL_HW_RELEASE_MAJOR_AT(major) XCHAL_HW_RELEASE_AT(major,0)
1253#endif
1254
1255/*
1256 * Specific errata:
1257 */
1258
1259/*
1260 * Erratum T1020.H13, T1030.H7, T1040.H10, T1050.H4 (fixed in T1040.3 and T1050.1;
1261 * relevant only in XEA1, kernel-vector mode, level-one interrupts and overflows enabled):
1262 */
1263#define XCHAL_MAYHAVE_ERRATUM_XEA1KWIN (XCHAL_HAVE_XEA1 && \
1264 (XCHAL_HW_RELEASE_AT_OR_BELOW(1040,2) != 0 \
1265 || XCHAL_HW_RELEASE_AT(1050,0)))
1266
1267
1268
1269#endif /*XTENSA_CONFIG_CORE_H*/
1270
diff --git a/include/asm-xtensa/xtensa/config-linux_be/defs.h b/include/asm-xtensa/xtensa/config-linux_be/defs.h
new file mode 100644
index 0000000000..f7c58b2733
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/defs.h
@@ -0,0 +1,270 @@
1/* Definitions for Xtensa instructions, types, and protos. */
2
3/*
4 * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of version 2.1 of the GNU Lesser General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *
14 * Further, this software is distributed without any warranty that it is
15 * free of the rightful claim of any third person regarding infringement
16 * or the like. Any license provided herein, whether implied or
17 * otherwise, applies only to this software file. Patent licenses, if
18 * any, provided herein do not apply to combinations of this program with
19 * other software, or any other product whatsoever.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
24 * USA.
25 */
26
27/* Do not modify. This is automatically generated.*/
28
29#ifndef _XTENSA_BASE_HEADER
30#define _XTENSA_BASE_HEADER
31
32#ifdef __XTENSA__
33#if defined(__GNUC__) && !defined(__XCC__)
34
35#define L8UI_ASM(arr, ars, imm) { \
36 __asm__ volatile("l8ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
37}
38
39#define XT_L8UI(ars, imm) \
40({ \
41 unsigned char _arr; \
42 const unsigned char *_ars = ars; \
43 L8UI_ASM(_arr, _ars, imm); \
44 _arr; \
45})
46
47#define L16UI_ASM(arr, ars, imm) { \
48 __asm__ volatile("l16ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
49}
50
51#define XT_L16UI(ars, imm) \
52({ \
53 unsigned short _arr; \
54 const unsigned short *_ars = ars; \
55 L16UI_ASM(_arr, _ars, imm); \
56 _arr; \
57})
58
59#define L16SI_ASM(arr, ars, imm) {\
60 __asm__ volatile("l16si %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
61}
62
63#define XT_L16SI(ars, imm) \
64({ \
65 signed short _arr; \
66 const signed short *_ars = ars; \
67 L16SI_ASM(_arr, _ars, imm); \
68 _arr; \
69})
70
71#define L32I_ASM(arr, ars, imm) { \
72 __asm__ volatile("l32i %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
73}
74
75#define XT_L32I(ars, imm) \
76({ \
77 unsigned _arr; \
78 const unsigned *_ars = ars; \
79 L32I_ASM(_arr, _ars, imm); \
80 _arr; \
81})
82
83#define S8I_ASM(arr, ars, imm) {\
84 __asm__ volatile("s8i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
85}
86
87#define XT_S8I(arr, ars, imm) \
88({ \
89 signed char _arr = arr; \
90 const signed char *_ars = ars; \
91 S8I_ASM(_arr, _ars, imm); \
92})
93
94#define S16I_ASM(arr, ars, imm) {\
95 __asm__ volatile("s16i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
96}
97
98#define XT_S16I(arr, ars, imm) \
99({ \
100 signed short _arr = arr; \
101 const signed short *_ars = ars; \
102 S16I_ASM(_arr, _ars, imm); \
103})
104
105#define S32I_ASM(arr, ars, imm) { \
106 __asm__ volatile("s32i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
107}
108
109#define XT_S32I(arr, ars, imm) \
110({ \
111 signed int _arr = arr; \
112 const signed int *_ars = ars; \
113 S32I_ASM(_arr, _ars, imm); \
114})
115
116#define ADDI_ASM(art, ars, imm) {\
117 __asm__ ("addi %0, %1, %2" : "=a" (art) : "a" (ars), "i" (imm)); \
118}
119
120#define XT_ADDI(ars, imm) \
121({ \
122 unsigned _art; \
123 unsigned _ars = ars; \
124 ADDI_ASM(_art, _ars, imm); \
125 _art; \
126})
127
128#define ABS_ASM(arr, art) {\
129 __asm__ ("abs %0, %1" : "=a" (arr) : "a" (art)); \
130}
131
132#define XT_ABS(art) \
133({ \
134 unsigned _arr; \
135 signed _art = art; \
136 ABS_ASM(_arr, _art); \
137 _arr; \
138})
139
140/* Note: In the following macros that reference SAR, the magic "state"
141 register is used to capture the dependency on SAR. This is because
142 SAR is a 5-bit register and thus there are no C types that can be
143 used to represent it. It doesn't appear that the SAR register is
144 even relevant to GCC, but it is marked as "clobbered" just in
145 case. */
146
147#define SRC_ASM(arr, ars, art) {\
148 register int _xt_sar __asm__ ("state"); \
149 __asm__ ("src %0, %1, %2" \
150 : "=a" (arr) : "a" (ars), "a" (art), "t" (_xt_sar)); \
151}
152
153#define XT_SRC(ars, art) \
154({ \
155 unsigned _arr; \
156 unsigned _ars = ars; \
157 unsigned _art = art; \
158 SRC_ASM(_arr, _ars, _art); \
159 _arr; \
160})
161
162#define SSR_ASM(ars) {\
163 register int _xt_sar __asm__ ("state"); \
164 __asm__ ("ssr %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
165}
166
167#define XT_SSR(ars) \
168({ \
169 unsigned _ars = ars; \
170 SSR_ASM(_ars); \
171})
172
173#define SSL_ASM(ars) {\
174 register int _xt_sar __asm__ ("state"); \
175 __asm__ ("ssl %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
176}
177
178#define XT_SSL(ars) \
179({ \
180 unsigned _ars = ars; \
181 SSL_ASM(_ars); \
182})
183
184#define SSA8B_ASM(ars) {\
185 register int _xt_sar __asm__ ("state"); \
186 __asm__ ("ssa8b %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
187}
188
189#define XT_SSA8B(ars) \
190({ \
191 unsigned _ars = ars; \
192 SSA8B_ASM(_ars); \
193})
194
195#define SSA8L_ASM(ars) {\
196 register int _xt_sar __asm__ ("state"); \
197 __asm__ ("ssa8l %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
198}
199
200#define XT_SSA8L(ars) \
201({ \
202 unsigned _ars = ars; \
203 SSA8L_ASM(_ars); \
204})
205
206#define SSAI_ASM(imm) {\
207 register int _xt_sar __asm__ ("state"); \
208 __asm__ ("ssai %1" : "=t" (_xt_sar) : "i" (imm) : "sar"); \
209}
210
211#define XT_SSAI(imm) \
212({ \
213 SSAI_ASM(imm); \
214})
215
216
217
218
219
220
221
222
223#endif /* __GNUC__ && !__XCC__ */
224
225#ifdef __XCC__
226
227/* Core load/store instructions */
228extern unsigned char _TIE_L8UI(const unsigned char * ars, immediate imm);
229extern unsigned short _TIE_L16UI(const unsigned short * ars, immediate imm);
230extern signed short _TIE_L16SI(const signed short * ars, immediate imm);
231extern unsigned _TIE_L32I(const unsigned * ars, immediate imm);
232extern void _TIE_S8I(unsigned char arr, unsigned char * ars, immediate imm);
233extern void _TIE_S16I(unsigned short arr, unsigned short * ars, immediate imm);
234extern void _TIE_S32I(unsigned arr, unsigned * ars, immediate imm);
235
236#define XT_L8UI _TIE_L8UI
237#define XT_L16UI _TIE_L16UI
238#define XT_L16SI _TIE_L16SI
239#define XT_L32I _TIE_L32I
240#define XT_S8I _TIE_S8I
241#define XT_S16I _TIE_S16I
242#define XT_S32I _TIE_S32I
243
244/* Add-immediate instruction */
245extern unsigned _TIE_ADDI(unsigned ars, immediate imm);
246#define XT_ADDI _TIE_ADDI
247
248/* Absolute value instruction */
249extern unsigned _TIE_ABS(int art);
250#define XT_ABS _TIE_ABS
251
252/* funnel shift instructions */
253extern unsigned _TIE_SRC(unsigned ars, unsigned art);
254#define XT_SRC _TIE_SRC
255extern void _TIE_SSR(unsigned ars);
256#define XT_SSR _TIE_SSR
257extern void _TIE_SSL(unsigned ars);
258#define XT_SSL _TIE_SSL
259extern void _TIE_SSA8B(unsigned ars);
260#define XT_SSA8B _TIE_SSA8B
261extern void _TIE_SSA8L(unsigned ars);
262#define XT_SSA8L _TIE_SSA8L
263extern void _TIE_SSAI(immediate imm);
264#define XT_SSAI _TIE_SSAI
265
266
267#endif /* __XCC__ */
268
269#endif /* __XTENSA__ */
270#endif /* !_XTENSA_BASE_HEADER */
diff --git a/include/asm-xtensa/xtensa/config-linux_be/specreg.h b/include/asm-xtensa/xtensa/config-linux_be/specreg.h
new file mode 100644
index 0000000000..fa4106aa9a
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/specreg.h
@@ -0,0 +1,99 @@
1/*
2 * Xtensa Special Register symbolic names
3 */
4
5/* $Id: specreg.h,v 1.2 2003/03/07 19:15:18 joetaylor Exp $ */
6
7/*
8 * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2.1 of the GNU Lesser General Public
12 * License as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it would be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this program; if not, write the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
28 * USA.
29 */
30
31#ifndef XTENSA_SPECREG_H
32#define XTENSA_SPECREG_H
33
34/* Include these special register bitfield definitions, for historical reasons: */
35#include <xtensa/corebits.h>
36
37
38/* Special registers: */
39#define LBEG 0
40#define LEND 1
41#define LCOUNT 2
42#define SAR 3
43#define WINDOWBASE 72
44#define WINDOWSTART 73
45#define PTEVADDR 83
46#define RASID 90
47#define ITLBCFG 91
48#define DTLBCFG 92
49#define IBREAKENABLE 96
50#define DDR 104
51#define IBREAKA_0 128
52#define IBREAKA_1 129
53#define DBREAKA_0 144
54#define DBREAKA_1 145
55#define DBREAKC_0 160
56#define DBREAKC_1 161
57#define EPC_1 177
58#define EPC_2 178
59#define EPC_3 179
60#define EPC_4 180
61#define DEPC 192
62#define EPS_2 194
63#define EPS_3 195
64#define EPS_4 196
65#define EXCSAVE_1 209
66#define EXCSAVE_2 210
67#define EXCSAVE_3 211
68#define EXCSAVE_4 212
69#define INTERRUPT 226
70#define INTENABLE 228
71#define PS 230
72#define EXCCAUSE 232
73#define DEBUGCAUSE 233
74#define CCOUNT 234
75#define ICOUNT 236
76#define ICOUNTLEVEL 237
77#define EXCVADDR 238
78#define CCOMPARE_0 240
79#define CCOMPARE_1 241
80#define CCOMPARE_2 242
81#define MISC_REG_0 244
82#define MISC_REG_1 245
83
84/* Special cases (bases of special register series): */
85#define IBREAKA 128
86#define DBREAKA 144
87#define DBREAKC 160
88#define EPC 176
89#define EPS 192
90#define EXCSAVE 208
91#define CCOMPARE 240
92
93/* Special names for read-only and write-only interrupt registers: */
94#define INTREAD 226
95#define INTSET 226
96#define INTCLEAR 227
97
98#endif /* XTENSA_SPECREG_H */
99
diff --git a/include/asm-xtensa/xtensa/config-linux_be/system.h b/include/asm-xtensa/xtensa/config-linux_be/system.h
new file mode 100644
index 0000000000..cf9d4d308e
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/system.h
@@ -0,0 +1,198 @@
1/*
2 * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration
3 *
4 * NOTE: The location and contents of this file are highly subject to change.
5 *
6 * Source for configuration-independent binaries (which link in a
7 * configuration-specific HAL library) must NEVER include this file.
8 * The HAL itself has historically included this file in some instances,
9 * but this is not appropriate either, because the HAL is meant to be
10 * core-specific but system independent.
11 */
12
13/*
14 * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of version 2.1 of the GNU Lesser General Public
18 * License as published by the Free Software Foundation.
19 *
20 * This program is distributed in the hope that it would be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 *
24 * Further, this software is distributed without any warranty that it is
25 * free of the rightful claim of any third person regarding infringement
26 * or the like. Any license provided herein, whether implied or
27 * otherwise, applies only to this software file. Patent licenses, if
28 * any, provided herein do not apply to combinations of this program with
29 * other software, or any other product whatsoever.
30 *
31 * You should have received a copy of the GNU Lesser General Public
32 * License along with this program; if not, write the Free Software
33 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
34 * USA.
35 */
36
37
38#ifndef XTENSA_CONFIG_SYSTEM_H
39#define XTENSA_CONFIG_SYSTEM_H
40
41/*#include <xtensa/hal.h>*/
42
43
44
45/*----------------------------------------------------------------------
46 DEVICE ADDRESSES
47 ----------------------------------------------------------------------*/
48
49/*
50 * Strange place to find these, but the configuration GUI
51 * allows moving these around to account for various core
52 * configurations. Specific boards (and their BSP software)
53 * will have specific meanings for these components.
54 */
55
56/* I/O Block areas: */
57#define XSHAL_IOBLOCK_CACHED_VADDR 0xE0000000
58#define XSHAL_IOBLOCK_CACHED_PADDR 0xF0000000
59#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000
60
61#define XSHAL_IOBLOCK_BYPASS_VADDR 0xF0000000
62#define XSHAL_IOBLOCK_BYPASS_PADDR 0xF0000000
63#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000
64
65/* System ROM: */
66#define XSHAL_ROM_VADDR 0xEE000000
67#define XSHAL_ROM_PADDR 0xFE000000
68#define XSHAL_ROM_SIZE 0x00400000
69/* Largest available area (free of vectors): */
70#define XSHAL_ROM_AVAIL_VADDR 0xEE00052C
71#define XSHAL_ROM_AVAIL_VSIZE 0x003FFAD4
72
73/* System RAM: */
74#define XSHAL_RAM_VADDR 0xD0000000
75#define XSHAL_RAM_PADDR 0x00000000
76#define XSHAL_RAM_VSIZE 0x08000000
77#define XSHAL_RAM_PSIZE 0x10000000
78#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE
79/* Largest available area (free of vectors): */
80#define XSHAL_RAM_AVAIL_VADDR 0xD0000370
81#define XSHAL_RAM_AVAIL_VSIZE 0x07FFFC90
82
83/*
84 * Shadow system RAM (same device as system RAM, at different address).
85 * (Emulation boards need this for the SONIC Ethernet driver
86 * when data caches are configured for writeback mode.)
87 * NOTE: on full MMU configs, this points to the BYPASS virtual address
88 * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual
89 * addresses are viewed through the BYPASS static map rather than
90 * the CACHED static map.
91 */
92#define XSHAL_RAM_BYPASS_VADDR 0xD8000000
93#define XSHAL_RAM_BYPASS_PADDR 0x00000000
94#define XSHAL_RAM_BYPASS_PSIZE 0x08000000
95
96/* Alternate system RAM (different device than system RAM): */
97#define XSHAL_ALTRAM_VADDR 0xCEE00000
98#define XSHAL_ALTRAM_PADDR 0xC0000000
99#define XSHAL_ALTRAM_SIZE 0x00200000
100
101
102/*----------------------------------------------------------------------
103 * DEVICE-ADDRESS DEPENDENT...
104 *
105 * Values written to CACHEATTR special register (or its equivalent)
106 * to enable and disable caches in various modes.
107 *----------------------------------------------------------------------*/
108
109/*----------------------------------------------------------------------
110 BACKWARD COMPATIBILITY ...
111 ----------------------------------------------------------------------*/
112
113/*
114 * NOTE: the following two macros are DEPRECATED. Use the latter
115 * board-specific macros instead, which are specially tuned for the
116 * particular target environments' memory maps.
117 */
118#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */
119#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */
120
121/*----------------------------------------------------------------------
122 ISS (Instruction Set Simulator) SPECIFIC ...
123 ----------------------------------------------------------------------*/
124
125#define XSHAL_ISS_CACHEATTR_WRITEBACK 0x1122222F /* enable caches in write-back mode */
126#define XSHAL_ISS_CACHEATTR_WRITEALLOC 0x1122222F /* enable caches in write-allocate mode */
127#define XSHAL_ISS_CACHEATTR_WRITETHRU 0x1122222F /* enable caches in write-through mode */
128#define XSHAL_ISS_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */
129#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_ISS_CACHEATTR_WRITEBACK /* default setting to enable caches */
130
131/* For Coware only: */
132#define XSHAL_COWARE_CACHEATTR_WRITEBACK 0x11222222 /* enable caches in write-back mode */
133#define XSHAL_COWARE_CACHEATTR_WRITEALLOC 0x11222222 /* enable caches in write-allocate mode */
134#define XSHAL_COWARE_CACHEATTR_WRITETHRU 0x11222222 /* enable caches in write-through mode */
135#define XSHAL_COWARE_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */
136#define XSHAL_COWARE_CACHEATTR_DEFAULT XSHAL_COWARE_CACHEATTR_WRITEBACK /* default setting to enable caches */
137
138/* For BFM and other purposes: */
139#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x11222222 /* enable caches without any invalid regions */
140#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting for caches without any invalid regions */
141
142#define XSHAL_ISS_PIPE_REGIONS 0
143#define XSHAL_ISS_SDRAM_REGIONS 0
144
145
146/*----------------------------------------------------------------------
147 XT2000 BOARD SPECIFIC ...
148 ----------------------------------------------------------------------*/
149
150#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0x22FFFFFF /* enable caches in write-back mode */
151#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0x22FFFFFF /* enable caches in write-allocate mode */
152#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0x22FFFFFF /* enable caches in write-through mode */
153#define XSHAL_XT2000_CACHEATTR_BYPASS 0x22FFFFFF /* disable caches in bypass mode */
154#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */
155
156#define XSHAL_XT2000_PIPE_REGIONS 0x00001000 /* BusInt pipeline regions */
157#define XSHAL_XT2000_SDRAM_REGIONS 0x00000005 /* BusInt SDRAM regions */
158
159
160/*----------------------------------------------------------------------
161 VECTOR SIZES
162 ----------------------------------------------------------------------*/
163
164/*
165 * Sizes allocated to vectors by the system (memory map) configuration.
166 * These sizes are constrained by core configuration (eg. one vector's
167 * code cannot overflow into another vector) but are dependent on the
168 * system or board (or LSP) memory map configuration.
169 *
170 * Whether or not each vector happens to be in a system ROM is also
171 * a system configuration matter, sometimes useful, included here also:
172 */
173#define XSHAL_RESET_VECTOR_SIZE 0x000004E0
174#define XSHAL_RESET_VECTOR_ISROM 1
175#define XSHAL_USER_VECTOR_SIZE 0x0000001C
176#define XSHAL_USER_VECTOR_ISROM 0
177#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */
178#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */
179#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C
180#define XSHAL_KERNEL_VECTOR_ISROM 0
181#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */
182#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */
183#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x000000E0
184#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0
185#define XSHAL_WINDOW_VECTORS_SIZE 0x00000180
186#define XSHAL_WINDOW_VECTORS_ISROM 0
187#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000000C
188#define XSHAL_INTLEVEL2_VECTOR_ISROM 0
189#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000000C
190#define XSHAL_INTLEVEL3_VECTOR_ISROM 0
191#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000000C
192#define XSHAL_INTLEVEL4_VECTOR_ISROM 1
193#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL4_VECTOR_SIZE
194#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL4_VECTOR_ISROM
195
196
197#endif /*XTENSA_CONFIG_SYSTEM_H*/
198
diff --git a/include/asm-xtensa/xtensa/config-linux_be/tie.h b/include/asm-xtensa/xtensa/config-linux_be/tie.h
new file mode 100644
index 0000000000..3c2e514602
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/tie.h
@@ -0,0 +1,275 @@
1/*
2 * xtensa/config/tie.h -- HAL definitions that are dependent on CORE and TIE configuration
3 *
4 * This header file is sometimes referred to as the "compile-time HAL" or CHAL.
5 * It was generated for a specific Xtensa processor configuration,
6 * and furthermore for a specific set of TIE source files that extend
7 * basic core functionality.
8 *
9 * Source for configuration-independent binaries (which link in a
10 * configuration-specific HAL library) must NEVER include this file.
11 * It is perfectly normal, however, for the HAL source itself to include this file.
12 */
13
14/*
15 * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of version 2.1 of the GNU Lesser General Public
19 * License as published by the Free Software Foundation.
20 *
21 * This program is distributed in the hope that it would be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 *
25 * Further, this software is distributed without any warranty that it is
26 * free of the rightful claim of any third person regarding infringement
27 * or the like. Any license provided herein, whether implied or
28 * otherwise, applies only to this software file. Patent licenses, if
29 * any, provided herein do not apply to combinations of this program with
30 * other software, or any other product whatsoever.
31 *
32 * You should have received a copy of the GNU Lesser General Public
33 * License along with this program; if not, write the Free Software
34 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
35 * USA.
36 */
37
38
39#ifndef XTENSA_CONFIG_TIE_H
40#define XTENSA_CONFIG_TIE_H
41
42#include <xtensa/hal.h>
43
44
45/*----------------------------------------------------------------------
46 GENERAL
47 ----------------------------------------------------------------------*/
48
49/*
50 * Separators for macros that expand into arrays.
51 * These can be predefined by files that #include this one,
52 * when different separators are required.
53 */
54/* Element separator for macros that expand into 1-dimensional arrays: */
55#ifndef XCHAL_SEP
56#define XCHAL_SEP ,
57#endif
58/* Array separator for macros that expand into 2-dimensional arrays: */
59#ifndef XCHAL_SEP2
60#define XCHAL_SEP2 },{
61#endif
62
63
64
65
66
67
68/*----------------------------------------------------------------------
69 COPROCESSORS and EXTRA STATE
70 ----------------------------------------------------------------------*/
71
72#define XCHAL_CP_NUM 0 /* number of coprocessors */
73#define XCHAL_CP_MAX 0 /* max coprocessor id plus one (0 if none) */
74#define XCHAL_CP_MASK 0x00 /* bitmask of coprocessors by id */
75
76/* Space for coprocessors' state save areas: */
77#define XCHAL_CP0_SA_SIZE 0
78#define XCHAL_CP1_SA_SIZE 0
79#define XCHAL_CP2_SA_SIZE 0
80#define XCHAL_CP3_SA_SIZE 0
81#define XCHAL_CP4_SA_SIZE 0
82#define XCHAL_CP5_SA_SIZE 0
83#define XCHAL_CP6_SA_SIZE 0
84#define XCHAL_CP7_SA_SIZE 0
85/* Minimum required alignments of CP state save areas: */
86#define XCHAL_CP0_SA_ALIGN 1
87#define XCHAL_CP1_SA_ALIGN 1
88#define XCHAL_CP2_SA_ALIGN 1
89#define XCHAL_CP3_SA_ALIGN 1
90#define XCHAL_CP4_SA_ALIGN 1
91#define XCHAL_CP5_SA_ALIGN 1
92#define XCHAL_CP6_SA_ALIGN 1
93#define XCHAL_CP7_SA_ALIGN 1
94
95/* Indexing macros: */
96#define _XCHAL_CP_SA_SIZE(n) XCHAL_CP ## n ## _SA_SIZE
97#define XCHAL_CP_SA_SIZE(n) _XCHAL_CP_SA_SIZE(n) /* n = 0 .. 7 */
98#define _XCHAL_CP_SA_ALIGN(n) XCHAL_CP ## n ## _SA_ALIGN
99#define XCHAL_CP_SA_ALIGN(n) _XCHAL_CP_SA_ALIGN(n) /* n = 0 .. 7 */
100
101
102/* Space for "extra" state (user special registers and non-cp TIE) save area: */
103#define XCHAL_EXTRA_SA_SIZE 0
104#define XCHAL_EXTRA_SA_ALIGN 1
105
106/* Total save area size (extra + all coprocessors) */
107/* (not useful until xthal_{save,restore}_all_extra() is implemented, */
108/* but included for Tor2 beta; doesn't account for alignment!): */
109#define XCHAL_CPEXTRA_SA_SIZE_TOR2 0 /* Tor2Beta temporary definition -- do not use */
110
111/* Combined required alignment for all CP and EXTRA state save areas */
112/* (does not include required alignment for any base config registers): */
113#define XCHAL_CPEXTRA_SA_ALIGN 1
114
115/* ... */
116
117
118#ifdef _ASMLANGUAGE
119/*
120 * Assembly-language specific definitions (assembly macros, etc.).
121 */
122#include <xtensa/config/specreg.h>
123
124/********************
125 * Macros to save and restore the non-coprocessor TIE portion of EXTRA state.
126 */
127
128/* (none) */
129
130
131/********************
132 * Macros to create functions that save and restore all EXTRA (non-coprocessor) state
133 * (does not include zero-overhead loop registers and non-optional registers).
134 */
135
136 /*
137 * Macro that expands to the body of a function that
138 * stores the extra (non-coprocessor) optional/custom state.
139 * Entry: a2 = ptr to save area in which to save extra state
140 * Exit: any register a2-a15 (?) may have been clobbered.
141 */
142 .macro xchal_extra_store_funcbody
143 .endm
144
145
146 /*
147 * Macro that expands to the body of a function that
148 * loads the extra (non-coprocessor) optional/custom state.
149 * Entry: a2 = ptr to save area from which to restore extra state
150 * Exit: any register a2-a15 (?) may have been clobbered.
151 */
152 .macro xchal_extra_load_funcbody
153 .endm
154
155
156/********************
157 * Macros to save and restore the state of each TIE coprocessor.
158 */
159
160
161
162/********************
163 * Macros to create functions that save and restore the state of *any* TIE coprocessor.
164 */
165
166 /*
167 * Macro that expands to the body of a function
168 * that stores the selected coprocessor's state (registers etc).
169 * Entry: a2 = ptr to save area in which to save cp state
170 * a3 = coprocessor number
171 * Exit: any register a2-a15 (?) may have been clobbered.
172 */
173 .macro xchal_cpi_store_funcbody
174 .endm
175
176
177 /*
178 * Macro that expands to the body of a function
179 * that loads the selected coprocessor's state (registers etc).
180 * Entry: a2 = ptr to save area from which to restore cp state
181 * a3 = coprocessor number
182 * Exit: any register a2-a15 (?) may have been clobbered.
183 */
184 .macro xchal_cpi_load_funcbody
185 .endm
186
187#endif /*_ASMLANGUAGE*/
188
189
190/*
191 * Contents of save areas in terms of libdb register numbers.
192 * NOTE: CONTENTS_LIBDB_{UREG,REGF} macros are not defined in this file;
193 * it is up to the user of this header file to define these macros
194 * usefully before each expansion of the CONTENTS_LIBDB macros.
195 * (Fields rsv[123] are reserved for future additions; they are currently
196 * set to zero but may be set to some useful values in the future.)
197 *
198 * CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum, bitmask, rsv2, rsv3)
199 * CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum, bitmask, rsv2, rsv3)
200 * CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, numentries, contentsize, regname_base, regfile_name, rsv2, rsv3)
201 */
202
203#define XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM 0
204#define XCHAL_EXTRA_SA_CONTENTS_LIBDB /* empty */
205
206#define XCHAL_CP0_SA_CONTENTS_LIBDB_NUM 0
207#define XCHAL_CP0_SA_CONTENTS_LIBDB /* empty */
208
209#define XCHAL_CP1_SA_CONTENTS_LIBDB_NUM 0
210#define XCHAL_CP1_SA_CONTENTS_LIBDB /* empty */
211
212#define XCHAL_CP2_SA_CONTENTS_LIBDB_NUM 0
213#define XCHAL_CP2_SA_CONTENTS_LIBDB /* empty */
214
215#define XCHAL_CP3_SA_CONTENTS_LIBDB_NUM 0
216#define XCHAL_CP3_SA_CONTENTS_LIBDB /* empty */
217
218#define XCHAL_CP4_SA_CONTENTS_LIBDB_NUM 0
219#define XCHAL_CP4_SA_CONTENTS_LIBDB /* empty */
220
221#define XCHAL_CP5_SA_CONTENTS_LIBDB_NUM 0
222#define XCHAL_CP5_SA_CONTENTS_LIBDB /* empty */
223
224#define XCHAL_CP6_SA_CONTENTS_LIBDB_NUM 0
225#define XCHAL_CP6_SA_CONTENTS_LIBDB /* empty */
226
227#define XCHAL_CP7_SA_CONTENTS_LIBDB_NUM 0
228#define XCHAL_CP7_SA_CONTENTS_LIBDB /* empty */
229
230
231
232
233
234
235/*----------------------------------------------------------------------
236 MISC
237 ----------------------------------------------------------------------*/
238
239#if 0 /* is there something equivalent for user TIE? */
240#define XCHAL_CORE_ID "linux_be" /* configuration's alphanumeric core identifier
241 (CoreID) set in the Xtensa Processor Generator */
242
243#define XCHAL_BUILD_UNIQUE_ID 0x00003256 /* software build-unique ID (22-bit) */
244
245/* These definitions describe the hardware targeted by this software: */
246#define XCHAL_HW_CONFIGID0 0xC103D1FF /* config ID reg 0 value (upper 32 of 64 bits) */
247#define XCHAL_HW_CONFIGID1 0x00803256 /* config ID reg 1 value (lower 32 of 64 bits) */
248#define XCHAL_CONFIGID0 XCHAL_HW_CONFIGID0 /* for backward compatibility only -- don't use! */
249#define XCHAL_CONFIGID1 XCHAL_HW_CONFIGID1 /* for backward compatibility only -- don't use! */
250#define XCHAL_HW_RELEASE_MAJOR 1050 /* major release of targeted hardware */
251#define XCHAL_HW_RELEASE_MINOR 1 /* minor release of targeted hardware */
252#define XCHAL_HW_RELEASE_NAME "T1050.1" /* full release name of targeted hardware */
253#define XTHAL_HW_REL_T1050 1
254#define XTHAL_HW_REL_T1050_1 1
255#define XCHAL_HW_CONFIGID_RELIABLE 1
256#endif /*0*/
257
258
259
260/*----------------------------------------------------------------------
261 ISA
262 ----------------------------------------------------------------------*/
263
264#if 0 /* these probably don't belong here, but are related to or implemented using TIE */
265#define XCHAL_HAVE_BOOLEANS 0 /* 1 if booleans option configured, 0 otherwise */
266/* Misc instructions: */
267#define XCHAL_HAVE_MUL32 0 /* 1 if 32-bit integer multiply option configured, 0 otherwise */
268#define XCHAL_HAVE_MUL32_HIGH 0 /* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
269
270#define XCHAL_HAVE_FP 0 /* 1 if floating point option configured, 0 otherwise */
271#endif /*0*/
272
273
274#endif /*XTENSA_CONFIG_TIE_H*/
275
diff --git a/include/asm-xtensa/xtensa/coreasm.h b/include/asm-xtensa/xtensa/coreasm.h
new file mode 100644
index 0000000000..a8cfb54c20
--- /dev/null
+++ b/include/asm-xtensa/xtensa/coreasm.h
@@ -0,0 +1,526 @@
1#ifndef XTENSA_COREASM_H
2#define XTENSA_COREASM_H
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * include/asm-xtensa/xtensa/coreasm.h -- assembler-specific
8 * definitions that depend on CORE configuration.
9 *
10 * Source for configuration-independent binaries (which link in a
11 * configuration-specific HAL library) must NEVER include this file.
12 * It is perfectly normal, however, for the HAL itself to include this
13 * file.
14 *
15 * This file must NOT include xtensa/config/system.h. Any assembler
16 * header file that depends on system information should likely go in
17 * a new systemasm.h (or sysasm.h) header file.
18 *
19 * NOTE: macro beqi32 is NOT configuration-dependent, and is placed
20 * here til we will have configuration-independent header file.
21 *
22 * This file is subject to the terms and conditions of the GNU General
23 * Public License. See the file "COPYING" in the main directory of
24 * this archive for more details.
25 *
26 * Copyright (C) 2002 Tensilica Inc.
27 */
28
29
30#include <xtensa/config/core.h>
31#include <xtensa/config/specreg.h>
32
33/*
34 * Assembly-language specific definitions (assembly macros, etc.).
35 */
36
37/*----------------------------------------------------------------------
38 * find_ms_setbit
39 *
40 * This macro finds the most significant bit that is set in <as>
41 * and return its index + <base> in <ad>, or <base> - 1 if <as> is zero.
42 * The index counts starting at zero for the lsbit, so the return
43 * value ranges from <base>-1 (no bit set) to <base>+31 (msbit set).
44 *
45 * Parameters:
46 * <ad> destination address register (any register)
47 * <as> source address register
48 * <at> temporary address register (must be different than <as>)
49 * <base> constant value added to result (usually 0 or 1)
50 * On entry:
51 * <ad> = undefined if different than <as>
52 * <as> = value whose most significant set bit is to be found
53 * <at> = undefined
54 * no other registers are used by this macro.
55 * On exit:
56 * <ad> = <base> + index of msbit set in original <as>,
57 * = <base> - 1 if original <as> was zero.
58 * <as> clobbered (if not <ad>)
59 * <at> clobbered (if not <ad>)
60 * Example:
61 * find_ms_setbit a0, a4, a0, 0 -- return in a0 index of msbit set in a4
62 */
63
64 .macro find_ms_setbit ad, as, at, base
65#if XCHAL_HAVE_NSA
66 movi \at, 31+\base
67 nsau \as, \as // get index of \as, numbered from msbit (32 if absent)
68 sub \ad, \at, \as // get numbering from lsbit (0..31, -1 if absent)
69#else /* XCHAL_HAVE_NSA */
70 movi \at, \base // start with result of 0 (point to lsbit of 32)
71
72 beqz \as, 2f // special case for zero argument: return -1
73 bltui \as, 0x10000, 1f // is it one of the 16 lsbits? (if so, check lower 16 bits)
74 addi \at, \at, 16 // no, increment result to upper 16 bits (of 32)
75 //srli \as, \as, 16 // check upper half (shift right 16 bits)
76 extui \as, \as, 16, 16 // check upper half (shift right 16 bits)
771: bltui \as, 0x100, 1f // is it one of the 8 lsbits? (if so, check lower 8 bits)
78 addi \at, \at, 8 // no, increment result to upper 8 bits (of 16)
79 srli \as, \as, 8 // shift right to check upper 8 bits
801: bltui \as, 0x10, 1f // is it one of the 4 lsbits? (if so, check lower 4 bits)
81 addi \at, \at, 4 // no, increment result to upper 4 bits (of 8)
82 srli \as, \as, 4 // shift right 4 bits to check upper half
831: bltui \as, 0x4, 1f // is it one of the 2 lsbits? (if so, check lower 2 bits)
84 addi \at, \at, 2 // no, increment result to upper 2 bits (of 4)
85 srli \as, \as, 2 // shift right 2 bits to check upper half
861: bltui \as, 0x2, 1f // is it the lsbit?
87 addi \at, \at, 2 // no, increment result to upper bit (of 2)
882: addi \at, \at, -1 // (from just above: add 1; from beqz: return -1)
89 //srli \as, \as, 1
901: // done! \at contains index of msbit set (or -1 if none set)
91 .if 0x\ad - 0x\at // destination different than \at ? (works because regs are a0-a15)
92 mov \ad, \at // then move result to \ad
93 .endif
94#endif /* XCHAL_HAVE_NSA */
95 .endm // find_ms_setbit
96
97/*----------------------------------------------------------------------
98 * find_ls_setbit
99 *
100 * This macro finds the least significant bit that is set in <as>,
101 * and return its index in <ad>.
102 * Usage is the same as for the find_ms_setbit macro.
103 * Example:
104 * find_ls_setbit a0, a4, a0, 0 -- return in a0 index of lsbit set in a4
105 */
106
107 .macro find_ls_setbit ad, as, at, base
108 neg \at, \as // keep only the least-significant bit that is set...
109 and \as, \at, \as // ... in \as
110 find_ms_setbit \ad, \as, \at, \base
111 .endm // find_ls_setbit
112
113/*----------------------------------------------------------------------
114 * find_ls_one
115 *
116 * Same as find_ls_setbit with base zero.
117 * Source (as) and destination (ad) registers must be different.
118 * Provided for backward compatibility.
119 */
120
121 .macro find_ls_one ad, as
122 find_ls_setbit \ad, \as, \ad, 0
123 .endm // find_ls_one
124
125/*----------------------------------------------------------------------
126 * floop, floopnez, floopgtz, floopend
127 *
128 * These macros are used for fast inner loops that
129 * work whether or not the Loops options is configured.
130 * If the Loops option is configured, they simply use
131 * the zero-overhead LOOP instructions; otherwise
132 * they use explicit decrement and branch instructions.
133 *
134 * They are used in pairs, with floop, floopnez or floopgtz
135 * at the beginning of the loop, and floopend at the end.
136 *
137 * Each pair of loop macro calls must be given the loop count
138 * address register and a unique label for that loop.
139 *
140 * Example:
141 *
142 * movi a3, 16 // loop 16 times
143 * floop a3, myloop1
144 * :
145 * bnez a7, end1 // exit loop if a7 != 0
146 * :
147 * floopend a3, myloop1
148 * end1:
149 *
150 * Like the LOOP instructions, these macros cannot be
151 * nested, must include at least one instruction,
152 * cannot call functions inside the loop, etc.
153 * The loop can be exited by jumping to the instruction
154 * following floopend (or elsewhere outside the loop),
155 * or continued by jumping to a NOP instruction placed
156 * immediately before floopend.
157 *
158 * Unlike LOOP instructions, the register passed to floop*
159 * cannot be used inside the loop, because it is used as
160 * the loop counter if the Loops option is not configured.
161 * And its value is undefined after exiting the loop.
162 * And because the loop counter register is active inside
163 * the loop, you can't easily use this construct to loop
164 * across a register file using ROTW as you might with LOOP
165 * instructions, unless you copy the loop register along.
166 */
167
168 /* Named label version of the macros: */
169
170 .macro floop ar, endlabel
171 floop_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
172 .endm
173
174 .macro floopnez ar, endlabel
175 floopnez_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
176 .endm
177
178 .macro floopgtz ar, endlabel
179 floopgtz_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
180 .endm
181
182 .macro floopend ar, endlabel
183 floopend_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
184 .endm
185
186 /* Numbered local label version of the macros: */
187#if 0 /*UNTESTED*/
188 .macro floop89 ar
189 floop_ \ar, 8, 9f
190 .endm
191
192 .macro floopnez89 ar
193 floopnez_ \ar, 8, 9f
194 .endm
195
196 .macro floopgtz89 ar
197 floopgtz_ \ar, 8, 9f
198 .endm
199
200 .macro floopend89 ar
201 floopend_ \ar, 8b, 9
202 .endm
203#endif /*0*/
204
205 /* Underlying version of the macros: */
206
207 .macro floop_ ar, startlabel, endlabelref
208 .ifdef _infloop_
209 .if _infloop_
210 .err // Error: floop cannot be nested
211 .endif
212 .endif
213 .set _infloop_, 1
214#if XCHAL_HAVE_LOOPS
215 loop \ar, \endlabelref
216#else /* XCHAL_HAVE_LOOPS */
217\startlabel:
218 addi \ar, \ar, -1
219#endif /* XCHAL_HAVE_LOOPS */
220 .endm // floop_
221
222 .macro floopnez_ ar, startlabel, endlabelref
223 .ifdef _infloop_
224 .if _infloop_
225 .err // Error: floopnez cannot be nested
226 .endif
227 .endif
228 .set _infloop_, 1
229#if XCHAL_HAVE_LOOPS
230 loopnez \ar, \endlabelref
231#else /* XCHAL_HAVE_LOOPS */
232 beqz \ar, \endlabelref
233\startlabel:
234 addi \ar, \ar, -1
235#endif /* XCHAL_HAVE_LOOPS */
236 .endm // floopnez_
237
238 .macro floopgtz_ ar, startlabel, endlabelref
239 .ifdef _infloop_
240 .if _infloop_
241 .err // Error: floopgtz cannot be nested
242 .endif
243 .endif
244 .set _infloop_, 1
245#if XCHAL_HAVE_LOOPS
246 loopgtz \ar, \endlabelref
247#else /* XCHAL_HAVE_LOOPS */
248 bltz \ar, \endlabelref
249 beqz \ar, \endlabelref
250\startlabel:
251 addi \ar, \ar, -1
252#endif /* XCHAL_HAVE_LOOPS */
253 .endm // floopgtz_
254
255
256 .macro floopend_ ar, startlabelref, endlabel
257 .ifndef _infloop_
258 .err // Error: floopend without matching floopXXX
259 .endif
260 .ifeq _infloop_
261 .err // Error: floopend without matching floopXXX
262 .endif
263 .set _infloop_, 0
264#if ! XCHAL_HAVE_LOOPS
265 bnez \ar, \startlabelref
266#endif /* XCHAL_HAVE_LOOPS */
267\endlabel:
268 .endm // floopend_
269
270/*----------------------------------------------------------------------
271 * crsil -- conditional RSIL (read/set interrupt level)
272 *
273 * Executes the RSIL instruction if it exists, else just reads PS.
274 * The RSIL instruction does not exist in the new exception architecture
275 * if the interrupt option is not selected.
276 */
277
278 .macro crsil ar, newlevel
279#if XCHAL_HAVE_OLD_EXC_ARCH || XCHAL_HAVE_INTERRUPTS
280 rsil \ar, \newlevel
281#else
282 rsr \ar, PS
283#endif
284 .endm // crsil
285
286/*----------------------------------------------------------------------
287 * window_spill{4,8,12}
288 *
289 * These macros spill callers' register windows to the stack.
290 * They work for both privileged and non-privileged tasks.
291 * Must be called from a windowed ABI context, eg. within
292 * a windowed ABI function (ie. valid stack frame, window
293 * exceptions enabled, not in exception mode, etc).
294 *
295 * This macro requires a single invocation of the window_spill_common
296 * macro in the same assembly unit and section.
297 *
298 * Note that using window_spill{4,8,12} macros is more efficient
299 * than calling a function implemented using window_spill_function,
300 * because the latter needs extra code to figure out the size of
301 * the call to the spilling function.
302 *
303 * Example usage:
304 *
305 * .text
306 * .align 4
307 * .global some_function
308 * .type some_function,@function
309 * some_function:
310 * entry a1, 16
311 * :
312 * :
313 *
314 * window_spill4 // spill windows of some_function's callers; preserves a0..a3 only;
315 * // to use window_spill{8,12} in this example function we'd have
316 * // to increase space allocated by the entry instruction, because
317 * // 16 bytes only allows call4; 32 or 48 bytes (+locals) are needed
318 * // for call8/window_spill8 or call12/window_spill12 respectively.
319 * :
320 *
321 * retw
322 *
323 * window_spill_common // instantiates code used by window_spill4
324 *
325 *
326 * On entry:
327 * none (if window_spill4)
328 * stack frame has enough space allocated for call8 (if window_spill8)
329 * stack frame has enough space allocated for call12 (if window_spill12)
330 * On exit:
331 * a4..a15 clobbered (if window_spill4)
332 * a8..a15 clobbered (if window_spill8)
333 * a12..a15 clobbered (if window_spill12)
334 * no caller windows are in live registers
335 */
336
337 .macro window_spill4
338#if XCHAL_HAVE_WINDOWED
339# if XCHAL_NUM_AREGS == 16
340 movi a15, 0 // for 16-register files, no need to call to reach the end
341# elif XCHAL_NUM_AREGS == 32
342 call4 .L__wdwspill_assist28 // call deep enough to clear out any live callers
343# elif XCHAL_NUM_AREGS == 64
344 call4 .L__wdwspill_assist60 // call deep enough to clear out any live callers
345# endif
346#endif
347 .endm // window_spill4
348
349 .macro window_spill8
350#if XCHAL_HAVE_WINDOWED
351# if XCHAL_NUM_AREGS == 16
352 movi a15, 0 // for 16-register files, no need to call to reach the end
353# elif XCHAL_NUM_AREGS == 32
354 call8 .L__wdwspill_assist24 // call deep enough to clear out any live callers
355# elif XCHAL_NUM_AREGS == 64
356 call8 .L__wdwspill_assist56 // call deep enough to clear out any live callers
357# endif
358#endif
359 .endm // window_spill8
360
361 .macro window_spill12
362#if XCHAL_HAVE_WINDOWED
363# if XCHAL_NUM_AREGS == 16
364 movi a15, 0 // for 16-register files, no need to call to reach the end
365# elif XCHAL_NUM_AREGS == 32
366 call12 .L__wdwspill_assist20 // call deep enough to clear out any live callers
367# elif XCHAL_NUM_AREGS == 64
368 call12 .L__wdwspill_assist52 // call deep enough to clear out any live callers
369# endif
370#endif
371 .endm // window_spill12
372
373/*----------------------------------------------------------------------
374 * window_spill_function
375 *
376 * This macro outputs a function that will spill its caller's callers'
377 * register windows to the stack. Eg. it could be used to implement
378 * a version of xthal_window_spill() that works in non-privileged tasks.
379 * This works for both privileged and non-privileged tasks.
380 *
381 * Typical usage:
382 *
383 * .text
384 * .align 4
385 * .global my_spill_function
386 * .type my_spill_function,@function
387 * my_spill_function:
388 * window_spill_function
389 *
390 * On entry to resulting function:
391 * none
392 * On exit from resulting function:
393 * none (no caller windows are in live registers)
394 */
395
396 .macro window_spill_function
397#if XCHAL_HAVE_WINDOWED
398# if XCHAL_NUM_AREGS == 32
399 entry sp, 48
400 bbci.l a0, 31, 1f // branch if called with call4
401 bbsi.l a0, 30, 2f // branch if called with call12
402 call8 .L__wdwspill_assist16 // called with call8, only need another 8
403 retw
4041: call12 .L__wdwspill_assist16 // called with call4, only need another 12
405 retw
4062: call4 .L__wdwspill_assist16 // called with call12, only need another 4
407 retw
408# elif XCHAL_NUM_AREGS == 64
409 entry sp, 48
410 bbci.l a0, 31, 1f // branch if called with call4
411 bbsi.l a0, 30, 2f // branch if called with call12
412 call4 .L__wdwspill_assist52 // called with call8, only need a call4
413 retw
4141: call8 .L__wdwspill_assist52 // called with call4, only need a call8
415 retw
4162: call12 .L__wdwspill_assist40 // called with call12, can skip a call12
417 retw
418# elif XCHAL_NUM_AREGS == 16
419 entry sp, 16
420 bbci.l a0, 31, 1f // branch if called with call4
421 bbsi.l a0, 30, 2f // branch if called with call12
422 movi a7, 0 // called with call8
423 retw
4241: movi a11, 0 // called with call4
4252: retw // if called with call12, everything already spilled
426
427// movi a15, 0 // trick to spill all but the direct caller
428// j 1f
429// // The entry instruction is magical in the assembler (gets auto-aligned)
430// // so we have to jump to it to avoid falling through the padding.
431// // We need entry/retw to know where to return.
432//1: entry sp, 16
433// retw
434# else
435# error "unrecognized address register file size"
436# endif
437#endif /* XCHAL_HAVE_WINDOWED */
438 window_spill_common
439 .endm // window_spill_function
440
441/*----------------------------------------------------------------------
442 * window_spill_common
443 *
444 * Common code used by any number of invocations of the window_spill##
445 * and window_spill_function macros.
446 *
447 * Must be instantiated exactly once within a given assembly unit,
448 * within call/j range of and same section as window_spill##
449 * macro invocations for that assembly unit.
450 * (Is automatically instantiated by the window_spill_function macro.)
451 */
452
453 .macro window_spill_common
454#if XCHAL_HAVE_WINDOWED && (XCHAL_NUM_AREGS == 32 || XCHAL_NUM_AREGS == 64)
455 .ifndef .L__wdwspill_defined
456# if XCHAL_NUM_AREGS >= 64
457.L__wdwspill_assist60:
458 entry sp, 32
459 call8 .L__wdwspill_assist52
460 retw
461.L__wdwspill_assist56:
462 entry sp, 16
463 call4 .L__wdwspill_assist52
464 retw
465.L__wdwspill_assist52:
466 entry sp, 48
467 call12 .L__wdwspill_assist40
468 retw
469.L__wdwspill_assist40:
470 entry sp, 48
471 call12 .L__wdwspill_assist28
472 retw
473# endif
474.L__wdwspill_assist28:
475 entry sp, 48
476 call12 .L__wdwspill_assist16
477 retw
478.L__wdwspill_assist24:
479 entry sp, 32
480 call8 .L__wdwspill_assist16
481 retw
482.L__wdwspill_assist20:
483 entry sp, 16
484 call4 .L__wdwspill_assist16
485 retw
486.L__wdwspill_assist16:
487 entry sp, 16
488 movi a15, 0
489 retw
490 .set .L__wdwspill_defined, 1
491 .endif
492#endif /* XCHAL_HAVE_WINDOWED with 32 or 64 aregs */
493 .endm // window_spill_common
494
495/*----------------------------------------------------------------------
496 * beqi32
497 *
498 * macro implements version of beqi for arbitrary 32-bit immidiate value
499 *
500 * beqi32 ax, ay, imm32, label
501 *
502 * Compares value in register ax with imm32 value and jumps to label if
503 * equal. Clobberes register ay if needed
504 *
505 */
506 .macro beqi32 ax, ay, imm, label
507 .ifeq ((\imm-1) & ~7) // 1..8 ?
508 beqi \ax, \imm, \label
509 .else
510 .ifeq (\imm+1) // -1 ?
511 beqi \ax, \imm, \label
512 .else
513 .ifeq (\imm) // 0 ?
514 beqz \ax, \label
515 .else
516 // We could also handle immediates 10,12,16,32,64,128,256
517 // but it would be a long macro...
518 movi \ay, \imm
519 beq \ax, \ay, \label
520 .endif
521 .endif
522 .endif
523 .endm // beqi32
524
525#endif /*XTENSA_COREASM_H*/
526
diff --git a/include/asm-xtensa/xtensa/corebits.h b/include/asm-xtensa/xtensa/corebits.h
new file mode 100644
index 0000000000..e578ade416
--- /dev/null
+++ b/include/asm-xtensa/xtensa/corebits.h
@@ -0,0 +1,77 @@
1#ifndef XTENSA_COREBITS_H
2#define XTENSA_COREBITS_H
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * xtensa/corebits.h - Xtensa Special Register field positions and masks.
8 *
9 * (In previous releases, these were defined in specreg.h, a generated file.
10 * This file is not generated, i.e. it is processor configuration independent.)
11 */
12
13
14/* EXCCAUSE register fields: */
15#define EXCCAUSE_EXCCAUSE_SHIFT 0
16#define EXCCAUSE_EXCCAUSE_MASK 0x3F
17/* Exception causes (mostly incomplete!): */
18#define EXCCAUSE_ILLEGAL 0
19#define EXCCAUSE_SYSCALL 1
20#define EXCCAUSE_IFETCHERROR 2
21#define EXCCAUSE_LOADSTOREERROR 3
22#define EXCCAUSE_LEVEL1INTERRUPT 4
23#define EXCCAUSE_ALLOCA 5
24
25/* PS register fields: */
26#define PS_WOE_SHIFT 18
27#define PS_WOE_MASK 0x00040000
28#define PS_WOE PS_WOE_MASK
29#define PS_CALLINC_SHIFT 16
30#define PS_CALLINC_MASK 0x00030000
31#define PS_CALLINC(n) (((n)&3)<<PS_CALLINC_SHIFT) /* n = 0..3 */
32#define PS_OWB_SHIFT 8
33#define PS_OWB_MASK 0x00000F00
34#define PS_OWB(n) (((n)&15)<<PS_OWB_SHIFT) /* n = 0..15 (or 0..7) */
35#define PS_RING_SHIFT 6
36#define PS_RING_MASK 0x000000C0
37#define PS_RING(n) (((n)&3)<<PS_RING_SHIFT) /* n = 0..3 */
38#define PS_UM_SHIFT 5
39#define PS_UM_MASK 0x00000020
40#define PS_UM PS_UM_MASK
41#define PS_EXCM_SHIFT 4
42#define PS_EXCM_MASK 0x00000010
43#define PS_EXCM PS_EXCM_MASK
44#define PS_INTLEVEL_SHIFT 0
45#define PS_INTLEVEL_MASK 0x0000000F
46#define PS_INTLEVEL(n) ((n)&PS_INTLEVEL_MASK) /* n = 0..15 */
47/* Backward compatibility (deprecated): */
48#define PS_PROGSTACK_SHIFT PS_UM_SHIFT
49#define PS_PROGSTACK_MASK PS_UM_MASK
50#define PS_PROG_SHIFT PS_UM_SHIFT
51#define PS_PROG_MASK PS_UM_MASK
52#define PS_PROG PS_UM
53
54/* DBREAKCn register fields: */
55#define DBREAKC_MASK_SHIFT 0
56#define DBREAKC_MASK_MASK 0x0000003F
57#define DBREAKC_LOADBREAK_SHIFT 30
58#define DBREAKC_LOADBREAK_MASK 0x40000000
59#define DBREAKC_STOREBREAK_SHIFT 31
60#define DBREAKC_STOREBREAK_MASK 0x80000000
61
62/* DEBUGCAUSE register fields: */
63#define DEBUGCAUSE_DEBUGINT_SHIFT 5
64#define DEBUGCAUSE_DEBUGINT_MASK 0x20 /* debug interrupt */
65#define DEBUGCAUSE_BREAKN_SHIFT 4
66#define DEBUGCAUSE_BREAKN_MASK 0x10 /* BREAK.N instruction */
67#define DEBUGCAUSE_BREAK_SHIFT 3
68#define DEBUGCAUSE_BREAK_MASK 0x08 /* BREAK instruction */
69#define DEBUGCAUSE_DBREAK_SHIFT 2
70#define DEBUGCAUSE_DBREAK_MASK 0x04 /* DBREAK match */
71#define DEBUGCAUSE_IBREAK_SHIFT 1
72#define DEBUGCAUSE_IBREAK_MASK 0x02 /* IBREAK match */
73#define DEBUGCAUSE_ICOUNT_SHIFT 0
74#define DEBUGCAUSE_ICOUNT_MASK 0x01 /* ICOUNT would increment to zero */
75
76#endif /*XTENSA_COREBITS_H*/
77
diff --git a/include/asm-xtensa/xtensa/hal.h b/include/asm-xtensa/xtensa/hal.h
new file mode 100644
index 0000000000..d104725054
--- /dev/null
+++ b/include/asm-xtensa/xtensa/hal.h
@@ -0,0 +1,822 @@
1#ifndef XTENSA_HAL_H
2#define XTENSA_HAL_H
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * include/asm-xtensa/xtensa/hal.h -- contains a definition of the
8 * Core HAL interface.
9 *
10 * All definitions in this header file are independent of any specific
11 * Xtensa processor configuration. Thus an OS or other software can
12 * include this header file and be compiled into configuration-
13 * independent objects that can be distributed and eventually linked
14 * to the HAL library (libhal.a) to create a configuration-specific
15 * final executable.
16 *
17 * Certain definitions, however, are release-specific -- such as the
18 * XTHAL_RELEASE_xxx macros (or additions made in later releases).
19 *
20 * This file is subject to the terms and conditions of the GNU General Public
21 * License. See the file "COPYING" in the main directory of this archive
22 * for more details.
23 *
24 * Copyright (C) 2002 Tensilica Inc.
25 */
26
27
28/*----------------------------------------------------------------------
29 Constant Definitions
30 (shared with assembly)
31 ----------------------------------------------------------------------*/
32
33/* Software release information (not configuration-specific!): */
34#define XTHAL_RELEASE_MAJOR 1050
35#define XTHAL_RELEASE_MINOR 0
36#define XTHAL_RELEASE_NAME "T1050.0-2002-08-06-eng0"
37#define XTHAL_RELEASE_INTERNAL "2002-08-06-eng0"
38#define XTHAL_REL_T1050 1
39#define XTHAL_REL_T1050_0 1
40#define XTHAL_REL_T1050_0_2002 1
41#define XTHAL_REL_T1050_0_2002_08 1
42#define XTHAL_REL_T1050_0_2002_08_06 1
43#define XTHAL_REL_T1050_0_2002_08_06_ENG0 1
44
45/* HAL version numbers (these names are for backward compatibility): */
46#define XTHAL_MAJOR_REV XTHAL_RELEASE_MAJOR
47#define XTHAL_MINOR_REV XTHAL_RELEASE_MINOR
48/*
49 * A bit of software release history on values of XTHAL_{MAJOR,MINOR}_REV:
50 *
51 * Release MAJOR MINOR Comment
52 * ======= ===== ===== =======
53 * T1015.n n/a n/a (HAL not yet available)
54 * T1020.{0,1,2} 0 1 (HAL beta)
55 * T1020.{3,4} 0 2 First release.
56 * T1020.n (n>4) 0 2 or >3 (TBD)
57 * T1030.0 0 1 (HAL beta)
58 * T1030.{1,2} 0 3 Equivalent to first release.
59 * T1030.n (n>=3) 0 >= 3 (TBD)
60 * T1040.n 1040 n Full CHAL available from T1040.2
61 * T1050.n 1050 n Current release.
62 *
63 *
64 * Note: there is a distinction between the software release with
65 * which something is compiled (accessible using XTHAL_RELEASE_* macros)
66 * and the software release with which the HAL library was compiled
67 * (accessible using Xthal_release_* global variables). This
68 * distinction is particularly relevant for vendors that distribute
69 * configuration-independent binaries (eg. an OS), where their customer
70 * might link it with a HAL of a different Xtensa software release.
71 * In this case, it may be appropriate for the OS to verify at run-time
72 * whether XTHAL_RELEASE_* and Xthal_release_* are compatible.
73 * [Guidelines as to which release is compatible with which are not
74 * currently provided explicitly, but might be inferred from reading
75 * OSKit documentation for all releases -- compatibility is also highly
76 * dependent on which HAL features are used. Each release is usually
77 * backward compatible, with very few exceptions if any.]
78 *
79 * Notes:
80 * Tornado 2.0 supported in T1020.3+, T1030.1+, and T1040.{0,1} only.
81 * Tornado 2.0.2 supported in T1040.2+, and T1050.
82 * Compile-time HAL port of NucleusPlus supported by T1040.2+ and T1050.
83 */
84
85
86/*
87 * Architectural limits, independent of configuration.
88 * Note that these are ISA-defined limits, not micro-architecture implementation
89 * limits enforced by the Xtensa Processor Generator (which may be stricter than
90 * these below).
91 */
92#define XTHAL_MAX_CPS 8 /* max number of coprocessors (0..7) */
93#define XTHAL_MAX_INTERRUPTS 32 /* max number of interrupts (0..31) */
94#define XTHAL_MAX_INTLEVELS 16 /* max number of interrupt levels (0..15) */
95 /* (as of T1040, implementation limit is 7: 0..6) */
96#define XTHAL_MAX_TIMERS 4 /* max number of timers (CCOMPARE0..CCOMPARE3) */
97 /* (as of T1040, implementation limit is 3: 0..2) */
98
99/* Misc: */
100#define XTHAL_LITTLEENDIAN 0
101#define XTHAL_BIGENDIAN 1
102
103
104/* Interrupt types: */
105#define XTHAL_INTTYPE_UNCONFIGURED 0
106#define XTHAL_INTTYPE_SOFTWARE 1
107#define XTHAL_INTTYPE_EXTERN_EDGE 2
108#define XTHAL_INTTYPE_EXTERN_LEVEL 3
109#define XTHAL_INTTYPE_TIMER 4
110#define XTHAL_INTTYPE_NMI 5
111#define XTHAL_MAX_INTTYPES 6 /* number of interrupt types */
112
113/* Timer related: */
114#define XTHAL_TIMER_UNCONFIGURED -1 /* Xthal_timer_interrupt[] value for non-existent timers */
115#define XTHAL_TIMER_UNASSIGNED XTHAL_TIMER_UNCONFIGURED /* (for backwards compatibility only) */
116
117
118/* Access Mode bits (tentative): */ /* bit abbr unit short_name PPC equ - Description */
119#define XTHAL_AMB_EXCEPTION 0 /* 001 E EX fls: EXception none - generate exception on any access (aka "illegal") */
120#define XTHAL_AMB_HITCACHE 1 /* 002 C CH fls: use Cache on Hit ~(I CI) - use cache on hit -- way from tag match [or H HC, or U UC] (ISA: same, except for Isolate case) */
121#define XTHAL_AMB_ALLOCATE 2 /* 004 A AL fl?: ALlocate none - refill cache on miss -- way from LRU [or F FI fill] (ISA: Read/Write Miss Refill) */
122#define XTHAL_AMB_WRITETHRU 3 /* 008 W WT --s: WriteThrough W WT - store immediately to memory (ISA: same) */
123#define XTHAL_AMB_ISOLATE 4 /* 010 I IS fls: ISolate none - use cache regardless of hit-vs-miss -- way from vaddr (ISA: use-cache-on-miss+hit) */
124#define XTHAL_AMB_GUARD 5 /* 020 G GU ?l?: GUard G * - non-speculative; spec/replay refs not permitted */
125#if 0
126#define XTHAL_AMB_ORDERED x /* 000 O OR fls: ORdered G * - mem accesses cannot be out of order */
127#define XTHAL_AMB_FUSEWRITES x /* 000 F FW --s: FuseWrites none - allow combining/merging multiple writes (to same datapath data unit) into one (implied by writeback) */
128#define XTHAL_AMB_COHERENT x /* 000 M MC fl?: Mem/MP Coherent M - on reads, other CPUs/bus-masters may need to supply data */
129#define XTHAL_AMB_TRUSTED x /* 000 T TR ?l?: TRusted none - memory will not bus error (if it does, handle as fatal imprecise interrupt) */
130#define XTHAL_AMB_PREFETCH x /* 000 P PR fl?: PRefetch none - on refill, read line+1 into prefetch buffers */
131#define XTHAL_AMB_STREAM x /* 000 S ST ???: STreaming none - access one of N stream buffers */
132#endif /*0*/
133
134#define XTHAL_AM_EXCEPTION (1<<XTHAL_AMB_EXCEPTION)
135#define XTHAL_AM_HITCACHE (1<<XTHAL_AMB_HITCACHE)
136#define XTHAL_AM_ALLOCATE (1<<XTHAL_AMB_ALLOCATE)
137#define XTHAL_AM_WRITETHRU (1<<XTHAL_AMB_WRITETHRU)
138#define XTHAL_AM_ISOLATE (1<<XTHAL_AMB_ISOLATE)
139#define XTHAL_AM_GUARD (1<<XTHAL_AMB_GUARD)
140#if 0
141#define XTHAL_AM_ORDERED (1<<XTHAL_AMB_ORDERED)
142#define XTHAL_AM_FUSEWRITES (1<<XTHAL_AMB_FUSEWRITES)
143#define XTHAL_AM_COHERENT (1<<XTHAL_AMB_COHERENT)
144#define XTHAL_AM_TRUSTED (1<<XTHAL_AMB_TRUSTED)
145#define XTHAL_AM_PREFETCH (1<<XTHAL_AMB_PREFETCH)
146#define XTHAL_AM_STREAM (1<<XTHAL_AMB_STREAM)
147#endif /*0*/
148
149/*
150 * Allowed Access Modes (bit combinations).
151 *
152 * Columns are:
153 * "FOGIWACE"
154 * Access mode bits (see XTHAL_AMB_xxx above).
155 * <letter> = bit is set
156 * '-' = bit is clear
157 * '.' = bit is irrelevant / don't care, as follows:
158 * E=1 makes all others irrelevant
159 * W,F relevant only for stores
160 * "2345"
161 * Indicates which Xtensa releases support the corresponding
162 * access mode. Releases for each character column are:
163 * 2 = prior to T1020.2: T1015 (V1.5), T1020.0, T1020.1
164 * 3 = T1020.2 and later: T1020.2+, T1030
165 * 4 = T1040
166 * 5 = T1050 (maybe)
167 * And the character column contents are:
168 * <number> = support by release(s)
169 * "." = unsupported by release(s)
170 * "?" = support unknown
171 */
172 /* FOGIWACE 2345 */
173/* For instruction fetch: */
174#define XTHAL_FAM_EXCEPTION 0x001 /* .......E 2345 exception */
175#define XTHAL_FAM_ISOLATE 0x012 /* .--I.-C- .... isolate */
176#define XTHAL_FAM_BYPASS 0x000 /* .---.--- 2345 bypass */
177#define XTHAL_FAM_NACACHED 0x002 /* .---.-C- .... cached no-allocate (frozen) */
178#define XTHAL_FAM_CACHED 0x006 /* .---.AC- 2345 cached */
179/* For data load: */
180#define XTHAL_LAM_EXCEPTION 0x001 /* .......E 2345 exception */
181#define XTHAL_LAM_ISOLATE 0x012 /* .--I.-C- 2345 isolate */
182#define XTHAL_LAM_BYPASS 0x000 /* .O--.--- 2... bypass speculative */
183#define XTHAL_LAM_BYPASSG 0x020 /* .OG-.--- .345 bypass guarded */
184#define XTHAL_LAM_NACACHED 0x002 /* .O--.-C- 2... cached no-allocate speculative */
185#define XTHAL_LAM_NACACHEDG 0x022 /* .OG-.-C- .345 cached no-allocate guarded */
186#define XTHAL_LAM_CACHED 0x006 /* .---.AC- 2345 cached speculative */
187#define XTHAL_LAM_CACHEDG 0x026 /* .?G-.AC- .... cached guarded */
188/* For data store: */
189#define XTHAL_SAM_EXCEPTION 0x001 /* .......E 2345 exception */
190#define XTHAL_SAM_ISOLATE 0x032 /* .-GI--C- 2345 isolate */
191#define XTHAL_SAM_BYPASS 0x028 /* -OG-W--- 2345 bypass */
192/*efine XTHAL_SAM_BYPASSF 0x028*/ /* F-G-W--- ...? bypass write-combined */
193#define XTHAL_SAM_WRITETHRU 0x02A /* -OG-W-C- 234? writethrough */
194/*efine XTHAL_SAM_WRITETHRUF 0x02A*/ /* F-G-W-C- ...5 writethrough write-combined */
195#define XTHAL_SAM_WRITEALLOC 0x02E /* -OG-WAC- ...? writethrough-allocate */
196/*efine XTHAL_SAM_WRITEALLOCF 0x02E*/ /* F-G-WAC- ...? writethrough-allocate write-combined */
197#define XTHAL_SAM_WRITEBACK 0x026 /* F-G--AC- ...5 writeback */
198
199#if 0
200/*
201 Cache attribute encoding for CACHEATTR (per ISA):
202 (Note: if this differs from ISA Ref Manual, ISA has precedence)
203
204 Inst-fetches Loads Stores
205 ------------- ------------ -------------
2060x0 FCA_EXCEPTION ?LCA_NACACHED_G* SCA_WRITETHRU "uncached"
2070x1 FCA_CACHED LCA_CACHED SCA_WRITETHRU cached
2080x2 FCA_BYPASS LCA_BYPASS_G* SCA_BYPASS bypass
2090x3 FCA_CACHED LCA_CACHED SCA_WRITEALLOCF write-allocate
210 or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented)
2110x4 FCA_CACHED LCA_CACHED SCA_WRITEBACK write-back
212 or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented)
2130x5..D FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION (reserved)
2140xE FCA_EXCEPTION LCA_ISOLATE SCA_ISOLATE isolate
2150xF FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION illegal
216 * Prior to T1020.2?, guard feature not supported, this defaulted to speculative (no _G)
217*/
218#endif /*0*/
219
220
221#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
222#ifdef __cplusplus
223extern "C" {
224#endif
225
226/*----------------------------------------------------------------------
227 HAL
228 ----------------------------------------------------------------------*/
229
230/* Constant to be checked in build = (XTHAL_MAJOR_REV<<16)|XTHAL_MINOR_REV */
231extern const unsigned int Xthal_rev_no;
232
233
234/*----------------------------------------------------------------------
235 Processor State
236 ----------------------------------------------------------------------*/
237/* save & restore the extra processor state */
238extern void xthal_save_extra(void *base);
239extern void xthal_restore_extra(void *base);
240
241extern void xthal_save_cpregs(void *base, int);
242extern void xthal_restore_cpregs(void *base, int);
243
244/*extern void xthal_save_all_extra(void *base);*/
245/*extern void xthal_restore_all_extra(void *base);*/
246
247/* space for processor state */
248extern const unsigned int Xthal_extra_size;
249extern const unsigned int Xthal_extra_align;
250/* space for TIE register files */
251extern const unsigned int Xthal_cpregs_size[XTHAL_MAX_CPS];
252extern const unsigned int Xthal_cpregs_align[XTHAL_MAX_CPS];
253
254/* total of space for the processor state (for Tor2) */
255extern const unsigned int Xthal_all_extra_size;
256extern const unsigned int Xthal_all_extra_align;
257
258/* initialize the extra processor */
259/*extern void xthal_init_extra(void);*/
260/* initialize the TIE coprocessor */
261/*extern void xthal_init_cp(int);*/
262
263/* initialize the extra processor */
264extern void xthal_init_mem_extra(void *);
265/* initialize the TIE coprocessor */
266extern void xthal_init_mem_cp(void *, int);
267
268/* validate & invalidate the TIE register file */
269extern void xthal_validate_cp(int);
270extern void xthal_invalidate_cp(int);
271
272/* the number of TIE coprocessors contiguous from zero (for Tor2) */
273extern const unsigned int Xthal_num_coprocessors;
274
275/* actual number of coprocessors */
276extern const unsigned char Xthal_cp_num;
277/* index of highest numbered coprocessor, plus one */
278extern const unsigned char Xthal_cp_max;
279/* index of highest allowed coprocessor number, per cfg, plus one */
280/*extern const unsigned char Xthal_cp_maxcfg;*/
281/* bitmask of which coprocessors are present */
282extern const unsigned int Xthal_cp_mask;
283
284/* read and write cpenable register */
285extern void xthal_set_cpenable(unsigned);
286extern unsigned xthal_get_cpenable(void);
287
288/* read & write extra state register */
289/*extern int xthal_read_extra(void *base, unsigned reg, unsigned *value);*/
290/*extern int xthal_write_extra(void *base, unsigned reg, unsigned value);*/
291
292/* read & write a TIE coprocessor register */
293/*extern int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value);*/
294/*extern int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value);*/
295
296/* return coprocessor number based on register */
297/*extern int xthal_which_cp(unsigned reg);*/
298
299/*----------------------------------------------------------------------
300 Interrupts
301 ----------------------------------------------------------------------*/
302
303/* the number of interrupt levels */
304extern const unsigned char Xthal_num_intlevels;
305/* the number of interrupts */
306extern const unsigned char Xthal_num_interrupts;
307
308/* mask for level of interrupts */
309extern const unsigned int Xthal_intlevel_mask[XTHAL_MAX_INTLEVELS];
310/* mask for level 0 to N interrupts */
311extern const unsigned int Xthal_intlevel_andbelow_mask[XTHAL_MAX_INTLEVELS];
312
313/* level of each interrupt */
314extern const unsigned char Xthal_intlevel[XTHAL_MAX_INTERRUPTS];
315
316/* type per interrupt */
317extern const unsigned char Xthal_inttype[XTHAL_MAX_INTERRUPTS];
318
319/* masks of each type of interrupt */
320extern const unsigned int Xthal_inttype_mask[XTHAL_MAX_INTTYPES];
321
322/* interrupt numbers assigned to each timer interrupt */
323extern const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS];
324
325/*** Virtual interrupt prioritization: ***/
326
327/* Convert between interrupt levels (as per PS.INTLEVEL) and virtual interrupt priorities: */
328extern unsigned xthal_vpri_to_intlevel(unsigned vpri);
329extern unsigned xthal_intlevel_to_vpri(unsigned intlevel);
330
331/* Enables/disables given set (mask) of interrupts; returns previous enabled-mask of all ints: */
332extern unsigned xthal_int_enable(unsigned);
333extern unsigned xthal_int_disable(unsigned);
334
335/* Set/get virtual priority of an interrupt: */
336extern int xthal_set_int_vpri(int intnum, int vpri);
337extern int xthal_get_int_vpri(int intnum);
338
339/* Set/get interrupt lockout level for exclusive access to virtual priority data structures: */
340extern void xthal_set_vpri_locklevel(unsigned intlevel);
341extern unsigned xthal_get_vpri_locklevel(void);
342
343/* Set/get current virtual interrupt priority: */
344extern unsigned xthal_set_vpri(unsigned vpri);
345extern unsigned xthal_get_vpri(unsigned vpri);
346extern unsigned xthal_set_vpri_intlevel(unsigned intlevel);
347extern unsigned xthal_set_vpri_lock(void);
348
349
350
351/*----------------------------------------------------------------------
352 Generic Interrupt Trampolining Support
353 ----------------------------------------------------------------------*/
354
355typedef void (XtHalVoidFunc)(void);
356
357/*
358 * Bitmask of interrupts currently trampolining down:
359 */
360extern unsigned Xthal_tram_pending;
361
362/*
363 * Bitmask of which interrupts currently trampolining down
364 * synchronously are actually enabled; this bitmask is necessary
365 * because INTENABLE cannot hold that state (sync-trampolining
366 * interrupts must be kept disabled while trampolining);
367 * in the current implementation, any bit set here is not set
368 * in INTENABLE, and vice-versa; once a sync-trampoline is
369 * handled (at level one), its enable bit must be moved from
370 * here to INTENABLE:
371 */
372extern unsigned Xthal_tram_enabled;
373
374/*
375 * Bitmask of interrupts configured for sync trampolining:
376 */
377extern unsigned Xthal_tram_sync;
378
379
380/* Trampoline support functions: */
381extern unsigned xthal_tram_pending_to_service( void );
382extern void xthal_tram_done( unsigned serviced_mask );
383extern int xthal_tram_set_sync( int intnum, int sync );
384extern XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn );
385
386/* INTENABLE,INTREAD,INTSET,INTCLEAR register access functions: */
387extern unsigned xthal_get_intenable( void );
388extern void xthal_set_intenable( unsigned );
389extern unsigned xthal_get_intread( void );
390extern void xthal_set_intset( unsigned );
391extern void xthal_set_intclear( unsigned );
392
393
394/*----------------------------------------------------------------------
395 Register Windows
396 ----------------------------------------------------------------------*/
397
398/* number of registers in register window */
399extern const unsigned int Xthal_num_aregs;
400extern const unsigned char Xthal_num_aregs_log2;
401
402/* This spill any live register windows (other than the caller's): */
403extern void xthal_window_spill( void );
404
405
406/*----------------------------------------------------------------------
407 Cache
408 ----------------------------------------------------------------------*/
409
410/* size of the cache lines in log2(bytes) */
411extern const unsigned char Xthal_icache_linewidth;
412extern const unsigned char Xthal_dcache_linewidth;
413/* size of the cache lines in bytes */
414extern const unsigned short Xthal_icache_linesize;
415extern const unsigned short Xthal_dcache_linesize;
416/* number of cache sets in log2(lines per way) */
417extern const unsigned char Xthal_icache_setwidth;
418extern const unsigned char Xthal_dcache_setwidth;
419/* cache set associativity (number of ways) */
420extern const unsigned int Xthal_icache_ways;
421extern const unsigned int Xthal_dcache_ways;
422/* size of the caches in bytes (ways * 2^(linewidth + setwidth)) */
423extern const unsigned int Xthal_icache_size;
424extern const unsigned int Xthal_dcache_size;
425/* cache features */
426extern const unsigned char Xthal_dcache_is_writeback;
427extern const unsigned char Xthal_icache_line_lockable;
428extern const unsigned char Xthal_dcache_line_lockable;
429
430/* cache attribute register control (used by other HAL routines) */
431extern unsigned xthal_get_cacheattr( void );
432extern unsigned xthal_get_icacheattr( void );
433extern unsigned xthal_get_dcacheattr( void );
434extern void xthal_set_cacheattr( unsigned );
435extern void xthal_set_icacheattr( unsigned );
436extern void xthal_set_dcacheattr( unsigned );
437
438/* initialize cache support (must be called once at startup, before all other cache calls) */
439/*extern void xthal_cache_startinit( void );*/
440/* reset caches */
441/*extern void xthal_icache_reset( void );*/
442/*extern void xthal_dcache_reset( void );*/
443/* enable caches */
444extern void xthal_icache_enable( void ); /* DEPRECATED */
445extern void xthal_dcache_enable( void ); /* DEPRECATED */
446/* disable caches */
447extern void xthal_icache_disable( void ); /* DEPRECATED */
448extern void xthal_dcache_disable( void ); /* DEPRECATED */
449
450/* invalidate the caches */
451extern void xthal_icache_all_invalidate( void );
452extern void xthal_dcache_all_invalidate( void );
453extern void xthal_icache_region_invalidate( void *addr, unsigned size );
454extern void xthal_dcache_region_invalidate( void *addr, unsigned size );
455extern void xthal_icache_line_invalidate(void *addr);
456extern void xthal_dcache_line_invalidate(void *addr);
457/* write dirty data back */
458extern void xthal_dcache_all_writeback( void );
459extern void xthal_dcache_region_writeback( void *addr, unsigned size );
460extern void xthal_dcache_line_writeback(void *addr);
461/* write dirty data back and invalidate */
462extern void xthal_dcache_all_writeback_inv( void );
463extern void xthal_dcache_region_writeback_inv( void *addr, unsigned size );
464extern void xthal_dcache_line_writeback_inv(void *addr);
465/* prefetch and lock specified memory range into cache */
466extern void xthal_icache_region_lock( void *addr, unsigned size );
467extern void xthal_dcache_region_lock( void *addr, unsigned size );
468extern void xthal_icache_line_lock(void *addr);
469extern void xthal_dcache_line_lock(void *addr);
470/* unlock from cache */
471extern void xthal_icache_all_unlock( void );
472extern void xthal_dcache_all_unlock( void );
473extern void xthal_icache_region_unlock( void *addr, unsigned size );
474extern void xthal_dcache_region_unlock( void *addr, unsigned size );
475extern void xthal_icache_line_unlock(void *addr);
476extern void xthal_dcache_line_unlock(void *addr);
477
478
479/* sync icache and memory */
480extern void xthal_icache_sync( void );
481/* sync dcache and memory */
482extern void xthal_dcache_sync( void );
483
484/*----------------------------------------------------------------------
485 Debug
486 ----------------------------------------------------------------------*/
487
488/* 1 if debug option configured, 0 if not: */
489extern const int Xthal_debug_configured;
490
491/* Number of instruction and data break registers: */
492extern const int Xthal_num_ibreak;
493extern const int Xthal_num_dbreak;
494
495/* Set (plant) and remove software breakpoint, both synchronizing cache: */
496extern unsigned int xthal_set_soft_break(void *addr);
497extern void xthal_remove_soft_break(void *addr, unsigned int);
498
499
500/*----------------------------------------------------------------------
501 Disassembler
502 ----------------------------------------------------------------------*/
503
504/* Max expected size of the return buffer for a disassembled instruction (hint only): */
505#define XTHAL_DISASM_BUFSIZE 80
506
507/* Disassembly option bits for selecting what to return: */
508#define XTHAL_DISASM_OPT_ADDR 0x0001 /* display address */
509#define XTHAL_DISASM_OPT_OPHEX 0x0002 /* display opcode bytes in hex */
510#define XTHAL_DISASM_OPT_OPCODE 0x0004 /* display opcode name (mnemonic) */
511#define XTHAL_DISASM_OPT_PARMS 0x0008 /* display parameters */
512#define XTHAL_DISASM_OPT_ALL 0x0FFF /* display everything */
513
514/* routine to get a string for the disassembled instruction */
515extern int xthal_disassemble( unsigned char *instr_buf, void *tgt_addr,
516 char *buffer, unsigned buflen, unsigned options );
517
518/* routine to get the size of the next instruction. Returns 0 for
519 illegal instruction */
520extern int xthal_disassemble_size( unsigned char *instr_buf );
521
522
523/*----------------------------------------------------------------------
524 Core Counter
525 ----------------------------------------------------------------------*/
526
527/* counter info */
528extern const unsigned char Xthal_have_ccount; /* set if CCOUNT register present */
529extern const unsigned char Xthal_num_ccompare; /* number of CCOMPAREn registers */
530
531/* get CCOUNT register (if not present return 0) */
532extern unsigned xthal_get_ccount(void);
533
534/* set and get CCOMPAREn registers (if not present, get returns 0) */
535extern void xthal_set_ccompare(int, unsigned);
536extern unsigned xthal_get_ccompare(int);
537
538
539/*----------------------------------------------------------------------
540 Instruction/Data RAM/ROM Access
541 ----------------------------------------------------------------------*/
542
543extern void* xthal_memcpy(void *dst, const void *src, unsigned len);
544extern void* xthal_bcopy(const void *src, void *dst, unsigned len);
545
546/*----------------------------------------------------------------------
547 MP Synchronization
548 ----------------------------------------------------------------------*/
549extern int xthal_compare_and_set( int *addr, int test_val, int compare_val );
550extern unsigned xthal_get_prid( void );
551
552/*extern const char Xthal_have_s32c1i;*/
553extern const unsigned char Xthal_have_prid;
554
555
556/*----------------------------------------------------------------------
557 Miscellaneous
558 ----------------------------------------------------------------------*/
559
560extern const unsigned int Xthal_release_major;
561extern const unsigned int Xthal_release_minor;
562extern const char * const Xthal_release_name;
563extern const char * const Xthal_release_internal;
564
565extern const unsigned char Xthal_memory_order;
566extern const unsigned char Xthal_have_windowed;
567extern const unsigned char Xthal_have_density;
568extern const unsigned char Xthal_have_booleans;
569extern const unsigned char Xthal_have_loops;
570extern const unsigned char Xthal_have_nsa;
571extern const unsigned char Xthal_have_minmax;
572extern const unsigned char Xthal_have_sext;
573extern const unsigned char Xthal_have_clamps;
574extern const unsigned char Xthal_have_mac16;
575extern const unsigned char Xthal_have_mul16;
576extern const unsigned char Xthal_have_fp;
577extern const unsigned char Xthal_have_speculation;
578extern const unsigned char Xthal_have_exceptions;
579extern const unsigned char Xthal_xea_version;
580extern const unsigned char Xthal_have_interrupts;
581extern const unsigned char Xthal_have_highlevel_interrupts;
582extern const unsigned char Xthal_have_nmi;
583
584extern const unsigned short Xthal_num_writebuffer_entries;
585
586extern const unsigned int Xthal_build_unique_id;
587/* Release info for hardware targeted by software upgrades: */
588extern const unsigned int Xthal_hw_configid0;
589extern const unsigned int Xthal_hw_configid1;
590extern const unsigned int Xthal_hw_release_major;
591extern const unsigned int Xthal_hw_release_minor;
592extern const char * const Xthal_hw_release_name;
593extern const char * const Xthal_hw_release_internal;
594
595
596/* Internal memories... */
597
598extern const unsigned char Xthal_num_instrom;
599extern const unsigned char Xthal_num_instram;
600extern const unsigned char Xthal_num_datarom;
601extern const unsigned char Xthal_num_dataram;
602extern const unsigned char Xthal_num_xlmi;
603extern const unsigned int Xthal_instrom_vaddr[1];
604extern const unsigned int Xthal_instrom_paddr[1];
605extern const unsigned int Xthal_instrom_size [1];
606extern const unsigned int Xthal_instram_vaddr[1];
607extern const unsigned int Xthal_instram_paddr[1];
608extern const unsigned int Xthal_instram_size [1];
609extern const unsigned int Xthal_datarom_vaddr[1];
610extern const unsigned int Xthal_datarom_paddr[1];
611extern const unsigned int Xthal_datarom_size [1];
612extern const unsigned int Xthal_dataram_vaddr[1];
613extern const unsigned int Xthal_dataram_paddr[1];
614extern const unsigned int Xthal_dataram_size [1];
615extern const unsigned int Xthal_xlmi_vaddr[1];
616extern const unsigned int Xthal_xlmi_paddr[1];
617extern const unsigned int Xthal_xlmi_size [1];
618
619
620
621/*----------------------------------------------------------------------
622 Memory Management Unit
623 ----------------------------------------------------------------------*/
624
625extern const unsigned char Xthal_have_spanning_way;
626extern const unsigned char Xthal_have_identity_map;
627extern const unsigned char Xthal_have_mimic_cacheattr;
628extern const unsigned char Xthal_have_xlt_cacheattr;
629extern const unsigned char Xthal_have_cacheattr;
630extern const unsigned char Xthal_have_tlbs;
631
632extern const unsigned char Xthal_mmu_asid_bits; /* 0 .. 8 */
633extern const unsigned char Xthal_mmu_asid_kernel;
634extern const unsigned char Xthal_mmu_rings; /* 1 .. 4 (perhaps 0 if no MMU and/or no protection?) */
635extern const unsigned char Xthal_mmu_ring_bits;
636extern const unsigned char Xthal_mmu_sr_bits;
637extern const unsigned char Xthal_mmu_ca_bits;
638extern const unsigned int Xthal_mmu_max_pte_page_size;
639extern const unsigned int Xthal_mmu_min_pte_page_size;
640
641extern const unsigned char Xthal_itlb_way_bits;
642extern const unsigned char Xthal_itlb_ways;
643extern const unsigned char Xthal_itlb_arf_ways;
644extern const unsigned char Xthal_dtlb_way_bits;
645extern const unsigned char Xthal_dtlb_ways;
646extern const unsigned char Xthal_dtlb_arf_ways;
647
648/* Convert between virtual and physical addresses (through static maps only): */
649/*** WARNING: these two functions may go away in a future release; don't depend on them! ***/
650extern int xthal_static_v2p( unsigned vaddr, unsigned *paddrp );
651extern int xthal_static_p2v( unsigned paddr, unsigned *vaddrp, unsigned cached );
652
653#if 0
654/******************* EXPERIMENTAL AND TENTATIVE ONLY ********************/
655
656#define XTHAL_MMU_PAGESZ_COUNT_MAX 8 /* maximum number of different page sizes */
657extern const char Xthal_mmu_pagesz_count; /* 0 .. 8 number of different page sizes configured */
658
659/* Note: the following table doesn't necessarily have page sizes in increasing order: */
660extern const char Xthal_mmu_pagesz_log2[XTHAL_MMU_PAGESZ_COUNT_MAX]; /* 10 .. 28 (0 past count) */
661
662/* Sorted (increasing) table of page sizes, that indexes into the above table: */
663extern const char Xthal_mmu_pagesz_sorted[XTHAL_MMU_PAGESZ_COUNT_MAX]; /* 0 .. 7 (0 past count) */
664
665/*u32 Xthal_virtual_exceptions;*/ /* bitmask of which exceptions execute in virtual mode... */
666
667extern const char Xthal_mmu_pte_pagesz_log2_min; /* ?? minimum page size in PTEs */
668extern const char Xthal_mmu_pte_pagesz_log2_max; /* ?? maximum page size in PTEs */
669
670/* Cache Attribute Bits Implemented by the Cache (part of the cache abstraction) */
671extern const char Xthal_icache_fca_bits_implemented; /* ITLB/UTLB only! */
672extern const char Xthal_dcache_lca_bits_implemented; /* DTLB/UTLB only! */
673extern const char Xthal_dcache_sca_bits_implemented; /* DTLB/UTLB only! */
674
675/* Per TLB Parameters (Instruction, Data, Unified) */
676struct XtHalMmuTlb Xthal_itlb; /* description of MMU I-TLB generic features */
677struct XtHalMmuTlb Xthal_dtlb; /* description of MMU D-TLB generic features */
678struct XtHalMmuTlb Xthal_utlb; /* description of MMU U-TLB generic features */
679
680#define XTHAL_MMU_WAYS_MAX 8 /* maximum number of ways (associativities) for each TLB */
681
682/* Structure for common information described for each possible TLB (instruction, data and unified): */
683typedef struct XtHalMmuTlb {
684 u8 va_bits; /* 32 (number of virtual address bits) */
685 u8 pa_bits; /* 32 (number of physical address bits) */
686 bool tlb_va_indexed; /* 1 (set if TLB is indexed by virtual address) */
687 bool tlb_va_tagged; /* 0 (set if TLB is tagged by virtual address) */
688 bool cache_va_indexed; /* 1 (set if cache is indexed by virtual address) */
689 bool cache_va_tagged; /* 0 (set if cache is tagged by virtual address) */
690 /*bool (whether page tables are traversed in vaddr sorted order, paddr sorted order, ...) */
691 /*u8 (set of available page attribute bits, other than cache attribute bits defined above) */
692 /*u32 (various masks for pages, MMU table/TLB entries, etc.) */
693 u8 way_count; /* 0 .. 8 (number of ways, a.k.a. associativities, for this TLB) */
694 XtHalMmuTlbWay * ways[XTHAL_MMU_WAYS_MAX]; /* pointers to per-way parms for each way */
695} XtHalMmuTlb;
696
697/* Per TLB Way (Per Associativity) Parameters */
698typedef struct XtHalMmuTlbWay {
699 u32 index_count_log2; /* 0 .. 4 */
700 u32 pagesz_mask; /* 0 .. 2^pagesz_count - 1 (each bit corresponds to a size */
701 /* defined in the Xthal_mmu_pagesz_log2[] table) */
702 u32 vpn_const_mask;
703 u32 vpn_const_value;
704 u64 ppn_const_mask; /* future may support pa_bits > 32 */
705 u64 ppn_const_value;
706 u32 ppn_id_mask; /* paddr bits taken directly from vaddr */
707 bool backgnd_match; /* 0 or 1 */
708 /* These are defined in terms of the XTHAL_CACHE_xxx bits: */
709 u8 fca_const_mask; /* ITLB/UTLB only! */
710 u8 fca_const_value; /* ITLB/UTLB only! */
711 u8 lca_const_mask; /* DTLB/UTLB only! */
712 u8 lca_const_value; /* DTLB/UTLB only! */
713 u8 sca_const_mask; /* DTLB/UTLB only! */
714 u8 sca_const_value; /* DTLB/UTLB only! */
715 /* These define an encoding that map 5 bits in TLB and PTE entries to */
716 /* 8 bits (FCA, ITLB), 16 bits (LCA+SCA, DTLB) or 24 bits (FCA+LCA+SCA, UTLB): */
717 /* (they may be moved to struct XtHalMmuTlb) */
718 u8 ca_bits; /* number of bits in TLB/PTE entries for cache attributes */
719 u32 * ca_map; /* pointer to array of 2^ca_bits entries of FCA+LCA+SCA bits */
720} XtHalMmuTlbWay;
721
722/*
723 * The way to determine whether protection support is present in core
724 * is to [look at Xthal_mmu_rings ???].
725 * Give info on memory requirements for MMU tables and other in-memory
726 * data structures (globally, per task, base and per page, etc.) - whatever bounds can be calculated.
727 */
728
729
730/* Default vectors: */
731xthal_immu_fetch_miss_vector
732xthal_dmmu_load_miss_vector
733xthal_dmmu_store_miss_vector
734
735/* Functions called when a fault is detected: */
736typedef void (XtHalMmuFaultFunc)( unsigned vaddr, ...context... );
737/* Or, */
738/* a? = vaddr */
739/* a? = context... */
740/* PS.xxx = xxx */
741XtHalMMuFaultFunc *Xthal_immu_fetch_fault_func;
742XtHalMMuFaultFunc *Xthal_dmmu_load_fault_func;
743XtHalMMuFaultFunc *Xthal_dmmu_store_fault_func;
744
745/* Default Handlers: */
746/* The user and/or kernel exception handlers may jump to these handlers to handle the relevant exceptions,
747 * according to the value of EXCCAUSE. The exact register state on entry to these handlers is TBD. */
748/* When multiple TLB entries match (hit) on the same access: */
749xthal_immu_fetch_multihit_handler
750xthal_dmmu_load_multihit_handler
751xthal_dmmu_store_multihit_handler
752/* Protection violations according to cache attributes, and other cache attribute mismatches: */
753xthal_immu_fetch_attr_handler
754xthal_dmmu_load_attr_handler
755xthal_dmmu_store_attr_handler
756/* Protection violations due to insufficient ring level: */
757xthal_immu_fetch_priv_handler
758xthal_dmmu_load_priv_handler
759xthal_dmmu_store_priv_handler
760/* Alignment exception handlers (if supported by the particular Xtensa MMU configuration): */
761xthal_dmmu_load_align_handler
762xthal_dmmu_store_align_handler
763
764/* Or, alternatively, the OS user and/or kernel exception handlers may simply jump to the
765 * following entry points which will handle any values of EXCCAUSE not handled by the OS: */
766xthal_user_exc_default_handler
767xthal_kernel_exc_default_handler
768
769#endif /*0*/
770
771#ifdef INCLUDE_DEPRECATED_HAL_CODE
772extern const unsigned char Xthal_have_old_exc_arch;
773extern const unsigned char Xthal_have_mmu;
774extern const unsigned int Xthal_num_regs;
775extern const unsigned char Xthal_num_iroms;
776extern const unsigned char Xthal_num_irams;
777extern const unsigned char Xthal_num_droms;
778extern const unsigned char Xthal_num_drams;
779extern const unsigned int Xthal_configid0;
780extern const unsigned int Xthal_configid1;
781#endif
782
783#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE
784#define XTHAL_24_BIT_BREAK 0x80000000
785#define XTHAL_16_BIT_BREAK 0x40000000
786extern const unsigned short Xthal_ill_inst_16[16];
787#define XTHAL_DEST_REG 0xf0000000 /* Mask for destination register */
788#define XTHAL_DEST_REG_INST 0x08000000 /* Branch address is in register */
789#define XTHAL_DEST_REL_INST 0x04000000 /* Branch address is relative */
790#define XTHAL_RFW_INST 0x00000800
791#define XTHAL_RFUE_INST 0x00000400
792#define XTHAL_RFI_INST 0x00000200
793#define XTHAL_RFE_INST 0x00000100
794#define XTHAL_RET_INST 0x00000080
795#define XTHAL_BREAK_INST 0x00000040
796#define XTHAL_SYSCALL_INST 0x00000020
797#define XTHAL_LOOP_END 0x00000010 /* Not set by xthal_inst_type */
798#define XTHAL_JUMP_INST 0x00000008 /* Call or jump instruction */
799#define XTHAL_BRANCH_INST 0x00000004 /* Branch instruction */
800#define XTHAL_24_BIT_INST 0x00000002
801#define XTHAL_16_BIT_INST 0x00000001
802typedef struct xthal_state {
803 unsigned pc;
804 unsigned ar[16];
805 unsigned lbeg;
806 unsigned lend;
807 unsigned lcount;
808 unsigned extra_ptr;
809 unsigned cpregs_ptr[XTHAL_MAX_CPS];
810} XTHAL_STATE;
811extern unsigned int xthal_inst_type(void *addr);
812extern unsigned int xthal_branch_addr(void *addr);
813extern unsigned int xthal_get_npc(XTHAL_STATE *user_state);
814#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */
815
816#ifdef __cplusplus
817}
818#endif
819#endif /*!__ASSEMBLY__ */
820
821#endif /*XTENSA_HAL_H*/
822
diff --git a/include/asm-xtensa/xtensa/simcall.h b/include/asm-xtensa/xtensa/simcall.h
new file mode 100644
index 0000000000..a2b868929a
--- /dev/null
+++ b/include/asm-xtensa/xtensa/simcall.h
@@ -0,0 +1,130 @@
1#ifndef SIMCALL_INCLUDED
2#define SIMCALL_INCLUDED
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * include/asm-xtensa/xtensa/simcall.h - Simulator call numbers
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of
11 * this archive for more details.
12 *
13 * Copyright (C) 2002 Tensilica Inc.
14 */
15
16
17/*
18 * System call like services offered by the simulator host.
19 * These are modeled after the Linux 2.4 kernel system calls
20 * for Xtensa processors. However not all system calls and
21 * not all functionality of a given system call are implemented,
22 * or necessarily have well defined or equivalent semantics in
23 * the context of a simulation (as opposed to a Unix kernel).
24 *
25 * These services behave largely as if they had been invoked
26 * as a task in the simulator host's operating system
27 * (eg. files accessed are those of the simulator host).
28 * However, these SIMCALLs model a virtual operating system
29 * so that various definitions, bit assignments etc
30 * (eg. open mode bits, errno values, etc) are independent
31 * of the host operating system used to run the simulation.
32 * Rather these definitions are specific to the Xtensa ISS.
33 * This way Xtensa ISA code written to use these SIMCALLs
34 * can (in principle) be simulated on any host.
35 *
36 * Up to 6 parameters are passed in registers a3 to a8
37 * (note the 6th parameter isn't passed on the stack,
38 * unlike windowed function calling conventions).
39 * The return value is in a2. A negative value in the
40 * range -4096 to -1 indicates a negated error code to be
41 * reported in errno with a return value of -1, otherwise
42 * the value in a2 is returned as is.
43 */
44
45/* These #defines need to match what's in Xtensa/OS/vxworks/xtiss/simcalls.c */
46
47#define SYS_nop 0 /* n/a - setup; used to flush register windows */
48#define SYS_exit 1 /*x*/
49#define SYS_fork 2
50#define SYS_read 3 /*x*/
51#define SYS_write 4 /*x*/
52#define SYS_open 5 /*x*/
53#define SYS_close 6 /*x*/
54#define SYS_rename 7 /*x 38 - waitpid */
55#define SYS_creat 8 /*x*/
56#define SYS_link 9 /*x (not implemented on WIN32) */
57#define SYS_unlink 10 /*x*/
58#define SYS_execv 11 /* n/a - execve */
59#define SYS_execve 12 /* 11 - chdir */
60#define SYS_pipe 13 /* 42 - time */
61#define SYS_stat 14 /* 106 - mknod */
62#define SYS_chmod 15
63#define SYS_chown 16 /* 202 - lchown */
64#define SYS_utime 17 /* 30 - break */
65#define SYS_wait 18 /* n/a - oldstat */
66#define SYS_lseek 19 /*x*/
67#define SYS_getpid 20
68#define SYS_isatty 21 /* n/a - mount */
69#define SYS_fstat 22 /* 108 - oldumount */
70#define SYS_time 23 /* 13 - setuid */
71#define SYS_gettimeofday 24 /*x 78 - getuid (not implemented on WIN32) */
72#define SYS_times 25 /*X 43 - stime (Xtensa-specific implementation) */
73#define SYS_socket 26
74#define SYS_sendto 27
75#define SYS_recvfrom 28
76#define SYS_select_one 29 /* not compitible select, one file descriptor at the time */
77#define SYS_bind 30
78#define SYS_ioctl 31
79
80/*
81 * Other...
82 */
83#define SYS_iss_argc 1000 /* returns value of argc */
84#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */
85#define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */
86
87/*
88 * SIMCALLs for the ferret memory debugger. All are invoked by
89 * libferret.a ... ( Xtensa/Target-Libs/ferret )
90 */
91#define SYS_ferret 1010
92#define SYS_malloc 1011
93#define SYS_free 1012
94#define SYS_more_heap 1013
95#define SYS_no_heap 1014
96
97
98/*
99 * Extra SIMCALLs for GDB:
100 */
101#define SYS_gdb_break -1 /* invoked by XTOS on user exceptions if EPC points
102 to a break.n/break, regardless of cause! */
103#define SYS_xmon_out -2 /* invoked by XMON: ... */
104#define SYS_xmon_in -3 /* invoked by XMON: ... */
105#define SYS_xmon_flush -4 /* invoked by XMON: ... */
106#define SYS_gdb_abort -5 /* invoked by XTOS in _xtos_panic() */
107#define SYS_gdb_illegal_inst -6 /* invoked by XTOS for illegal instructions (too deeply) */
108#define SYS_xmon_init -7 /* invoked by XMON: ... */
109#define SYS_gdb_enter_sktloop -8 /* invoked by XTOS on debug exceptions */
110
111/*
112 * SIMCALLs for vxWorks xtiss BSP:
113 */
114#define SYS_setup_ppp_pipes -83
115#define SYS_log_msg -84
116
117/*
118 * Test SIMCALLs:
119 */
120#define SYS_test_write_state -100
121#define SYS_test_read_state -101
122
123/*
124 * SYS_select_one specifiers
125 */
126#define XTISS_SELECT_ONE_READ 1
127#define XTISS_SELECT_ONE_WRITE 2
128#define XTISS_SELECT_ONE_EXCEPT 3
129
130#endif /* !SIMCALL_INCLUDED */
diff --git a/include/asm-xtensa/xtensa/xt2000-uart.h b/include/asm-xtensa/xtensa/xt2000-uart.h
new file mode 100644
index 0000000000..0154460f0e
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xt2000-uart.h
@@ -0,0 +1,155 @@
1#ifndef _uart_h_included_
2#define _uart_h_included_
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * include/asm-xtensa/xtensa/xt2000-uart.h -- NatSemi PC16552D DUART
8 * definitions
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file "COPYING" in the main directory of this archive
12 * for more details.
13 *
14 * Copyright (C) 2002 Tensilica Inc.
15 */
16
17
18#include <xtensa/xt2000.h>
19
20
21/* 16550 UART DEVICE REGISTERS
22 The XT2000 board aligns each register to a 32-bit word but the UART device only uses
23 one byte of the word, which is the least-significant byte regardless of the
24 endianness of the core (ie. byte offset 0 for little-endian and 3 for big-endian).
25 So if using word accesses then endianness doesn't matter.
26 The macros provided here do that.
27*/
28struct uart_dev_s {
29 union {
30 unsigned int rxb; /* DLAB=0: receive buffer, read-only */
31 unsigned int txb; /* DLAB=0: transmit buffer, write-only */
32 unsigned int dll; /* DLAB=1: divisor, least-significant byte latch (was write-only?) */
33 } w0;
34 union {
35 unsigned int ier; /* DLAB=0: interrupt-enable register (was write-only?) */
36 unsigned int dlm; /* DLAB=1: divisor, most-significant byte latch (was write-only?) */
37 } w1;
38
39 union {
40 unsigned int isr; /* DLAB=0: interrupt status register, read-only */
41 unsigned int fcr; /* DLAB=0: FIFO control register, write-only */
42 unsigned int afr; /* DLAB=1: alternate function register */
43 } w2;
44
45 unsigned int lcr; /* line control-register, write-only */
46 unsigned int mcr; /* modem control-regsiter, write-only */
47 unsigned int lsr; /* line status register, read-only */
48 unsigned int msr; /* modem status register, read-only */
49 unsigned int scr; /* scratch regsiter, read/write */
50};
51
52#define _RXB(u) ((u)->w0.rxb)
53#define _TXB(u) ((u)->w0.txb)
54#define _DLL(u) ((u)->w0.dll)
55#define _IER(u) ((u)->w1.ier)
56#define _DLM(u) ((u)->w1.dlm)
57#define _ISR(u) ((u)->w2.isr)
58#define _FCR(u) ((u)->w2.fcr)
59#define _AFR(u) ((u)->w2.afr)
60#define _LCR(u) ((u)->lcr)
61#define _MCR(u) ((u)->mcr)
62#define _LSR(u) ((u)->lsr)
63#define _MSR(u) ((u)->msr)
64#define _SCR(u) ((u)->scr)
65
66typedef volatile struct uart_dev_s uart_dev_t;
67
68/* IER bits */
69#define RCVR_DATA_REG_INTENABLE 0x01
70#define XMIT_HOLD_REG_INTENABLE 0x02
71#define RCVR_STATUS_INTENABLE 0x04
72#define MODEM_STATUS_INTENABLE 0x08
73
74/* FCR bits */
75#define _FIFO_ENABLE 0x01
76#define RCVR_FIFO_RESET 0x02
77#define XMIT_FIFO_RESET 0x04
78#define DMA_MODE_SELECT 0x08
79#define RCVR_TRIGGER_LSB 0x40
80#define RCVR_TRIGGER_MSB 0x80
81
82/* AFR bits */
83#define AFR_CONC_WRITE 0x01
84#define AFR_BAUDOUT_SEL 0x02
85#define AFR_RXRDY_SEL 0x04
86
87/* ISR bits */
88#define INT_STATUS(r) ((r)&1)
89#define INT_PRIORITY(r) (((r)>>1)&0x7)
90
91/* LCR bits */
92#define WORD_LENGTH(n) (((n)-5)&0x3)
93#define STOP_BIT_ENABLE 0x04
94#define PARITY_ENABLE 0x08
95#define EVEN_PARITY 0x10
96#define FORCE_PARITY 0x20
97#define XMIT_BREAK 0x40
98#define DLAB_ENABLE 0x80
99
100/* MCR bits */
101#define _DTR 0x01
102#define _RTS 0x02
103#define _OP1 0x04
104#define _OP2 0x08
105#define LOOP_BACK 0x10
106
107/* LSR Bits */
108#define RCVR_DATA_READY 0x01
109#define OVERRUN_ERROR 0x02
110#define PARITY_ERROR 0x04
111#define FRAMING_ERROR 0x08
112#define BREAK_INTERRUPT 0x10
113#define XMIT_HOLD_EMPTY 0x20
114#define XMIT_EMPTY 0x40
115#define FIFO_ERROR 0x80
116#define RCVR_READY(u) (_LSR(u)&RCVR_DATA_READY)
117#define XMIT_READY(u) (_LSR(u)&XMIT_HOLD_EMPTY)
118
119/* MSR bits */
120#define _RDR 0x01
121#define DELTA_DSR 0x02
122#define DELTA_RI 0x04
123#define DELTA_CD 0x08
124#define _CTS 0x10
125#define _DSR 0x20
126#define _RI 0x40
127#define _CD 0x80
128
129/* prototypes */
130void uart_init( uart_dev_t *u, int bitrate );
131void uart_out( uart_dev_t *u, char c );
132void uart_puts( uart_dev_t *u, char *s );
133char uart_in( uart_dev_t *u );
134void uart_enable_rcvr_int( uart_dev_t *u );
135void uart_disable_rcvr_int( uart_dev_t *u );
136
137#ifdef DUART16552_1_VADDR
138/* DUART present. */
139#define DUART_1_BASE (*(uart_dev_t*)DUART16552_1_VADDR)
140#define DUART_2_BASE (*(uart_dev_t*)DUART16552_2_VADDR)
141#define UART1_PUTS(s) uart_puts( &DUART_1_BASE, s )
142#define UART2_PUTS(s) uart_puts( &DUART_2_BASE, s )
143#else
144/* DUART not configured, use dummy placeholders to allow compiles to work. */
145#define DUART_1_BASE (*(uart_dev_t*)0)
146#define DUART_2_BASE (*(uart_dev_t*)0)
147#define UART1_PUTS(s)
148#define UART2_PUTS(s)
149#endif
150
151/* Compute 16-bit divisor for baudrate generator, with rounding: */
152#define DUART_DIVISOR(crystal,speed) (((crystal)/16 + (speed)/2)/(speed))
153
154#endif /*_uart_h_included_*/
155
diff --git a/include/asm-xtensa/xtensa/xt2000.h b/include/asm-xtensa/xtensa/xt2000.h
new file mode 100644
index 0000000000..703a45002f
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xt2000.h
@@ -0,0 +1,408 @@
1#ifndef _INC_XT2000_H_
2#define _INC_XT2000_H_
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * include/asm-xtensa/xtensa/xt2000.h - Definitions specific to the
8 * Tensilica XT2000 Emulation Board
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file "COPYING" in the main directory of this archive
12 * for more details.
13 *
14 * Copyright (C) 2002 Tensilica Inc.
15 */
16
17
18#include <xtensa/config/core.h>
19#include <xtensa/config/system.h>
20
21
22/*
23 * Default assignment of XT2000 devices to external interrupts.
24 */
25
26/* Ethernet interrupt: */
27#ifdef XCHAL_EXTINT3_NUM
28#define SONIC83934_INTNUM XCHAL_EXTINT3_NUM
29#define SONIC83934_INTLEVEL XCHAL_EXTINT3_LEVEL
30#define SONIC83934_INTMASK XCHAL_EXTINT3_MASK
31#else
32#define SONIC83934_INTMASK 0
33#endif
34
35/* DUART channel 1 interrupt (P1 - console): */
36#ifdef XCHAL_EXTINT4_NUM
37#define DUART16552_1_INTNUM XCHAL_EXTINT4_NUM
38#define DUART16552_1_INTLEVEL XCHAL_EXTINT4_LEVEL
39#define DUART16552_1_INTMASK XCHAL_EXTINT4_MASK
40#else
41#define DUART16552_1_INTMASK 0
42#endif
43
44/* DUART channel 2 interrupt (P2 - 2nd serial port): */
45#ifdef XCHAL_EXTINT5_NUM
46#define DUART16552_2_INTNUM XCHAL_EXTINT5_NUM
47#define DUART16552_2_INTLEVEL XCHAL_EXTINT5_LEVEL
48#define DUART16552_2_INTMASK XCHAL_EXTINT5_MASK
49#else
50#define DUART16552_2_INTMASK 0
51#endif
52
53/* FPGA-combined PCI/etc interrupts: */
54#ifdef XCHAL_EXTINT6_NUM
55#define XT2000_FPGAPCI_INTNUM XCHAL_EXTINT6_NUM
56#define XT2000_FPGAPCI_INTLEVEL XCHAL_EXTINT6_LEVEL
57#define XT2000_FPGAPCI_INTMASK XCHAL_EXTINT6_MASK
58#else
59#define XT2000_FPGAPCI_INTMASK 0
60#endif
61
62
63
64/*
65 * Device addresses.
66 *
67 * Note: for endianness-independence, use 32-bit loads and stores for all
68 * register accesses to Ethernet, DUART and LED devices. Undefined bits
69 * may need to be masked out if needed when reading if the actual register
70 * size is smaller than 32 bits.
71 *
72 * Note: XT2000 bus byte lanes are defined in terms of msbyte and lsbyte
73 * relative to the processor. So 32-bit registers are accessed consistently
74 * from both big and little endian processors. However, this means byte
75 * sequences are not consistent between big and little endian processors.
76 * This is fine for RAM, and for ROM if ROM is created for a specific
77 * processor (and thus has correct byte sequences). However this may be
78 * unexpected for Flash, which might contain a file-system that one wants
79 * to use for multiple processor configurations (eg. the Flash might contain
80 * the Ethernet card's address, endianness-independent application data, etc).
81 * That is, byte sequences written in Flash by a core of a given endianness
82 * will be byte-swapped when seen by a core of the other endianness.
83 * Someone implementing an endianness-independent Flash file system will
84 * likely handle this byte-swapping issue in the Flash driver software.
85 */
86
87#define DUART16552_XTAL_FREQ 18432000 /* crystal frequency in Hz */
88#define XTBOARD_FLASH_MAXSIZE 0x4000000 /* 64 MB (max; depends on what is socketed!) */
89#define XTBOARD_EPROM_MAXSIZE 0x0400000 /* 4 MB (max; depends on what is socketed!) */
90#define XTBOARD_EEPROM_MAXSIZE 0x0080000 /* 512 kB (max; depends on what is socketed!) */
91#define XTBOARD_ASRAM_SIZE 0x0100000 /* 1 MB */
92#define XTBOARD_PCI_MEM_SIZE 0x8000000 /* 128 MB (allocated) */
93#define XTBOARD_PCI_IO_SIZE 0x1000000 /* 16 MB (allocated) */
94
95#ifdef XSHAL_IOBLOCK_BYPASS_PADDR
96/* PCI memory space: */
97# define XTBOARD_PCI_MEM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0000000)
98/* Socketed Flash (eg. 2 x 16-bit devices): */
99# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x8000000)
100/* PCI I/O space: */
101# define XTBOARD_PCI_IO_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xC000000)
102/* V3 PCI interface chip register/config space: */
103# define XTBOARD_V3PCI_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD000000)
104/* Bus Interface registers: */
105# define XTBOARD_BUSINT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD010000)
106/* FPGA registers: */
107# define XT2000_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD020000)
108/* SONIC SN83934 Ethernet controller/transceiver: */
109# define SONIC83934_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD030000)
110/* 8-character bitmapped LED display: */
111# define XTBOARD_LED_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD040000)
112/* National-Semi PC16552D DUART: */
113# define DUART16552_1_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD050020) /* channel 1 (P1 - console) */
114# define DUART16552_2_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD050000) /* channel 2 (P2) */
115/* Asynchronous Static RAM: */
116# define XTBOARD_ASRAM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD400000)
117/* 8-bit EEPROM: */
118# define XTBOARD_EEPROM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD600000)
119/* 2 x 16-bit EPROMs: */
120# define XTBOARD_EPROM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD800000)
121#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */
122
123/* These devices might be accessed cached: */
124#ifdef XSHAL_IOBLOCK_CACHED_PADDR
125# define XTBOARD_PCI_MEM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0000000)
126# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x8000000)
127# define XTBOARD_ASRAM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD400000)
128# define XTBOARD_EEPROM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD600000)
129# define XTBOARD_EPROM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD800000)
130#endif /* XSHAL_IOBLOCK_CACHED_PADDR */
131
132
133/*** Same thing over again, this time with virtual addresses: ***/
134
135#ifdef XSHAL_IOBLOCK_BYPASS_VADDR
136/* PCI memory space: */
137# define XTBOARD_PCI_MEM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0000000)
138/* Socketed Flash (eg. 2 x 16-bit devices): */
139# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x8000000)
140/* PCI I/O space: */
141# define XTBOARD_PCI_IO_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xC000000)
142/* V3 PCI interface chip register/config space: */
143# define XTBOARD_V3PCI_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD000000)
144/* Bus Interface registers: */
145# define XTBOARD_BUSINT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD010000)
146/* FPGA registers: */
147# define XT2000_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD020000)
148/* SONIC SN83934 Ethernet controller/transceiver: */
149# define SONIC83934_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD030000)
150/* 8-character bitmapped LED display: */
151# define XTBOARD_LED_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD040000)
152/* National-Semi PC16552D DUART: */
153# define DUART16552_1_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD050020) /* channel 1 (P1 - console) */
154# define DUART16552_2_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD050000) /* channel 2 (P2) */
155/* Asynchronous Static RAM: */
156# define XTBOARD_ASRAM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD400000)
157/* 8-bit EEPROM: */
158# define XTBOARD_EEPROM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD600000)
159/* 2 x 16-bit EPROMs: */
160# define XTBOARD_EPROM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD800000)
161#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */
162
163/* These devices might be accessed cached: */
164#ifdef XSHAL_IOBLOCK_CACHED_VADDR
165# define XTBOARD_PCI_MEM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0000000)
166# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x8000000)
167# define XTBOARD_ASRAM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD400000)
168# define XTBOARD_EEPROM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD600000)
169# define XTBOARD_EPROM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD800000)
170#endif /* XSHAL_IOBLOCK_CACHED_VADDR */
171
172
173/* System ROM: */
174#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE
175#ifdef XSHAL_ROM_VADDR
176#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR
177#endif
178#ifdef XSHAL_ROM_PADDR
179#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR
180#endif
181
182/* System RAM: */
183#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE
184#ifdef XSHAL_RAM_VADDR
185#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR
186#endif
187#ifdef XSHAL_RAM_PADDR
188#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR
189#endif
190#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR
191#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR
192
193
194
195/*
196 * Things that depend on device addresses.
197 */
198
199
200#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK
201#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC
202#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU
203#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS
204#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT
205
206#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS
207#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS
208
209
210
211/*
212 * BusLogic (FPGA) registers.
213 * All these registers are normally accessed using 32-bit loads/stores.
214 */
215
216/* Register offsets: */
217#define XT2000_DATECD_OFS 0x00 /* date code (read-only) */
218#define XT2000_STSREG_OFS 0x04 /* status (read-only) */
219#define XT2000_SYSLED_OFS 0x08 /* system LED */
220#define XT2000_WRPROT_OFS 0x0C /* write protect */
221#define XT2000_SWRST_OFS 0x10 /* software reset */
222#define XT2000_SYSRST_OFS 0x14 /* system (peripherals) reset */
223#define XT2000_IMASK_OFS 0x18 /* interrupt mask */
224#define XT2000_ISTAT_OFS 0x1C /* interrupt status */
225#define XT2000_V3CFG_OFS 0x20 /* V3 config (V320 PCI) */
226
227/* Physical register addresses: */
228#ifdef XT2000_FPGAREGS_PADDR
229#define XT2000_DATECD_PADDR (XT2000_FPGAREGS_PADDR+XT2000_DATECD_OFS)
230#define XT2000_STSREG_PADDR (XT2000_FPGAREGS_PADDR+XT2000_STSREG_OFS)
231#define XT2000_SYSLED_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SYSLED_OFS)
232#define XT2000_WRPROT_PADDR (XT2000_FPGAREGS_PADDR+XT2000_WRPROT_OFS)
233#define XT2000_SWRST_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SWRST_OFS)
234#define XT2000_SYSRST_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SYSRST_OFS)
235#define XT2000_IMASK_PADDR (XT2000_FPGAREGS_PADDR+XT2000_IMASK_OFS)
236#define XT2000_ISTAT_PADDR (XT2000_FPGAREGS_PADDR+XT2000_ISTAT_OFS)
237#define XT2000_V3CFG_PADDR (XT2000_FPGAREGS_PADDR+XT2000_V3CFG_OFS)
238#endif
239
240/* Virtual register addresses: */
241#ifdef XT2000_FPGAREGS_VADDR
242#define XT2000_DATECD_VADDR (XT2000_FPGAREGS_VADDR+XT2000_DATECD_OFS)
243#define XT2000_STSREG_VADDR (XT2000_FPGAREGS_VADDR+XT2000_STSREG_OFS)
244#define XT2000_SYSLED_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SYSLED_OFS)
245#define XT2000_WRPROT_VADDR (XT2000_FPGAREGS_VADDR+XT2000_WRPROT_OFS)
246#define XT2000_SWRST_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SWRST_OFS)
247#define XT2000_SYSRST_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SYSRST_OFS)
248#define XT2000_IMASK_VADDR (XT2000_FPGAREGS_VADDR+XT2000_IMASK_OFS)
249#define XT2000_ISTAT_VADDR (XT2000_FPGAREGS_VADDR+XT2000_ISTAT_OFS)
250#define XT2000_V3CFG_VADDR (XT2000_FPGAREGS_VADDR+XT2000_V3CFG_OFS)
251/* Register access (for C code): */
252#define XT2000_DATECD_REG (*(volatile unsigned*) XT2000_DATECD_VADDR)
253#define XT2000_STSREG_REG (*(volatile unsigned*) XT2000_STSREG_VADDR)
254#define XT2000_SYSLED_REG (*(volatile unsigned*) XT2000_SYSLED_VADDR)
255#define XT2000_WRPROT_REG (*(volatile unsigned*) XT2000_WRPROT_VADDR)
256#define XT2000_SWRST_REG (*(volatile unsigned*) XT2000_SWRST_VADDR)
257#define XT2000_SYSRST_REG (*(volatile unsigned*) XT2000_SYSRST_VADDR)
258#define XT2000_IMASK_REG (*(volatile unsigned*) XT2000_IMASK_VADDR)
259#define XT2000_ISTAT_REG (*(volatile unsigned*) XT2000_ISTAT_VADDR)
260#define XT2000_V3CFG_REG (*(volatile unsigned*) XT2000_V3CFG_VADDR)
261#endif
262
263/* DATECD (date code) bit fields: */
264
265/* BCD-coded month (01..12): */
266#define XT2000_DATECD_MONTH_SHIFT 24
267#define XT2000_DATECD_MONTH_BITS 8
268#define XT2000_DATECD_MONTH_MASK 0xFF000000
269/* BCD-coded day (01..31): */
270#define XT2000_DATECD_DAY_SHIFT 16
271#define XT2000_DATECD_DAY_BITS 8
272#define XT2000_DATECD_DAY_MASK 0x00FF0000
273/* BCD-coded year (2001..9999): */
274#define XT2000_DATECD_YEAR_SHIFT 0
275#define XT2000_DATECD_YEAR_BITS 16
276#define XT2000_DATECD_YEAR_MASK 0x0000FFFF
277
278/* STSREG (status) bit fields: */
279
280/* Switch SW3 setting bit fields (0=off/up, 1=on/down): */
281#define XT2000_STSREG_SW3_SHIFT 0
282#define XT2000_STSREG_SW3_BITS 4
283#define XT2000_STSREG_SW3_MASK 0x0000000F
284/* Boot-select bits of switch SW3: */
285#define XT2000_STSREG_BOOTSEL_SHIFT 0
286#define XT2000_STSREG_BOOTSEL_BITS 2
287#define XT2000_STSREG_BOOTSEL_MASK 0x00000003
288/* Boot-select values: */
289#define XT2000_STSREG_BOOTSEL_FLASH 0
290#define XT2000_STSREG_BOOTSEL_EPROM16 1
291#define XT2000_STSREG_BOOTSEL_PROM8 2
292#define XT2000_STSREG_BOOTSEL_ASRAM 3
293/* User-defined bits of switch SW3: */
294#define XT2000_STSREG_SW3_2_SHIFT 2
295#define XT2000_STSREG_SW3_2_MASK 0x00000004
296#define XT2000_STSREG_SW3_3_SHIFT 3
297#define XT2000_STSREG_SW3_3_MASK 0x00000008
298
299/* SYSLED (system LED) bit fields: */
300
301/* LED control bit (0=off, 1=on): */
302#define XT2000_SYSLED_LEDON_SHIFT 0
303#define XT2000_SYSLED_LEDON_MASK 0x00000001
304
305/* WRPROT (write protect) bit fields (0=writable, 1=write-protected [default]): */
306
307/* Flash write protect: */
308#define XT2000_WRPROT_FLWP_SHIFT 0
309#define XT2000_WRPROT_FLWP_MASK 0x00000001
310/* Reserved but present write protect bits: */
311#define XT2000_WRPROT_WRP_SHIFT 1
312#define XT2000_WRPROT_WRP_BITS 7
313#define XT2000_WRPROT_WRP_MASK 0x000000FE
314
315/* SWRST (software reset; allows s/w to generate power-on equivalent reset): */
316
317/* Software reset bits: */
318#define XT2000_SWRST_SWR_SHIFT 0
319#define XT2000_SWRST_SWR_BITS 16
320#define XT2000_SWRST_SWR_MASK 0x0000FFFF
321/* Software reset value -- writing this value resets the board: */
322#define XT2000_SWRST_RESETVALUE 0x0000DEAD
323
324/* SYSRST (system reset; controls reset of individual peripherals): */
325
326/* All-device reset: */
327#define XT2000_SYSRST_ALL_SHIFT 0
328#define XT2000_SYSRST_ALL_BITS 4
329#define XT2000_SYSRST_ALL_MASK 0x0000000F
330/* HDSP-2534 LED display reset (1=reset, 0=nothing): */
331#define XT2000_SYSRST_LED_SHIFT 0
332#define XT2000_SYSRST_LED_MASK 0x00000001
333/* Sonic DP83934 Ethernet controller reset (1=reset, 0=nothing): */
334#define XT2000_SYSRST_SONIC_SHIFT 1
335#define XT2000_SYSRST_SONIC_MASK 0x00000002
336/* DP16552 DUART reset (1=reset, 0=nothing): */
337#define XT2000_SYSRST_DUART_SHIFT 2
338#define XT2000_SYSRST_DUART_MASK 0x00000004
339/* V3 V320 PCI bridge controller reset (1=reset, 0=nothing): */
340#define XT2000_SYSRST_V3_SHIFT 3
341#define XT2000_SYSRST_V3_MASK 0x00000008
342
343/* IMASK (interrupt mask; 0=disable, 1=enable): */
344/* ISTAT (interrupt status; 0=inactive, 1=pending): */
345
346/* PCI INTP interrupt: */
347#define XT2000_INTMUX_PCI_INTP_SHIFT 2
348#define XT2000_INTMUX_PCI_INTP_MASK 0x00000004
349/* PCI INTS interrupt: */
350#define XT2000_INTMUX_PCI_INTS_SHIFT 3
351#define XT2000_INTMUX_PCI_INTS_MASK 0x00000008
352/* PCI INTD interrupt: */
353#define XT2000_INTMUX_PCI_INTD_SHIFT 4
354#define XT2000_INTMUX_PCI_INTD_MASK 0x00000010
355/* V320 PCI controller interrupt: */
356#define XT2000_INTMUX_V3_SHIFT 5
357#define XT2000_INTMUX_V3_MASK 0x00000020
358/* PCI ENUM interrupt: */
359#define XT2000_INTMUX_PCI_ENUM_SHIFT 6
360#define XT2000_INTMUX_PCI_ENUM_MASK 0x00000040
361/* PCI DEG interrupt: */
362#define XT2000_INTMUX_PCI_DEG_SHIFT 7
363#define XT2000_INTMUX_PCI_DEG_MASK 0x00000080
364
365/* V3CFG (V3 config, V320 PCI controller): */
366
367/* V3 address control (0=pass-thru, 1=V3 address bits 31:28 set to 4'b0001 [default]): */
368#define XT2000_V3CFG_V3ADC_SHIFT 0
369#define XT2000_V3CFG_V3ADC_MASK 0x00000001
370
371/* I2C Devices */
372
373#define XT2000_I2C_RTC_ID 0x68
374#define XT2000_I2C_NVRAM0_ID 0x56 /* 1st 256 byte block */
375#define XT2000_I2C_NVRAM1_ID 0x57 /* 2nd 256 byte block */
376
377/* NVRAM Board Info structure: */
378
379#define XT2000_NVRAM_SIZE 512
380
381#define XT2000_NVRAM_BINFO_START 0x100
382#define XT2000_NVRAM_BINFO_SIZE 0x20
383#define XT2000_NVRAM_BINFO_VERSION 0x10 /* version 1.0 */
384#if 0
385#define XT2000_NVRAM_BINFO_VERSION_OFFSET 0x00
386#define XT2000_NVRAM_BINFO_VERSION_SIZE 0x1
387#define XT2000_NVRAM_BINFO_ETH_ADDR_OFFSET 0x02
388#define XT2000_NVRAM_BINFO_ETH_ADDR_SIZE 0x6
389#define XT2000_NVRAM_BINFO_SN_OFFSET 0x10
390#define XT2000_NVRAM_BINFO_SN_SIZE 0xE
391#define XT2000_NVRAM_BINFO_CRC_OFFSET 0x1E
392#define XT2000_NVRAM_BINFO_CRC_SIZE 0x2
393#endif /*0*/
394
395#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
396typedef struct xt2000_nvram_binfo {
397 unsigned char version;
398 unsigned char reserved1;
399 unsigned char eth_addr[6];
400 unsigned char reserved8[8];
401 unsigned char serialno[14];
402 unsigned char crc[2]; /* 16-bit CRC */
403} xt2000_nvram_binfo;
404#endif /*!__ASSEMBLY__ && !_NOCLANGUAGE*/
405
406
407#endif /*_INC_XT2000_H_*/
408
diff --git a/include/asm-xtensa/xtensa/xtboard.h b/include/asm-xtensa/xtensa/xtboard.h
new file mode 100644
index 0000000000..22469c1753
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xtboard.h
@@ -0,0 +1,120 @@
1#ifndef _xtboard_h_included_
2#define _xtboard_h_included_
3
4/*
5 * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
6 *
7 * xtboard.h -- Routines for getting useful information from the board.
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 *
13 * Copyright (C) 2002 Tensilica Inc.
14 */
15
16
17#include <xtensa/xt2000.h>
18
19#define XTBOARD_RTC_ERROR -1
20#define XTBOARD_RTC_STOPPED -2
21
22
23/* xt2000-i2cdev.c: */
24typedef void XtboardDelayFunc( unsigned );
25extern XtboardDelayFunc* xtboard_set_nsdelay_func( XtboardDelayFunc *delay_fn );
26extern int xtboard_i2c_read (unsigned id, unsigned char *buf, unsigned addr, unsigned size);
27extern int xtboard_i2c_write(unsigned id, unsigned char *buf, unsigned addr, unsigned size);
28extern int xtboard_i2c_wait_nvram_ack(unsigned id, unsigned swtimer);
29
30/* xtboard.c: */
31extern int xtboard_nvram_read (unsigned addr, unsigned len, unsigned char *buf);
32extern int xtboard_nvram_write(unsigned addr, unsigned len, unsigned char *buf);
33extern int xtboard_nvram_binfo_read (xt2000_nvram_binfo *buf);
34extern int xtboard_nvram_binfo_write(xt2000_nvram_binfo *buf);
35extern int xtboard_nvram_binfo_valid(xt2000_nvram_binfo *buf);
36extern int xtboard_ethermac_get(unsigned char *buf);
37extern int xtboard_ethermac_set(unsigned char *buf);
38
39/*+*----------------------------------------------------------------------------
40/ Function: xtboard_get_rtc_time
41/
42/ Description: Get time stored in real-time clock.
43/
44/ Returns: time in seconds stored in real-time clock.
45/-**----------------------------------------------------------------------------*/
46
47extern unsigned xtboard_get_rtc_time(void);
48
49/*+*----------------------------------------------------------------------------
50/ Function: xtboard_set_rtc_time
51/
52/ Description: Set time stored in real-time clock.
53/
54/ Parameters: time -- time in seconds to store to real-time clock
55/
56/ Returns: 0 on success, xtboard_i2c_write() error code otherwise.
57/-**----------------------------------------------------------------------------*/
58
59extern int xtboard_set_rtc_time(unsigned time);
60
61
62/* xtfreq.c: */
63/*+*----------------------------------------------------------------------------
64/ Function: xtboard_measure_sys_clk
65/
66/ Description: Get frequency of system clock.
67/
68/ Parameters: none
69/
70/ Returns: frequency of system clock.
71/-**----------------------------------------------------------------------------*/
72
73extern unsigned xtboard_measure_sys_clk(void);
74
75
76#if 0 /* old stuff from xtboard.c: */
77
78/*+*----------------------------------------------------------------------------
79/ Function: xtboard_nvram valid
80/
81/ Description: Determines if data in NVRAM is valid.
82/
83/ Parameters: delay -- 10us delay function
84/
85/ Returns: 1 if NVRAM is valid, 0 otherwise
86/-**----------------------------------------------------------------------------*/
87
88extern unsigned xtboard_nvram_valid(void (*delay)( void ));
89
90/*+*----------------------------------------------------------------------------
91/ Function: xtboard_get_nvram_contents
92/
93/ Description: Returns contents of NVRAM.
94/
95/ Parameters: buf -- buffer to NVRAM contents.
96/ delay -- 10us delay function
97/
98/ Returns: 1 if NVRAM is valid, 0 otherwise
99/-**----------------------------------------------------------------------------*/
100
101extern unsigned xtboard_get_nvram_contents(unsigned char *buf, void (*delay)( void ));
102
103/*+*----------------------------------------------------------------------------
104/ Function: xtboard_get_ether_addr
105/
106/ Description: Returns ethernet address of board.
107/
108/ Parameters: buf -- buffer to store ethernet address
109/ delay -- 10us delay function
110/
111/ Returns: nothing.
112/-**----------------------------------------------------------------------------*/
113
114extern void xtboard_get_ether_addr(unsigned char *buf, void (*delay)( void ));
115
116#endif /*0*/
117
118
119#endif /*_xtboard_h_included_*/
120
diff --git a/include/linux/dqblk_v1.h b/include/linux/dqblk_v1.h
index 42fbf47971..57f1250d5a 100644
--- a/include/linux/dqblk_v1.h
+++ b/include/linux/dqblk_v1.h
@@ -11,6 +11,12 @@
11/* Root squash turned on */ 11/* Root squash turned on */
12#define V1_DQF_RSQUASH 1 12#define V1_DQF_RSQUASH 1
13 13
14/* Numbers of blocks needed for updates */
15#define V1_INIT_ALLOC 1
16#define V1_INIT_REWRITE 1
17#define V1_DEL_ALLOC 0
18#define V1_DEL_REWRITE 2
19
14/* Special information about quotafile */ 20/* Special information about quotafile */
15struct v1_mem_dqinfo { 21struct v1_mem_dqinfo {
16}; 22};
diff --git a/include/linux/dqblk_v2.h b/include/linux/dqblk_v2.h
index 4a6c5f6867..4f853322cb 100644
--- a/include/linux/dqblk_v2.h
+++ b/include/linux/dqblk_v2.h
@@ -10,6 +10,12 @@
10/* id numbers of quota format */ 10/* id numbers of quota format */
11#define QFMT_VFS_V0 2 11#define QFMT_VFS_V0 2
12 12
13/* Numbers of blocks needed for updates */
14#define V2_INIT_ALLOC 4
15#define V2_INIT_REWRITE 2
16#define V2_DEL_ALLOC 0
17#define V2_DEL_REWRITE 6
18
13/* Inmemory copy of version specific information */ 19/* Inmemory copy of version specific information */
14struct v2_mem_dqinfo { 20struct v2_mem_dqinfo {
15 unsigned int dqi_blocks; 21 unsigned int dqi_blocks;
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index fab43527e5..a657130ba0 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -300,18 +300,19 @@ struct ext2_inode {
300/* 300/*
301 * Mount flags 301 * Mount flags
302 */ 302 */
303#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ 303#define EXT2_MOUNT_CHECK 0x000001 /* Do mount-time checks */
304#define EXT2_MOUNT_OLDALLOC 0x0002 /* Don't use the new Orlov allocator */ 304#define EXT2_MOUNT_OLDALLOC 0x000002 /* Don't use the new Orlov allocator */
305#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ 305#define EXT2_MOUNT_GRPID 0x000004 /* Create files with directory's group */
306#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ 306#define EXT2_MOUNT_DEBUG 0x000008 /* Some debugging messages */
307#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ 307#define EXT2_MOUNT_ERRORS_CONT 0x000010 /* Continue on errors */
308#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ 308#define EXT2_MOUNT_ERRORS_RO 0x000020 /* Remount fs ro on errors */
309#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ 309#define EXT2_MOUNT_ERRORS_PANIC 0x000040 /* Panic on errors */
310#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ 310#define EXT2_MOUNT_MINIX_DF 0x000080 /* Mimics the Minix statfs */
311#define EXT2_MOUNT_NOBH 0x0100 /* No buffer_heads */ 311#define EXT2_MOUNT_NOBH 0x000100 /* No buffer_heads */
312#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ 312#define EXT2_MOUNT_NO_UID32 0x000200 /* Disable 32-bit UIDs */
313#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ 313#define EXT2_MOUNT_XATTR_USER 0x004000 /* Extended user attributes */
314#define EXT2_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ 314#define EXT2_MOUNT_POSIX_ACL 0x008000 /* POSIX Access Control Lists */
315#define EXT2_MOUNT_XIP 0x010000 /* Execute in place */
315 316
316#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt 317#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
317#define set_opt(o, opt) o |= EXT2_MOUNT_##opt 318#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 74ad31781e..4b6e1ab216 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -358,6 +358,7 @@ struct ext3_inode {
358#define EXT3_MOUNT_RESERVATION 0x10000 /* Preallocation */ 358#define EXT3_MOUNT_RESERVATION 0x10000 /* Preallocation */
359#define EXT3_MOUNT_BARRIER 0x20000 /* Use block barriers */ 359#define EXT3_MOUNT_BARRIER 0x20000 /* Use block barriers */
360#define EXT3_MOUNT_NOBH 0x40000 /* No bufferheads */ 360#define EXT3_MOUNT_NOBH 0x40000 /* No bufferheads */
361#define EXT3_MOUNT_QUOTA 0x80000 /* Some quota option set */
361 362
362/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ 363/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
363#ifndef _LINUX_EXT2_FS_H 364#ifndef _LINUX_EXT2_FS_H
diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
index e8292af903..c8307c02dd 100644
--- a/include/linux/ext3_jbd.h
+++ b/include/linux/ext3_jbd.h
@@ -42,15 +42,15 @@
42 * superblock only gets updated once, of course, so don't bother 42 * superblock only gets updated once, of course, so don't bother
43 * counting that again for the quota updates. */ 43 * counting that again for the quota updates. */
44 44
45#define EXT3_DATA_TRANS_BLOCKS (EXT3_SINGLEDATA_TRANS_BLOCKS + \ 45#define EXT3_DATA_TRANS_BLOCKS(sb) (EXT3_SINGLEDATA_TRANS_BLOCKS + \
46 EXT3_XATTR_TRANS_BLOCKS - 2 + \ 46 EXT3_XATTR_TRANS_BLOCKS - 2 + \
47 2*EXT3_QUOTA_TRANS_BLOCKS) 47 2*EXT3_QUOTA_TRANS_BLOCKS(sb))
48 48
49/* Delete operations potentially hit one directory's namespace plus an 49/* Delete operations potentially hit one directory's namespace plus an
50 * entire inode, plus arbitrary amounts of bitmap/indirection data. Be 50 * entire inode, plus arbitrary amounts of bitmap/indirection data. Be
51 * generous. We can grow the delete transaction later if necessary. */ 51 * generous. We can grow the delete transaction later if necessary. */
52 52
53#define EXT3_DELETE_TRANS_BLOCKS (2 * EXT3_DATA_TRANS_BLOCKS + 64) 53#define EXT3_DELETE_TRANS_BLOCKS(sb) (2 * EXT3_DATA_TRANS_BLOCKS(sb) + 64)
54 54
55/* Define an arbitrary limit for the amount of data we will anticipate 55/* Define an arbitrary limit for the amount of data we will anticipate
56 * writing to any given transaction. For unbounded transactions such as 56 * writing to any given transaction. For unbounded transactions such as
@@ -74,14 +74,17 @@
74#ifdef CONFIG_QUOTA 74#ifdef CONFIG_QUOTA
75/* Amount of blocks needed for quota update - we know that the structure was 75/* Amount of blocks needed for quota update - we know that the structure was
76 * allocated so we need to update only inode+data */ 76 * allocated so we need to update only inode+data */
77#define EXT3_QUOTA_TRANS_BLOCKS 2 77#define EXT3_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
78/* Amount of blocks needed for quota insert/delete - we do some block writes 78/* Amount of blocks needed for quota insert/delete - we do some block writes
79 * but inode, sb and group updates are done only once */ 79 * but inode, sb and group updates are done only once */
80#define EXT3_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*\ 80#define EXT3_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
81 (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3) 81 (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_INIT_REWRITE) : 0)
82#define EXT3_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
83 (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_DEL_REWRITE) : 0)
82#else 84#else
83#define EXT3_QUOTA_TRANS_BLOCKS 0 85#define EXT3_QUOTA_TRANS_BLOCKS(sb) 0
84#define EXT3_QUOTA_INIT_BLOCKS 0 86#define EXT3_QUOTA_INIT_BLOCKS(sb) 0
87#define EXT3_QUOTA_DEL_BLOCKS(sb) 0
85#endif 88#endif
86 89
87int 90int
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 517bf4966b..3ae8e37bdf 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -220,6 +220,7 @@ extern int dir_notify_enable;
220 220
221struct iovec; 221struct iovec;
222struct nameidata; 222struct nameidata;
223struct kiocb;
223struct pipe_inode_info; 224struct pipe_inode_info;
224struct poll_table_struct; 225struct poll_table_struct;
225struct kstatfs; 226struct kstatfs;
@@ -240,7 +241,7 @@ typedef int (get_block_t)(struct inode *inode, sector_t iblock,
240typedef int (get_blocks_t)(struct inode *inode, sector_t iblock, 241typedef int (get_blocks_t)(struct inode *inode, sector_t iblock,
241 unsigned long max_blocks, 242 unsigned long max_blocks,
242 struct buffer_head *bh_result, int create); 243 struct buffer_head *bh_result, int create);
243typedef void (dio_iodone_t)(struct inode *inode, loff_t offset, 244typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
244 ssize_t bytes, void *private); 245 ssize_t bytes, void *private);
245 246
246/* 247/*
@@ -302,7 +303,6 @@ struct iattr {
302struct page; 303struct page;
303struct address_space; 304struct address_space;
304struct writeback_control; 305struct writeback_control;
305struct kiocb;
306 306
307struct address_space_operations { 307struct address_space_operations {
308 int (*writepage)(struct page *page, struct writeback_control *wbc); 308 int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -330,6 +330,8 @@ struct address_space_operations {
330 int (*releasepage) (struct page *, int); 330 int (*releasepage) (struct page *, int);
331 ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov, 331 ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
332 loff_t offset, unsigned long nr_segs); 332 loff_t offset, unsigned long nr_segs);
333 struct page* (*get_xip_page)(struct address_space *, sector_t,
334 int);
333}; 335};
334 336
335struct backing_dev_info; 337struct backing_dev_info;
@@ -885,6 +887,7 @@ struct block_device_operations {
885 int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); 887 int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
886 long (*unlocked_ioctl) (struct file *, unsigned, unsigned long); 888 long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
887 long (*compat_ioctl) (struct file *, unsigned, unsigned long); 889 long (*compat_ioctl) (struct file *, unsigned, unsigned long);
890 int (*direct_access) (struct block_device *, sector_t, unsigned long *);
888 int (*media_changed) (struct gendisk *); 891 int (*media_changed) (struct gendisk *);
889 int (*revalidate_disk) (struct gendisk *); 892 int (*revalidate_disk) (struct gendisk *);
890 struct module *owner; 893 struct module *owner;
@@ -1496,6 +1499,23 @@ extern loff_t remote_llseek(struct file *file, loff_t offset, int origin);
1496extern int generic_file_open(struct inode * inode, struct file * filp); 1499extern int generic_file_open(struct inode * inode, struct file * filp);
1497extern int nonseekable_open(struct inode * inode, struct file * filp); 1500extern int nonseekable_open(struct inode * inode, struct file * filp);
1498 1501
1502#ifdef CONFIG_FS_XIP
1503extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
1504 loff_t *ppos);
1505extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos,
1506 size_t count, read_actor_t actor,
1507 void *target);
1508extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma);
1509extern ssize_t xip_file_write(struct file *filp, const char __user *buf,
1510 size_t len, loff_t *ppos);
1511extern int xip_truncate_page(struct address_space *mapping, loff_t from);
1512#else
1513static inline int xip_truncate_page(struct address_space *mapping, loff_t from)
1514{
1515 return 0;
1516}
1517#endif
1518
1499static inline void do_generic_file_read(struct file * filp, loff_t *ppos, 1519static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
1500 read_descriptor_t * desc, 1520 read_descriptor_t * desc,
1501 read_actor_t actor) 1521 read_actor_t actor)
diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h
index ef7f644dd8..36fd18cdad 100644
--- a/include/linux/i2o-dev.h
+++ b/include/linux/i2o-dev.h
@@ -24,6 +24,13 @@
24#define MAX_I2O_CONTROLLERS 32 24#define MAX_I2O_CONTROLLERS 32
25 25
26//#include <linux/ioctl.h> 26//#include <linux/ioctl.h>
27#ifndef __KERNEL__
28
29typedef unsigned char u8;
30typedef unsigned short u16;
31typedef unsigned int u32;
32
33#endif /* __KERNEL__ */
27 34
28/* 35/*
29 * I2O Control IOCTLs and structures 36 * I2O Control IOCTLs and structures
@@ -113,6 +120,10 @@ struct i2o_evt_get {
113 int lost; 120 int lost;
114}; 121};
115 122
123typedef struct i2o_sg_io_hdr {
124 unsigned int flags; /* see I2O_DPT_SG_IO_FLAGS */
125} i2o_sg_io_hdr_t;
126
116/************************************************************************** 127/**************************************************************************
117 * HRT related constants and structures 128 * HRT related constants and structures
118 **************************************************************************/ 129 **************************************************************************/
@@ -126,14 +137,6 @@ struct i2o_evt_get {
126#define I2O_BUS_CARDBUS 7 137#define I2O_BUS_CARDBUS 7
127#define I2O_BUS_UNKNOWN 0x80 138#define I2O_BUS_UNKNOWN 0x80
128 139
129#ifndef __KERNEL__
130
131typedef unsigned char u8;
132typedef unsigned short u16;
133typedef unsigned int u32;
134
135#endif /* __KERNEL__ */
136
137typedef struct _i2o_pci_bus { 140typedef struct _i2o_pci_bus {
138 u8 PciFunctionNumber; 141 u8 PciFunctionNumber;
139 u8 PciDeviceNumber; 142 u8 PciDeviceNumber;
@@ -333,7 +336,7 @@ typedef struct _i2o_status_block {
333#define I2O_CLASS_ATE_PERIPHERAL 0x061 336#define I2O_CLASS_ATE_PERIPHERAL 0x061
334#define I2O_CLASS_FLOPPY_CONTROLLER 0x070 337#define I2O_CLASS_FLOPPY_CONTROLLER 0x070
335#define I2O_CLASS_FLOPPY_DEVICE 0x071 338#define I2O_CLASS_FLOPPY_DEVICE 0x071
336#define I2O_CLASS_BUS_ADAPTER_PORT 0x080 339#define I2O_CLASS_BUS_ADAPTER 0x080
337#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090 340#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090
338#define I2O_CLASS_PEER_TRANSPORT 0x091 341#define I2O_CLASS_PEER_TRANSPORT 0x091
339#define I2O_CLASS_END 0xfff 342#define I2O_CLASS_END 0xfff
@@ -399,4 +402,26 @@ typedef struct _i2o_status_block {
399#define ADAPTER_STATE_FAILED 0x10 402#define ADAPTER_STATE_FAILED 0x10
400#define ADAPTER_STATE_FAULTED 0x11 403#define ADAPTER_STATE_FAULTED 0x11
401 404
405/*
406 * Software module types
407 */
408#define I2O_SOFTWARE_MODULE_IRTOS 0x11
409#define I2O_SOFTWARE_MODULE_IOP_PRIVATE 0x22
410#define I2O_SOFTWARE_MODULE_IOP_CONFIG 0x23
411
412/*
413 * Vendors
414 */
415#define I2O_VENDOR_DPT 0x001b
416
417/*
418 * DPT / Adaptec specific values for i2o_sg_io_hdr flags.
419 */
420#define I2O_DPT_SG_FLAG_INTERPRET 0x00010000
421#define I2O_DPT_SG_FLAG_PHYSICAL 0x00020000
422
423#define I2O_DPT_FLASH_FRAG_SIZE 0x10000
424#define I2O_DPT_FLASH_READ 0x0101
425#define I2O_DPT_FLASH_WRITE 0x0102
426
402#endif /* _I2O_DEV_H */ 427#endif /* _I2O_DEV_H */
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index ea9a3ad4b6..bdc286ec94 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -119,12 +119,21 @@ struct i2o_driver {
119}; 119};
120 120
121/* 121/*
122 * Contains all information which are necessary for DMA operations 122 * Contains DMA mapped address information
123 */ 123 */
124struct i2o_dma { 124struct i2o_dma {
125 void *virt; 125 void *virt;
126 dma_addr_t phys; 126 dma_addr_t phys;
127 u32 len; 127 size_t len;
128};
129
130/*
131 * Contains IO mapped address information
132 */
133struct i2o_io {
134 void __iomem *virt;
135 unsigned long phys;
136 unsigned long len;
128}; 137};
129 138
130/* 139/*
@@ -147,28 +156,25 @@ struct i2o_controller {
147 156
148 struct pci_dev *pdev; /* PCI device */ 157 struct pci_dev *pdev; /* PCI device */
149 158
150 unsigned int short_req:1; /* use small block sizes */ 159 unsigned int promise:1; /* Promise controller */
160 unsigned int adaptec:1; /* DPT / Adaptec controller */
161 unsigned int raptor:1; /* split bar */
151 unsigned int no_quiesce:1; /* dont quiesce before reset */ 162 unsigned int no_quiesce:1; /* dont quiesce before reset */
152 unsigned int raptor:1; /* split bar */ 163 unsigned int short_req:1; /* use small block sizes */
153 unsigned int promise:1; /* Promise controller */ 164 unsigned int limit_sectors:1; /* limit number of sectors / request */
154 165 unsigned int pae_support:1; /* controller has 64-bit SGL support */
155#ifdef CONFIG_MTRR
156 int mtrr_reg0;
157 int mtrr_reg1;
158#endif
159 166
160 struct list_head devices; /* list of I2O devices */ 167 struct list_head devices; /* list of I2O devices */
161
162 struct notifier_block *event_notifer; /* Events */
163 atomic_t users;
164 struct list_head list; /* Controller list */ 168 struct list_head list; /* Controller list */
165 void __iomem *post_port; /* Inbout port address */ 169
166 void __iomem *reply_port; /* Outbound port address */ 170 void __iomem *in_port; /* Inbout port address */
167 void __iomem *irq_mask; /* Interrupt register address */ 171 void __iomem *out_port; /* Outbound port address */
172 void __iomem *irq_status; /* Interrupt status register address */
173 void __iomem *irq_mask; /* Interrupt mask register address */
168 174
169 /* Dynamic LCT related data */ 175 /* Dynamic LCT related data */
170 176
171 struct i2o_dma status; /* status of IOP */ 177 struct i2o_dma status; /* IOP status block */
172 178
173 struct i2o_dma hrt; /* HW Resource Table */ 179 struct i2o_dma hrt; /* HW Resource Table */
174 i2o_lct *lct; /* Logical Config Table */ 180 i2o_lct *lct; /* Logical Config Table */
@@ -176,21 +182,19 @@ struct i2o_controller {
176 struct semaphore lct_lock; /* Lock for LCT updates */ 182 struct semaphore lct_lock; /* Lock for LCT updates */
177 struct i2o_dma status_block; /* IOP status block */ 183 struct i2o_dma status_block; /* IOP status block */
178 184
179 struct i2o_dma base; /* controller messaging unit */ 185 struct i2o_io base; /* controller messaging unit */
180 struct i2o_dma in_queue; /* inbound message queue Host->IOP */ 186 struct i2o_io in_queue; /* inbound message queue Host->IOP */
181 struct i2o_dma out_queue; /* outbound message queue IOP->Host */ 187 struct i2o_dma out_queue; /* outbound message queue IOP->Host */
182 188
183 unsigned int battery:1; /* Has a battery backup */ 189 unsigned int battery:1; /* Has a battery backup */
184 unsigned int io_alloc:1; /* An I/O resource was allocated */ 190 unsigned int io_alloc:1; /* An I/O resource was allocated */
185 unsigned int mem_alloc:1; /* A memory resource was allocated */ 191 unsigned int mem_alloc:1; /* A memory resource was allocated */
186 192
187 struct resource io_resource; /* I/O resource allocated to the IOP */ 193 struct resource io_resource; /* I/O resource allocated to the IOP */
188 struct resource mem_resource; /* Mem resource allocated to the IOP */ 194 struct resource mem_resource; /* Mem resource allocated to the IOP */
189 195
190 struct proc_dir_entry *proc_entry; /* /proc dir */
191
192 struct list_head bus_list; /* list of busses on IOP */
193 struct device device; 196 struct device device;
197 struct class_device classdev; /* I2O controller class */
194 struct i2o_device *exec; /* Executive */ 198 struct i2o_device *exec; /* Executive */
195#if BITS_PER_LONG == 64 199#if BITS_PER_LONG == 64
196 spinlock_t context_list_lock; /* lock for context_list */ 200 spinlock_t context_list_lock; /* lock for context_list */
@@ -241,9 +245,10 @@ struct i2o_sys_tbl {
241extern struct list_head i2o_controllers; 245extern struct list_head i2o_controllers;
242 246
243/* Message functions */ 247/* Message functions */
244static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message __iomem **); 248static inline u32 i2o_msg_get(struct i2o_controller *,
245extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message __iomem **, 249 struct i2o_message __iomem **);
246 int); 250extern u32 i2o_msg_get_wait(struct i2o_controller *,
251 struct i2o_message __iomem **, int);
247static inline void i2o_msg_post(struct i2o_controller *, u32); 252static inline void i2o_msg_post(struct i2o_controller *, u32);
248static inline int i2o_msg_post_wait(struct i2o_controller *, u32, 253static inline int i2o_msg_post_wait(struct i2o_controller *, u32,
249 unsigned long); 254 unsigned long);
@@ -252,15 +257,6 @@ extern int i2o_msg_post_wait_mem(struct i2o_controller *, u32, unsigned long,
252extern void i2o_msg_nop(struct i2o_controller *, u32); 257extern void i2o_msg_nop(struct i2o_controller *, u32);
253static inline void i2o_flush_reply(struct i2o_controller *, u32); 258static inline void i2o_flush_reply(struct i2o_controller *, u32);
254 259
255/* DMA handling functions */
256static inline int i2o_dma_alloc(struct device *, struct i2o_dma *, size_t,
257 unsigned int);
258static inline void i2o_dma_free(struct device *, struct i2o_dma *);
259int i2o_dma_realloc(struct device *, struct i2o_dma *, size_t, unsigned int);
260
261static inline int i2o_dma_map(struct device *, struct i2o_dma *);
262static inline void i2o_dma_unmap(struct device *, struct i2o_dma *);
263
264/* IOP functions */ 260/* IOP functions */
265extern int i2o_status_get(struct i2o_controller *); 261extern int i2o_status_get(struct i2o_controller *);
266 262
@@ -285,6 +281,16 @@ static inline u32 i2o_ptr_high(void *ptr)
285{ 281{
286 return (u32) ((u64) ptr >> 32); 282 return (u32) ((u64) ptr >> 32);
287}; 283};
284
285static inline u32 i2o_dma_low(dma_addr_t dma_addr)
286{
287 return (u32) (u64) dma_addr;
288};
289
290static inline u32 i2o_dma_high(dma_addr_t dma_addr)
291{
292 return (u32) ((u64) dma_addr >> 32);
293};
288#else 294#else
289static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) 295static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
290{ 296{
@@ -315,8 +321,246 @@ static inline u32 i2o_ptr_high(void *ptr)
315{ 321{
316 return 0; 322 return 0;
317}; 323};
324
325static inline u32 i2o_dma_low(dma_addr_t dma_addr)
326{
327 return (u32) dma_addr;
328};
329
330static inline u32 i2o_dma_high(dma_addr_t dma_addr)
331{
332 return 0;
333};
318#endif 334#endif
319 335
336/**
337 * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL
338 * @c: I2O controller for which the calculation should be done
339 * @body_size: maximum body size used for message in 32-bit words.
340 *
341 * Return the maximum number of SG elements in a SG list.
342 */
343static inline u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
344{
345 i2o_status_block *sb = c->status_block.virt;
346 u16 sg_count =
347 (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -
348 body_size;
349
350 if (c->pae_support) {
351 /*
352 * for 64-bit a SG attribute element must be added and each
353 * SG element needs 12 bytes instead of 8.
354 */
355 sg_count -= 2;
356 sg_count /= 3;
357 } else
358 sg_count /= 2;
359
360 if (c->short_req && (sg_count > 8))
361 sg_count = 8;
362
363 return sg_count;
364};
365
366/**
367 * i2o_dma_map_single - Map pointer to controller and fill in I2O message.
368 * @c: I2O controller
369 * @ptr: pointer to the data which should be mapped
370 * @size: size of data in bytes
371 * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
372 * @sg_ptr: pointer to the SG list inside the I2O message
373 *
374 * This function does all necessary DMA handling and also writes the I2O
375 * SGL elements into the I2O message. For details on DMA handling see also
376 * dma_map_single(). The pointer sg_ptr will only be set to the end of the
377 * SG list if the allocation was successful.
378 *
379 * Returns DMA address which must be checked for failures using
380 * dma_mapping_error().
381 */
382static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
383 size_t size,
384 enum dma_data_direction direction,
385 u32 __iomem ** sg_ptr)
386{
387 u32 sg_flags;
388 u32 __iomem *mptr = *sg_ptr;
389 dma_addr_t dma_addr;
390
391 switch (direction) {
392 case DMA_TO_DEVICE:
393 sg_flags = 0xd4000000;
394 break;
395 case DMA_FROM_DEVICE:
396 sg_flags = 0xd0000000;
397 break;
398 default:
399 return 0;
400 }
401
402 dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
403 if (!dma_mapping_error(dma_addr)) {
404#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
405 if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
406 writel(0x7C020002, mptr++);
407 writel(PAGE_SIZE, mptr++);
408 }
409#endif
410
411 writel(sg_flags | size, mptr++);
412 writel(i2o_dma_low(dma_addr), mptr++);
413#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
414 if ((sizeof(dma_addr_t) > 4) && c->pae_support)
415 writel(i2o_dma_high(dma_addr), mptr++);
416#endif
417 *sg_ptr = mptr;
418 }
419 return dma_addr;
420};
421
422/**
423 * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message.
424 * @c: I2O controller
425 * @sg: SG list to be mapped
426 * @sg_count: number of elements in the SG list
427 * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
428 * @sg_ptr: pointer to the SG list inside the I2O message
429 *
430 * This function does all necessary DMA handling and also writes the I2O
431 * SGL elements into the I2O message. For details on DMA handling see also
432 * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG
433 * list if the allocation was successful.
434 *
435 * Returns 0 on failure or 1 on success.
436 */
437static inline int i2o_dma_map_sg(struct i2o_controller *c,
438 struct scatterlist *sg, int sg_count,
439 enum dma_data_direction direction,
440 u32 __iomem ** sg_ptr)
441{
442 u32 sg_flags;
443 u32 __iomem *mptr = *sg_ptr;
444
445 switch (direction) {
446 case DMA_TO_DEVICE:
447 sg_flags = 0x14000000;
448 break;
449 case DMA_FROM_DEVICE:
450 sg_flags = 0x10000000;
451 break;
452 default:
453 return 0;
454 }
455
456 sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);
457 if (!sg_count)
458 return 0;
459
460#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
461 if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
462 writel(0x7C020002, mptr++);
463 writel(PAGE_SIZE, mptr++);
464 }
465#endif
466
467 while (sg_count-- > 0) {
468 if (!sg_count)
469 sg_flags |= 0xC0000000;
470 writel(sg_flags | sg_dma_len(sg), mptr++);
471 writel(i2o_dma_low(sg_dma_address(sg)), mptr++);
472#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
473 if ((sizeof(dma_addr_t) > 4) && c->pae_support)
474 writel(i2o_dma_high(sg_dma_address(sg)), mptr++);
475#endif
476 sg++;
477 }
478 *sg_ptr = mptr;
479
480 return 1;
481};
482
483/**
484 * i2o_dma_alloc - Allocate DMA memory
485 * @dev: struct device pointer to the PCI device of the I2O controller
486 * @addr: i2o_dma struct which should get the DMA buffer
487 * @len: length of the new DMA memory
488 * @gfp_mask: GFP mask
489 *
490 * Allocate a coherent DMA memory and write the pointers into addr.
491 *
492 * Returns 0 on success or -ENOMEM on failure.
493 */
494static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
495 size_t len, unsigned int gfp_mask)
496{
497 struct pci_dev *pdev = to_pci_dev(dev);
498 int dma_64 = 0;
499
500 if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) {
501 dma_64 = 1;
502 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK))
503 return -ENOMEM;
504 }
505
506 addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
507
508 if ((sizeof(dma_addr_t) > 4) && dma_64)
509 if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
510 printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
511
512 if (!addr->virt)
513 return -ENOMEM;
514
515 memset(addr->virt, 0, len);
516 addr->len = len;
517
518 return 0;
519};
520
521/**
522 * i2o_dma_free - Free DMA memory
523 * @dev: struct device pointer to the PCI device of the I2O controller
524 * @addr: i2o_dma struct which contains the DMA buffer
525 *
526 * Free a coherent DMA memory and set virtual address of addr to NULL.
527 */
528static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
529{
530 if (addr->virt) {
531 if (addr->phys)
532 dma_free_coherent(dev, addr->len, addr->virt,
533 addr->phys);
534 else
535 kfree(addr->virt);
536 addr->virt = NULL;
537 }
538};
539
540/**
541 * i2o_dma_realloc - Realloc DMA memory
542 * @dev: struct device pointer to the PCI device of the I2O controller
543 * @addr: pointer to a i2o_dma struct DMA buffer
544 * @len: new length of memory
545 * @gfp_mask: GFP mask
546 *
547 * If there was something allocated in the addr, free it first. If len > 0
548 * than try to allocate it and write the addresses back to the addr
549 * structure. If len == 0 set the virtual address to NULL.
550 *
551 * Returns the 0 on success or negative error code on failure.
552 */
553static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
554 size_t len, unsigned int gfp_mask)
555{
556 i2o_dma_free(dev, addr);
557
558 if (len)
559 return i2o_dma_alloc(dev, addr, len, gfp_mask);
560
561 return 0;
562};
563
320/* I2O driver (OSM) functions */ 564/* I2O driver (OSM) functions */
321extern int i2o_driver_register(struct i2o_driver *); 565extern int i2o_driver_register(struct i2o_driver *);
322extern void i2o_driver_unregister(struct i2o_driver *); 566extern void i2o_driver_unregister(struct i2o_driver *);
@@ -385,49 +629,11 @@ extern int i2o_device_claim_release(struct i2o_device *);
385/* Exec OSM functions */ 629/* Exec OSM functions */
386extern int i2o_exec_lct_get(struct i2o_controller *); 630extern int i2o_exec_lct_get(struct i2o_controller *);
387 631
388/* device to i2o_device and driver to i2o_driver convertion functions */ 632/* device / driver / kobject conversion functions */
389#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver) 633#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
390#define to_i2o_device(dev) container_of(dev, struct i2o_device, device) 634#define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
391 635#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device)
392/* 636#define kobj_to_i2o_device(kobj) to_i2o_device(container_of(kobj, struct device, kobj))
393 * Messenger inlines
394 */
395static inline u32 I2O_POST_READ32(struct i2o_controller *c)
396{
397 rmb();
398 return readl(c->post_port);
399};
400
401static inline void I2O_POST_WRITE32(struct i2o_controller *c, u32 val)
402{
403 wmb();
404 writel(val, c->post_port);
405};
406
407static inline u32 I2O_REPLY_READ32(struct i2o_controller *c)
408{
409 rmb();
410 return readl(c->reply_port);
411};
412
413static inline void I2O_REPLY_WRITE32(struct i2o_controller *c, u32 val)
414{
415 wmb();
416 writel(val, c->reply_port);
417};
418
419static inline u32 I2O_IRQ_READ32(struct i2o_controller *c)
420{
421 rmb();
422 return readl(c->irq_mask);
423};
424
425static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
426{
427 wmb();
428 writel(val, c->irq_mask);
429 wmb();
430};
431 637
432/** 638/**
433 * i2o_msg_get - obtain an I2O message from the IOP 639 * i2o_msg_get - obtain an I2O message from the IOP
@@ -443,11 +649,11 @@ static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
443 * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. 649 * available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
444 */ 650 */
445static inline u32 i2o_msg_get(struct i2o_controller *c, 651static inline u32 i2o_msg_get(struct i2o_controller *c,
446 struct i2o_message __iomem **msg) 652 struct i2o_message __iomem ** msg)
447{ 653{
448 u32 m; 654 u32 m = readl(c->in_port);
449 655
450 if ((m = I2O_POST_READ32(c)) != I2O_QUEUE_EMPTY) 656 if (m != I2O_QUEUE_EMPTY)
451 *msg = c->in_queue.virt + m; 657 *msg = c->in_queue.virt + m;
452 658
453 return m; 659 return m;
@@ -462,7 +668,7 @@ static inline u32 i2o_msg_get(struct i2o_controller *c,
462 */ 668 */
463static inline void i2o_msg_post(struct i2o_controller *c, u32 m) 669static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
464{ 670{
465 I2O_POST_WRITE32(c, m); 671 writel(m, c->in_port);
466}; 672};
467 673
468/** 674/**
@@ -491,12 +697,10 @@ static inline int i2o_msg_post_wait(struct i2o_controller *c, u32 m,
491 * The I2O controller must be informed that the reply message is not needed 697 * The I2O controller must be informed that the reply message is not needed
492 * anymore. If you forget to flush the reply, the message frame can't be 698 * anymore. If you forget to flush the reply, the message frame can't be
493 * used by the controller anymore and is therefore lost. 699 * used by the controller anymore and is therefore lost.
494 *
495 * FIXME: is there a timeout after which the controller reuse the message?
496 */ 700 */
497static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) 701static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
498{ 702{
499 I2O_REPLY_WRITE32(c, m); 703 writel(m, c->out_port);
500}; 704};
501 705
502/** 706/**
@@ -530,97 +734,13 @@ static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c,
530 * work for receive side messages as they are kmalloc objects 734 * work for receive side messages as they are kmalloc objects
531 * in a different pool. 735 * in a different pool.
532 */ 736 */
533static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct i2o_controller *c, 737static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct
534 u32 m) 738 i2o_controller *c,
739 u32 m)
535{ 740{
536 return c->in_queue.virt + m; 741 return c->in_queue.virt + m;
537}; 742};
538 743
539/**
540 * i2o_dma_alloc - Allocate DMA memory
541 * @dev: struct device pointer to the PCI device of the I2O controller
542 * @addr: i2o_dma struct which should get the DMA buffer
543 * @len: length of the new DMA memory
544 * @gfp_mask: GFP mask
545 *
546 * Allocate a coherent DMA memory and write the pointers into addr.
547 *
548 * Returns 0 on success or -ENOMEM on failure.
549 */
550static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
551 size_t len, unsigned int gfp_mask)
552{
553 addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
554 if (!addr->virt)
555 return -ENOMEM;
556
557 memset(addr->virt, 0, len);
558 addr->len = len;
559
560 return 0;
561};
562
563/**
564 * i2o_dma_free - Free DMA memory
565 * @dev: struct device pointer to the PCI device of the I2O controller
566 * @addr: i2o_dma struct which contains the DMA buffer
567 *
568 * Free a coherent DMA memory and set virtual address of addr to NULL.
569 */
570static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
571{
572 if (addr->virt) {
573 if (addr->phys)
574 dma_free_coherent(dev, addr->len, addr->virt,
575 addr->phys);
576 else
577 kfree(addr->virt);
578 addr->virt = NULL;
579 }
580};
581
582/**
583 * i2o_dma_map - Map the memory to DMA
584 * @dev: struct device pointer to the PCI device of the I2O controller
585 * @addr: i2o_dma struct which should be mapped
586 *
587 * Map the memory in addr->virt to coherent DMA memory and write the
588 * physical address into addr->phys.
589 *
590 * Returns 0 on success or -ENOMEM on failure.
591 */
592static inline int i2o_dma_map(struct device *dev, struct i2o_dma *addr)
593{
594 if (!addr->virt)
595 return -EFAULT;
596
597 if (!addr->phys)
598 addr->phys = dma_map_single(dev, addr->virt, addr->len,
599 DMA_BIDIRECTIONAL);
600 if (!addr->phys)
601 return -ENOMEM;
602
603 return 0;
604};
605
606/**
607 * i2o_dma_unmap - Unmap the DMA memory
608 * @dev: struct device pointer to the PCI device of the I2O controller
609 * @addr: i2o_dma struct which should be unmapped
610 *
611 * Unmap the memory in addr->virt from DMA memory.
612 */
613static inline void i2o_dma_unmap(struct device *dev, struct i2o_dma *addr)
614{
615 if (!addr->virt)
616 return;
617
618 if (addr->phys) {
619 dma_unmap_single(dev, addr->phys, addr->len, DMA_BIDIRECTIONAL);
620 addr->phys = 0;
621 }
622};
623
624/* 744/*
625 * Endian handling wrapped into the macro - keeps the core code 745 * Endian handling wrapped into the macro - keeps the core code
626 * cleaner. 746 * cleaner.
@@ -773,6 +893,14 @@ extern void i2o_debug_state(struct i2o_controller *c);
773#define I2O_CMD_SCSI_BUSRESET 0x27 893#define I2O_CMD_SCSI_BUSRESET 0x27
774 894
775/* 895/*
896 * Bus Adapter Class
897 */
898#define I2O_CMD_BUS_ADAPTER_RESET 0x85
899#define I2O_CMD_BUS_RESET 0x87
900#define I2O_CMD_BUS_SCAN 0x89
901#define I2O_CMD_BUS_QUIESCE 0x8b
902
903/*
776 * Random Block Storage Class 904 * Random Block Storage Class
777 */ 905 */
778#define I2O_CMD_BLOCK_READ 0x30 906#define I2O_CMD_BLOCK_READ 0x30
@@ -784,7 +912,7 @@ extern void i2o_debug_state(struct i2o_controller *c);
784#define I2O_CMD_BLOCK_MEJECT 0x43 912#define I2O_CMD_BLOCK_MEJECT 0x43
785#define I2O_CMD_BLOCK_POWER 0x70 913#define I2O_CMD_BLOCK_POWER 0x70
786 914
787#define I2O_PRIVATE_MSG 0xFF 915#define I2O_CMD_PRIVATE 0xFF
788 916
789/* Command status values */ 917/* Command status values */
790 918
@@ -922,7 +1050,7 @@ extern void i2o_debug_state(struct i2o_controller *c);
922#define I2OVER15 0x0001 1050#define I2OVER15 0x0001
923#define I2OVER20 0x0002 1051#define I2OVER20 0x0002
924 1052
925/* Default is 1.5, FIXME: Need support for both 1.5 and 2.0 */ 1053/* Default is 1.5 */
926#define I2OVERSION I2OVER15 1054#define I2OVERSION I2OVER15
927 1055
928#define SGL_OFFSET_0 I2OVERSION 1056#define SGL_OFFSET_0 I2OVERSION
@@ -933,9 +1061,9 @@ extern void i2o_debug_state(struct i2o_controller *c);
933#define SGL_OFFSET_8 (0x0080 | I2OVERSION) 1061#define SGL_OFFSET_8 (0x0080 | I2OVERSION)
934#define SGL_OFFSET_9 (0x0090 | I2OVERSION) 1062#define SGL_OFFSET_9 (0x0090 | I2OVERSION)
935#define SGL_OFFSET_10 (0x00A0 | I2OVERSION) 1063#define SGL_OFFSET_10 (0x00A0 | I2OVERSION)
936 1064#define SGL_OFFSET_11 (0x00B0 | I2OVERSION)
937#define TRL_OFFSET_5 (0x0050 | I2OVERSION) 1065#define SGL_OFFSET_12 (0x00C0 | I2OVERSION)
938#define TRL_OFFSET_6 (0x0060 | I2OVERSION) 1066#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION)
939 1067
940/* Transaction Reply Lists (TRL) Control Word structure */ 1068/* Transaction Reply Lists (TRL) Control Word structure */
941#define TRL_SINGLE_FIXED_LENGTH 0x00 1069#define TRL_SINGLE_FIXED_LENGTH 0x00
@@ -962,17 +1090,13 @@ extern void i2o_debug_state(struct i2o_controller *c);
962#define ELEVEN_WORD_MSG_SIZE 0x000B0000 1090#define ELEVEN_WORD_MSG_SIZE 0x000B0000
963#define I2O_MESSAGE_SIZE(x) ((x)<<16) 1091#define I2O_MESSAGE_SIZE(x) ((x)<<16)
964 1092
965/* Special TID Assignments */ 1093/* special TID assignments */
966
967#define ADAPTER_TID 0 1094#define ADAPTER_TID 0
968#define HOST_TID 1 1095#define HOST_TID 1
969 1096
970#define MSG_FRAME_SIZE 128 /* i2o_scsi assumes >= 32 */ 1097/* outbound queue defines */
971#define REPLY_FRAME_SIZE 17 1098#define I2O_MAX_OUTBOUND_MSG_FRAMES 128
972#define SG_TABLESIZE 30 1099#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */
973#define NMBR_MSG_FRAMES 128
974
975#define MSG_POOL_SIZE (MSG_FRAME_SIZE*NMBR_MSG_FRAMES*sizeof(u32))
976 1100
977#define I2O_POST_WAIT_OK 0 1101#define I2O_POST_WAIT_OK 0
978#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT 1102#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT
@@ -993,11 +1117,10 @@ extern void i2o_debug_state(struct i2o_controller *c);
993#define I2O_HRT_GET_TRIES 3 1117#define I2O_HRT_GET_TRIES 3
994#define I2O_LCT_GET_TRIES 3 1118#define I2O_LCT_GET_TRIES 3
995 1119
996/* request queue sizes */ 1120/* defines for max_sectors and max_phys_segments */
997#define I2O_MAX_SECTORS 1024 1121#define I2O_MAX_SECTORS 1024
998#define I2O_MAX_SEGMENTS 128 1122#define I2O_MAX_SECTORS_LIMITED 256
999 1123#define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS
1000#define I2O_REQ_MEMPOOL_SIZE 32
1001 1124
1002#endif /* __KERNEL__ */ 1125#endif /* __KERNEL__ */
1003#endif /* _I2O_H */ 1126#endif /* _I2O_H */
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 2ec265e104..596ca61301 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -209,6 +209,11 @@ struct kernel_ipmi_msg
209#include <linux/list.h> 209#include <linux/list.h>
210#include <linux/module.h> 210#include <linux/module.h>
211 211
212#ifdef CONFIG_PROC_FS
213#include <linux/proc_fs.h>
214extern struct proc_dir_entry *proc_ipmi_root;
215#endif /* CONFIG_PROC_FS */
216
212/* Opaque type for a IPMI message user. One of these is needed to 217/* Opaque type for a IPMI message user. One of these is needed to
213 send and receive messages. */ 218 send and receive messages. */
214typedef struct ipmi_user *ipmi_user_t; 219typedef struct ipmi_user *ipmi_user_t;
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 7fc1022be9..12277799c0 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -88,7 +88,6 @@ extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
88 struct irqaction *action); 88 struct irqaction *action);
89extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); 89extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
90extern void note_interrupt(unsigned int irq, irq_desc_t *desc, int action_ret); 90extern void note_interrupt(unsigned int irq, irq_desc_t *desc, int action_ret);
91extern void report_bad_irq(unsigned int irq, irq_desc_t *desc, int action_ret);
92extern int can_request_irq(unsigned int irq, unsigned long irqflags); 91extern int can_request_irq(unsigned int irq, unsigned long irqflags);
93 92
94extern void init_irq_proc(void); 93extern void init_irq_proc(void);
diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h
index 60cc7b762e..cc326174a8 100644
--- a/include/linux/key-ui.h
+++ b/include/linux/key-ui.h
@@ -1,4 +1,4 @@
1/* key-ui.h: key userspace interface stuff for use by keyfs 1/* key-ui.h: key userspace interface stuff
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
@@ -31,8 +31,10 @@ extern spinlock_t key_serial_lock;
31 * subscribed 31 * subscribed
32 */ 32 */
33struct keyring_list { 33struct keyring_list {
34 unsigned maxkeys; /* max keys this list can hold */ 34 struct rcu_head rcu; /* RCU deletion hook */
35 unsigned nkeys; /* number of keys currently held */ 35 unsigned short maxkeys; /* max keys this list can hold */
36 unsigned short nkeys; /* number of keys currently held */
37 unsigned short delkey; /* key to be unlinked by RCU */
36 struct key *keys[0]; 38 struct key *keys[0];
37}; 39};
38 40
@@ -82,8 +84,45 @@ static inline int key_any_permission(const struct key *key, key_perm_t perm)
82 return kperm != 0; 84 return kperm != 0;
83} 85}
84 86
87static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid)
88{
89 int ret;
90
91 task_lock(tsk);
92 ret = groups_search(tsk->group_info, gid);
93 task_unlock(tsk);
94 return ret;
95}
96
97static inline int key_task_permission(const struct key *key,
98 struct task_struct *context,
99 key_perm_t perm)
100{
101 key_perm_t kperm;
102
103 if (key->uid == context->fsuid) {
104 kperm = key->perm >> 16;
105 }
106 else if (key->gid != -1 &&
107 key->perm & KEY_GRP_ALL && (
108 key->gid == context->fsgid ||
109 key_task_groups_search(context, key->gid)
110 )
111 ) {
112 kperm = key->perm >> 8;
113 }
114 else {
115 kperm = key->perm;
116 }
117
118 kperm = kperm & perm & KEY_ALL;
119
120 return kperm == perm;
121
122}
85 123
86extern struct key *lookup_user_key(key_serial_t id, int create, int part, 124extern struct key *lookup_user_key(struct task_struct *context,
125 key_serial_t id, int create, int partial,
87 key_perm_t perm); 126 key_perm_t perm);
88 127
89extern long join_session_keyring(const char *name); 128extern long join_session_keyring(const char *name);
diff --git a/include/linux/key.h b/include/linux/key.h
index 6aa46d0e81..970bbd916c 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -18,7 +18,7 @@
18#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/rbtree.h> 20#include <linux/rbtree.h>
21#include <linux/spinlock.h> 21#include <linux/rcupdate.h>
22#include <asm/atomic.h> 22#include <asm/atomic.h>
23 23
24#ifdef __KERNEL__ 24#ifdef __KERNEL__
@@ -78,7 +78,6 @@ struct key {
78 key_serial_t serial; /* key serial number */ 78 key_serial_t serial; /* key serial number */
79 struct rb_node serial_node; 79 struct rb_node serial_node;
80 struct key_type *type; /* type of key */ 80 struct key_type *type; /* type of key */
81 rwlock_t lock; /* examination vs change lock */
82 struct rw_semaphore sem; /* change vs change sem */ 81 struct rw_semaphore sem; /* change vs change sem */
83 struct key_user *user; /* owner of this key */ 82 struct key_user *user; /* owner of this key */
84 time_t expiry; /* time at which key expires (or 0) */ 83 time_t expiry; /* time at which key expires (or 0) */
@@ -86,14 +85,10 @@ struct key {
86 gid_t gid; 85 gid_t gid;
87 key_perm_t perm; /* access permissions */ 86 key_perm_t perm; /* access permissions */
88 unsigned short quotalen; /* length added to quota */ 87 unsigned short quotalen; /* length added to quota */
89 unsigned short datalen; /* payload data length */ 88 unsigned short datalen; /* payload data length
90 unsigned short flags; /* status flags (change with lock writelocked) */ 89 * - may not match RCU dereferenced payload
91#define KEY_FLAG_INSTANTIATED 0x00000001 /* set if key has been instantiated */ 90 * - payload should contain own length
92#define KEY_FLAG_DEAD 0x00000002 /* set if key type has been deleted */ 91 */
93#define KEY_FLAG_REVOKED 0x00000004 /* set if key had been revoked */
94#define KEY_FLAG_IN_QUOTA 0x00000008 /* set if key consumes quota */
95#define KEY_FLAG_USER_CONSTRUCT 0x00000010 /* set if key is being constructed in userspace */
96#define KEY_FLAG_NEGATIVE 0x00000020 /* set if key is negative */
97 92
98#ifdef KEY_DEBUGGING 93#ifdef KEY_DEBUGGING
99 unsigned magic; 94 unsigned magic;
@@ -101,6 +96,14 @@ struct key {
101#define KEY_DEBUG_MAGIC_X 0xf8e9dacbu 96#define KEY_DEBUG_MAGIC_X 0xf8e9dacbu
102#endif 97#endif
103 98
99 unsigned long flags; /* status flags (change with bitops) */
100#define KEY_FLAG_INSTANTIATED 0 /* set if key has been instantiated */
101#define KEY_FLAG_DEAD 1 /* set if key type has been deleted */
102#define KEY_FLAG_REVOKED 2 /* set if key had been revoked */
103#define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */
104#define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */
105#define KEY_FLAG_NEGATIVE 5 /* set if key is negative */
106
104 /* the description string 107 /* the description string
105 * - this is used to match a key against search criteria 108 * - this is used to match a key against search criteria
106 * - this should be a printable string 109 * - this should be a printable string
@@ -196,10 +199,12 @@ extern int key_payload_reserve(struct key *key, size_t datalen);
196extern int key_instantiate_and_link(struct key *key, 199extern int key_instantiate_and_link(struct key *key,
197 const void *data, 200 const void *data,
198 size_t datalen, 201 size_t datalen,
199 struct key *keyring); 202 struct key *keyring,
203 struct key *instkey);
200extern int key_negate_and_link(struct key *key, 204extern int key_negate_and_link(struct key *key,
201 unsigned timeout, 205 unsigned timeout,
202 struct key *keyring); 206 struct key *keyring,
207 struct key *instkey);
203extern void key_revoke(struct key *key); 208extern void key_revoke(struct key *key);
204extern void key_put(struct key *key); 209extern void key_put(struct key *key);
205 210
@@ -242,14 +247,13 @@ extern struct key *keyring_search(struct key *keyring,
242 struct key_type *type, 247 struct key_type *type,
243 const char *description); 248 const char *description);
244 249
245extern struct key *search_process_keyrings(struct key_type *type,
246 const char *description);
247
248extern int keyring_add_key(struct key *keyring, 250extern int keyring_add_key(struct key *keyring,
249 struct key *key); 251 struct key *key);
250 252
251extern struct key *key_lookup(key_serial_t id); 253extern struct key *key_lookup(key_serial_t id);
252 254
255extern void keyring_replace_payload(struct key *key, void *replacement);
256
253#define key_serial(key) ((key) ? (key)->serial : 0) 257#define key_serial(key) ((key) ? (key)->serial : 0)
254 258
255/* 259/*
@@ -268,14 +272,22 @@ extern void key_fsuid_changed(struct task_struct *tsk);
268extern void key_fsgid_changed(struct task_struct *tsk); 272extern void key_fsgid_changed(struct task_struct *tsk);
269extern void key_init(void); 273extern void key_init(void);
270 274
275#define __install_session_keyring(tsk, keyring) \
276({ \
277 struct key *old_session = tsk->signal->session_keyring; \
278 tsk->signal->session_keyring = keyring; \
279 old_session; \
280})
281
271#else /* CONFIG_KEYS */ 282#else /* CONFIG_KEYS */
272 283
273#define key_validate(k) 0 284#define key_validate(k) 0
274#define key_serial(k) 0 285#define key_serial(k) 0
275#define key_get(k) NULL 286#define key_get(k) ({ NULL; })
276#define key_put(k) do { } while(0) 287#define key_put(k) do { } while(0)
277#define alloc_uid_keyring(u) 0 288#define alloc_uid_keyring(u) 0
278#define switch_uid_keyring(u) do { } while(0) 289#define switch_uid_keyring(u) do { } while(0)
290#define __install_session_keyring(t, k) ({ NULL; })
279#define copy_keys(f,t) 0 291#define copy_keys(f,t) 0
280#define copy_thread_group_keys(t) 0 292#define copy_thread_group_keys(t) 0
281#define exit_keys(t) do { } while(0) 293#define exit_keys(t) do { } while(0)
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 381dedc370..8d7c59a29e 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -20,6 +20,16 @@
20#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */ 20#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */
21#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */ 21#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */
22 22
23/* request-key default keyrings */
24#define KEY_REQKEY_DEFL_NO_CHANGE -1
25#define KEY_REQKEY_DEFL_DEFAULT 0
26#define KEY_REQKEY_DEFL_THREAD_KEYRING 1
27#define KEY_REQKEY_DEFL_PROCESS_KEYRING 2
28#define KEY_REQKEY_DEFL_SESSION_KEYRING 3
29#define KEY_REQKEY_DEFL_USER_KEYRING 4
30#define KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5
31#define KEY_REQKEY_DEFL_GROUP_KEYRING 6
32
23/* keyctl commands */ 33/* keyctl commands */
24#define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */ 34#define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */
25#define KEYCTL_JOIN_SESSION_KEYRING 1 /* join or start named session keyring */ 35#define KEYCTL_JOIN_SESSION_KEYRING 1 /* join or start named session keyring */
@@ -35,5 +45,6 @@
35#define KEYCTL_READ 11 /* read a key or keyring's contents */ 45#define KEYCTL_READ 11 /* read a key or keyring's contents */
36#define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */ 46#define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */
37#define KEYCTL_NEGATE 13 /* negate a partially constructed key */ 47#define KEYCTL_NEGATE 13 /* negate a partially constructed key */
48#define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */
38 49
39#endif /* _LINUX_KEYCTL_H */ 50#endif /* _LINUX_KEYCTL_H */
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 95d0e4b081..e4a2315494 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -19,6 +19,7 @@
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */ 20 */
21 21
22#include <linux/stddef.h>
22#include <linux/config.h> 23#include <linux/config.h>
23#include <linux/errno.h> 24#include <linux/errno.h>
24#include <linux/compiler.h> 25#include <linux/compiler.h>
@@ -34,7 +35,17 @@ static inline int request_module(const char * name, ...) { return -ENOSYS; }
34#endif 35#endif
35 36
36#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x))) 37#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
37extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait); 38
39struct key;
40extern int call_usermodehelper_keys(char *path, char *argv[], char *envp[],
41 struct key *session_keyring, int wait);
42
43static inline int
44call_usermodehelper(char *path, char **argv, char **envp, int wait)
45{
46 return call_usermodehelper_keys(path, argv, envp, NULL, wait);
47}
48
38extern void usermodehelper_init(void); 49extern void usermodehelper_init(void);
39 50
40#endif /* __LINUX_KMOD_H__ */ 51#endif /* __LINUX_KMOD_H__ */
diff --git a/include/linux/module.h b/include/linux/module.h
index 0e432a0f4a..f05372b7fe 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -51,6 +51,9 @@ struct module_attribute {
51 ssize_t (*show)(struct module_attribute *, struct module *, char *); 51 ssize_t (*show)(struct module_attribute *, struct module *, char *);
52 ssize_t (*store)(struct module_attribute *, struct module *, 52 ssize_t (*store)(struct module_attribute *, struct module *,
53 const char *, size_t count); 53 const char *, size_t count);
54 void (*setup)(struct module *, const char *);
55 int (*test)(struct module *);
56 void (*free)(struct module *);
54}; 57};
55 58
56struct module_kobject 59struct module_kobject
@@ -239,6 +242,8 @@ struct module
239 /* Sysfs stuff. */ 242 /* Sysfs stuff. */
240 struct module_kobject mkobj; 243 struct module_kobject mkobj;
241 struct module_param_attrs *param_attrs; 244 struct module_param_attrs *param_attrs;
245 const char *version;
246 const char *srcversion;
242 247
243 /* Exported symbols */ 248 /* Exported symbols */
244 const struct kernel_symbol *syms; 249 const struct kernel_symbol *syms;
diff --git a/include/linux/namespace.h b/include/linux/namespace.h
index 9eca1558d7..697991b69f 100644
--- a/include/linux/namespace.h
+++ b/include/linux/namespace.h
@@ -12,7 +12,6 @@ struct namespace {
12 struct rw_semaphore sem; 12 struct rw_semaphore sem;
13}; 13};
14 14
15extern void umount_tree(struct vfsmount *);
16extern int copy_namespace(int, struct task_struct *); 15extern int copy_namespace(int, struct task_struct *);
17extern void __put_namespace(struct namespace *namespace); 16extern void __put_namespace(struct namespace *namespace);
18 17
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 5bb5b2fd7b..0c1c306cda 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -28,7 +28,7 @@
28#define NFS4_ACCESS_DELETE 0x0010 28#define NFS4_ACCESS_DELETE 0x0010
29#define NFS4_ACCESS_EXECUTE 0x0020 29#define NFS4_ACCESS_EXECUTE 0x0020
30 30
31#define NFS4_FH_PERISTENT 0x0000 31#define NFS4_FH_PERSISTENT 0x0000
32#define NFS4_FH_NOEXPIRE_WITH_OPEN 0x0001 32#define NFS4_FH_NOEXPIRE_WITH_OPEN 0x0001
33#define NFS4_FH_VOLATILE_ANY 0x0002 33#define NFS4_FH_VOLATILE_ANY 0x0002
34#define NFS4_FH_VOL_MIGRATION 0x0004 34#define NFS4_FH_VOL_MIGRATION 0x0004
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 4bf931d5ff..5791dfd30d 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -145,15 +145,19 @@ int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
145 * NFSv4 State 145 * NFSv4 State
146 */ 146 */
147#ifdef CONFIG_NFSD_V4 147#ifdef CONFIG_NFSD_V4
148int nfs4_state_init(void); 148void nfs4_state_init(void);
149int nfs4_state_start(void);
149void nfs4_state_shutdown(void); 150void nfs4_state_shutdown(void);
150time_t nfs4_lease_time(void); 151time_t nfs4_lease_time(void);
151void nfs4_reset_lease(time_t leasetime); 152void nfs4_reset_lease(time_t leasetime);
153int nfs4_reset_recoverydir(char *recdir);
152#else 154#else
153static inline int nfs4_state_init(void){return 0;} 155static inline void nfs4_state_init(void){};
156static inline int nfs4_state_start(void){return 0;}
154static inline void nfs4_state_shutdown(void){} 157static inline void nfs4_state_shutdown(void){}
155static inline time_t nfs4_lease_time(void){return 0;} 158static inline time_t nfs4_lease_time(void){return 0;}
156static inline void nfs4_reset_lease(time_t leasetime){} 159static inline void nfs4_reset_lease(time_t leasetime){}
160static inline int nfs4_reset_recoverydir(char *recdir) {return 0;}
157#endif 161#endif
158 162
159/* 163/*
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index b6b2fe1e7c..a84a3fa99b 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -61,11 +61,6 @@ typedef struct {
61#define si_stateownerid si_opaque.so_stateownerid 61#define si_stateownerid si_opaque.so_stateownerid
62#define si_fileid si_opaque.so_fileid 62#define si_fileid si_opaque.so_fileid
63 63
64extern stateid_t zerostateid;
65extern stateid_t onestateid;
66
67#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
68#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
69 64
70struct nfs4_cb_recall { 65struct nfs4_cb_recall {
71 u32 cbr_ident; 66 u32 cbr_ident;
@@ -77,8 +72,8 @@ struct nfs4_cb_recall {
77}; 72};
78 73
79struct nfs4_delegation { 74struct nfs4_delegation {
80 struct list_head dl_del_perfile; /* nfs4_file->fi_del_perfile */ 75 struct list_head dl_perfile;
81 struct list_head dl_del_perclnt; /* nfs4_client->cl_del_perclnt*/ 76 struct list_head dl_perclnt;
82 struct list_head dl_recall_lru; /* delegation recalled */ 77 struct list_head dl_recall_lru; /* delegation recalled */
83 atomic_t dl_count; /* ref count */ 78 atomic_t dl_count; /* ref count */
84 struct nfs4_client *dl_client; 79 struct nfs4_client *dl_client;
@@ -97,7 +92,6 @@ struct nfs4_delegation {
97/* client delegation callback info */ 92/* client delegation callback info */
98struct nfs4_callback { 93struct nfs4_callback {
99 /* SETCLIENTID info */ 94 /* SETCLIENTID info */
100 u32 cb_parsed; /* addr parsed */
101 u32 cb_addr; 95 u32 cb_addr;
102 unsigned short cb_port; 96 unsigned short cb_port;
103 u32 cb_prog; 97 u32 cb_prog;
@@ -109,6 +103,8 @@ struct nfs4_callback {
109 struct rpc_clnt * cb_client; 103 struct rpc_clnt * cb_client;
110}; 104};
111 105
106#define HEXDIR_LEN 33 /* hex version of 16 byte md5 of cl_name plus '\0' */
107
112/* 108/*
113 * struct nfs4_client - one per client. Clientids live here. 109 * struct nfs4_client - one per client. Clientids live here.
114 * o Each nfs4_client is hashed by clientid. 110 * o Each nfs4_client is hashed by clientid.
@@ -122,10 +118,11 @@ struct nfs4_callback {
122struct nfs4_client { 118struct nfs4_client {
123 struct list_head cl_idhash; /* hash by cl_clientid.id */ 119 struct list_head cl_idhash; /* hash by cl_clientid.id */
124 struct list_head cl_strhash; /* hash by cl_name */ 120 struct list_head cl_strhash; /* hash by cl_name */
125 struct list_head cl_perclient; /* list: stateowners */ 121 struct list_head cl_openowners;
126 struct list_head cl_del_perclnt; /* list: delegations */ 122 struct list_head cl_delegations;
127 struct list_head cl_lru; /* tail queue */ 123 struct list_head cl_lru; /* tail queue */
128 struct xdr_netobj cl_name; /* id generated by client */ 124 struct xdr_netobj cl_name; /* id generated by client */
125 char cl_recdir[HEXDIR_LEN]; /* recovery dir */
129 nfs4_verifier cl_verifier; /* generated by client */ 126 nfs4_verifier cl_verifier; /* generated by client */
130 time_t cl_time; /* time of last lease renewal */ 127 time_t cl_time; /* time of last lease renewal */
131 u32 cl_addr; /* client ipaddress */ 128 u32 cl_addr; /* client ipaddress */
@@ -134,6 +131,7 @@ struct nfs4_client {
134 nfs4_verifier cl_confirm; /* generated by server */ 131 nfs4_verifier cl_confirm; /* generated by server */
135 struct nfs4_callback cl_callback; /* callback info */ 132 struct nfs4_callback cl_callback; /* callback info */
136 atomic_t cl_count; /* ref count */ 133 atomic_t cl_count; /* ref count */
134 u32 cl_firststate; /* recovery dir creation */
137}; 135};
138 136
139/* struct nfs4_client_reset 137/* struct nfs4_client_reset
@@ -143,7 +141,7 @@ struct nfs4_client {
143 */ 141 */
144struct nfs4_client_reclaim { 142struct nfs4_client_reclaim {
145 struct list_head cr_strhash; /* hash by cr_name */ 143 struct list_head cr_strhash; /* hash by cr_name */
146 struct xdr_netobj cr_name; /* id generated by client */ 144 char cr_recdir[HEXDIR_LEN]; /* recover dir */
147}; 145};
148 146
149static inline void 147static inline void
@@ -197,9 +195,9 @@ struct nfs4_stateowner {
197 struct kref so_ref; 195 struct kref so_ref;
198 struct list_head so_idhash; /* hash by so_id */ 196 struct list_head so_idhash; /* hash by so_id */
199 struct list_head so_strhash; /* hash by op_name */ 197 struct list_head so_strhash; /* hash by op_name */
200 struct list_head so_perclient; /* nfs4_client->cl_perclient */ 198 struct list_head so_perclient;
201 struct list_head so_perfilestate; /* list: nfs4_stateid */ 199 struct list_head so_stateids;
202 struct list_head so_perlockowner; /* nfs4_stateid->st_perlockowner */ 200 struct list_head so_perstateid; /* for lockowners only */
203 struct list_head so_close_lru; /* tail queue */ 201 struct list_head so_close_lru; /* tail queue */
204 time_t so_time; /* time of placement on so_close_lru */ 202 time_t so_time; /* time of placement on so_close_lru */
205 int so_is_open_owner; /* 1=openowner,0=lockowner */ 203 int so_is_open_owner; /* 1=openowner,0=lockowner */
@@ -217,9 +215,10 @@ struct nfs4_stateowner {
217* share_acces, share_deny on the file. 215* share_acces, share_deny on the file.
218*/ 216*/
219struct nfs4_file { 217struct nfs4_file {
218 struct kref fi_ref;
220 struct list_head fi_hash; /* hash by "struct inode *" */ 219 struct list_head fi_hash; /* hash by "struct inode *" */
221 struct list_head fi_perfile; /* list: nfs4_stateid */ 220 struct list_head fi_stateids;
222 struct list_head fi_del_perfile; /* list: nfs4_delegation */ 221 struct list_head fi_delegations;
223 struct inode *fi_inode; 222 struct inode *fi_inode;
224 u32 fi_id; /* used with stateowner->so_id 223 u32 fi_id; /* used with stateowner->so_id
225 * for stateid_hashtbl hash */ 224 * for stateid_hashtbl hash */
@@ -241,8 +240,8 @@ struct nfs4_file {
241struct nfs4_stateid { 240struct nfs4_stateid {
242 struct list_head st_hash; 241 struct list_head st_hash;
243 struct list_head st_perfile; 242 struct list_head st_perfile;
244 struct list_head st_perfilestate; 243 struct list_head st_perstateowner;
245 struct list_head st_perlockowner; 244 struct list_head st_lockowners;
246 struct nfs4_stateowner * st_stateowner; 245 struct nfs4_stateowner * st_stateowner;
247 struct nfs4_file * st_file; 246 struct nfs4_file * st_file;
248 stateid_t st_stateid; 247 stateid_t st_stateid;
@@ -267,12 +266,9 @@ struct nfs4_stateid {
267 ((err) != nfserr_stale_stateid) && \ 266 ((err) != nfserr_stale_stateid) && \
268 ((err) != nfserr_bad_stateid)) 267 ((err) != nfserr_bad_stateid))
269 268
270extern time_t nfs4_laundromat(void);
271extern int nfsd4_renew(clientid_t *clid); 269extern int nfsd4_renew(clientid_t *clid);
272extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, 270extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
273 stateid_t *stateid, int flags, struct file **filp); 271 stateid_t *stateid, int flags, struct file **filp);
274extern int nfs4_share_conflict(struct svc_fh *current_fh,
275 unsigned int deny_type);
276extern void nfs4_lock_state(void); 272extern void nfs4_lock_state(void);
277extern void nfs4_unlock_state(void); 273extern void nfs4_unlock_state(void);
278extern int nfs4_in_grace(void); 274extern int nfs4_in_grace(void);
@@ -282,6 +278,15 @@ extern void nfs4_free_stateowner(struct kref *kref);
282extern void nfsd4_probe_callback(struct nfs4_client *clp); 278extern void nfsd4_probe_callback(struct nfs4_client *clp);
283extern void nfsd4_cb_recall(struct nfs4_delegation *dp); 279extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
284extern void nfs4_put_delegation(struct nfs4_delegation *dp); 280extern void nfs4_put_delegation(struct nfs4_delegation *dp);
281extern int nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
282extern void nfsd4_init_recdir(char *recdir_name);
283extern int nfsd4_recdir_load(void);
284extern void nfsd4_shutdown_recdir(void);
285extern int nfs4_client_to_reclaim(const char *name);
286extern int nfs4_has_reclaimed_state(const char *name);
287extern void nfsd4_recdir_purge_old(void);
288extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
289extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
285 290
286static inline void 291static inline void
287nfs4_put_stateowner(struct nfs4_stateowner *so) 292nfs4_put_stateowner(struct nfs4_stateowner *so)
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index a1f5ad0be1..4d24d65c0e 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -210,6 +210,7 @@ struct nfsd4_open {
210 u32 op_share_access; /* request */ 210 u32 op_share_access; /* request */
211 u32 op_share_deny; /* request */ 211 u32 op_share_deny; /* request */
212 stateid_t op_stateid; /* response */ 212 stateid_t op_stateid; /* response */
213 u32 op_recall; /* recall */
213 struct nfsd4_change_info op_cinfo; /* response */ 214 struct nfsd4_change_info op_cinfo; /* response */
214 u32 op_rflags; /* response */ 215 u32 op_rflags; /* response */
215 int op_truncate; /* used during processing */ 216 int op_truncate; /* used during processing */
diff --git a/include/linux/nfsd_idmap.h b/include/linux/nfsd_idmap.h
index 9bb7f30e92..e82746fcad 100644
--- a/include/linux/nfsd_idmap.h
+++ b/include/linux/nfsd_idmap.h
@@ -43,8 +43,13 @@
43/* XXX from linux/nfs_idmap.h */ 43/* XXX from linux/nfs_idmap.h */
44#define IDMAP_NAMESZ 128 44#define IDMAP_NAMESZ 128
45 45
46#ifdef CONFIG_NFSD_V4
46void nfsd_idmap_init(void); 47void nfsd_idmap_init(void);
47void nfsd_idmap_shutdown(void); 48void nfsd_idmap_shutdown(void);
49#else
50static inline void nfsd_idmap_init(void) {};
51static inline void nfsd_idmap_shutdown(void) {};
52#endif
48 53
49int nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *); 54int nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *);
50int nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, __u32 *); 55int nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, __u32 *);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 63e89e47b8..bf608808a6 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1568,6 +1568,7 @@
1568#define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220 1568#define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
1569#define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB 1569#define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB
1570#define PCI_DEVICE_ID_SERVERWORKS_CSB6USB 0x0221 1570#define PCI_DEVICE_ID_SERVERWORKS_CSB6USB 0x0221
1571#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
1571#define PCI_DEVICE_ID_SERVERWORKS_GCLE 0x0225 1572#define PCI_DEVICE_ID_SERVERWORKS_GCLE 0x0225
1572#define PCI_DEVICE_ID_SERVERWORKS_GCLE2 0x0227 1573#define PCI_DEVICE_ID_SERVERWORKS_GCLE2 0x0227
1573#define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230 1574#define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230
diff --git a/include/linux/quota.h b/include/linux/quota.h
index ac5b90f4f2..700ead4508 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -138,8 +138,11 @@ struct if_dqinfo {
138#include <linux/dqblk_v2.h> 138#include <linux/dqblk_v2.h>
139 139
140/* Maximal numbers of writes for quota operation (insert/delete/update) 140/* Maximal numbers of writes for quota operation (insert/delete/update)
141 * (over all formats) - info block, 4 pointer blocks, data block */ 141 * (over VFS all formats) */
142#define DQUOT_MAX_WRITES 6 142#define DQUOT_INIT_ALLOC max(V1_INIT_ALLOC, V2_INIT_ALLOC)
143#define DQUOT_INIT_REWRITE max(V1_INIT_REWRITE, V2_INIT_REWRITE)
144#define DQUOT_DEL_ALLOC max(V1_DEL_ALLOC, V2_DEL_ALLOC)
145#define DQUOT_DEL_REWRITE max(V1_DEL_REWRITE, V2_DEL_REWRITE)
143 146
144/* 147/*
145 * Data for one user/group kept in memory 148 * Data for one user/group kept in memory
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 32148625fc..4c7c5689ad 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1644,11 +1644,18 @@ struct reiserfs_journal_header {
1644#define JOURNAL_MAX_TRANS_AGE 30 1644#define JOURNAL_MAX_TRANS_AGE 30
1645#define JOURNAL_PER_BALANCE_CNT (3 * (MAX_HEIGHT-2) + 9) 1645#define JOURNAL_PER_BALANCE_CNT (3 * (MAX_HEIGHT-2) + 9)
1646#ifdef CONFIG_QUOTA 1646#ifdef CONFIG_QUOTA
1647#define REISERFS_QUOTA_TRANS_BLOCKS 2 /* We need to update data and inode (atime) */ 1647/* We need to update data and inode (atime) */
1648#define REISERFS_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*(JOURNAL_PER_BALANCE_CNT+2)+1) /* 1 balancing, 1 bitmap, 1 data per write + stat data update */ 1648#define REISERFS_QUOTA_TRANS_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? 2 : 0)
1649/* 1 balancing, 1 bitmap, 1 data per write + stat data update */
1650#define REISERFS_QUOTA_INIT_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? \
1651(DQUOT_INIT_ALLOC*(JOURNAL_PER_BALANCE_CNT+2)+DQUOT_INIT_REWRITE+1) : 0)
1652/* same as with INIT */
1653#define REISERFS_QUOTA_DEL_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? \
1654(DQUOT_DEL_ALLOC*(JOURNAL_PER_BALANCE_CNT+2)+DQUOT_DEL_REWRITE+1) : 0)
1649#else 1655#else
1650#define REISERFS_QUOTA_TRANS_BLOCKS 0 1656#define REISERFS_QUOTA_TRANS_BLOCKS(s) 0
1651#define REISERFS_QUOTA_INIT_BLOCKS 0 1657#define REISERFS_QUOTA_INIT_BLOCKS(s) 0
1658#define REISERFS_QUOTA_DEL_BLOCKS(s) 0
1652#endif 1659#endif
1653 1660
1654/* both of these can be as low as 1, or as high as you want. The min is the 1661/* both of these can be as low as 1, or as high as you want. The min is the
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 37a3a7afbe..31c709d0fe 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -467,6 +467,8 @@ enum reiserfs_mount_options {
467 REISERFS_ERROR_RO, 467 REISERFS_ERROR_RO,
468 REISERFS_ERROR_CONTINUE, 468 REISERFS_ERROR_CONTINUE,
469 469
470 REISERFS_QUOTA, /* Some quota option specified */
471
470 REISERFS_TEST1, 472 REISERFS_TEST1,
471 REISERFS_TEST2, 473 REISERFS_TEST2,
472 REISERFS_TEST3, 474 REISERFS_TEST3,
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 11b484e37a..e80fb7ee6e 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -93,6 +93,12 @@ int page_referenced(struct page *, int is_locked, int ignore_token);
93int try_to_unmap(struct page *); 93int try_to_unmap(struct page *);
94 94
95/* 95/*
96 * Called from mm/filemap_xip.c to unmap empty zero page
97 */
98pte_t *page_check_address(struct page *, struct mm_struct *, unsigned long);
99
100
101/*
96 * Used by swapoff to help locate where page is expected in vma. 102 * Used by swapoff to help locate where page is expected in vma.
97 */ 103 */
98unsigned long page_address_in_vma(struct page *, struct vm_area_struct *); 104unsigned long page_address_in_vma(struct page *, struct vm_area_struct *);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 901742f923..2c69682b04 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -561,9 +561,10 @@ struct group_info {
561 groups_free(group_info); \ 561 groups_free(group_info); \
562} while (0) 562} while (0)
563 563
564struct group_info *groups_alloc(int gidsetsize); 564extern struct group_info *groups_alloc(int gidsetsize);
565void groups_free(struct group_info *group_info); 565extern void groups_free(struct group_info *group_info);
566int set_current_groups(struct group_info *group_info); 566extern int set_current_groups(struct group_info *group_info);
567extern int groups_search(struct group_info *group_info, gid_t grp);
567/* access the groups "array" with this macro */ 568/* access the groups "array" with this macro */
568#define GROUP_AT(gi, i) \ 569#define GROUP_AT(gi, i) \
569 ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK]) 570 ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK])
@@ -660,6 +661,7 @@ struct task_struct {
660 struct user_struct *user; 661 struct user_struct *user;
661#ifdef CONFIG_KEYS 662#ifdef CONFIG_KEYS
662 struct key *thread_keyring; /* keyring private to this thread */ 663 struct key *thread_keyring; /* keyring private to this thread */
664 unsigned char jit_keyring; /* default keyring to attach requested keys to */
663#endif 665#endif
664 int oomkilladj; /* OOM kill score adjustment (bit shift). */ 666 int oomkilladj; /* OOM kill score adjustment (bit shift). */
665 char comm[TASK_COMM_LEN]; /* executable name excluding path 667 char comm[TASK_COMM_LEN]; /* executable name excluding path
diff --git a/include/media/audiochip.h b/include/media/audiochip.h
index d3e9e30608..f345a61c3b 100644
--- a/include/media/audiochip.h
+++ b/include/media/audiochip.h
@@ -1,3 +1,7 @@
1/*
2 * $Id: audiochip.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
3 */
4
1#ifndef AUDIOCHIP_H 5#ifndef AUDIOCHIP_H
2#define AUDIOCHIP_H 6#define AUDIOCHIP_H
3 7
diff --git a/include/media/id.h b/include/media/id.h
index 1b0320dc8f..a39a642391 100644
--- a/include/media/id.h
+++ b/include/media/id.h
@@ -1,3 +1,7 @@
1/*
2 * $Id: id.h,v 1.4 2005/06/12 04:19:19 mchehab Exp $
3 */
4
1/* FIXME: this temporarely, until these are included in linux/i2c-id.h */ 5/* FIXME: this temporarely, until these are included in linux/i2c-id.h */
2 6
3/* drivers */ 7/* drivers */
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index 62c963a52d..698670547f 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: ir-common.h,v 1.8 2005/02/22 12:28:40 kraxel Exp $ 2 * $Id: ir-common.h,v 1.9 2005/05/15 19:01:26 mchehab Exp $
3 * 3 *
4 * some common structs and functions to handle infrared remotes via 4 * some common structs and functions to handle infrared remotes via
5 * input layer ... 5 * input layer ...
@@ -50,6 +50,7 @@ extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE];
50extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; 50extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE];
51extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; 51extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE];
52extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; 52extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
53extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
53 54
54void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, 55void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
55 int ir_type, IR_KEYTAB_TYPE *ir_codes); 56 int ir_type, IR_KEYTAB_TYPE *ir_codes);
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 156a9c51ff..2dd8310901 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -25,6 +25,8 @@
25 25
26#include "id.h" 26#include "id.h"
27 27
28#define ADDR_UNSET (255)
29
28#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */ 30#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */
29#define TUNER_PHILIPS_PAL_I 1 31#define TUNER_PHILIPS_PAL_I 1
30#define TUNER_PHILIPS_NTSC 2 32#define TUNER_PHILIPS_NTSC 2
@@ -98,12 +100,23 @@
98#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */ 100#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */
99#define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */ 101#define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */
100 102
103#define TUNER_YMEC_TVF_8531MF 58
104#define TUNER_YMEC_TVF_5533MF 59 /* Pixelview Pro Ultra NTSC */
105#define TUNER_THOMSON_DTT7611 60
106#define TUNER_TENA_9533_DI 61
107#define TUNER_TEA5767 62 /* Only FM Radio Tuner */
108
109#define TEA5767_TUNER_NAME "Philips TEA5767HN FM Radio"
110
111#define TUNER_THOMSON_DTT7611 60
112
101#define NOTUNER 0 113#define NOTUNER 0
102#define PAL 1 /* PAL_BG */ 114#define PAL 1 /* PAL_BG */
103#define PAL_I 2 115#define PAL_I 2
104#define NTSC 3 116#define NTSC 3
105#define SECAM 4 117#define SECAM 4
106#define ATSC 5 118#define ATSC 5
119#define RADIO 6
107 120
108#define NoTuner 0 121#define NoTuner 0
109#define Philips 1 122#define Philips 1
@@ -119,10 +132,20 @@
119#define TCL 11 132#define TCL 11
120#define THOMSON 12 133#define THOMSON 12
121 134
135enum v4l_radio_tuner {
136 TEA5767_LOW_LO_32768 = 0,
137 TEA5767_HIGH_LO_32768 = 1,
138 TEA5767_LOW_LO_13MHz = 2,
139 TEA5767_HIGH_LO_13MHz = 3,
140};
141
142
122#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */ 143#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */
123#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */ 144#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */
145#define TUNER_SET_TYPE_ADDR _IOW('T',3,int) /* set tuner type and I2C addr */
124 146
125#define TDA9887_SET_CONFIG _IOW('t',5,int) 147#define TDA9887_SET_CONFIG _IOW('t',5,int)
148
126/* tv card specific */ 149/* tv card specific */
127# define TDA9887_PRESENT (1<<0) 150# define TDA9887_PRESENT (1<<0)
128# define TDA9887_PORT1_INACTIVE (1<<1) 151# define TDA9887_PORT1_INACTIVE (1<<1)
@@ -143,6 +166,12 @@
143#define I2C_ADDR_TDA8290 0x4b 166#define I2C_ADDR_TDA8290 0x4b
144#define I2C_ADDR_TDA8275 0x61 167#define I2C_ADDR_TDA8275 0x61
145 168
169struct tuner_addr {
170 enum v4l2_tuner_type v4l2_tuner;
171 unsigned int type;
172 unsigned short addr;
173};
174
146struct tuner { 175struct tuner {
147 /* device */ 176 /* device */
148 struct i2c_client i2c; 177 struct i2c_client i2c;
diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h
index 627603e561..5c4fe30e8d 100644
--- a/include/media/tveeprom.h
+++ b/include/media/tveeprom.h
@@ -1,3 +1,7 @@
1/*
2 * $Id: tveeprom.h,v 1.2 2005/06/12 04:19:19 mchehab Exp $
3 */
4
1struct tveeprom { 5struct tveeprom {
2 u32 has_radio; 6 u32 has_radio;
3 7
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index a53e08a45e..88d9fe5975 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -131,7 +131,6 @@ sctp_state_fn_t sctp_sf_do_ecne;
131sctp_state_fn_t sctp_sf_ootb; 131sctp_state_fn_t sctp_sf_ootb;
132sctp_state_fn_t sctp_sf_pdiscard; 132sctp_state_fn_t sctp_sf_pdiscard;
133sctp_state_fn_t sctp_sf_violation; 133sctp_state_fn_t sctp_sf_violation;
134sctp_state_fn_t sctp_sf_violation_chunklen;
135sctp_state_fn_t sctp_sf_discard_chunk; 134sctp_state_fn_t sctp_sf_discard_chunk;
136sctp_state_fn_t sctp_sf_do_5_2_1_siminit; 135sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
137sctp_state_fn_t sctp_sf_do_5_2_2_dupinit; 136sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
@@ -259,11 +258,6 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
259void sctp_chunk_assign_tsn(struct sctp_chunk *); 258void sctp_chunk_assign_tsn(struct sctp_chunk *);
260void sctp_chunk_assign_ssn(struct sctp_chunk *); 259void sctp_chunk_assign_ssn(struct sctp_chunk *);
261 260
262sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
263 __u16 error,
264 const struct sctp_association *asoc,
265 struct sctp_transport *transport);
266
267/* Prototypes for statetable processing. */ 261/* Prototypes for statetable processing. */
268 262
269int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, 263int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
diff --git a/include/scsi/sg_request.h b/include/scsi/sg_request.h
new file mode 100644
index 0000000000..57ff525bdd
--- /dev/null
+++ b/include/scsi/sg_request.h
@@ -0,0 +1,26 @@
1typedef struct scsi_request Scsi_Request;
2
3static Scsi_Request *dummy_cmdp; /* only used for sizeof */
4
5typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
6 unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
7 unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */
8 unsigned bufflen; /* Size of (aggregate) data buffer */
9 unsigned b_malloc_len; /* actual len malloc'ed in buffer */
10 void *buffer; /* Data buffer or scatter list (k_use_sg>0) */
11 char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */
12 unsigned char cmd_opcode; /* first byte of command */
13} Sg_scatter_hold;
14
15typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
16 Scsi_Request *my_cmdp; /* != 0 when request with lower levels */
17 struct sg_request *nextrp; /* NULL -> tail request (slist) */
18 struct sg_fd *parentfp; /* NULL -> not in use */
19 Sg_scatter_hold data; /* hold buffer, perhaps scatter list */
20 sg_io_hdr_t header; /* scsi command+info, see <scsi/sg.h> */
21 unsigned char sense_b[sizeof (dummy_cmdp->sr_sense_buffer)];
22 char res_used; /* 1 -> using reserve buffer, 0 -> not ... */
23 char orphan; /* 1 -> drop on sight, 0 -> normal */
24 char sg_io_owned; /* 1 -> packet belongs to SG_IO */
25 volatile char done; /* 0->before bh, 1->before read, 2->read */
26} Sg_request;
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index f6297c3069..ba039e827d 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -45,7 +45,7 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
45 } 45 }
46} 46}
47 47
48void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) 48static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
49{ 49{
50 static int count = 100; 50 static int count = 100;
51 51
diff --git a/kernel/kmod.c b/kernel/kmod.c
index eed53d4f52..44166e3bb8 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -120,6 +120,7 @@ struct subprocess_info {
120 char *path; 120 char *path;
121 char **argv; 121 char **argv;
122 char **envp; 122 char **envp;
123 struct key *ring;
123 int wait; 124 int wait;
124 int retval; 125 int retval;
125}; 126};
@@ -130,16 +131,21 @@ struct subprocess_info {
130static int ____call_usermodehelper(void *data) 131static int ____call_usermodehelper(void *data)
131{ 132{
132 struct subprocess_info *sub_info = data; 133 struct subprocess_info *sub_info = data;
134 struct key *old_session;
133 int retval; 135 int retval;
134 136
135 /* Unblock all signals. */ 137 /* Unblock all signals and set the session keyring. */
138 key_get(sub_info->ring);
136 flush_signals(current); 139 flush_signals(current);
137 spin_lock_irq(&current->sighand->siglock); 140 spin_lock_irq(&current->sighand->siglock);
141 old_session = __install_session_keyring(current, sub_info->ring);
138 flush_signal_handlers(current, 1); 142 flush_signal_handlers(current, 1);
139 sigemptyset(&current->blocked); 143 sigemptyset(&current->blocked);
140 recalc_sigpending(); 144 recalc_sigpending();
141 spin_unlock_irq(&current->sighand->siglock); 145 spin_unlock_irq(&current->sighand->siglock);
142 146
147 key_put(old_session);
148
143 /* We can run anywhere, unlike our parent keventd(). */ 149 /* We can run anywhere, unlike our parent keventd(). */
144 set_cpus_allowed(current, CPU_MASK_ALL); 150 set_cpus_allowed(current, CPU_MASK_ALL);
145 151
@@ -211,10 +217,11 @@ static void __call_usermodehelper(void *data)
211} 217}
212 218
213/** 219/**
214 * call_usermodehelper - start a usermode application 220 * call_usermodehelper_keys - start a usermode application
215 * @path: pathname for the application 221 * @path: pathname for the application
216 * @argv: null-terminated argument list 222 * @argv: null-terminated argument list
217 * @envp: null-terminated environment list 223 * @envp: null-terminated environment list
224 * @session_keyring: session keyring for process (NULL for an empty keyring)
218 * @wait: wait for the application to finish and return status. 225 * @wait: wait for the application to finish and return status.
219 * 226 *
220 * Runs a user-space application. The application is started 227 * Runs a user-space application. The application is started
@@ -224,7 +231,8 @@ static void __call_usermodehelper(void *data)
224 * Must be called from process context. Returns a negative error code 231 * Must be called from process context. Returns a negative error code
225 * if program was not execed successfully, or 0. 232 * if program was not execed successfully, or 0.
226 */ 233 */
227int call_usermodehelper(char *path, char **argv, char **envp, int wait) 234int call_usermodehelper_keys(char *path, char **argv, char **envp,
235 struct key *session_keyring, int wait)
228{ 236{
229 DECLARE_COMPLETION(done); 237 DECLARE_COMPLETION(done);
230 struct subprocess_info sub_info = { 238 struct subprocess_info sub_info = {
@@ -232,6 +240,7 @@ int call_usermodehelper(char *path, char **argv, char **envp, int wait)
232 .path = path, 240 .path = path,
233 .argv = argv, 241 .argv = argv,
234 .envp = envp, 242 .envp = envp,
243 .ring = session_keyring,
235 .wait = wait, 244 .wait = wait,
236 .retval = 0, 245 .retval = 0,
237 }; 246 };
@@ -247,7 +256,7 @@ int call_usermodehelper(char *path, char **argv, char **envp, int wait)
247 wait_for_completion(&done); 256 wait_for_completion(&done);
248 return sub_info.retval; 257 return sub_info.retval;
249} 258}
250EXPORT_SYMBOL(call_usermodehelper); 259EXPORT_SYMBOL(call_usermodehelper_keys);
251 260
252void __init usermodehelper_init(void) 261void __init usermodehelper_init(void)
253{ 262{
diff --git a/kernel/module.c b/kernel/module.c
index a566745dde..068e271ab3 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -35,6 +35,7 @@
35#include <linux/notifier.h> 35#include <linux/notifier.h>
36#include <linux/stop_machine.h> 36#include <linux/stop_machine.h>
37#include <linux/device.h> 37#include <linux/device.h>
38#include <linux/string.h>
38#include <asm/uaccess.h> 39#include <asm/uaccess.h>
39#include <asm/semaphore.h> 40#include <asm/semaphore.h>
40#include <asm/cacheflush.h> 41#include <asm/cacheflush.h>
@@ -370,6 +371,43 @@ static inline void percpu_modcopy(void *pcpudst, const void *src,
370#endif /* CONFIG_SMP */ 371#endif /* CONFIG_SMP */
371 372
372#ifdef CONFIG_MODULE_UNLOAD 373#ifdef CONFIG_MODULE_UNLOAD
374#define MODINFO_ATTR(field) \
375static void setup_modinfo_##field(struct module *mod, const char *s) \
376{ \
377 mod->field = kstrdup(s, GFP_KERNEL); \
378} \
379static ssize_t show_modinfo_##field(struct module_attribute *mattr, \
380 struct module *mod, char *buffer) \
381{ \
382 return sprintf(buffer, "%s\n", mod->field); \
383} \
384static int modinfo_##field##_exists(struct module *mod) \
385{ \
386 return mod->field != NULL; \
387} \
388static void free_modinfo_##field(struct module *mod) \
389{ \
390 kfree(mod->field); \
391 mod->field = NULL; \
392} \
393static struct module_attribute modinfo_##field = { \
394 .attr = { .name = __stringify(field), .mode = 0444, \
395 .owner = THIS_MODULE }, \
396 .show = show_modinfo_##field, \
397 .setup = setup_modinfo_##field, \
398 .test = modinfo_##field##_exists, \
399 .free = free_modinfo_##field, \
400};
401
402MODINFO_ATTR(version);
403MODINFO_ATTR(srcversion);
404
405static struct module_attribute *modinfo_attrs[] = {
406 &modinfo_version,
407 &modinfo_srcversion,
408 NULL,
409};
410
373/* Init the unload section of the module. */ 411/* Init the unload section of the module. */
374static void module_unload_init(struct module *mod) 412static void module_unload_init(struct module *mod)
375{ 413{
@@ -692,7 +730,7 @@ static int obsparm_copy_string(const char *val, struct kernel_param *kp)
692 return 0; 730 return 0;
693} 731}
694 732
695int set_obsolete(const char *val, struct kernel_param *kp) 733static int set_obsolete(const char *val, struct kernel_param *kp)
696{ 734{
697 unsigned int min, max; 735 unsigned int min, max;
698 unsigned int size, maxsize; 736 unsigned int size, maxsize;
@@ -1031,6 +1069,32 @@ static void module_remove_refcnt_attr(struct module *mod)
1031} 1069}
1032#endif 1070#endif
1033 1071
1072#ifdef CONFIG_MODULE_UNLOAD
1073static int module_add_modinfo_attrs(struct module *mod)
1074{
1075 struct module_attribute *attr;
1076 int error = 0;
1077 int i;
1078
1079 for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
1080 if (!attr->test ||
1081 (attr->test && attr->test(mod)))
1082 error = sysfs_create_file(&mod->mkobj.kobj,&attr->attr);
1083 }
1084 return error;
1085}
1086
1087static void module_remove_modinfo_attrs(struct module *mod)
1088{
1089 struct module_attribute *attr;
1090 int i;
1091
1092 for (i = 0; (attr = modinfo_attrs[i]); i++) {
1093 sysfs_remove_file(&mod->mkobj.kobj,&attr->attr);
1094 attr->free(mod);
1095 }
1096}
1097#endif
1034 1098
1035static int mod_sysfs_setup(struct module *mod, 1099static int mod_sysfs_setup(struct module *mod,
1036 struct kernel_param *kparam, 1100 struct kernel_param *kparam,
@@ -1056,6 +1120,12 @@ static int mod_sysfs_setup(struct module *mod,
1056 if (err) 1120 if (err)
1057 goto out_unreg; 1121 goto out_unreg;
1058 1122
1123#ifdef CONFIG_MODULE_UNLOAD
1124 err = module_add_modinfo_attrs(mod);
1125 if (err)
1126 goto out_unreg;
1127#endif
1128
1059 return 0; 1129 return 0;
1060 1130
1061out_unreg: 1131out_unreg:
@@ -1066,6 +1136,9 @@ out:
1066 1136
1067static void mod_kobject_remove(struct module *mod) 1137static void mod_kobject_remove(struct module *mod)
1068{ 1138{
1139#ifdef CONFIG_MODULE_UNLOAD
1140 module_remove_modinfo_attrs(mod);
1141#endif
1069 module_remove_refcnt_attr(mod); 1142 module_remove_refcnt_attr(mod);
1070 module_param_sysfs_remove(mod); 1143 module_param_sysfs_remove(mod);
1071 1144
@@ -1311,6 +1384,23 @@ static char *get_modinfo(Elf_Shdr *sechdrs,
1311 return NULL; 1384 return NULL;
1312} 1385}
1313 1386
1387#ifdef CONFIG_MODULE_UNLOAD
1388static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
1389 unsigned int infoindex)
1390{
1391 struct module_attribute *attr;
1392 int i;
1393
1394 for (i = 0; (attr = modinfo_attrs[i]); i++) {
1395 if (attr->setup)
1396 attr->setup(mod,
1397 get_modinfo(sechdrs,
1398 infoindex,
1399 attr->attr.name));
1400 }
1401}
1402#endif
1403
1314#ifdef CONFIG_KALLSYMS 1404#ifdef CONFIG_KALLSYMS
1315int is_exported(const char *name, const struct module *mod) 1405int is_exported(const char *name, const struct module *mod)
1316{ 1406{
@@ -1615,6 +1705,11 @@ static struct module *load_module(void __user *umod,
1615 /* Set up license info based on the info section */ 1705 /* Set up license info based on the info section */
1616 set_license(mod, get_modinfo(sechdrs, infoindex, "license")); 1706 set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
1617 1707
1708#ifdef CONFIG_MODULE_UNLOAD
1709 /* Set up MODINFO_ATTR fields */
1710 setup_modinfo(mod, sechdrs, infoindex);
1711#endif
1712
1618 /* Fix up syms, so that st_value is a pointer to location. */ 1713 /* Fix up syms, so that st_value is a pointer to location. */
1619 err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex, 1714 err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
1620 mod); 1715 mod);
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 90b3b68dee..53f9f8720e 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -81,7 +81,7 @@ static int nr_copy_pages_check;
81extern char resume_file[]; 81extern char resume_file[];
82 82
83/* Local variables that should not be affected by save */ 83/* Local variables that should not be affected by save */
84unsigned int nr_copy_pages __nosavedata = 0; 84static unsigned int nr_copy_pages __nosavedata = 0;
85 85
86/* Suspend pagedir is allocated before final copy, therefore it 86/* Suspend pagedir is allocated before final copy, therefore it
87 must be freed after resume 87 must be freed after resume
diff --git a/kernel/sys.c b/kernel/sys.c
index 5a9d6b0750..da24bc1292 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1259,7 +1259,7 @@ static void groups_sort(struct group_info *group_info)
1259} 1259}
1260 1260
1261/* a simple bsearch */ 1261/* a simple bsearch */
1262static int groups_search(struct group_info *group_info, gid_t grp) 1262int groups_search(struct group_info *group_info, gid_t grp)
1263{ 1263{
1264 int left, right; 1264 int left, right;
1265 1265
diff --git a/mm/Makefile b/mm/Makefile
index 8f70ffd763..4cd69e3ce4 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_SPARSEMEM) += sparse.o
19obj-$(CONFIG_SHMEM) += shmem.o 19obj-$(CONFIG_SHMEM) += shmem.o
20obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o 20obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
21 21
22obj-$(CONFIG_FS_XIP) += filemap_xip.o
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 57264d74b8..5f19e87bc5 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -43,6 +43,10 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
43 goto out; 43 goto out;
44 } 44 }
45 45
46 if (mapping->a_ops->get_xip_page)
47 /* no bad return value, but ignore advice */
48 goto out;
49
46 /* Careful about overflows. Len == 0 means "as much as possible" */ 50 /* Careful about overflows. Len == 0 means "as much as possible" */
47 endbyte = offset + len; 51 endbyte = offset + len;
48 if (!len || endbyte < len) 52 if (!len || endbyte < len)
diff --git a/mm/filemap.c b/mm/filemap.c
index a3598b542a..7332194d7a 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -28,6 +28,7 @@
28#include <linux/blkdev.h> 28#include <linux/blkdev.h>
29#include <linux/security.h> 29#include <linux/security.h>
30#include <linux/syscalls.h> 30#include <linux/syscalls.h>
31#include "filemap.h"
31/* 32/*
32 * FIXME: remove all knowledge of the buffer layer from the core VM 33 * FIXME: remove all knowledge of the buffer layer from the core VM
33 */ 34 */
@@ -1714,32 +1715,7 @@ int remove_suid(struct dentry *dentry)
1714} 1715}
1715EXPORT_SYMBOL(remove_suid); 1716EXPORT_SYMBOL(remove_suid);
1716 1717
1717/* 1718size_t
1718 * Copy as much as we can into the page and return the number of bytes which
1719 * were sucessfully copied. If a fault is encountered then clear the page
1720 * out to (offset+bytes) and return the number of bytes which were copied.
1721 */
1722static inline size_t
1723filemap_copy_from_user(struct page *page, unsigned long offset,
1724 const char __user *buf, unsigned bytes)
1725{
1726 char *kaddr;
1727 int left;
1728
1729 kaddr = kmap_atomic(page, KM_USER0);
1730 left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
1731 kunmap_atomic(kaddr, KM_USER0);
1732
1733 if (left != 0) {
1734 /* Do it the slow way */
1735 kaddr = kmap(page);
1736 left = __copy_from_user(kaddr + offset, buf, bytes);
1737 kunmap(page);
1738 }
1739 return bytes - left;
1740}
1741
1742static size_t
1743__filemap_copy_from_user_iovec(char *vaddr, 1719__filemap_copy_from_user_iovec(char *vaddr,
1744 const struct iovec *iov, size_t base, size_t bytes) 1720 const struct iovec *iov, size_t base, size_t bytes)
1745{ 1721{
@@ -1767,52 +1743,6 @@ __filemap_copy_from_user_iovec(char *vaddr,
1767} 1743}
1768 1744
1769/* 1745/*
1770 * This has the same sideeffects and return value as filemap_copy_from_user().
1771 * The difference is that on a fault we need to memset the remainder of the
1772 * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
1773 * single-segment behaviour.
1774 */
1775static inline size_t
1776filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
1777 const struct iovec *iov, size_t base, size_t bytes)
1778{
1779 char *kaddr;
1780 size_t copied;
1781
1782 kaddr = kmap_atomic(page, KM_USER0);
1783 copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
1784 base, bytes);
1785 kunmap_atomic(kaddr, KM_USER0);
1786 if (copied != bytes) {
1787 kaddr = kmap(page);
1788 copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
1789 base, bytes);
1790 kunmap(page);
1791 }
1792 return copied;
1793}
1794
1795static inline void
1796filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
1797{
1798 const struct iovec *iov = *iovp;
1799 size_t base = *basep;
1800
1801 while (bytes) {
1802 int copy = min(bytes, iov->iov_len - base);
1803
1804 bytes -= copy;
1805 base += copy;
1806 if (iov->iov_len == base) {
1807 iov++;
1808 base = 0;
1809 }
1810 }
1811 *iovp = iov;
1812 *basep = base;
1813}
1814
1815/*
1816 * Performs necessary checks before doing a write 1746 * Performs necessary checks before doing a write
1817 * 1747 *
1818 * Can adjust writing position aor amount of bytes to write. 1748 * Can adjust writing position aor amount of bytes to write.
diff --git a/mm/filemap.h b/mm/filemap.h
new file mode 100644
index 0000000000..13793ba0ce
--- /dev/null
+++ b/mm/filemap.h
@@ -0,0 +1,94 @@
1/*
2 * linux/mm/filemap.h
3 *
4 * Copyright (C) 1994-1999 Linus Torvalds
5 */
6
7#ifndef __FILEMAP_H
8#define __FILEMAP_H
9
10#include <linux/types.h>
11#include <linux/fs.h>
12#include <linux/mm.h>
13#include <linux/highmem.h>
14#include <linux/uio.h>
15#include <linux/config.h>
16#include <asm/uaccess.h>
17
18size_t
19__filemap_copy_from_user_iovec(char *vaddr,
20 const struct iovec *iov,
21 size_t base,
22 size_t bytes);
23
24/*
25 * Copy as much as we can into the page and return the number of bytes which
26 * were sucessfully copied. If a fault is encountered then clear the page
27 * out to (offset+bytes) and return the number of bytes which were copied.
28 */
29static inline size_t
30filemap_copy_from_user(struct page *page, unsigned long offset,
31 const char __user *buf, unsigned bytes)
32{
33 char *kaddr;
34 int left;
35
36 kaddr = kmap_atomic(page, KM_USER0);
37 left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
38 kunmap_atomic(kaddr, KM_USER0);
39
40 if (left != 0) {
41 /* Do it the slow way */
42 kaddr = kmap(page);
43 left = __copy_from_user(kaddr + offset, buf, bytes);
44 kunmap(page);
45 }
46 return bytes - left;
47}
48
49/*
50 * This has the same sideeffects and return value as filemap_copy_from_user().
51 * The difference is that on a fault we need to memset the remainder of the
52 * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
53 * single-segment behaviour.
54 */
55static inline size_t
56filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
57 const struct iovec *iov, size_t base, size_t bytes)
58{
59 char *kaddr;
60 size_t copied;
61
62 kaddr = kmap_atomic(page, KM_USER0);
63 copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
64 base, bytes);
65 kunmap_atomic(kaddr, KM_USER0);
66 if (copied != bytes) {
67 kaddr = kmap(page);
68 copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
69 base, bytes);
70 kunmap(page);
71 }
72 return copied;
73}
74
75static inline void
76filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
77{
78 const struct iovec *iov = *iovp;
79 size_t base = *basep;
80
81 while (bytes) {
82 int copy = min(bytes, iov->iov_len - base);
83
84 bytes -= copy;
85 base += copy;
86 if (iov->iov_len == base) {
87 iov++;
88 base = 0;
89 }
90 }
91 *iovp = iov;
92 *basep = base;
93}
94#endif
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
new file mode 100644
index 0000000000..3b6e384b98
--- /dev/null
+++ b/mm/filemap_xip.c
@@ -0,0 +1,447 @@
1/*
2 * linux/mm/filemap_xip.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 * Author: Carsten Otte <cotte@de.ibm.com>
6 *
7 * derived from linux/mm/filemap.c - Copyright (C) Linus Torvalds
8 *
9 */
10
11#include <linux/fs.h>
12#include <linux/pagemap.h>
13#include <linux/module.h>
14#include <linux/uio.h>
15#include <linux/rmap.h>
16#include <asm/tlbflush.h>
17#include "filemap.h"
18
19/*
20 * This is a file read routine for execute in place files, and uses
21 * the mapping->a_ops->get_xip_page() function for the actual low-level
22 * stuff.
23 *
24 * Note the struct file* is not used at all. It may be NULL.
25 */
26static void
27do_xip_mapping_read(struct address_space *mapping,
28 struct file_ra_state *_ra,
29 struct file *filp,
30 loff_t *ppos,
31 read_descriptor_t *desc,
32 read_actor_t actor)
33{
34 struct inode *inode = mapping->host;
35 unsigned long index, end_index, offset;
36 loff_t isize;
37
38 BUG_ON(!mapping->a_ops->get_xip_page);
39
40 index = *ppos >> PAGE_CACHE_SHIFT;
41 offset = *ppos & ~PAGE_CACHE_MASK;
42
43 isize = i_size_read(inode);
44 if (!isize)
45 goto out;
46
47 end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
48 for (;;) {
49 struct page *page;
50 unsigned long nr, ret;
51
52 /* nr is the maximum number of bytes to copy from this page */
53 nr = PAGE_CACHE_SIZE;
54 if (index >= end_index) {
55 if (index > end_index)
56 goto out;
57 nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
58 if (nr <= offset) {
59 goto out;
60 }
61 }
62 nr = nr - offset;
63
64 page = mapping->a_ops->get_xip_page(mapping,
65 index*(PAGE_SIZE/512), 0);
66 if (!page)
67 goto no_xip_page;
68 if (unlikely(IS_ERR(page))) {
69 if (PTR_ERR(page) == -ENODATA) {
70 /* sparse */
71 page = virt_to_page(empty_zero_page);
72 } else {
73 desc->error = PTR_ERR(page);
74 goto out;
75 }
76 } else
77 BUG_ON(!PageUptodate(page));
78
79 /* If users can be writing to this page using arbitrary
80 * virtual addresses, take care about potential aliasing
81 * before reading the page on the kernel side.
82 */
83 if (mapping_writably_mapped(mapping))
84 flush_dcache_page(page);
85
86 /*
87 * Ok, we have the page, and it's up-to-date, so
88 * now we can copy it to user space...
89 *
90 * The actor routine returns how many bytes were actually used..
91 * NOTE! This may not be the same as how much of a user buffer
92 * we filled up (we may be padding etc), so we can only update
93 * "pos" here (the actor routine has to update the user buffer
94 * pointers and the remaining count).
95 */
96 ret = actor(desc, page, offset, nr);
97 offset += ret;
98 index += offset >> PAGE_CACHE_SHIFT;
99 offset &= ~PAGE_CACHE_MASK;
100
101 if (ret == nr && desc->count)
102 continue;
103 goto out;
104
105no_xip_page:
106 /* Did not get the page. Report it */
107 desc->error = -EIO;
108 goto out;
109 }
110
111out:
112 *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
113 if (filp)
114 file_accessed(filp);
115}
116
117ssize_t
118xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
119{
120 read_descriptor_t desc;
121
122 if (!access_ok(VERIFY_WRITE, buf, len))
123 return -EFAULT;
124
125 desc.written = 0;
126 desc.arg.buf = buf;
127 desc.count = len;
128 desc.error = 0;
129
130 do_xip_mapping_read(filp->f_mapping, &filp->f_ra, filp,
131 ppos, &desc, file_read_actor);
132
133 if (desc.written)
134 return desc.written;
135 else
136 return desc.error;
137}
138EXPORT_SYMBOL_GPL(xip_file_read);
139
140ssize_t
141xip_file_sendfile(struct file *in_file, loff_t *ppos,
142 size_t count, read_actor_t actor, void *target)
143{
144 read_descriptor_t desc;
145
146 if (!count)
147 return 0;
148
149 desc.written = 0;
150 desc.count = count;
151 desc.arg.data = target;
152 desc.error = 0;
153
154 do_xip_mapping_read(in_file->f_mapping, &in_file->f_ra, in_file,
155 ppos, &desc, actor);
156 if (desc.written)
157 return desc.written;
158 return desc.error;
159}
160EXPORT_SYMBOL_GPL(xip_file_sendfile);
161
162/*
163 * __xip_unmap is invoked from xip_unmap and
164 * xip_write
165 *
166 * This function walks all vmas of the address_space and unmaps the
167 * empty_zero_page when found at pgoff. Should it go in rmap.c?
168 */
169static void
170__xip_unmap (struct address_space * mapping,
171 unsigned long pgoff)
172{
173 struct vm_area_struct *vma;
174 struct mm_struct *mm;
175 struct prio_tree_iter iter;
176 unsigned long address;
177 pte_t *pte;
178 pte_t pteval;
179
180 spin_lock(&mapping->i_mmap_lock);
181 vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
182 mm = vma->vm_mm;
183 address = vma->vm_start +
184 ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
185 BUG_ON(address < vma->vm_start || address >= vma->vm_end);
186 /*
187 * We need the page_table_lock to protect us from page faults,
188 * munmap, fork, etc...
189 */
190 pte = page_check_address(virt_to_page(empty_zero_page), mm,
191 address);
192 if (!IS_ERR(pte)) {
193 /* Nuke the page table entry. */
194 flush_cache_page(vma, address, pte_pfn(pte));
195 pteval = ptep_clear_flush(vma, address, pte);
196 BUG_ON(pte_dirty(pteval));
197 pte_unmap(pte);
198 spin_unlock(&mm->page_table_lock);
199 }
200 }
201 spin_unlock(&mapping->i_mmap_lock);
202}
203
204/*
205 * xip_nopage() is invoked via the vma operations vector for a
206 * mapped memory region to read in file data during a page fault.
207 *
208 * This function is derived from filemap_nopage, but used for execute in place
209 */
210static struct page *
211xip_file_nopage(struct vm_area_struct * area,
212 unsigned long address,
213 int *type)
214{
215 struct file *file = area->vm_file;
216 struct address_space *mapping = file->f_mapping;
217 struct inode *inode = mapping->host;
218 struct page *page;
219 unsigned long size, pgoff, endoff;
220
221 pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT)
222 + area->vm_pgoff;
223 endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT)
224 + area->vm_pgoff;
225
226 size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
227 if (pgoff >= size) {
228 return NULL;
229 }
230
231 page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0);
232 if (!IS_ERR(page)) {
233 BUG_ON(!PageUptodate(page));
234 return page;
235 }
236 if (PTR_ERR(page) != -ENODATA)
237 return NULL;
238
239 /* sparse block */
240 if ((area->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
241 (area->vm_flags & (VM_SHARED| VM_MAYSHARE)) &&
242 (!(mapping->host->i_sb->s_flags & MS_RDONLY))) {
243 /* maybe shared writable, allocate new block */
244 page = mapping->a_ops->get_xip_page (mapping,
245 pgoff*(PAGE_SIZE/512), 1);
246 if (IS_ERR(page))
247 return NULL;
248 BUG_ON(!PageUptodate(page));
249 /* unmap page at pgoff from all other vmas */
250 __xip_unmap(mapping, pgoff);
251 } else {
252 /* not shared and writable, use empty_zero_page */
253 page = virt_to_page(empty_zero_page);
254 }
255
256 return page;
257}
258
259static struct vm_operations_struct xip_file_vm_ops = {
260 .nopage = xip_file_nopage,
261};
262
263int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
264{
265 BUG_ON(!file->f_mapping->a_ops->get_xip_page);
266
267 file_accessed(file);
268 vma->vm_ops = &xip_file_vm_ops;
269 return 0;
270}
271EXPORT_SYMBOL_GPL(xip_file_mmap);
272
273static ssize_t
274__xip_file_write(struct file *filp, const char __user *buf,
275 size_t count, loff_t pos, loff_t *ppos)
276{
277 struct address_space * mapping = filp->f_mapping;
278 struct address_space_operations *a_ops = mapping->a_ops;
279 struct inode *inode = mapping->host;
280 long status = 0;
281 struct page *page;
282 size_t bytes;
283 ssize_t written = 0;
284
285 BUG_ON(!mapping->a_ops->get_xip_page);
286
287 do {
288 unsigned long index;
289 unsigned long offset;
290 size_t copied;
291
292 offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
293 index = pos >> PAGE_CACHE_SHIFT;
294 bytes = PAGE_CACHE_SIZE - offset;
295 if (bytes > count)
296 bytes = count;
297
298 /*
299 * Bring in the user page that we will copy from _first_.
300 * Otherwise there's a nasty deadlock on copying from the
301 * same page as we're writing to, without it being marked
302 * up-to-date.
303 */
304 fault_in_pages_readable(buf, bytes);
305
306 page = a_ops->get_xip_page(mapping,
307 index*(PAGE_SIZE/512), 0);
308 if (IS_ERR(page) && (PTR_ERR(page) == -ENODATA)) {
309 /* we allocate a new page unmap it */
310 page = a_ops->get_xip_page(mapping,
311 index*(PAGE_SIZE/512), 1);
312 if (!IS_ERR(page))
313 /* unmap page at pgoff from all other vmas */
314 __xip_unmap(mapping, index);
315 }
316
317 if (IS_ERR(page)) {
318 status = PTR_ERR(page);
319 break;
320 }
321
322 BUG_ON(!PageUptodate(page));
323
324 copied = filemap_copy_from_user(page, offset, buf, bytes);
325 flush_dcache_page(page);
326 if (likely(copied > 0)) {
327 status = copied;
328
329 if (status >= 0) {
330 written += status;
331 count -= status;
332 pos += status;
333 buf += status;
334 }
335 }
336 if (unlikely(copied != bytes))
337 if (status >= 0)
338 status = -EFAULT;
339 if (status < 0)
340 break;
341 } while (count);
342 *ppos = pos;
343 /*
344 * No need to use i_size_read() here, the i_size
345 * cannot change under us because we hold i_sem.
346 */
347 if (pos > inode->i_size) {
348 i_size_write(inode, pos);
349 mark_inode_dirty(inode);
350 }
351
352 return written ? written : status;
353}
354
355ssize_t
356xip_file_write(struct file *filp, const char __user *buf, size_t len,
357 loff_t *ppos)
358{
359 struct address_space *mapping = filp->f_mapping;
360 struct inode *inode = mapping->host;
361 size_t count;
362 loff_t pos;
363 ssize_t ret;
364
365 down(&inode->i_sem);
366
367 if (!access_ok(VERIFY_READ, buf, len)) {
368 ret=-EFAULT;
369 goto out_up;
370 }
371
372 pos = *ppos;
373 count = len;
374
375 vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
376
377 /* We can write back this queue in page reclaim */
378 current->backing_dev_info = mapping->backing_dev_info;
379
380 ret = generic_write_checks(filp, &pos, &count, S_ISBLK(inode->i_mode));
381 if (ret)
382 goto out_backing;
383 if (count == 0)
384 goto out_backing;
385
386 ret = remove_suid(filp->f_dentry);
387 if (ret)
388 goto out_backing;
389
390 inode_update_time(inode, 1);
391
392 ret = __xip_file_write (filp, buf, count, pos, ppos);
393
394 out_backing:
395 current->backing_dev_info = NULL;
396 out_up:
397 up(&inode->i_sem);
398 return ret;
399}
400EXPORT_SYMBOL_GPL(xip_file_write);
401
402/*
403 * truncate a page used for execute in place
404 * functionality is analog to block_truncate_page but does use get_xip_page
405 * to get the page instead of page cache
406 */
407int
408xip_truncate_page(struct address_space *mapping, loff_t from)
409{
410 pgoff_t index = from >> PAGE_CACHE_SHIFT;
411 unsigned offset = from & (PAGE_CACHE_SIZE-1);
412 unsigned blocksize;
413 unsigned length;
414 struct page *page;
415 void *kaddr;
416
417 BUG_ON(!mapping->a_ops->get_xip_page);
418
419 blocksize = 1 << mapping->host->i_blkbits;
420 length = offset & (blocksize - 1);
421
422 /* Block boundary? Nothing to do */
423 if (!length)
424 return 0;
425
426 length = blocksize - length;
427
428 page = mapping->a_ops->get_xip_page(mapping,
429 index*(PAGE_SIZE/512), 0);
430 if (!page)
431 return -ENOMEM;
432 if (unlikely(IS_ERR(page))) {
433 if (PTR_ERR(page) == -ENODATA)
434 /* Hole? No need to truncate */
435 return 0;
436 else
437 return PTR_ERR(page);
438 } else
439 BUG_ON(!PageUptodate(page));
440 kaddr = kmap_atomic(page, KM_USER0);
441 memset(kaddr + offset, 0, length);
442 kunmap_atomic(kaddr, KM_USER0);
443
444 flush_dcache_page(page);
445 return 0;
446}
447EXPORT_SYMBOL_GPL(xip_truncate_page);
diff --git a/mm/madvise.c b/mm/madvise.c
index 54a5d3bc55..73180a2287 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -86,6 +86,11 @@ static long madvise_willneed(struct vm_area_struct * vma,
86 if (!file) 86 if (!file)
87 return -EBADF; 87 return -EBADF;
88 88
89 if (file->f_mapping->a_ops->get_xip_page) {
90 /* no bad return value, but ignore advice */
91 return 0;
92 }
93
89 *prev = vma; 94 *prev = vma;
90 start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; 95 start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
91 if (end > vma->vm_end) 96 if (end > vma->vm_end)
diff --git a/mm/memory.c b/mm/memory.c
index 30975ef487..c256175742 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1458,7 +1458,7 @@ restart:
1458 * unmap_mapping_range - unmap the portion of all mmaps 1458 * unmap_mapping_range - unmap the portion of all mmaps
1459 * in the specified address_space corresponding to the specified 1459 * in the specified address_space corresponding to the specified
1460 * page range in the underlying file. 1460 * page range in the underlying file.
1461 * @address_space: the address space containing mmaps to be unmapped. 1461 * @mapping: the address space containing mmaps to be unmapped.
1462 * @holebegin: byte in first page to unmap, relative to the start of 1462 * @holebegin: byte in first page to unmap, relative to the start of
1463 * the underlying file. This will be rounded down to a PAGE_SIZE 1463 * the underlying file. This will be rounded down to a PAGE_SIZE
1464 * boundary. Note that this is different from vmtruncate(), which 1464 * boundary. Note that this is different from vmtruncate(), which
diff --git a/mm/rmap.c b/mm/rmap.c
index 89770bd25f..08ac5c7fa9 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -247,8 +247,8 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
247 * 247 *
248 * On success returns with mapped pte and locked mm->page_table_lock. 248 * On success returns with mapped pte and locked mm->page_table_lock.
249 */ 249 */
250static pte_t *page_check_address(struct page *page, struct mm_struct *mm, 250pte_t *page_check_address(struct page *page, struct mm_struct *mm,
251 unsigned long address) 251 unsigned long address)
252{ 252{
253 pgd_t *pgd; 253 pgd_t *pgd;
254 pud_t *pud; 254 pud_t *pud;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 058189684c..86073df418 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -92,6 +92,17 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
92 sctp_cmd_seq_t *commands); 92 sctp_cmd_seq_t *commands);
93static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); 93static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
94 94
95static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
96 __u16 error,
97 const struct sctp_association *asoc,
98 struct sctp_transport *transport);
99
100static sctp_disposition_t sctp_sf_violation_chunklen(
101 const struct sctp_endpoint *ep,
102 const struct sctp_association *asoc,
103 const sctp_subtype_t type,
104 void *arg,
105 sctp_cmd_seq_t *commands);
95 106
96/* Small helper function that checks if the chunk length 107/* Small helper function that checks if the chunk length
97 * is of the appropriate length. The 'required_length' argument 108 * is of the appropriate length. The 'required_length' argument
@@ -2328,7 +2339,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
2328 * 2339 *
2329 * This is common code called by several sctp_sf_*_abort() functions above. 2340 * This is common code called by several sctp_sf_*_abort() functions above.
2330 */ 2341 */
2331sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, 2342static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
2332 __u16 error, 2343 __u16 error,
2333 const struct sctp_association *asoc, 2344 const struct sctp_association *asoc,
2334 struct sctp_transport *transport) 2345 struct sctp_transport *transport)
@@ -3687,7 +3698,8 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
3687 * 3698 *
3688 * Generate an ABORT chunk and terminate the association. 3699 * Generate an ABORT chunk and terminate the association.
3689 */ 3700 */
3690sctp_disposition_t sctp_sf_violation_chunklen(const struct sctp_endpoint *ep, 3701static sctp_disposition_t sctp_sf_violation_chunklen(
3702 const struct sctp_endpoint *ep,
3691 const struct sctp_association *asoc, 3703 const struct sctp_association *asoc,
3692 const sctp_subtype_t type, 3704 const sctp_subtype_t type,
3693 void *arg, 3705 void *arg,
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 32e8acbc60..62a0734952 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -41,6 +41,7 @@ EXPORT_SYMBOL(rpc_release_task);
41 41
42/* RPC client functions */ 42/* RPC client functions */
43EXPORT_SYMBOL(rpc_create_client); 43EXPORT_SYMBOL(rpc_create_client);
44EXPORT_SYMBOL(rpc_new_client);
44EXPORT_SYMBOL(rpc_clone_client); 45EXPORT_SYMBOL(rpc_clone_client);
45EXPORT_SYMBOL(rpc_bind_new_program); 46EXPORT_SYMBOL(rpc_bind_new_program);
46EXPORT_SYMBOL(rpc_destroy_client); 47EXPORT_SYMBOL(rpc_destroy_client);
diff --git a/security/keys/Makefile b/security/keys/Makefile
index ddb495d650..c392d750b2 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -7,8 +7,9 @@ obj-y := \
7 keyring.o \ 7 keyring.o \
8 keyctl.o \ 8 keyctl.o \
9 process_keys.o \ 9 process_keys.o \
10 user_defined.o \ 10 request_key.o \
11 request_key.o 11 request_key_auth.o \
12 user_defined.o
12 13
13obj-$(CONFIG_KEYS_COMPAT) += compat.o 14obj-$(CONFIG_KEYS_COMPAT) += compat.o
14obj-$(CONFIG_PROC_FS) += proc.o 15obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/security/keys/compat.c b/security/keys/compat.c
index aff8b22dcb..3303673c63 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -1,6 +1,6 @@
1/* compat.c: 32-bit compatibility syscall for 64-bit systems 1/* compat.c: 32-bit compatibility syscall for 64-bit systems
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -24,7 +24,7 @@
24 * - if you can, you should call sys_keyctl directly 24 * - if you can, you should call sys_keyctl directly
25 */ 25 */
26asmlinkage long compat_sys_keyctl(u32 option, 26asmlinkage long compat_sys_keyctl(u32 option,
27 u32 arg2, u32 arg3, u32 arg4, u32 arg5) 27 u32 arg2, u32 arg3, u32 arg4, u32 arg5)
28{ 28{
29 switch (option) { 29 switch (option) {
30 case KEYCTL_GET_KEYRING_ID: 30 case KEYCTL_GET_KEYRING_ID:
@@ -71,6 +71,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
71 case KEYCTL_NEGATE: 71 case KEYCTL_NEGATE:
72 return keyctl_negate_key(arg2, arg3, arg4); 72 return keyctl_negate_key(arg2, arg3, arg4);
73 73
74 case KEYCTL_SET_REQKEY_KEYRING:
75 return keyctl_set_reqkey_keyring(arg2);
76
74 default: 77 default:
75 return -EOPNOTSUPP; 78 return -EOPNOTSUPP;
76 } 79 }
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 67b2b93a74..46c8602661 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -1,6 +1,6 @@
1/* internal.h: authentication token and access key management internal defs 1/* internal.h: authentication token and access key management internal defs
2 * 2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -15,6 +15,16 @@
15#include <linux/key.h> 15#include <linux/key.h>
16#include <linux/key-ui.h> 16#include <linux/key-ui.h>
17 17
18#if 0
19#define kenter(FMT, a...) printk("==> %s("FMT")\n",__FUNCTION__ , ## a)
20#define kleave(FMT, a...) printk("<== %s()"FMT"\n",__FUNCTION__ , ## a)
21#define kdebug(FMT, a...) printk(FMT"\n" , ## a)
22#else
23#define kenter(FMT, a...) do {} while(0)
24#define kleave(FMT, a...) do {} while(0)
25#define kdebug(FMT, a...) do {} while(0)
26#endif
27
18extern struct key_type key_type_dead; 28extern struct key_type key_type_dead;
19extern struct key_type key_type_user; 29extern struct key_type key_type_user;
20 30
@@ -66,20 +76,46 @@ extern struct key *__keyring_search_one(struct key *keyring,
66 const char *description, 76 const char *description,
67 key_perm_t perm); 77 key_perm_t perm);
68 78
79extern struct key *keyring_search_instkey(struct key *keyring,
80 key_serial_t target_id);
81
69typedef int (*key_match_func_t)(const struct key *, const void *); 82typedef int (*key_match_func_t)(const struct key *, const void *);
70 83
71extern struct key *keyring_search_aux(struct key *keyring, 84extern struct key *keyring_search_aux(struct key *keyring,
85 struct task_struct *tsk,
72 struct key_type *type, 86 struct key_type *type,
73 const void *description, 87 const void *description,
74 key_match_func_t match); 88 key_match_func_t match);
75 89
76extern struct key *search_process_keyrings_aux(struct key_type *type, 90extern struct key *search_process_keyrings(struct key_type *type,
77 const void *description, 91 const void *description,
78 key_match_func_t match); 92 key_match_func_t match,
93 struct task_struct *tsk);
79 94
80extern struct key *find_keyring_by_name(const char *name, key_serial_t bound); 95extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
81 96
82extern int install_thread_keyring(struct task_struct *tsk); 97extern int install_thread_keyring(struct task_struct *tsk);
98extern int install_process_keyring(struct task_struct *tsk);
99
100extern struct key *request_key_and_link(struct key_type *type,
101 const char *description,
102 const char *callout_info,
103 struct key *dest_keyring);
104
105/*
106 * request_key authorisation
107 */
108struct request_key_auth {
109 struct key *target_key;
110 struct task_struct *context;
111 pid_t pid;
112};
113
114extern struct key_type key_type_request_key_auth;
115extern struct key *request_key_auth_new(struct key *target,
116 struct key **_rkakey);
117
118extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
83 119
84/* 120/*
85 * keyctl functions 121 * keyctl functions
@@ -100,6 +136,7 @@ extern long keyctl_setperm_key(key_serial_t, key_perm_t);
100extern long keyctl_instantiate_key(key_serial_t, const void __user *, 136extern long keyctl_instantiate_key(key_serial_t, const void __user *,
101 size_t, key_serial_t); 137 size_t, key_serial_t);
102extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t); 138extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
139extern long keyctl_set_reqkey_keyring(int);
103 140
104 141
105/* 142/*
diff --git a/security/keys/key.c b/security/keys/key.c
index 59402c8432..3304d37bb3 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
1/* key.c: basic authentication token and access key management 1/* key.c: basic authentication token and access key management
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -294,7 +294,6 @@ struct key *key_alloc(struct key_type *type, const char *desc,
294 } 294 }
295 295
296 atomic_set(&key->usage, 1); 296 atomic_set(&key->usage, 1);
297 rwlock_init(&key->lock);
298 init_rwsem(&key->sem); 297 init_rwsem(&key->sem);
299 key->type = type; 298 key->type = type;
300 key->user = user; 299 key->user = user;
@@ -308,7 +307,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
308 key->payload.data = NULL; 307 key->payload.data = NULL;
309 308
310 if (!not_in_quota) 309 if (!not_in_quota)
311 key->flags |= KEY_FLAG_IN_QUOTA; 310 key->flags |= 1 << KEY_FLAG_IN_QUOTA;
312 311
313 memset(&key->type_data, 0, sizeof(key->type_data)); 312 memset(&key->type_data, 0, sizeof(key->type_data));
314 313
@@ -359,7 +358,7 @@ int key_payload_reserve(struct key *key, size_t datalen)
359 key_check(key); 358 key_check(key);
360 359
361 /* contemplate the quota adjustment */ 360 /* contemplate the quota adjustment */
362 if (delta != 0 && key->flags & KEY_FLAG_IN_QUOTA) { 361 if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
363 spin_lock(&key->user->lock); 362 spin_lock(&key->user->lock);
364 363
365 if (delta > 0 && 364 if (delta > 0 &&
@@ -392,7 +391,8 @@ EXPORT_SYMBOL(key_payload_reserve);
392static int __key_instantiate_and_link(struct key *key, 391static int __key_instantiate_and_link(struct key *key,
393 const void *data, 392 const void *data,
394 size_t datalen, 393 size_t datalen,
395 struct key *keyring) 394 struct key *keyring,
395 struct key *instkey)
396{ 396{
397 int ret, awaken; 397 int ret, awaken;
398 398
@@ -405,27 +405,25 @@ static int __key_instantiate_and_link(struct key *key,
405 down_write(&key_construction_sem); 405 down_write(&key_construction_sem);
406 406
407 /* can't instantiate twice */ 407 /* can't instantiate twice */
408 if (!(key->flags & KEY_FLAG_INSTANTIATED)) { 408 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
409 /* instantiate the key */ 409 /* instantiate the key */
410 ret = key->type->instantiate(key, data, datalen); 410 ret = key->type->instantiate(key, data, datalen);
411 411
412 if (ret == 0) { 412 if (ret == 0) {
413 /* mark the key as being instantiated */ 413 /* mark the key as being instantiated */
414 write_lock(&key->lock);
415
416 atomic_inc(&key->user->nikeys); 414 atomic_inc(&key->user->nikeys);
417 key->flags |= KEY_FLAG_INSTANTIATED; 415 set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
418 416
419 if (key->flags & KEY_FLAG_USER_CONSTRUCT) { 417 if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
420 key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
421 awaken = 1; 418 awaken = 1;
422 }
423
424 write_unlock(&key->lock);
425 419
426 /* and link it into the destination keyring */ 420 /* and link it into the destination keyring */
427 if (keyring) 421 if (keyring)
428 ret = __key_link(keyring, key); 422 ret = __key_link(keyring, key);
423
424 /* disable the authorisation key */
425 if (instkey)
426 key_revoke(instkey);
429 } 427 }
430 } 428 }
431 429
@@ -446,19 +444,21 @@ static int __key_instantiate_and_link(struct key *key,
446int key_instantiate_and_link(struct key *key, 444int key_instantiate_and_link(struct key *key,
447 const void *data, 445 const void *data,
448 size_t datalen, 446 size_t datalen,
449 struct key *keyring) 447 struct key *keyring,
448 struct key *instkey)
450{ 449{
451 int ret; 450 int ret;
452 451
453 if (keyring) 452 if (keyring)
454 down_write(&keyring->sem); 453 down_write(&keyring->sem);
455 454
456 ret = __key_instantiate_and_link(key, data, datalen, keyring); 455 ret = __key_instantiate_and_link(key, data, datalen, keyring, instkey);
457 456
458 if (keyring) 457 if (keyring)
459 up_write(&keyring->sem); 458 up_write(&keyring->sem);
460 459
461 return ret; 460 return ret;
461
462} /* end key_instantiate_and_link() */ 462} /* end key_instantiate_and_link() */
463 463
464EXPORT_SYMBOL(key_instantiate_and_link); 464EXPORT_SYMBOL(key_instantiate_and_link);
@@ -469,7 +469,8 @@ EXPORT_SYMBOL(key_instantiate_and_link);
469 */ 469 */
470int key_negate_and_link(struct key *key, 470int key_negate_and_link(struct key *key,
471 unsigned timeout, 471 unsigned timeout,
472 struct key *keyring) 472 struct key *keyring,
473 struct key *instkey)
473{ 474{
474 struct timespec now; 475 struct timespec now;
475 int ret, awaken; 476 int ret, awaken;
@@ -486,26 +487,26 @@ int key_negate_and_link(struct key *key,
486 down_write(&key_construction_sem); 487 down_write(&key_construction_sem);
487 488
488 /* can't instantiate twice */ 489 /* can't instantiate twice */
489 if (!(key->flags & KEY_FLAG_INSTANTIATED)) { 490 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
490 /* mark the key as being negatively instantiated */ 491 /* mark the key as being negatively instantiated */
491 write_lock(&key->lock);
492
493 atomic_inc(&key->user->nikeys); 492 atomic_inc(&key->user->nikeys);
494 key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE; 493 set_bit(KEY_FLAG_NEGATIVE, &key->flags);
494 set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
495 now = current_kernel_time(); 495 now = current_kernel_time();
496 key->expiry = now.tv_sec + timeout; 496 key->expiry = now.tv_sec + timeout;
497 497
498 if (key->flags & KEY_FLAG_USER_CONSTRUCT) { 498 if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
499 key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
500 awaken = 1; 499 awaken = 1;
501 }
502 500
503 write_unlock(&key->lock);
504 ret = 0; 501 ret = 0;
505 502
506 /* and link it into the destination keyring */ 503 /* and link it into the destination keyring */
507 if (keyring) 504 if (keyring)
508 ret = __key_link(keyring, key); 505 ret = __key_link(keyring, key);
506
507 /* disable the authorisation key */
508 if (instkey)
509 key_revoke(instkey);
509 } 510 }
510 511
511 up_write(&key_construction_sem); 512 up_write(&key_construction_sem);
@@ -553,8 +554,10 @@ static void key_cleanup(void *data)
553 rb_erase(&key->serial_node, &key_serial_tree); 554 rb_erase(&key->serial_node, &key_serial_tree);
554 spin_unlock(&key_serial_lock); 555 spin_unlock(&key_serial_lock);
555 556
557 key_check(key);
558
556 /* deal with the user's key tracking and quota */ 559 /* deal with the user's key tracking and quota */
557 if (key->flags & KEY_FLAG_IN_QUOTA) { 560 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
558 spin_lock(&key->user->lock); 561 spin_lock(&key->user->lock);
559 key->user->qnkeys--; 562 key->user->qnkeys--;
560 key->user->qnbytes -= key->quotalen; 563 key->user->qnbytes -= key->quotalen;
@@ -562,7 +565,7 @@ static void key_cleanup(void *data)
562 } 565 }
563 566
564 atomic_dec(&key->user->nkeys); 567 atomic_dec(&key->user->nkeys);
565 if (key->flags & KEY_FLAG_INSTANTIATED) 568 if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
566 atomic_dec(&key->user->nikeys); 569 atomic_dec(&key->user->nikeys);
567 570
568 key_user_put(key->user); 571 key_user_put(key->user);
@@ -631,9 +634,9 @@ struct key *key_lookup(key_serial_t id)
631 goto error; 634 goto error;
632 635
633 found: 636 found:
634 /* pretent doesn't exist if it's dead */ 637 /* pretend it doesn't exist if it's dead */
635 if (atomic_read(&key->usage) == 0 || 638 if (atomic_read(&key->usage) == 0 ||
636 (key->flags & KEY_FLAG_DEAD) || 639 test_bit(KEY_FLAG_DEAD, &key->flags) ||
637 key->type == &key_type_dead) 640 key->type == &key_type_dead)
638 goto not_found; 641 goto not_found;
639 642
@@ -708,12 +711,9 @@ static inline struct key *__key_update(struct key *key, const void *payload,
708 711
709 ret = key->type->update(key, payload, plen); 712 ret = key->type->update(key, payload, plen);
710 713
711 if (ret == 0) { 714 if (ret == 0)
712 /* updating a negative key instantiates it */ 715 /* updating a negative key instantiates it */
713 write_lock(&key->lock); 716 clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
714 key->flags &= ~KEY_FLAG_NEGATIVE;
715 write_unlock(&key->lock);
716 }
717 717
718 up_write(&key->sem); 718 up_write(&key->sem);
719 719
@@ -793,7 +793,7 @@ struct key *key_create_or_update(struct key *keyring,
793 } 793 }
794 794
795 /* instantiate it and link it into the target keyring */ 795 /* instantiate it and link it into the target keyring */
796 ret = __key_instantiate_and_link(key, payload, plen, keyring); 796 ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL);
797 if (ret < 0) { 797 if (ret < 0) {
798 key_put(key); 798 key_put(key);
799 key = ERR_PTR(ret); 799 key = ERR_PTR(ret);
@@ -841,12 +841,9 @@ int key_update(struct key *key, const void *payload, size_t plen)
841 down_write(&key->sem); 841 down_write(&key->sem);
842 ret = key->type->update(key, payload, plen); 842 ret = key->type->update(key, payload, plen);
843 843
844 if (ret == 0) { 844 if (ret == 0)
845 /* updating a negative key instantiates it */ 845 /* updating a negative key instantiates it */
846 write_lock(&key->lock); 846 clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
847 key->flags &= ~KEY_FLAG_NEGATIVE;
848 write_unlock(&key->lock);
849 }
850 847
851 up_write(&key->sem); 848 up_write(&key->sem);
852 } 849 }
@@ -892,10 +889,7 @@ struct key *key_duplicate(struct key *source, const char *desc)
892 goto error2; 889 goto error2;
893 890
894 atomic_inc(&key->user->nikeys); 891 atomic_inc(&key->user->nikeys);
895 892 set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
896 write_lock(&key->lock);
897 key->flags |= KEY_FLAG_INSTANTIATED;
898 write_unlock(&key->lock);
899 893
900 error_k: 894 error_k:
901 up_read(&key_types_sem); 895 up_read(&key_types_sem);
@@ -922,9 +916,7 @@ void key_revoke(struct key *key)
922 /* make sure no one's trying to change or use the key when we mark 916 /* make sure no one's trying to change or use the key when we mark
923 * it */ 917 * it */
924 down_write(&key->sem); 918 down_write(&key->sem);
925 write_lock(&key->lock); 919 set_bit(KEY_FLAG_REVOKED, &key->flags);
926 key->flags |= KEY_FLAG_REVOKED;
927 write_unlock(&key->lock);
928 up_write(&key->sem); 920 up_write(&key->sem);
929 921
930} /* end key_revoke() */ 922} /* end key_revoke() */
@@ -975,24 +967,33 @@ void unregister_key_type(struct key_type *ktype)
975 /* withdraw the key type */ 967 /* withdraw the key type */
976 list_del_init(&ktype->link); 968 list_del_init(&ktype->link);
977 969
978 /* need to withdraw all keys of this type */ 970 /* mark all the keys of this type dead */
979 spin_lock(&key_serial_lock); 971 spin_lock(&key_serial_lock);
980 972
981 for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { 973 for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
982 key = rb_entry(_n, struct key, serial_node); 974 key = rb_entry(_n, struct key, serial_node);
983 975
984 if (key->type != ktype) 976 if (key->type == ktype)
985 continue; 977 key->type = &key_type_dead;
978 }
979
980 spin_unlock(&key_serial_lock);
981
982 /* make sure everyone revalidates their keys */
983 synchronize_kernel();
986 984
987 write_lock(&key->lock); 985 /* we should now be able to destroy the payloads of all the keys of
988 key->type = &key_type_dead; 986 * this type with impunity */
989 write_unlock(&key->lock); 987 spin_lock(&key_serial_lock);
988
989 for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
990 key = rb_entry(_n, struct key, serial_node);
990 991
991 /* there shouldn't be anyone looking at the description or 992 if (key->type == ktype) {
992 * payload now */ 993 if (ktype->destroy)
993 if (ktype->destroy) 994 ktype->destroy(key);
994 ktype->destroy(key); 995 memset(&key->payload, 0xbd, sizeof(key->payload));
995 memset(&key->payload, 0xbd, sizeof(key->payload)); 996 }
996 } 997 }
997 998
998 spin_unlock(&key_serial_lock); 999 spin_unlock(&key_serial_lock);
@@ -1037,4 +1038,5 @@ void __init key_init(void)
1037 1038
1038 /* link the two root keyrings together */ 1039 /* link the two root keyrings together */
1039 key_link(&root_session_keyring, &root_user_keyring); 1040 key_link(&root_session_keyring, &root_user_keyring);
1041
1040} /* end key_init() */ 1042} /* end key_init() */
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index dc0011b3fa..fea262860e 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1,6 +1,6 @@
1/* keyctl.c: userspace keyctl operations 1/* keyctl.c: userspace keyctl operations
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -49,6 +49,13 @@ asmlinkage long sys_add_key(const char __user *_type,
49 goto error; 49 goto error;
50 type[31] = '\0'; 50 type[31] = '\0';
51 51
52 if (!type[0])
53 goto error;
54
55 ret = -EPERM;
56 if (type[0] == '.')
57 goto error;
58
52 ret = -EFAULT; 59 ret = -EFAULT;
53 dlen = strnlen_user(_description, PAGE_SIZE - 1); 60 dlen = strnlen_user(_description, PAGE_SIZE - 1);
54 if (dlen <= 0) 61 if (dlen <= 0)
@@ -82,7 +89,7 @@ asmlinkage long sys_add_key(const char __user *_type,
82 } 89 }
83 90
84 /* find the target keyring (which must be writable) */ 91 /* find the target keyring (which must be writable) */
85 keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 92 keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
86 if (IS_ERR(keyring)) { 93 if (IS_ERR(keyring)) {
87 ret = PTR_ERR(keyring); 94 ret = PTR_ERR(keyring);
88 goto error3; 95 goto error3;
@@ -181,7 +188,7 @@ asmlinkage long sys_request_key(const char __user *_type,
181 /* get the destination keyring if specified */ 188 /* get the destination keyring if specified */
182 dest = NULL; 189 dest = NULL;
183 if (destringid) { 190 if (destringid) {
184 dest = lookup_user_key(destringid, 1, 0, KEY_WRITE); 191 dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
185 if (IS_ERR(dest)) { 192 if (IS_ERR(dest)) {
186 ret = PTR_ERR(dest); 193 ret = PTR_ERR(dest);
187 goto error3; 194 goto error3;
@@ -196,23 +203,15 @@ asmlinkage long sys_request_key(const char __user *_type,
196 } 203 }
197 204
198 /* do the search */ 205 /* do the search */
199 key = request_key(ktype, description, callout_info); 206 key = request_key_and_link(ktype, description, callout_info, dest);
200 if (IS_ERR(key)) { 207 if (IS_ERR(key)) {
201 ret = PTR_ERR(key); 208 ret = PTR_ERR(key);
202 goto error5; 209 goto error5;
203 } 210 }
204 211
205 /* link the resulting key to the destination keyring */
206 if (dest) {
207 ret = key_link(dest, key);
208 if (ret < 0)
209 goto error6;
210 }
211
212 ret = key->serial; 212 ret = key->serial;
213 213
214 error6: 214 key_put(key);
215 key_put(key);
216 error5: 215 error5:
217 key_type_put(ktype); 216 key_type_put(ktype);
218 error4: 217 error4:
@@ -237,7 +236,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create)
237 struct key *key; 236 struct key *key;
238 long ret; 237 long ret;
239 238
240 key = lookup_user_key(id, create, 0, KEY_SEARCH); 239 key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH);
241 if (IS_ERR(key)) { 240 if (IS_ERR(key)) {
242 ret = PTR_ERR(key); 241 ret = PTR_ERR(key);
243 goto error; 242 goto error;
@@ -324,7 +323,7 @@ long keyctl_update_key(key_serial_t id,
324 } 323 }
325 324
326 /* find the target key (which must be writable) */ 325 /* find the target key (which must be writable) */
327 key = lookup_user_key(id, 0, 0, KEY_WRITE); 326 key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
328 if (IS_ERR(key)) { 327 if (IS_ERR(key)) {
329 ret = PTR_ERR(key); 328 ret = PTR_ERR(key);
330 goto error2; 329 goto error2;
@@ -352,7 +351,7 @@ long keyctl_revoke_key(key_serial_t id)
352 struct key *key; 351 struct key *key;
353 long ret; 352 long ret;
354 353
355 key = lookup_user_key(id, 0, 0, KEY_WRITE); 354 key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
356 if (IS_ERR(key)) { 355 if (IS_ERR(key)) {
357 ret = PTR_ERR(key); 356 ret = PTR_ERR(key);
358 goto error; 357 goto error;
@@ -378,7 +377,7 @@ long keyctl_keyring_clear(key_serial_t ringid)
378 struct key *keyring; 377 struct key *keyring;
379 long ret; 378 long ret;
380 379
381 keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 380 keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
382 if (IS_ERR(keyring)) { 381 if (IS_ERR(keyring)) {
383 ret = PTR_ERR(keyring); 382 ret = PTR_ERR(keyring);
384 goto error; 383 goto error;
@@ -404,13 +403,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
404 struct key *keyring, *key; 403 struct key *keyring, *key;
405 long ret; 404 long ret;
406 405
407 keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 406 keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
408 if (IS_ERR(keyring)) { 407 if (IS_ERR(keyring)) {
409 ret = PTR_ERR(keyring); 408 ret = PTR_ERR(keyring);
410 goto error; 409 goto error;
411 } 410 }
412 411
413 key = lookup_user_key(id, 1, 0, KEY_LINK); 412 key = lookup_user_key(NULL, id, 1, 0, KEY_LINK);
414 if (IS_ERR(key)) { 413 if (IS_ERR(key)) {
415 ret = PTR_ERR(key); 414 ret = PTR_ERR(key);
416 goto error2; 415 goto error2;
@@ -438,13 +437,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
438 struct key *keyring, *key; 437 struct key *keyring, *key;
439 long ret; 438 long ret;
440 439
441 keyring = lookup_user_key(ringid, 0, 0, KEY_WRITE); 440 keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE);
442 if (IS_ERR(keyring)) { 441 if (IS_ERR(keyring)) {
443 ret = PTR_ERR(keyring); 442 ret = PTR_ERR(keyring);
444 goto error; 443 goto error;
445 } 444 }
446 445
447 key = lookup_user_key(id, 0, 0, 0); 446 key = lookup_user_key(NULL, id, 0, 0, 0);
448 if (IS_ERR(key)) { 447 if (IS_ERR(key)) {
449 ret = PTR_ERR(key); 448 ret = PTR_ERR(key);
450 goto error2; 449 goto error2;
@@ -475,16 +474,29 @@ long keyctl_describe_key(key_serial_t keyid,
475 char __user *buffer, 474 char __user *buffer,
476 size_t buflen) 475 size_t buflen)
477{ 476{
478 struct key *key; 477 struct key *key, *instkey;
479 char *tmpbuf; 478 char *tmpbuf;
480 long ret; 479 long ret;
481 480
482 key = lookup_user_key(keyid, 0, 1, KEY_VIEW); 481 key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
483 if (IS_ERR(key)) { 482 if (IS_ERR(key)) {
483 /* viewing a key under construction is permitted if we have the
484 * authorisation token handy */
485 if (PTR_ERR(key) == -EACCES) {
486 instkey = key_get_instantiation_authkey(keyid);
487 if (!IS_ERR(instkey)) {
488 key_put(instkey);
489 key = lookup_user_key(NULL, keyid, 0, 1, 0);
490 if (!IS_ERR(key))
491 goto okay;
492 }
493 }
494
484 ret = PTR_ERR(key); 495 ret = PTR_ERR(key);
485 goto error; 496 goto error;
486 } 497 }
487 498
499okay:
488 /* calculate how much description we're going to return */ 500 /* calculate how much description we're going to return */
489 ret = -ENOMEM; 501 ret = -ENOMEM;
490 tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); 502 tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -568,7 +580,7 @@ long keyctl_keyring_search(key_serial_t ringid,
568 goto error2; 580 goto error2;
569 581
570 /* get the keyring at which to begin the search */ 582 /* get the keyring at which to begin the search */
571 keyring = lookup_user_key(ringid, 0, 0, KEY_SEARCH); 583 keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
572 if (IS_ERR(keyring)) { 584 if (IS_ERR(keyring)) {
573 ret = PTR_ERR(keyring); 585 ret = PTR_ERR(keyring);
574 goto error2; 586 goto error2;
@@ -577,7 +589,7 @@ long keyctl_keyring_search(key_serial_t ringid,
577 /* get the destination keyring if specified */ 589 /* get the destination keyring if specified */
578 dest = NULL; 590 dest = NULL;
579 if (destringid) { 591 if (destringid) {
580 dest = lookup_user_key(destringid, 1, 0, KEY_WRITE); 592 dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
581 if (IS_ERR(dest)) { 593 if (IS_ERR(dest)) {
582 ret = PTR_ERR(dest); 594 ret = PTR_ERR(dest);
583 goto error3; 595 goto error3;
@@ -656,24 +668,23 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
656 long ret; 668 long ret;
657 669
658 /* find the key first */ 670 /* find the key first */
659 key = lookup_user_key(keyid, 0, 0, 0); 671 key = lookup_user_key(NULL, keyid, 0, 0, 0);
660 if (!IS_ERR(key)) { 672 if (!IS_ERR(key)) {
661 /* see if we can read it directly */ 673 /* see if we can read it directly */
662 if (key_permission(key, KEY_READ)) 674 if (key_permission(key, KEY_READ))
663 goto can_read_key; 675 goto can_read_key;
664 676
665 /* can't; see if it's searchable from this process's 677 /* we can't; see if it's searchable from this process's
666 * keyrings */ 678 * keyrings
667 ret = -ENOKEY; 679 * - we automatically take account of the fact that it may be
668 if (key_permission(key, KEY_SEARCH)) { 680 * dangling off an instantiation key
669 /* okay - we do have search permission on the key 681 */
670 * itself, but do we have the key? */ 682 skey = search_process_keyrings(key->type, key,
671 skey = search_process_keyrings_aux(key->type, key, 683 keyctl_read_key_same, current);
672 keyctl_read_key_same); 684 if (!IS_ERR(skey))
673 if (!IS_ERR(skey)) 685 goto can_read_key2;
674 goto can_read_key2; 686
675 } 687 ret = PTR_ERR(skey);
676
677 goto error2; 688 goto error2;
678 } 689 }
679 690
@@ -719,7 +730,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
719 if (uid == (uid_t) -1 && gid == (gid_t) -1) 730 if (uid == (uid_t) -1 && gid == (gid_t) -1)
720 goto error; 731 goto error;
721 732
722 key = lookup_user_key(id, 1, 1, 0); 733 key = lookup_user_key(NULL, id, 1, 1, 0);
723 if (IS_ERR(key)) { 734 if (IS_ERR(key)) {
724 ret = PTR_ERR(key); 735 ret = PTR_ERR(key);
725 goto error; 736 goto error;
@@ -728,7 +739,6 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
728 /* make the changes with the locks held to prevent chown/chown races */ 739 /* make the changes with the locks held to prevent chown/chown races */
729 ret = -EACCES; 740 ret = -EACCES;
730 down_write(&key->sem); 741 down_write(&key->sem);
731 write_lock(&key->lock);
732 742
733 if (!capable(CAP_SYS_ADMIN)) { 743 if (!capable(CAP_SYS_ADMIN)) {
734 /* only the sysadmin can chown a key to some other UID */ 744 /* only the sysadmin can chown a key to some other UID */
@@ -755,7 +765,6 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
755 ret = 0; 765 ret = 0;
756 766
757 no_access: 767 no_access:
758 write_unlock(&key->lock);
759 up_write(&key->sem); 768 up_write(&key->sem);
760 key_put(key); 769 key_put(key);
761 error: 770 error:
@@ -778,32 +787,25 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
778 if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) 787 if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
779 goto error; 788 goto error;
780 789
781 key = lookup_user_key(id, 1, 1, 0); 790 key = lookup_user_key(NULL, id, 1, 1, 0);
782 if (IS_ERR(key)) { 791 if (IS_ERR(key)) {
783 ret = PTR_ERR(key); 792 ret = PTR_ERR(key);
784 goto error; 793 goto error;
785 } 794 }
786 795
787 /* make the changes with the locks held to prevent chown/chmod 796 /* make the changes with the locks held to prevent chown/chmod races */
788 * races */
789 ret = -EACCES; 797 ret = -EACCES;
790 down_write(&key->sem); 798 down_write(&key->sem);
791 write_lock(&key->lock);
792 799
793 /* if we're not the sysadmin, we can only chmod a key that we 800 /* if we're not the sysadmin, we can only change a key that we own */
794 * own */ 801 if (capable(CAP_SYS_ADMIN) || key->uid == current->fsuid) {
795 if (!capable(CAP_SYS_ADMIN) && key->uid != current->fsuid) 802 key->perm = perm;
796 goto no_access; 803 ret = 0;
797 804 }
798 /* changing the permissions mask */
799 key->perm = perm;
800 ret = 0;
801 805
802 no_access:
803 write_unlock(&key->lock);
804 up_write(&key->sem); 806 up_write(&key->sem);
805 key_put(key); 807 key_put(key);
806 error: 808error:
807 return ret; 809 return ret;
808 810
809} /* end keyctl_setperm_key() */ 811} /* end keyctl_setperm_key() */
@@ -818,7 +820,8 @@ long keyctl_instantiate_key(key_serial_t id,
818 size_t plen, 820 size_t plen,
819 key_serial_t ringid) 821 key_serial_t ringid)
820{ 822{
821 struct key *key, *keyring; 823 struct request_key_auth *rka;
824 struct key *instkey, *keyring;
822 void *payload; 825 void *payload;
823 long ret; 826 long ret;
824 827
@@ -840,18 +843,21 @@ long keyctl_instantiate_key(key_serial_t id,
840 goto error2; 843 goto error2;
841 } 844 }
842 845
843 /* find the target key (which must be writable) */ 846 /* find the instantiation authorisation key */
844 key = lookup_user_key(id, 0, 1, KEY_WRITE); 847 instkey = key_get_instantiation_authkey(id);
845 if (IS_ERR(key)) { 848 if (IS_ERR(instkey)) {
846 ret = PTR_ERR(key); 849 ret = PTR_ERR(instkey);
847 goto error2; 850 goto error2;
848 } 851 }
849 852
850 /* find the destination keyring if present (which must also be 853 rka = instkey->payload.data;
851 * writable) */ 854
855 /* find the destination keyring amongst those belonging to the
856 * requesting task */
852 keyring = NULL; 857 keyring = NULL;
853 if (ringid) { 858 if (ringid) {
854 keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 859 keyring = lookup_user_key(rka->context, ringid, 1, 0,
860 KEY_WRITE);
855 if (IS_ERR(keyring)) { 861 if (IS_ERR(keyring)) {
856 ret = PTR_ERR(keyring); 862 ret = PTR_ERR(keyring);
857 goto error3; 863 goto error3;
@@ -859,11 +865,12 @@ long keyctl_instantiate_key(key_serial_t id,
859 } 865 }
860 866
861 /* instantiate the key and link it into a keyring */ 867 /* instantiate the key and link it into a keyring */
862 ret = key_instantiate_and_link(key, payload, plen, keyring); 868 ret = key_instantiate_and_link(rka->target_key, payload, plen,
869 keyring, instkey);
863 870
864 key_put(keyring); 871 key_put(keyring);
865 error3: 872 error3:
866 key_put(key); 873 key_put(instkey);
867 error2: 874 error2:
868 kfree(payload); 875 kfree(payload);
869 error: 876 error:
@@ -878,21 +885,24 @@ long keyctl_instantiate_key(key_serial_t id,
878 */ 885 */
879long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) 886long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
880{ 887{
881 struct key *key, *keyring; 888 struct request_key_auth *rka;
889 struct key *instkey, *keyring;
882 long ret; 890 long ret;
883 891
884 /* find the target key (which must be writable) */ 892 /* find the instantiation authorisation key */
885 key = lookup_user_key(id, 0, 1, KEY_WRITE); 893 instkey = key_get_instantiation_authkey(id);
886 if (IS_ERR(key)) { 894 if (IS_ERR(instkey)) {
887 ret = PTR_ERR(key); 895 ret = PTR_ERR(instkey);
888 goto error; 896 goto error;
889 } 897 }
890 898
899 rka = instkey->payload.data;
900
891 /* find the destination keyring if present (which must also be 901 /* find the destination keyring if present (which must also be
892 * writable) */ 902 * writable) */
893 keyring = NULL; 903 keyring = NULL;
894 if (ringid) { 904 if (ringid) {
895 keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 905 keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
896 if (IS_ERR(keyring)) { 906 if (IS_ERR(keyring)) {
897 ret = PTR_ERR(keyring); 907 ret = PTR_ERR(keyring);
898 goto error2; 908 goto error2;
@@ -900,11 +910,11 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
900 } 910 }
901 911
902 /* instantiate the key and link it into a keyring */ 912 /* instantiate the key and link it into a keyring */
903 ret = key_negate_and_link(key, timeout, keyring); 913 ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey);
904 914
905 key_put(keyring); 915 key_put(keyring);
906 error2: 916 error2:
907 key_put(key); 917 key_put(instkey);
908 error: 918 error:
909 return ret; 919 return ret;
910 920
@@ -912,6 +922,44 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
912 922
913/*****************************************************************************/ 923/*****************************************************************************/
914/* 924/*
925 * set the default keyring in which request_key() will cache keys
926 * - return the old setting
927 */
928long keyctl_set_reqkey_keyring(int reqkey_defl)
929{
930 int ret;
931
932 switch (reqkey_defl) {
933 case KEY_REQKEY_DEFL_THREAD_KEYRING:
934 ret = install_thread_keyring(current);
935 if (ret < 0)
936 return ret;
937 goto set;
938
939 case KEY_REQKEY_DEFL_PROCESS_KEYRING:
940 ret = install_process_keyring(current);
941 if (ret < 0)
942 return ret;
943
944 case KEY_REQKEY_DEFL_DEFAULT:
945 case KEY_REQKEY_DEFL_SESSION_KEYRING:
946 case KEY_REQKEY_DEFL_USER_KEYRING:
947 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
948 set:
949 current->jit_keyring = reqkey_defl;
950
951 case KEY_REQKEY_DEFL_NO_CHANGE:
952 return current->jit_keyring;
953
954 case KEY_REQKEY_DEFL_GROUP_KEYRING:
955 default:
956 return -EINVAL;
957 }
958
959} /* end keyctl_set_reqkey_keyring() */
960
961/*****************************************************************************/
962/*
915 * the key control system call 963 * the key control system call
916 */ 964 */
917asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, 965asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
@@ -980,6 +1028,9 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
980 (unsigned) arg3, 1028 (unsigned) arg3,
981 (key_serial_t) arg4); 1029 (key_serial_t) arg4);
982 1030
1031 case KEYCTL_SET_REQKEY_KEYRING:
1032 return keyctl_set_reqkey_keyring(arg2);
1033
983 default: 1034 default:
984 return -EOPNOTSUPP; 1035 return -EOPNOTSUPP;
985 } 1036 }
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index e2ab4f8e74..90a551e4da 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1,6 +1,6 @@
1/* keyring.c: keyring handling 1/* keyring.c: keyring handling
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -132,10 +132,17 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
132 (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key); 132 (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key);
133 133
134 ret = 0; 134 ret = 0;
135 sklist = source->payload.subscriptions;
136 135
137 if (sklist && sklist->nkeys > 0) { 136 /* find out how many keys are currently linked */
137 rcu_read_lock();
138 sklist = rcu_dereference(source->payload.subscriptions);
139 max = 0;
140 if (sklist)
138 max = sklist->nkeys; 141 max = sklist->nkeys;
142 rcu_read_unlock();
143
144 /* allocate a new payload and stuff load with key links */
145 if (max > 0) {
139 BUG_ON(max > limit); 146 BUG_ON(max > limit);
140 147
141 max = (max + 3) & ~3; 148 max = (max + 3) & ~3;
@@ -148,6 +155,10 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
148 if (!klist) 155 if (!klist)
149 goto error; 156 goto error;
150 157
158 /* set links */
159 rcu_read_lock();
160 sklist = rcu_dereference(source->payload.subscriptions);
161
151 klist->maxkeys = max; 162 klist->maxkeys = max;
152 klist->nkeys = sklist->nkeys; 163 klist->nkeys = sklist->nkeys;
153 memcpy(klist->keys, 164 memcpy(klist->keys,
@@ -157,7 +168,9 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
157 for (loop = klist->nkeys - 1; loop >= 0; loop--) 168 for (loop = klist->nkeys - 1; loop >= 0; loop--)
158 atomic_inc(&klist->keys[loop]->usage); 169 atomic_inc(&klist->keys[loop]->usage);
159 170
160 keyring->payload.subscriptions = klist; 171 rcu_read_unlock();
172
173 rcu_assign_pointer(keyring->payload.subscriptions, klist);
161 ret = 0; 174 ret = 0;
162 } 175 }
163 176
@@ -192,7 +205,7 @@ static void keyring_destroy(struct key *keyring)
192 write_unlock(&keyring_name_lock); 205 write_unlock(&keyring_name_lock);
193 } 206 }
194 207
195 klist = keyring->payload.subscriptions; 208 klist = rcu_dereference(keyring->payload.subscriptions);
196 if (klist) { 209 if (klist) {
197 for (loop = klist->nkeys - 1; loop >= 0; loop--) 210 for (loop = klist->nkeys - 1; loop >= 0; loop--)
198 key_put(klist->keys[loop]); 211 key_put(klist->keys[loop]);
@@ -216,17 +229,20 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m)
216 seq_puts(m, "[anon]"); 229 seq_puts(m, "[anon]");
217 } 230 }
218 231
219 klist = keyring->payload.subscriptions; 232 rcu_read_lock();
233 klist = rcu_dereference(keyring->payload.subscriptions);
220 if (klist) 234 if (klist)
221 seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); 235 seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
222 else 236 else
223 seq_puts(m, ": empty"); 237 seq_puts(m, ": empty");
238 rcu_read_unlock();
224 239
225} /* end keyring_describe() */ 240} /* end keyring_describe() */
226 241
227/*****************************************************************************/ 242/*****************************************************************************/
228/* 243/*
229 * read a list of key IDs from the keyring's contents 244 * read a list of key IDs from the keyring's contents
245 * - the keyring's semaphore is read-locked
230 */ 246 */
231static long keyring_read(const struct key *keyring, 247static long keyring_read(const struct key *keyring,
232 char __user *buffer, size_t buflen) 248 char __user *buffer, size_t buflen)
@@ -237,7 +253,7 @@ static long keyring_read(const struct key *keyring,
237 int loop, ret; 253 int loop, ret;
238 254
239 ret = 0; 255 ret = 0;
240 klist = keyring->payload.subscriptions; 256 klist = rcu_dereference(keyring->payload.subscriptions);
241 257
242 if (klist) { 258 if (klist) {
243 /* calculate how much data we could return */ 259 /* calculate how much data we could return */
@@ -292,7 +308,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
292 uid, gid, KEY_USR_ALL, not_in_quota); 308 uid, gid, KEY_USR_ALL, not_in_quota);
293 309
294 if (!IS_ERR(keyring)) { 310 if (!IS_ERR(keyring)) {
295 ret = key_instantiate_and_link(keyring, NULL, 0, dest); 311 ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
296 if (ret < 0) { 312 if (ret < 0) {
297 key_put(keyring); 313 key_put(keyring);
298 keyring = ERR_PTR(ret); 314 keyring = ERR_PTR(ret);
@@ -310,17 +326,18 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
310 * - we only find keys on which we have search permission 326 * - we only find keys on which we have search permission
311 * - we use the supplied match function to see if the description (or other 327 * - we use the supplied match function to see if the description (or other
312 * feature of interest) matches 328 * feature of interest) matches
313 * - we readlock the keyrings as we search down the tree 329 * - we rely on RCU to prevent the keyring lists from disappearing on us
314 * - we return -EAGAIN if we didn't find any matching key 330 * - we return -EAGAIN if we didn't find any matching key
315 * - we return -ENOKEY if we only found negative matching keys 331 * - we return -ENOKEY if we only found negative matching keys
316 */ 332 */
317struct key *keyring_search_aux(struct key *keyring, 333struct key *keyring_search_aux(struct key *keyring,
334 struct task_struct *context,
318 struct key_type *type, 335 struct key_type *type,
319 const void *description, 336 const void *description,
320 key_match_func_t match) 337 key_match_func_t match)
321{ 338{
322 struct { 339 struct {
323 struct key *keyring; 340 struct keyring_list *keylist;
324 int kix; 341 int kix;
325 } stack[KEYRING_SEARCH_MAX_DEPTH]; 342 } stack[KEYRING_SEARCH_MAX_DEPTH];
326 343
@@ -328,13 +345,15 @@ struct key *keyring_search_aux(struct key *keyring,
328 struct timespec now; 345 struct timespec now;
329 struct key *key; 346 struct key *key;
330 long err; 347 long err;
331 int sp, psp, kix; 348 int sp, kix;
332 349
333 key_check(keyring); 350 key_check(keyring);
334 351
352 rcu_read_lock();
353
335 /* top keyring must have search permission to begin the search */ 354 /* top keyring must have search permission to begin the search */
336 key = ERR_PTR(-EACCES); 355 key = ERR_PTR(-EACCES);
337 if (!key_permission(keyring, KEY_SEARCH)) 356 if (!key_task_permission(keyring, context, KEY_SEARCH))
338 goto error; 357 goto error;
339 358
340 key = ERR_PTR(-ENOTDIR); 359 key = ERR_PTR(-ENOTDIR);
@@ -347,11 +366,10 @@ struct key *keyring_search_aux(struct key *keyring,
347 366
348 /* start processing a new keyring */ 367 /* start processing a new keyring */
349 descend: 368 descend:
350 read_lock(&keyring->lock); 369 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
351 if (keyring->flags & KEY_FLAG_REVOKED)
352 goto not_this_keyring; 370 goto not_this_keyring;
353 371
354 keylist = keyring->payload.subscriptions; 372 keylist = rcu_dereference(keyring->payload.subscriptions);
355 if (!keylist) 373 if (!keylist)
356 goto not_this_keyring; 374 goto not_this_keyring;
357 375
@@ -364,7 +382,7 @@ struct key *keyring_search_aux(struct key *keyring,
364 continue; 382 continue;
365 383
366 /* skip revoked keys and expired keys */ 384 /* skip revoked keys and expired keys */
367 if (key->flags & KEY_FLAG_REVOKED) 385 if (test_bit(KEY_FLAG_REVOKED, &key->flags))
368 continue; 386 continue;
369 387
370 if (key->expiry && now.tv_sec >= key->expiry) 388 if (key->expiry && now.tv_sec >= key->expiry)
@@ -375,11 +393,11 @@ struct key *keyring_search_aux(struct key *keyring,
375 continue; 393 continue;
376 394
377 /* key must have search permissions */ 395 /* key must have search permissions */
378 if (!key_permission(key, KEY_SEARCH)) 396 if (!key_task_permission(key, context, KEY_SEARCH))
379 continue; 397 continue;
380 398
381 /* we set a different error code if we find a negative key */ 399 /* we set a different error code if we find a negative key */
382 if (key->flags & KEY_FLAG_NEGATIVE) { 400 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
383 err = -ENOKEY; 401 err = -ENOKEY;
384 continue; 402 continue;
385 } 403 }
@@ -390,48 +408,37 @@ struct key *keyring_search_aux(struct key *keyring,
390 /* search through the keyrings nested in this one */ 408 /* search through the keyrings nested in this one */
391 kix = 0; 409 kix = 0;
392 ascend: 410 ascend:
393 while (kix < keylist->nkeys) { 411 for (; kix < keylist->nkeys; kix++) {
394 key = keylist->keys[kix]; 412 key = keylist->keys[kix];
395 if (key->type != &key_type_keyring) 413 if (key->type != &key_type_keyring)
396 goto next; 414 continue;
397 415
398 /* recursively search nested keyrings 416 /* recursively search nested keyrings
399 * - only search keyrings for which we have search permission 417 * - only search keyrings for which we have search permission
400 */ 418 */
401 if (sp >= KEYRING_SEARCH_MAX_DEPTH) 419 if (sp >= KEYRING_SEARCH_MAX_DEPTH)
402 goto next; 420 continue;
403
404 if (!key_permission(key, KEY_SEARCH))
405 goto next;
406 421
407 /* evade loops in the keyring tree */ 422 if (!key_task_permission(key, context, KEY_SEARCH))
408 for (psp = 0; psp < sp; psp++) 423 continue;
409 if (stack[psp].keyring == keyring)
410 goto next;
411 424
412 /* stack the current position */ 425 /* stack the current position */
413 stack[sp].keyring = keyring; 426 stack[sp].keylist = keylist;
414 stack[sp].kix = kix; 427 stack[sp].kix = kix;
415 sp++; 428 sp++;
416 429
417 /* begin again with the new keyring */ 430 /* begin again with the new keyring */
418 keyring = key; 431 keyring = key;
419 goto descend; 432 goto descend;
420
421 next:
422 kix++;
423 } 433 }
424 434
425 /* the keyring we're looking at was disqualified or didn't contain a 435 /* the keyring we're looking at was disqualified or didn't contain a
426 * matching key */ 436 * matching key */
427 not_this_keyring: 437 not_this_keyring:
428 read_unlock(&keyring->lock);
429
430 if (sp > 0) { 438 if (sp > 0) {
431 /* resume the processing of a keyring higher up in the tree */ 439 /* resume the processing of a keyring higher up in the tree */
432 sp--; 440 sp--;
433 keyring = stack[sp].keyring; 441 keylist = stack[sp].keylist;
434 keylist = keyring->payload.subscriptions;
435 kix = stack[sp].kix + 1; 442 kix = stack[sp].kix + 1;
436 goto ascend; 443 goto ascend;
437 } 444 }
@@ -442,16 +449,9 @@ struct key *keyring_search_aux(struct key *keyring,
442 /* we found a viable match */ 449 /* we found a viable match */
443 found: 450 found:
444 atomic_inc(&key->usage); 451 atomic_inc(&key->usage);
445 read_unlock(&keyring->lock);
446
447 /* unwind the keyring stack */
448 while (sp > 0) {
449 sp--;
450 read_unlock(&stack[sp].keyring->lock);
451 }
452
453 key_check(key); 452 key_check(key);
454 error: 453 error:
454 rcu_read_unlock();
455 return key; 455 return key;
456 456
457} /* end keyring_search_aux() */ 457} /* end keyring_search_aux() */
@@ -469,7 +469,11 @@ struct key *keyring_search(struct key *keyring,
469 struct key_type *type, 469 struct key_type *type,
470 const char *description) 470 const char *description)
471{ 471{
472 return keyring_search_aux(keyring, type, description, type->match); 472 if (!type->match)
473 return ERR_PTR(-ENOKEY);
474
475 return keyring_search_aux(keyring, current,
476 type, description, type->match);
473 477
474} /* end keyring_search() */ 478} /* end keyring_search() */
475 479
@@ -489,15 +493,18 @@ struct key *__keyring_search_one(struct key *keyring,
489 struct key *key; 493 struct key *key;
490 int loop; 494 int loop;
491 495
492 klist = keyring->payload.subscriptions; 496 rcu_read_lock();
497
498 klist = rcu_dereference(keyring->payload.subscriptions);
493 if (klist) { 499 if (klist) {
494 for (loop = 0; loop < klist->nkeys; loop++) { 500 for (loop = 0; loop < klist->nkeys; loop++) {
495 key = klist->keys[loop]; 501 key = klist->keys[loop];
496 502
497 if (key->type == ktype && 503 if (key->type == ktype &&
498 key->type->match(key, description) && 504 (!key->type->match ||
505 key->type->match(key, description)) &&
499 key_permission(key, perm) && 506 key_permission(key, perm) &&
500 !(key->flags & KEY_FLAG_REVOKED) 507 !test_bit(KEY_FLAG_REVOKED, &key->flags)
501 ) 508 )
502 goto found; 509 goto found;
503 } 510 }
@@ -509,12 +516,58 @@ struct key *__keyring_search_one(struct key *keyring,
509 found: 516 found:
510 atomic_inc(&key->usage); 517 atomic_inc(&key->usage);
511 error: 518 error:
519 rcu_read_unlock();
512 return key; 520 return key;
513 521
514} /* end __keyring_search_one() */ 522} /* end __keyring_search_one() */
515 523
516/*****************************************************************************/ 524/*****************************************************************************/
517/* 525/*
526 * search for an instantiation authorisation key matching a target key
527 * - the RCU read lock must be held by the caller
528 * - a target_id of zero specifies any valid token
529 */
530struct key *keyring_search_instkey(struct key *keyring,
531 key_serial_t target_id)
532{
533 struct request_key_auth *rka;
534 struct keyring_list *klist;
535 struct key *instkey;
536 int loop;
537
538 klist = rcu_dereference(keyring->payload.subscriptions);
539 if (klist) {
540 for (loop = 0; loop < klist->nkeys; loop++) {
541 instkey = klist->keys[loop];
542
543 if (instkey->type != &key_type_request_key_auth)
544 continue;
545
546 rka = instkey->payload.data;
547 if (target_id && rka->target_key->serial != target_id)
548 continue;
549
550 /* the auth key is revoked during instantiation */
551 if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags))
552 goto found;
553
554 instkey = ERR_PTR(-EKEYREVOKED);
555 goto error;
556 }
557 }
558
559 instkey = ERR_PTR(-EACCES);
560 goto error;
561
562found:
563 atomic_inc(&instkey->usage);
564error:
565 return instkey;
566
567} /* end keyring_search_instkey() */
568
569/*****************************************************************************/
570/*
518 * find a keyring with the specified name 571 * find a keyring with the specified name
519 * - all named keyrings are searched 572 * - all named keyrings are searched
520 * - only find keyrings with search permission for the process 573 * - only find keyrings with search permission for the process
@@ -540,7 +593,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
540 &keyring_name_hash[bucket], 593 &keyring_name_hash[bucket],
541 type_data.link 594 type_data.link
542 ) { 595 ) {
543 if (keyring->flags & KEY_FLAG_REVOKED) 596 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
544 continue; 597 continue;
545 598
546 if (strcmp(keyring->description, name) != 0) 599 if (strcmp(keyring->description, name) != 0)
@@ -579,7 +632,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
579static int keyring_detect_cycle(struct key *A, struct key *B) 632static int keyring_detect_cycle(struct key *A, struct key *B)
580{ 633{
581 struct { 634 struct {
582 struct key *subtree; 635 struct keyring_list *keylist;
583 int kix; 636 int kix;
584 } stack[KEYRING_SEARCH_MAX_DEPTH]; 637 } stack[KEYRING_SEARCH_MAX_DEPTH];
585 638
@@ -587,20 +640,21 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
587 struct key *subtree, *key; 640 struct key *subtree, *key;
588 int sp, kix, ret; 641 int sp, kix, ret;
589 642
643 rcu_read_lock();
644
590 ret = -EDEADLK; 645 ret = -EDEADLK;
591 if (A == B) 646 if (A == B)
592 goto error; 647 goto cycle_detected;
593 648
594 subtree = B; 649 subtree = B;
595 sp = 0; 650 sp = 0;
596 651
597 /* start processing a new keyring */ 652 /* start processing a new keyring */
598 descend: 653 descend:
599 read_lock(&subtree->lock); 654 if (test_bit(KEY_FLAG_REVOKED, &subtree->flags))
600 if (subtree->flags & KEY_FLAG_REVOKED)
601 goto not_this_keyring; 655 goto not_this_keyring;
602 656
603 keylist = subtree->payload.subscriptions; 657 keylist = rcu_dereference(subtree->payload.subscriptions);
604 if (!keylist) 658 if (!keylist)
605 goto not_this_keyring; 659 goto not_this_keyring;
606 kix = 0; 660 kix = 0;
@@ -619,7 +673,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
619 goto too_deep; 673 goto too_deep;
620 674
621 /* stack the current position */ 675 /* stack the current position */
622 stack[sp].subtree = subtree; 676 stack[sp].keylist = keylist;
623 stack[sp].kix = kix; 677 stack[sp].kix = kix;
624 sp++; 678 sp++;
625 679
@@ -632,13 +686,10 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
632 /* the keyring we're looking at was disqualified or didn't contain a 686 /* the keyring we're looking at was disqualified or didn't contain a
633 * matching key */ 687 * matching key */
634 not_this_keyring: 688 not_this_keyring:
635 read_unlock(&subtree->lock);
636
637 if (sp > 0) { 689 if (sp > 0) {
638 /* resume the checking of a keyring higher up in the tree */ 690 /* resume the checking of a keyring higher up in the tree */
639 sp--; 691 sp--;
640 subtree = stack[sp].subtree; 692 keylist = stack[sp].keylist;
641 keylist = subtree->payload.subscriptions;
642 kix = stack[sp].kix + 1; 693 kix = stack[sp].kix + 1;
643 goto ascend; 694 goto ascend;
644 } 695 }
@@ -646,30 +697,36 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
646 ret = 0; /* no cycles detected */ 697 ret = 0; /* no cycles detected */
647 698
648 error: 699 error:
700 rcu_read_unlock();
649 return ret; 701 return ret;
650 702
651 too_deep: 703 too_deep:
652 ret = -ELOOP; 704 ret = -ELOOP;
653 goto error_unwind; 705 goto error;
706
654 cycle_detected: 707 cycle_detected:
655 ret = -EDEADLK; 708 ret = -EDEADLK;
656 error_unwind:
657 read_unlock(&subtree->lock);
658
659 /* unwind the keyring stack */
660 while (sp > 0) {
661 sp--;
662 read_unlock(&stack[sp].subtree->lock);
663 }
664
665 goto error; 709 goto error;
666 710
667} /* end keyring_detect_cycle() */ 711} /* end keyring_detect_cycle() */
668 712
669/*****************************************************************************/ 713/*****************************************************************************/
670/* 714/*
715 * dispose of a keyring list after the RCU grace period
716 */
717static void keyring_link_rcu_disposal(struct rcu_head *rcu)
718{
719 struct keyring_list *klist =
720 container_of(rcu, struct keyring_list, rcu);
721
722 kfree(klist);
723
724} /* end keyring_link_rcu_disposal() */
725
726/*****************************************************************************/
727/*
671 * link a key into to a keyring 728 * link a key into to a keyring
672 * - must be called with the keyring's semaphore held 729 * - must be called with the keyring's semaphore write-locked
673 */ 730 */
674int __key_link(struct key *keyring, struct key *key) 731int __key_link(struct key *keyring, struct key *key)
675{ 732{
@@ -679,7 +736,7 @@ int __key_link(struct key *keyring, struct key *key)
679 int ret; 736 int ret;
680 737
681 ret = -EKEYREVOKED; 738 ret = -EKEYREVOKED;
682 if (keyring->flags & KEY_FLAG_REVOKED) 739 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
683 goto error; 740 goto error;
684 741
685 ret = -ENOTDIR; 742 ret = -ENOTDIR;
@@ -710,9 +767,10 @@ int __key_link(struct key *keyring, struct key *key)
710 /* there's sufficient slack space to add directly */ 767 /* there's sufficient slack space to add directly */
711 atomic_inc(&key->usage); 768 atomic_inc(&key->usage);
712 769
713 write_lock(&keyring->lock); 770 klist->keys[klist->nkeys] = key;
714 klist->keys[klist->nkeys++] = key; 771 smp_wmb();
715 write_unlock(&keyring->lock); 772 klist->nkeys++;
773 smp_wmb();
716 774
717 ret = 0; 775 ret = 0;
718 } 776 }
@@ -723,6 +781,8 @@ int __key_link(struct key *keyring, struct key *key)
723 max += klist->maxkeys; 781 max += klist->maxkeys;
724 782
725 ret = -ENFILE; 783 ret = -ENFILE;
784 if (max > 65535)
785 goto error3;
726 size = sizeof(*klist) + sizeof(*key) * max; 786 size = sizeof(*klist) + sizeof(*key) * max;
727 if (size > PAGE_SIZE) 787 if (size > PAGE_SIZE)
728 goto error3; 788 goto error3;
@@ -743,14 +803,13 @@ int __key_link(struct key *keyring, struct key *key)
743 803
744 /* add the key into the new space */ 804 /* add the key into the new space */
745 atomic_inc(&key->usage); 805 atomic_inc(&key->usage);
746
747 write_lock(&keyring->lock);
748 keyring->payload.subscriptions = nklist;
749 nklist->keys[nklist->nkeys++] = key; 806 nklist->keys[nklist->nkeys++] = key;
750 write_unlock(&keyring->lock); 807
808 rcu_assign_pointer(keyring->payload.subscriptions, nklist);
751 809
752 /* dispose of the old keyring list */ 810 /* dispose of the old keyring list */
753 kfree(klist); 811 if (klist)
812 call_rcu(&klist->rcu, keyring_link_rcu_disposal);
754 813
755 ret = 0; 814 ret = 0;
756 } 815 }
@@ -791,11 +850,26 @@ EXPORT_SYMBOL(key_link);
791 850
792/*****************************************************************************/ 851/*****************************************************************************/
793/* 852/*
853 * dispose of a keyring list after the RCU grace period, freeing the unlinked
854 * key
855 */
856static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
857{
858 struct keyring_list *klist =
859 container_of(rcu, struct keyring_list, rcu);
860
861 key_put(klist->keys[klist->delkey]);
862 kfree(klist);
863
864} /* end keyring_unlink_rcu_disposal() */
865
866/*****************************************************************************/
867/*
794 * unlink the first link to a key from a keyring 868 * unlink the first link to a key from a keyring
795 */ 869 */
796int key_unlink(struct key *keyring, struct key *key) 870int key_unlink(struct key *keyring, struct key *key)
797{ 871{
798 struct keyring_list *klist; 872 struct keyring_list *klist, *nklist;
799 int loop, ret; 873 int loop, ret;
800 874
801 key_check(keyring); 875 key_check(keyring);
@@ -819,31 +893,45 @@ int key_unlink(struct key *keyring, struct key *key)
819 ret = -ENOENT; 893 ret = -ENOENT;
820 goto error; 894 goto error;
821 895
822 key_is_present: 896key_is_present:
897 /* we need to copy the key list for RCU purposes */
898 nklist = kmalloc(sizeof(*klist) + sizeof(*key) * klist->maxkeys,
899 GFP_KERNEL);
900 if (!nklist)
901 goto nomem;
902 nklist->maxkeys = klist->maxkeys;
903 nklist->nkeys = klist->nkeys - 1;
904
905 if (loop > 0)
906 memcpy(&nklist->keys[0],
907 &klist->keys[0],
908 loop * sizeof(klist->keys[0]));
909
910 if (loop < nklist->nkeys)
911 memcpy(&nklist->keys[loop],
912 &klist->keys[loop + 1],
913 (nklist->nkeys - loop) * sizeof(klist->keys[0]));
914
823 /* adjust the user's quota */ 915 /* adjust the user's quota */
824 key_payload_reserve(keyring, 916 key_payload_reserve(keyring,
825 keyring->datalen - KEYQUOTA_LINK_BYTES); 917 keyring->datalen - KEYQUOTA_LINK_BYTES);
826 918
827 /* shuffle down the key pointers 919 rcu_assign_pointer(keyring->payload.subscriptions, nklist);
828 * - it might be worth shrinking the allocated memory, but that runs
829 * the risk of ENOMEM as we would have to copy
830 */
831 write_lock(&keyring->lock);
832 920
833 klist->nkeys--; 921 up_write(&keyring->sem);
834 if (loop < klist->nkeys)
835 memcpy(&klist->keys[loop],
836 &klist->keys[loop + 1],
837 (klist->nkeys - loop) * sizeof(struct key *));
838 922
839 write_unlock(&keyring->lock); 923 /* schedule for later cleanup */
924 klist->delkey = loop;
925 call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);
840 926
841 up_write(&keyring->sem);
842 key_put(key);
843 ret = 0; 927 ret = 0;
844 928
845 error: 929error:
846 return ret; 930 return ret;
931nomem:
932 ret = -ENOMEM;
933 up_write(&keyring->sem);
934 goto error;
847 935
848} /* end key_unlink() */ 936} /* end key_unlink() */
849 937
@@ -851,13 +939,32 @@ EXPORT_SYMBOL(key_unlink);
851 939
852/*****************************************************************************/ 940/*****************************************************************************/
853/* 941/*
942 * dispose of a keyring list after the RCU grace period, releasing the keys it
943 * links to
944 */
945static void keyring_clear_rcu_disposal(struct rcu_head *rcu)
946{
947 struct keyring_list *klist;
948 int loop;
949
950 klist = container_of(rcu, struct keyring_list, rcu);
951
952 for (loop = klist->nkeys - 1; loop >= 0; loop--)
953 key_put(klist->keys[loop]);
954
955 kfree(klist);
956
957} /* end keyring_clear_rcu_disposal() */
958
959/*****************************************************************************/
960/*
854 * clear the specified process keyring 961 * clear the specified process keyring
855 * - implements keyctl(KEYCTL_CLEAR) 962 * - implements keyctl(KEYCTL_CLEAR)
856 */ 963 */
857int keyring_clear(struct key *keyring) 964int keyring_clear(struct key *keyring)
858{ 965{
859 struct keyring_list *klist; 966 struct keyring_list *klist;
860 int loop, ret; 967 int ret;
861 968
862 ret = -ENOTDIR; 969 ret = -ENOTDIR;
863 if (keyring->type == &key_type_keyring) { 970 if (keyring->type == &key_type_keyring) {
@@ -870,20 +977,15 @@ int keyring_clear(struct key *keyring)
870 key_payload_reserve(keyring, 977 key_payload_reserve(keyring,
871 sizeof(struct keyring_list)); 978 sizeof(struct keyring_list));
872 979
873 write_lock(&keyring->lock); 980 rcu_assign_pointer(keyring->payload.subscriptions,
874 keyring->payload.subscriptions = NULL; 981 NULL);
875 write_unlock(&keyring->lock);
876 } 982 }
877 983
878 up_write(&keyring->sem); 984 up_write(&keyring->sem);
879 985
880 /* free the keys after the locks have been dropped */ 986 /* free the keys after the locks have been dropped */
881 if (klist) { 987 if (klist)
882 for (loop = klist->nkeys - 1; loop >= 0; loop--) 988 call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
883 key_put(klist->keys[loop]);
884
885 kfree(klist);
886 }
887 989
888 ret = 0; 990 ret = 0;
889 } 991 }
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 91343b85c3..c55cf1fd08 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -140,7 +140,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
140 140
141 now = current_kernel_time(); 141 now = current_kernel_time();
142 142
143 read_lock(&key->lock); 143 rcu_read_lock();
144 144
145 /* come up with a suitable timeout value */ 145 /* come up with a suitable timeout value */
146 if (key->expiry == 0) { 146 if (key->expiry == 0) {
@@ -164,14 +164,17 @@ static int proc_keys_show(struct seq_file *m, void *v)
164 sprintf(xbuf, "%luw", timo / (60*60*24*7)); 164 sprintf(xbuf, "%luw", timo / (60*60*24*7));
165 } 165 }
166 166
167#define showflag(KEY, LETTER, FLAG) \
168 (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-')
169
167 seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ", 170 seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ",
168 key->serial, 171 key->serial,
169 key->flags & KEY_FLAG_INSTANTIATED ? 'I' : '-', 172 showflag(key, 'I', KEY_FLAG_INSTANTIATED),
170 key->flags & KEY_FLAG_REVOKED ? 'R' : '-', 173 showflag(key, 'R', KEY_FLAG_REVOKED),
171 key->flags & KEY_FLAG_DEAD ? 'D' : '-', 174 showflag(key, 'D', KEY_FLAG_DEAD),
172 key->flags & KEY_FLAG_IN_QUOTA ? 'Q' : '-', 175 showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
173 key->flags & KEY_FLAG_USER_CONSTRUCT ? 'U' : '-', 176 showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
174 key->flags & KEY_FLAG_NEGATIVE ? 'N' : '-', 177 showflag(key, 'N', KEY_FLAG_NEGATIVE),
175 atomic_read(&key->usage), 178 atomic_read(&key->usage),
176 xbuf, 179 xbuf,
177 key->perm, 180 key->perm,
@@ -179,11 +182,13 @@ static int proc_keys_show(struct seq_file *m, void *v)
179 key->gid, 182 key->gid,
180 key->type->name); 183 key->type->name);
181 184
185#undef showflag
186
182 if (key->type->describe) 187 if (key->type->describe)
183 key->type->describe(key, m); 188 key->type->describe(key, m);
184 seq_putc(m, '\n'); 189 seq_putc(m, '\n');
185 190
186 read_unlock(&key->lock); 191 rcu_read_unlock();
187 192
188 return 0; 193 return 0;
189 194
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 2eb0e471cd..34db087bbc 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -1,6 +1,6 @@
1/* process_keys.c: management of a process's keyrings 1/* process_keys.c: management of a process's keyrings
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -38,10 +38,9 @@ struct key root_user_keyring = {
38 .serial = 2, 38 .serial = 2,
39 .type = &key_type_keyring, 39 .type = &key_type_keyring,
40 .user = &root_key_user, 40 .user = &root_key_user,
41 .lock = RW_LOCK_UNLOCKED,
42 .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), 41 .sem = __RWSEM_INITIALIZER(root_user_keyring.sem),
43 .perm = KEY_USR_ALL, 42 .perm = KEY_USR_ALL,
44 .flags = KEY_FLAG_INSTANTIATED, 43 .flags = 1 << KEY_FLAG_INSTANTIATED,
45 .description = "_uid.0", 44 .description = "_uid.0",
46#ifdef KEY_DEBUGGING 45#ifdef KEY_DEBUGGING
47 .magic = KEY_DEBUG_MAGIC, 46 .magic = KEY_DEBUG_MAGIC,
@@ -54,10 +53,9 @@ struct key root_session_keyring = {
54 .serial = 1, 53 .serial = 1,
55 .type = &key_type_keyring, 54 .type = &key_type_keyring,
56 .user = &root_key_user, 55 .user = &root_key_user,
57 .lock = RW_LOCK_UNLOCKED,
58 .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), 56 .sem = __RWSEM_INITIALIZER(root_session_keyring.sem),
59 .perm = KEY_USR_ALL, 57 .perm = KEY_USR_ALL,
60 .flags = KEY_FLAG_INSTANTIATED, 58 .flags = 1 << KEY_FLAG_INSTANTIATED,
61 .description = "_uid_ses.0", 59 .description = "_uid_ses.0",
62#ifdef KEY_DEBUGGING 60#ifdef KEY_DEBUGGING
63 .magic = KEY_DEBUG_MAGIC, 61 .magic = KEY_DEBUG_MAGIC,
@@ -167,7 +165,7 @@ int install_thread_keyring(struct task_struct *tsk)
167/* 165/*
168 * make sure a process keyring is installed 166 * make sure a process keyring is installed
169 */ 167 */
170static int install_process_keyring(struct task_struct *tsk) 168int install_process_keyring(struct task_struct *tsk)
171{ 169{
172 unsigned long flags; 170 unsigned long flags;
173 struct key *keyring; 171 struct key *keyring;
@@ -183,7 +181,7 @@ static int install_process_keyring(struct task_struct *tsk)
183 goto error; 181 goto error;
184 } 182 }
185 183
186 /* attach or swap keyrings */ 184 /* attach keyring */
187 spin_lock_irqsave(&tsk->sighand->siglock, flags); 185 spin_lock_irqsave(&tsk->sighand->siglock, flags);
188 if (!tsk->signal->process_keyring) { 186 if (!tsk->signal->process_keyring) {
189 tsk->signal->process_keyring = keyring; 187 tsk->signal->process_keyring = keyring;
@@ -229,12 +227,14 @@ static int install_session_keyring(struct task_struct *tsk,
229 227
230 /* install the keyring */ 228 /* install the keyring */
231 spin_lock_irqsave(&tsk->sighand->siglock, flags); 229 spin_lock_irqsave(&tsk->sighand->siglock, flags);
232 old = tsk->signal->session_keyring; 230 old = rcu_dereference(tsk->signal->session_keyring);
233 tsk->signal->session_keyring = keyring; 231 rcu_assign_pointer(tsk->signal->session_keyring, keyring);
234 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 232 spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
235 233
236 ret = 0; 234 ret = 0;
237 235
236 /* we're using RCU on the pointer */
237 synchronize_kernel();
238 key_put(old); 238 key_put(old);
239 error: 239 error:
240 return ret; 240 return ret;
@@ -247,8 +247,6 @@ static int install_session_keyring(struct task_struct *tsk,
247 */ 247 */
248int copy_thread_group_keys(struct task_struct *tsk) 248int copy_thread_group_keys(struct task_struct *tsk)
249{ 249{
250 unsigned long flags;
251
252 key_check(current->thread_group->session_keyring); 250 key_check(current->thread_group->session_keyring);
253 key_check(current->thread_group->process_keyring); 251 key_check(current->thread_group->process_keyring);
254 252
@@ -256,10 +254,10 @@ int copy_thread_group_keys(struct task_struct *tsk)
256 tsk->signal->process_keyring = NULL; 254 tsk->signal->process_keyring = NULL;
257 255
258 /* same session keyring */ 256 /* same session keyring */
259 spin_lock_irqsave(&current->sighand->siglock, flags); 257 rcu_read_lock();
260 tsk->signal->session_keyring = 258 tsk->signal->session_keyring =
261 key_get(current->signal->session_keyring); 259 key_get(rcu_dereference(current->signal->session_keyring));
262 spin_unlock_irqrestore(&current->sighand->siglock, flags); 260 rcu_read_unlock();
263 261
264 return 0; 262 return 0;
265 263
@@ -349,9 +347,7 @@ void key_fsuid_changed(struct task_struct *tsk)
349 /* update the ownership of the thread keyring */ 347 /* update the ownership of the thread keyring */
350 if (tsk->thread_keyring) { 348 if (tsk->thread_keyring) {
351 down_write(&tsk->thread_keyring->sem); 349 down_write(&tsk->thread_keyring->sem);
352 write_lock(&tsk->thread_keyring->lock);
353 tsk->thread_keyring->uid = tsk->fsuid; 350 tsk->thread_keyring->uid = tsk->fsuid;
354 write_unlock(&tsk->thread_keyring->lock);
355 up_write(&tsk->thread_keyring->sem); 351 up_write(&tsk->thread_keyring->sem);
356 } 352 }
357 353
@@ -366,9 +362,7 @@ void key_fsgid_changed(struct task_struct *tsk)
366 /* update the ownership of the thread keyring */ 362 /* update the ownership of the thread keyring */
367 if (tsk->thread_keyring) { 363 if (tsk->thread_keyring) {
368 down_write(&tsk->thread_keyring->sem); 364 down_write(&tsk->thread_keyring->sem);
369 write_lock(&tsk->thread_keyring->lock);
370 tsk->thread_keyring->gid = tsk->fsgid; 365 tsk->thread_keyring->gid = tsk->fsgid;
371 write_unlock(&tsk->thread_keyring->lock);
372 up_write(&tsk->thread_keyring->sem); 366 up_write(&tsk->thread_keyring->sem);
373 } 367 }
374 368
@@ -382,13 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk)
382 * - we return -EAGAIN if we didn't find any matching key 376 * - we return -EAGAIN if we didn't find any matching key
383 * - we return -ENOKEY if we found only negative matching keys 377 * - we return -ENOKEY if we found only negative matching keys
384 */ 378 */
385struct key *search_process_keyrings_aux(struct key_type *type, 379struct key *search_process_keyrings(struct key_type *type,
386 const void *description, 380 const void *description,
387 key_match_func_t match) 381 key_match_func_t match,
382 struct task_struct *context)
388{ 383{
389 struct task_struct *tsk = current; 384 struct request_key_auth *rka;
390 unsigned long flags; 385 struct key *key, *ret, *err, *instkey;
391 struct key *key, *ret, *err, *tmp;
392 386
393 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 387 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
394 * searchable, but we failed to find a key or we found a negative key; 388 * searchable, but we failed to find a key or we found a negative key;
@@ -402,9 +396,9 @@ struct key *search_process_keyrings_aux(struct key_type *type,
402 err = ERR_PTR(-EAGAIN); 396 err = ERR_PTR(-EAGAIN);
403 397
404 /* search the thread keyring first */ 398 /* search the thread keyring first */
405 if (tsk->thread_keyring) { 399 if (context->thread_keyring) {
406 key = keyring_search_aux(tsk->thread_keyring, type, 400 key = keyring_search_aux(context->thread_keyring,
407 description, match); 401 context, type, description, match);
408 if (!IS_ERR(key)) 402 if (!IS_ERR(key))
409 goto found; 403 goto found;
410 404
@@ -422,9 +416,9 @@ struct key *search_process_keyrings_aux(struct key_type *type,
422 } 416 }
423 417
424 /* search the process keyring second */ 418 /* search the process keyring second */
425 if (tsk->signal->process_keyring) { 419 if (context->signal->process_keyring) {
426 key = keyring_search_aux(tsk->signal->process_keyring, 420 key = keyring_search_aux(context->signal->process_keyring,
427 type, description, match); 421 context, type, description, match);
428 if (!IS_ERR(key)) 422 if (!IS_ERR(key))
429 goto found; 423 goto found;
430 424
@@ -441,52 +435,93 @@ struct key *search_process_keyrings_aux(struct key_type *type,
441 } 435 }
442 } 436 }
443 437
444 /* search the session keyring last */ 438 /* search the session keyring */
445 spin_lock_irqsave(&tsk->sighand->siglock, flags); 439 if (context->signal->session_keyring) {
440 rcu_read_lock();
441 key = keyring_search_aux(
442 rcu_dereference(context->signal->session_keyring),
443 context, type, description, match);
444 rcu_read_unlock();
446 445
447 tmp = tsk->signal->session_keyring; 446 if (!IS_ERR(key))
448 if (!tmp) 447 goto found;
449 tmp = tsk->user->session_keyring;
450 atomic_inc(&tmp->usage);
451 448
452 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 449 switch (PTR_ERR(key)) {
450 case -EAGAIN: /* no key */
451 if (ret)
452 break;
453 case -ENOKEY: /* negative key */
454 ret = key;
455 break;
456 default:
457 err = key;
458 break;
459 }
460
461 /* if this process has a session keyring and that has an
462 * instantiation authorisation key in the bottom level, then we
463 * also search the keyrings of the process mentioned there */
464 if (context != current)
465 goto no_key;
466
467 rcu_read_lock();
468 instkey = __keyring_search_one(
469 rcu_dereference(context->signal->session_keyring),
470 &key_type_request_key_auth, NULL, 0);
471 rcu_read_unlock();
472
473 if (IS_ERR(instkey))
474 goto no_key;
475
476 rka = instkey->payload.data;
453 477
454 key = keyring_search_aux(tmp, type, description, match); 478 key = search_process_keyrings(type, description, match,
455 key_put(tmp); 479 rka->context);
456 if (!IS_ERR(key)) 480 key_put(instkey);
457 goto found;
458 481
459 switch (PTR_ERR(key)) { 482 if (!IS_ERR(key))
460 case -EAGAIN: /* no key */ 483 goto found;
461 if (ret) 484
485 switch (PTR_ERR(key)) {
486 case -EAGAIN: /* no key */
487 if (ret)
488 break;
489 case -ENOKEY: /* negative key */
490 ret = key;
462 break; 491 break;
463 case -ENOKEY: /* negative key */ 492 default:
464 ret = key; 493 err = key;
465 break; 494 break;
466 default: 495 }
467 err = key; 496 }
468 break; 497 /* or search the user-session keyring */
498 else {
499 key = keyring_search_aux(context->user->session_keyring,
500 context, type, description, match);
501 if (!IS_ERR(key))
502 goto found;
503
504 switch (PTR_ERR(key)) {
505 case -EAGAIN: /* no key */
506 if (ret)
507 break;
508 case -ENOKEY: /* negative key */
509 ret = key;
510 break;
511 default:
512 err = key;
513 break;
514 }
469 } 515 }
470 516
517
518no_key:
471 /* no key - decide on the error we're going to go for */ 519 /* no key - decide on the error we're going to go for */
472 key = ret ? ret : err; 520 key = ret ? ret : err;
473 521
474 found: 522found:
475 return key; 523 return key;
476 524
477} /* end search_process_keyrings_aux() */
478
479/*****************************************************************************/
480/*
481 * search the process keyrings for the first matching key
482 * - we return -EAGAIN if we didn't find any matching key
483 * - we return -ENOKEY if we found only negative matching keys
484 */
485struct key *search_process_keyrings(struct key_type *type,
486 const char *description)
487{
488 return search_process_keyrings_aux(type, description, type->match);
489
490} /* end search_process_keyrings() */ 525} /* end search_process_keyrings() */
491 526
492/*****************************************************************************/ 527/*****************************************************************************/
@@ -495,72 +530,73 @@ struct key *search_process_keyrings(struct key_type *type,
495 * - don't create special keyrings unless so requested 530 * - don't create special keyrings unless so requested
496 * - partially constructed keys aren't found unless requested 531 * - partially constructed keys aren't found unless requested
497 */ 532 */
498struct key *lookup_user_key(key_serial_t id, int create, int partial, 533struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
499 key_perm_t perm) 534 int create, int partial, key_perm_t perm)
500{ 535{
501 struct task_struct *tsk = current;
502 unsigned long flags;
503 struct key *key; 536 struct key *key;
504 int ret; 537 int ret;
505 538
539 if (!context)
540 context = current;
541
506 key = ERR_PTR(-ENOKEY); 542 key = ERR_PTR(-ENOKEY);
507 543
508 switch (id) { 544 switch (id) {
509 case KEY_SPEC_THREAD_KEYRING: 545 case KEY_SPEC_THREAD_KEYRING:
510 if (!tsk->thread_keyring) { 546 if (!context->thread_keyring) {
511 if (!create) 547 if (!create)
512 goto error; 548 goto error;
513 549
514 ret = install_thread_keyring(tsk); 550 ret = install_thread_keyring(context);
515 if (ret < 0) { 551 if (ret < 0) {
516 key = ERR_PTR(ret); 552 key = ERR_PTR(ret);
517 goto error; 553 goto error;
518 } 554 }
519 } 555 }
520 556
521 key = tsk->thread_keyring; 557 key = context->thread_keyring;
522 atomic_inc(&key->usage); 558 atomic_inc(&key->usage);
523 break; 559 break;
524 560
525 case KEY_SPEC_PROCESS_KEYRING: 561 case KEY_SPEC_PROCESS_KEYRING:
526 if (!tsk->signal->process_keyring) { 562 if (!context->signal->process_keyring) {
527 if (!create) 563 if (!create)
528 goto error; 564 goto error;
529 565
530 ret = install_process_keyring(tsk); 566 ret = install_process_keyring(context);
531 if (ret < 0) { 567 if (ret < 0) {
532 key = ERR_PTR(ret); 568 key = ERR_PTR(ret);
533 goto error; 569 goto error;
534 } 570 }
535 } 571 }
536 572
537 key = tsk->signal->process_keyring; 573 key = context->signal->process_keyring;
538 atomic_inc(&key->usage); 574 atomic_inc(&key->usage);
539 break; 575 break;
540 576
541 case KEY_SPEC_SESSION_KEYRING: 577 case KEY_SPEC_SESSION_KEYRING:
542 if (!tsk->signal->session_keyring) { 578 if (!context->signal->session_keyring) {
543 /* always install a session keyring upon access if one 579 /* always install a session keyring upon access if one
544 * doesn't exist yet */ 580 * doesn't exist yet */
545 ret = install_session_keyring( 581 ret = install_session_keyring(
546 tsk, tsk->user->session_keyring); 582 context, context->user->session_keyring);
547 if (ret < 0) 583 if (ret < 0)
548 goto error; 584 goto error;
549 } 585 }
550 586
551 spin_lock_irqsave(&tsk->sighand->siglock, flags); 587 rcu_read_lock();
552 key = tsk->signal->session_keyring; 588 key = rcu_dereference(context->signal->session_keyring);
553 atomic_inc(&key->usage); 589 atomic_inc(&key->usage);
554 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 590 rcu_read_unlock();
555 break; 591 break;
556 592
557 case KEY_SPEC_USER_KEYRING: 593 case KEY_SPEC_USER_KEYRING:
558 key = tsk->user->uid_keyring; 594 key = context->user->uid_keyring;
559 atomic_inc(&key->usage); 595 atomic_inc(&key->usage);
560 break; 596 break;
561 597
562 case KEY_SPEC_USER_SESSION_KEYRING: 598 case KEY_SPEC_USER_SESSION_KEYRING:
563 key = tsk->user->session_keyring; 599 key = context->user->session_keyring;
564 atomic_inc(&key->usage); 600 atomic_inc(&key->usage);
565 break; 601 break;
566 602
@@ -580,7 +616,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
580 break; 616 break;
581 } 617 }
582 618
583 /* check the status and permissions */ 619 /* check the status */
584 if (perm) { 620 if (perm) {
585 ret = key_validate(key); 621 ret = key_validate(key);
586 if (ret < 0) 622 if (ret < 0)
@@ -588,11 +624,13 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
588 } 624 }
589 625
590 ret = -EIO; 626 ret = -EIO;
591 if (!partial && !(key->flags & KEY_FLAG_INSTANTIATED)) 627 if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
592 goto invalid_key; 628 goto invalid_key;
593 629
630 /* check the permissions */
594 ret = -EACCES; 631 ret = -EACCES;
595 if (!key_permission(key, perm)) 632
633 if (!key_task_permission(key, context, perm))
596 goto invalid_key; 634 goto invalid_key;
597 635
598 error: 636 error:
@@ -615,7 +653,6 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
615long join_session_keyring(const char *name) 653long join_session_keyring(const char *name)
616{ 654{
617 struct task_struct *tsk = current; 655 struct task_struct *tsk = current;
618 unsigned long flags;
619 struct key *keyring; 656 struct key *keyring;
620 long ret; 657 long ret;
621 658
@@ -625,9 +662,9 @@ long join_session_keyring(const char *name)
625 if (ret < 0) 662 if (ret < 0)
626 goto error; 663 goto error;
627 664
628 spin_lock_irqsave(&tsk->sighand->siglock, flags); 665 rcu_read_lock();
629 ret = tsk->signal->session_keyring->serial; 666 ret = rcu_dereference(tsk->signal->session_keyring)->serial;
630 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 667 rcu_read_unlock();
631 goto error; 668 goto error;
632 } 669 }
633 670
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 9705b1aeba..dfcd983af1 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -1,6 +1,6 @@
1/* request_key.c: request a key from userspace 1/* request_key.c: request a key from userspace
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -13,6 +13,7 @@
13#include <linux/sched.h> 13#include <linux/sched.h>
14#include <linux/kmod.h> 14#include <linux/kmod.h>
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/keyctl.h>
16#include "internal.h" 17#include "internal.h"
17 18
18struct key_construction { 19struct key_construction {
@@ -27,18 +28,26 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq);
27/* 28/*
28 * request userspace finish the construction of a key 29 * request userspace finish the construction of a key
29 * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>" 30 * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>"
30 * - if callout_info is an empty string, it'll be rendered as a "-" instead
31 */ 31 */
32static int call_request_key(struct key *key, 32static int call_request_key(struct key *key,
33 const char *op, 33 const char *op,
34 const char *callout_info) 34 const char *callout_info)
35{ 35{
36 struct task_struct *tsk = current; 36 struct task_struct *tsk = current;
37 unsigned long flags;
38 key_serial_t prkey, sskey; 37 key_serial_t prkey, sskey;
38 struct key *session_keyring, *rkakey;
39 char *argv[10], *envp[3], uid_str[12], gid_str[12]; 39 char *argv[10], *envp[3], uid_str[12], gid_str[12];
40 char key_str[12], keyring_str[3][12]; 40 char key_str[12], keyring_str[3][12];
41 int i; 41 int ret, i;
42
43 kenter("{%d},%s,%s", key->serial, op, callout_info);
44
45 /* generate a new session keyring with an auth key in it */
46 session_keyring = request_key_auth_new(key, &rkakey);
47 if (IS_ERR(session_keyring)) {
48 ret = PTR_ERR(session_keyring);
49 goto error;
50 }
42 51
43 /* record the UID and GID */ 52 /* record the UID and GID */
44 sprintf(uid_str, "%d", current->fsuid); 53 sprintf(uid_str, "%d", current->fsuid);
@@ -55,17 +64,17 @@ static int call_request_key(struct key *key,
55 if (tsk->signal->process_keyring) 64 if (tsk->signal->process_keyring)
56 prkey = tsk->signal->process_keyring->serial; 65 prkey = tsk->signal->process_keyring->serial;
57 66
58 sskey = 0; 67 sprintf(keyring_str[1], "%d", prkey);
59 spin_lock_irqsave(&tsk->sighand->siglock, flags);
60 if (tsk->signal->session_keyring)
61 sskey = tsk->signal->session_keyring->serial;
62 spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
63
64 68
65 if (!sskey) 69 if (tsk->signal->session_keyring) {
70 rcu_read_lock();
71 sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
72 rcu_read_unlock();
73 }
74 else {
66 sskey = tsk->user->session_keyring->serial; 75 sskey = tsk->user->session_keyring->serial;
76 }
67 77
68 sprintf(keyring_str[1], "%d", prkey);
69 sprintf(keyring_str[2], "%d", sskey); 78 sprintf(keyring_str[2], "%d", sskey);
70 79
71 /* set up a minimal environment */ 80 /* set up a minimal environment */
@@ -84,11 +93,20 @@ static int call_request_key(struct key *key,
84 argv[i++] = keyring_str[0]; 93 argv[i++] = keyring_str[0];
85 argv[i++] = keyring_str[1]; 94 argv[i++] = keyring_str[1];
86 argv[i++] = keyring_str[2]; 95 argv[i++] = keyring_str[2];
87 argv[i++] = callout_info[0] ? (char *) callout_info : "-"; 96 argv[i++] = (char *) callout_info;
88 argv[i] = NULL; 97 argv[i] = NULL;
89 98
90 /* do it */ 99 /* do it */
91 return call_usermodehelper(argv[0], argv, envp, 1); 100 ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1);
101
102 /* dispose of the special keys */
103 key_revoke(rkakey);
104 key_put(rkakey);
105 key_put(session_keyring);
106
107 error:
108 kleave(" = %d", ret);
109 return ret;
92 110
93} /* end call_request_key() */ 111} /* end call_request_key() */
94 112
@@ -105,7 +123,9 @@ static struct key *__request_key_construction(struct key_type *type,
105 struct key_construction cons; 123 struct key_construction cons;
106 struct timespec now; 124 struct timespec now;
107 struct key *key; 125 struct key *key;
108 int ret, negative; 126 int ret, negated;
127
128 kenter("%s,%s,%s", type->name, description, callout_info);
109 129
110 /* create a key and add it to the queue */ 130 /* create a key and add it to the queue */
111 key = key_alloc(type, description, 131 key = key_alloc(type, description,
@@ -113,9 +133,7 @@ static struct key *__request_key_construction(struct key_type *type,
113 if (IS_ERR(key)) 133 if (IS_ERR(key))
114 goto alloc_failed; 134 goto alloc_failed;
115 135
116 write_lock(&key->lock); 136 set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
117 key->flags |= KEY_FLAG_USER_CONSTRUCT;
118 write_unlock(&key->lock);
119 137
120 cons.key = key; 138 cons.key = key;
121 list_add_tail(&cons.link, &key->user->consq); 139 list_add_tail(&cons.link, &key->user->consq);
@@ -130,7 +148,7 @@ static struct key *__request_key_construction(struct key_type *type,
130 148
131 /* if the key wasn't instantiated, then we want to give an error */ 149 /* if the key wasn't instantiated, then we want to give an error */
132 ret = -ENOKEY; 150 ret = -ENOKEY;
133 if (!(key->flags & KEY_FLAG_INSTANTIATED)) 151 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
134 goto request_failed; 152 goto request_failed;
135 153
136 down_write(&key_construction_sem); 154 down_write(&key_construction_sem);
@@ -139,12 +157,13 @@ static struct key *__request_key_construction(struct key_type *type,
139 157
140 /* also give an error if the key was negatively instantiated */ 158 /* also give an error if the key was negatively instantiated */
141 check_not_negative: 159 check_not_negative:
142 if (key->flags & KEY_FLAG_NEGATIVE) { 160 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
143 key_put(key); 161 key_put(key);
144 key = ERR_PTR(-ENOKEY); 162 key = ERR_PTR(-ENOKEY);
145 } 163 }
146 164
147 out: 165 out:
166 kleave(" = %p", key);
148 return key; 167 return key;
149 168
150 request_failed: 169 request_failed:
@@ -152,24 +171,23 @@ static struct key *__request_key_construction(struct key_type *type,
152 * - remove from construction queue 171 * - remove from construction queue
153 * - mark the key as dead 172 * - mark the key as dead
154 */ 173 */
155 negative = 0; 174 negated = 0;
156 down_write(&key_construction_sem); 175 down_write(&key_construction_sem);
157 176
158 list_del(&cons.link); 177 list_del(&cons.link);
159 178
160 write_lock(&key->lock);
161 key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
162
163 /* check it didn't get instantiated between the check and the down */ 179 /* check it didn't get instantiated between the check and the down */
164 if (!(key->flags & KEY_FLAG_INSTANTIATED)) { 180 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
165 key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE; 181 set_bit(KEY_FLAG_NEGATIVE, &key->flags);
166 negative = 1; 182 set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
183 negated = 1;
167 } 184 }
168 185
169 write_unlock(&key->lock); 186 clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
187
170 up_write(&key_construction_sem); 188 up_write(&key_construction_sem);
171 189
172 if (!negative) 190 if (!negated)
173 goto check_not_negative; /* surprisingly, the key got 191 goto check_not_negative; /* surprisingly, the key got
174 * instantiated */ 192 * instantiated */
175 193
@@ -178,13 +196,12 @@ static struct key *__request_key_construction(struct key_type *type,
178 key->expiry = now.tv_sec + key_negative_timeout; 196 key->expiry = now.tv_sec + key_negative_timeout;
179 197
180 if (current->signal->session_keyring) { 198 if (current->signal->session_keyring) {
181 unsigned long flags;
182 struct key *keyring; 199 struct key *keyring;
183 200
184 spin_lock_irqsave(&current->sighand->siglock, flags); 201 rcu_read_lock();
185 keyring = current->signal->session_keyring; 202 keyring = rcu_dereference(current->signal->session_keyring);
186 atomic_inc(&keyring->usage); 203 atomic_inc(&keyring->usage);
187 spin_unlock_irqrestore(&current->sighand->siglock, flags); 204 rcu_read_unlock();
188 205
189 key_link(keyring, key); 206 key_link(keyring, key);
190 key_put(keyring); 207 key_put(keyring);
@@ -220,6 +237,9 @@ static struct key *request_key_construction(struct key_type *type,
220 237
221 DECLARE_WAITQUEUE(myself, current); 238 DECLARE_WAITQUEUE(myself, current);
222 239
240 kenter("%s,%s,{%d},%s",
241 type->name, description, user->uid, callout_info);
242
223 /* see if there's such a key under construction already */ 243 /* see if there's such a key under construction already */
224 down_write(&key_construction_sem); 244 down_write(&key_construction_sem);
225 245
@@ -236,6 +256,7 @@ static struct key *request_key_construction(struct key_type *type,
236 /* see about getting userspace to construct the key */ 256 /* see about getting userspace to construct the key */
237 key = __request_key_construction(type, description, callout_info); 257 key = __request_key_construction(type, description, callout_info);
238 error: 258 error:
259 kleave(" = %p", key);
239 return key; 260 return key;
240 261
241 /* someone else has the same key under construction 262 /* someone else has the same key under construction
@@ -249,8 +270,10 @@ static struct key *request_key_construction(struct key_type *type,
249 add_wait_queue(&request_key_conswq, &myself); 270 add_wait_queue(&request_key_conswq, &myself);
250 271
251 for (;;) { 272 for (;;) {
252 set_current_state(TASK_UNINTERRUPTIBLE); 273 set_current_state(TASK_INTERRUPTIBLE);
253 if (!(ckey->flags & KEY_FLAG_USER_CONSTRUCT)) 274 if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags))
275 break;
276 if (signal_pending(current))
254 break; 277 break;
255 schedule(); 278 schedule();
256 } 279 }
@@ -271,21 +294,83 @@ static struct key *request_key_construction(struct key_type *type,
271 294
272/*****************************************************************************/ 295/*****************************************************************************/
273/* 296/*
297 * link a freshly minted key to an appropriate destination keyring
298 */
299static void request_key_link(struct key *key, struct key *dest_keyring)
300{
301 struct task_struct *tsk = current;
302 struct key *drop = NULL;
303
304 kenter("{%d},%p", key->serial, dest_keyring);
305
306 /* find the appropriate keyring */
307 if (!dest_keyring) {
308 switch (tsk->jit_keyring) {
309 case KEY_REQKEY_DEFL_DEFAULT:
310 case KEY_REQKEY_DEFL_THREAD_KEYRING:
311 dest_keyring = tsk->thread_keyring;
312 if (dest_keyring)
313 break;
314
315 case KEY_REQKEY_DEFL_PROCESS_KEYRING:
316 dest_keyring = tsk->signal->process_keyring;
317 if (dest_keyring)
318 break;
319
320 case KEY_REQKEY_DEFL_SESSION_KEYRING:
321 rcu_read_lock();
322 dest_keyring = key_get(
323 rcu_dereference(tsk->signal->session_keyring));
324 rcu_read_unlock();
325 drop = dest_keyring;
326
327 if (dest_keyring)
328 break;
329
330 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
331 dest_keyring = current->user->session_keyring;
332 break;
333
334 case KEY_REQKEY_DEFL_USER_KEYRING:
335 dest_keyring = current->user->uid_keyring;
336 break;
337
338 case KEY_REQKEY_DEFL_GROUP_KEYRING:
339 default:
340 BUG();
341 }
342 }
343
344 /* and attach the key to it */
345 key_link(dest_keyring, key);
346
347 key_put(drop);
348
349 kleave("");
350
351} /* end request_key_link() */
352
353/*****************************************************************************/
354/*
274 * request a key 355 * request a key
275 * - search the process's keyrings 356 * - search the process's keyrings
276 * - check the list of keys being created or updated 357 * - check the list of keys being created or updated
277 * - call out to userspace for a key if requested (supplementary info can be 358 * - call out to userspace for a key if supplementary info was provided
278 * passed) 359 * - cache the key in an appropriate keyring
279 */ 360 */
280struct key *request_key(struct key_type *type, 361struct key *request_key_and_link(struct key_type *type,
281 const char *description, 362 const char *description,
282 const char *callout_info) 363 const char *callout_info,
364 struct key *dest_keyring)
283{ 365{
284 struct key_user *user; 366 struct key_user *user;
285 struct key *key; 367 struct key *key;
286 368
369 kenter("%s,%s,%s,%p",
370 type->name, description, callout_info, dest_keyring);
371
287 /* search all the process keyrings for a key */ 372 /* search all the process keyrings for a key */
288 key = search_process_keyrings_aux(type, description, type->match); 373 key = search_process_keyrings(type, description, type->match, current);
289 374
290 if (PTR_ERR(key) == -EAGAIN) { 375 if (PTR_ERR(key) == -EAGAIN) {
291 /* the search failed, but the keyrings were searchable, so we 376 /* the search failed, but the keyrings were searchable, so we
@@ -296,12 +381,13 @@ struct key *request_key(struct key_type *type,
296 381
297 /* - get hold of the user's construction queue */ 382 /* - get hold of the user's construction queue */
298 user = key_user_lookup(current->fsuid); 383 user = key_user_lookup(current->fsuid);
299 if (!user) { 384 if (!user)
300 key = ERR_PTR(-ENOMEM); 385 goto nomem;
301 goto error; 386
302 } 387 do {
388 if (signal_pending(current))
389 goto interrupted;
303 390
304 for (;;) {
305 /* ask userspace (returns NULL if it waited on a key 391 /* ask userspace (returns NULL if it waited on a key
306 * being constructed) */ 392 * being constructed) */
307 key = request_key_construction(type, description, 393 key = request_key_construction(type, description,
@@ -311,18 +397,46 @@ struct key *request_key(struct key_type *type,
311 397
312 /* someone else made the key we want, so we need to 398 /* someone else made the key we want, so we need to
313 * search again as it might now be available to us */ 399 * search again as it might now be available to us */
314 key = search_process_keyrings_aux(type, description, 400 key = search_process_keyrings(type, description,
315 type->match); 401 type->match, current);
316 if (PTR_ERR(key) != -EAGAIN) 402
317 break; 403 } while (PTR_ERR(key) == -EAGAIN);
318 }
319 404
320 key_user_put(user); 405 key_user_put(user);
406
407 /* link the new key into the appropriate keyring */
408 if (!PTR_ERR(key))
409 request_key_link(key, dest_keyring);
321 } 410 }
322 411
323 error: 412error:
413 kleave(" = %p", key);
324 return key; 414 return key;
325 415
416nomem:
417 key = ERR_PTR(-ENOMEM);
418 goto error;
419
420interrupted:
421 key_user_put(user);
422 key = ERR_PTR(-EINTR);
423 goto error;
424
425} /* end request_key_and_link() */
426
427/*****************************************************************************/
428/*
429 * request a key
430 * - search the process's keyrings
431 * - check the list of keys being created or updated
432 * - call out to userspace for a key if supplementary info was provided
433 */
434struct key *request_key(struct key_type *type,
435 const char *description,
436 const char *callout_info)
437{
438 return request_key_and_link(type, description, callout_info, NULL);
439
326} /* end request_key() */ 440} /* end request_key() */
327 441
328EXPORT_SYMBOL(request_key); 442EXPORT_SYMBOL(request_key);
@@ -339,7 +453,8 @@ int key_validate(struct key *key)
339 if (key) { 453 if (key) {
340 /* check it's still accessible */ 454 /* check it's still accessible */
341 ret = -EKEYREVOKED; 455 ret = -EKEYREVOKED;
342 if (key->flags & (KEY_FLAG_REVOKED | KEY_FLAG_DEAD)) 456 if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
457 test_bit(KEY_FLAG_DEAD, &key->flags))
343 goto error; 458 goto error;
344 459
345 /* check it hasn't expired */ 460 /* check it hasn't expired */
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
new file mode 100644
index 0000000000..f222646322
--- /dev/null
+++ b/security/keys/request_key_auth.c
@@ -0,0 +1,180 @@
1/* request_key_auth.c: request key authorisation controlling key def
2 *
3 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/sched.h>
14#include <linux/err.h>
15#include <linux/seq_file.h>
16#include "internal.h"
17
18static int request_key_auth_instantiate(struct key *, const void *, size_t);
19static void request_key_auth_describe(const struct key *, struct seq_file *);
20static void request_key_auth_destroy(struct key *);
21
22/*
23 * the request-key authorisation key type definition
24 */
25struct key_type key_type_request_key_auth = {
26 .name = ".request_key_auth",
27 .def_datalen = sizeof(struct request_key_auth),
28 .instantiate = request_key_auth_instantiate,
29 .describe = request_key_auth_describe,
30 .destroy = request_key_auth_destroy,
31};
32
33/*****************************************************************************/
34/*
35 * instantiate a request-key authorisation record
36 */
37static int request_key_auth_instantiate(struct key *key,
38 const void *data,
39 size_t datalen)
40{
41 struct request_key_auth *rka, *irka;
42 struct key *instkey;
43 int ret;
44
45 ret = -ENOMEM;
46 rka = kmalloc(sizeof(*rka), GFP_KERNEL);
47 if (rka) {
48 /* see if the calling process is already servicing the key
49 * request of another process */
50 instkey = key_get_instantiation_authkey(0);
51 if (!IS_ERR(instkey)) {
52 /* it is - use that instantiation context here too */
53 irka = instkey->payload.data;
54 rka->context = irka->context;
55 rka->pid = irka->pid;
56 key_put(instkey);
57 }
58 else {
59 /* it isn't - use this process as the context */
60 rka->context = current;
61 rka->pid = current->pid;
62 }
63
64 rka->target_key = key_get((struct key *) data);
65 key->payload.data = rka;
66 ret = 0;
67 }
68
69 return ret;
70
71} /* end request_key_auth_instantiate() */
72
73/*****************************************************************************/
74/*
75 *
76 */
77static void request_key_auth_describe(const struct key *key,
78 struct seq_file *m)
79{
80 struct request_key_auth *rka = key->payload.data;
81
82 seq_puts(m, "key:");
83 seq_puts(m, key->description);
84 seq_printf(m, " pid:%d", rka->pid);
85
86} /* end request_key_auth_describe() */
87
88/*****************************************************************************/
89/*
90 * destroy an instantiation authorisation token key
91 */
92static void request_key_auth_destroy(struct key *key)
93{
94 struct request_key_auth *rka = key->payload.data;
95
96 kenter("{%d}", key->serial);
97
98 key_put(rka->target_key);
99
100} /* end request_key_auth_destroy() */
101
102/*****************************************************************************/
103/*
104 * create a session keyring to be for the invokation of /sbin/request-key and
105 * stick an authorisation token in it
106 */
107struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
108{
109 struct key *keyring, *rkakey = NULL;
110 char desc[20];
111 int ret;
112
113 kenter("%d,", target->serial);
114
115 /* allocate a new session keyring */
116 sprintf(desc, "_req.%u", target->serial);
117
118 keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
119 if (IS_ERR(keyring)) {
120 kleave("= %ld", PTR_ERR(keyring));
121 return keyring;
122 }
123
124 /* allocate the auth key */
125 sprintf(desc, "%x", target->serial);
126
127 rkakey = key_alloc(&key_type_request_key_auth, desc,
128 current->fsuid, current->fsgid,
129 KEY_USR_VIEW, 1);
130 if (IS_ERR(rkakey)) {
131 key_put(keyring);
132 kleave("= %ld", PTR_ERR(rkakey));
133 return rkakey;
134 }
135
136 /* construct and attach to the keyring */
137 ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL);
138 if (ret < 0) {
139 key_revoke(rkakey);
140 key_put(rkakey);
141 key_put(keyring);
142 kleave("= %d", ret);
143 return ERR_PTR(ret);
144 }
145
146 *_rkakey = rkakey;
147 kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial);
148 return keyring;
149
150} /* end request_key_auth_new() */
151
152/*****************************************************************************/
153/*
154 * get the authorisation key for instantiation of a specific key if attached to
155 * the current process's keyrings
156 * - this key is inserted into a keyring and that is set as /sbin/request-key's
157 * session keyring
158 * - a target_id of zero specifies any valid token
159 */
160struct key *key_get_instantiation_authkey(key_serial_t target_id)
161{
162 struct task_struct *tsk = current;
163 struct key *instkey;
164
165 /* we must have our own personal session keyring */
166 if (!tsk->signal->session_keyring)
167 return ERR_PTR(-EACCES);
168
169 /* and it must contain a suitable request authorisation key
170 * - lock RCU against session keyring changing
171 */
172 rcu_read_lock();
173
174 instkey = keyring_search_instkey(
175 rcu_dereference(tsk->signal->session_keyring), target_id);
176
177 rcu_read_unlock();
178 return instkey;
179
180} /* end key_get_instantiation_authkey() */
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 8d65b3a281..e446acba73 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -42,12 +42,21 @@ struct key_type key_type_user = {
42 .read = user_read, 42 .read = user_read,
43}; 43};
44 44
45struct user_key_payload {
46 struct rcu_head rcu; /* RCU destructor */
47 unsigned short datalen; /* length of this data */
48 char data[0]; /* actual data */
49};
50
51EXPORT_SYMBOL_GPL(key_type_user);
52
45/*****************************************************************************/ 53/*****************************************************************************/
46/* 54/*
47 * instantiate a user defined key 55 * instantiate a user defined key
48 */ 56 */
49static int user_instantiate(struct key *key, const void *data, size_t datalen) 57static int user_instantiate(struct key *key, const void *data, size_t datalen)
50{ 58{
59 struct user_key_payload *upayload;
51 int ret; 60 int ret;
52 61
53 ret = -EINVAL; 62 ret = -EINVAL;
@@ -58,13 +67,15 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen)
58 if (ret < 0) 67 if (ret < 0)
59 goto error; 68 goto error;
60 69
61 /* attach the data */
62 ret = -ENOMEM; 70 ret = -ENOMEM;
63 key->payload.data = kmalloc(datalen, GFP_KERNEL); 71 upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
64 if (!key->payload.data) 72 if (!upayload)
65 goto error; 73 goto error;
66 74
67 memcpy(key->payload.data, data, datalen); 75 /* attach the data */
76 upayload->datalen = datalen;
77 memcpy(upayload->data, data, datalen);
78 rcu_assign_pointer(key->payload.data, upayload);
68 ret = 0; 79 ret = 0;
69 80
70 error: 81 error:
@@ -75,18 +86,25 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen)
75/*****************************************************************************/ 86/*****************************************************************************/
76/* 87/*
77 * duplicate a user defined key 88 * duplicate a user defined key
89 * - both keys' semaphores are locked against further modification
90 * - the new key cannot yet be accessed
78 */ 91 */
79static int user_duplicate(struct key *key, const struct key *source) 92static int user_duplicate(struct key *key, const struct key *source)
80{ 93{
94 struct user_key_payload *upayload, *spayload;
81 int ret; 95 int ret;
82 96
83 /* just copy the payload */ 97 /* just copy the payload */
84 ret = -ENOMEM; 98 ret = -ENOMEM;
85 key->payload.data = kmalloc(source->datalen, GFP_KERNEL); 99 upayload = kmalloc(sizeof(*upayload) + source->datalen, GFP_KERNEL);
100 if (upayload) {
101 spayload = rcu_dereference(source->payload.data);
102 BUG_ON(source->datalen != spayload->datalen);
103
104 upayload->datalen = key->datalen = spayload->datalen;
105 memcpy(upayload->data, spayload->data, key->datalen);
86 106
87 if (key->payload.data) { 107 key->payload.data = upayload;
88 key->datalen = source->datalen;
89 memcpy(key->payload.data, source->payload.data, source->datalen);
90 ret = 0; 108 ret = 0;
91 } 109 }
92 110
@@ -96,40 +114,54 @@ static int user_duplicate(struct key *key, const struct key *source)
96 114
97/*****************************************************************************/ 115/*****************************************************************************/
98/* 116/*
117 * dispose of the old data from an updated user defined key
118 */
119static void user_update_rcu_disposal(struct rcu_head *rcu)
120{
121 struct user_key_payload *upayload;
122
123 upayload = container_of(rcu, struct user_key_payload, rcu);
124
125 kfree(upayload);
126
127} /* end user_update_rcu_disposal() */
128
129/*****************************************************************************/
130/*
99 * update a user defined key 131 * update a user defined key
132 * - the key's semaphore is write-locked
100 */ 133 */
101static int user_update(struct key *key, const void *data, size_t datalen) 134static int user_update(struct key *key, const void *data, size_t datalen)
102{ 135{
103 void *new, *zap; 136 struct user_key_payload *upayload, *zap;
104 int ret; 137 int ret;
105 138
106 ret = -EINVAL; 139 ret = -EINVAL;
107 if (datalen <= 0 || datalen > 32767 || !data) 140 if (datalen <= 0 || datalen > 32767 || !data)
108 goto error; 141 goto error;
109 142
110 /* copy the data */ 143 /* construct a replacement payload */
111 ret = -ENOMEM; 144 ret = -ENOMEM;
112 new = kmalloc(datalen, GFP_KERNEL); 145 upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
113 if (!new) 146 if (!upayload)
114 goto error; 147 goto error;
115 148
116 memcpy(new, data, datalen); 149 upayload->datalen = datalen;
150 memcpy(upayload->data, data, datalen);
117 151
118 /* check the quota and attach the new data */ 152 /* check the quota and attach the new data */
119 zap = new; 153 zap = upayload;
120 write_lock(&key->lock);
121 154
122 ret = key_payload_reserve(key, datalen); 155 ret = key_payload_reserve(key, datalen);
123 156
124 if (ret == 0) { 157 if (ret == 0) {
125 /* attach the new data, displacing the old */ 158 /* attach the new data, displacing the old */
126 zap = key->payload.data; 159 zap = key->payload.data;
127 key->payload.data = new; 160 rcu_assign_pointer(key->payload.data, upayload);
128 key->expiry = 0; 161 key->expiry = 0;
129 } 162 }
130 163
131 write_unlock(&key->lock); 164 call_rcu(&zap->rcu, user_update_rcu_disposal);
132 kfree(zap);
133 165
134 error: 166 error:
135 return ret; 167 return ret;
@@ -152,13 +184,15 @@ static int user_match(const struct key *key, const void *description)
152 */ 184 */
153static void user_destroy(struct key *key) 185static void user_destroy(struct key *key)
154{ 186{
155 kfree(key->payload.data); 187 struct user_key_payload *upayload = key->payload.data;
188
189 kfree(upayload);
156 190
157} /* end user_destroy() */ 191} /* end user_destroy() */
158 192
159/*****************************************************************************/ 193/*****************************************************************************/
160/* 194/*
161 * describe the user 195 * describe the user key
162 */ 196 */
163static void user_describe(const struct key *key, struct seq_file *m) 197static void user_describe(const struct key *key, struct seq_file *m)
164{ 198{
@@ -171,18 +205,23 @@ static void user_describe(const struct key *key, struct seq_file *m)
171/*****************************************************************************/ 205/*****************************************************************************/
172/* 206/*
173 * read the key data 207 * read the key data
208 * - the key's semaphore is read-locked
174 */ 209 */
175static long user_read(const struct key *key, 210static long user_read(const struct key *key,
176 char __user *buffer, size_t buflen) 211 char __user *buffer, size_t buflen)
177{ 212{
178 long ret = key->datalen; 213 struct user_key_payload *upayload;
214 long ret;
215
216 upayload = rcu_dereference(key->payload.data);
217 ret = upayload->datalen;
179 218
180 /* we can return the data as is */ 219 /* we can return the data as is */
181 if (buffer && buflen > 0) { 220 if (buffer && buflen > 0) {
182 if (buflen > key->datalen) 221 if (buflen > upayload->datalen)
183 buflen = key->datalen; 222 buflen = upayload->datalen;
184 223
185 if (copy_to_user(buffer, key->payload.data, buflen) != 0) 224 if (copy_to_user(buffer, upayload->data, buflen) != 0)
186 ret = -EFAULT; 225 ret = -EFAULT;
187 } 226 }
188 227