aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavem <davem>2002-01-08 16:00:03 +0000
committerdavem <davem>2002-01-08 16:00:03 +0000
commit1b0fcd5b56be7bece7dbdfdafb3adf5dba5ddd08 (patch)
tree26ef016fd2ec3fcf4854a5e10da0482bf7a20fde
parent9aa1683bcf3738584a2d68ca333b1001da5fef51 (diff)
downloadnetdev-vger-cvs-1b0fcd5b56be7bece7dbdfdafb3adf5dba5ddd08.tar.gz
Merge mainline to 2.5.2-pre9
-rw-r--r--Documentation/Configure.help115
-rw-r--r--Documentation/filesystems/devfs/ChangeLog69
-rw-r--r--Documentation/filesystems/devfs/README100
-rw-r--r--Documentation/filesystems/devfs/rc.devfs104
-rw-r--r--Documentation/usb/ehci.txt164
-rw-r--r--Documentation/usb/ov511.txt302
-rw-r--r--Documentation/usb/stv680.txt55
-rw-r--r--Documentation/usb/usb-serial.txt86
-rw-r--r--MAINTAINERS8
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c5
-rw-r--r--arch/alpha/kernel/pci-noop.c9
-rw-r--r--arch/alpha/kernel/pci_iommu.c42
-rw-r--r--arch/alpha/kernel/process.c1
-rw-r--r--arch/alpha/kernel/setup.c7
-rw-r--r--arch/alpha/lib/dec_and_lock.c1
-rw-r--r--arch/arm/Makefile66
-rw-r--r--arch/arm/boot/Makefile16
-rw-r--r--arch/arm/boot/compressed/Makefile10
-rw-r--r--arch/arm/boot/compressed/head-shark.S2
-rw-r--r--arch/arm/boot/compressed/head-xscale.S66
-rw-r--r--arch/arm/boot/compressed/head.S21
-rw-r--r--arch/arm/boot/compressed/ofw-shark.c2
-rw-r--r--arch/arm/config.in131
-rw-r--r--arch/arm/def-configs/adi_evb681
-rw-r--r--arch/arm/def-configs/flexanet357
-rw-r--r--arch/arm/def-configs/iq80310812
-rw-r--r--arch/arm/def-configs/shannon737
-rw-r--r--arch/arm/def-configs/system3977
-rw-r--r--arch/arm/kernel/Makefile57
-rw-r--r--arch/arm/kernel/arch.c133
-rw-r--r--arch/arm/kernel/armksyms.c32
-rw-r--r--arch/arm/kernel/bios32.c255
-rw-r--r--arch/arm/kernel/compat.c10
-rw-r--r--arch/arm/kernel/dma-isa.c2
-rw-r--r--arch/arm/kernel/dma.c4
-rw-r--r--arch/arm/kernel/entry-armo.S2
-rw-r--r--arch/arm/kernel/entry-armv.S70
-rw-r--r--arch/arm/kernel/entry-common.S2
-rw-r--r--arch/arm/kernel/entry-header.S6
-rw-r--r--arch/arm/kernel/fiq.c4
-rw-r--r--arch/arm/kernel/init_task.c1
-rw-r--r--arch/arm/kernel/irq.c2
-rw-r--r--arch/arm/kernel/process.c9
-rw-r--r--arch/arm/kernel/semaphore.c10
-rw-r--r--arch/arm/kernel/setup.c206
-rw-r--r--arch/arm/kernel/signal.c6
-rw-r--r--arch/arm/kernel/time.c48
-rw-r--r--arch/arm/kernel/traps.c40
-rw-r--r--arch/arm/lib/Makefile6
-rw-r--r--arch/arm/lib/changebit.S4
-rw-r--r--arch/arm/lib/clearbit.S5
-rw-r--r--arch/arm/lib/copy_page-armv3.S59
-rw-r--r--arch/arm/lib/copy_page-armv4.S70
-rw-r--r--arch/arm/lib/copy_page-armv4mc.S71
-rw-r--r--arch/arm/lib/copy_page-armv5te.S79
-rw-r--r--arch/arm/lib/delay.S22
-rw-r--r--arch/arm/lib/findbit.S40
-rw-r--r--arch/arm/lib/getuser.S11
-rw-r--r--arch/arm/lib/io-shark.c2
-rw-r--r--arch/arm/lib/memcpy.S122
-rw-r--r--arch/arm/lib/putuser.S7
-rw-r--r--arch/arm/lib/setbit.S15
-rw-r--r--arch/arm/lib/testchangebit.S4
-rw-r--r--arch/arm/lib/testclearbit.S4
-rw-r--r--arch/arm/lib/testsetbit.S4
-rw-r--r--arch/arm/lib/uaccess.S224
-rw-r--r--arch/arm/mach-adifcc/Makefile21
-rw-r--r--arch/arm/mach-adifcc/arch.c49
-rw-r--r--arch/arm/mach-adifcc/irq.c66
-rw-r--r--arch/arm/mach-adifcc/mm.c24
-rw-r--r--arch/arm/mach-arc/Makefile28
-rw-r--r--arch/arm/mach-arc/arch.c39
-rw-r--r--arch/arm/mach-arc/debug.S (renamed from arch/arm/kernel/debug-armo.S)0
-rw-r--r--arch/arm/mach-arc/dma.c (renamed from arch/arm/kernel/dma-arc.c)0
-rw-r--r--arch/arm/mach-arc/fault.c (renamed from arch/arm/mm/fault-armo.c)0
-rw-r--r--arch/arm/mach-arc/head.S (renamed from arch/arm/kernel/head-armo.S)0
-rw-r--r--arch/arm/mach-arc/irq.c153
-rw-r--r--arch/arm/mach-arc/mm.c (renamed from arch/arm/mm/mm-armo.c)0
-rw-r--r--arch/arm/mach-arc/oldlatches.c (renamed from arch/arm/kernel/oldlatches.c)0
-rw-r--r--arch/arm/mach-clps711x/Makefile29
-rw-r--r--arch/arm/mach-clps711x/autcpu12.c72
-rw-r--r--arch/arm/mach-clps711x/cdb89712.c75
-rw-r--r--arch/arm/mach-clps711x/clep7312.c49
-rw-r--r--arch/arm/mach-clps711x/dma.c35
-rw-r--r--arch/arm/mach-clps711x/edb7211-arch.c59
-rw-r--r--arch/arm/mach-clps711x/edb7211-mm.c74
-rw-r--r--arch/arm/mach-clps711x/irq.c138
-rw-r--r--arch/arm/mach-clps711x/mm.c70
-rw-r--r--arch/arm/mach-clps711x/p720t-leds.c67
-rw-r--r--arch/arm/mach-clps711x/p720t.c118
-rw-r--r--arch/arm/mach-clps711x/time.c54
-rw-r--r--arch/arm/mach-clps7500/Makefile21
-rw-r--r--arch/arm/mach-clps7500/core.c236
-rw-r--r--arch/arm/mach-ebsa110/Makefile2
-rw-r--r--arch/arm/mach-ebsa110/arch.c30
-rw-r--r--arch/arm/mach-ebsa110/core.c97
-rw-r--r--arch/arm/mach-ebsa110/hardware.h16
-rw-r--r--arch/arm/mach-ebsa110/io.c38
-rw-r--r--arch/arm/mach-ebsa110/irq.c55
-rw-r--r--arch/arm/mach-ebsa110/mm.c43
-rw-r--r--arch/arm/mach-epxa10db/mm.c1
-rw-r--r--arch/arm/mach-footbridge/Makefile2
-rw-r--r--arch/arm/mach-footbridge/cats-pci.c15
-rw-r--r--arch/arm/mach-footbridge/ebsa285-pci.c16
-rw-r--r--arch/arm/mach-footbridge/netwinder-pci.c49
-rw-r--r--arch/arm/mach-footbridge/personal-pci.c10
-rw-r--r--arch/arm/mach-ftvpci/Makefile24
-rw-r--r--arch/arm/mach-ftvpci/core.c98
-rw-r--r--arch/arm/mach-integrator/pci.c6
-rw-r--r--arch/arm/mach-integrator/pci_v3.c108
-rw-r--r--arch/arm/mach-iop310/Makefile33
-rw-r--r--arch/arm/mach-iop310/arch.c61
-rw-r--r--arch/arm/mach-iop310/iop310-irq.c109
-rw-r--r--arch/arm/mach-iop310/iop310-pci.c500
-rw-r--r--arch/arm/mach-iop310/iq80310-irq.c172
-rw-r--r--arch/arm/mach-iop310/iq80310-pci.c149
-rw-r--r--arch/arm/mach-iop310/iq80310-time.c125
-rw-r--r--arch/arm/mach-iop310/mm.c71
-rw-r--r--arch/arm/mach-iop310/xs80200-irq.c66
-rw-r--r--arch/arm/mach-l7200/Makefile21
-rw-r--r--arch/arm/mach-l7200/core.c114
-rw-r--r--arch/arm/mach-rpc/Makefile22
-rw-r--r--arch/arm/mach-rpc/irq.c142
-rw-r--r--arch/arm/mach-rpc/riscpc.c94
-rw-r--r--arch/arm/mach-sa1100/Makefile32
-rw-r--r--arch/arm/mach-sa1100/adsbitsy.c31
-rw-r--r--arch/arm/mach-sa1100/assabet.c99
-rw-r--r--arch/arm/mach-sa1100/cerf.c49
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c17
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1110.c214
-rw-r--r--arch/arm/mach-sa1100/dma-sa1100.c620
-rw-r--r--arch/arm/mach-sa1100/dma-sa1111.c363
-rw-r--r--arch/arm/mach-sa1100/dma.c343
-rw-r--r--arch/arm/mach-sa1100/dma.h69
-rw-r--r--arch/arm/mach-sa1100/flexanet.c157
-rw-r--r--arch/arm/mach-sa1100/freebird.c30
-rw-r--r--arch/arm/mach-sa1100/generic.c68
-rw-r--r--arch/arm/mach-sa1100/generic.h3
-rw-r--r--arch/arm/mach-sa1100/graphicsclient.c20
-rw-r--r--arch/arm/mach-sa1100/graphicsmaster.c22
-rw-r--r--arch/arm/mach-sa1100/h3600.c488
-rw-r--r--arch/arm/mach-sa1100/huw_webpanel.c27
-rw-r--r--arch/arm/mach-sa1100/irq.c16
-rw-r--r--arch/arm/mach-sa1100/jornada720.c18
-rw-r--r--arch/arm/mach-sa1100/lart.c1
-rw-r--r--arch/arm/mach-sa1100/leds-assabet.c5
-rw-r--r--arch/arm/mach-sa1100/leds-flexanet.c12
-rw-r--r--arch/arm/mach-sa1100/leds-system3.c49
-rw-r--r--arch/arm/mach-sa1100/leds.c2
-rw-r--r--arch/arm/mach-sa1100/leds.h1
-rw-r--r--arch/arm/mach-sa1100/neponset.c33
-rw-r--r--arch/arm/mach-sa1100/omnimeter.c24
-rw-r--r--arch/arm/mach-sa1100/pangolin.c7
-rw-r--r--arch/arm/mach-sa1100/pfs168.c8
-rw-r--r--arch/arm/mach-sa1100/pm.c87
-rw-r--r--arch/arm/mach-sa1100/sa1111.c241
-rw-r--r--arch/arm/mach-sa1100/sa1111.h4
-rw-r--r--arch/arm/mach-sa1100/shannon.c40
-rw-r--r--arch/arm/mach-sa1100/sherman.c7
-rw-r--r--arch/arm/mach-sa1100/simpad.c23
-rw-r--r--arch/arm/mach-sa1100/sleep.S2
-rw-r--r--arch/arm/mach-sa1100/system3.c479
-rw-r--r--arch/arm/mach-sa1100/xp860.c4
-rw-r--r--arch/arm/mach-sa1100/yopy.c16
-rw-r--r--arch/arm/mach-shark/Makefile2
-rw-r--r--arch/arm/mach-shark/core.c (renamed from arch/arm/mach-shark/arch.c)22
-rw-r--r--arch/arm/mach-shark/irq.c124
-rw-r--r--arch/arm/mach-shark/mm.c28
-rw-r--r--arch/arm/mach-tbox/Makefile21
-rw-r--r--arch/arm/mach-tbox/core.c75
-rw-r--r--arch/arm/mm/Makefile34
-rw-r--r--arch/arm/mm/alignment.c578
-rw-r--r--arch/arm/mm/armv4-early-abort.S29
-rw-r--r--arch/arm/mm/armv4t-early-abort.S31
-rw-r--r--arch/arm/mm/armv4t-late-abort.S224
-rw-r--r--arch/arm/mm/armv5ej-early-abort.S35
-rw-r--r--arch/arm/mm/fault-armv.c559
-rw-r--r--arch/arm/mm/fault-common.c4
-rw-r--r--arch/arm/mm/minicache.c63
-rw-r--r--arch/arm/mm/mm-armv.c12
-rw-r--r--arch/arm/mm/mm-clps7500.c30
-rw-r--r--arch/arm/mm/mm-ftvpci.c32
-rw-r--r--arch/arm/mm/mm-l7200.c28
-rw-r--r--arch/arm/mm/mm-rpc.c32
-rw-r--r--arch/arm/mm/mm-tbox.c28
-rw-r--r--arch/arm/mm/proc-arm1020.S34
-rw-r--r--arch/arm/mm/proc-arm2,3.S6
-rw-r--r--arch/arm/mm/proc-arm6,7.S14
-rw-r--r--arch/arm/mm/proc-arm720.S236
-rw-r--r--arch/arm/mm/proc-arm920.S34
-rw-r--r--arch/arm/mm/proc-arm922.S639
-rw-r--r--arch/arm/mm/proc-arm926.S33
-rw-r--r--arch/arm/mm/proc-sa110.S97
-rw-r--r--arch/arm/mm/proc-xscale.S812
-rw-r--r--arch/arm/nwfpe/ARM-gcc.h8
-rw-r--r--arch/arm/nwfpe/entry.S23
-rw-r--r--arch/arm/nwfpe/entry26.S2
-rw-r--r--arch/arm/nwfpe/fpa11.c76
-rw-r--r--arch/arm/nwfpe/fpa11_cpdt.c114
-rw-r--r--arch/arm/tools/Makefile14
-rw-r--r--arch/arm/tools/getconstants.c11
-rw-r--r--arch/arm/tools/mach-types27
-rw-r--r--arch/arm/vmlinux-armo.lds.in1
-rw-r--r--arch/arm/vmlinux-armv.lds.in1
-rw-r--r--arch/cris/drivers/usb-host.c36
-rw-r--r--arch/cris/kernel/process.c1
-rw-r--r--arch/i386/config.in3
-rw-r--r--arch/i386/defconfig8
-rw-r--r--arch/i386/kernel/Makefile3
-rw-r--r--arch/i386/kernel/apic.c23
-rw-r--r--arch/i386/kernel/cpuid.c4
-rw-r--r--arch/i386/kernel/msr.c6
-rw-r--r--arch/i386/kernel/pci-pc.c20
-rw-r--r--arch/i386/kernel/process.c1
-rw-r--r--arch/i386/kernel/setup-visws.c126
-rw-r--r--arch/i386/kernel/setup.c148
-rw-r--r--arch/ia64/hp/hpsim_console.c13
-rw-r--r--arch/ia64/kernel/process.c2
-rw-r--r--arch/ia64/sn/io/hcl.c12
-rw-r--r--arch/m68k/amiga/config.c29
-rw-r--r--arch/m68k/kernel/process.c1
-rw-r--r--arch/m68k/mac/debug.c14
-rw-r--r--arch/m68k/mvme147/config.c24
-rw-r--r--arch/m68k/q40/config.c2
-rw-r--r--arch/m68k/sun3x/prom.c1
-rw-r--r--arch/mips/au1000/common/serial.c30
-rw-r--r--arch/mips/baget/vacserial.c38
-rw-r--r--arch/mips/dec/promcon.c6
-rw-r--r--arch/mips/kernel/process.c1
-rw-r--r--arch/mips64/kernel/process.c1
-rw-r--r--arch/parisc/kernel/pdc_cons.c4
-rw-r--r--arch/parisc/kernel/process.c1
-rw-r--r--arch/ppc/8260_io/uart.c51
-rw-r--r--arch/ppc/8xx_io/uart.c9
-rw-r--r--arch/ppc/amiga/config.c29
-rw-r--r--arch/ppc/kernel/idle.c1
-rw-r--r--arch/s390/kernel/process.c1
-rw-r--r--arch/s390x/kernel/process.c1
-rw-r--r--arch/sh/kernel/process.c1
-rw-r--r--arch/sh/kernel/setup.c10
-rw-r--r--arch/sparc/kernel/process.c4
-rw-r--r--arch/sparc/kernel/sys_sunos.c6
-rw-r--r--arch/sparc64/defconfig9
-rw-r--r--arch/sparc64/kernel/chmc.c6
-rw-r--r--arch/sparc64/kernel/process.c4
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c14
-rw-r--r--arch/sparc64/solaris/fs.c6
-rw-r--r--arch/sparc64/solaris/misc.c6
-rw-r--r--arch/sparc64/solaris/socksys.c6
-rw-r--r--arch/sparc64/solaris/timod.c4
-rw-r--r--drivers/acorn/block/mfmhd.c4
-rw-r--r--drivers/acorn/scsi/acornscsi.c7
-rw-r--r--drivers/acorn/scsi/arxescsi.c6
-rw-r--r--drivers/acorn/scsi/cumana_1.c6
-rw-r--r--drivers/acorn/scsi/cumana_2.c6
-rw-r--r--drivers/acorn/scsi/ecoscsi.c6
-rw-r--r--drivers/acorn/scsi/eesox.c6
-rw-r--r--drivers/acorn/scsi/oak.c6
-rw-r--r--drivers/acorn/scsi/powertec.c6
-rw-r--r--drivers/acpi/ospm/ac_adapter/ac_osl.c1
-rw-r--r--drivers/acpi/ospm/battery/bt_osl.c1
-rw-r--r--drivers/acpi/ospm/busmgr/bm_osl.c1
-rw-r--r--drivers/acpi/ospm/button/bn_osl.c1
-rw-r--r--drivers/acpi/ospm/ec/ec_osl.c1
-rw-r--r--drivers/acpi/ospm/processor/pr_osl.c1
-rw-r--r--drivers/acpi/ospm/system/sm_osl.c1
-rw-r--r--drivers/acpi/ospm/thermal/tz_osl.c1
-rw-r--r--drivers/acpi/ospm/thermal/tzpolicy.c1
-rw-r--r--drivers/atm/fore200e.c1
-rw-r--r--drivers/block/DAC960.c20
-rw-r--r--drivers/block/DAC960.h6
-rw-r--r--drivers/block/acsi.c2
-rw-r--r--drivers/block/blkpg.c47
-rw-r--r--drivers/block/block_ioctl.c2
-rw-r--r--drivers/block/cciss.c44
-rw-r--r--drivers/block/cciss.h2
-rw-r--r--drivers/block/cciss_cmd.h2
-rw-r--r--drivers/block/cpqarray.c42
-rw-r--r--drivers/block/elevator.c214
-rw-r--r--drivers/block/floppy.c22
-rw-r--r--drivers/block/genhd.c6
-rw-r--r--drivers/block/ll_rw_blk.c193
-rw-r--r--drivers/block/loop.c53
-rw-r--r--drivers/block/nbd.c15
-rw-r--r--drivers/block/paride/pcd.c6
-rw-r--r--drivers/block/paride/pd.c11
-rw-r--r--drivers/block/paride/pf.c6
-rw-r--r--drivers/block/paride/pg.c2
-rw-r--r--drivers/block/paride/pt.c6
-rw-r--r--drivers/block/ps2esdi.c7
-rw-r--r--drivers/block/rd.c12
-rw-r--r--drivers/block/xd.c10
-rw-r--r--drivers/cdrom/aztcd.c12
-rw-r--r--drivers/cdrom/cdrom.c9
-rw-r--r--drivers/cdrom/cdu31a.c191
-rw-r--r--drivers/cdrom/cm206.c10
-rw-r--r--drivers/cdrom/gscd.c11
-rw-r--r--drivers/cdrom/mcd.c12
-rw-r--r--drivers/cdrom/mcdx.c34
-rw-r--r--drivers/cdrom/optcd.c14
-rw-r--r--drivers/cdrom/sbpcd.c48
-rw-r--r--drivers/cdrom/sjcd.c17
-rw-r--r--drivers/cdrom/sonycd535.c211
-rw-r--r--drivers/char/Config.in2
-rw-r--r--drivers/char/acquirewdt.c4
-rw-r--r--drivers/char/advantechwdt.c4
-rw-r--r--drivers/char/agp/agpgart_fe.c2
-rw-r--r--drivers/char/amiserial.c4
-rw-r--r--drivers/char/busmouse.c2
-rw-r--r--drivers/char/console.c11
-rw-r--r--drivers/char/cyclades.c2
-rw-r--r--drivers/char/drm/drm_drv.h2
-rw-r--r--drivers/char/drm/drm_fops.h2
-rw-r--r--drivers/char/drm/drm_stub.h2
-rw-r--r--drivers/char/dsp56k.c13
-rw-r--r--drivers/char/dtlk.c9
-rw-r--r--drivers/char/dz.c13
-rw-r--r--drivers/char/epca.c5
-rw-r--r--drivers/char/esp.c3
-rw-r--r--drivers/char/eurotechwdt.c4
-rw-r--r--drivers/char/ftape/lowlevel/ftape-buffer.c1
-rw-r--r--drivers/char/ftape/lowlevel/ftape-io.c1
-rw-r--r--drivers/char/ftape/lowlevel/ftape-read.c1
-rw-r--r--drivers/char/ftape/lowlevel/ftape-setup.c1
-rw-r--r--drivers/char/ftape/lowlevel/ftape-write.c1
-rw-r--r--drivers/char/ftape/zftape/zftape-buffers.c1
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c17
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.c1
-rw-r--r--drivers/char/ftape/zftape/zftape-vtbl.c1
-rw-r--r--drivers/char/h8.c1
-rw-r--r--drivers/char/ib700wdt.c4
-rw-r--r--drivers/char/ip2main.c23
-rw-r--r--drivers/char/isicom.c3
-rw-r--r--drivers/char/istallion.c8
-rw-r--r--drivers/char/ite_gpio.c2
-rw-r--r--drivers/char/joystick/serport.c4
-rw-r--r--drivers/char/keyboard.c9
-rw-r--r--drivers/char/lp.c12
-rw-r--r--drivers/char/machzwd.c4
-rw-r--r--drivers/char/mem.c2
-rw-r--r--drivers/char/misc.c2
-rw-r--r--drivers/char/moxa.c5
-rw-r--r--drivers/char/mxser.c3
-rw-r--r--drivers/char/n_hdlc.c3
-rw-r--r--drivers/char/n_tty.c12
-rw-r--r--drivers/char/pc110pad.c2
-rw-r--r--drivers/char/pcwd.c6
-rw-r--r--drivers/char/pcxx.c4
-rw-r--r--drivers/char/ppdev.c10
-rw-r--r--drivers/char/pty.c12
-rw-r--r--drivers/char/raw.c37
-rw-r--r--drivers/char/rio/linux_compat.h3
-rw-r--r--drivers/char/rio/rio.h8
-rw-r--r--drivers/char/rio/rio_linux.c12
-rw-r--r--drivers/char/rio/rio_linux.h7
-rw-r--r--drivers/char/rio/rioctrl.c6
-rw-r--r--drivers/char/riscom8.c4
-rw-r--r--drivers/char/sbc60xxwdt.c4
-rw-r--r--drivers/char/ser_a2232.c2
-rw-r--r--drivers/char/serial.c34
-rw-r--r--drivers/char/serial167.c64
-rw-r--r--drivers/char/serial_21285.c16
-rw-r--r--drivers/char/serial_amba.c25
-rw-r--r--drivers/char/serial_tx3912.c20
-rw-r--r--drivers/char/sh-sci.c14
-rw-r--r--drivers/char/shwdt.c4
-rw-r--r--drivers/char/specialix.c6
-rw-r--r--drivers/char/stallion.c4
-rw-r--r--drivers/char/sx.c2
-rw-r--r--drivers/char/synclink.c3
-rw-r--r--drivers/char/sysrq.c4
-rw-r--r--drivers/char/tpqic02.c12
-rw-r--r--drivers/char/tty_io.c74
-rw-r--r--drivers/char/vc_screen.c11
-rw-r--r--drivers/char/vme_scc.c40
-rw-r--r--drivers/char/w83877f_wdt.c4
-rw-r--r--drivers/char/wdt.c6
-rw-r--r--drivers/char/wdt_pci.c6
-rw-r--r--drivers/i2c/i2c-dev.c4
-rw-r--r--drivers/ide/ataraid.c1
-rw-r--r--drivers/ide/hd.c1
-rw-r--r--drivers/ide/hptraid.c111
-rw-r--r--drivers/ide/icside.c112
-rw-r--r--drivers/ide/ide-cd.c21
-rw-r--r--drivers/ide/ide-disk.c4
-rw-r--r--drivers/ide/ide-floppy.c3
-rw-r--r--drivers/ide/ide-probe.c13
-rw-r--r--drivers/ide/ide-timing.h38
-rw-r--r--drivers/ide/ide.c39
-rw-r--r--drivers/ide/pdc4030.c50
-rw-r--r--drivers/ide/pdcraid.c113
-rw-r--r--drivers/ide/via82cxxx.c129
-rw-r--r--drivers/ieee1394/ohci1394.c1
-rw-r--r--drivers/ieee1394/raw1394.c2
-rw-r--r--drivers/ieee1394/sbp2.c4
-rw-r--r--drivers/ieee1394/video1394.c1
-rw-r--r--drivers/input/evdev.c2
-rw-r--r--drivers/input/input.c2
-rw-r--r--drivers/input/joydev.c3
-rw-r--r--drivers/input/mousedev.c2
-rw-r--r--drivers/isdn/Config.in3
-rw-r--r--drivers/isdn/act2000/act2000.h1
-rw-r--r--drivers/isdn/avmb1/avmcard.h25
-rw-r--r--drivers/isdn/avmb1/b1.c64
-rw-r--r--drivers/isdn/avmb1/b1dma.c45
-rw-r--r--drivers/isdn/avmb1/b1pci.c39
-rw-r--r--drivers/isdn/avmb1/c4.c42
-rw-r--r--drivers/isdn/avmb1/capi.c83
-rw-r--r--drivers/isdn/avmb1/capidrv.c1
-rw-r--r--drivers/isdn/avmb1/capifs.c2
-rw-r--r--drivers/isdn/avmb1/capiutil.c1
-rw-r--r--drivers/isdn/avmb1/kcapi.c1
-rw-r--r--drivers/isdn/avmb1/t1pci.c29
-rw-r--r--drivers/isdn/eicon/eicon.h1
-rw-r--r--drivers/isdn/eicon/lincfg.c1
-rw-r--r--drivers/isdn/hisax/Makefile4
-rw-r--r--drivers/isdn/hisax/config.c54
-rw-r--r--drivers/isdn/hisax/hisax.h5
-rw-r--r--drivers/isdn/icn/icn.h1
-rw-r--r--drivers/isdn/isdn_bsdcomp.c1
-rw-r--r--drivers/isdn/isdn_common.c12
-rw-r--r--drivers/isdn/isdn_ppp.c2
-rw-r--r--drivers/isdn/isdn_tty.c6
-rw-r--r--drivers/isdn/isdnloop/isdnloop.h1
-rw-r--r--drivers/isdn/sc/command.c2
-rw-r--r--drivers/isdn/sc/includes.h1
-rw-r--r--drivers/macintosh/mac_keyb.c2
-rw-r--r--drivers/macintosh/macserial.c26
-rw-r--r--drivers/md/lvm-fs.c28
-rw-r--r--drivers/md/lvm-snap.c41
-rw-r--r--drivers/md/lvm.c145
-rw-r--r--drivers/md/md.c239
-rw-r--r--drivers/md/multipath.c13
-rw-r--r--drivers/md/raid1.c12
-rw-r--r--drivers/md/raid5.c29
-rw-r--r--drivers/md/xor.c1
-rw-r--r--drivers/media/video/adv7175.c1
-rw-r--r--drivers/media/video/bt856.c1
-rw-r--r--drivers/media/video/bttv-driver.c1
-rw-r--r--drivers/media/video/cpia.c2
-rw-r--r--drivers/media/video/saa7185.c1
-rw-r--r--drivers/media/video/stradis.c1
-rw-r--r--drivers/media/video/tvmixer.c2
-rw-r--r--drivers/media/video/videodev.c14
-rw-r--r--drivers/media/video/zr36067.c1
-rw-r--r--drivers/media/video/zr36120.c1
-rw-r--r--drivers/message/i2o/i2o_block.c1
-rw-r--r--drivers/mtd/devices/blkmtd.c10
-rw-r--r--drivers/mtd/devices/doc1000.c1
-rw-r--r--drivers/mtd/devices/pmc551.c1
-rw-r--r--drivers/mtd/devices/slram.c1
-rw-r--r--drivers/mtd/ftl.c47
-rw-r--r--drivers/mtd/nftlcore.c11
-rw-r--r--drivers/net/de2104x.c310
-rw-r--r--drivers/net/defxx.c2
-rw-r--r--drivers/net/fc/iph5526.c8
-rw-r--r--drivers/net/hamradio/bpqether.c1
-rw-r--r--drivers/net/hamradio/dmascc.c1
-rw-r--r--drivers/net/hamradio/mkiss.c1
-rw-r--r--drivers/net/irda/irda-usb.c144
-rw-r--r--drivers/net/irda/irtty.c5
-rw-r--r--drivers/net/jazzsonic.c1
-rw-r--r--drivers/net/macsonic.c1
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c1
-rw-r--r--drivers/net/sgiseeq.c1
-rw-r--r--drivers/net/slip.c10
-rw-r--r--drivers/net/strip.c1
-rw-r--r--drivers/net/wan/cosa.c4
-rw-r--r--drivers/net/wan/lapbether.c1
-rw-r--r--drivers/net/wan/lmc/lmc_main.c1
-rw-r--r--drivers/net/wan/lmc/lmc_media.c1
-rw-r--r--drivers/net/wan/lmc/lmc_proto.c1
-rw-r--r--drivers/net/wan/sdla_chdlc.c2
-rw-r--r--drivers/net/wireless/airo.c1
-rw-r--r--drivers/pcmcia/ds.c12
-rw-r--r--drivers/pcmcia/i82365.c1
-rw-r--r--drivers/pcmcia/tcic.c1
-rw-r--r--drivers/s390/block/dasd_int.h2
-rw-r--r--drivers/s390/char/tuball.c1
-rw-r--r--drivers/s390/s390io.c36
-rw-r--r--drivers/sbus/audio/audio.c16
-rw-r--r--drivers/sbus/char/aurora.c7
-rw-r--r--drivers/sbus/char/bpp.c1
-rw-r--r--drivers/sbus/char/cpwatchdog.c2
-rw-r--r--drivers/sbus/char/display7seg.c8
-rw-r--r--drivers/sbus/char/sab82532.c20
-rw-r--r--drivers/sbus/char/su.c43
-rw-r--r--drivers/sbus/char/sunkbd.c12
-rw-r--r--drivers/sbus/char/zs.c24
-rw-r--r--drivers/scsi/BusLogic.c16
-rw-r--r--drivers/scsi/BusLogic.h4
-rw-r--r--drivers/scsi/advansys.c102
-rw-r--r--drivers/scsi/aha152x.c4
-rw-r--r--drivers/scsi/aha1542.c46
-rw-r--r--drivers/scsi/aha1740.c10
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_linux.c11
-rw-r--r--drivers/scsi/aic7xxx_old.c10
-rw-r--r--drivers/scsi/cpqfcTSworker.c29
-rw-r--r--drivers/scsi/dpt_i2o.c60
-rw-r--r--drivers/scsi/eata.c260
-rw-r--r--drivers/scsi/eata.h2
-rw-r--r--drivers/scsi/fdomain.c54
-rw-r--r--drivers/scsi/fdomain.h2
-rw-r--r--drivers/scsi/hosts.c9
-rw-r--r--drivers/scsi/hosts.h17
-rw-r--r--drivers/scsi/ide-scsi.c27
-rw-r--r--drivers/scsi/ide-scsi.h37
-rw-r--r--drivers/scsi/in2000.c10
-rw-r--r--drivers/scsi/in2000.h5
-rw-r--r--drivers/scsi/ips.c50
-rw-r--r--drivers/scsi/mac_scsi.c2
-rw-r--r--drivers/scsi/megaraid.c14
-rw-r--r--drivers/scsi/ncr53c8xx.c8
-rw-r--r--drivers/scsi/osst.c18
-rw-r--r--drivers/scsi/pci2000.c20
-rw-r--r--drivers/scsi/pci2220i.c32
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c4
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c4
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c4
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c4
-rw-r--r--drivers/scsi/qla1280.c1
-rw-r--r--drivers/scsi/scsi.c85
-rw-r--r--drivers/scsi/scsi.h2
-rw-r--r--drivers/scsi/scsi_lib.c9
-rw-r--r--drivers/scsi/scsi_module.c6
-rw-r--r--drivers/scsi/scsi_scan.c3
-rw-r--r--drivers/scsi/scsi_syms.c7
-rw-r--r--drivers/scsi/scsicam.c35
-rw-r--r--drivers/scsi/sd.c19
-rw-r--r--drivers/scsi/sd.h2
-rw-r--r--drivers/scsi/sg.c28
-rw-r--r--drivers/scsi/sim710.c7
-rw-r--r--drivers/scsi/sr.c64
-rw-r--r--drivers/scsi/sr_ioctl.c36
-rw-r--r--drivers/scsi/sr_vendor.c2
-rw-r--r--drivers/scsi/st.c12
-rw-r--r--drivers/scsi/sym53c8xx_comm.h12
-rw-r--r--drivers/scsi/tmscsim.c18
-rw-r--r--drivers/scsi/u14-34f.c165
-rw-r--r--drivers/scsi/u14-34f.h2
-rw-r--r--drivers/scsi/wd7000.c225
-rw-r--r--drivers/sgi/char/sgiserial.c11
-rw-r--r--drivers/sound/ad1848.c16
-rw-r--r--drivers/sound/btaudio.c6
-rw-r--r--drivers/sound/cs4281/cs4281m.c6
-rw-r--r--drivers/sound/cs46xx.c8
-rw-r--r--drivers/sound/es1370.c8
-rw-r--r--drivers/sound/es1371.c8
-rw-r--r--drivers/sound/esssolo1.c8
-rw-r--r--drivers/sound/i810_audio.c2
-rw-r--r--drivers/sound/maestro.c4
-rw-r--r--drivers/sound/maestro3.c4
-rw-r--r--drivers/sound/sound_core.c2
-rw-r--r--drivers/sound/soundcard.c15
-rw-r--r--drivers/sound/sscape.c1
-rw-r--r--drivers/sound/trident.c4
-rw-r--r--drivers/sound/ymfpci.c4
-rw-r--r--drivers/tc/zs.c14
-rw-r--r--drivers/telephony/ixj.c1
-rw-r--r--drivers/usb/Config.in5
-rw-r--r--drivers/usb/Makefile21
-rw-r--r--drivers/usb/acm.c2
-rw-r--r--drivers/usb/audio.c24
-rw-r--r--drivers/usb/bluetooth.c2
-rw-r--r--drivers/usb/catc.c62
-rw-r--r--drivers/usb/dabusb.c40
-rw-r--r--drivers/usb/dabusb.h2
-rw-r--r--drivers/usb/dc2xx.c2
-rw-r--r--drivers/usb/devio.c14
-rw-r--r--drivers/usb/hcd.c1305
-rw-r--r--drivers/usb/hcd.h219
-rw-r--r--drivers/usb/hcd/Config.in7
-rw-r--r--drivers/usb/hcd/Makefile27
-rw-r--r--drivers/usb/hcd/ehci-dbg.c179
-rw-r--r--drivers/usb/hcd/ehci-hcd.c758
-rw-r--r--drivers/usb/hcd/ehci-hub.c341
-rw-r--r--drivers/usb/hcd/ehci-mem.c237
-rw-r--r--drivers/usb/hcd/ehci-q.c949
-rw-r--r--drivers/usb/hcd/ehci-sched.c1053
-rw-r--r--drivers/usb/hcd/ehci.h383
-rw-r--r--drivers/usb/hiddev.c2
-rw-r--r--drivers/usb/hpusbscsi.c4
-rw-r--r--drivers/usb/hub.c273
-rw-r--r--drivers/usb/hub.h41
-rw-r--r--drivers/usb/inode.c1009
-rw-r--r--drivers/usb/mdc800.c6
-rw-r--r--drivers/usb/microtek.c6
-rw-r--r--drivers/usb/ov511.c6256
-rw-r--r--drivers/usb/ov511.h332
-rw-r--r--drivers/usb/printer.c2
-rw-r--r--drivers/usb/pwc-ctrl.c8
-rw-r--r--drivers/usb/pwc-if.c69
-rw-r--r--drivers/usb/pwc-ioctl.h4
-rw-r--r--drivers/usb/pwc.h6
-rw-r--r--drivers/usb/scanner.c14
-rw-r--r--drivers/usb/scanner.h4
-rw-r--r--drivers/usb/serial/Config.in2
-rw-r--r--drivers/usb/serial/Makefile4
-rw-r--r--drivers/usb/serial/ipaq.c525
-rw-r--r--drivers/usb/serial/ipaq.h60
-rw-r--r--drivers/usb/serial/kl5kusb105.c1086
-rw-r--r--drivers/usb/serial/kl5kusb105.h69
-rw-r--r--drivers/usb/serial/usb-serial.h2
-rw-r--r--drivers/usb/serial/usbserial.c34
-rw-r--r--drivers/usb/serial/visor.c53
-rw-r--r--drivers/usb/storage/datafab.c6
-rw-r--r--drivers/usb/storage/freecom.c19
-rw-r--r--drivers/usb/storage/jumpshot.c6
-rw-r--r--drivers/usb/storage/sddr09.c18
-rw-r--r--drivers/usb/storage/shuttle_usbat.c4
-rw-r--r--drivers/usb/storage/transport.c4
-rw-r--r--drivers/usb/storage/unusual_devs.h77
-rw-r--r--drivers/usb/storage/usb.c6
-rw-r--r--drivers/usb/stv680.c1633
-rw-r--r--drivers/usb/stv680.h222
-rw-r--r--drivers/usb/usb-debug.c34
-rw-r--r--drivers/usb/usb.c36
-rw-r--r--drivers/usb/usbnet.c4
-rw-r--r--drivers/usb/vicam.c986
-rw-r--r--drivers/usb/vicam.h81
-rw-r--r--drivers/usb/vicamurbs.h330
-rw-r--r--drivers/video/aty/atyfb_base.c3
-rw-r--r--drivers/video/dn_cfb4.c1
-rw-r--r--drivers/video/dn_cfb8.c1
-rw-r--r--drivers/video/dnfb.c1
-rw-r--r--drivers/video/fbcon.c4
-rw-r--r--drivers/video/fbmem.c12
-rw-r--r--drivers/video/q40fb.c1
-rw-r--r--drivers/video/sbusfb.c2
-rw-r--r--drivers/video/vesafb.c2
-rw-r--r--fs/Config.in2
-rw-r--r--fs/adfs/inode.c8
-rw-r--r--fs/adfs/super.c27
-rw-r--r--fs/affs/amigaffs.c4
-rw-r--r--fs/affs/bitmap.c4
-rw-r--r--fs/affs/file.c4
-rw-r--r--fs/affs/super.c14
-rw-r--r--fs/autofs/inode.c1
-rw-r--r--fs/autofs4/inode.c2
-rw-r--r--fs/bfs/dir.c10
-rw-r--r--fs/bfs/file.c28
-rw-r--r--fs/bfs/inode.c23
-rw-r--r--fs/binfmt_elf.c32
-rw-r--r--fs/bio.c5
-rw-r--r--fs/block_dev.c53
-rw-r--r--fs/buffer.c42
-rw-r--r--fs/char_dev.c1
-rw-r--r--fs/coda/cache.c1
-rw-r--r--fs/coda/coda_linux.c1
-rw-r--r--fs/coda/file.c1
-rw-r--r--fs/coda/inode.c9
-rw-r--r--fs/coda/pioctl.c3
-rw-r--r--fs/coda/psdev.c3
-rw-r--r--fs/coda/sysctl.c1
-rw-r--r--fs/coda/upcall.c1
-rw-r--r--fs/cramfs/inode.c10
-rw-r--r--fs/devfs/base.c688
-rw-r--r--fs/devfs/util.c71
-rw-r--r--fs/devices.c10
-rw-r--r--fs/dquot.c28
-rw-r--r--fs/efs/file.c7
-rw-r--r--fs/efs/super.c5
-rw-r--r--fs/ext2/ialloc.c2
-rw-r--r--fs/ext2/inode.c9
-rw-r--r--fs/ext2/super.c92
-rw-r--r--fs/ext3/ialloc.c4
-rw-r--r--fs/ext3/inode.c22
-rw-r--r--fs/ext3/super.c86
-rw-r--r--fs/fat/cache.c22
-rw-r--r--fs/fat/file.c8
-rw-r--r--fs/fat/inode.c27
-rw-r--r--fs/fat/misc.c2
-rw-r--r--fs/freevxfs/vxfs.h3
-rw-r--r--fs/freevxfs/vxfs_bmap.c62
-rw-r--r--fs/freevxfs/vxfs_extern.h4
-rw-r--r--fs/freevxfs/vxfs_fshead.c6
-rw-r--r--fs/freevxfs/vxfs_inode.c10
-rw-r--r--fs/freevxfs/vxfs_kcompat.h49
-rw-r--r--fs/freevxfs/vxfs_lookup.c7
-rw-r--r--fs/freevxfs/vxfs_olt.c15
-rw-r--r--fs/freevxfs/vxfs_subr.c11
-rw-r--r--fs/freevxfs/vxfs_super.c52
-rw-r--r--fs/hfs/dir.c8
-rw-r--r--fs/hfs/file.c8
-rw-r--r--fs/hfs/file_cap.c1
-rw-r--r--fs/hfs/file_hdr.c1
-rw-r--r--fs/hfs/inode.c7
-rw-r--r--fs/hfs/super.c6
-rw-r--r--fs/hpfs/file.c9
-rw-r--r--fs/hpfs/hpfs_fn.h1
-rw-r--r--fs/hpfs/super.c6
-rw-r--r--fs/inode.c4
-rw-r--r--fs/intermezzo/cache.c8
-rw-r--r--fs/intermezzo/dcache.c1
-rw-r--r--fs/intermezzo/ext_attr.c1
-rw-r--r--fs/intermezzo/inode.c1
-rw-r--r--fs/intermezzo/journal.c1
-rw-r--r--fs/intermezzo/journal_ext2.c1
-rw-r--r--fs/intermezzo/journal_ext3.c1
-rw-r--r--fs/intermezzo/journal_obdfs.c1
-rw-r--r--fs/intermezzo/journal_reiserfs.c1
-rw-r--r--fs/intermezzo/journal_xfs.c1
-rw-r--r--fs/intermezzo/presto.c5
-rw-r--r--fs/intermezzo/psdev.c10
-rw-r--r--fs/intermezzo/super.c8
-rw-r--r--fs/intermezzo/sysctl.c14
-rw-r--r--fs/intermezzo/upcall.c2
-rw-r--r--fs/intermezzo/vfs.c8
-rw-r--r--fs/isofs/inode.c58
-rw-r--r--fs/isofs/joliet.c2
-rw-r--r--fs/isofs/namei.c2
-rw-r--r--fs/isofs/rock.c4
-rw-r--r--fs/jbd/journal.c2
-rw-r--r--fs/jffs/inode-v23.c15
-rw-r--r--fs/jffs2/dir.c2
-rw-r--r--fs/jffs2/file.c4
-rw-r--r--fs/jffs2/gc.c4
-rw-r--r--fs/jffs2/super.c4
-rw-r--r--fs/jffs2/write.c17
-rw-r--r--fs/lockd/svclock.c20
-rw-r--r--fs/minix/bitmap.c6
-rw-r--r--fs/minix/inode.c25
-rw-r--r--fs/minix/itree_common.c8
-rw-r--r--fs/msdos/namei.c6
-rw-r--r--fs/namei.c6
-rw-r--r--fs/namespace.c240
-rw-r--r--fs/ncpfs/inode.c2
-rw-r--r--fs/ncpfs/symlink.c1
-rw-r--r--fs/nfs/dir.c24
-rw-r--r--fs/nfs/file.c8
-rw-r--r--fs/nfs/inode.c41
-rw-r--r--fs/nfs/nfsroot.c2
-rw-r--r--fs/nfs/read.c14
-rw-r--r--fs/nfs/write.c19
-rw-r--r--fs/nfsd/export.c39
-rw-r--r--fs/nfsd/nfs3xdr.c12
-rw-r--r--fs/nfsd/nfsctl.c4
-rw-r--r--fs/nfsd/nfsfh.c13
-rw-r--r--fs/nfsd/nfsproc.c6
-rw-r--r--fs/nfsd/nfsxdr.c4
-rw-r--r--fs/nfsd/vfs.c10
-rw-r--r--fs/nls/nls_base.c2
-rw-r--r--fs/nls/nls_big5.c1
-rw-r--r--fs/nls/nls_cp932.c1
-rw-r--r--fs/nls/nls_cp936.c1
-rw-r--r--fs/nls/nls_cp949.c1
-rw-r--r--fs/nls/nls_cp950.c1
-rw-r--r--fs/nls/nls_euc-jp.c1
-rw-r--r--fs/nls/nls_euc-kr.c1
-rw-r--r--fs/nls/nls_gb2312.c1
-rw-r--r--fs/nls/nls_iso8859-1.c1
-rw-r--r--fs/nls/nls_iso8859-13.c1
-rw-r--r--fs/nls/nls_iso8859-14.c1
-rw-r--r--fs/nls/nls_iso8859-15.c1
-rw-r--r--fs/nls/nls_iso8859-2.c1
-rw-r--r--fs/nls/nls_iso8859-3.c1
-rw-r--r--fs/nls/nls_iso8859-4.c1
-rw-r--r--fs/nls/nls_iso8859-5.c1
-rw-r--r--fs/nls/nls_iso8859-6.c1
-rw-r--r--fs/nls/nls_iso8859-7.c1
-rw-r--r--fs/nls/nls_iso8859-8.c1
-rw-r--r--fs/nls/nls_iso8859-9.c1
-rw-r--r--fs/nls/nls_koi8-r.c1
-rw-r--r--fs/nls/nls_koi8-ru.c1
-rw-r--r--fs/nls/nls_koi8-u.c1
-rw-r--r--fs/nls/nls_sjis.c1
-rw-r--r--fs/nls/nls_tis-620.c1
-rw-r--r--fs/nls/nls_utf8.c1
-rw-r--r--fs/ntfs/fs.c14
-rw-r--r--fs/ntfs/support.c2
-rw-r--r--fs/partitions/acorn.c4
-rw-r--r--fs/partitions/atari.c2
-rw-r--r--fs/partitions/check.c30
-rw-r--r--fs/partitions/check.h10
-rw-r--r--fs/partitions/ibm.c2
-rw-r--r--fs/proc/array.c5
-rw-r--r--fs/proc/base.c48
-rw-r--r--fs/proc/proc_misc.c15
-rw-r--r--fs/qnx4/dir.c1
-rw-r--r--fs/qnx4/fsync.c1
-rw-r--r--fs/qnx4/inode.c28
-rw-r--r--fs/qnx4/namei.c3
-rw-r--r--fs/qnx4/truncate.c3
-rw-r--r--fs/ramfs/inode.c7
-rw-r--r--fs/reiserfs/bitmap.c4
-rw-r--r--fs/reiserfs/buffer2.c16
-rw-r--r--fs/reiserfs/fix_node.c8
-rw-r--r--fs/reiserfs/inode.c20
-rw-r--r--fs/reiserfs/journal.c19
-rw-r--r--fs/reiserfs/namei.c4
-rw-r--r--fs/reiserfs/prints.c2
-rw-r--r--fs/reiserfs/procfs.c7
-rw-r--r--fs/reiserfs/resize.c2
-rw-r--r--fs/reiserfs/stree.c9
-rw-r--r--fs/reiserfs/super.c52
-rw-r--r--fs/romfs/inode.c13
-rw-r--r--fs/smbfs/ChangeLog10
-rw-r--r--fs/smbfs/file.c10
-rw-r--r--fs/smbfs/getopt.c2
-rw-r--r--fs/smbfs/getopt.h1
-rw-r--r--fs/smbfs/inode.c93
-rw-r--r--fs/super.c30
-rw-r--r--fs/sysv/ChangeLog47
-rw-r--r--fs/sysv/dir.c2
-rw-r--r--fs/sysv/ialloc.c2
-rw-r--r--fs/sysv/inode.c20
-rw-r--r--fs/sysv/itree.c4
-rw-r--r--fs/sysv/super.c30
-rw-r--r--fs/udf/inode.c15
-rw-r--r--fs/udf/namei.c11
-rw-r--r--fs/udf/super.c31
-rw-r--r--fs/ufs/inode.c27
-rw-r--r--fs/ufs/super.c24
-rw-r--r--fs/umsdos/inode.c4
-rw-r--r--fs/vfat/namei.c14
-rw-r--r--include/asm-arm/arch-adifcc/adi_evb.h19
-rw-r--r--include/asm-arm/arch-adifcc/dma.h18
-rw-r--r--include/asm-arm/arch-adifcc/hardware.h27
-rw-r--r--include/asm-arm/arch-adifcc/io.h22
-rw-r--r--include/asm-arm/arch-adifcc/irq.h13
-rw-r--r--include/asm-arm/arch-adifcc/irqs.h28
-rw-r--r--include/asm-arm/arch-adifcc/memory.h57
-rw-r--r--include/asm-arm/arch-adifcc/param.h3
-rw-r--r--include/asm-arm/arch-adifcc/serial.h36
-rw-r--r--include/asm-arm/arch-adifcc/system.h29
-rw-r--r--include/asm-arm/arch-adifcc/time.h9
-rw-r--r--include/asm-arm/arch-adifcc/timex.h10
-rw-r--r--include/asm-arm/arch-adifcc/uncompress.h35
-rw-r--r--include/asm-arm/arch-adifcc/vmalloc.h16
-rw-r--r--include/asm-arm/arch-anakin/io.h7
-rw-r--r--include/asm-arm/arch-anakin/time.h3
-rw-r--r--include/asm-arm/arch-arc/io.h6
-rw-r--r--include/asm-arm/arch-arc/irq.h138
-rw-r--r--include/asm-arm/arch-arc/time.h2
-rw-r--r--include/asm-arm/arch-cl7500/irq.h195
-rw-r--r--include/asm-arm/arch-cl7500/keyboard.h1
-rw-r--r--include/asm-arm/arch-cl7500/time.h5
-rw-r--r--include/asm-arm/arch-clps711x/autcpu12.h78
-rw-r--r--include/asm-arm/arch-clps711x/dma.h28
-rw-r--r--include/asm-arm/arch-clps711x/hardware.h179
-rw-r--r--include/asm-arm/arch-clps711x/io.h37
-rw-r--r--include/asm-arm/arch-clps711x/irq.h20
-rw-r--r--include/asm-arm/arch-clps711x/irqs.h53
-rw-r--r--include/asm-arm/arch-clps711x/keyboard.h26
-rw-r--r--include/asm-arm/arch-clps711x/memory.h204
-rw-r--r--include/asm-arm/arch-clps711x/param.h21
-rw-r--r--include/asm-arm/arch-clps711x/syspld.h121
-rw-r--r--include/asm-arm/arch-clps711x/system.h38
-rw-r--r--include/asm-arm/arch-clps711x/time.h43
-rw-r--r--include/asm-arm/arch-clps711x/timex.h23
-rw-r--r--include/asm-arm/arch-clps711x/uncompress.h67
-rw-r--r--include/asm-arm/arch-clps711x/vmalloc.h32
-rw-r--r--include/asm-arm/arch-ebsa110/io.h10
-rw-r--r--include/asm-arm/arch-ebsa110/time.h2
-rw-r--r--include/asm-arm/arch-ebsa110/vmalloc.h2
-rw-r--r--include/asm-arm/arch-ebsa285/io.h9
-rw-r--r--include/asm-arm/arch-ebsa285/time.h2
-rw-r--r--include/asm-arm/arch-ebsa285/vmalloc.h7
-rw-r--r--include/asm-arm/arch-epxa10db/ether00.h482
-rw-r--r--include/asm-arm/arch-epxa10db/io.h18
-rw-r--r--include/asm-arm/arch-epxa10db/tdkphy.h209
-rw-r--r--include/asm-arm/arch-epxa10db/time.h7
-rw-r--r--include/asm-arm/arch-integrator/io.h16
-rw-r--r--include/asm-arm/arch-integrator/time.h2
-rw-r--r--include/asm-arm/arch-iop310/dma.h109
-rw-r--r--include/asm-arm/arch-iop310/hardware.h38
-rw-r--r--include/asm-arm/arch-iop310/ide.h51
-rw-r--r--include/asm-arm/arch-iop310/io.h20
-rw-r--r--include/asm-arm/arch-iop310/iop310.h247
-rw-r--r--include/asm-arm/arch-iop310/iq80310.h30
-rw-r--r--include/asm-arm/arch-iop310/irq.h13
-rw-r--r--include/asm-arm/arch-iop310/irqs.h80
-rw-r--r--include/asm-arm/arch-iop310/memory.h58
-rw-r--r--include/asm-arm/arch-iop310/param.h3
-rw-r--r--include/asm-arm/arch-iop310/pmon.h50
-rw-r--r--include/asm-arm/arch-iop310/serial.h34
-rw-r--r--include/asm-arm/arch-iop310/system.h30
-rw-r--r--include/asm-arm/arch-iop310/time.h12
-rw-r--r--include/asm-arm/arch-iop310/timex.h23
-rw-r--r--include/asm-arm/arch-iop310/uncompress.h33
-rw-r--r--include/asm-arm/arch-iop310/vmalloc.h16
-rw-r--r--include/asm-arm/arch-l7200/io.h2
-rw-r--r--include/asm-arm/arch-l7200/irq.h56
-rw-r--r--include/asm-arm/arch-l7200/keyboard.h2
-rw-r--r--include/asm-arm/arch-l7200/time.h2
-rw-r--r--include/asm-arm/arch-nexuspci/io.h17
-rw-r--r--include/asm-arm/arch-nexuspci/irq.h55
-rw-r--r--include/asm-arm/arch-nexuspci/time.h2
-rw-r--r--include/asm-arm/arch-rpc/io.h6
-rw-r--r--include/asm-arm/arch-rpc/irq.h138
-rw-r--r--include/asm-arm/arch-rpc/time.h2
-rw-r--r--include/asm-arm/arch-sa1100/SA-1111.h648
-rw-r--r--include/asm-arm/arch-sa1100/assabet.h37
-rw-r--r--include/asm-arm/arch-sa1100/dma.h113
-rw-r--r--include/asm-arm/arch-sa1100/flexanet.h95
-rw-r--r--include/asm-arm/arch-sa1100/graphicsmaster.h2
-rw-r--r--include/asm-arm/arch-sa1100/h3600.h165
-rw-r--r--include/asm-arm/arch-sa1100/h3600_gpio.h540
-rw-r--r--include/asm-arm/arch-sa1100/hardware.h27
-rw-r--r--include/asm-arm/arch-sa1100/io.h9
-rw-r--r--include/asm-arm/arch-sa1100/irqs.h278
-rw-r--r--include/asm-arm/arch-sa1100/keyboard.h7
-rw-r--r--include/asm-arm/arch-sa1100/pcmcia.h70
-rw-r--r--include/asm-arm/arch-sa1100/shannon.h43
-rw-r--r--include/asm-arm/arch-sa1100/system3.h113
-rw-r--r--include/asm-arm/arch-sa1100/time.h33
-rw-r--r--include/asm-arm/arch-shark/io.h6
-rw-r--r--include/asm-arm/arch-shark/irq.h114
-rw-r--r--include/asm-arm/arch-shark/time.h2
-rw-r--r--include/asm-arm/arch-tbox/irq.h37
-rw-r--r--include/asm-arm/arch-tbox/time.h9
-rw-r--r--include/asm-arm/arch-tbox/vmalloc.h2
-rw-r--r--include/asm-arm/assembler.h13
-rw-r--r--include/asm-arm/bitops.h281
-rw-r--r--include/asm-arm/checksum.h61
-rw-r--r--include/asm-arm/cpu-multi32.h8
-rw-r--r--include/asm-arm/cpu-single.h59
-rw-r--r--include/asm-arm/hardware/clps7111.h3
-rw-r--r--include/asm-arm/hardware/cs89712.h49
-rw-r--r--include/asm-arm/hardware/ep7212.h21
-rw-r--r--include/asm-arm/hardware/ioc.h4
-rw-r--r--include/asm-arm/hardware/iomd.h8
-rw-r--r--include/asm-arm/hardware/linkup-l1110.h48
-rw-r--r--include/asm-arm/hardware/sa1111.h678
-rw-r--r--include/asm-arm/hdreg.h2
-rw-r--r--include/asm-arm/io.h259
-rw-r--r--include/asm-arm/mach/pci.h56
-rw-r--r--include/asm-arm/mach/serial_sa1100.h3
-rw-r--r--include/asm-arm/page.h18
-rw-r--r--include/asm-arm/pci.h43
-rw-r--r--include/asm-arm/pgtable.h8
-rw-r--r--include/asm-arm/proc-armo/ptrace.h32
-rw-r--r--include/asm-arm/proc-armv/assembler.h2
-rw-r--r--include/asm-arm/proc-armv/cache.h129
-rw-r--r--include/asm-arm/proc-armv/pgalloc.h17
-rw-r--r--include/asm-arm/proc-armv/pgtable.h140
-rw-r--r--include/asm-arm/proc-armv/ptrace.h76
-rw-r--r--include/asm-arm/proc-armv/uaccess.h21
-rw-r--r--include/asm-arm/proc-fns.h64
-rw-r--r--include/asm-arm/processor.h7
-rw-r--r--include/asm-arm/scatterlist.h5
-rw-r--r--include/asm-arm/types.h1
-rw-r--r--include/asm-arm/unaligned.h113
-rw-r--r--include/asm-arm/unistd.h7
-rw-r--r--include/asm-arm/vt.h8
-rw-r--r--include/asm-sparc/keyboard.h3
-rw-r--r--include/asm-sparc64/elf.h21
-rw-r--r--include/asm-sparc64/keyboard.h3
-rw-r--r--include/linux/acct.h2
-rw-r--r--include/linux/amigaffs.h3
-rw-r--r--include/linux/bio.h1
-rw-r--r--include/linux/blk.h88
-rw-r--r--include/linux/blkdev.h37
-rw-r--r--include/linux/cdrom.h2
-rw-r--r--include/linux/console.h1
-rw-r--r--include/linux/devfs_fs.h2
-rw-r--r--include/linux/devfs_fs_kernel.h27
-rw-r--r--include/linux/elevator.h79
-rw-r--r--include/linux/ext2_fs_sb.h1
-rw-r--r--include/linux/file.h2
-rw-r--r--include/linux/fs.h17
-rw-r--r--include/linux/genhd.h4
-rw-r--r--include/linux/gfp.h81
-rw-r--r--include/linux/hfs_sysdep.h2
-rw-r--r--include/linux/ide.h16
-rw-r--r--include/linux/interrupt.h2
-rw-r--r--include/linux/isdn.h1
-rw-r--r--include/linux/kbd_kern.h1
-rw-r--r--include/linux/kdev_t.h92
-rw-r--r--include/linux/kernel.h10
-rw-r--r--include/linux/keyboard.h1
-rw-r--r--include/linux/linkage.h10
-rw-r--r--include/linux/mm.h78
-rw-r--r--include/linux/msdos_fs.h4
-rw-r--r--include/linux/namespace.h42
-rw-r--r--include/linux/nfsd/nfsfh.h26
-rw-r--r--include/linux/parport.h1
-rw-r--r--include/linux/pci_ids.h9
-rw-r--r--include/linux/proc_fs.h2
-rw-r--r--include/linux/quota.h1
-rw-r--r--include/linux/quotaops.h6
-rw-r--r--include/linux/raid/md_k.h6
-rw-r--r--include/linux/reiserfs_fs.h15
-rw-r--r--include/linux/sched.h24
-rw-r--r--include/linux/shm.h1
-rw-r--r--include/linux/slab.h5
-rw-r--r--include/linux/sunrpc/clnt.h1
-rw-r--r--include/linux/threads.h2
-rw-r--r--include/linux/tpqic02.h6
-rw-r--r--include/linux/usb.h169
-rw-r--r--include/linux/usbdevice_fs.h11
-rw-r--r--include/linux/wait.h112
-rw-r--r--include/scsi/scsicam.h3
-rw-r--r--init/do_mounts.c108
-rw-r--r--ipc/shm.c1
-rw-r--r--kernel/acct.c4
-rw-r--r--kernel/device.c10
-rw-r--r--kernel/exit.c9
-rw-r--r--kernel/fork.c22
-rw-r--r--kernel/kmod.c8
-rw-r--r--kernel/ksyms.c3
-rw-r--r--kernel/pm.c1
-rw-r--r--kernel/sched.c168
-rw-r--r--kernel/sysctl.c1
-rw-r--r--kernel/timer.c5
-rw-r--r--mm/filemap.c4
-rw-r--r--mm/highmem.c12
-rw-r--r--mm/mempool.c1
-rw-r--r--mm/mprotect.c1
-rw-r--r--mm/mremap.c1
-rw-r--r--mm/oom_kill.c3
-rw-r--r--mm/page_io.c4
-rw-r--r--mm/slab.c2
-rw-r--r--mm/swapfile.c28
-rw-r--r--mm/vmscan.c1
-rw-r--r--net/802/fddi.c1
-rw-r--r--net/802/hippi.c1
-rw-r--r--net/8021q/vlanproc.c1
-rw-r--r--net/atm/resources.c1
-rw-r--r--net/decnet/af_decnet.c1
-rw-r--r--net/decnet/dn_nsp_in.c1
-rw-r--r--net/decnet/dn_nsp_out.c1
-rw-r--r--net/ipv4/ipconfig.c6
-rw-r--r--net/irda/ircomm/ircomm_tty.c5
-rw-r--r--net/irda/ircomm/ircomm_tty_ioctl.c1
-rw-r--r--net/irda/irda_device.c1
-rw-r--r--net/irda/irsyms.c1
-rw-r--r--net/irda/irsysctl.c1
-rw-r--r--net/netlink/netlink_dev.c12
-rw-r--r--net/rose/af_rose.c1
-rw-r--r--net/rose/rose_dev.c1
-rw-r--r--net/rose/rose_in.c1
-rw-r--r--net/rose/rose_link.c1
-rw-r--r--net/rose/rose_out.c1
-rw-r--r--net/rose/rose_route.c1
-rw-r--r--net/rose/rose_subr.c1
-rw-r--r--net/rose/rose_timer.c1
-rw-r--r--net/sunrpc/auth_null.c2
-rw-r--r--net/sunrpc/auth_unix.c2
-rw-r--r--net/x25/af_x25.c1
-rw-r--r--net/x25/x25_dev.c1
-rw-r--r--net/x25/x25_facilities.c1
-rw-r--r--net/x25/x25_in.c1
-rw-r--r--net/x25/x25_link.c1
-rw-r--r--net/x25/x25_out.c1
-rw-r--r--net/x25/x25_route.c1
-rw-r--r--net/x25/x25_subr.c1
-rw-r--r--net/x25/x25_timer.c1
1049 files changed, 42463 insertions, 14386 deletions
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index aeca339e8..d70d37324 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -12515,6 +12515,30 @@ CONFIG_USB_LONG_TIMEOUT
If you have an MGE Ellipse UPS, or you see timeouts in HID
transactions, say Y; otherwise say N.
+EHCI (USB 2.0) support
+CONFIG_USB_EHCI_HCD
+ The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
+ "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
+ If your USB host controller supports USB 2.0, you will likely want to
+ configure this Host Controller Driver. At this writing, the primary
+ implementation of EHCI is a chip from NEC, widely available in add-on
+ PCI cards, but implementations are in the works from other vendors
+ including Intel and Philips. Motherboard support is appearing.
+
+ EHCI controllers are packaged with "companion" host controllers (OHCI
+ or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports
+ will connect to EHCI if it the device is high speed, otherwise they
+ connect to a companion controller. If you configure EHCI, you should
+ probably configure the OHCI (for NEC and some other vendors) USB Host
+ Controller Driver too.
+
+ You may want to read <file:Documentation/usb/ehci.txt>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ehci-hcd.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
UHCI (Intel PIIX4, VIA, ...) support
CONFIG_USB_UHCI
The Universal Host Controller Interface is a standard by Intel for
@@ -12815,6 +12839,17 @@ CONFIG_USB_SERIAL_VISOR
The module will be called visor.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
+USB Compaq iPAQ Driver
+CONFIG_USB_SERIAL_IPAQ
+ Say Y here if you want to connect to your Compaq iPAQ running
+ Windows CE 3.0 using a USB autosync cable. For information on using
+ the driver, read <file:Documentation/usb/usb-serial.txt>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called ipaq.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
USB IR Dongle Serial Driver
CONFIG_USB_SERIAL_IR
Say Y here if you want to enable simple serial support for USB IrDA
@@ -13035,6 +13070,22 @@ CONFIG_USB_SERIAL_EDGEPORT
The module will be called io_edgeport.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
+USB PalmConnect (and other KL5KUSB105-based) Single Port Serial Driver
+CONFIG_USB_SERIAL_KLSI
+ Say Y here if you want to use a KL5KUSB105 - based single port
+ serial adapter. The most widely known -- and currently the only
+ tested -- device in this category is the PalmConnect USB Serial
+ adapter sold by Palm Inc. for use with their Palm III and Palm V
+ series PDAs.
+
+ Please read <file:Documentation/usb/usb-serial.txt> for more
+ information.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called kl5kusb105.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>.
+
USB Serial Converter verbose debug
CONFIG_USB_SERIAL_DEBUG
Say Y here if you want verbose debug messages from the USB Serial
@@ -13141,6 +13192,54 @@ CONFIG_USB_PWC
The module will be called pwc.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
+USB SE401 Camera support
+CONFIG_USB_SE401
+ Say Y here if you want to connect this type of camera to your
+ computer's USB port. See <file:Documentation/usb/se401.txt> for more
+ information and for a list of supported cameras.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called se401.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+USB STV680 (Pencam) Camera support
+CONFIG_USB_STV680
+ Say Y here if you want to connect this type of camera to your
+ computer's USB port. This includes the Pencam line of cameras.
+ See <file:Documentation/usb/stv680.txt> for more information and for
+ a list of supported cameras.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called stv680.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+Vicam
+CONFIG_USB_VICAM
+ Say Y here if you have 3com homeconnect camera (vicam).
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called vicam.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+
Pegasus/Pegasus II based USB-Ethernet device support
CONFIG_USB_PEGASUS
Say Y here if you know you have Pegasus or Pegasus II based adapter.
@@ -16935,22 +17034,6 @@ CONFIG_PM
will issue the hlt instruction if nothing is to be done, thereby
sending the processor to sleep and saving power.
-USB SE401 Camera support
-CONFIG_USB_SE401
- Say Y here if you want to connect this type of camera to your
- computer's USB port. See <file:Documentation/usb/se401.txt> for more
- information and for a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
- This code is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called se401.o. If you want to compile it as a
- module, say M here and read <file:Documentation/modules.txt>.
-
ACPI support
CONFIG_ACPI
ACPI/OSPM support for Linux is currently under development. As such,
diff --git a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog
index 0a8efe9bd..407a684e9 100644
--- a/Documentation/filesystems/devfs/ChangeLog
+++ b/Documentation/filesystems/devfs/ChangeLog
@@ -1794,3 +1794,72 @@ Changes for patch v198
- Use "existing" directory in <_devfs_make_parent_for_leaf>
- Use slab cache rather than fixed buffer for devfsd events
+===============================================================================
+Changes for patch v199
+
+- Removed obsolete usage of DEVFS_FL_NO_PERSISTENCE
+
+- Send DEVFSD_NOTIFY_REGISTERED events in <devfs_mk_dir>
+
+- Fixed locking bug in <devfs_d_revalidate_wait> due to typo
+
+- Do not send CREATE, CHANGE, ASYNC_OPEN or DELETE events from devfsd
+ or children
+===============================================================================
+Changes for patch v200
+
+- Ported to kernel 2.5.1-pre2
+===============================================================================
+Changes for patch v201
+
+- Fixed bug in <devfsd_read>: was dereferencing freed pointer
+===============================================================================
+Changes for patch v202
+
+- Fixed bug in <devfsd_close>: was dereferencing freed pointer
+
+- Added process group check for devfsd privileges
+===============================================================================
+Changes for patch v203
+
+- Use SLAB_ATOMIC in <devfsd_notify_de> from <devfs_d_delete>
+===============================================================================
+Changes for patch v204
+
+- Removed long obsolete rc.devfs
+
+- Return old entry in <devfs_mk_dir> for 2.4.x kernels
+
+- Updated README from master HTML file
+
+- Increment refcount on module in <check_disc_changed>
+
+- Created <devfs_get_handle> and exported <devfs_put>
+
+- Increment refcount on module in <devfs_get_ops>
+
+- Created <devfs_put_ops> and used where needed to fix races
+
+- Added clarifying comments in response to preliminary EMC code review
+
+- Added poisoning to <devfs_put>
+
+- Improved debugging messages
+
+- Fixed unregister bugs in drivers/md/lvm-fs.c
+===============================================================================
+Changes for patch v205
+
+- Corrected (made useful) debugging message in <unregister>
+
+- Moved <kmem_cache_create> in <mount_devfs_fs> to <init_devfs_fs>
+
+- Fixed drivers/md/lvm-fs.c to create "lvm" entry
+
+- Added magic number to guard against scribbling drivers
+
+- Only return old entry in <devfs_mk_dir> if a directory
+
+- Defined macros for error and debug messages
+
+- Updated README from master HTML file
diff --git a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README
index 7149cbcbb..a34fcd321 100644
--- a/Documentation/filesystems/devfs/README
+++ b/Documentation/filesystems/devfs/README
@@ -3,7 +3,7 @@ Devfs (Device File System) FAQ
Linux Devfs (Device File System) FAQ
Richard Gooch
-9-NOV-2001
+21-DEC-2001
-----------------------------------------------------------------------------
@@ -66,6 +66,9 @@ Questions and Answers
Making things work
Alternatives to devfs
+What I don't like about devfs
+How to report bugs
+Strange kernel messages
Other resources
@@ -557,8 +560,10 @@ options.
Devfsd
OK, if you're reading this, I assume you want to play with
-devfs. First you need to compile devfsd, the device management daemon,
-available at
+devfs. First you should ensure that /usr/src/linux contains a
+recent kernel source tree. Then you need to compile devfsd, the device
+management daemon, available at
+
http://www.atnf.csiro.au/~rgooch/linux/.
Because the kernel has a naming scheme
which is quite different from the old naming scheme, you need to
@@ -1470,6 +1475,8 @@ Questions and Answers
Making things work
Alternatives to devfs
What I don't like about devfs
+How to report bugs
+Strange kernel messages
@@ -1734,6 +1741,93 @@ Devfs is bloatware
This is not even remotely true. As shown above,
both code and data size are quite modest.
+
+How to report bugs
+
+If you have (or think you have) a bug with devfs, please follow the
+steps below:
+
+
+
+please make sure you have the latest devfs patches applied. The
+latest kernel version might not have the latest devfs patches applied
+yet (Linus is very busy)
+
+
+save a copy of your complete kernel logs (preferably by
+using the dmesg programme) for later inclusion in your bug
+report. You may need to use the -s switch to increase the
+internal buffer size so you can capture all the boot messages
+
+
+try booting with devfs=dall passed to the kernel boot
+command line (read the documentation on your bootloader on how to do
+this), and save the result to a file. This may be quite verbose, and
+it may overflow the messages buffer, but try to get as much of it as
+you can
+
+
+if you get an Oops, run ksymoops to decode it so that the
+names of the offending functions are provided. A non-decoded Oops is
+pretty useless
+
+
+send a copy of your devfsd configuration file(s)
+
+send the bug report to me first.
+Don't expect that I will see it if you post it to the linux-kernel
+mailing list. Include all the information listed above, plus
+anything else that you think might be relevant. Put the string
+devfs somewhere in the subject line, so my mail filters mark
+it as urgent
+
+
+
+
+Here is a general guide on how to ask questions in a way that greatly
+improves your chances of getting a reply:
+
+http://www.tuxedo.org/~esr/faqs/smart-questions.html. If you have
+a bug to report, you should also read
+
+http://www.chiark.greenend.org.uk/~sgtatham/bugs.html.
+
+
+Strange kernel messages
+
+You may see devfs-related messages in your kernel logs. Below are some
+messages and what they mean (and what you should do about them, if
+anything).
+
+
+
+devfs_register(fred): could not append to parent, err: -17
+
+You need to check what the error code means, but usually 17 means
+EEXIST. This means that a driver attempted to create an entry
+fred in a directory, but there already was an entry with that
+name. This is often caused by flawed boot scripts which untar a bunch
+of inodes into /dev, as a way to restore permissions. This
+message is harmless, as the device nodes will still
+provide access to the driver (unless you use the devfs=only
+boot option, which is only for dedicated souls:-). If you want to get
+rid of these annoying messages, upgrade to devfsd-v1.3.20 and use the
+recommended RESTORE directive to restore permissions.
+
+
+devfs_mk_dir(bill): using old entry in dir: c1808724 ""
+
+This is similar to the message above, except that a driver attempted
+to create a directory named bill, and the parent directory
+has an entry with the same name. In this case, to ensure that drivers
+continue to work properly, the old entry is re-used and given to the
+driver. In 2.5 kernels, the driver is given a NULL entry, and thus,
+under rare circumstances, may not create the require device nodes.
+The solution is the same as above.
+
+
+
+
-----------------------------------------------------------------------------
diff --git a/Documentation/filesystems/devfs/rc.devfs b/Documentation/filesystems/devfs/rc.devfs
deleted file mode 100644
index 73bbb3ac2..000000000
--- a/Documentation/filesystems/devfs/rc.devfs
+++ /dev/null
@@ -1,104 +0,0 @@
-#! /bin/sh
-#
-# /etc/rc.d/rc.devfs
-#
-# Linux Boot Scripts by Richard Gooch <rgooch@atnf.csiro.au>
-# Copyright 1993-1999 under GNU Copyleft version 2.0. See /etc/rc for
-# copyright notice.
-#
-# Save and restore devfs ownerships and permissions
-#
-# Written by Richard Gooch 11-JAN-1998
-#
-# Updated by Richard Gooch 23-JAN-1998: Added "start" and "stop".
-#
-# Updated by Richard Gooch 5-AUG-1998: Robustness improvements by
-# Roderich Schupp.
-#
-# Updated by Richard Gooch 9-AUG-1998: Took account of change from
-# ".epoch" to ".devfsd".
-#
-# Updated by Richard Gooch 19-AUG-1998: Test and tty pattern patch
-# by Roderich Schupp.
-#
-# Updated by Richard Gooch 24-MAY-1999: Use sed instead of tr.
-#
-# Last updated by Richard Gooch 25-MAY-1999: Don't save /dev/log.
-#
-#
-# Usage: rc.devfs save|restore [savedir] [devfsdir]
-#
-# Note: "start" is a synonym for "restore" and "stop" is a synonym for "save".
-
-# Set VERBOSE to "no" if you would like a more quiet operation.
-VERBOSE=yes
-
-# Set TAROPTS to "v" or even "vv" to see which files get saved/restored.
-TAROPTS=
-
-option="$1"
-
-case "$option" in
- save|restore) ;;
- start) option=restore ;;
- stop) option=save ;;
- *) echo "No save or restore option given" ; exit 1 ;;
-esac
-
-if [ "$2" = "" ]; then
- savedir=/var/state
-else
- savedir=$2
-fi
-
-if [ ! -d $savedir ]; then
- echo "Directory: $savedir does not exist"
- exit 1
-fi
-
-if [ "$3" = "" ]; then
- if [ -d /devfs ]; then
- devfs=/devfs
- else
- devfs=/dev
- fi
-else
- devfs=$3
-fi
-
-grep devfs /proc/filesystems >/dev/null || exit 0
-
-if [ ! -d $devfs ]; then
- echo "Directory: $devfs does not exist"
- exit 1
-elif [ ! -c $devfs/.devfsd ]; then
- echo "Directory: $devfs is not the root of a devfs filesystem"
- exit 1
-fi
-
-savefile=`echo $devfs | sed 's*/*_*g'`
-tarfile=${savedir}/devfssave.${savefile}.tar.gz
-
-cd $devfs
-
-case "$option" in
- save)
- [ "$VERBOSE" != no ] && echo "Saving $devfs permissions..."
-
- # You might want to adjust the pattern below to control
- # which file's permissions will be saved.
- # The sample pattern exludes all virtual consoles
- # as well as old and new style pseudo terminals.
- files=`find * -noleaf -cnewer .devfsd \
- ! -regex 'tty[0-9]+\|vc/.*\|vcsa?[0-9]+\|vcc/.*\|[pt]ty[a-z][0-9a-f]\|pt[ms]/.*\|log' -print`
- rm -f $tarfile
- [ -n "$files" ] && tar cz${TAROPTS}f $tarfile $files
- ;;
-
- restore)
- [ "$VERBOSE" != no ] && echo "Restoring $devfs permissions..."
- [ -f $tarfile ] && tar xpz${TAROPTS}f $tarfile
- ;;
-esac
-
-exit 0
diff --git a/Documentation/usb/ehci.txt b/Documentation/usb/ehci.txt
new file mode 100644
index 000000000..205d412ae
--- /dev/null
+++ b/Documentation/usb/ehci.txt
@@ -0,0 +1,164 @@
+18-Dec-2001
+
+The EHCI driver is used to talk to high speed USB 2.0 devices using
+USB 2.0-capable host controller hardware. The USB 2.0 standard is
+compatible with the USB 1.1 standard. It defines three transfer speeds:
+
+ - "High Speed" 480 Mbit/sec (60 MByte/sec)
+ - "Full Speed" 12 Mbit/sec (1.5 MByte/sec)
+ - "Low Speed" 1.5 Mbit/sec
+
+USB 1.1 only addressed full speed and low speed. High speed devices
+can be used on USB 1.1 systems, but they slow down to USB 1.1 speeds.
+
+USB 1.1 devices may also be used on USB 2.0 systems. When plugged
+into an EHCI controller, they are given to a USB 1.1 "companion"
+controller, which is a OHCI or UHCI controller as normally used with
+such devices. When USB 1.1 devices plug into USB 2.0 hubs, they
+interact with the EHCI controller through a "Transaction Translator"
+(TT) in the hub, which turns low or full speed transactions into
+high speed "split transactions" that don't waste transfer bandwidth.
+
+At this writing, high speed devices are finally beginning to appear.
+While usb-storage devices have been available for some time (working
+quite speedily on the 2.4 version of this driver), hubs have only
+very recently become available.
+
+Note that USB 2.0 support involves more than just EHCI. It requires
+other changes to the Linux-USB core APIs, including the hub driver,
+but those changes haven't needed to really change the basic "usbcore"
+APIs exposed to USB device drivers.
+
+- David Brownell
+ <dbrownell@users.sourceforge.net>
+
+
+FUNCTIONALITY
+
+This driver is regularly tested on x86 hardware, and has also been
+used on PPC hardware so big/little endianneess issues should be gone.
+It's believed to do all the right PCI magic so that I/O works even on
+systems with interesting DMA mapping issues.
+
+At this writing the driver should comfortably handle all control and bulk
+transfers, including requests to USB 1.1 devices through transaction
+translators (TTs) in USB 2.0 hubs. However, there some situations where
+the hub driver needs to clear TT error state, which it doesn't yet do.
+
+Interrupt transfer support is newly functional and not yet as robust as
+control and bulk traffic. As yet there is no support for split transaction
+scheduling for interrupt transfers, which means among other things that
+connecting USB 1.1 hubs, keyboards, and mice to USB 2.0 hubs won't work.
+Connect them to USB 1.1 hubs, or to a root hub.
+
+Isochronous (ISO) transfer support is not yet working. No production
+high speed devices are available which would need it (though high quality
+webcams are in the works!). Note that split transaction support for ISO
+transfers can't share much code with the code for high speed ISO transfers,
+since EHCI represents these with a different data structure.
+
+The EHCI root hub code should hand off USB 1.1 devices to its companion
+controller. This driver doesn't need to know anything about those
+drivers; a OHCI or UHCI driver that works already doesn't need to change
+just because the EHCI driver is also present.
+
+There are some issues with power management; suspend/resume doesn't
+behave quite right at the moment.
+
+
+USE BY
+
+Assuming you have an EHCI controller (on a PCI card or motherboard)
+and have compiled this driver as a module, load this like:
+
+ # modprobe ehci-hcd
+
+and remove it by:
+
+ # rmmod ehci-hcd
+
+You should also have a driver for a "companion controller", such as
+"ohci-hcd", "usb-ohci", "usb-uhci", or "uhci". In case of any trouble
+with the EHCI driver, remove its module and then the driver for that
+companion controller will take over (at lower speed) all the devices
+that were previously handled by the EHCI driver.
+
+Module parameters (pass to "modprobe") include:
+
+ log2_irq_thresh (default 0):
+ Log2 of default interrupt delay, in microframes. The default
+ value is 0, indicating 1 microframe (125 usec). Maximum value
+ is 6, indicating 2^6 = 64 microframes. This controls how often
+ the EHCI controller can issue interrupts.
+
+The EHCI interrupt handler just acknowledges interrupts and schedules
+a tasklet to handle whatever needs handling. That keeps latencies low,
+no matter how often interrupts are issued.
+
+Device drivers shouldn't care whether they're running over EHCI or not,
+but they may want to check for "usb_device->speed == USB_SPEED_HIGH".
+High speed devices can do things that full speed (or low speed) ones
+can't, such as "high bandwidth" periodic (interrupt or ISO) transfers.
+
+
+PERFORMANCE
+
+USB 2.0 throughput is gated by two main factors: how fast the host
+controller can process requests, and how fast devices can respond to
+them. The 480 Mbit/sec "raw transfer rate" is obeyed by all devices,
+but aggregate throughput is also affected by issues like delays between
+individual high speed packets, driver intelligence, and of course the
+overall system load. Latency is also a performance concern.
+
+Bulk transfers are most often used where throughput is an issue. It's
+good to keep in mind that bulk transfers are always in 512 byte packets,
+and at most 13 of those fit into one USB 2.0 microframe. Eight USB 2.0
+microframes fit in a USB 1.1 frame; a microframe is 1 msec/8 = 125 usec.
+
+Hardware Performance
+
+At this writing, individual USB 2.0 devices tend to max out at around
+20 MByte/sec transfer rates. This is of course subject to change;
+and some devices now go faster, while others go slower.
+
+The NEC implementation of EHCI seems to have a hardware bottleneck
+at around 28 MByte/sec aggregate transfer rate. While this is clearly
+enough for a single device at 20 MByte/sec, putting three such devices
+onto one bus does not get you 60 MByte/sec. The issue appears to be
+that the controller hardware won't do concurrent USB and PCI access,
+so that it's only trying six (or maybe seven) USB transactions each
+microframe rather than thirteen. (Seems like a reasonable trade off
+for a product that beat all the others to market by over a year!)
+It's expected that newer implementations will better this, throwing
+more silicon real estate at the problem so that new motherboard chip
+sets will get closer to that 60 MByte/sec target.
+
+There's a minimum latency of one microframe (125 usec) for the host
+to receive interrupts from the EHCI controller indicating completion
+of requests. That latency is tunable; there's a module option. By
+default ehci-hcd driver uses the minimum latency, which means that if
+you issue a control or bulk request you can often expect to learn that
+it completed in less than 250 usec (depending on transfer size).
+
+Software Performance
+
+To get even 20 MByte/sec transfer rates, Linux-USB device drivers will
+need to keep the EHCI queue full. That means issuing large requests,
+or using bulk queuing if a series of small requests needs to be issued.
+When drivers don't do that, their performance results will show it.
+
+In typical situations, a usb_bulk_msg() loop writing out 4 KB chunks is
+going to waste more than half the USB 2.0 bandwidth. Delays between the
+I/O completion and the driver issuing the next request will take longer
+than the I/O. If that same loop used 16 KB chunks, it'd be better; a
+sequence of 128 KB chunks would waste a lot less.
+
+But rather than depending on such large I/O buffers to make synchronous
+I/O be efficient, it's better to just queue all several (bulk) requests
+to the HC, and wait for them all to complete (or be canceled on error).
+Such URB queuing should work with all the USB 1.1 HC drivers too.
+
+TBD: Interrupt and ISO transfer performance issues. Those periodic
+transfers are fully scheduled, so the main issue is likely to be how
+to trigger "high bandwidth" modes.
+
diff --git a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt
index bc9cad2ab..519bcf8bc 100644
--- a/Documentation/usb/ov511.txt
+++ b/Documentation/usb/ov511.txt
@@ -8,11 +8,11 @@ Homepage: http://alpha.dyndns.org/ov511
INTRODUCTION:
This is a driver for the OV511, a USB-only chip used in many "webcam" devices.
-Any camera using the OV511/OV511+ and the OV7610/20/20AE CCD should work. It
+Any camera using the OV511/OV511+ and the OV6620/OV7610/20/20AE should work.
+Video capture devices that use the Philips SAA7111A decoder also work. It
supports streaming and capture of color or monochrome video via the Video4Linux
-API. Most V4L apps are compatible with it, but a few video-conferencing programs
-do not work yet. The following resolutions are supported: 640x480, 448x336,
-384x288, 352x288, and 320x240.
+API. Most V4L apps are compatible with it. Most resolutions with a width and
+height that are a multiple of 8 are supported.
If you need more information, please visit the OV511 homepage at the above URL.
@@ -27,22 +27,25 @@ WHAT YOU NEED:
HOW TO USE IT:
+Note: These are simplified instructions. For complete instructions see:
+ http://alpha.dyndns.org/ov511/install.html
+
You must have first compiled USB support, support for your specific USB host
controller (UHCI or OHCI), and Video4Linux support for your kernel (I recommend
-making them modules.)
+making them modules.) Make sure "Enforce bandwidth allocation" is NOT enabled.
-Next, (as root) from your appropriate modules directory (lib/modules/2.3.XX):
+Next, (as root):
- insmod usb/usbcore.o
- insmod usb/usb-uhci.o <OR> insmod usb/ohci-hcd.o
- insmod misc/videodev.o
- insmod usb/ov511.o
+ modprobe usbcore
+ modprobe usb-uhci <OR> modprobe usb-ohci
+ modprobe videodev
+ modprobe ov511
If it is not already there (it usually is), create the video device:
- mknod /dev/video c 81 0
+ mknod /dev/video0 c 81 0
-Sometimes /dev/video is a symlink to /dev/video0
+Optionally, symlink /dev/video to /dev/video0
You will have to set permissions on this device to allow you to read/write
from it:
@@ -55,39 +58,40 @@ at 640x480.
[Using vidcat:]
- vidcat -s 640x480 > test.jpg
+ vidcat -s 640x480 -p c > test.jpg
xview test.jpg
[Using xawtv:]
-You must make some modifications to the source and compile it before you use it.
-(Note: this may not be applicable to versions other than 3.06)
-
-In src/Xawtv.ad, change xawtv.tv.width to 640 and xawtv.tv.height to 480. Next,
-in src/grab-v4l.c, change SYNC_TIMEOUT from 1 to 2. Then, from the main xawtv
-directory:
+From the main xawtv directory:
make clean
./configure
make
make install
-Now you should be able to run xawtv. Right click for the options dialog. If
-you get a scrambled image it is likely that you made a mistake in Xawtv.ad.
-Try setting the size to 320x240 if all else fails.
+Now you should be able to run xawtv. Right click for the options dialog.
MODULE PARAMETERS:
You can set these with: insmod ov511 NAME=VALUE
There is currently no way to set these on a per-camera basis.
- NAME: autoadjust
- TYPE: integer (boolean)
+ NAME: autobright
+ TYPE: integer (Boolean)
DEFAULT: 1
- DESC: The camera normally adjusts exposure, gain, and hue automatically. This
- can be set to 0 to disable this automatic adjustment. Note that there is
- currently no way to set these parameters manually once autoadjust is
- disabled.
+ DESC: Brightness is normally under automatic control and can't be set
+ manually by the video app. Set to 0 for manual control.
+
+ NAME: autogain
+ TYPE: integer (Boolean)
+ DEFAULT: 1
+ DESC: Auto Gain Control enable. This feature is not yet implemented.
+
+ NAME: autoexp
+ TYPE: integer (Boolean)
+ DEFAULT: 1
+ DESC: Auto Exposure Control enable. This feature is not yet implemented.
NAME: debug
TYPE: integer (0-6)
@@ -102,49 +106,23 @@ MODULE PARAMETERS:
5=highly repetitive mesgs
NAME: fix_rgb_offset
- TYPE: integer (boolean)
+ TYPE: integer (Boolean)
DEFAULT: 0
DESC: Some people have reported that the blue component of the image is one
or so lines higher than the red component. This is only apparent in
images with white objects on black backgrounds at 640x480. Setting this
- to 1 will realign the color planes correctly. NOTE: This is still
- experimental and very buggy. You will likely need a fast (500 MHz) CPU.
+ to 1 will realign the color planes correctly. NOTE: You will likely
+ need a fast (500 MHz) CPU.
NAME: snapshot
- TYPE: integer (boolean)
+ TYPE: integer (Boolean)
DEFAULT: 0
- DESC: Set to 1 to enable snapshot mode. read() will block until the snapshot
- button is pressed. Note that this does not yet work with most apps,
- including xawtv and vidcat. NOTE: See the section "TODO" for more info.
-
- NAME: sensor
- TYPE: integer ([0, 1, 3])
- DEFAULT: [varies]
- DESC: If you know that your camera sensor is not detected correctly, set this
- parameter. This is a global option for all attached OV511 cameras. You
- will probably never need to set this, but if you do, valid values are:
- 0 for OV7620
- 1 for OV7620AE
- 3 for OV7610
-
- NAME: i2c_detect_tries
- TYPE: integer (don't set it insanely high!)
- DEFAULT: 5
- DESC: This is the number of times the driver will try to sync and detect the
- internal i2c bus (which connects the OV511 and sensor). If you are
- getting intermittent detection failures ("Failed to read sensor ID...")
- you should increase this by a modest amount. If setting it to 20 or so
- doesn't fix things, look elsewhere for the cause of the problem.
-
- NAME: aperture
- TYPE: integer (0 - 15)
- DEFAULT: [varies by sensor]
- DESC: For legal values, see the OV7610/7620 specs under register Common F.
- This setting affects the upper nybble of that reg (bits 4-7). This is
- for if you want to play with the camera's pixel saturation.
-
- NAME: force_rgb
- TYPE: integer (boolean)
+ DESC: Set to 1 to enable snapshot mode. read()/VIDIOCSYNC will block until
+ the snapshot button is pressed. Note: enabling this mode disables
+ /proc/video/ov511/<minor#>/button
+
+ NAME: force_rgb (Deprecated; may be removed in the future)
+ TYPE: integer (Boolean)
DEFAULT: 0
DESC: Force image to be read in RGB instead of BGR. This option allow
programs that expect RGB data (e.g. gqcam) to work with this driver. If
@@ -169,60 +147,179 @@ MODULE PARAMETERS:
both OV511 and OV511+ cameras, trial-and-error may be necessary for
finding the optimum setting.
- NAME: retry_sync
- TYPE: boolean
+ NAME: compress
+ TYPE: integer (Boolean)
+ DEFAULT: 0
+ DESC: Set this to 1 to turn on the camera's compression engine. This can
+ potentially increase the frame rate at the expense of quality, if you
+ have a fast CPU. You must load the proper compression module for your
+ camera before starting your application (ov511_decomp or ov518_decomp).
+
+ NAME: testpat
+ TYPE: integer (Boolean)
DEFAULT: 0
- DESC: Prevent apps from timing out if frame is not done in time. This is
- useful if you are having problems with Xawtv getting "stuck" on a frame
- when your system is under heavy load.
+ DESC: This configures the camera's sensor to transmit a colored test-pattern
+ instead of an image. This does not work correctly yet.
- NAME: sensor_gbr
- TYPE: boolean
+ NAME: sensor_gbr (*** TEMPORARILY DISABLED ***)
+ TYPE: integer (Boolean)
DEFAULT: 0
DESC: This makes the sensor output GBR422 instead of YUV420. This saves the
driver the trouble of converting YUV to RGB, but it currently does not
work very well (the colors are not quite right)
+ NAME: dumppix
+ TYPE: integer (0-2)
+ DEFAULT: 0
+ DESC: Dumps raw pixel data and skips post-processing and format conversion.
+ It is for debugging purposes only. Options are:
+ 0: Disable (default)
+ 1: Dump raw data from camera, excluding headers and trailers
+ 2: Dumps data exactly as received from camera
+
+ NAME: led
+ TYPE: integer (0-2)
+ DEFAULT: 1 (Always on)
+ DESC: Controls whether the LED (the little light) on the front of the camera
+ is always off (0), always on (1), or only on when driver is open (2).
+ This is only supported with the OV511+ chipset, and even then only on
+ some cameras (ones that actually have the LED wired to the control pin,
+ and not just hardwired to be on all the time).
+
+ NAME: dump_bridge
+ TYPE: integer (Boolean)
+ DEFAULT: 0
+ DESC: Dumps the bridge (OV511[+] or OV518[+]) register values to the system
+ log. Only useful for serious debugging/development purposes.
+
+ NAME: dump_sensor
+ TYPE: integer (Boolean)
+ DEFAULT: 0
+ DESC: Dumps the sensor register values to the system log. Only useful for
+ serious debugging/development purposes.
+
+ NAME: printph
+ TYPE: integer (Boolean)
+ DEFAULT: 0
+ DESC: Setting this to 1 will dump the first 12 bytes of each isoc frame. This
+ is only useful if you are trying to debug problems with the isoc data
+ stream (i.e.: camera initializes, but vidcat hangs until Ctrl-C). Be
+ warned that this dumps a large number of messages to your kernel log.
+
+ NAME: phy, phuv, pvy, pvuv, qhy, qhuv, qvy, qvuv
+ TYPE: integer (0-63 for phy and phuv, 0-255 for rest)
+ DEFAULT: OV511 default values
+ DESC: These are registers 70h - 77h of the OV511, which control the
+ prediction ranges and quantization thresholds of the compressor, for
+ the Y and UV channels in the horizontal and vertical directions. See
+ the OV511 or OV511+ data sheet for more detailed descriptions. These
+ normally do not need to be changed.
+
+ NAME: lightfreq
+ TYPE: integer (0, 50, or 60)
+ DEFAULT: 0 (use sensor default)
+ DESC: Sets the sensor to match your lighting frequency. This can reduce the
+ appearance of "banding", i.e. horizontal lines or waves of light and
+ dark that are often caused by artificial lighting. Valid values are:
+ 0 - Use default (depends on sensor, most likely 60 Hz)
+ 50 - For European and Asian 50 Hz power
+ 60 - For American 60 Hz power
+
+ NAME: bandingfilter
+ TYPE: integer (Boolean)
+ DEFAULT: 0 (off)
+ DESC: Enables the sensor´s banding filter exposure algorithm. This reduces
+ or stabilizes the "banding" caused by some artificial light sources
+ (especially fluorescent). You might have to set lightfreq correctly for
+ this to work right. As an added bonus, this sometimes makes it
+ possible to capture your monitor´s output.
+
+ NAME: fastset
+ TYPE: integer (Boolean)
+ DEFAULT: 0 (off)
+ DESC: Allows picture settings (brightness, contrast, color, and hue) to take
+ effect immediately, even in the middle of a frame. This reduces the
+ time to change settings, but can ruin frames during the change. Only
+ affects OmniVision sensors.
+
+ NAME: force_palette
+ TYPE: integer (Boolean)
+ DEFAULT: 0 (off)
+ DESC: Forces the palette (color format) to a specific value. If an
+ application requests a different palette, it will be rejected, thereby
+ forcing it to try others until it succeeds. This is useful for forcing
+ greyscale mode with a color camera, for example. Supported modes are:
+ 0 (Allows all the following formats)
+ 1 VIDEO_PALETTE_GREY (Linear greyscale)
+ 3 VIDEO_PALETTE_RGB565 (565 16 bit RGB)
+ 4 VIDEO_PALETTE_RGB24 (24bit RGB)
+ 7 VIDEO_PALETTE_YUV422 (YUV422 capture)
+ 8 VIDEO_PALETTE_YUYV (YUV422 capture; same as 7)
+ 10 VIDEO_PALETTE_YUV420 (YUV 4:2:0 Planar)
+ 13 VIDEO_PALETTE_YUV422P (YUV 4:2:2 Planar)
+ 15 VIDEO_PALETTE_YUV420P (YUV 4:2:0 Planar, same as 10)
+
+ NAME: tuner
+ TYPE: integer
+ DEFAULT: -1 (autodetect)
+ DESC: This sets the exact type of the tuner module in a device. This is set
+ automatically based on the custom ID of the OV511 device. In cases
+ where this fails, you can override this auto-detection. Please see
+ linux/drivers/media/video/tuner.h for a complete list.
+
+ NAME: backlight
+ TYPE: integer (Boolean)
+ DEFAULT: 0 (off)
+ DESC: Setting this flag changes the exposure algorithm for OmniVision sensors
+ such that objects in the camera's view (i.e. your head) can be clearly
+ seen when they are illuminated from behind. It reduces or eliminates
+ the sensor's auto-exposure function, so it should only be used when
+ needed. Additionally, it is only supported with the OV6620 and OV7620.
+
+ NAME: unit_video
+ TYPE: Up to 16 comma-separated integers
+ DEFAULT: 0,0,0... (automatically assign the next available minor(s))
+ DESC: You can specify up to 16 minor numbers to be assigned to ov511 devices.
+ For example, "unit_video=1,3" will make the driver use /dev/video1 and
+ /dev/video3 for the first two devices it detects. Additional devices
+ will be assigned automatically starting at the first available device
+ node (/dev/video0 in this case). Note that you cannot specify 0 as a
+ minor number. This feature requires kernel version 2.4.5 or higher.
+
+ NAME: remove_zeros
+ TYPE: integer (Boolean)
+ DEFAULT: 0 (do not skip any incoming data)
+ DESC: Setting this to 1 will remove zero-padding from incoming data. This
+ will compensate for the blocks of corruption that can appear when the
+ camera cannot keep up with the speed of the USB bus (eg. at low frame
+ resolutions). This feature is always enabled when compression is on.
+
WORKING FEATURES:
- o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, and 320x240
- o RGB24, RGB565, YUV420, YUV422, YUYV, and YUV422P color
- o Monochrome
+ o Color streaming/capture at most widths and heights that are multiples of 8.
+ o RGB24, RGB565, YUV420/YUV420P, YUV422/YUYV, and YUV422P color
+ o Monochrome (use force_palette=1 to enable)
o Setting/getting of saturation, contrast, brightness, and hue (only some of
them work the OV7620 and OV7620AE)
o /proc status reporting
+ o SAA7111A video capture support at 320x240 and 640x480
+ o Compression support
EXPERIMENTAL FEATURES:
- o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and
- corrupted frames. If you have a very fast CPU, you can try it.
- o Snapshot mode (only works with some read() based apps; see below for more)
- o OV6620 sensor support
- o GBR422 parsing
- o 160x120
-
-TODO:
- o Fix the noise / grainy image problem.
- o Get compression working. It would be a nice addition as it improves
- frame rate quite a bit. OmniVision wouldn't tell me how the algorithm works,
- so we can't really work on that yet. Please kindly inform OmniVision that you
- would like them to release their specifications to the Linux community.
- o YUV422
- o Fix fixFrameRGBoffset(). It is not stable yet with streaming video.
- o V4L2 support (Probably not until it goes into the kernel)
- o Get rid of the memory management functions (put them in videodev.c??)
- o Setting of contrast and brightness not working with 7620/7620AE
- o Driver/camera state save/restore for when USB supports suspend/resume
- o Unstable on SMP systems
- o OV7620/OV6620 experience frame corruption with moving objects
- o OV6620 is too dark
- o 176x144 support
- o Driver sometimes hangs upon close() with OHCI
- o The image should always be written properly to the mmap'ed buffer as long as
- the requested image size is at least the minimum size. This will likely
- require a rewrite of all the parsing code.
+ o OV6630 sensor support
+ o Banding filter
+ o SMP compatibility
+
+TO-DO:
+ o V4L2 support (This will be done after the next kernel patch release)
+ o Setting of hue not working with OV7620
+ o Setting of contrast and hue not working with OV7620AE
+ o OV8600 sensor support (Not used in anything yet)
+ o OV518/OV518+ support (all that's needed is the decompressor)
+ o cams >= 3 not working
HOW TO CONTACT ME:
-You can email me at mwm@i.am . Please prefix the subject line
+You can email me at mmcclell@bigfoot.com . Please prefix the subject line
with "OV511: " so that I am certain to notice your message.
CREDITS:
@@ -232,3 +329,4 @@ Randy Dunlap, and others. Big thanks to them for their pioneering work on that
and the USB stack. Thanks to Bret Wallach for getting camera reg IO, ISOC, and
image capture working. Thanks to Orion Sky Lawlor, Kevin Moore, and Claudio
Matsuoka for their work as well.
+
diff --git a/Documentation/usb/stv680.txt b/Documentation/usb/stv680.txt
new file mode 100644
index 000000000..6448041e7
--- /dev/null
+++ b/Documentation/usb/stv680.txt
@@ -0,0 +1,55 @@
+Linux driver for STV0680 based USB cameras
+
+Copyright, 2001, Kevin Sisson
+
+
+INTRODUCTION:
+
+STMicroelectronics produces the STV0680B chip, which comes in two
+types, -001 and -003. The -003 version allows the recording and downloading
+of sound clips from the camera, and allows a flash attachment. Otherwise,
+it uses the same commands as the -001 version. Both versions support a
+variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20
+CIF pictures. The STV0680 supports either a serial or a usb interface, and
+video is possible through the usb interface.
+
+The following cameras are known to work with this driver, although any
+camera with Vendor/Product codes of 0553/0202 should work:
+
+Aiptek Pencam (various models)
+Nisis QuickPix 2
+Radio Shack 'Kid's digital camera' (#60-1207)
+At least one Trust Spycam model
+Several other European brand models
+
+WHAT YOU NEED:
+
+- USB support
+- VIDEO4LINUX support
+
+More information about USB support for linux can be found at:
+http://www.linux-usb.org
+
+
+MODULE OPTIONS:
+
+When the driver is compiled as a module, you can set a "swapRGB=1"
+option, if necessary, for those applications that require it
+(such as xawtv). However, the driver should detect and set this
+automatically, so this option should not normally be used.
+
+
+KNOWN PROBLEMS:
+
+The driver seems to work better with the usb-ohci than the usb-uhci host
+controller driver.
+
+HELP:
+
+The latest info on this driver can be found at:
+http://personal.clt.bellsouth.net/~kjsisson or at
+http://stv0680-usb.sourceforge.net
+
+Any questions to me can be send to: kjsisson@bellsouth.net
+
+
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
index a3b816d1a..dbab7aa4a 100644
--- a/Documentation/usb/usb-serial.txt
+++ b/Documentation/usb/usb-serial.txt
@@ -95,6 +95,66 @@ HandSpring Visor, Palm USB, and Clié USB driver
Kroah-Hartman at greg@kroah.com
+Compaq iPAQ driver
+
+ This driver can be used to connect to Compaq iPAQ PDAs running
+ Windows CE 3.0 using a USB autosync cable. It has been tested only on
+ the Compaq H3135. It should work with the H3600 and later models too.
+ It may work with other CE based handhelds as well.
+
+ The driver presents a serial interface (usually on /dev/ttyUSB0) over
+ which one may run ppp and establish a TCP/IP link to the iPAQ. Once this
+ is done, you can transfer files, backup, download email etc. The most
+ significant advantage of using USB is speed - you can get 73 to 113
+ kbytes/sec for download/upload to the iPAQ.
+
+ The driver works intermittently with the usb-uhci driver but quite
+ reliably with the uhci driver. Make sure you have the right driver
+ loaded - usb-uhci is often the default.
+
+ You must setup hotplug to invoke pppd as soon as the iPAQ is connected.
+ A ppp script like the one below may be used:
+
+ #!/bin/bash
+
+ MYIP=linux.box.ip
+ REMOTEIP=ipaq.ip
+ MYDNS=my.dns.server
+ killall -9 pppd
+ /usr/sbin/pppd /dev/ttyUSB0 \
+ connect "/usr/sbin/chat -v TIMEOUT 60 CLIENT 'CLIENTSERVER\c'" \
+ nocrtscts local debug passive $MYIP:$REMOTEIP ms-dns $MYDNS noauth \
+ proxyarp
+
+ You must also download and install asyncd from http://synce.sourceforge.net
+ This is required to emulate keep-alive packets which are exchanged by
+ ActiveSync and the iPAQ.
+
+ On connecting the cable, you should see the usual "Device Connected",
+ "User Authenticated" messages flash by on your iPAQ. Once connected,
+ you can use Win CE programs like ftpView, Pocket Outlook from the iPAQ
+ and other synce utilities from the Linux side. Remember to enable IP
+ forwarding.
+
+ To use Pocket IE, follow the instructions given at
+ http://www.tekguru.co.uk/EM500/usbtonet.htm to achieve the same thing
+ on Win98. Omit the proxy server part; Linux is quite capable of forwarding
+ packets unlike Win98. Another modification is required at least for the
+ iPAQ - disable autosync by going to the Start/Settings/Connections menu
+ and unchecking the "Automatically synchronize ..." box. Go to
+ Start/Programs/Connections, connect the cable and select "usbdial" (or
+ whatever you named your new USB connection). You should finally wind
+ up with a "Connected to usbdial" window with status shown as connected.
+ Now start up PIE and browse away.
+
+ If it doesn't work for some reason, load both the usbserial and ipaq module
+ with the module parameter "debug" set to 1 and examine the system log.
+ You can also try soft-resetting your iPAQ before attempting a connection.
+
+ For any questions or problems with the driver, please contact Ganesh
+ Varadarajan <ganesh@veritas.com>
+
+
Keyspan PDA Serial Adapter
Single port DB-9 serial adapter, pushed as a PDA adapter for iMacs (mostly
@@ -302,6 +362,32 @@ Prolific PL2303 Driver
Kroah-Hartman at greg@kroah.com
+KL5KUSB105 chipset / PalmConnect USB single-port adapter
+
+Current status:
+ The driver was put together by looking at the usb bus transactions
+ done by Palm's driver under Windows, so a lot of functionality is
+ still missing. Notably, serial ioctls are sometimes faked or not yet
+ implemented. Support for finding out about DSR and CTS line status is
+ however implemented (though not nicely), so your favorite autopilot(1)
+ and pilot-manager -daemon calls will work. Baud rates up to 115200
+ are supported, but handshaking (software or hardware) is not, which is
+ why it is wise to cut down on the rate used is wise for large
+ transfers until this is settled.
+
+Options supported:
+ If this driver is compiled as a module you can pass the following
+ options to it:
+ debug - extra verbose debugging info
+ (default: 0; nonzero enables)
+ use_lowlatency - use low_latency flag to speed up tty layer
+ when reading from from the device.
+ (default: 0; nonzero enables)
+
+ See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
+ information on this driver.
+
+
Generic Serial driver
If your device is not one of the above listed devices, compatible with
diff --git a/MAINTAINERS b/MAINTAINERS
index de42ab861..b2d05b640 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -849,7 +849,7 @@ P: Vojtech Pavlik
M: vojtech@suse.cz
L: linux-joystick@atrey.karlin.mff.cuni.cz
W: http://www.suse.cz/development/joystick/
-S: Supported
+S: Maintained
KERNEL AUTOMOUNTER (AUTOFS)
P: H. Peter Anvin
@@ -1552,7 +1552,7 @@ P: Vojtech Pavlik
M: vojtech@suse.cz
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
-S: Supported
+S: Maintained
USB BLUETOOTH DRIVER
P: Greg Kroah-Hartman
@@ -1575,7 +1575,7 @@ M: vojtech@suse.cz
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
W: http://www.suse.cz/development/input/
-S: Supported
+S: Maintained
USB HUB
P: Johannes Erdfelt
@@ -1626,7 +1626,7 @@ P: Vojtech Pavlik
M: vojtech@suse.cz
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
-S: Supported
+S: Maintained
USB SE401 DRIVER
P: Jeroen Vreeken
diff --git a/Makefile b/Makefile
index f280d8f93..8ce3734e4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 2
-EXTRAVERSION =-pre1
+EXTRAVERSION =-pre9
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index e2cc14540..4cfcab881 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -259,3 +259,8 @@ EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memchr);
EXPORT_SYMBOL(get_wchan);
+
+#ifdef CONFIG_ALPHA_IRONGATE
+EXPORT_SYMBOL(irongate_ioremap);
+EXPORT_SYMBOL(irongate_iounmap);
+#endif
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 005d6c971..860875f55 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -104,21 +104,21 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
}
/* stubs for the routines in pci_iommu.c */
void *
-pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp)
+pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
{
}
void
-pci_free_consistent(struct pci_dev *pdev, long size, void *cpu_addr,
+pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
dma_addr_t dma_addr)
{
}
dma_addr_t
-pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size,
+pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size,
int direction)
{
}
void
-pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size,
+pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
int direction)
{
}
@@ -126,6 +126,7 @@ int
pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
int direction)
{
+ return 0;
}
void
pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index ffa69a431..eb2bf74d8 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -215,12 +215,20 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
/* If the machine doesn't define a pci_tbi routine, we have to
assume it doesn't support sg mapping. */
if (! alpha_mv.mv_pci_tbi) {
- printk(KERN_WARNING "pci_map_single failed: no hw sg\n");
- return 0;
+ static int been_here = 0;
+ if (!been_here) {
+ printk(KERN_WARNING "pci_map_single: no hw sg, using "
+ "direct map when possible\n");
+ been_here = 1;
+ }
+ if (paddr + size <= __direct_map_size)
+ return (paddr + __direct_map_base);
+ else
+ return 0;
}
arena = hose->sg_pci;
- if (!arena || arena->dma_base + arena->size > max_dma)
+ if (!arena || arena->dma_base + arena->size - 1 > max_dma)
arena = hose->sg_isa;
npages = calc_npages((paddr & ~PAGE_MASK) + size);
@@ -247,20 +255,27 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
dma_addr_t
pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
{
+ int dac_allowed;
+
if (dir == PCI_DMA_NONE)
BUG();
- return pci_map_single_1(pdev, cpu_addr, size,
- pdev ? (pdev->dma_mask >> 32) != 0 : 0);
+
+ dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ return pci_map_single_1(pdev, cpu_addr, size, dac_allowed);
}
dma_addr_t
pci_map_page(struct pci_dev *pdev, struct page *page, unsigned long offset,
size_t size, int dir)
{
+ int dac_allowed;
+
if (dir == PCI_DMA_NONE)
BUG();
- return pci_map_single_1(pdev, (char *)page_address(page) + offset,
- size, pdev ? (pdev->dma_mask >> 32) != 0 : 0);
+
+ dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ return pci_map_single_1(pdev, (char *)page_address(page) + offset,
+ size, dac_allowed);
}
/* Unmap a single streaming mode DMA translation. The DMA_ADDR and
@@ -558,7 +573,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
if (direction == PCI_DMA_NONE)
BUG();
- dac_allowed = ((pdev->dma_mask >> 32) != 0);
+ dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
/* Fast path single entry scatterlists. */
if (nents == 1) {
@@ -580,7 +595,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
hose = pdev ? pdev->sysdata : pci_isa_hose;
max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
arena = hose->sg_pci;
- if (!arena || arena->dma_base + arena->size > max_dma)
+ if (!arena || arena->dma_base + arena->size - 1 > max_dma)
arena = hose->sg_isa;
} else {
max_dma = -1;
@@ -643,7 +658,7 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
hose = pdev ? pdev->sysdata : pci_isa_hose;
max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
arena = hose->sg_pci;
- if (!arena || arena->dma_base + arena->size > max_dma)
+ if (!arena || arena->dma_base + arena->size - 1 > max_dma)
arena = hose->sg_isa;
fbeg = -1, fend = 0;
@@ -710,11 +725,10 @@ pci_dma_supported(struct pci_dev *pdev, u64 mask)
struct pci_iommu_arena *arena;
/* If there exists a direct map, and the mask fits either
- MAX_DMA_ADDRESS defined such that GFP_DMA does something
- useful, or the total system memory as shifted by the
- map base. */
+ the entire direct mapped space or the total system memory as
+ shifted by the map base */
if (__direct_map_size != 0
- && (__direct_map_base + MAX_DMA_ADDRESS-IDENT_ADDR-1 <= mask
+ && (__direct_map_base + __direct_map_size - 1 <= mask
|| __direct_map_base + (max_low_pfn<<PAGE_SHIFT)-1 <= mask))
return 1;
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index e4ca5f6ac..708220d6d 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -75,7 +75,6 @@ cpu_idle(void)
{
/* An endless idle loop with no priority at all. */
current->nice = 20;
- current->counter = -100;
while (1) {
/* FIXME -- EV6 and LCA45 know how to power down
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 442550c65..94a3c1a18 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -440,12 +440,6 @@ static kdev_t srm_console_device(struct console *c)
return MKDEV(TTY_MAJOR, 64 + c->index);
}
-static int srm_console_wait_key(struct console *co)
-{
- /* Huh? */
- return 1;
-}
-
static int __init srm_console_setup(struct console *co, char *options)
{
return 1;
@@ -455,7 +449,6 @@ static struct console srmcons = {
name: "srm0",
write: srm_console_write,
device: srm_console_device,
- wait_key: srm_console_wait_key,
setup: srm_console_setup,
flags: CON_PRINTBUFFER | CON_ENABLED, /* fake it out */
index: -1,
diff --git a/arch/alpha/lib/dec_and_lock.c b/arch/alpha/lib/dec_and_lock.c
index 875966988..98598bc0e 100644
--- a/arch/alpha/lib/dec_and_lock.c
+++ b/arch/alpha/lib/dec_and_lock.c
@@ -27,6 +27,7 @@ atomic_dec_and_lock: \n\
br $atomic_dec_and_lock_1..ng \n\
.subsection 2 \n\
4: br 1b \n\
+ .previous \n\
.end atomic_dec_and_lock");
static int __attribute__((unused))
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 26c4c3b6a..4d6086874 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -9,7 +9,7 @@
LINKFLAGS :=-p -X -T arch/arm/vmlinux.lds
GZFLAGS :=-9
-CFLAGS +=-fno-common -pipe
+CFLAGS +=-pipe
ifneq ($(CONFIG_NO_FRAME_POINTER),y)
CFLAGS :=$(CFLAGS:-fomit-frame-pointer=)
@@ -22,9 +22,7 @@ endif
# Select CPU dependent flags. Note that order of declaration is important;
# the options further down the list override previous items.
#
-# Note! For APCS-26 YOU MUST HAVE AN APCS-26 LIBGCC.A
-#
-apcs-y :=-mapcs-32
+apcs-$(CONFIG_CPU_32) :=-mapcs-32
apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3 -Os
# This selects which instruction set is used.
@@ -32,6 +30,7 @@ arch-y :=
arch-$(CONFIG_CPU_32v3) :=-march=armv3
arch-$(CONFIG_CPU_32v4) :=-march=armv4
arch-$(CONFIG_CPU_32v5) :=-march=armv5
+arch-$(CONFIG_CPU_XSCALE) :=-march=armv4 -Wa,-mxscale #-march=armv5te
# This selects how we optimise for the processor.
tune-y :=
@@ -39,15 +38,19 @@ tune-$(CONFIG_CPU_ARM610) :=-mtune=arm610
tune-$(CONFIG_CPU_ARM710) :=-mtune=arm710
tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi
tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
+tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm #-mtune=xscale
+CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
ifeq ($(CONFIG_CPU_26),y)
-PROCESSOR = armo
+PROCESSOR := armo
+HEAD := arch/arm/mach-arc/head.o arch/arm/kernel/init_task.o
ifeq ($(CONFIG_ROM_KERNEL),y)
DATAADDR = 0x02080000
TEXTADDR = 0x03800000
@@ -60,6 +63,7 @@ endif
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
+HEAD := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
TEXTADDR = 0xC0008000
LDSCRIPT = arch/arm/vmlinux-armv.lds.in
endif
@@ -134,51 +138,55 @@ ifeq ($(CONFIG_ARCH_ANAKIN),y)
MACHINE = anakin
endif
-export MACHINE PROCESSOR TEXTADDR GZFLAGS
+ifeq ($(CONFIG_ARCH_IOP310),y)
+MACHINE = iop310
+endif
+
+ifeq ($(CONFIG_ARCH_ADIFCC),y)
+MACHINE = adifcc
+endif
+
+export MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT
# Only set INCDIR if its not already defined above
# Grr, ?= doesn't work as all the other assignment operators do. Make bug?
ifeq ($(origin INCDIR), undefined)
-INCDIR := $(MACHINE)
+INCDIR :=$(MACHINE)
endif
ifeq ($(origin DATAADDR), undefined)
DATAADDR := .
endif
-# If we have a machine-specific directory, then include it in the build.
-MACHDIR := arch/arm/mach-$(MACHINE)
-ifeq ($(MACHDIR),$(wildcard $(MACHDIR)))
-SUBDIRS += $(MACHDIR)
-CORE_FILES := $(MACHDIR)/$(MACHINE).o $(CORE_FILES)
+# Do we have FASTFPE?
+FASTFPE :=arch/arm/fastfpe
+ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
+SUBDIRS +=$(FASTFPE)
+FASTFPE_OBJ :=$(FASTFPE)/fast-math-emu.o
endif
-HEAD := arch/arm/kernel/head-$(PROCESSOR).o \
- arch/arm/kernel/init_task.o
-SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe
-CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
-LIBS := arch/arm/lib/lib.a $(LIBS)
+# If we have a machine-specific directory, then include it in the build.
+SUBDIRS +=arch/arm/mach-$(MACHINE) \
+ arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe
+CORE_FILES :=arch/arm/mach-$(MACHINE)/$(MACHINE).o \
+ arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
+LIBS :=arch/arm/lib/lib.a $(LIBS)
ifeq ($(CONFIG_FPE_NWFPE),y)
-LIBS := arch/arm/nwfpe/math-emu.o $(LIBS)
+LIBS :=arch/arm/nwfpe/math-emu.o $(LIBS)
endif
-# Only include fastfpe if it is part of the kernel tree.
-FASTFPE := arch/arm/fastfpe
-ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
-SUBDIRS += $(FASTFPE)
ifeq ($(CONFIG_FPE_FASTFPE),y)
-LIBS := arch/arm/fastfpe/fast-math-emu.o $(LIBS)
-endif
+LIBS :=$(FASTFPE_OBJ) $(LIBS)
endif
ifeq ($(findstring y,$(CONFIG_ARCH_CLPS7500) $(CONFIG_ARCH_L7200)),y)
-SUBDIRS += drivers/acorn/char
-DRIVERS += drivers/acorn/char/acorn-char.o
+SUBDIRS +=drivers/acorn/char
+DRIVERS +=drivers/acorn/char/acorn-char.o
endif
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
-MAKETOOLS = $(MAKE) -C arch/$(ARCH)/tools
+MAKEBOOT =$(MAKE) -C arch/$(ARCH)/boot
+MAKETOOLS =$(MAKE) -C arch/$(ARCH)/tools
# The following is a hack to get 'constants.h' up
# to date before starting compilation
@@ -254,7 +262,7 @@ bp:; @$(MAKEBOOT) bootpImage
@( \
CFG=$(@:_config=); \
if [ -f arch/arm/def-configs/$$CFG ]; then \
- [ -f .config ] && $(MV) .config .config.old; \
+ [ -f .config ] && mv -f .config .config.old; \
cp arch/arm/def-configs/$$CFG .config; \
echo "*** Default configuration for $$CFG installed"; \
echo "*** Next, you may run 'make oldconfig'"; \
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index dc257329b..2817fbb83 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -118,6 +118,22 @@ ifeq ($(CONFIG_ARCH_ANAKIN),y)
ZTEXTADDR = 0x20008000
endif
+ifeq ($(CONFIG_ARCH_IQ80310),y)
+ZRELADDR = 0xa0008000
+
+# for serial upload
+ZTEXTADDR = 0xa1008000
+
+# for direct flash execution
+# ZTEXTADDR = 0x00060000
+# ZBSSADDR = 0xa1008000
+endif
+
+ifeq ($(CONFIG_ARCH_ADIFCC),y)
+ZRELADDR = 0xc0008000
+ZTEXTADDR = 0xc1000000
+endif
+
#
# If you don't define ZRELADDR above,
# then it defaults to ZTEXTADDR
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 3d7abdb9e..cfdbe3692 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -9,7 +9,7 @@
HEAD = head.o
OBJS = misc.o
-CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_PROC) -msoft-float
+CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_BOOT)
FONTC = $(TOPDIR)/drivers/video/font_acorn_8x8.c
ZLDFLAGS = -p -X -T vmlinux.lds
@@ -57,6 +57,10 @@ ifeq ($(CONFIG_SA1100_NANOENGINE),y)
endif
endif
+ifeq ($(CONFIG_CPU_XSCALE),y)
+OBJS += head-xscale.o
+endif
+
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;
ifneq ($(ZBSSADDR),)
@@ -84,12 +88,12 @@ piggy.o: $(SYSTEM)
font.o: $(FONTC)
$(CC) $(CFLAGS) -Dstatic= -c -o $@ $(FONTC)
-vmlinux.lds: vmlinux.lds.in
+vmlinux.lds: vmlinux.lds.in Makefile $(TOPDIR)/arch/$(ARCH)/boot/Makefile $(TOPDIR)/.config
@sed "$(SEDFLAGS)" < vmlinux.lds.in > $@
clean:; rm -f vmlinux core piggy* vmlinux.lds
-.PHONY: vmlinux.lds clean
+.PHONY: clean
misc.o: misc.c $(TOPDIR)/include/asm/arch/uncompress.h $(TOPDIR)/lib/inflate.c
diff --git a/arch/arm/boot/compressed/head-shark.S b/arch/arm/boot/compressed/head-shark.S
index c41f84ddd..26da294e9 100644
--- a/arch/arm/boot/compressed/head-shark.S
+++ b/arch/arm/boot/compressed/head-shark.S
@@ -1,5 +1,5 @@
/* The head-file for the Shark
- * by Alexander Schulz <aschulz@netwinder.org>
+ * by Alexander Schulz
*
* Does the following:
* - get the memory layout from firmware. This can only be done as long as the mmu
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
new file mode 100644
index 000000000..abe2fe19a
--- /dev/null
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -0,0 +1,66 @@
+/*
+ * linux/arch/arm/boot/compressed/head-xscale.S
+ *
+ * XScale specific tweaks. This is merged into head.S by the linker.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/mach-types.h>
+
+ .section ".start", #alloc, #execinstr
+
+__XScale_start:
+
+ @ Preserve r8/r7 i.e. kernel entry values
+
+ @ Data cache might be active.
+ @ Be sure to flush kernel binary out of the cache,
+ @ whatever state it is, before it is turned off.
+ @ This is done by fetching through currently executed
+ @ memory to be sure we hit the same cache.
+ bic r2, pc, #0x1f
+ add r3, r2, #0x10000 @ 64 kb is quite enough...
+1: ldr r0, [r2], #32
+ teq r2, r3
+ bne 1b
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches
+
+ @ disabling MMU and caches
+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
+ bic r0, r0, #0x05 @ clear DC, MMU
+ bic r0, r0, #0x1000 @ clear Icache
+ mcr p15, 0, r0, c1, c0, 0
+
+#ifdef CONFIG_ARCH_LUBBOCK
+ mov r7, #MACH_TYPE_LUBBOCK
+#endif
+
+#ifdef CONFIG_ARCH_COTULLA_IDP
+ mov r7, #MACH_TYPE_COTULLA_IDP
+#endif
+
+#ifdef CONFIG_ARCH_IQ80310
+ /*
+ * Crank the CPU up to 733MHz
+ */
+ mov r1, #9
+ mcr p14, 0, r1, c6, c0, 0
+
+ /*
+ * Disable ECC error notification
+ * At some point, we should add an ECC handler to Linux
+ */
+ mov r1, #0x1500
+ mov r0, #0x4
+ str r0, [r1, #0x34]
+
+ mov r7, #MACH_TYPE_IQ80310
+#endif
+
+#ifdef CONFIG_ARCH_ADI_EVB
+ mov r7, #MACH_TYPE_ADI_EVB
+#endif
+
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 0238a3b8a..12eeb2099 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -64,7 +64,7 @@
kphex r7, 8 /* architecture id */
kputc #':'
mrc p15, 0, r0, c1, c0
- kphex r0, 8 /* control reg
+ kphex r0, 8 /* control reg */
kputc #'\n'
kphex r5, 8 /* decompressed kernel start */
kputc #'-'
@@ -218,7 +218,12 @@ cache_on: ldr r1, proc_sa110_type
ldr r1, proc_sa1110_type
eor r1, r1, r6
movs r1, r1, lsr #4
- movne pc, lr
+ beq 1f
+ ldr r1, proc_xscale_type
+ eor r1, r1, r6
+ movs r1, r1, lsr #16
+@ movne pc, lr
+ bne cache_off
1:
sub r3, r4, #16384 @ Page directory size
bic r3, r3, #0xff @ Align the pointer
@@ -379,10 +384,14 @@ cache_clean_flush:
ldr r1, proc_sa1110_type
eor r1, r1, r6
movs r1, r1, lsr #4
+ beq 1f
+ ldr r1, proc_xscale_type
+ eor r1, r1, r6
+ movs r1, r1, lsr #16
movne pc, lr
1:
bic r1, pc, #31
- add r2, r1, #32768
+ add r2, r1, #65536 @ 2x the largest dcache size
1: ldr r12, [r1], #32 @ s/w flush D cache
teq r1, r2
bne 1b
@@ -391,6 +400,12 @@ cache_clean_flush:
mcr p15, 0, r1, c7, c10, 4 @ drain WB
mov pc, lr
+ .type proc_xscale_type,#object
+proc_xscale_type:
+ .word 0x69050000
+ .size proc_xscale_type, . - proc_xscale_type
+
+
/*
* Various debugging routines for printing hex characters and
* memory, which again must be relocatable.
diff --git a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c
index 088b16bcc..821e549c1 100644
--- a/arch/arm/boot/compressed/ofw-shark.c
+++ b/arch/arm/boot/compressed/ofw-shark.c
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/boot/compressed/ofw-shark.c
*
- * by Alexander Schulz <aschulz@netwinder.org>
+ * by Alexander Schulz
*
* This file is used to get some basic information
* about the memory layout of the shark we are running
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 845918443..02bcbfa8b 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -33,7 +33,8 @@ mainmenu_option next_comment
comment 'System Type'
choice 'ARM system type' \
- "Anakin CONFIG_ARCH_ANAKIN \
+ "ADIFCC-based CONFIG_ARCH_ADIFCC \
+ Anakin CONFIG_ARCH_ANAKIN \
Archimedes/A5000 CONFIG_ARCH_ARCA5K \
Cirrus-CL-PS7500FE CONFIG_ARCH_CLPS7500 \
CLPS711x/EP721x-based CONFIG_ARCH_CLPS711X \
@@ -42,6 +43,7 @@ choice 'ARM system type' \
Epxa10db CONFIG_ARCH_CAMELOT \
FootBridge CONFIG_ARCH_FOOTBRIDGE \
Integrator CONFIG_ARCH_INTEGRATOR \
+ IOP310-based CONFIG_ARCH_IOP310 \
LinkUp-L7200 CONFIG_ARCH_L7200 \
RiscPC CONFIG_ARCH_RPC \
SA1100-based CONFIG_ARCH_SA1100 \
@@ -85,7 +87,14 @@ if [ "$CONFIG_SA1100_CERF" = "y" ]; then
32MB CONFIG_SA1100_CERF_FLASH_32MB" CerfFlash
bool 'Cerf w/CPLD support (CerfPDA)' CONFIG_SA1100_CERF_CPLD
fi
-dep_bool ' Compaq iPAQ H3600' CONFIG_SA1100_H3600 $CONFIG_ARCH_SA1100
+dep_bool ' Compaq iPAQ H3100' CONFIG_SA1100_H3100 $CONFIG_ARCH_SA1100
+dep_bool ' Compaq iPAQ H3600/H3700' CONFIG_SA1100_H3600 $CONFIG_ARCH_SA1100
+dep_bool ' Compaq iPAQ H3800' CONFIG_SA1100_H3800 $CONFIG_ARCH_SA1100
+if [ "$CONFIG_SA1100_H3100" = "y" -o "$CONFIG_SA1100_H3600" = "y" -o "$CONFIG_SA1100_H3800" = "y" ]; then
+ define_bool CONFIG_SA1100_H3XXX y
+else
+ define_bool CONFIG_SA1100_H3XXX n
+fi
#dep_bool ' Empeg' CONFIG_SA1100_EMPEG $CONFIG_ARCH_SA1100
dep_bool ' Extenex HandHeld Theater (Squashtail)' CONFIG_SA1100_EXTENEX1 $CONFIG_ARCH_SA1100
if [ "$CONFIG_SA1100_EXTENEX1" = "y" ]; then
@@ -103,6 +112,8 @@ dep_bool ' nanoEngine' CONFIG_SA1100_NANOENGINE $CONFIG_ARCH_SA1100
dep_bool ' OmniMeter' CONFIG_SA1100_OMNIMETER $CONFIG_ARCH_SA1100
dep_bool ' Pangolin' CONFIG_SA1100_PANGOLIN $CONFIG_ARCH_SA1100
dep_bool ' PLEB' CONFIG_SA1100_PLEB $CONFIG_ARCH_SA1100
+dep_bool ' PT System 3' CONFIG_SA1100_PT_SYSTEM3 $CONFIG_ARCH_SA1100
+dep_bool ' Shannon' CONFIG_SA1100_SHANNON $CONFIG_ARCH_SA1100
dep_bool ' Sherman' CONFIG_SA1100_SHERMAN $CONFIG_ARCH_SA1100
dep_bool ' Simpad' CONFIG_SA1100_SIMPAD $CONFIG_ARCH_SA1100
dep_bool ' Tulsa' CONFIG_SA1100_PFS168 $CONFIG_ARCH_SA1100
@@ -116,14 +127,22 @@ if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \
"$CONFIG_SA1100_PFS168" = "y" -o \
"$CONFIG_SA1100_XP860" = "y" -o \
"$CONFIG_SA1100_GRAPHICSMASTER" = "y" -o \
+ "$CONFIG_SA1100_PT_SYSTEM3" = "y" -o \
"$CONFIG_SA1100_ADSBITSY" = "y" ]; then
define_bool CONFIG_SA1111 y
define_int CONFIG_FORCE_MAX_ZONEORDER 9
fi
+
+dep_tristate 'SA1100 USB function support' CONFIG_SA1100_USB $CONFIG_ARCH_SA1100
+dep_tristate ' Support for SA11x0 USB network link function' CONFIG_SA1100_USB_NETLINK $CONFIG_SA1100_USB
+dep_tristate ' Support for SA11x0 USB character device emulation' CONFIG_SA1100_USB_CHAR $CONFIG_SA1100_USB
+
+dep_tristate 'Compaq iPAQ Handheld sleeve support' CONFIG_H3600_SLEEVE $CONFIG_SA1100_H3600
endmenu
mainmenu_option next_comment
comment 'CLPS711X/EP721X Implementations'
+dep_bool ' AUTCPU12' CONFIG_ARCH_AUTCPU12 $CONFIG_ARCH_CLPS711X
dep_bool ' CDB89712' CONFIG_ARCH_CDB89712 $CONFIG_ARCH_CLPS711X
dep_bool ' CLEP7312' CONFIG_ARCH_CLEP7312 $CONFIG_ARCH_CLPS711X
dep_bool ' EDB7211' CONFIG_ARCH_EDB7211 $CONFIG_ARCH_CLPS711X
@@ -148,6 +167,19 @@ if [ "$CONFIG_ARCH_EP7211" = "y" -o \
fi
endmenu
+if [ "$CONFIG_ARCH_IOP310" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'IOP310 Implementation Options'
+ choice 'IOP310 System Type' \
+ "IQ80310 CONFIG_ARCH_IQ80310" IQ80310
+ comment 'IOP310 Chipset Features'
+ bool 'Support Intel 80312 Application Accelerator Unit (EXPERIMENTAL)' CONFIG_IOP310_AAU
+ bool 'Support Intel 80312 DMA (EXPERIMENTAL)' CONFIG_IOP310_DMA
+ bool 'Support Intel 80312 Messaging Unit (EXPERIMENTAL)' CONFIG_IOP310_MU
+ bool 'Support Intel 80312 Performance Monitor (EXPERIMENTAL)' CONFIG_IOP310_PMON
+ endmenu
+fi
+
# Definitions to make life easier
if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \
"$CONFIG_ARCH_RPC" = "y" ]; then
@@ -195,6 +227,8 @@ fi
comment 'Processor Type'
# Firstly, figure out what processor architecture version we should be using.
+# This depends more on the machine type than anything else.
+
if [ "$CONFIG_ARCH_RPC" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
define_bool CONFIG_CPU_32v3 y
else
@@ -261,6 +295,21 @@ if [ "$CONFIG_CPU_ARM920T" = "y" ]; then
fi
fi
+# ARM922T
+if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
+ define_bool CONFIG_CPU_ARM922T y
+else
+ define_bool CONFIG_CPU_ARM922T n
+fi
+if [ "$CONFIG_CPU_ARM922T" = "y" ]; then
+ bool ' ARM922T CPU idle' CONFIG_CPU_ARM922_CPU_IDLE
+ bool ' ARM922T I-Cache on' CONFIG_CPU_ARM922_I_CACHE_ON
+ bool ' ARM922T D-Cache on' CONFIG_CPU_ARM922_D_CACHE_ON
+ if [ "$CONFIG_CPU_ARM922_D_CACHE_ON" = "y" ] ; then
+ bool ' Force write through caches on ARM922T' CONFIG_CPU_ARM922_WRITETHROUGH
+ fi
+fi
+
# ARM926T
if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
bool 'Support ARM926T processor' CONFIG_CPU_ARM926T
@@ -318,6 +367,22 @@ else
define_bool CONFIG_CPU_SA1100 n
fi
+# XScale
+if [ "$CONFIG_ARCH_IOP310" = "y" -o "$CONFIG_ARCH_ADIFCC" = "y" ]; then
+ define_bool CONFIG_CPU_32v5 y
+ define_bool CONFIG_CPU_XSCALE y
+fi
+
+#if [ "$CONFIG_CPU_XSCALE" = "y" ]; then
+# bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER
+#fi
+
+if [ "$CONFIG_CPU_XSCALE" = "y" -a "$CONFIG_XSCALE_PMU_TIMER" != "y" ]; then
+ define_bool CONFIG_XSCALE_PMU y
+else
+ define_bool CONFIG_XSCALE_PMU n
+fi
+
if [ "$CONFIG_CPU_32" = "y" ]; then
dep_bool 'Support Thumb instructions (experimental)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
fi
@@ -338,7 +403,8 @@ comment 'General setup'
# Now handle the bus types
if [ "$CONFIG_ARCH_FTVPCI" = "y" -o \
"$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_FOOTBRIDGE_HOST" = "y" ]; then
+ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
+ "$CONFIG_ARCH_IOP310" = "y" ]; then
define_bool CONFIG_PCI y
else
if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
@@ -349,6 +415,20 @@ else
fi
fi
+# Select the host bridge type
+if [ "$CONFIG_PCI" = "y" ]; then
+ if [ "$CONFIG_ARCH_FTVPCI" = "y" ]; then
+ define_bool CONFIG_PCI_HOST_PLX90X0 y
+ else
+ define_bool CONFIG_PCI_HOST_PLX90X0 n
+ fi
+ if [ "$CONFIG_ARCH_SHARK" = "y" ]; then
+ define_bool CONFIG_PCI_HOST_VIA82C505 y
+ else
+ define_bool CONFIG_PCI_HOST_VIA82C505 n
+ fi
+fi
+
if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
"$CONFIG_ARCH_SHARK" = "y" -o \
"$CONFIG_ARCH_CLPS7500" = "y" -o \
@@ -368,6 +448,13 @@ else
define_bool CONFIG_ISA_DMA n
fi
+if [ "$CONFIG_ARCH_ACORN" = "y" -o \
+ "$CONFIG_ARCH_L7200" = "y" ]; then
+ define_bool CONFIG_FIQ y
+else
+ define_bool CONFIG_FIQ n
+fi
+
if [ "$CONFIG_ARCH_SA1100" = "y" -o \
"$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL
@@ -393,7 +480,8 @@ choice 'Kernel core (/proc/kcore) format' \
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
-dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
+bool 'Power Management support' CONFIG_PM
+dep_tristate 'Advanced Power Management Emulation' CONFIG_APM $CONFIG_PM
dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32
if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
@@ -404,7 +492,9 @@ if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
"$CONFIG_ARCH_P720T" = "y" -o \
"$CONFIG_ARCH_CDB89712" = "y" -o \
"$CONFIG_ARCH_CAMELOT" = "y" -o \
- "$CONFIG_ARCH_ANAKIN" = "y" ]; then
+ "$CONFIG_ARCH_ANAKIN" = "y" -o \
+ "$CONFIG_ARCH_IOP310" = "y" -o \
+ "$CONFIG_ARCH_ADIFCC" = "y" ]; then
string 'Default kernel command string' CONFIG_CMDLINE ""
fi
if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
@@ -434,8 +524,16 @@ if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
define_bool CONFIG_LEDS_TIMER y
fi
fi
-if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
- bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP
+
+if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
+ define_bool CONFIG_ALIGNMENT_TRAP y
+else
+ if [ "$CONFIG_CPU_32" = "y" -a \
+ "$CONFIG_ARCH_EBSA110" != "y" ]; then
+ bool 'Mis-alignment trap handler' CONFIG_ALIGNMENT_TRAP
+ else
+ define_bool CONFIG_ALIGNMENT_TRAP n
+ fi
fi
endmenu
@@ -594,15 +692,20 @@ comment 'Kernel hacking'
# Always compile kernel with framepointer (until 2.4 real comes out)
# Bug reports aren't much use without this.
bool 'Compile kernel without frame pointer' CONFIG_NO_FRAME_POINTER
-bool 'Verbose kernel error messages' CONFIG_DEBUG_ERRORS
bool 'Verbose user fault messages' CONFIG_DEBUG_USER
bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
-bool 'Debug memory allocations' CONFIG_DEBUG_SLAB
-bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
-bool 'Spinlock debugging' CONFIG_DEBUG_SPINLOCK
dep_bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE $CONFIG_CPU_26
+
+bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+dep_bool ' Debug memory allocations' CONFIG_DEBUG_SLAB $CONFIG_DEBUG_KERNEL
+dep_bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_DEBUG_KERNEL
+dep_bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK $CONFIG_DEBUG_KERNEL
+dep_bool ' Wait queue debugging' CONFIG_DEBUG_WAITQ $CONFIG_DEBUG_KERNEL
+dep_bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE $CONFIG_DEBUG_KERNEL
+dep_bool ' Verbose kernel error messages' CONFIG_DEBUG_ERRORS $CONFIG_DEBUG_KERNEL
# These options are only for real kernel hackers who want to get their hands dirty.
-dep_bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_EXPERIMENTAL
-dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
-dep_bool ' kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
+dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
+dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
+dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
+dep_bool ' Kernel low-level debugging messages via SA1100 Ser3 (otherwise Ser1)' CONFIG_DEBUG_LL_SER3 $CONFIG_DEBUG_LL $CONFIG_ARCH_SA1100
endmenu
diff --git a/arch/arm/def-configs/adi_evb b/arch/arm/def-configs/adi_evb
new file mode 100644
index 000000000..efad962e9
--- /dev/null
+++ b/arch/arm/def-configs/adi_evb
@@ -0,0 +1,681 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+CONFIG_ARCH_ADIFCC=y
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+CONFIG_ARCH_ADI_EVB=y
+CONFIG_XSCALE_PMU_TIMER=y
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_XSCALE=y
+CONFIG_ARM_THUMB=y
+# CONFIG_XSCALE_TOOLS is not set
+CONFIG_XSCALE_WRITE_ALLOC=y
+CONFIG_XSCALE_PMU=y
+CONFIG_ARM_THUMB=y
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/mtdblock1"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_BOOTLDR_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+CONFIG_MTD_ADI_EVB=y
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK=y
+CONFIG_RTNETLINK=y
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_CMS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_FREEVXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+# CONFIG_USB_OHCI is not set
+# CONFIG_USB_OHCI_SA1111 is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_ID75 is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_NO_FRAME_POINTER is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
diff --git a/arch/arm/def-configs/flexanet b/arch/arm/def-configs/flexanet
index 121a31c72..c27ae0a74 100644
--- a/arch/arm/def-configs/flexanet
+++ b/arch/arm/def-configs/flexanet
@@ -8,6 +8,8 @@ CONFIG_ARM=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
#
# Code maturity level options
@@ -25,17 +27,19 @@ CONFIG_MODULES=y
#
# System Type
#
+# CONFIG_ARCH_ANAKIN is not set
# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_RPC is not set
CONFIG_ARCH_SA1100=y
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_SHARK is not set
#
# Archimedes/A5000 Implementations
@@ -44,22 +48,32 @@ CONFIG_ARCH_SA1100=y
#
# Archimedes/A5000 Implementations (select only ONE)
#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
#
# Footbridge Implementations
#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_BITSY is not set
+# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_EXTENEX1 is not set
CONFIG_SA1100_FLEXANET=y
# CONFIG_SA1100_FREEBIRD is not set
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
# CONFIG_SA1100_JORNADA720 is not set
# CONFIG_SA1100_HUW_WEBPANEL is not set
# CONFIG_SA1100_ITSY is not set
@@ -68,7 +82,9 @@ CONFIG_SA1100_FLEXANET=y
# CONFIG_SA1100_OMNIMETER is not set
# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_SHANNON is not set
# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
# CONFIG_SA1100_PFS168 is not set
# CONFIG_SA1100_VICTOR is not set
# CONFIG_SA1100_XP860 is not set
@@ -76,11 +92,17 @@ CONFIG_SA1100_FLEXANET=y
CONFIG_SA1100_USB=y
CONFIG_SA1100_USB_NETLINK=y
# CONFIG_SA1100_USB_CHAR is not set
-# CONFIG_SA1100_FREQUENCY_SCALE is not set
#
# CLPS711X/EP721X Implementations
#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
# CONFIG_ARCH_ACORN is not set
# CONFIG_FOOTBRIDGE is not set
# CONFIG_FOOTBRIDGE_HOST is not set
@@ -97,32 +119,40 @@ CONFIG_CPU_32v4=y
# CONFIG_CPU_ARM710 is not set
# CONFIG_CPU_ARM720T is not set
# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_CPU_ARM926T is not set
# CONFIG_CPU_ARM1020 is not set
# CONFIG_CPU_SA110 is not set
CONFIG_CPU_SA1100=y
+# CONFIG_ARM_THUMB is not set
CONFIG_DISCONTIGMEM=y
-# CONFIG_CPU_BIG_ENDIAN is not set
#
# General setup
#
# CONFIG_PCI is not set
-# CONFIG_ISA is not set
+CONFIG_ISA=y
# CONFIG_ISA_DMA is not set
-# CONFIG_CPU_CLOCK is not set
+CONFIG_CPU_FREQ=y
CONFIG_HOTPLUG=y
#
# PCMCIA/CardBus support
#
CONFIG_PCMCIA=y
+# CONFIG_I82092 is not set
# CONFIG_I82365 is not set
# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_CLPS6700 is not set
CONFIG_PCMCIA_SA1100=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
+
+#
+# At least one math emulation must be selected
+#
CONFIG_FPE_NWFPE=y
CONFIG_FPE_FASTFPE=y
CONFIG_KCORE_ELF=y
@@ -130,7 +160,7 @@ CONFIG_KCORE_ELF=y
# CONFIG_BINFMT_AOUT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
+CONFIG_PM=y
# CONFIG_ARTHUR is not set
CONFIG_CMDLINE=""
CONFIG_LEDS=y
@@ -149,7 +179,7 @@ CONFIG_ALIGNMENT_TRAP=y
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_REDBOOT_PARTS=y
# CONFIG_MTD_BOOTLDR_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -165,43 +195,42 @@ CONFIG_MTD_BLOCK=y
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
-# CONFIG_MTD_CFI_VIRTUAL_ER is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LART_BIT_SWAP is not set
# CONFIG_MTD_CFI_GEOMETRY is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
# CONFIG_MTD_JEDEC is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_SUN_UFLASH is not set
# CONFIG_MTD_NORA is not set
-# CONFIG_MTD_PNC2000 is not set
-# CONFIG_MTD_RPXLITE is not set
-# CONFIG_MTD_SC520CDP is not set
-# CONFIG_MTD_NETSC520 is not set
-# CONFIG_MTD_SBC_GXX is not set
-# CONFIG_MTD_ELAN_104NC is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
CONFIG_MTD_SA1100=y
+# CONFIG_MTD_DC21285 is not set
# CONFIG_MTD_IQ80310 is not set
-# CONFIG_MTD_CFI_FLAGADM is not set
-# CONFIG_MTD_ARMFLASH is not set
+# CONFIG_MTD_PCI is not set
#
# Self-contained MTD device drivers
#
+# CONFIG_MTD_PMC551 is not set
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
#
# Disk-On-Chip Device Drivers
@@ -220,11 +249,17 @@ CONFIG_MTD_SA1100=y
# Plug and Play configuration
#
# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
@@ -235,6 +270,13 @@ CONFIG_BLK_DEV_INITRD=y
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
#
# Networking options
@@ -258,6 +300,7 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
#
#
@@ -293,42 +336,75 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-# CONFIG_NET_SB1000 is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
CONFIG_NET_VENDOR_SMC=y
# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
CONFIG_SMC9194=y
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
# CONFIG_NET_PCI is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
#
# Wireless LAN (non-hamradio)
#
-# CONFIG_NET_RADIO is not set
+CONFIG_NET_RADIO=y
+# CONFIG_STRIP is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_ARLAN is not set
+# CONFIG_AIRONET4500 is not set
+# CONFIG_AIRONET4500_NONCS is not set
+# CONFIG_AIRONET4500_PROC is not set
+# CONFIG_AIRO is not set
+CONFIG_HERMES=m
+
+#
+# Wireless Pcmcia cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_AIRO_CS is not set
+CONFIG_NET_WIRELESS=y
#
# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set
#
@@ -347,8 +423,10 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_PCMCIA_NMCLAN is not set
# CONFIG_PCMCIA_SMC91C92 is not set
# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
# CONFIG_NET_PCMCIA_RADIO is not set
-CONFIG_PCMCIA_NETCARD=y
#
# Amateur Radio support
@@ -378,20 +456,33 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
CONFIG_BLK_DEV_IDECS=y
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
#
# IDE chipset support/bugfixes
#
# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_DMA_NONPCI is not set
# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
#
# SCSI support
@@ -402,6 +493,10 @@ CONFIG_BLK_DEV_IDECS=y
# I2O device support
#
# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
#
# ISDN subsystem
@@ -412,6 +507,10 @@ CONFIG_BLK_DEV_IDECS=y
# Input core support
#
# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
#
# Character devices
@@ -419,21 +518,38 @@ CONFIG_BLK_DEV_IDECS=y
CONFIG_VT=y
# CONFIG_VT_CONSOLE is not set
# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
CONFIG_SERIAL_SA1100=y
-# CONFIG_SERIAL_SA1100_OLD is not set
CONFIG_SERIAL_SA1100_CONSOLE=y
CONFIG_SA1100_DEFAULT_BAUDRATE=57600
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=32
-CONFIG_UCB1200=y
-CONFIG_TOUCHSCREEN_UCB1200=y
-CONFIG_AUDIO_UCB1200=y
-CONFIG_ADC_UCB1200=y
-# CONFIG_TOUCHSCREEN_BITSY is not set
-# CONFIG_PROFILER is not set
#
# I2C support
@@ -441,37 +557,35 @@ CONFIG_ADC_UCB1200=y
# CONFIG_I2C is not set
#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
+# L3 serial bus support
#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
#
-# Game port support
+# Other L3 adapters
#
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
#
-# Gameport joysticks
-#
-
-#
-# Serial port support
+# Mice
#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
#
-# Serial port joysticks
+# Joysticks
#
+# CONFIG_INPUT_GAMEPORT is not set
#
-# Parallel port joysticks
+# Input core support is needed for gameports
#
#
-# Parport support is needed for parallel port joysticks
+# Input core support is needed for joysticks
#
# CONFIG_QIC02_TAPE is not set
@@ -479,6 +593,7 @@ CONFIG_ADC_UCB1200=y
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
CONFIG_SA1100_RTC=y
@@ -509,44 +624,74 @@ CONFIG_SA1100_RTC=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
# CONFIG_TMPFS is not set
CONFIG_RAMFS=y
# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-CONFIG_ROMFS_FS=y
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
CONFIG_ROOT_NFS=y
# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
#
# Partition Types
@@ -562,6 +707,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MINIX_SUBPARTITION is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -573,15 +719,17 @@ CONFIG_MSDOS_PARTITION=y
#
CONFIG_PC_KEYMAP=y
# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
#
# Frame-buffer support
#
CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_ACORN is not set
+# CONFIG_FB_ANAKIN is not set
+# CONFIG_FB_CLPS711X is not set
CONFIG_FB_SA1100=y
-# CONFIG_FB_E1355 is not set
+# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB2=y
@@ -597,28 +745,49 @@ CONFIG_FONT_8x16=y
# Sound
#
CONFIG_SOUND=y
-# CONFIG_SOUND_SA1100_SSP is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_ESSSOLO1 is not set
# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
# CONFIG_SOUND_SONICVIBES is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_SA1100 is not set
+# CONFIG_SOUND_UDA1341 is not set
+# CONFIG_SOUND_ASSABET_UDA1341 is not set
+# CONFIG_SOUND_H3600_UDA1341 is not set
+# CONFIG_SOUND_PANGOLIN_UDA1341 is not set
+# CONFIG_SOUND_SA1111_UDA1341 is not set
+# CONFIG_SOUND_SA1100SSP is not set
# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_WAVEARTIST is not set
+# CONFIG_SOUND_TVMIXER is not set
#
-# USB support
+# Multimedia Capabilities Port drivers
#
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
#
-# Miscellaneous USB options
+# USB support
#
-# CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB is not set
#
# USB Controllers
@@ -626,15 +795,22 @@ CONFIG_USB_DEBUG=y
# CONFIG_USB_UHCI is not set
# CONFIG_USB_UHCI_ALT is not set
# CONFIG_USB_OHCI is not set
+# CONFIG_USB_OHCI_SA1111 is not set
#
# USB Device Class drivers
#
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
@@ -652,40 +828,83 @@ CONFIG_USB_DEBUG=y
# CONFIG_USB_DC2XX is not set
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
#
-# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
#
# USB Network adaptors
#
-# CONFIG_USB_PLUSB is not set
# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_NET1080 is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
# CONFIG_USB_USBNET is not set
#
# USB port drivers
#
+# CONFIG_USB_USS720 is not set
#
# USB Serial Converter support
#
# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_RIO500 is not set
#
-# USB misc drivers
+# Bluetooth support
#
-# CONFIG_USB_RIO500 is not set
+# CONFIG_BLUEZ is not set
#
# Kernel hacking
#
# CONFIG_NO_FRAME_POINTER is not set
-CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_MAGIC_SYSRQ=y
+# CONFIG_NO_PGT_CACHE is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_ERRORS is not set
# CONFIG_DEBUG_LL is not set
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
diff --git a/arch/arm/def-configs/iq80310 b/arch/arm/def-configs/iq80310
new file mode 100644
index 000000000..dfad4f2d3
--- /dev/null
+++ b/arch/arm/def-configs/iq80310
@@ -0,0 +1,812 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ADIFCC is not set
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_IOP310=y
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+
+#
+# IOP310 Implementation Options
+#
+CONFIG_ARCH_IQ80310=y
+# CONFIG_IOP310_AAU is not set
+# CONFIG_IOP310_DMA is not set
+# CONFIG_IOP310_MU is not set
+# CONFIG_IOP310_PMON is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_32v3 is not set
+# CONFIG_CPU_32v4 is not set
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_XSCALE=y
+CONFIG_ARM_THUMB=y
+# CONFIG_XSCALE_TOOLS is not set
+# CONFIG_XSCALE_CACHE_WRITE_ALLOC is not set
+CONFIG_XSCALE_PMU=y
+CONFIG_ARM_THUMB=y
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_BOOTLDR_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+CONFIG_MTD_IQ80310=y
+# CONFIG_MTD_EPXA10DB is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK=y
+CONFIG_RTNETLINK=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TULIP is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+CONFIG_EEPRO100=y
+# CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_RHINE_MMIO is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_AMD74XX_OVERRIDE is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
+CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_SA1100 is not set
+# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+# CONFIG_USB_OHCI is not set
+# CONFIG_USB_OHCI_SA1111 is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_RIO500 is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_NO_FRAME_POINTER is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
diff --git a/arch/arm/def-configs/shannon b/arch/arm/def-configs/shannon
new file mode 100644
index 000000000..c59fb0cb6
--- /dev/null
+++ b/arch/arm/def-configs/shannon
@@ -0,0 +1,737 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_OBSOLETE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_RPC is not set
+CONFIG_ARCH_SA1100=y
+# CONFIG_ARCH_SHARK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Archimedes/A5000 Implementations (select only ONE)
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+CONFIG_SA1100_SHANNON=y
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+
+#
+# Processor Type
+#
+# CONFIG_CPU_32v3 is not set
+CONFIG_CPU_32v4=y
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_SA110 is not set
+CONFIG_CPU_SA1100=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_DISCONTIGMEM=y
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+CONFIG_ISA=y
+# CONFIG_ISA_DMA is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_SA1100=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttySA0,9600 console=tty1 root=/dev/mtdblock2 init=/linuxrc"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_BOOTLDR_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_SA1100=y
+# CONFIG_MTD_IQ80310 is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=y
+# CONFIG_PCMCIA_NMCLAN is not set
+CONFIG_PCMCIA_SMC91C92=y
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_NET_PCMCIA_RADIO is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=m
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=9600
+# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+
+#
+# Other L3 adapters
+#
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_SERIO is not set
+
+#
+# Joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_SA1100_WATCHDOG=y
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+# CONFIG_I810_TCO is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_W83877F_WDT is not set
+# CONFIG_MACHZ_WDT is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_SA1100_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_CMS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_FREEVXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFSD is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYMAP=y
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_SA1100=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_SA1100=y
+# CONFIG_SOUND_SA1100SSP is not set
+# CONFIG_SOUND_OSS is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+CONFIG_MCP=y
+CONFIG_MCP_SA1100=y
+CONFIG_MCP_UCB1200=y
+CONFIG_MCP_UCB1200_AUDIO=y
+CONFIG_MCP_UCB1200_TS=y
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Controllers
+#
+
+#
+# USB Device Class drivers
+#
+
+#
+# USB Human Interface Devices (HID)
+#
+
+#
+# USB Imaging devices
+#
+
+#
+# USB Multimedia devices
+#
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+
+#
+# USB Miscellaneous drivers
+#
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_NO_FRAME_POINTER is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/def-configs/system3 b/arch/arm/def-configs/system3
new file mode 100644
index 000000000..003eae55c
--- /dev/null
+++ b/arch/arm/def-configs/system3
@@ -0,0 +1,977 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_GENERIC_BUST_SPINLOCK is not set
+# CONFIG_GENERIC_ISA_DMA is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_RPC is not set
+CONFIG_ARCH_SA1100=y
+# CONFIG_ARCH_SHARK is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Archimedes/A5000 Implementations (select only ONE)
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_ADSBITSY is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+CONFIG_SA1100_PT_SYSTEM3=y
+CONFIG_SA1111=y
+CONFIG_FORCE_MAX_ZONEORDER=9
+CONFIG_SA1100_USB=m
+CONFIG_SA1100_USB_NETLINK=m
+CONFIG_SA1100_USB_CHAR=m
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_EP7211 is not set
+# CONFIG_ARCH_EP7212 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+
+#
+# Processor Type
+#
+# CONFIG_CPU_32v3 is not set
+CONFIG_CPU_32v4=y
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM922T is not set
+# CONFIG_CPU_ARM926T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_SA110 is not set
+CONFIG_CPU_SA1100=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_DISCONTIGMEM=y
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+CONFIG_ISA=y
+# CONFIG_ISA_DMA is not set
+CONFIG_CPU_FREQ=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_CLPS6700 is not set
+CONFIG_PCMCIA_SA1100=m
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PM=y
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="noinitrd root=/dev/mtdblock3"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_BOOTLDR_PARTS=m
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_CDB89712 is not set
+CONFIG_MTD_SA1100=y
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+CONFIG_SMC9194=m
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+CONFIG_PCMCIA_SMC91C92=m
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+# CONFIG_NET_PCMCIA_RADIO is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+# CONFIG_IRNET is not set
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+# CONFIG_IRDA_OPTIONS is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+CONFIG_IRPORT_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+CONFIG_SA1100_FIR=m
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_ANAKIN is not set
+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_UART00 is not set
+# CONFIG_SERIAL_UART00_CONSOLE is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=38400
+CONFIG_SERIAL_8250=m
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=32
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+# CONFIG_L3_ALGOBIT is not set
+# CONFIG_L3_BIT_SA1100_GPIO is not set
+
+#
+# Other L3 adapters
+#
+# CONFIG_L3_SA1111 is not set
+# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_INPUT_SERIO is not set
+# CONFIG_INPUT_SERPORT is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_SA1100_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_PCMCIA_SERIAL_CS=m
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYMAP=y
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_ACORN is not set
+# CONFIG_FB_ANAKIN is not set
+# CONFIG_FB_CLPS711X is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_FONTWIDTH8_ONLY=y
+CONFIG_FBCON_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+# CONFIG_MCP_SA1100 is not set
+# CONFIG_MCP_UCB1200 is not set
+# CONFIG_MCP_UCB1200_AUDIO is not set
+# CONFIG_MCP_UCB1200_TS is not set
+
+#
+# USB support
+#
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_LONG_TIMEOUT is not set
+
+#
+# USB Controllers
+#
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+# CONFIG_USB_OHCI is not set
+CONFIG_USB_OHCI_SA1111=m
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=m
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+# CONFIG_USB_WACOM is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
+CONFIG_USB_USBNET=m
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_RIO500 is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_NO_FRAME_POINTER is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SLAB=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_WAITQ=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 42efdf5ca..2e481d241 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -7,60 +7,45 @@
USE_STANDARD_AS_RULE := true
-HEAD_OBJ = head-$(PROCESSOR).o
ENTRY_OBJ = entry-$(PROCESSOR).o
-AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR)
-AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR)
+AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR)
-# This is depreciated.
-O_OBJS_arc = dma-arc.o oldlatches.o
-O_OBJS_rpc = dma-rpc.o
-O_OBJS_footbridge = dma-footbridge.o isa.o
-O_OBJS_l7200 = fiq.o
-
-pci-ftvpci = plx90x0.o
-pci-footbridge = dec21285.o
-pci-shark = via82c505.o
-
-# this is here to allow us to eventually move it out to mach-ftvpci
-pci-$(CONFIG_ARCH_FTVPCI) += ftv-pci.o
-
-
-O_TARGET := kernel.o
+O_TARGET := kernel.o
# Object file lists.
obj-y := arch.o compat.o dma.o $(ENTRY_OBJ) entry-common.o irq.o \
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
- time.o traps.o $(O_OBJS_$(MACHINE))
+ time.o traps.o
obj-m :=
obj-n :=
obj- :=
-export-objs := armksyms.o dma.o ecard.o fiq.o io.o oldlatches.o time.o
+export-objs := armksyms.o apm.o dma.o ecard.o fiq.o io.o time.o
-no-irq-arch := $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \
- $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
- $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT)
-
-ifneq ($(findstring y,$(no-irq-arch)),y)
- obj-y += irq-arch.o
-endif
-
-obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o
-obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o
-obj-$(CONFIG_DEBUG_LL) += debug-$(PROCESSOR).o
-obj-$(CONFIG_MODULES) += armksyms.o
-obj-$(CONFIG_ARTHUR) += arthur.o
-obj-$(CONFIG_ISA_DMA) += dma-isa.o
-obj-$(CONFIG_PCI) += bios32.o $(pci-$(MACHINE)) $(pci-y)
+obj-$(CONFIG_APM) += apm.o
+obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o
+obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o
+obj-$(CONFIG_FOOTBRIDGE) += isa.o
+obj-$(CONFIG_FIQ) += fiq.o
+obj-$(CONFIG_MODULES) += armksyms.o
+obj-$(CONFIG_ARTHUR) += arthur.o
+obj-$(CONFIG_ISA_DMA) += dma-isa.o
+obj-$(CONFIG_PCI) += bios32.o
+obj-$(CONFIG_PCI_HOST_PLX90X0) += plx90x0.o
+obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
ifneq ($(MACHINE),ebsa110)
obj-y += io.o
endif
-all: kernel.o $(HEAD_OBJ) init_task.o
+ifeq ($(CONFIG_CPU_32),y)
+head-y := head.o
+obj-$(CONFIG_DEBUG_LL) += debug.o
+endif
+
+all: kernel.o $(head-y) init_task.o
include $(TOPDIR)/Rules.make
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c
index 99a6e0e0c..e1e97a8b7 100644
--- a/arch/arm/kernel/arch.c
+++ b/arch/arm/kernel/arch.c
@@ -4,19 +4,13 @@
* Architecture specific fixups.
*/
#include <linux/config.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
#include <linux/init.h>
+#include <linux/types.h>
#include <asm/elf.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
-
#include <asm/mach/arch.h>
-#include <asm/hardware/dec21285.h>
-
-extern void genarch_init_irq(void);
unsigned int vram_size;
@@ -49,129 +43,4 @@ static int __init parse_tag_acorn(const struct tag *tag)
__tagtable(ATAG_ACORN, parse_tag_acorn);
-#ifdef CONFIG_ARCH_RPC
-static void __init
-fixup_riscpc(struct machine_desc *desc, struct param_struct *unusd,
- char **cmdline, struct meminfo *mi)
-{
- /*
- * RiscPC can't handle half-word loads and stores
- */
- elf_hwcap &= ~HWCAP_HALF;
-}
-
-extern void __init rpc_map_io(void);
-
-MACHINE_START(RISCPC, "Acorn-RiscPC")
- MAINTAINER("Russell King")
- BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
- BOOT_PARAMS(0x10000100)
- DISABLE_PARPORT(0)
- DISABLE_PARPORT(1)
- FIXUP(fixup_riscpc)
- MAPIO(rpc_map_io)
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-#ifdef CONFIG_ARCH_ARC
-MACHINE_START(ARCHIMEDES, "Acorn-Archimedes")
- MAINTAINER("Dave Gilbert")
- BOOT_PARAMS(0x0207c000)
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-#ifdef CONFIG_ARCH_A5K
-MACHINE_START(A5K, "Acorn-A5000")
- MAINTAINER("Russell King")
- BOOT_PARAMS(0x0207c000)
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-#endif
-
-#ifdef CONFIG_ARCH_L7200
-extern void __init l7200_map_io(void);
-
-static void __init
-fixup_l7200(struct machine_desc *desc, struct param_struct *unused,
- char **cmdline, struct meminfo *mi)
-{
- mi->nr_banks = 1;
- mi->bank[0].start = PHYS_OFFSET;
- mi->bank[0].size = (32*1024*1024);
- mi->bank[0].node = 0;
-
- ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
- setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE);
- setup_initrd( __phys_to_virt(0xf1000000), 0x005dac7b);
-
- /* Serial Console COM2 and LCD */
- strcpy( *cmdline, "console=tty0 console=ttyLU1,115200");
-
- /* Serial Console COM1 and LCD */
- //strcpy( *cmdline, "console=tty0 console=ttyLU0,115200");
-
- /* Console on LCD */
- //strcpy( *cmdline, "console=tty0");
-}
-
-MACHINE_START(L7200, "LinkUp Systems L7200")
- MAINTAINER("Steve Hill / Scott McConnell")
- BOOT_MEM(0xf0000000, 0x80040000, 0xd0000000)
- FIXUP(fixup_l7200)
- MAPIO(l7200_map_io)
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-
-#ifdef CONFIG_ARCH_NEXUSPCI
-
-extern void __init nexuspci_map_io(void);
-
-MACHINE_START(NEXUSPCI, "FTV/PCI")
- MAINTAINER("Philip Blundell")
- BOOT_MEM(0x40000000, 0x10000000, 0xe0000000)
- MAPIO(nexuspci_map_io)
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-#ifdef CONFIG_ARCH_TBOX
-
-extern void __init tbox_map_io(void);
-
-MACHINE_START(TBOX, "unknown-TBOX")
- MAINTAINER("Philip Blundell")
- BOOT_MEM(0x80000000, 0x00400000, 0xe0000000)
- MAPIO(tbox_map_io)
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-#ifdef CONFIG_ARCH_CLPS7110
-MACHINE_START(CLPS7110, "CL-PS7110")
- MAINTAINER("Werner Almesberger")
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-#ifdef CONFIG_ARCH_ETOILE
-MACHINE_START(ETOILE, "Etoile")
- MAINTAINER("Alex de Vries")
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-#ifdef CONFIG_ARCH_LACIE_NAS
-MACHINE_START(LACIE_NAS, "LaCie_NAS")
- MAINTAINER("Benjamin Herrenschmidt")
- INITIRQ(genarch_init_irq)
-MACHINE_END
-#endif
-#ifdef CONFIG_ARCH_CLPS7500
-
-extern void __init clps7500_map_io(void);
-
-MACHINE_START(CLPS7500, "CL-PS7500")
- MAINTAINER("Philip Blundell")
- BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
- MAPIO(clps7500_map_io)
- INITIRQ(genarch_init_irq)
-MACHINE_END
#endif
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index fc9cc15a9..4c496827b 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -19,6 +19,7 @@
#include <linux/in6.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
+#include <linux/tty.h>
#include <linux/vt_kern.h>
#include <asm/byteorder.h>
@@ -77,7 +78,7 @@ extern void fp_enter(void);
extern void __do_softirq(void);
#define EXPORT_SYMBOL_ALIAS(sym,orig) \
- const char __kstrtab_##sym##[] \
+ const char __kstrtab_##sym[] \
__attribute__((section(".kstrtab"))) = \
__MODULE_STRING(sym); \
const struct module_symbol __ksymtab_##sym \
@@ -115,7 +116,9 @@ EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(system_rev);
EXPORT_SYMBOL(system_serial_low);
EXPORT_SYMBOL(system_serial_high);
+#ifdef CONFIG_DEBUG_BUGVERBOSE
EXPORT_SYMBOL(__bug);
+#endif
EXPORT_SYMBOL(__bad_xchg);
EXPORT_SYMBOL(__readwrite_bug);
EXPORT_SYMBOL(enable_irq);
@@ -231,14 +234,25 @@ EXPORT_SYMBOL_NOVERS(__udivsi3);
EXPORT_SYMBOL_NOVERS(__umodsi3);
/* bitops */
-EXPORT_SYMBOL(set_bit);
-EXPORT_SYMBOL(test_and_set_bit);
-EXPORT_SYMBOL(clear_bit);
-EXPORT_SYMBOL(test_and_clear_bit);
-EXPORT_SYMBOL(change_bit);
-EXPORT_SYMBOL(test_and_change_bit);
-EXPORT_SYMBOL(find_first_zero_bit);
-EXPORT_SYMBOL(find_next_zero_bit);
+EXPORT_SYMBOL(_set_bit_le);
+EXPORT_SYMBOL(_test_and_set_bit_le);
+EXPORT_SYMBOL(_clear_bit_le);
+EXPORT_SYMBOL(_test_and_clear_bit_le);
+EXPORT_SYMBOL(_change_bit_le);
+EXPORT_SYMBOL(_test_and_change_bit_le);
+EXPORT_SYMBOL(_find_first_zero_bit_le);
+EXPORT_SYMBOL(_find_next_zero_bit_le);
+
+#ifdef __ARMEB__
+EXPORT_SYMBOL(_set_bit_be);
+EXPORT_SYMBOL(_test_and_set_bit_be);
+EXPORT_SYMBOL(_clear_bit_be);
+EXPORT_SYMBOL(_test_and_clear_bit_be);
+EXPORT_SYMBOL(_change_bit_be);
+EXPORT_SYMBOL(_test_and_change_bit_be);
+EXPORT_SYMBOL(_find_first_zero_bit_be);
+EXPORT_SYMBOL(_find_next_zero_bit_be);
+#endif
/* elf */
EXPORT_SYMBOL(elf_platform);
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 5da4d39ba..6558faf6e 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -19,20 +19,6 @@
static int debug_pci;
int have_isa_bridge;
-struct pci_sys_data {
- /*
- * The hardware we are attached to
- */
- struct hw_pci *hw;
-
- unsigned long mem_offset;
-
- /*
- * These are the resources for the root bus.
- */
- struct resource *resource[3];
-};
-
void pcibios_report_status(u_int status_mask, int warn)
{
struct pci_dev *dev;
@@ -153,8 +139,7 @@ static void __init pci_fixup_dec21285(struct pci_dev *dev)
}
/*
- * PCI IDE controllers use non-standard I/O port
- * decoding, respect it.
+ * PCI IDE controllers use non-standard I/O port decoding, respect it.
*/
static void __init pci_fixup_ide_bases(struct pci_dev *dev)
{
@@ -181,9 +166,82 @@ static void __init pci_fixup_dec21142(struct pci_dev *dev)
pci_write_config_dword(dev, 0x40, 0x80000000);
}
+/*
+ * The CY82C693 needs some rather major fixups to ensure that it does
+ * the right thing. Idea from the Alpha people, with a few additions.
+ *
+ * We ensure that the IDE base registers are set to 1f0/3f4 for the
+ * primary bus, and 170/374 for the secondary bus. Also, hide them
+ * from the PCI subsystem view as well so we won't try to perform
+ * our own auto-configuration on them.
+ *
+ * In addition, we ensure that the PCI IDE interrupts are routed to
+ * IRQ 14 and IRQ 15 respectively.
+ *
+ * The above gets us to a point where the IDE on this device is
+ * functional. However, The CY82C693U _does not work_ in bus
+ * master mode without locking the PCI bus solid.
+ */
+static void __init pci_fixup_cy82c693(struct pci_dev *dev)
+{
+ if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+ u32 base0, base1;
+
+ if (dev->class & 0x80) { /* primary */
+ base0 = 0x1f0;
+ base1 = 0x3f4;
+ } else { /* secondary */
+ base0 = 0x170;
+ base1 = 0x374;
+ }
+
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ base0 | PCI_BASE_ADDRESS_SPACE_IO);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
+ base1 | PCI_BASE_ADDRESS_SPACE_IO);
+
+ dev->resource[0].start = 0;
+ dev->resource[0].end = 0;
+ dev->resource[0].flags = 0;
+
+ dev->resource[1].start = 0;
+ dev->resource[1].end = 0;
+ dev->resource[1].flags = 0;
+ } else if (PCI_FUNC(dev->devfn) == 0) {
+ /*
+ * Setup IDE IRQ routing.
+ */
+ pci_write_config_byte(dev, 0x4b, 14);
+ pci_write_config_byte(dev, 0x4c, 15);
+
+ /*
+ * Disable FREQACK handshake, enable USB.
+ */
+ pci_write_config_byte(dev, 0x4d, 0x41);
+
+ /*
+ * Enable PCI retry, and PCI post-write buffer.
+ */
+ pci_write_config_byte(dev, 0x44, 0x17);
+
+ /*
+ * Enable ISA master and DMA post write buffering.
+ */
+ pci_write_config_byte(dev, 0x45, 0x03);
+ }
+}
+
struct pci_fixup pcibios_fixups[] = {
{
PCI_FIXUP_HEADER,
+ PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
+ pci_fixup_cy82c693
+ }, {
+ PCI_FIXUP_HEADER,
+ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
+ pci_fixup_dec21142
+ }, {
+ PCI_FIXUP_HEADER,
PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285,
pci_fixup_dec21285
}, {
@@ -198,10 +256,6 @@ struct pci_fixup pcibios_fixups[] = {
PCI_FIXUP_HEADER,
PCI_ANY_ID, PCI_ANY_ID,
pci_fixup_ide_bases
- }, {
- PCI_FIXUP_HEADER,
- PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
- pci_fixup_dec21142
}, { 0 }
};
@@ -232,6 +286,8 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
val = res->start;
if (res->flags & IORESOURCE_MEM)
val -= sys->mem_offset;
+ else
+ val -= sys->io_offset;
val |= res->flags & PCI_REGION_FLAG_MASK;
pci_write_config_dword(dev, reg, val);
@@ -268,15 +324,19 @@ static inline int pdev_bad_for_parity(struct pci_dev *dev)
static void __init
pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
{
+ unsigned long offset;
int i;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
if (dev->resource[i].start == 0)
continue;
- if (dev->resource[i].flags & IORESOURCE_MEM) {
- dev->resource[i].start += root->mem_offset;
- dev->resource[i].end += root->mem_offset;
- }
+ if (dev->resource[i].flags & IORESOURCE_MEM)
+ offset = root->mem_offset;
+ else
+ offset = root->io_offset;
+
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
}
}
@@ -388,15 +448,116 @@ pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *rang
{
struct pci_sys_data *root = bus->sysdata;
+ ranges->io_start -= root->io_offset;
+ ranges->io_end -= root->io_offset;
ranges->mem_start -= root->mem_offset;
ranges->mem_end -= root->mem_offset;
ranges->prefetch_start -= root->mem_offset;
ranges->prefetch_end -= root->mem_offset;
}
-u8 __init no_swizzle(struct pci_dev *dev, u8 *pin)
+/*
+ * This is the standard PCI-PCI bridge swizzling algorithm:
+ *
+ * Dev: 0 1 2 3
+ * A A B C D
+ * B B C D A
+ * C C D A B
+ * D D A B C
+ * ^^^^^^^^^^ irq pin on bridge
+ */
+u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp)
{
- return 0;
+ int pin = *pinp;
+
+ if (pin != 0) {
+ pin -= 1;
+ while (dev->bus->self) {
+ pin = (pin + PCI_SLOT(dev->devfn)) & 3;
+ /*
+ * move up the chain of bridges,
+ * swizzling as we go.
+ */
+ dev = dev->bus->self;
+ }
+ *pinp = pin + 1;
+ }
+
+ return PCI_SLOT(dev->devfn);
+}
+
+/*
+ * Swizzle the device pin each time we cross a bridge.
+ * This might update pin and returns the slot number.
+ */
+static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
+{
+ struct pci_sys_data *sys = dev->sysdata;
+ int slot = 0, oldpin = *pin;
+
+ if (sys->swizzle)
+ slot = sys->swizzle(dev, pin);
+
+ if (debug_pci)
+ printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
+ dev->slot_name, oldpin, *pin, slot);
+
+ return slot;
+}
+
+/*
+ * Map a slot/pin to an IRQ.
+ */
+static int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ struct pci_sys_data *sys = dev->sysdata;
+ int irq = -1;
+
+ if (sys->map_irq)
+ irq = sys->map_irq(dev, slot, pin);
+
+ if (debug_pci)
+ printk("PCI: %s mapping slot %d pin %d => irq %d\n",
+ dev->slot_name, slot, pin, irq);
+
+ return irq;
+}
+
+static void __init pcibios_init_hw(struct hw_pci *hw)
+{
+ struct pci_sys_data *sys = NULL;
+ int ret;
+ int nr, busnr;
+
+ for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
+ sys = kmalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
+ if (!sys)
+ panic("PCI: unable to allocate sys data!");
+
+ memset(sys, 0, sizeof(struct pci_sys_data));
+
+ sys->hw = hw;
+ sys->busnr = busnr;
+ sys->swizzle = hw->swizzle;
+ sys->map_irq = hw->map_irq;
+ sys->resource[0] = &ioport_resource;
+ sys->resource[1] = &iomem_resource;
+
+ ret = hw->setup(nr, sys);
+
+ if (ret > 0) {
+ sys->bus = hw->scan(nr, sys);
+
+ if (!sys->bus)
+ panic("PCI: unable to scan bus!");
+
+ busnr = sys->bus->subordinate + 1;
+ } else if (ret < 0)
+ break;
+ }
+
+ kfree(sys);
+
}
extern struct hw_pci ebsa285_pci;
@@ -406,10 +567,10 @@ extern struct hw_pci personal_server_pci;
extern struct hw_pci ftv_pci;
extern struct hw_pci shark_pci;
extern struct hw_pci integrator_pci;
+extern struct hw_pci iq80310_pci;
void __init pcibios_init(void)
{
- struct pci_sys_data *root;
struct hw_pci *hw = NULL;
do {
@@ -455,44 +616,28 @@ void __init pcibios_init(void)
break;
}
#endif
+#ifdef CONFIG_ARCH_IQ80310
+ if (machine_is_iq80310()) {
+ hw = &iq80310_pci;
+ break;
+ }
+#endif
} while (0);
if (hw == NULL)
return;
- root = kmalloc(sizeof(*root), GFP_KERNEL);
- if (!root)
- panic("PCI: unable to allocate root data!");
-
- root->hw = hw;
- root->mem_offset = hw->mem_offset;
-
- memset(root->resource, 0, sizeof(root->resource));
-
- /*
- * Setup the resources for this bus.
- * resource[0] - IO ports
- * resource[1] - non-prefetchable memory
- * resource[2] - prefetchable memory
- */
- if (root->hw->setup_resources)
- root->hw->setup_resources(root->resource);
- else {
- root->resource[0] = &ioport_resource;
- root->resource[1] = &iomem_resource;
- root->resource[2] = NULL;
- }
-
- /*
- * Set up the host bridge, and scan the bus.
- */
- root->hw->init(root);
+ if (hw->preinit)
+ hw->preinit();
+ pcibios_init_hw(hw);
+ if (hw->postinit)
+ hw->postinit();
/*
* Assign any unassigned resources.
*/
pci_assign_unassigned_resources();
- pci_fixup_irqs(root->hw->swizzle, root->hw->map_irq);
+ pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
}
char * __init pcibios_setup(char *str)
diff --git a/arch/arm/kernel/compat.c b/arch/arm/kernel/compat.c
index 676febed1..624136709 100644
--- a/arch/arm/kernel/compat.c
+++ b/arch/arm/kernel/compat.c
@@ -89,10 +89,12 @@ static void __init build_tag_list(struct param_struct *params, void *taglist, in
}
#ifdef CONFIG_FOOTBRIDGE
- tag = tag_next(tag);
- tag->hdr.tag = ATAG_MEMCLK;
- tag->hdr.size = tag_size(tag_memclk);
- tag->u.memclk.fmemclk = params->u1.s.mem_fclk_21285;
+ if (params->u1.s.mem_fclk_21285) {
+ tag = tag_next(tag);
+ tag->hdr.tag = ATAG_MEMCLK;
+ tag->hdr.size = tag_size(tag_memclk);
+ tag->u.memclk.fmemclk = params->u1.s.mem_fclk_21285;
+ }
#endif
#ifdef CONFIG_ARCH_ACORN
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 4a055a125..1d36940b8 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -95,7 +95,7 @@ static void isa_enable_dma(dmach_t channel, dma_t *dma)
* coherence.
*/
dma->buf.dma_address = pci_map_single(NULL,
- dma->buf.address, dma->buf.length,
+ dma->buf.__address, dma->buf.length,
direction);
}
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 7f0106953..383e93975 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -139,7 +139,7 @@ void set_dma_addr (dmach_t channel, unsigned long physaddr)
dma->sg = &dma->buf;
dma->sgcount = 1;
- dma->buf.address = bus_to_virt(physaddr);
+ dma->buf.__address = bus_to_virt(physaddr);
dma->using_sg = 0;
dma->invalid = 1;
}
@@ -275,6 +275,8 @@ GLOBAL_ALIAS(init_dma, get_dma_residue);
#endif
+EXPORT_SYMBOL(request_dma);
+EXPORT_SYMBOL(free_dma);
EXPORT_SYMBOL(enable_dma);
EXPORT_SYMBOL(disable_dma);
EXPORT_SYMBOL(set_dma_addr);
diff --git a/arch/arm/kernel/entry-armo.S b/arch/arm/kernel/entry-armo.S
index b0bc88a1f..77c8ed015 100644
--- a/arch/arm/kernel/entry-armo.S
+++ b/arch/arm/kernel/entry-armo.S
@@ -169,7 +169,7 @@ vector_undefinstr:
bne __und_svc
save_user_regs
zero_fp
- teqp pc, #I_BIT | MODE_SVC
+ teqp pc, #PSR_I_BIT | MODE_SVC
.Lbug_undef:
ldr r4, .LC2
ldr pc, [r4] @ Call FP module USR entry point
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 6c31b56c0..889ddca82 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -548,6 +548,39 @@ ENTRY(anakin_active_irqs)
.text
.endm
+#elif defined(CONFIG_ARCH_IOP310) || defined(CONFIG_ARCH_ADIFCC)
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ mrc p13, 0, \irqstat, c4, c0, 0 @ get INTSRC
+ mrc p13, 0, \base, c0, c0, 0 @ get INTCTL
+
+ tst \irqstat, #(1<<29) @ if INTSRC_BI
+ tstne \base, #(1<<3) @ and INTCTL_BM
+ movne \irqnr, #IRQ_XS80200_BCU
+ bne 1001f
+
+ tst \irqstat, #(1<<28) @ if INTSRC_PI
+ tstne \base, #(1<<2) @ and INTCTL_PM
+ movne \irqnr, #IRQ_XS80200_PMU
+ bne 1001f
+
+ tst \irqstat, #(1<<31) @ if INTSRC_FI
+ tstne \base, #(1<<0) @ and INTCTL_FM
+ movne \irqnr, #IRQ_XS80200_EXTFIQ
+ bne 1001f
+
+ tst \irqstat, #(1<<30) @ if INTSRC_II
+ tstne \base, #(1<<1) @ and INTCTL_IM
+ movne \irqnr, #IRQ_XS80200_EXTIRQ
+
+1001:
+ .endm
+
+ .macro irq_prio_table
+ .endm
#else
#error Unknown architecture
#endif
@@ -641,23 +674,23 @@ __dabt_svc: sub sp, sp, #S_FRAME_SIZE
mov r1, lr
stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
mrs r9, cpsr @ Enable interrupts if they were
- tst r3, #I_BIT
- biceq r9, r9, #I_BIT @ previously
- mov r0, r2
+ tst r3, #PSR_I_BIT
+ biceq r9, r9, #PSR_I_BIT @ previously
+ mov r0, r2 @ *** remove once everyones in sync
/*
* This routine must not corrupt r9
*/
#ifdef MULTI_CPU
- ldr r2, .LCprocfns @ pass r0, r3 to
+ ldr r4, .LCprocfns @ pass r0, r3 to
mov lr, pc @ processor code
- ldr pc, [r2] @ call processor specific code
+ ldr pc, [r4] @ call processor specific code
#else
bl cpu_data_abort
#endif
msr cpsr_c, r9
mov r2, sp
bl SYMBOL_NAME(do_DataAbort)
- mov r0, #I_BIT | MODE_SVC
+ mov r0, #PSR_I_BIT | MODE_SVC
msr cpsr_c, r0
ldr r0, [sp, #S_PSR]
msr spsr, r0
@@ -700,7 +733,7 @@ __und_svc: sub sp, sp, #S_FRAME_SIZE
mov r1, sp @ struct pt_regs *regs
bl SYMBOL_NAME(do_undefinstr)
-1: mov r0, #I_BIT | MODE_SVC
+1: mov r0, #PSR_I_BIT | MODE_SVC
msr cpsr_c, r0
ldr lr, [sp, #S_PSR] @ Get SVC cpsr
msr spsr, lr
@@ -716,13 +749,13 @@ __pabt_svc: sub sp, sp, #S_FRAME_SIZE
mov r1, lr
stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
mrs r9, cpsr @ Enable interrupts if they were
- tst r3, #I_BIT
- biceq r9, r9, #I_BIT @ previously
+ tst r3, #PSR_I_BIT
+ biceq r9, r9, #PSR_I_BIT @ previously
msr cpsr_c, r9
mov r0, r2 @ address (pc)
mov r1, sp @ regs
bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler
- mov r0, #I_BIT | MODE_SVC
+ mov r0, #PSR_I_BIT | MODE_SVC
msr cpsr_c, r0
ldr r0, [sp, #S_PSR]
msr spsr, r0
@@ -747,15 +780,16 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia sp, {r0 - r12} @ save r0 - r12
ldr r7, .LCabt
add r5, sp, #S_PC
- ldmia r7, {r0, r3, r4} @ Get USR pc, cpsr
- stmia r5, {r0, r3, r4} @ Save USR pc, cpsr, old_r0
+ ldmia r7, {r2 - r4} @ Get USR pc, cpsr
+ stmia r5, {r2 - r4} @ Save USR pc, cpsr, old_r0
stmdb r5, {sp, lr}^
alignment_trap r7, r7, __temp_abt
zero_fp
+ mov r0, r2 @ remove once everyones in sync
#ifdef MULTI_CPU
- ldr r2, .LCprocfns @ pass r0, r3 to
+ ldr r4, .LCprocfns @ pass r0, r3 to
mov lr, pc @ processor code
- ldr pc, [r2] @ call processor specific code
+ ldr pc, [r4] @ call processor specific code
#else
bl cpu_data_abort
#endif
@@ -883,7 +917,7 @@ vector_IRQ: @
@
@ now branch to the relevent MODE handling routine
@
- mov r13, #I_BIT | MODE_SVC
+ mov r13, #PSR_I_BIT | MODE_SVC
msr spsr_c, r13 @ switch to SVC_32 mode
and lr, lr, #15
@@ -924,7 +958,7 @@ vector_data: @
@
@ now branch to the relevent MODE handling routine
@
- mov r13, #I_BIT | MODE_SVC
+ mov r13, #PSR_I_BIT | MODE_SVC
msr spsr_c, r13 @ switch to SVC_32 mode
and lr, lr, #15
@@ -966,7 +1000,7 @@ vector_prefetch:
@
@ now branch to the relevent MODE handling routine
@
- mov r13, #I_BIT | MODE_SVC
+ mov r13, #PSR_I_BIT | MODE_SVC
msr spsr_c, r13 @ switch to SVC_32 mode
ands lr, lr, #15
@@ -1007,7 +1041,7 @@ vector_undefinstr:
@
@ now branch to the relevent MODE handling routine
@
- mov r13, #I_BIT | MODE_SVC
+ mov r13, #PSR_I_BIT | MODE_SVC
msr spsr_c, r13 @ switch to SVC_32 mode
and lr, lr, #15
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 5f645f0c4..2947d32a8 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -22,12 +22,10 @@
* Our do_softirq out of line code. See include/asm-arm/softirq.h for
* the calling assembly.
*/
- .section ".text.lock","ax"
ENTRY(__do_softirq)
stmfd sp!, {r0 - r3, ip, lr}
bl do_softirq
ldmfd sp!, {r0 - r3, ip, pc}
- .previous
.align 5
/*
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index c9c457dbf..184145c2b 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -83,7 +83,7 @@
.macro restore_user_regs
ldr r0, [sp, #S_PSR] @ Get calling cpsr
- mov ip, #I_BIT | MODE_SVC
+ mov ip, #PSR_I_BIT | MODE_SVC
msr cpsr_c, ip @ disable IRQs
msr spsr, r0 @ save in spsr_svc
ldr lr, [sp, #S_PC] @ Get PC
@@ -94,7 +94,7 @@
.endm
.macro fast_restore_user_regs
- mov ip, #I_BIT | MODE_SVC
+ mov ip, #PSR_I_BIT | MODE_SVC
msr cpsr_c, ip @ disable IRQs
ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
ldr lr, [sp, #S_OFF + S_PC]! @ get pc
@@ -207,7 +207,7 @@ tsk .req r9 @ current task
*/
.macro get_scno
#ifdef CONFIG_ARM_THUMB
- tst r8, #T_BIT @ this is SPSR from save_user_regs
+ tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
addne scno, r7, #OS_NUMBER << 20 @ put OS number in
ldreq scno, [lr, #-4]
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index e0ce969ea..cdf9655f3 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -139,7 +139,7 @@ void set_fiq_regs(struct pt_regs *regs)
mov r0, r0"
#endif
: "=&r" (tmp), "=&r" (tmp2)
- : "r" (&regs->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE)
+ : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
/* These registers aren't modified by the above code in a way
visible to the compiler, but we mark them as clobbers anyway
so that GCC won't put any of the input or output operands in
@@ -171,7 +171,7 @@ void get_fiq_regs(struct pt_regs *regs)
mov r0, r0"
#endif
: "=&r" (tmp), "=&r" (tmp2)
- : "r" (&regs->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE)
+ : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
/* These registers aren't modified by the above code in a way
visible to the compiler, but we mark them as clobbers anyway
so that GCC won't put any of the input or output operands in
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
index 480c025fb..7245a45b0 100644
--- a/arch/arm/kernel/init_task.c
+++ b/arch/arm/kernel/init_task.c
@@ -9,7 +9,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 60049c59d..e6e9606f7 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -114,7 +114,7 @@ int show_interrupts(struct seq_file *p, void *v)
}
#ifdef CONFIG_ARCH_ACORN
- show_fiq_list(p);
+ show_fiq_list(p, v);
#endif
seq_printf(p, "Err: %10lu\n", irq_err_count);
return 0;
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index f34403608..741984e0c 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -85,7 +85,6 @@ void cpu_idle(void)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
while (1) {
void (*idle)(void) = pm_idle;
@@ -173,10 +172,10 @@ void show_regs(struct pt_regs * regs)
regs->ARM_r3, regs->ARM_r2,
regs->ARM_r1, regs->ARM_r0);
printk("Flags: %c%c%c%c",
- flags & CC_N_BIT ? 'N' : 'n',
- flags & CC_Z_BIT ? 'Z' : 'z',
- flags & CC_C_BIT ? 'C' : 'c',
- flags & CC_V_BIT ? 'V' : 'v');
+ flags & PSR_N_BIT ? 'N' : 'n',
+ flags & PSR_Z_BIT ? 'Z' : 'z',
+ flags & PSR_C_BIT ? 'C' : 'c',
+ flags & PSR_V_BIT ? 'V' : 'v');
printk(" IRQs %s FIQs %s Mode %s%s Segment %s\n",
interrupts_enabled(regs) ? "on" : "off",
fast_interrupts_enabled(regs) ? "on" : "off",
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index 969f09546..19aa6e922 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -177,8 +177,7 @@ int __down_trylock(struct semaphore * sem)
* value in some cases..
*/
#ifdef CONFIG_CPU_26
-asm(" .section .text.lock, \"ax\"
- .align 5
+asm(" .align 5
.globl __down_failed
__down_failed:
stmfd sp!, {r0 - r3, lr}
@@ -211,14 +210,11 @@ __up_wakeup:
mov r0, ip
bl __up
ldmfd sp!, {r0 - r3, pc}^
-
- .previous
");
#else
/* 32 bit version */
-asm(" .section .text.lock, \"ax\"
- .align 5
+asm(" .align 5
.globl __down_failed
__down_failed:
stmfd sp!, {r0 - r3, lr}
@@ -251,8 +247,6 @@ __up_wakeup:
mov r0, ip
bl __up
ldmfd sp!, {r0 - r3, pc}
-
- .previous
");
#endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index f7a26043c..fbec81f49 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -17,6 +17,7 @@
#include <linux/console.h>
#include <linux/bootmem.h>
#include <linux/seq_file.h>
+#include <linux/tty.h>
#include <linux/init.h>
#include <asm/elf.h>
@@ -105,6 +106,109 @@ static struct resource io_res[] = {
#define lp1 io_res[1]
#define lp2 io_res[2]
+#ifdef CONFIG_CPU_32
+static const char *cache_types[16] = {
+ "write-through",
+ "write-back",
+ "write-back",
+ "undefined 3",
+ "undefined 4",
+ "undefined 5",
+ "write-back",
+ "write-back",
+ "undefined 8",
+ "undefined 9",
+ "undefined 10",
+ "undefined 11",
+ "undefined 12",
+ "undefined 13",
+ "undefined 14",
+ "undefined 15",
+};
+
+static const char *cache_clean[16] = {
+ "not required",
+ "read-block",
+ "cp15 c7 ops",
+ "undefined 3",
+ "undefined 4",
+ "undefined 5",
+ "cp15 c7 ops",
+ "cp15 c7 ops",
+ "undefined 8",
+ "undefined 9",
+ "undefined 10",
+ "undefined 11",
+ "undefined 12",
+ "undefined 13",
+ "undefined 14",
+ "undefined 15",
+};
+
+static const char *cache_lockdown[16] = {
+ "not supported",
+ "not supported",
+ "not supported",
+ "undefined 3",
+ "undefined 4",
+ "undefined 5",
+ "format A",
+ "format B",
+ "undefined 8",
+ "undefined 9",
+ "undefined 10",
+ "undefined 11",
+ "undefined 12",
+ "undefined 13",
+ "undefined 14",
+ "undefined 15",
+};
+
+#define CACHE_TYPE(x) (((x) >> 25) & 15)
+#define CACHE_S(x) ((x) & (1 << 24))
+#define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */
+#define CACHE_ISIZE(x) ((x) & 4095)
+
+#define CACHE_SIZE(y) (((y) >> 6) & 7)
+#define CACHE_ASSOC(y) (((y) >> 3) & 7)
+#define CACHE_M(y) ((y) & (1 << 2))
+#define CACHE_LINE(y) ((y) & 3)
+
+static inline void dump_cache(const char *prefix, unsigned int cache)
+{
+ unsigned int mult = 2 + CACHE_M(cache) ? 1 : 0;
+
+ printk("%s size %dK associativity %d line length %d sets %d\n",
+ prefix,
+ mult << (8 + CACHE_SIZE(cache)),
+ (mult << CACHE_ASSOC(cache)) >> 1,
+ 8 << CACHE_LINE(cache),
+ 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
+ CACHE_LINE(cache)));
+}
+
+static inline void dump_cpu_cache_id(void)
+{
+ unsigned int cache_info;
+
+ asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
+
+ if (cache_info == processor_id)
+ return;
+
+ printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(cache_info)]);
+ if (CACHE_S(cache_info)) {
+ dump_cache("CPU: I cache", CACHE_ISIZE(cache_info));
+ dump_cache("CPU: D cache", CACHE_DSIZE(cache_info));
+ } else {
+ dump_cache("CPU: cache", CACHE_ISIZE(cache_info));
+ }
+}
+
+#else
+#define dump_cpu_cache_id() do { } while (0)
+#endif
+
static void __init setup_processor(void)
{
extern struct proc_info_list __proc_info_begin, __proc_info_end;
@@ -139,6 +243,8 @@ static void __init setup_processor(void)
proc_info.manufacturer, proc_info.cpu_name,
(int)processor_id & 15);
+ dump_cpu_cache_id();
+
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
elf_hwcap = list->elf_hwcap;
@@ -146,7 +252,7 @@ static void __init setup_processor(void)
cpu_proc_init();
}
-static struct machine_desc * __init setup_architecture(unsigned int nr)
+static struct machine_desc * __init setup_machine(unsigned int nr)
{
extern struct machine_desc __arch_info_begin, __arch_info_end;
struct machine_desc *list;
@@ -168,7 +274,7 @@ static struct machine_desc * __init setup_architecture(unsigned int nr)
while (1);
}
- printk("Architecture: %s\n", list->name);
+ printk("Machine: %s\n", list->name);
if (compat)
printk(KERN_WARNING "Using compatibility code "
"scheduled for removal in v%d.%d.%d\n",
@@ -231,7 +337,7 @@ void __init
setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
{
#ifdef CONFIG_BLK_DEV_RAM
- extern int rd_size;
+ extern int rd_size, rd_image_start, rd_prompt, rd_doload;
rd_image_start = image_start;
rd_prompt = prompt;
@@ -458,10 +564,10 @@ void __init setup_arch(char **cmdline_p)
struct machine_desc *mdesc;
char *from = default_command_line;
- ROOT_DEV = MKDEV(0, 255);
+ ROOT_DEV = mk_kdev(0, 255);
setup_processor();
- mdesc = setup_architecture(machine_arch_type);
+ mdesc = setup_machine(machine_arch_type);
machine_name = mdesc->name;
if (mdesc->soft_reboot)
@@ -533,6 +639,41 @@ static const char *hwcap_str[] = {
NULL
};
+static const char *proc_arch[16] = {
+ "undefined 0",
+ "4",
+ "4T",
+ "5",
+ "5T",
+ "5TE",
+ "undefined 6",
+ "undefined 7",
+ "undefined 8",
+ "undefined 9",
+ "undefined 10",
+ "undefined 11",
+ "undefined 12",
+ "undefined 13",
+ "undefined 14",
+ "undefined 15"
+};
+
+static void
+c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
+{
+ unsigned int mult = 2 + CACHE_M(cache) ? 1 : 0;
+
+ seq_printf(m, "%s size\t\t: %d\n"
+ "%s assoc\t\t: %d\n"
+ "%s line length\t: %d\n"
+ "%s sets\t\t: %d\n",
+ type, mult << (8 + CACHE_SIZE(cache)),
+ type, (mult << CACHE_ASSOC(cache)) >> 1,
+ type, 8 << CACHE_LINE(cache),
+ type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
+ CACHE_LINE(cache)));
+}
+
static int c_show(struct seq_file *m, void *v)
{
int i;
@@ -552,7 +693,60 @@ static int c_show(struct seq_file *m, void *v)
if (elf_hwcap & (1 << i))
seq_printf(m, "%s ", hwcap_str[i]);
- seq_puts(m, "\n\n");
+ seq_puts(m, "\n");
+
+ if ((processor_id & 0x0000f000) == 0x00000000) {
+ /* pre-ARM7 */
+ seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
+ } else if ((processor_id & 0x0000f000) == 0x00007000) {
+ /* ARM7 */
+ seq_printf(m, "CPU implementor\t: 0x%02x\n"
+ "CPU architecture: %s\n"
+ "CPU variant\t: 0x%02x\n"
+ "CPU part\t: 0x%03x\n",
+ processor_id >> 24,
+ processor_id & (1 << 23) ? "4T" : "3",
+ (processor_id >> 16) & 127,
+ (processor_id >> 4) & 0xfff);
+ } else {
+ /* post-ARM7 */
+ seq_printf(m, "CPU implementor\t: 0x%02x\n"
+ "CPU architecture: %s\n"
+ "CPU variant\t: 0x%x\n"
+ "CPU part\t: 0x%03x\n",
+ processor_id >> 24,
+ proc_arch[(processor_id >> 16) & 15],
+ (processor_id >> 20) & 15,
+ (processor_id >> 4) & 0xfff);
+ }
+ seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
+
+#ifdef CONFIG_CPU_32
+ {
+ unsigned int cache_info;
+
+ asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
+ if (cache_info != processor_id) {
+ seq_printf(m, "Cache type\t: %s\n"
+ "Cache clean\t: %s\n"
+ "Cache lockdown\t: %s\n"
+ "Cache unified\t: %s\n",
+ cache_types[CACHE_TYPE(cache_info)],
+ cache_clean[CACHE_TYPE(cache_info)],
+ cache_lockdown[CACHE_TYPE(cache_info)],
+ CACHE_S(cache_info) ? "separate I,D" : "unified");
+
+ if (CACHE_S(cache_info)) {
+ c_show_cache(m, "I", CACHE_ISIZE(cache_info));
+ c_show_cache(m, "D", CACHE_DSIZE(cache_info));
+ } else {
+ c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
+ }
+ }
+ }
+#endif
+
+ seq_puts(m, "\n");
seq_printf(m, "Hardware\t: %s\n", machine_name);
seq_printf(m, "Revision\t: %04x\n", system_rev);
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 0d5bc71ae..d2bc87e2e 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -344,7 +344,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
/*
* This is the X/Open sanctioned signal stack switching.
*/
- if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(sp))
+ if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
/*
@@ -378,9 +378,9 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
thumb = handler & 1;
if (thumb)
- cpsr |= T_BIT;
+ cpsr |= PSR_T_BIT;
else
- cpsr &= ~T_BIT;
+ cpsr &= ~PSR_T_BIT;
}
#endif
#endif
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 2d4cbd916..e0ef62055 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -2,7 +2,7 @@
* linux/arch/arm/kernel/time.c
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
- * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King
+ * Modifications for ARM (C) 1994-2001 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -24,13 +24,12 @@
#include <linux/time.h>
#include <linux/init.h>
#include <linux/smp.h>
+#include <linux/timex.h>
-#include <asm/uaccess.h>
+#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
-
-#include <linux/timex.h>
-#include <asm/hardware.h>
+#include <asm/leds.h>
extern int setup_arm_irq(int, struct irqaction *);
extern rwlock_t xtime_lock;
@@ -122,18 +121,14 @@ static inline void do_set_rtc(void)
#ifdef CONFIG_LEDS
-#include <asm/leds.h>
-
static void dummy_leds_event(led_event_t evt)
{
}
void (*leds_event)(led_event_t) = dummy_leds_event;
-#ifdef CONFIG_MODULES
EXPORT_SYMBOL(leds_event);
#endif
-#endif
#ifdef CONFIG_LEDS_TIMER
static void do_leds(void)
@@ -152,16 +147,15 @@ static void do_leds(void)
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
- unsigned long usec, sec;
+ unsigned long usec, sec, lost;
read_lock_irqsave(&xtime_lock, flags);
usec = gettimeoffset();
- {
- unsigned long lost = jiffies - wall_jiffies;
- if (lost)
- usec += lost * USECS_PER_JIFFY;
- }
+ lost = jiffies - wall_jiffies;
+ if (lost)
+ usec += lost * USECS_PER_JIFFY;
+
sec = xtime.tv_sec;
usec += xtime.tv_usec;
read_unlock_irqrestore(&xtime_lock, flags);
@@ -179,11 +173,11 @@ void do_gettimeofday(struct timeval *tv)
void do_settimeofday(struct timeval *tv)
{
write_lock_irq(&xtime_lock);
- /* This is revolting. We need to set the xtime.tv_usec
- * correctly. However, the value in this location is
- * is value at the last tick.
- * Discover what correction gettimeofday
- * would have done, and then undo it!
+ /*
+ * This is revolting. We need to set "xtime" correctly. However, the
+ * value in this location is the value at the most recent update of
+ * wall time. Discover what correction gettimeofday() would have
+ * done, and then undo it!
*/
tv->tv_usec -= gettimeoffset();
tv->tv_usec -= (jiffies - wall_jiffies) * USECS_PER_JIFFY;
@@ -209,17 +203,3 @@ static struct irqaction timer_irq = {
* Include architecture specific code
*/
#include <asm/arch/time.h>
-
-/*
- * This must cause the timer to start ticking.
- * It doesn't have to set the current time though
- * from an RTC - it can be done later once we have
- * some buses initialised.
- */
-void __init time_init(void)
-{
- xtime.tv_usec = 0;
- xtime.tv_sec = 0;
-
- setup_timer();
-}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 1b36af10f..29fdb8263 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -53,7 +53,7 @@ static const char *handler[]= { "prefetch abort", "data abort", "address excepti
*/
static int verify_stack(unsigned long sp)
{
- if (sp < PAGE_OFFSET || sp > (unsigned long)high_memory)
+ if (sp < PAGE_OFFSET || (sp > (unsigned long)high_memory && high_memory != 0))
return -EFAULT;
return 0;
@@ -62,13 +62,16 @@ static int verify_stack(unsigned long sp)
/*
* Dump out the contents of some memory nicely...
*/
-void dump_mem(unsigned long bottom, unsigned long top)
+static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
{
unsigned long p = bottom & ~31;
int i;
+ printk("%s", str);
+ printk("(0x%08lx to 0x%08lx)\n", bottom, top);
+
for (p = bottom & ~31; p < top;) {
- printk("%08lx: ", p);
+ printk("%04lx: ", p & 0xffff);
for (i = 0; i < 8; i++, p += 4) {
unsigned int val;
@@ -79,21 +82,11 @@ void dump_mem(unsigned long bottom, unsigned long top)
__get_user(val, (unsigned long *)p);
printk("%08x ", val);
}
- if (i == 3)
- printk(" ");
}
printk ("\n");
}
}
-/*
- * These constants are for searching for possible module text
- * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
- * a guess of how much space is likely to be vmalloced.
- */
-#define VMALLOC_OFFSET (8*1024*1024)
-#define MODULE_RANGE (8*1024*1024)
-
static void dump_instr(struct pt_regs *regs)
{
unsigned long addr = instruction_pointer(regs);
@@ -122,8 +115,7 @@ static void dump_instr(struct pt_regs *regs)
static void dump_stack(struct task_struct *tsk, unsigned long sp)
{
- printk("Stack:\n");
- dump_mem(sp - 16, 8192+(unsigned long)tsk);
+ dump_mem("Stack: ", sp - 16, 8192+(unsigned long)tsk);
}
static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
@@ -289,10 +281,9 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
handler[reason], processor_modes[proc_mode]);
/*
- * We need to switch to kernel mode so that we can
- * use __get_user to safely read from kernel space.
- * Note that we now dump the code first, just in case
- * the backtrace kills us.
+ * We need to switch to kernel mode so that we can use __get_user
+ * to safely read from kernel space. Note that we now dump the
+ * code first, just in case the backtrace kills us.
*/
fs = get_fs();
set_fs(KERNEL_DS);
@@ -301,10 +292,8 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
* Dump out the vectors and stub routines. Maybe a better solution
* would be to dump them out only if we detect that they are corrupted.
*/
- printk(KERN_CRIT "Vectors:\n");
- dump_mem(vectors, 0x40);
- printk(KERN_CRIT "Stubs:\n");
- dump_mem(vectors + 0x200, 0x4b8);
+ dump_mem(KERN_CRIT "Vectors: ", vectors, vectors + 0x40);
+ dump_mem(KERN_CRIT "Stubs: ", vectors + 0x200, vectors + 0x4b8);
set_fs(fs);
@@ -528,11 +517,6 @@ asmlinkage void __div0(void)
void abort(void)
{
- void *lr = __builtin_return_address(0);
-
- printk(KERN_CRIT "abort() called from %p! (Please "
- "report to rmk@arm.linux.org.uk)\n", lr);
-
BUG();
/* if that doesn't kill us, halt */
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index d591be3de..63992fa32 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -43,9 +43,9 @@ obj-$(v3) += io-readsw-armv3.o io-writesw-armv3.o io-readsl-armv3.o
obj-$(v4) += io-readsw-armv4.o io-writesw-armv4.o io-readsl-armv4.o
obj-y += io-writesl.o
-ifeq ($(PROCESSOR),armo)
- obj-y += uaccess-armo.o
-endif
+obj-$(CONFIG_CPU_26) += uaccess-armo.o
+obj-$(CONFIG_CPU_32) += copy_page-armv3.o copy_page-armv4.o copy_page-armv4mc.o
+obj-$(CONFIG_CPU_32v5) += copy_page-armv5te.o
include $(TOPDIR)/Rules.make
diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S
index 6feb62783..3af45cab7 100644
--- a/arch/arm/lib/changebit.S
+++ b/arch/arm/lib/changebit.S
@@ -14,7 +14,9 @@
/* Purpose : Function to change a bit
* Prototype: int change_bit(int bit, void *addr)
*/
-ENTRY(change_bit)
+ENTRY(_change_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_change_bit_le)
and r2, r0, #7
mov r3, #1
mov r3, r3, lsl r2
diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S
index 225aa6fb9..069a2ce41 100644
--- a/arch/arm/lib/clearbit.S
+++ b/arch/arm/lib/clearbit.S
@@ -15,8 +15,9 @@
* Purpose : Function to clear a bit
* Prototype: int clear_bit(int bit, void *addr)
*/
-
-ENTRY(clear_bit)
+ENTRY(_clear_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_clear_bit_le)
and r2, r0, #7
mov r3, #1
mov r3, r3, lsl r2
diff --git a/arch/arm/lib/copy_page-armv3.S b/arch/arm/lib/copy_page-armv3.S
new file mode 100644
index 000000000..1666c3f92
--- /dev/null
+++ b/arch/arm/lib/copy_page-armv3.S
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/arm/lib/copypage.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ASM optimised string functions
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/constants.h>
+
+ .text
+ .align 5
+/*
+ * ARMv3 optimised copy_user_page
+ *
+ * FIXME: do we need to handle cache stuff...
+ */
+ENTRY(armv3_copy_user_page)
+ stmfd sp!, {r4, lr} @ 2
+ mov r2, #PAGE_SZ/64 @ 1
+ ldmia r1!, {r3, r4, ip, lr} @ 4+1
+1: stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4+1
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4+1
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4
+ subs r2, r2, #1 @ 1
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmneia r1!, {r3, r4, ip, lr} @ 4
+ bne 1b @ 1
+ LOADREGS(fd, sp!, {r4, pc}) @ 3
+
+ .align 5
+/*
+ * ARMv3 optimised clear_user_page
+ *
+ * FIXME: do we need to handle cache stuff...
+ */
+ENTRY(armv3_clear_user_page)
+ str lr, [sp, #-4]!
+ mov r1, #PAGE_SZ/64 @ 1
+ mov r2, #0 @ 1
+ mov r3, #0 @ 1
+ mov ip, #0 @ 1
+ mov lr, #0 @ 1
+1: stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ subs r1, r1, #1 @ 1
+ bne 1b @ 1
+ ldr pc, [sp], #4
+
diff --git a/arch/arm/lib/copy_page-armv4.S b/arch/arm/lib/copy_page-armv4.S
new file mode 100644
index 000000000..d4cdbdd11
--- /dev/null
+++ b/arch/arm/lib/copy_page-armv4.S
@@ -0,0 +1,70 @@
+/*
+ * linux/arch/arm/lib/copypage.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ASM optimised string functions
+ */
+#include <linux/linkage.h>
+#include <asm/constants.h>
+
+ .text
+ .align 5
+/*
+ * ARMv4 optimised copy_user_page
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address. Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue. The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ *
+ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
+ * instruction. If your processor does not supply this, you have to write your
+ * own copy_user_page that does the right thing.
+ */
+ENTRY(armv4_copy_user_page)
+ stmfd sp!, {r4, lr} @ 2
+ mov r2, #PAGE_SZ/64 @ 1
+ ldmia r1!, {r3, r4, ip, lr} @ 4
+1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4+1
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4
+ mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmia r1!, {r3, r4, ip, lr} @ 4
+ subs r2, r2, #1 @ 1
+ stmia r0!, {r3, r4, ip, lr} @ 4
+ ldmneia r1!, {r3, r4, ip, lr} @ 4
+ bne 1b @ 1
+ mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB
+ ldmfd sp!, {r4, pc} @ 3
+
+ .align 5
+/*
+ * ARMv4 optimised clear_user_page
+ *
+ * Same story as above.
+ */
+ENTRY(armv4_clear_user_page)
+ str lr, [sp, #-4]!
+ mov r1, #PAGE_SZ/64 @ 1
+ mov r2, #0 @ 1
+ mov r3, #0 @ 1
+ mov ip, #0 @ 1
+ mov lr, #0 @ 1
+1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ subs r1, r1, #1 @ 1
+ bne 1b @ 1
+ mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB
+ ldr pc, [sp], #4
diff --git a/arch/arm/lib/copy_page-armv4mc.S b/arch/arm/lib/copy_page-armv4mc.S
new file mode 100644
index 000000000..8d8d02200
--- /dev/null
+++ b/arch/arm/lib/copy_page-armv4mc.S
@@ -0,0 +1,71 @@
+/*
+ * linux/arch/arm/lib/copy_page-armv4mc.S
+ *
+ * Copyright (C) 1995-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ASM optimised string functions
+ */
+#include <linux/linkage.h>
+#include <asm/constants.h>
+
+ .text
+ .align 5
+/*
+ * ARMv4 mini-dcache optimised copy_user_page
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address. Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue. The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ *
+ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
+ * instruction. If your processor does not supply this, you have to write your
+ * own copy_user_page that does the right thing.
+ */
+ENTRY(armv4_mc_copy_user_page)
+ stmfd sp!, {r4, lr} @ 2
+ mov r4, r0
+ mov r0, r1
+ bl map_page_minicache
+ mov r1, #PAGE_SZ/64 @ 1
+ ldmia r0!, {r2, r3, ip, lr} @ 4
+1: mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line
+ stmia r4!, {r2, r3, ip, lr} @ 4
+ ldmia r0!, {r2, r3, ip, lr} @ 4+1
+ stmia r4!, {r2, r3, ip, lr} @ 4
+ ldmia r0!, {r2, r3, ip, lr} @ 4
+ mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line
+ stmia r4!, {r2, r3, ip, lr} @ 4
+ ldmia r0!, {r2, r3, ip, lr} @ 4
+ subs r1, r1, #1 @ 1
+ stmia r4!, {r2, r3, ip, lr} @ 4
+ ldmneia r0!, {r2, r3, ip, lr} @ 4
+ bne 1b @ 1
+ ldmfd sp!, {r4, pc} @ 3
+
+ .align 5
+/*
+ * ARMv4 optimised clear_user_page
+ *
+ * Same story as above.
+ */
+ENTRY(armv4_mc_clear_user_page)
+ str lr, [sp, #-4]!
+ mov r1, #PAGE_SZ/64 @ 1
+ mov r2, #0 @ 1
+ mov r3, #0 @ 1
+ mov ip, #0 @ 1
+ mov lr, #0 @ 1
+1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ subs r1, r1, #1 @ 1
+ bne 1b @ 1
+ ldr pc, [sp], #4
diff --git a/arch/arm/lib/copy_page-armv5te.S b/arch/arm/lib/copy_page-armv5te.S
new file mode 100644
index 000000000..0cd3fff19
--- /dev/null
+++ b/arch/arm/lib/copy_page-armv5te.S
@@ -0,0 +1,79 @@
+/*
+ * linux/arch/arm/lib/copypage-armv5te.S
+ *
+ * Copyright (C) 2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/constants.h>
+
+/*
+ * General note:
+ * We don't really want write-allocate cache behaviour for these functions
+ * since that will just eat through 8K of the cache.
+ */
+
+ .text
+ .align 5
+/*
+ * ARMv5TE optimised copy_user_page
+ * r0 = destination
+ * r1 = source
+ * r2 = virtual user address of ultimate destination page
+ *
+ * The source page may have some clean entries in the cache already, but we
+ * can safely ignore them - break_cow() will flush them out of the cache
+ * if we eventually end up using our copied page.
+ *
+ * What we could do is use the mini-cache to buffer reads from the source
+ * page. We rely on the mini-cache being smaller than one page, so we'll
+ * cycle through the complete cache anyway.
+ */
+ENTRY(armv5te_copy_user_page)
+ stmfd sp!, {r4, r5, lr}
+ mov r5, r0
+ mov r0, r1
+ bl map_page_minicache
+ mov r1, r5
+ mov lr, #PAGE_SZ/32
+
+1: mov ip, r1
+ ldrd r2, [r0], #8
+ ldrd r4, [r0], #8
+ strd r2, [r1], #8
+ ldrd r2, [r0], #8
+ strd r4, [r1], #8
+ ldrd r4, [r0], #8
+ strd r2, [r1], #8
+ strd r4, [r1], #8
+ mcr p15, 0, ip, c7, c10, 1 @ clean D line
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate D line
+ subs lr, lr, #1
+ bne 1b
+
+ ldmfd sp!, {r4, r5, pc}
+
+ .align 5
+/*
+ * ARMv5TE optimised clear_user_page
+ * r0 = destination
+ * r1 = virtual user address of ultimate destination page
+ */
+ENTRY(armv5te_clear_user_page)
+ str lr, [sp, #-4]!
+ mov r1, #PAGE_SZ/32
+ mov r2, #0
+ mov r3, #0
+1: mov ip, r0
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ mcr p15, 0, ip, c7, c10, 1 @ clean D line
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate D line
+ subs r1, r1, #1
+ bne 1b
+ ldr pc, [sp], #4
diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S
index 415ca1ae3..990598ff3 100644
--- a/arch/arm/lib/delay.S
+++ b/arch/arm/lib/delay.S
@@ -29,25 +29,29 @@ ENTRY(udelay)
RETINSTR(moveq,pc,lr)
/*
- * loops = (r0 * 0x10c6 * 100 * loops_per_jiffie) / 2^32
+ * loops = (r0 * 0x10c6 * 100 * loops_per_jiffy) / 2^32
+ *
+ * Oh, if only we had a cycle counter...
*/
@ Delay routine
ENTRY(__delay)
subs r0, r0, #1
- RETINSTR(movcc,pc,lr)
+#if 0
+ RETINSTR(movls,pc,lr)
subs r0, r0, #1
- RETINSTR(movcc,pc,lr)
+ RETINSTR(movls,pc,lr)
subs r0, r0, #1
- RETINSTR(movcc,pc,lr)
+ RETINSTR(movls,pc,lr)
subs r0, r0, #1
- RETINSTR(movcc,pc,lr)
+ RETINSTR(movls,pc,lr)
subs r0, r0, #1
- RETINSTR(movcc,pc,lr)
+ RETINSTR(movls,pc,lr)
subs r0, r0, #1
- RETINSTR(movcc,pc,lr)
+ RETINSTR(movls,pc,lr)
subs r0, r0, #1
- RETINSTR(movcc,pc,lr)
+ RETINSTR(movls,pc,lr)
subs r0, r0, #1
- bcs SYMBOL_NAME(__delay)
+#endif
+ bhi SYMBOL_NAME(__delay)
RETINSTR(mov,pc,lr)
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 279230292..946961db7 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -15,14 +15,14 @@
* Purpose : Find a 'zero' bit
* Prototype: int find_first_zero_bit(void *addr, int maxbit);
*/
-ENTRY(find_first_zero_bit)
+ENTRY(_find_first_zero_bit_le)
mov r2, #0
-.bytelp: ldrb r3, [r0, r2, lsr #3]
+1: ldrb r3, [r0, r2, lsr #3]
eors r3, r3, #0xff @ invert bits
bne .found @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
cmp r2, r1 @ any more?
- bcc .bytelp
+ bcc 1b
add r0, r1, #1 @ no free bits
RETINSTR(mov,pc,lr)
@@ -30,15 +30,43 @@ ENTRY(find_first_zero_bit)
* Purpose : Find next 'zero' bit
* Prototype: int find_next_zero_bit(void *addr, int maxbit, int offset)
*/
-ENTRY(find_next_zero_bit)
+ENTRY(_find_next_zero_bit_le)
ands ip, r2, #7
- beq .bytelp @ If new byte, goto old routine
+ beq 1b @ If new byte, goto old routine
ldrb r3, [r0, r2, lsr#3]
eor r3, r3, #0xff @ now looking for a 1 bit
movs r3, r3, lsr ip @ shift off unused bits
+ bne .found
+ orr r2, r2, #7 @ if zero, then no bits here
+ add r2, r2, #1 @ align bit pointer
+ b 1b @ loop for next bit
+
+#ifdef __ARMEB__
+
+ENTRY(_find_first_zero_bit_be)
+ mov r2, #0
+1: eor r3, r2, #0x18 @ big endian byte ordering
+ ldrb r3, [r0, r3, lsr #3]
+ eors r3, r3, #0xff @ invert bits
+ bne .found @ any now set - found zero bit
+ add r2, r2, #8 @ next bit pointer
+ cmp r2, r1 @ any more?
+ bcc 1b
+ add r0, r1, #1 @ no free bits
+ RETINSTR(mov,pc,lr)
+
+ENTRY(_find_next_zero_bit_be)
+ ands ip, r2, #7
+ beq 1b @ If new byte, goto old routine
+ eor r3, r2, #0x18 @ big endian byte ordering
+ ldrb r3, [r0, r3, lsr#3]
+ eor r3, r3, #0xff @ now looking for a 1 bit
+ movs r3, r3, lsr ip @ shift off unused bits
orreq r2, r2, #7 @ if zero, then no bits here
addeq r2, r2, #1 @ align bit pointer
- beq .bytelp @ loop for next bit
+ beq 1b @ loop for next bit
+
+#endif
/*
* One or more bits in the LSB of r3 are assumed to be set.
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 578cebb18..6278b2a60 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -49,7 +49,11 @@ __get_user_2:
cmp r0, r2
2: ldrlsbt r1, [r0], #1
3: ldrlsbt r2, [r0]
+#ifndef __ARMEB__
orrls r1, r1, r2, lsl #8
+#else
+ orrls r1, r2, r1, lsl #8
+#endif
movls r0, #0
movls pc, lr
b __get_user_bad
@@ -80,8 +84,9 @@ __get_user_8:
/* fall through */
-__get_user_bad:
+__get_user_bad_8:
mov r2, #0
+__get_user_bad:
mov r1, #0
mov r0, #-14
mov pc, lr
@@ -91,6 +96,6 @@ __get_user_bad:
.long 2b, __get_user_bad
.long 3b, __get_user_bad
.long 4b, __get_user_bad
- .long 5b, __get_user_bad
- .long 6b, __get_user_bad
+ .long 5b, __get_user_bad_8
+ .long 6b, __get_user_bad_8
.previous
diff --git a/arch/arm/lib/io-shark.c b/arch/arm/lib/io-shark.c
index 07072f66a..108d4573e 100644
--- a/arch/arm/lib/io-shark.c
+++ b/arch/arm/lib/io-shark.c
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/lib/io-shark.c
*
- * by Alexander Schulz <aschulz@netwinder.org>
+ * by Alexander Schulz
*
* derived from:
* linux/arch/arm/lib/io-ebsa.S
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S
index 87342f299..50ec63192 100644
--- a/arch/arm/lib/memcpy.S
+++ b/arch/arm/lib/memcpy.S
@@ -99,24 +99,24 @@ ENTRY(memmove)
cmp r2, #12
blt 10f
sub r2, r2, #12
-9: mov r3, r7, lsr #8
+9: mov r3, r7, pull #8
ldmia r1!, {r4 - r7}
- orr r3, r3, r4, lsl #24
- mov r4, r4, lsr #8
- orr r4, r4, r5, lsl #24
- mov r5, r5, lsr #8
- orr r5, r5, r6, lsl #24
- mov r6, r6, lsr #8
- orr r6, r6, r7, lsl #24
+ orr r3, r3, r4, push #24
+ mov r4, r4, pull #8
+ orr r4, r4, r5, push #24
+ mov r5, r5, pull #8
+ orr r5, r5, r6, push #24
+ mov r6, r6, pull #8
+ orr r6, r6, r7, push #24
stmia r0!, {r3 - r6}
subs r2, r2, #16
bge 9b
adds r2, r2, #12
blt 100f
-10: mov r3, r7, lsr #8
+10: mov r3, r7, pull #8
ldr r7, [r1], #4
subs r2, r2, #4
- orr r3, r3, r7, lsl #24
+ orr r3, r3, r7, push #24
str r3, [r0], #4
bge 10b
100: sub r1, r1, #3
@@ -125,24 +125,24 @@ ENTRY(memmove)
11: cmp r2, #12
blt 13f /* */
sub r2, r2, #12
-12: mov r3, r7, lsr #16
+12: mov r3, r7, pull #16
ldmia r1!, {r4 - r7}
- orr r3, r3, r4, lsl #16
- mov r4, r4, lsr #16
- orr r4, r4, r5, lsl #16
- mov r5, r5, lsr #16
- orr r5, r5, r6, lsl #16
- mov r6, r6, lsr #16
- orr r6, r6, r7,LSL#16
+ orr r3, r3, r4, push #16
+ mov r4, r4, pull #16
+ orr r4, r4, r5, push #16
+ mov r5, r5, pull #16
+ orr r5, r5, r6, push #16
+ mov r6, r6, pull #16
+ orr r6, r6, r7, push #16
stmia r0!, {r3 - r6}
subs r2, r2, #16
bge 12b
adds r2, r2, #12
blt 14f
-13: mov r3, r7, lsr #16
+13: mov r3, r7, pull #16
ldr r7, [r1], #4
subs r2, r2, #4
- orr r3, r3, r7, lsl #16
+ orr r3, r3, r7, push #16
str r3, [r0], #4
bge 13b
14: sub r1, r1, #2
@@ -151,24 +151,24 @@ ENTRY(memmove)
15: cmp r2, #12
blt 17f
sub r2, r2, #12
-16: mov r3, r7, lsr #24
- ldmia r1!,{r4 - r7}
- orr r3, r3, r4, lsl #8
- mov r4, r4, lsr #24
- orr r4, r4, r5, lsl #8
- mov r5, r5, lsr #24
- orr r5, r5, r6, lsl #8
- mov r6, r6, lsr #24
- orr r6, r6, r7, lsl #8
+16: mov r3, r7, pull #24
+ ldmia r1!, {r4 - r7}
+ orr r3, r3, r4, push #8
+ mov r4, r4, pull #24
+ orr r4, r4, r5, push #8
+ mov r5, r5, pull #24
+ orr r5, r5, r6, push #8
+ mov r6, r6, pull #24
+ orr r6, r6, r7, push #8
stmia r0!, {r3 - r6}
subs r2, r2, #16
bge 16b
adds r2, r2, #12
blt 18f
-17: mov r3, r7, lsr #24
+17: mov r3, r7, pull #24
ldr r7, [r1], #4
subs r2, r2, #4
- orr r3, r3, r7, lsl#8
+ orr r3, r3, r7, push #8
str r3, [r0], #4
bge 17b
18: sub r1, r1, #1
@@ -240,24 +240,24 @@ ENTRY(memmove)
cmp r2, #12
blt 28f
sub r2, r2, #12
-27: mov r7, r3, lsl #8
+27: mov r7, r3, push #8
ldmdb r1!, {r3, r4, r5, r6}
- orr r7, r7, r6, lsr #24
- mov r6, r6, lsl #8
- orr r6, r6, r5, lsr #24
- mov r5, r5, lsl #8
- orr r5, r5, r4, lsr #24
- mov r4, r4, lsl #8
- orr r4, r4, r3, lsr #24
+ orr r7, r7, r6, pull #24
+ mov r6, r6, push #8
+ orr r6, r6, r5, pull #24
+ mov r5, r5, push #8
+ orr r5, r5, r4, pull #24
+ mov r4, r4, push #8
+ orr r4, r4, r3, pull #24
stmdb r0!, {r4, r5, r6, r7}
subs r2, r2, #16
bge 27b
adds r2, r2, #12
blt 29f
-28: mov ip, r3, lsl #8
+28: mov ip, r3, push #8
ldr r3, [r1, #-4]!
subs r2, r2, #4
- orr ip, ip, r3, lsr #24
+ orr ip, ip, r3, pull #24
str ip, [r0, #-4]!
bge 28b
29: add r1, r1, #3
@@ -266,24 +266,24 @@ ENTRY(memmove)
30: cmp r2, #12
blt 32f
sub r2, r2, #12
-31: mov r7, r3, lsl #16
+31: mov r7, r3, push #16
ldmdb r1!, {r3, r4, r5, r6}
- orr r7, r7, r6, lsr #16
- mov r6, r6, lsl #16
- orr r6, r6, r5, lsr #16
- mov r5, r5, lsl #16
- orr r5, r5, r4, lsr #16
- mov r4, r4, lsl #16
- orr r4, r4, r3, lsr #16
+ orr r7, r7, r6, pull #16
+ mov r6, r6, push #16
+ orr r6, r6, r5, pull #16
+ mov r5, r5, push #16
+ orr r5, r5, r4, pull #16
+ mov r4, r4, push #16
+ orr r4, r4, r3, pull #16
stmdb r0!, {r4, r5, r6, r7}
subs r2, r2, #16
bge 31b
adds r2, r2, #12
blt 33f
-32: mov ip, r3, lsl #16
+32: mov ip, r3, push #16
ldr r3, [r1, #-4]!
subs r2, r2, #4
- orr ip, ip, r3, lsr #16
+ orr ip, ip, r3, pull #16
str ip, [r0, #-4]!
bge 32b
33: add r1, r1, #2
@@ -292,24 +292,24 @@ ENTRY(memmove)
34: cmp r2, #12
blt 36f
sub r2, r2, #12
-35: mov r7, r3, lsl #24
+35: mov r7, r3, push #24
ldmdb r1!, {r3, r4, r5, r6}
- orr r7, r7, r6, lsr #8
- mov r6, r6, lsl #24
- orr r6, r6, r5, lsr #8
- mov r5, r5, lsl #24
- orr r5, r5, r4, lsr #8
- mov r4, r4, lsl #24
- orr r4, r4, r3, lsr #8
+ orr r7, r7, r6, pull #8
+ mov r6, r6, push #24
+ orr r6, r6, r5, pull #8
+ mov r5, r5, push #24
+ orr r5, r5, r4, pull #8
+ mov r4, r4, push #24
+ orr r4, r4, r3, pull #8
stmdb r0!, {r4, r5, r6, r7}
subs r2, r2, #16
bge 35b
adds r2, r2, #12
blt 37f
-36: mov ip, r3, lsl #24
+36: mov ip, r3, push #24
ldr r3, [r1, #-4]!
subs r2, r2, #4
- orr ip, ip, r3, lsr #8
+ orr ip, ip, r3, pull #8
str ip, [r0, #-4]!
bge 36b
37: add r1, r1, #1
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 0ba85e017..b98b89a30 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -47,9 +47,14 @@ __put_user_2:
ldr r2, [r2, #TSK_ADDR_LIMIT]
sub r2, r2, #2
cmp r0, r2
+ movls r2, r1, lsr #8
+#ifndef __ARMEB__
2: strlsbt r1, [r0], #1
- movls r1, r1, lsr #8
+3: strlsbt r2, [r0]
+#else
+2: strlsbt r2, [r0], #1
3: strlsbt r1, [r0]
+#endif
movls r0, #0
movls pc, lr
b __put_user_bad
diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S
index 5e51b27a8..8f337df5d 100644
--- a/arch/arm/lib/setbit.S
+++ b/arch/arm/lib/setbit.S
@@ -9,22 +9,21 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
- .text
+ .text
/*
* Purpose : Function to set a bit
* Prototype: int set_bit(int bit, void *addr)
*/
-
-ENTRY(set_bit)
- and r2, r0, #7
- mov r3, #1
- mov r3, r3, lsl r2
+ENTRY(_set_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_set_bit_le)
+ and r2, r0, #7
+ mov r3, #1
+ mov r3, r3, lsl r2
save_and_disable_irqs ip, r2
ldrb r2, [r1, r0, lsr #3]
orr r2, r2, r3
strb r2, [r1, r0, lsr #3]
restore_irqs ip
RETINSTR(mov,pc,lr)
-
-
diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S
index 3131538d8..4aba4676b 100644
--- a/arch/arm/lib/testchangebit.S
+++ b/arch/arm/lib/testchangebit.S
@@ -11,7 +11,9 @@
#include <asm/assembler.h>
.text
-ENTRY(test_and_change_bit)
+ENTRY(_test_and_change_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_test_and_change_bit_le)
add r1, r1, r0, lsr #3
and r3, r0, #7
mov r0, #1
diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S
index d6c612fe1..e07c5bd24 100644
--- a/arch/arm/lib/testclearbit.S
+++ b/arch/arm/lib/testclearbit.S
@@ -11,7 +11,9 @@
#include <asm/assembler.h>
.text
-ENTRY(test_and_clear_bit)
+ENTRY(_test_and_clear_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_test_and_clear_bit_le)
add r1, r1, r0, lsr #3 @ Get byte offset
and r3, r0, #7 @ Get bit offset
mov r0, #1
diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S
index b022c324f..a570fc74c 100644
--- a/arch/arm/lib/testsetbit.S
+++ b/arch/arm/lib/testsetbit.S
@@ -11,7 +11,9 @@
#include <asm/assembler.h>
.text
-ENTRY(test_and_set_bit)
+ENTRY(_test_and_set_bit_be)
+ eor r0, r0, #0x18 @ big endian byte ordering
+ENTRY(_test_and_set_bit_le)
add r1, r1, r0, lsr #3 @ Get byte offset
and r3, r0, #7 @ Get bit offset
mov r0, #1
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
index 13af269c6..549270cf7 100644
--- a/arch/arm/lib/uaccess.S
+++ b/arch/arm/lib/uaccess.S
@@ -115,9 +115,9 @@ USER( strgtbt r3, [r0], #1) @ May fault
.c2u_1fupi: subs r2, r2, #4
addmi ip, r2, #4
bmi .c2u_1nowords
- mov r3, r7, lsr #8
+ mov r3, r7, pull #8
ldr r7, [r1], #4
- orr r3, r3, r7, lsl #24
+ orr r3, r3, r7, push #24
USER( strt r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
@@ -129,49 +129,49 @@ USER( strt r3, [r0], #4) @ May fault
subs ip, ip, #16
blt .c2u_1rem8lp
-.c2u_1cpy8lp: mov r3, r7, lsr #8
+.c2u_1cpy8lp: mov r3, r7, pull #8
ldmia r1!, {r4 - r7}
- orr r3, r3, r4, lsl #24
- mov r4, r4, lsr #8
- orr r4, r4, r5, lsl #24
- mov r5, r5, lsr #8
- orr r5, r5, r6, lsl #24
- mov r6, r6, lsr #8
- orr r6, r6, r7, lsl #24
+ orr r3, r3, r4, push #24
+ mov r4, r4, pull #8
+ orr r4, r4, r5, push #24
+ mov r5, r5, pull #8
+ orr r5, r5, r6, push #24
+ mov r6, r6, pull #8
+ orr r6, r6, r7, push #24
stmia r0!, {r3 - r6} @ Shouldnt fault
subs ip, ip, #16
bpl .c2u_1cpy8lp
.c2u_1rem8lp: tst ip, #8
- movne r3, r7, lsr #8
+ movne r3, r7, pull #8
ldmneia r1!, {r4, r7}
- orrne r3, r3, r4, lsl #24
- movne r4, r4, lsr #8
- orrne r4, r4, r7, lsl #24
+ orrne r3, r3, r4, push #24
+ movne r4, r4, pull #8
+ orrne r4, r4, r7, push #24
stmneia r0!, {r3 - r4} @ Shouldnt fault
tst ip, #4
- movne r3, r7, lsr #8
+ movne r3, r7, pull #8
ldrne r7, [r1], #4
- orrne r3, r3, r7, lsl #24
+ orrne r3, r3, r7, push #24
strnet r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .c2u_1fupi
-.c2u_1nowords: mov r3, r7, lsr #8
+.c2u_1nowords: mov r3, r7, lsr #byte(1)
teq ip, #0
beq .c2u_finished
cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault
- movge r3, r3, lsr #8
+ movge r3, r7, lsr #byte(2)
USER( strgebt r3, [r0], #1) @ May fault
- movgt r3, r3, lsr #8
+ movgt r3, r7, lsr #byte(3)
USER( strgtbt r3, [r0], #1) @ May fault
b .c2u_finished
.c2u_2fupi: subs r2, r2, #4
addmi ip, r2, #4
bmi .c2u_2nowords
- mov r3, r7, lsr #16
+ mov r3, r7, pull #16
ldr r7, [r1], #4
- orr r3, r3, r7, lsl #16
+ orr r3, r3, r7, push #16
USER( strt r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
@@ -183,38 +183,38 @@ USER( strt r3, [r0], #4) @ May fault
subs ip, ip, #16
blt .c2u_2rem8lp
-.c2u_2cpy8lp: mov r3, r7, lsr #16
+.c2u_2cpy8lp: mov r3, r7, pull #16
ldmia r1!, {r4 - r7}
- orr r3, r3, r4, lsl #16
- mov r4, r4, lsr #16
- orr r4, r4, r5, lsl #16
- mov r5, r5, lsr #16
- orr r5, r5, r6, lsl #16
- mov r6, r6, lsr #16
- orr r6, r6, r7, lsl #16
+ orr r3, r3, r4, push #16
+ mov r4, r4, pull #16
+ orr r4, r4, r5, push #16
+ mov r5, r5, pull #16
+ orr r5, r5, r6, push #16
+ mov r6, r6, pull #16
+ orr r6, r6, r7, push #16
stmia r0!, {r3 - r6} @ Shouldnt fault
subs ip, ip, #16
bpl .c2u_2cpy8lp
.c2u_2rem8lp: tst ip, #8
- movne r3, r7, lsr #16
+ movne r3, r7, pull #16
ldmneia r1!, {r4, r7}
- orrne r3, r3, r4, lsl #16
- movne r4, r4, lsr #16
- orrne r4, r4, r7, lsl #16
+ orrne r3, r3, r4, push #16
+ movne r4, r4, pull #16
+ orrne r4, r4, r7, push #16
stmneia r0!, {r3 - r4} @ Shouldnt fault
tst ip, #4
- movne r3, r7, lsr #16
+ movne r3, r7, pull #16
ldrne r7, [r1], #4
- orrne r3, r3, r7, lsl #16
+ orrne r3, r3, r7, push #16
strnet r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .c2u_2fupi
-.c2u_2nowords: mov r3, r7, lsr #16
+.c2u_2nowords: mov r3, r7, lsr #byte(2)
teq ip, #0
beq .c2u_finished
cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault
- movge r3, r3, lsr #8
+ movge r3, r7, lsr #byte(3)
USER( strgebt r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #0
USER( strgtbt r3, [r0], #1) @ May fault
@@ -223,9 +223,9 @@ USER( strgtbt r3, [r0], #1) @ May fault
.c2u_3fupi: subs r2, r2, #4
addmi ip, r2, #4
bmi .c2u_3nowords
- mov r3, r7, lsr #24
+ mov r3, r7, pull #24
ldr r7, [r1], #4
- orr r3, r3, r7, lsl #8
+ orr r3, r3, r7, push #8
USER( strt r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
@@ -237,40 +237,40 @@ USER( strt r3, [r0], #4) @ May fault
subs ip, ip, #16
blt .c2u_3rem8lp
-.c2u_3cpy8lp: mov r3, r7, lsr #24
+.c2u_3cpy8lp: mov r3, r7, pull #24
ldmia r1!, {r4 - r7}
- orr r3, r3, r4, lsl #8
- mov r4, r4, lsr #24
- orr r4, r4, r5, lsl #8
- mov r5, r5, lsr #24
- orr r5, r5, r6, lsl #8
- mov r6, r6, lsr #24
- orr r6, r6, r7, lsl #8
+ orr r3, r3, r4, push #8
+ mov r4, r4, pull #24
+ orr r4, r4, r5, push #8
+ mov r5, r5, pull #24
+ orr r5, r5, r6, push #8
+ mov r6, r6, pull #24
+ orr r6, r6, r7, push #8
stmia r0!, {r3 - r6} @ Shouldnt fault
subs ip, ip, #16
bpl .c2u_3cpy8lp
.c2u_3rem8lp: tst ip, #8
- movne r3, r7, lsr #24
+ movne r3, r7, pull #24
ldmneia r1!, {r4, r7}
- orrne r3, r3, r4, lsl #8
- movne r4, r4, lsr #24
- orrne r4, r4, r7, lsl #8
+ orrne r3, r3, r4, push #8
+ movne r4, r4, pull #24
+ orrne r4, r4, r7, push #8
stmneia r0!, {r3 - r4} @ Shouldnt fault
tst ip, #4
- movne r3, r7, lsr #24
+ movne r3, r7, pull #24
ldrne r7, [r1], #4
- orrne r3, r3, r7, lsl #8
+ orrne r3, r3, r7, push #8
strnet r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .c2u_3fupi
-.c2u_3nowords: mov r3, r7, lsr #24
+.c2u_3nowords: mov r3, r7, lsr #byte(3)
teq ip, #0
beq .c2u_finished
cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault
- ldrge r3, [r1], #0
+ ldrgeb r3, [r1], #1
USER( strgebt r3, [r0], #1) @ May fault
- movgt r3, r3, lsr #8
+ ldrgtb r3, [r1], #0
USER( strgtbt r3, [r0], #1) @ May fault
b .c2u_finished
@@ -374,9 +374,9 @@ USER( ldrt r7, [r1], #4) @ May fault
.cfu_1fupi: subs r2, r2, #4
addmi ip, r2, #4
bmi .cfu_1nowords
- mov r3, r7, lsr #8
+ mov r3, r7, pull #8
USER( ldrt r7, [r1], #4) @ May fault
- orr r3, r3, r7, lsl #24
+ orr r3, r3, r7, push #24
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
@@ -388,49 +388,49 @@ USER( ldrt r7, [r1], #4) @ May fault
subs ip, ip, #16
blt .cfu_1rem8lp
-.cfu_1cpy8lp: mov r3, r7, lsr #8
+.cfu_1cpy8lp: mov r3, r7, pull #8
ldmia r1!, {r4 - r7} @ Shouldnt fault
- orr r3, r3, r4, lsl #24
- mov r4, r4, lsr #8
- orr r4, r4, r5, lsl #24
- mov r5, r5, lsr #8
- orr r5, r5, r6, lsl #24
- mov r6, r6, lsr #8
- orr r6, r6, r7, lsl #24
+ orr r3, r3, r4, push #24
+ mov r4, r4, pull #8
+ orr r4, r4, r5, push #24
+ mov r5, r5, pull #8
+ orr r5, r5, r6, push #24
+ mov r6, r6, pull #8
+ orr r6, r6, r7, push #24
stmia r0!, {r3 - r6}
subs ip, ip, #16
bpl .cfu_1cpy8lp
.cfu_1rem8lp: tst ip, #8
- movne r3, r7, lsr #8
+ movne r3, r7, pull #8
ldmneia r1!, {r4, r7} @ Shouldnt fault
- orrne r3, r3, r4, lsl #24
- movne r4, r4, lsr #8
- orrne r4, r4, r7, lsl #24
+ orrne r3, r3, r4, push #24
+ movne r4, r4, pull #8
+ orrne r4, r4, r7, push #24
stmneia r0!, {r3 - r4}
tst ip, #4
- movne r3, r7, lsr #8
+ movne r3, r7, pull #8
USER( ldrnet r7, [r1], #4) @ May fault
- orrne r3, r3, r7, lsl #24
+ orrne r3, r3, r7, push #24
strne r3, [r0], #4
ands ip, ip, #3
beq .cfu_1fupi
-.cfu_1nowords: mov r3, r7, lsr #8
+.cfu_1nowords: mov r3, r7, lsr #byte(1)
teq ip, #0
beq .cfu_finished
cmp ip, #2
strb r3, [r0], #1
- movge r3, r3, lsr #8
+ movge r3, r7, lsr #byte(2)
strgeb r3, [r0], #1
- movgt r3, r3, lsr #8
+ movgt r3, r7, lsr #byte(3)
strgtb r3, [r0], #1
b .cfu_finished
.cfu_2fupi: subs r2, r2, #4
addmi ip, r2, #4
bmi .cfu_2nowords
- mov r3, r7, lsr #16
+ mov r3, r7, pull #16
USER( ldrt r7, [r1], #4) @ May fault
- orr r3, r3, r7, lsl #16
+ orr r3, r3, r7, push #16
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
@@ -442,38 +442,38 @@ USER( ldrt r7, [r1], #4) @ May fault
subs ip, ip, #16
blt .cfu_2rem8lp
-.cfu_2cpy8lp: mov r3, r7, lsr #16
+.cfu_2cpy8lp: mov r3, r7, pull #16
ldmia r1!, {r4 - r7} @ Shouldnt fault
- orr r3, r3, r4, lsl #16
- mov r4, r4, lsr #16
- orr r4, r4, r5, lsl #16
- mov r5, r5, lsr #16
- orr r5, r5, r6, lsl #16
- mov r6, r6, lsr #16
- orr r6, r6, r7, lsl #16
+ orr r3, r3, r4, push #16
+ mov r4, r4, pull #16
+ orr r4, r4, r5, push #16
+ mov r5, r5, pull #16
+ orr r5, r5, r6, push #16
+ mov r6, r6, pull #16
+ orr r6, r6, r7, push #16
stmia r0!, {r3 - r6}
subs ip, ip, #16
bpl .cfu_2cpy8lp
.cfu_2rem8lp: tst ip, #8
- movne r3, r7, lsr #16
+ movne r3, r7, pull #16
ldmneia r1!, {r4, r7} @ Shouldnt fault
- orrne r3, r3, r4, lsl #16
- movne r4, r4, lsr #16
- orrne r4, r4, r7, lsl #16
+ orrne r3, r3, r4, push #16
+ movne r4, r4, pull #16
+ orrne r4, r4, r7, push #16
stmneia r0!, {r3 - r4}
tst ip, #4
- movne r3, r7, lsr #16
+ movne r3, r7, pull #16
USER( ldrnet r7, [r1], #4) @ May fault
- orrne r3, r3, r7, lsl #16
+ orrne r3, r3, r7, push #16
strne r3, [r0], #4
ands ip, ip, #3
beq .cfu_2fupi
-.cfu_2nowords: mov r3, r7, lsr #16
+.cfu_2nowords: mov r3, r7, lsr #byte(2)
teq ip, #0
beq .cfu_finished
cmp ip, #2
strb r3, [r0], #1
- movge r3, r3, lsr #8
+ movge r3, r7, lsr #byte(3)
strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #0) @ May fault
strgtb r3, [r0], #1
@@ -482,9 +482,9 @@ USER( ldrgtbt r3, [r1], #0) @ May fault
.cfu_3fupi: subs r2, r2, #4
addmi ip, r2, #4
bmi .cfu_3nowords
- mov r3, r7, lsr #24
+ mov r3, r7, pull #24
USER( ldrt r7, [r1], #4) @ May fault
- orr r3, r3, r7, lsl #8
+ orr r3, r3, r7, push #8
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
@@ -496,40 +496,40 @@ USER( ldrt r7, [r1], #4) @ May fault
subs ip, ip, #16
blt .cfu_3rem8lp
-.cfu_3cpy8lp: mov r3, r7, lsr #24
+.cfu_3cpy8lp: mov r3, r7, pull #24
ldmia r1!, {r4 - r7} @ Shouldnt fault
- orr r3, r3, r4, lsl #8
- mov r4, r4, lsr #24
- orr r4, r4, r5, lsl #8
- mov r5, r5, lsr #24
- orr r5, r5, r6, lsl #8
- mov r6, r6, lsr #24
- orr r6, r6, r7, lsl #8
+ orr r3, r3, r4, push #8
+ mov r4, r4, pull #24
+ orr r4, r4, r5, push #8
+ mov r5, r5, pull #24
+ orr r5, r5, r6, push #8
+ mov r6, r6, pull #24
+ orr r6, r6, r7, push #8
stmia r0!, {r3 - r6}
subs ip, ip, #16
bpl .cfu_3cpy8lp
.cfu_3rem8lp: tst ip, #8
- movne r3, r7, lsr #24
+ movne r3, r7, pull #24
ldmneia r1!, {r4, r7} @ Shouldnt fault
- orrne r3, r3, r4, lsl #8
- movne r4, r4, lsr #24
- orrne r4, r4, r7, lsl #8
+ orrne r3, r3, r4, push #8
+ movne r4, r4, pull #24
+ orrne r4, r4, r7, push #8
stmneia r0!, {r3 - r4}
tst ip, #4
- movne r3, r7, lsr #24
+ movne r3, r7, pull #24
USER( ldrnet r7, [r1], #4) @ May fault
- orrne r3, r3, r7, lsl #8
+ orrne r3, r3, r7, push #8
strne r3, [r0], #4
ands ip, ip, #3
beq .cfu_3fupi
-.cfu_3nowords: mov r3, r7, lsr #24
+.cfu_3nowords: mov r3, r7, lsr #byte(3)
teq ip, #0
beq .cfu_finished
cmp ip, #2
strb r3, [r0], #1
-USER( ldrget r3, [r1], #0) @ May fault
+USER( ldrgebt r3, [r1], #1) @ May fault
strgeb r3, [r0], #1
- movgt r3, r3, lsr #8
+USER( ldrgtbt r3, [r1], #1) @ May fault
strgtb r3, [r0], #1
b .cfu_finished
diff --git a/arch/arm/mach-adifcc/Makefile b/arch/arm/mach-adifcc/Makefile
new file mode 100644
index 000000000..ef626a1a6
--- /dev/null
+++ b/arch/arm/mach-adifcc/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := adifcc.o
+
+# Object file lists.
+
+obj-y := arch.o irq.o mm.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs :=
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/arm/mach-adifcc/arch.c b/arch/arm/mach-adifcc/arch.c
new file mode 100644
index 000000000..353af8e71
--- /dev/null
+++ b/arch/arm/mach-adifcc/arch.c
@@ -0,0 +1,49 @@
+/*
+ * linux/arch/arm/mach-adifcc/arch.c
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+extern void adifcc_map_io(void);
+extern void adifcc_init_irq(void);
+
+static void __init
+fixup_adifcc(struct machine_desc *desc, struct param_struct *params,
+ char **cmdline, struct meminfo *mi)
+{
+#ifdef CONFIG_ARCH_ADI_EVB
+ mi->bank[0].start = PHYS_OFFSET;
+ mi->bank[0].size = (32*1024*1024);
+ mi->bank[0].node = 0;
+ mi->nr_banks = 1;
+
+ setup_ramdisk( 1, 0, 0, 8192 );
+ setup_initrd( 0xc0800000, 3*1024*1024 );
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+#endif
+}
+
+#ifdef CONFIG_ARCH_ADI_EVB
+MACHINE_START(ADI_EVB, "ADI 80200FCC Evaluation Board")
+ MAINTAINER("MontaVista Software Inc.")
+ BOOT_MEM(0xc0000000, 0x00400000, 0xff400000)
+ FIXUP(fixup_adifcc)
+ MAPIO(adifcc_map_io)
+ INITIRQ(adifcc_init_irq)
+MACHINE_END
+#endif
+
diff --git a/arch/arm/mach-adifcc/irq.c b/arch/arm/mach-adifcc/irq.c
new file mode 100644
index 000000000..de4067072
--- /dev/null
+++ b/arch/arm/mach-adifcc/irq.c
@@ -0,0 +1,66 @@
+/*
+ * linux/arch/arm/mach-xscale/irq.c
+ *
+ * Author: Deepak Saxena
+ * Copyright: (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on IOP80310 code. Currently there's nothing more than the
+ * 80200 on chip interrupts. That'll change once the hardware adds
+ * support for PCI though.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/mach-types.h>
+
+static void xs80200_irq_mask (unsigned int irq)
+{
+ long INTCTL;
+ asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (INTCTL));
+ switch (irq) {
+ case IRQ_XS80200_BCU: INTCTL &= ~(1<<3); break;
+ case IRQ_XS80200_PMU: INTCTL &= ~(1<<2); break;
+ case IRQ_XS80200_EXTIRQ: INTCTL &= ~(1<<1); break;
+ case IRQ_XS80200_EXTFIQ: INTCTL &= ~(1<<0); break;
+ }
+ asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (INTCTL));
+}
+
+static void xs80200_irq_unmask (unsigned int irq)
+{
+ long INTCTL;
+ asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (INTCTL));
+ switch (irq) {
+ case IRQ_XS80200_BCU: INTCTL |= (1<<3); break;
+ case IRQ_XS80200_PMU: INTCTL |= (1<<2); break;
+ case IRQ_XS80200_EXTIRQ: INTCTL |= (1<<1); break;
+ case IRQ_XS80200_EXTFIQ: INTCTL |= (1<<0); break;
+ }
+ asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (INTCTL));
+}
+
+void __init adifcc_init_irq(void)
+{
+ int i;
+
+ for (i = 0; i < NR_XS80200_IRQS; i++) {
+ irq_desc[i].valid = 1;
+ irq_desc[i].probe_ok = 0;
+ irq_desc[i].mask_ack = xs80200_irq_mask;
+ irq_desc[i].mask = xs80200_irq_mask;
+ irq_desc[i].unmask = xs80200_irq_unmask;
+ }
+}
+
+
diff --git a/arch/arm/mach-adifcc/mm.c b/arch/arm/mach-adifcc/mm.c
new file mode 100644
index 000000000..3d0db7087
--- /dev/null
+++ b/arch/arm/mach-adifcc/mm.c
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/mach-xscale/mm.c
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+
+
+static struct map_desc adifcc_io_desc[] __initdata = {
+ /* on-board devices */
+ { 0xff400000, 0x00400000, 0x00300000, DOMAIN_IO, 1, 1, 0, 0},
+ LAST_DESC
+};
+
+void __init adifcc_map_io(void)
+{
+ iotable_init(adifcc_io_desc);
+}
diff --git a/arch/arm/mach-arc/Makefile b/arch/arm/mach-arc/Makefile
new file mode 100644
index 000000000..b54f95f3f
--- /dev/null
+++ b/arch/arm/mach-arc/Makefile
@@ -0,0 +1,28 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := arc.o
+
+# Object file lists.
+
+obj-y := arch.o dma.o fault.o irq.o mm.o oldlatches.o \
+ small_page.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs := oldlatches.o
+
+obj-$(CONFIG_DEBUG_LL) += debug.o
+
+all: arc.o head.o
+
+include $(TOPDIR)/Rules.make
+
+AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR)
diff --git a/arch/arm/mach-arc/arch.c b/arch/arm/mach-arc/arch.c
new file mode 100644
index 000000000..00472e7cc
--- /dev/null
+++ b/arch/arm/mach-arc/arch.c
@@ -0,0 +1,39 @@
+/*
+ * linux/arch/arm/mach-arc/arch.c
+ *
+ * Copyright (C) 1998-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Architecture specific fixups.
+ */
+#include <linux/tty.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+extern void arc_init_irq(void);
+
+#ifdef CONFIG_ARCH_ARC
+MACHINE_START(ARCHIMEDES, "Acorn-Archimedes")
+ MAINTAINER("Dave Gilbert")
+ BOOT_PARAMS(0x0207c000)
+ INITIRQ(arc_init_irq)
+MACHINE_END
+#endif
+#ifdef CONFIG_ARCH_A5K
+MACHINE_START(A5K, "Acorn-A5000")
+ MAINTAINER("Russell King")
+ BOOT_PARAMS(0x0207c000)
+ INITIRQ(arc_init_irq)
+MACHINE_END
+#endif
+
diff --git a/arch/arm/kernel/debug-armo.S b/arch/arm/mach-arc/debug.S
index cc10311ff..cc10311ff 100644
--- a/arch/arm/kernel/debug-armo.S
+++ b/arch/arm/mach-arc/debug.S
diff --git a/arch/arm/kernel/dma-arc.c b/arch/arm/mach-arc/dma.c
index 50c057e73..50c057e73 100644
--- a/arch/arm/kernel/dma-arc.c
+++ b/arch/arm/mach-arc/dma.c
diff --git a/arch/arm/mm/fault-armo.c b/arch/arm/mach-arc/fault.c
index a37c625f4..a37c625f4 100644
--- a/arch/arm/mm/fault-armo.c
+++ b/arch/arm/mach-arc/fault.c
diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/mach-arc/head.S
index 0dabd06b2..0dabd06b2 100644
--- a/arch/arm/kernel/head-armo.S
+++ b/arch/arm/mach-arc/head.S
diff --git a/arch/arm/mach-arc/irq.c b/arch/arm/mach-arc/irq.c
new file mode 100644
index 000000000..c271db09b
--- /dev/null
+++ b/arch/arm/mach-arc/irq.c
@@ -0,0 +1,153 @@
+/*
+ * linux/arch/arm/mach-arc/irq.c
+ *
+ * Copyright (C) 1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Changelog:
+ * 24-09-1996 RMK Created
+ * 10-10-1996 RMK Brought up to date with arch-sa110eval
+ * 22-10-1996 RMK Changed interrupt numbers & uses new inb/outb macros
+ * 11-01-1998 RMK Added mask_and_ack_irq
+ * 22-08-1998 RMK Restructured IRQ routines
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/mach/irq.h>
+#include <asm/hardware/ioc.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+extern void init_FIQ(void);
+
+#ifdef CONFIG_ARCH_ARC
+#define a_clf() clf()
+#define a_stf() stf()
+#else
+#define a_clf() do { } while (0)
+#define a_stf() do { } while (0)
+#endif
+
+static void arc_mask_irq_ack_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ a_clf();
+ val = ioc_readb(IOC_IRQMASKA);
+ ioc_writeb(val & ~mask, IOC_IRQMASKA);
+ ioc_writeb(mask, IOC_IRQCLRA);
+ a_stf();
+}
+
+static void arc_mask_irq_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ a_clf();
+ val = ioc_readb(IOC_IRQMASKA);
+ ioc_writeb(val & ~mask, IOC_IRQMASKA);
+ a_stf();
+}
+
+static void arc_unmask_irq_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ a_clf();
+ val = ioc_readb(IOC_IRQMASKA);
+ ioc_writeb(val | mask, IOC_IRQMASKA);
+ a_stf();
+}
+
+static void arc_mask_irq_b(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = ioc_readb(IOC_IRQMASKB);
+ ioc_writeb(val & ~mask, IOC_IRQMASKB);
+}
+
+static void arc_unmask_irq_b(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = ioc_readb(IOC_IRQMASKB);
+ ioc_writeb(val | mask, IOC_IRQMASKB);
+}
+
+static void arc_mask_irq_fiq(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = ioc_readb(IOC_FIQMASK);
+ ioc_writeb(val & ~mask, IOC_FIQMASK);
+}
+
+static void arc_unmask_irq_fiq(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = ioc_readb(IOC_FIQMASK);
+ ioc_writeb(val | mask, IOC_FIQMASK);
+}
+
+void __init arc_init_irq(void)
+{
+ int irq;
+
+ ioc_writeb(0, IOC_IRQMASKA);
+ ioc_writeb(0, IOC_IRQMASKB);
+ ioc_writeb(0, IOC_FIQMASK);
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ switch (irq) {
+ case 0 ... 6:
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
+ irq_desc[irq].mask = arc_mask_irq_a;
+ irq_desc[irq].unmask = arc_unmask_irq_a;
+ break;
+
+ case 7:
+ irq_desc[irq].noautoenable = 1;
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
+ irq_desc[irq].mask = arc_mask_irq_a;
+ irq_desc[irq].unmask = arc_unmask_irq_a;
+ break;
+
+ case 9 ... 15:
+ irq_desc[irq].probe_ok = 1;
+ case 8:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = arc_mask_irq_b;
+ irq_desc[irq].mask = arc_mask_irq_b;
+ irq_desc[irq].unmask = arc_unmask_irq_b;
+ break;
+
+ case 64 ... 72:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = arc_mask_irq_fiq;
+ irq_desc[irq].mask = arc_mask_irq_fiq;
+ irq_desc[irq].unmask = arc_unmask_irq_fiq;
+ break;
+ }
+ }
+
+ irq_desc[IRQ_KEYBOARDTX].noautoenable = 1;
+
+ init_FIQ();
+}
+
diff --git a/arch/arm/mm/mm-armo.c b/arch/arm/mach-arc/mm.c
index aec1dad54..aec1dad54 100644
--- a/arch/arm/mm/mm-armo.c
+++ b/arch/arm/mach-arc/mm.c
diff --git a/arch/arm/kernel/oldlatches.c b/arch/arm/mach-arc/oldlatches.c
index c7237c40d..c7237c40d 100644
--- a/arch/arm/kernel/oldlatches.c
+++ b/arch/arm/mach-arc/oldlatches.c
diff --git a/arch/arm/mach-clps711x/Makefile b/arch/arm/mach-clps711x/Makefile
new file mode 100644
index 000000000..27688676e
--- /dev/null
+++ b/arch/arm/mach-clps711x/Makefile
@@ -0,0 +1,29 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := clps711x.o
+
+# Object file lists.
+
+obj-y := irq.o mm.o time.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs := leds-p720t.o
+
+obj-$(CONFIG_ARCH_AUTCPU12) += autcpu12.o
+obj-$(CONFIG_ARCH_CDB89712) += cdb89712.o
+obj-$(CONFIG_ARCH_CLEP7312) += clep7312.o
+obj-$(CONFIG_ARCH_EDB7211) += edb7211-arch.o edb7211-mm.o
+obj-$(CONFIG_ARCH_P720T) += p720t.o
+leds-$(CONFIG_ARCH_P720T) += p720t-leds.o
+obj-$(CONFIG_LEDS) += $(leds-y)
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
new file mode 100644
index 000000000..dff16c193
--- /dev/null
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -0,0 +1,72 @@
+/*
+ * linux/arch/arm/mach-clps711x/autcpu12.c
+ *
+ * (c) 2001 Thomas Gleixner, autronix automation <gleixner@autronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/hardware.h>
+#include <asm/sizes.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/arch/autcpu12.h>
+
+extern void clps711x_map_io(void);
+extern void clps711x_init_irq(void);
+
+/*
+ * The on-chip registers are given a size of 1MB so that a section can
+ * be used to map them; this saves a page table. This is the place to
+ * add mappings for ROM, expansion memory, PCMCIA, etc. (if static
+ * mappings are chosen for those areas).
+ *
+*/
+
+static struct map_desc autcpu12_io_desc[] __initdata = {
+ /* virtual, physical, length, domain, r, w, c, b */
+ /* memory-mapped extra io and CS8900A Ethernet chip */
+ /* ethernet chip */
+ { AUTCPU12_VIRT_CS8900A, AUTCPU12_PHYS_CS8900A, SZ_1M, DOMAIN_IO, 1, 1, 0, 0 },
+
+ LAST_DESC
+};
+
+void __init autcpu12_map_io(void)
+{
+ clps711x_map_io();
+ iotable_init(autcpu12_io_desc);
+}
+
+MACHINE_START(AUTCPU12, "autronix autcpu12")
+ MAINTAINER("Thomas Gleixner")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xff000000)
+ BOOT_PARAMS(0xc0020000)
+ MAPIO(autcpu12_map_io)
+ INITIRQ(clps711x_init_irq)
+MACHINE_END
+
diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
new file mode 100644
index 000000000..9764b379b
--- /dev/null
+++ b/arch/arm/mach-clps711x/cdb89712.c
@@ -0,0 +1,75 @@
+/*
+ * linux/arch/arm/mach-clps711x/cdb89712.c
+ *
+ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+extern void clps711x_init_irq(void);
+extern void clps711x_map_io(void);
+
+/*
+ * Map the CS89712 Ethernet port. That should be moved to the
+ * ethernet driver, perhaps.
+ */
+static struct map_desc cdb89712_io_desc[] __initdata = {
+ { ETHER_BASE, ETHER_START, ETHER_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+static void __init
+fixup_cdb89712(struct machine_desc *desc, struct param_struct *params,
+ char **cmdline, struct meminfo *mi)
+{
+}
+
+static void __init cdb89712_map_io(void)
+{
+ clps711x_map_io();
+ iotable_init(cdb89712_io_desc);
+}
+
+MACHINE_START(CDB89712, "Cirrus-CDB89712")
+ MAINTAINER("Ray Lehtiniemi")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xff000000)
+ BOOT_PARAMS(0xc0000100)
+ FIXUP(fixup_cdb89712)
+ MAPIO(cdb89712_map_io)
+ INITIRQ(clps711x_init_irq)
+MACHINE_END
+
+static int cdb89712_hw_init(void)
+{
+ return 0;
+}
+
+__initcall(cdb89712_hw_init);
+
diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c
new file mode 100644
index 000000000..4a685c39d
--- /dev/null
+++ b/arch/arm/mach-clps711x/clep7312.c
@@ -0,0 +1,49 @@
+/*
+ * linux/arch/arm/mach-clps711x/clep7312.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+extern void clps711x_init_irq(void);
+extern void clps711x_map_io(void);
+
+static void __init
+fixup_clep7312(struct machine_desc *desc, struct param_struct *params,
+ char **cmdline, struct meminfo *mi)
+{
+ mi->nr_banks=1;
+ mi->end = 0xc0FFFFFF;
+ mi->bank[0].start = 0xc0000000;
+ mi->bank[0].size = 0x01000000;
+ mi->bank[0].node = 0;
+}
+
+
+MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
+ MAINTAINER("Nobody")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xff000000)
+ BOOT_PARAMS(0xc0000100)
+ FIXUP(fixup_clep7312)
+ MAPIO(clps711x_map_io)
+ INITIRQ(clps711x_init_irq)
+MACHINE_END
+
diff --git a/arch/arm/mach-clps711x/dma.c b/arch/arm/mach-clps711x/dma.c
new file mode 100644
index 000000000..26d13ae97
--- /dev/null
+++ b/arch/arm/mach-clps711x/dma.c
@@ -0,0 +1,35 @@
+/*
+ * linux/arch/arm/mach-clps711x/dma.c
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/mman.h>
+#include <linux/init.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/dma.h>
+
+void __init arch_dma_init(dma_t *dma)
+{
+}
diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c
new file mode 100644
index 000000000..e53b0d913
--- /dev/null
+++ b/arch/arm/mach-clps711x/edb7211-arch.c
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/arm/mach-clps711x/arch-edb7211.c
+ *
+ * Copyright (C) 2000, 2001 Blue Mug, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+extern void clps711x_init_irq(void);
+extern void edb7211_map_io(void);
+
+static void __init
+fixup_edb7211(struct machine_desc *desc, struct param_struct *params,
+ char **cmdline, struct meminfo *mi)
+{
+ /*
+ * Bank start addresses are not present in the information
+ * passed in from the boot loader. We could potentially
+ * detect them, but instead we hard-code them.
+ *
+ * Banks sizes _are_ present in the param block, but we're
+ * not using that information yet.
+ */
+ mi->bank[0].start = 0xc0000000;
+ mi->bank[0].size = 8*1024*1024;
+ mi->bank[0].node = 0;
+ mi->bank[1].start = 0xc1000000;
+ mi->bank[1].size = 8*1024*1024;
+ mi->bank[1].node = 1;
+ mi->nr_banks = 2;
+}
+
+MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
+ MAINTAINER("Jon McClintock")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xff000000)
+ BOOT_PARAMS(0xc0020100) /* 0xc0000000 - 0xc001ffff can be video RAM */
+ FIXUP(fixup_edb7211)
+ MAPIO(edb7211_map_io)
+ INITIRQ(clps711x_init_irq)
+MACHINE_END
diff --git a/arch/arm/mach-clps711x/edb7211-mm.c b/arch/arm/mach-clps711x/edb7211-mm.c
new file mode 100644
index 000000000..e4e970451
--- /dev/null
+++ b/arch/arm/mach-clps711x/edb7211-mm.c
@@ -0,0 +1,74 @@
+/*
+ * linux/arch/arm/mach-clps711x/mm.c
+ *
+ * Extra MM routines for the EDB7211 board
+ *
+ * Copyright (C) 2000, 2001 Blue Mug, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+
+#define MB1 1048576 /* one megabyte == size of an MMU section */
+
+extern void clps711x_map_io(void);
+
+/*
+ * The on-chip registers are given a size of 1MB so that a section can
+ * be used to map them; this saves a page table. This is the place to
+ * add mappings for ROM, expansion memory, PCMCIA, etc. (if static
+ * mappings are chosen for those areas).
+ *
+ * Here is a physical memory map (to be fleshed out later):
+ *
+ * Physical Address Size Description
+ * ----------------- ----- ---------------------------------
+ * c0000000-c001ffff 128KB reserved for video RAM [1]
+ * c0020000-c0023fff 16KB parameters (see Documentation/arm/Setup)
+ * c0024000-c0027fff 16KB swapper_pg_dir (task 0 page directory)
+ * c0028000-... kernel image (TEXTADDR)
+ *
+ * [1] Unused pages should be given back to the VM; they are not yet.
+ * The parameter block should also be released (not sure if this
+ * happens).
+ */
+static struct map_desc edb7211_io_desc[] __initdata = {
+ /* virtual, physical, length, domain, r, w, c, b */
+
+ /* memory-mapped extra keyboard row and CS8900A Ethernet chip */
+ { EP7211_VIRT_EXTKBD, EP7211_PHYS_EXTKBD, MB1, DOMAIN_IO, 1, 1, 0, 0 },
+ { EP7211_VIRT_CS8900A, EP7211_PHYS_CS8900A, MB1, DOMAIN_IO, 1, 1, 0, 0 },
+
+ /* flash banks */
+ { EP7211_VIRT_FLASH1, EP7211_PHYS_FLASH1, MB1 * 8, DOMAIN_KERNEL, 1, 1, 0, 0 },
+ { EP7211_VIRT_FLASH2, EP7211_PHYS_FLASH2, MB1 * 8, DOMAIN_KERNEL, 1, 1, 0, 0 },
+
+ LAST_DESC
+};
+
+void __init edb7211_map_io(void)
+{
+ clps711x_map_io();
+ iotable_init(edb7211_io_desc);
+}
+
diff --git a/arch/arm/mach-clps711x/irq.c b/arch/arm/mach-clps711x/irq.c
new file mode 100644
index 000000000..91f7c664e
--- /dev/null
+++ b/arch/arm/mach-clps711x/irq.c
@@ -0,0 +1,138 @@
+/*
+ * linux/arch/arm/mach-clps711x/irq.c
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+
+#include <asm/mach/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/hardware/clps7111.h>
+
+static void mask_irq_int1(unsigned int irq)
+{
+ u32 intmr1;
+
+ intmr1 = clps_readl(INTMR1);
+ intmr1 &= ~(1 << irq);
+ clps_writel(intmr1, INTMR1);
+}
+
+static void mask_ack_irq_int1(unsigned int irq)
+{
+ u32 intmr1;
+
+ intmr1 = clps_readl(INTMR1);
+ intmr1 &= ~(1 << irq);
+ clps_writel(intmr1, INTMR1);
+
+ switch (irq) {
+ case IRQ_CSINT: clps_writel(0, COEOI); break;
+ case IRQ_TC1OI: clps_writel(0, TC1EOI); break;
+ case IRQ_TC2OI: clps_writel(0, TC2EOI); break;
+ case IRQ_RTCMI: clps_writel(0, RTCEOI); break;
+ case IRQ_TINT: clps_writel(0, TEOI); break;
+ case IRQ_UMSINT: clps_writel(0, UMSEOI); break;
+ }
+}
+
+static void unmask_irq_int1(unsigned int irq)
+{
+ u32 intmr1;
+
+ intmr1 = clps_readl(INTMR1);
+ intmr1 |= 1 << irq;
+ clps_writel(intmr1, INTMR1);
+}
+
+static void mask_irq_int2(unsigned int irq)
+{
+ u32 intmr2;
+
+ intmr2 = clps_readl(INTMR2);
+ intmr2 &= ~(1 << (irq - 16));
+ clps_writel(intmr2, INTMR2);
+}
+
+static void mask_ack_irq_int2(unsigned int irq)
+{
+ u32 intmr2;
+
+ intmr2 = clps_readl(INTMR2);
+ intmr2 &= ~(1 << (irq - 16));
+ clps_writel(intmr2, INTMR2);
+
+ switch (irq) {
+ case IRQ_KBDINT: clps_writel(0, KBDEOI); break;
+ }
+}
+
+static void unmask_irq_int2(unsigned int irq)
+{
+ u32 intmr2;
+
+ intmr2 = clps_readl(INTMR2);
+ intmr2 |= 1 << (irq - 16);
+ clps_writel(intmr2, INTMR2);
+}
+
+void __init clps711x_init_irq(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < NR_IRQS; i++) {
+ if (INT1_IRQS & (1 << i)) {
+ irq_desc[i].valid = 1;
+ irq_desc[i].probe_ok = 1;
+ irq_desc[i].mask_ack = (INT1_ACK_IRQS & (1 << i)) ?
+ mask_ack_irq_int1 :
+ mask_irq_int1;
+ irq_desc[i].mask = mask_irq_int1;
+ irq_desc[i].unmask = unmask_irq_int1;
+ }
+ if (INT2_IRQS & (1 << i)) {
+ irq_desc[i].valid = 1;
+ irq_desc[i].probe_ok = 1;
+ irq_desc[i].mask_ack = (INT2_ACK_IRQS & (1 << i)) ?
+ mask_ack_irq_int2 :
+ mask_irq_int2;
+ irq_desc[i].mask = mask_irq_int2;
+ irq_desc[i].unmask = unmask_irq_int2;
+ }
+ }
+
+ /*
+ * Disable interrupts
+ */
+ clps_writel(0, INTMR1);
+ clps_writel(0, INTMR2);
+
+ /*
+ * Clear down any pending interrupts
+ */
+ clps_writel(0, COEOI);
+ clps_writel(0, TC1EOI);
+ clps_writel(0, TC2EOI);
+ clps_writel(0, RTCEOI);
+ clps_writel(0, TEOI);
+ clps_writel(0, UMSEOI);
+ clps_writel(0, SYNCIO);
+ clps_writel(0, KBDEOI);
+}
diff --git a/arch/arm/mach-clps711x/mm.c b/arch/arm/mach-clps711x/mm.c
new file mode 100644
index 000000000..077610a76
--- /dev/null
+++ b/arch/arm/mach-clps711x/mm.c
@@ -0,0 +1,70 @@
+/*
+ * linux/arch/arm/mach-clps711x/mm.c
+ *
+ * Generic MM setup for the CLPS711x-based machines.
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+
+#include <asm/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/clps7111.h>
+
+#if 0 //def CONFIG_DISCONTIGMEM
+
+/*
+ * The assumption of maximum 4 discontiguous memory banks is present
+ * in several places in the ARM kernel, including the parameter block
+ * (this affects boot loaders, too). Banks do not necessarily
+ * correspond 1:1 with NUMA nodes, although they usually will,
+ * especially if they are widely discontiguous.
+ *
+ * - note that the parameter block is depreciated for new implementations
+ * - also note that discontig_node_data is actually used
+ * -- rmk
+ */
+
+static bootmem_data_t node_bootmem_data[4];
+
+pg_data_t clps711x_node_data[4] = {
+ { bdata: &node_bootmem_data[0] },
+ { bdata: &node_bootmem_data[1] },
+ { bdata: &node_bootmem_data[2] },
+ { bdata: &node_bootmem_data[3] },
+};
+
+#endif
+
+/*
+ * This maps the generic CLPS711x registers
+ */
+static struct map_desc clps711x_io_desc[] __initdata = {
+ { CLPS7111_VIRT_BASE, CLPS7111_PHYS_BASE, 1048576, DOMAIN_IO, 0, 1 },
+ LAST_DESC
+};
+
+void __init clps711x_map_io(void)
+{
+ iotable_init(clps711x_io_desc);
+}
diff --git a/arch/arm/mach-clps711x/p720t-leds.c b/arch/arm/mach-clps711x/p720t-leds.c
new file mode 100644
index 000000000..23e014f97
--- /dev/null
+++ b/arch/arm/mach-clps711x/p720t-leds.c
@@ -0,0 +1,67 @@
+/*
+ * linux/arch/arm/mach-clps711x/leds.c
+ *
+ * Integrator LED control routines
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include <asm/hardware/clps7111.h>
+#include <asm/hardware/ep7212.h>
+
+static void p720t_leds_event(led_event_t ledevt)
+{
+ unsigned long flags;
+ u32 pddr;
+
+ local_irq_save(flags);
+ switch(ledevt) {
+ case led_idle_start:
+ break;
+
+ case led_idle_end:
+ break;
+
+ case led_timer:
+ pddr = clps_readb(PDDR);
+ clps_writeb(pddr ^ 1, PDDR);
+ break;
+
+ default:
+ break;
+ }
+
+ local_irq_restore(flags);
+}
+
+static int __init leds_init(void)
+{
+ if (machine_is_p720t())
+ leds_event = p720t_leds_event;
+
+ return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
new file mode 100644
index 000000000..ffb6daecd
--- /dev/null
+++ b/arch/arm/mach-clps711x/p720t.c
@@ -0,0 +1,118 @@
+/*
+ * linux/arch/arm/mach-clps711x/p720t.c
+ *
+ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/syspld.h>
+
+extern void clps711x_init_irq(void);
+extern void clps711x_map_io(void);
+
+/*
+ * Map the P720T system PLD. It occupies two address spaces:
+ * SYSPLD_PHYS_BASE and SYSPLD_PHYS_BASE + 0x00400000
+ * We map both here.
+ */
+static struct map_desc p720t_io_desc[] __initdata = {
+ { SYSPLD_VIRT_BASE, SYSPLD_PHYS_BASE, 1048576, DOMAIN_IO, 0, 1 },
+ { 0xfe400000, 0x10400000, 1048576, DOMAIN_IO, 0, 1 },
+ LAST_DESC
+};
+
+static void __init
+fixup_p720t(struct machine_desc *desc, struct param_struct *params,
+ char **cmdline, struct meminfo *mi)
+{
+ struct tag *tag = (struct tag *)params;
+
+ /*
+ * Our bootloader doesn't setup any tags (yet).
+ */
+ if (tag->hdr.tag != ATAG_CORE) {
+ tag->hdr.tag = ATAG_CORE;
+ tag->hdr.size = tag_size(tag_core);
+ tag->u.core.flags = 0;
+ tag->u.core.pagesize = PAGE_SIZE;
+ tag->u.core.rootdev = 0x0100;
+
+ tag = tag_next(tag);
+ tag->hdr.tag = ATAG_MEM;
+ tag->hdr.size = tag_size(tag_mem32);
+ tag->u.mem.size = 4096;
+ tag->u.mem.start = PHYS_OFFSET;
+
+ tag = tag_next(tag);
+ tag->hdr.tag = ATAG_NONE;
+ tag->hdr.size = 0;
+ }
+}
+
+static void __init p720t_map_io(void)
+{
+ clps711x_map_io();
+ iotable_init(p720t_io_desc);
+}
+
+MACHINE_START(P720T, "ARM-Prospector720T")
+ MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xff000000)
+ BOOT_PARAMS(0xc0000100)
+ FIXUP(fixup_p720t)
+ MAPIO(p720t_map_io)
+ INITIRQ(clps711x_init_irq)
+MACHINE_END
+
+static int p720t_hw_init(void)
+{
+ /*
+ * Power down as much as possible in case we don't
+ * have the drivers loaded.
+ */
+ PLD_LCDEN = 0;
+ PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
+
+ PLD_KBD = 0;
+ PLD_IO = 0;
+ PLD_IRDA = 0;
+ PLD_CODEC = 0;
+ PLD_TCH = 0;
+ PLD_SPI = 0;
+#ifndef CONFIG_DEBUG_LL
+ PLD_COM2 = 0;
+ PLD_COM1 = 0;
+#endif
+
+ return 0;
+}
+
+__initcall(p720t_hw_init);
+
diff --git a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c
new file mode 100644
index 000000000..95994b409
--- /dev/null
+++ b/arch/arm/mach-clps711x/time.c
@@ -0,0 +1,54 @@
+/*
+ * linux/arch/arm/mach-clps711x/time.c
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/hardware/clps7111.h>
+
+extern unsigned long (*gettimeoffset)(void);
+
+/*
+ * gettimeoffset() returns time since last timer tick, in usecs.
+ *
+ * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+ * 'tick' is usecs per jiffy.
+ */
+static unsigned long clps711x_gettimeoffset(void)
+{
+ unsigned long hwticks;
+ hwticks = LATCH - (clps_readl(TC2D) & 0xffff); /* since last underflow */
+ return (hwticks * tick) / LATCH;
+}
+
+void __init clps711x_setup_timer(void)
+{
+ unsigned int syscon;
+
+ gettimeoffset = clps711x_gettimeoffset;
+
+ syscon = clps_readl(SYSCON1);
+ syscon |= SYSCON1_TC2S | SYSCON1_TC2M;
+ clps_writel(syscon, SYSCON1);
+
+ clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */
+
+ xtime.tv_sec = clps_readl(RTCDR);
+}
diff --git a/arch/arm/mach-clps7500/Makefile b/arch/arm/mach-clps7500/Makefile
new file mode 100644
index 000000000..06ae353c9
--- /dev/null
+++ b/arch/arm/mach-clps7500/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := clps7500.o
+
+# Object file lists.
+
+obj-y := core.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs :=
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
new file mode 100644
index 000000000..29707ac9a
--- /dev/null
+++ b/arch/arm/mach-clps7500/core.c
@@ -0,0 +1,236 @@
+/*
+ * linux/arch/arm/mm/mm-cl7500.c
+ *
+ * Copyright (C) 1998 Russell King
+ * Copyright (C) 1999 Nexus Electronics Ltd
+ *
+ * Extra MM routines for CL7500 architecture
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/proc/domain.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+static void cl7500_mask_irq_ack_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ val = iomd_readb(IOMD_IRQMASKA);
+ iomd_writeb(val & ~mask, IOMD_IRQMASKA);
+ iomd_writeb(mask, IOMD_IRQCLRA);
+}
+
+static void cl7500_mask_irq_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ val = iomd_readb(IOMD_IRQMASKA);
+ iomd_writeb(val & ~mask, IOMD_IRQMASKA);
+}
+
+static void cl7500_unmask_irq_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ val = iomd_readb(IOMD_IRQMASKA);
+ iomd_writeb(val | mask, IOMD_IRQMASKA);
+}
+
+static void cl7500_mask_irq_b(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_IRQMASKB);
+ iomd_writeb(val & ~mask, IOMD_IRQMASKB);
+}
+
+static void cl7500_unmask_irq_b(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_IRQMASKB);
+ iomd_writeb(val | mask, IOMD_IRQMASKB);
+}
+
+static void cl7500_mask_irq_c(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_IRQMASKC);
+ iomd_writeb(val & ~mask, IOMD_IRQMASKC);
+}
+
+static void cl7500_unmask_irq_c(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_IRQMASKC);
+ iomd_writeb(val | mask, IOMD_IRQMASKC);
+}
+
+
+static void cl7500_mask_irq_d(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_IRQMASKD);
+ iomd_writeb(val & ~mask, IOMD_IRQMASKD);
+}
+
+static void cl7500_unmask_irq_d(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_IRQMASKD);
+ iomd_writeb(val | mask, IOMD_IRQMASKD);
+}
+
+static void cl7500_mask_irq_dma(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_DMAMASK);
+ iomd_writeb(val & ~mask, IOMD_DMAMASK);
+}
+
+static void cl7500_unmask_irq_dma(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_DMAMASK);
+ iomd_writeb(val | mask, IOMD_DMAMASK);
+}
+
+static void cl7500_mask_irq_fiq(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_FIQMASK);
+ iomd_writeb(val & ~mask, IOMD_FIQMASK);
+}
+
+static void cl7500_unmask_irq_fiq(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_FIQMASK);
+ iomd_writeb(val | mask, IOMD_FIQMASK);
+}
+
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
+
+static struct irqaction irq_isa = { no_action, 0, 0, "isa", NULL, NULL };
+
+static void __init clps7500_init_irq(void)
+{
+ int irq;
+
+ iomd_writeb(0, IOMD_IRQMASKA);
+ iomd_writeb(0, IOMD_IRQMASKB);
+ iomd_writeb(0, IOMD_FIQMASK);
+ iomd_writeb(0, IOMD_DMAMASK);
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ switch (irq) {
+ case 0 ... 6:
+ irq_desc[irq].probe_ok = 1;
+ case 7:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = cl7500_mask_irq_ack_a;
+ irq_desc[irq].mask = cl7500_mask_irq_a;
+ irq_desc[irq].unmask = cl7500_unmask_irq_a;
+ break;
+
+ case 9 ... 15:
+ irq_desc[irq].probe_ok = 1;
+ case 8:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = cl7500_mask_irq_b;
+ irq_desc[irq].mask = cl7500_mask_irq_b;
+ irq_desc[irq].unmask = cl7500_unmask_irq_b;
+ break;
+
+ case 16 ... 22:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = cl7500_mask_irq_dma;
+ irq_desc[irq].mask = cl7500_mask_irq_dma;
+ irq_desc[irq].unmask = cl7500_unmask_irq_dma;
+ break;
+
+ case 24 ... 31:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = cl7500_mask_irq_c;
+ irq_desc[irq].mask = cl7500_mask_irq_c;
+ irq_desc[irq].unmask = cl7500_unmask_irq_c;
+ break;
+
+ case 40 ... 47:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = cl7500_mask_irq_d;
+ irq_desc[irq].mask = cl7500_mask_irq_d;
+ irq_desc[irq].unmask = cl7500_unmask_irq_d;
+ break;
+
+ case 48 ... 55:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = no_action;
+ irq_desc[irq].mask = no_action;
+ irq_desc[irq].unmask = no_action;
+ break;
+
+ case 64 ... 72:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = cl7500_mask_irq_fiq;
+ irq_desc[irq].mask = cl7500_mask_irq_fiq;
+ irq_desc[irq].unmask = cl7500_unmask_irq_fiq;
+ break;
+ }
+ }
+
+ setup_arm_irq(IRQ_ISA, &irq_isa);
+}
+
+static struct map_desc cl7500_io_desc[] __initdata = {
+ { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1 }, /* IO space */
+ { ISA_BASE, ISA_START, ISA_SIZE , DOMAIN_IO, 0, 1 }, /* ISA space */
+ { FLASH_BASE, FLASH_START, FLASH_SIZE, DOMAIN_IO, 0, 1 }, /* Flash */
+ { LED_BASE, LED_START, LED_SIZE , DOMAIN_IO, 0, 1 }, /* LED */
+ LAST_DESC
+};
+
+static void __init clps7500_map_io(void)
+{
+ iotable_init(cl7500_io_desc);
+}
+
+MACHINE_START(CLPS7500, "CL-PS7500")
+ MAINTAINER("Philip Blundell")
+ BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
+ MAPIO(clps7500_map_io)
+ INITIRQ(clps7500_init_irq)
+MACHINE_END
+
diff --git a/arch/arm/mach-ebsa110/Makefile b/arch/arm/mach-ebsa110/Makefile
index 59e508bb4..e9777093a 100644
--- a/arch/arm/mach-ebsa110/Makefile
+++ b/arch/arm/mach-ebsa110/Makefile
@@ -11,7 +11,7 @@ O_TARGET := ebsa110.o
# Object file lists.
-obj-y := arch.o io.o irq.o mm.o time.o
+obj-y := core.o io.o time.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-ebsa110/arch.c b/arch/arm/mach-ebsa110/arch.c
deleted file mode 100644
index 384129705..000000000
--- a/arch/arm/mach-ebsa110/arch.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * linux/arch/arm/mach-ebsa110/arch.c
- *
- * Architecture specific fixups.
- */
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/init.h>
-
-#include <asm/elf.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/hardware/dec21285.h>
-
-extern void ebsa110_map_io(void);
-extern void ebsa110_init_irq(void);
-
-MACHINE_START(EBSA110, "EBSA110")
- MAINTAINER("Russell King")
- BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000)
- BOOT_PARAMS(0x00000400)
- DISABLE_PARPORT(0)
- DISABLE_PARPORT(2)
- SOFT_REBOOT
- MAPIO(ebsa110_map_io)
- INITIRQ(ebsa110_init_irq)
-MACHINE_END
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
new file mode 100644
index 000000000..b439af9cc
--- /dev/null
+++ b/arch/arm/mach-ebsa110/core.c
@@ -0,0 +1,97 @@
+/*
+ * linux/arch/arm/mach-ebsa110/core.c
+ *
+ * Copyright (C) 1998-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Extra MM routines for the EBSA-110 architecture
+ */
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+#define IRQ_MASK 0xfe000000 /* read */
+#define IRQ_MSET 0xfe000000 /* write */
+#define IRQ_STAT 0xff000000 /* read */
+#define IRQ_MCLR 0xff000000 /* write */
+
+static void ebsa110_mask_irq(unsigned int irq)
+{
+ __raw_writeb(1 << irq, IRQ_MCLR);
+}
+
+static void ebsa110_unmask_irq(unsigned int irq)
+{
+ __raw_writeb(1 << irq, IRQ_MSET);
+}
+
+static void __init ebsa110_init_irq(void)
+{
+ unsigned long flags;
+ int irq;
+
+ save_flags_cli (flags);
+ __raw_writeb(0xff, IRQ_MCLR);
+ __raw_writeb(0x55, IRQ_MSET);
+ __raw_writeb(0x00, IRQ_MSET);
+ if (__raw_readb(IRQ_MASK) != 0x55)
+ while (1);
+ __raw_writeb(0xff, IRQ_MCLR); /* clear all interrupt enables */
+ restore_flags (flags);
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = ebsa110_mask_irq;
+ irq_desc[irq].mask = ebsa110_mask_irq;
+ irq_desc[irq].unmask = ebsa110_unmask_irq;
+ }
+}
+
+static struct map_desc ebsa110_io_desc[] __initdata = {
+ /*
+ * sparse external-decode ISAIO space
+ */
+ { IRQ_STAT, TRICK4_PHYS, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* IRQ_STAT/IRQ_MCLR */
+ { IRQ_MASK, TRICK3_PHYS, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* IRQ_MASK/IRQ_MSET */
+ { SOFT_BASE, TRICK1_PHYS, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* SOFT_BASE */
+ { PIT_BASE, TRICK0_PHYS, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* PIT_BASE */
+
+ /*
+ * self-decode ISAIO space
+ */
+ { ISAIO_BASE, ISAIO_PHYS, ISAIO_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
+ { ISAMEM_BASE, ISAMEM_PHYS, ISAMEM_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+static void __init ebsa110_map_io(void)
+{
+ iotable_init(ebsa110_io_desc);
+}
+
+MACHINE_START(EBSA110, "EBSA110")
+ MAINTAINER("Russell King")
+ BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000)
+ BOOT_PARAMS(0x00000400)
+ DISABLE_PARPORT(0)
+ DISABLE_PARPORT(2)
+ SOFT_REBOOT
+ MAPIO(ebsa110_map_io)
+ INITIRQ(ebsa110_init_irq)
+MACHINE_END
diff --git a/arch/arm/mach-ebsa110/hardware.h b/arch/arm/mach-ebsa110/hardware.h
deleted file mode 100644
index 1f5039275..000000000
--- a/arch/arm/mach-ebsa110/hardware.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * linux/arch/arm/mach-ebsa110/hardware.h
- *
- * Copyright (C) 2001 Russell King
- *
- * Local hardware definitions.
- */
-#ifndef HARDWARE_H
-#define HARDWARE_H
-
-#define IRQ_MASK 0xfe000000 /* read */
-#define IRQ_MSET 0xfe000000 /* write */
-#define IRQ_STAT 0xff000000 /* read */
-#define IRQ_MCLR 0xff000000 /* write */
-
-#endif
diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c
index 0ebc07a29..c948ddf30 100644
--- a/arch/arm/mach-ebsa110/io.c
+++ b/arch/arm/mach-ebsa110/io.c
@@ -67,9 +67,9 @@ u8 __readb(void *addr)
u32 ret, a = __isamem_convert_addr(addr);
if ((int)addr & 1)
- ret = __arch_getl(a);
+ ret = __raw_getl(a);
else
- ret = __arch_getb(a);
+ ret = __raw_getb(a);
return ret;
}
@@ -80,7 +80,7 @@ u16 __readw(void *addr)
if ((int)addr & 1)
BUG();
- return __arch_getw(a);
+ return __raw_getw(a);
}
u32 __readl(void *addr)
@@ -90,8 +90,8 @@ u32 __readl(void *addr)
if ((int)addr & 3)
BUG();
- ret = __arch_getw(a);
- ret |= __arch_getw(a + 4) << 16;
+ ret = __raw_getw(a);
+ ret |= __raw_getw(a + 4) << 16;
return ret;
}
@@ -104,9 +104,9 @@ void __writeb(u8 val, void *addr)
u32 a = __isamem_convert_addr(addr);
if ((int)addr & 1)
- __arch_putl(val, a);
+ __raw_putl(val, a);
else
- __arch_putb(val, a);
+ __raw_putb(val, a);
}
void __writew(u16 val, void *addr)
@@ -116,7 +116,7 @@ void __writew(u16 val, void *addr)
if ((int)addr & 1)
BUG();
- __arch_putw(val, a);
+ __raw_putw(val, a);
}
void __writel(u32 val, void *addr)
@@ -126,8 +126,8 @@ void __writel(u32 val, void *addr)
if ((int)addr & 3)
BUG();
- __arch_putw(val, a);
- __arch_putw(val >> 16, a + 4);
+ __raw_putw(val, a);
+ __raw_putw(val >> 16, a + 4);
}
EXPORT_SYMBOL(__writeb);
@@ -147,7 +147,7 @@ u8 __inb(int port)
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- ret = __arch_getb(ISAIO_BASE + (port << 2));
+ ret = __raw_getb(ISAIO_BASE + (port << 2));
else {
u32 a = ISAIO_BASE + ((port & ~1) << 1);
@@ -155,9 +155,9 @@ u8 __inb(int port)
* Shame nothing else does
*/
if (port & 1)
- ret = __arch_getl(a);
+ ret = __raw_getl(a);
else
- ret = __arch_getb(a);
+ ret = __raw_getb(a);
}
return ret;
}
@@ -170,7 +170,7 @@ u16 __inw(int port)
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- ret = __arch_getw(ISAIO_BASE + (port << 2));
+ ret = __raw_getw(ISAIO_BASE + (port << 2));
else {
u32 a = ISAIO_BASE + ((port & ~1) << 1);
@@ -180,7 +180,7 @@ u16 __inw(int port)
if (port & 1)
BUG();
- ret = __arch_getw(a);
+ ret = __raw_getw(a);
}
return ret;
}
@@ -201,7 +201,7 @@ void __outb(u8 val, int port)
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- __arch_putb(val, ISAIO_BASE + (port << 2));
+ __raw_putb(val, ISAIO_BASE + (port << 2));
else {
u32 a = ISAIO_BASE + ((port & ~1) << 1);
@@ -209,9 +209,9 @@ void __outb(u8 val, int port)
* Shame nothing else does
*/
if (port & 1)
- __arch_putl(val, a);
+ __raw_putl(val, a);
else
- __arch_putb(val, a);
+ __raw_putb(val, a);
}
}
@@ -230,7 +230,7 @@ void __outw(u16 val, int port)
BUG();
}
- __arch_putw(val, ISAIO_BASE + off);
+ __raw_putw(val, ISAIO_BASE + off);
}
void __outl(u32 val, int port)
diff --git a/arch/arm/mach-ebsa110/irq.c b/arch/arm/mach-ebsa110/irq.c
deleted file mode 100644
index eb75998f4..000000000
--- a/arch/arm/mach-ebsa110/irq.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * linux/arch/arm/mach-ebsa110/irq.c
- *
- * Copyright (C) 1996-1998 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Changelog:
- * 22-08-1998 RMK Restructured IRQ routines
- */
-#include <linux/init.h>
-
-#include <asm/mach/irq.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include "hardware.h"
-
-static void ebsa110_mask_irq(unsigned int irq)
-{
- __raw_writeb(1 << irq, IRQ_MCLR);
-}
-
-static void ebsa110_unmask_irq(unsigned int irq)
-{
- __raw_writeb(1 << irq, IRQ_MSET);
-}
-
-void __init ebsa110_init_irq(void)
-{
- unsigned long flags;
- int irq;
-
- save_flags_cli (flags);
- __raw_writeb(0xff, IRQ_MCLR);
- __raw_writeb(0x55, IRQ_MSET);
- __raw_writeb(0x00, IRQ_MSET);
- if (__raw_readb(IRQ_MASK) != 0x55)
- while (1);
- __raw_writeb(0xff, IRQ_MCLR); /* clear all interrupt enables */
- restore_flags (flags);
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
- irq_desc[irq].mask_ack = ebsa110_mask_irq;
- irq_desc[irq].mask = ebsa110_mask_irq;
- irq_desc[irq].unmask = ebsa110_unmask_irq;
- }
-}
-
diff --git a/arch/arm/mach-ebsa110/mm.c b/arch/arm/mach-ebsa110/mm.c
deleted file mode 100644
index dda27d808..000000000
--- a/arch/arm/mach-ebsa110/mm.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/mach-ebsa110/mm.c
- *
- * Copyright (C) 1998-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Extra MM routines for the EBSA-110 architecture
- */
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-#include "hardware.h"
-
-static struct map_desc ebsa110_io_desc[] __initdata = {
- /*
- * sparse external-decode ISAIO space
- */
- { IRQ_STAT, TRICK4_PHYS, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* IRQ_STAT/IRQ_MCLR */
- { IRQ_MASK, TRICK3_PHYS, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* IRQ_MASK/IRQ_MSET */
- { SOFT_BASE, TRICK1_PHYS, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* SOFT_BASE */
- { PIT_BASE, TRICK0_PHYS, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* PIT_BASE */
-
- /*
- * self-decode ISAIO space
- */
- { ISAIO_BASE, ISAIO_PHYS, ISAIO_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
- { ISAMEM_BASE, ISAMEM_PHYS, ISAMEM_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
- LAST_DESC
-};
-
-void __init ebsa110_map_io(void)
-{
- iotable_init(ebsa110_io_desc);
-}
diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c
index 5b66964e0..55f172156 100644
--- a/arch/arm/mach-epxa10db/mm.c
+++ b/arch/arm/mach-epxa10db/mm.c
@@ -27,6 +27,7 @@
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
+#include <asm/sizes.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile
index a5992fd55..08eb0dd81 100644
--- a/arch/arm/mach-footbridge/Makefile
+++ b/arch/arm/mach-footbridge/Makefile
@@ -11,7 +11,7 @@ O_TARGET := footbridge.o
# Object file lists.
-obj-y := arch.o irq.o mm.o #dma.o
+obj-y := arch.o dc21285.o dma.o irq.o mm.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c
index 9b12f7314..0e09d3150 100644
--- a/arch/arm/mach-footbridge/cats-pci.c
+++ b/arch/arm/mach-footbridge/cats-pci.c
@@ -11,7 +11,6 @@
#include <asm/irq.h>
#include <asm/mach/pci.h>
-#include <asm/hardware/dec21285.h>
/* cats host-specific stuff */
static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
@@ -31,10 +30,16 @@ static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
return -1;
}
+/*
+ * why not the standard PCI swizzle? does this prevent 4-port tulip
+ * cards being used (ie, pci-pci bridge based cards)?
+ */
struct hw_pci cats_pci __initdata = {
- setup_resources: dc21285_setup_resources,
- init: dc21285_init,
- mem_offset: DC21285_PCI_MEM,
- swizzle: no_swizzle,
+ swizzle: NULL,
map_irq: cats_map_irq,
+ nr_controllers: 1,
+ setup: dc21285_setup,
+ scan: dc21285_scan_bus,
+ preinit: dc21285_preinit,
+ postinit: dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c
index 47a5cf271..8f1603d78 100644
--- a/arch/arm/mach-footbridge/ebsa285-pci.c
+++ b/arch/arm/mach-footbridge/ebsa285-pci.c
@@ -11,15 +11,9 @@
#include <asm/irq.h>
#include <asm/mach/pci.h>
-#include <asm/hardware/dec21285.h>
static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
-static u8 __init ebsa285_swizzle(struct pci_dev *dev, u8 *pin)
-{
- return PCI_SLOT(dev->devfn);
-}
-
static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
@@ -34,9 +28,11 @@ static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
}
struct hw_pci ebsa285_pci __initdata = {
- setup_resources: dc21285_setup_resources,
- init: dc21285_init,
- mem_offset: DC21285_PCI_MEM,
- swizzle: ebsa285_swizzle,
+ swizzle: pci_std_swizzle,
map_irq: ebsa285_map_irq,
+ nr_controllers: 1,
+ setup: dc21285_setup,
+ scan: dc21285_scan_bus,
+ preinit: dc21285_preinit,
+ postinit: dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c
index 4fe7436ce..d8bae268d 100644
--- a/arch/arm/mach-footbridge/netwinder-pci.c
+++ b/arch/arm/mach-footbridge/netwinder-pci.c
@@ -11,47 +11,42 @@
#include <asm/irq.h>
#include <asm/mach/pci.h>
-#include <asm/hardware/dec21285.h>
-/* netwinder host-specific stuff */
+/*
+ * We now use the slot ID instead of the device identifiers to select
+ * which interrupt is routed where.
+ */
static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
-#define DEV(v,d) ((v)<<16|(d))
- switch (DEV(dev->vendor, dev->device)) {
- case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142):
- case DEV(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885):
- case DEV(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_YELLOWFIN):
- return IRQ_NETWINDER_ETHER100;
+ switch (slot) {
+ case 0: /* host bridge */
+ return 0;
- case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a):
- return IRQ_NETWINDER_ETHER10;
+ case 9: /* CyberPro */
+ return IRQ_NETWINDER_VGA;
- case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553):
- return 0;
+ case 10: /* DC21143 */
+ return IRQ_NETWINDER_ETHER100;
- case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105):
+ case 12: /* Winbond 553 */
return IRQ_ISA_HARDDISK1;
- case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000):
- case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010):
- case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000):
- return IRQ_NETWINDER_VGA;
-
- case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285):
- return 0;
+ case 13: /* Winbond 89C940F */
+ return IRQ_NETWINDER_ETHER10;
default:
- printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n",
- dev->bus->number, dev->devfn,
- dev->vendor, dev->device);
+ printk(KERN_ERR "PCI: unknown device in slot %s: %s\n",
+ dev->slot_name, dev->name);
return 0;
}
}
struct hw_pci netwinder_pci __initdata = {
- setup_resources: dc21285_setup_resources,
- init: dc21285_init,
- mem_offset: DC21285_PCI_MEM,
- swizzle: no_swizzle,
+ swizzle: pci_std_swizzle,
map_irq: netwinder_map_irq,
+ nr_controllers: 1,
+ setup: dc21285_setup,
+ scan: dc21285_scan_bus,
+ preinit: dc21285_preinit,
+ postinit: dc21285_postinit,
};
diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c
index 2f4029c0f..9df2853b3 100644
--- a/arch/arm/mach-footbridge/personal-pci.c
+++ b/arch/arm/mach-footbridge/personal-pci.c
@@ -11,7 +11,6 @@
#include <asm/irq.h>
#include <asm/mach/pci.h>
-#include <asm/hardware/dec21285.h>
static int irqmap_personal_server[] __initdata = {
IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0,
@@ -38,9 +37,10 @@ static int __init personal_server_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
}
struct hw_pci personal_server_pci __initdata = {
- setup_resources: dc21285_setup_resources,
- init: dc21285_init,
- mem_offset: DC21285_PCI_MEM,
- swizzle: no_swizzle,
map_irq: personal_server_map_irq,
+ nr_controllers: 1,
+ setup: dc21285_setup,
+ scan: dc21285_scan_bus,
+ preinit: dc21285_preinit,
+ postinit: dc21285_postinit,
};
diff --git a/arch/arm/mach-ftvpci/Makefile b/arch/arm/mach-ftvpci/Makefile
new file mode 100644
index 000000000..ac9e394e1
--- /dev/null
+++ b/arch/arm/mach-ftvpci/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := ftvpci.o
+
+# Object file lists.
+
+obj-y := core.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs :=
+
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_LEDS) += leds.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/arm/mach-ftvpci/core.c b/arch/arm/mach-ftvpci/core.c
new file mode 100644
index 000000000..d9d2f3fea
--- /dev/null
+++ b/arch/arm/mach-ftvpci/core.c
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/arm/mach-ftvpci/core.c
+ *
+ * Architecture specific fixups.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+extern unsigned long soft_irq_mask;
+
+static const unsigned char irq_cmd[] =
+{
+ INTCONT_IRQ_DUART,
+ INTCONT_IRQ_PLX,
+ INTCONT_IRQ_D,
+ INTCONT_IRQ_C,
+ INTCONT_IRQ_B,
+ INTCONT_IRQ_A,
+ INTCONT_IRQ_SYSERR
+};
+
+static void ftvpci_mask_irq(unsigned int irq)
+{
+ __raw_writel(irq_cmd[irq], INTCONT_BASE);
+ soft_irq_mask &= ~(1<<irq);
+}
+
+static void ftvpci_unmask_irq(unsigned int irq)
+{
+ soft_irq_mask |= (1<<irq);
+ __raw_writel(irq_cmd[irq] | 1, INTCONT_BASE);
+}
+
+static void __init ftvpci_init_irq(void)
+{
+ unsigned int i;
+
+ /* Mask all FIQs */
+ __raw_writel(INTCONT_FIQ_PLX, INTCONT_BASE);
+ __raw_writel(INTCONT_FIQ_D, INTCONT_BASE);
+ __raw_writel(INTCONT_FIQ_C, INTCONT_BASE);
+ __raw_writel(INTCONT_FIQ_B, INTCONT_BASE);
+ __raw_writel(INTCONT_FIQ_A, INTCONT_BASE);
+ __raw_writel(INTCONT_FIQ_SYSERR, INTCONT_BASE);
+
+ /* Disable all interrupts initially. */
+ for (i = 0; i < NR_IRQS; i++) {
+ if (i >= FIRST_IRQ && i <= LAST_IRQ) {
+ irq_desc[i].valid = 1;
+ irq_desc[i].probe_ok = 1;
+ irq_desc[i].mask_ack = ftvpci_mask_irq;
+ irq_desc[i].mask = ftvpci_mask_irq;
+ irq_desc[i].unmask = ftvpci_unmask_irq;
+ ftvpci_mask_irq(i);
+ } else {
+ irq_desc[i].valid = 0;
+ irq_desc[i].probe_ok = 0;
+ }
+ }
+}
+
+static struct map_desc ftvpci_io_desc[] __initdata = {
+ { INTCONT_BASE, INTCONT_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { PLX_BASE, PLX_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { PCIO_BASE, PLX_IO_START, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
+ { DUART_BASE, DUART_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ { STATUS_BASE, STATUS_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+static void __init ftvpci_map_io(void)
+{
+ iotable_init(ftvpci_io_desc);
+}
+
+MACHINE_START(NEXUSPCI, "FTV/PCI")
+ MAINTAINER("Philip Blundell")
+ BOOT_MEM(0x40000000, 0x10000000, 0xe0000000)
+ MAPIO(ftvpci_map_io)
+ INITIRQ(ftvpci_init_irq)
+MACHINE_END
diff --git a/arch/arm/mach-integrator/pci.c b/arch/arm/mach-integrator/pci.c
index 21b151ec2..ca7f031ee 100644
--- a/arch/arm/mach-integrator/pci.c
+++ b/arch/arm/mach-integrator/pci.c
@@ -114,9 +114,11 @@ extern void pci_v3_setup_resources(struct resource **res);
extern void pci_v3_init(void *);
struct hw_pci integrator_pci __initdata = {
- setup_resources: pci_v3_setup_resources,
- init: pci_v3_init,
mem_offset: 0x40000000,
swizzle: integrator_swizzle,
map_irq: integrator_map_irq,
+ setup: pci_v3_setup,
+ scan: pci_v3_scan_bus,
+ preinit: pci_v3_preinit,
+ postinit: pci_v3_postinit,
};
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 8dee8740e..914d097a7 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -37,6 +37,8 @@
#include <asm/hardware/pci_v3.h>
+int setup_arm_irq(int irq, struct irqaction * new);
+
/*
* The V3 PCI interface chip in Integrator provides several windows from
* local bus memory into the PCI memory areas. Unfortunately, there
@@ -411,7 +413,7 @@ static struct resource pre_mem = {
flags: IORESOURCE_MEM | IORESOURCE_PREFETCH,
};
-void __init pci_v3_setup_resources(struct resource **resource)
+static void __init pci_v3_setup_resources(struct resource **resource)
{
if (request_resource(&iomem_resource, &non_mem))
printk("PCI: unable to allocate non-prefetchable memory region\n");
@@ -433,18 +435,21 @@ void __init pci_v3_setup_resources(struct resource **resource)
* means I can't get additional information on the reason for the pm2fb
* problems. I suppose I'll just have to mind-meld with the machine. ;)
*/
-#define SC_PCI (IO_ADDRESS(INTEGRATOR_SC_PCIENABLE))
-#define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE+0x20))
-#define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE+0x24))
+#define SC_PCI (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_PCIENABLE_OFFSET)
+#define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x20)
+#define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x24)
static int v3_fault(unsigned long addr, struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
unsigned long instr = *(unsigned long *)pc;
+// char buf[128];
- printk("V3 fault: address=0x%08lx, pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
- addr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
- v3_readb(V3_LB_ISTAT));
+// sprintf(buf, "V3 fault: address=0x%08lx, pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
+// addr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
+// v3_readb(V3_LB_ISTAT));
+// printk("%s", buf);
+// printascii(buf);
v3_writeb(V3_LB_ISTAT, 0);
__raw_writel(3, SC_PCI);
@@ -467,11 +472,20 @@ static int v3_fault(unsigned long addr, struct pt_regs *regs)
return 0;
}
+ if ((instr & 0x0e100090) == 0x00100090) {
+ int reg = (instr >> 12) & 15;
+
+ regs->uregs[reg] = -1;
+ regs->ARM_pc += 4;
+ return 0;
+ }
+
return 1;
}
static void v3_irq(int irq, void *devid, struct pt_regs *regs)
{
+#ifdef CONFIG_DEBUG_LL
unsigned long pc = instruction_pointer(regs);
unsigned long instr = *(unsigned long *)pc;
char buf[128];
@@ -480,10 +494,13 @@ static void v3_irq(int irq, void *devid, struct pt_regs *regs)
pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
v3_readb(V3_LB_ISTAT));
printascii(buf);
+#endif
+ v3_writew(V3_PCI_STAT, 0xf000);
v3_writeb(V3_LB_ISTAT, 0);
__raw_writel(3, SC_PCI);
+#ifdef CONFIG_DEBUG_LL
/*
* If the instruction being executed was a read,
* make it look like it read all-ones.
@@ -493,12 +510,14 @@ static void v3_irq(int irq, void *devid, struct pt_regs *regs)
sprintf(buf, " reg%d = %08lx\n", reg, regs->uregs[reg]);
printascii(buf);
}
+#endif
}
static struct irqaction v3_int = {
name: "V3",
handler: v3_irq,
};
+
static struct irqaction v3_int2 = {
name: "V3TM",
handler: v3_irq,
@@ -506,14 +525,26 @@ static struct irqaction v3_int2 = {
extern int (*external_fault)(unsigned long addr, struct pt_regs *regs);
+int pci_v3_setup(int nr, struct pci_sys_data *sys)
+{
+ if (nr)
+ pci_v3_setup_resources(sys->resource);
+ return nr ? 0 : 1;
+}
+
+struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ return pci_scan_bus(sys->busnr, &pci_v3_ops, sys);
+}
+
/*
* V3_LB_BASE? - local bus address
* V3_LB_MAP? - pci bus address
*/
-void __init pci_v3_init(void *sysdata)
+void __init pci_v3_preinit(void)
{
- unsigned int pci_cmd;
unsigned long flags;
+ unsigned int temp;
/*
* Hook in our fault handler for PCI errors
@@ -523,6 +554,12 @@ void __init pci_v3_init(void *sysdata)
spin_lock_irqsave(&v3_lock, flags);
/*
+ * Unlock V3 registers, but only if they were previously locked.
+ */
+ if (v3_readw(V3_SYSTEM) & V3_SYSTEM_M_LOCK)
+ v3_writew(V3_SYSTEM, 0xa05f);
+
+ /*
* Setup window 0 - PCI non-prefetchable memory
* Local: 0x40000000 Bus: 0x00000000 Size: 256MB
*/
@@ -548,27 +585,56 @@ void __init pci_v3_init(void *sysdata)
V3_LB_BASE_ENABLE);
v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
+ /*
+ * Disable PCI to host IO cycles
+ */
+ temp = v3_readw(V3_PCI_CFG) & ~V3_PCI_CFG_M_I2O_EN;
+ temp |= V3_PCI_CFG_M_IO_REG_DIS | V3_PCI_CFG_M_IO_DIS;
+ v3_writew(V3_PCI_CFG, temp);
+
+ printk("FIFO_CFG: %04x FIFO_PRIO: %04x\n",
+ v3_readw(V3_FIFO_CFG), v3_readw(V3_FIFO_PRIORITY));
+
+ /*
+ * Set the V3 FIFO such that writes have higher priority than
+ * reads, and local bus write causes local bus read fifo flush.
+ * Same for PCI.
+ */
+ v3_writew(V3_FIFO_PRIORITY, 0x0a0a);
+
+ /*
+ * Re-lock the system register.
+ */
+ temp = v3_readw(V3_SYSTEM) | V3_SYSTEM_M_LOCK;
+ v3_writew(V3_SYSTEM, temp);
+
+ /*
+ * Clear any error conditions, and enable write errors.
+ */
+ v3_writeb(V3_LB_ISTAT, 0);
+ v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10));
+ v3_writeb(V3_LB_IMASK, 0x28);
+ __raw_writel(3, SC_PCI);
+
+ /*
+ * Grab the PCI error interrupt.
+ */
+ setup_arm_irq(IRQ_V3INT, &v3_int);
+
spin_unlock_irqrestore(&v3_lock, flags);
+}
- pci_scan_bus(0, &pci_v3_ops, sysdata);
+void __init pci_v3_postinit(void)
+{
+ unsigned int pci_cmd;
pci_cmd = PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
v3_writew(V3_PCI_CMD, pci_cmd);
- /*
- * Clear any error conditions.
- */
- __raw_writel(3, SC_PCI);
- v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10));
- v3_writeb(V3_LB_ISTAT, 0);
+ v3_writeb(V3_LB_ISTAT, ~0x40);
v3_writeb(V3_LB_IMASK, 0x68);
- printk("LB_CFG: %04x LB_ISTAT: %02x LB_IMASK: %02x\n",
- v3_readw(V3_LB_CFG),
- v3_readb(V3_LB_ISTAT),
- v3_readb(V3_LB_IMASK));
- setup_arm_irq(IRQ_V3INT, &v3_int);
// setup_arm_irq(IRQ_LBUSTIMEOUT, &v3_int2);
}
diff --git a/arch/arm/mach-iop310/Makefile b/arch/arm/mach-iop310/Makefile
new file mode 100644
index 000000000..906e42518
--- /dev/null
+++ b/arch/arm/mach-iop310/Makefile
@@ -0,0 +1,33 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := iop310.o
+
+# Object file lists.
+
+obj-y := arch.o mm.o xs80200-irq.o iop310-irq.o \
+ iop310-pci.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs :=
+
+obj-$(CONFIG_ARCH_IQ80310) += iq80310-pci.o iq80310-irq.o
+
+ifneq ($(CONFIG_XSCALE_PMU_TIMER),y)
+obj-y += iq80310-time.o
+endif
+
+obj-$(CONFIG_IOP310_AAU) += aau.o
+obj-$(CONFIG_IOP310_DMA) += dma.o
+obj-$(CONFIG_IOP310_MU) += message.o
+obj-$(CONFIG_IOP310_PMON) += pmon.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/arm/mach-iop310/arch.c b/arch/arm/mach-iop310/arch.c
new file mode 100644
index 000000000..3e6956c2c
--- /dev/null
+++ b/arch/arm/mach-iop310/arch.c
@@ -0,0 +1,61 @@
+/*
+ * linux/arch/arm/mach-iop310/arch.c
+ *
+ * Author: Nicolas Pitre <nico@cam.org>
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#ifdef CONFIG_ARCH_IQ80310
+extern void iq80310_map_io(void);
+extern void iq80310_init_irq(void);
+
+static void __init
+fixup_iq80310(struct machine_desc *desc, struct param_struct *params,
+ char **cmdline, struct meminfo *mi)
+{
+ system_rev = (*(volatile unsigned int*)0xfe830000) & 0x0f;
+
+ if(system_rev)
+ system_rev = 0xF;
+
+ mi->bank[0].start = PHYS_OFFSET;
+ mi->bank[0].size = (32*1024*1024);
+ mi->bank[0].node = 0;
+ mi->nr_banks = 1;
+
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = to_kdev_t(0x00FF); /* /dev/nfs pseudo device */
+#elif defined(CONFIG_BLK_DEV_INITRD)
+ setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE );
+ setup_initrd( 0xc0800000, 4*1024*1024 );
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); /* /dev/ram */
+#endif
+}
+
+MACHINE_START(IQ80310, "Cyclone IQ80310")
+ MAINTAINER("MontaVista Software Inc.")
+ BOOT_MEM(0xa0000000, 0xfe000000, 0xfe000000)
+ FIXUP(fixup_iq80310)
+ MAPIO(iq80310_map_io)
+ INITIRQ(iq80310_init_irq)
+MACHINE_END
+
+#else
+#error No machine descriptor defined for this IOP310 implementation
+#endif
diff --git a/arch/arm/mach-iop310/iop310-irq.c b/arch/arm/mach-iop310/iop310-irq.c
new file mode 100644
index 000000000..30cc61408
--- /dev/null
+++ b/arch/arm/mach-iop310/iop310-irq.c
@@ -0,0 +1,109 @@
+/*
+ * linux/arch/arm/mach-iop310/iop310-irq.c
+ *
+ * Generic IOP310 IRQ handling functionality
+ *
+ * Author: Nicolas Pitre
+ * Copyright: (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Added IOP310 chipset and IQ80310 board demuxing, masking code. - DS
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/mach-types.h>
+
+extern void xs80200_irq_mask(unsigned int);
+extern void xs80200_irq_unmask(unsigned int);
+extern void xs80200_init_irq(void);
+
+extern void do_IRQ(int, struct pt_regs *);
+
+u32 iop310_mask = 0;
+
+static void
+iop310_irq_mask (unsigned int irq)
+{
+ iop310_mask |= (1 << (irq - IOP310_IRQ_OFS));
+
+ /*
+ * No mask bits on the 80312, so we have to
+ * mask everything from the outside!
+ */
+ xs80200_irq_mask(IRQ_XS80200_EXTIRQ);
+}
+
+static void
+iop310_irq_unmask (unsigned int irq)
+{
+ iop310_mask &= ~(1 << (irq - IOP310_IRQ_OFS));
+
+ /*
+ * Check if all 80312 sources are unmasked now
+ */
+ if(!iop310_mask)
+ {
+ xs80200_irq_unmask(IRQ_XS80200_EXTIRQ);
+
+ }
+}
+
+void iop310_irq_demux(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ u32 fiq1isr = *((volatile u32*)IOP310_FIQ1ISR);
+ u32 fiq2isr = *((volatile u32*)IOP310_FIQ2ISR);
+ unsigned int irqno = 0;
+
+ if(fiq1isr)
+ {
+ if(fiq1isr & 0x1)
+ irqno = IRQ_IOP310_DMA0;
+ if(fiq1isr & 0x2)
+ irqno = IRQ_IOP310_DMA1;
+ if(fiq1isr & 0x4)
+ irqno = IRQ_IOP310_DMA2;
+ if(fiq1isr & 0x10)
+ irqno = IRQ_IOP310_PMON;
+ if(fiq1isr & 0x20)
+ irqno = IRQ_IOP310_AAU;
+ }
+ else
+ {
+ if(fiq2isr & 0x2)
+ irqno = IRQ_IOP310_I2C;
+ if(fiq2isr & 0x4)
+ irqno = IRQ_IOP310_MU;
+ }
+
+ do_IRQ(irqno, regs);
+}
+
+void __init iop310_init_irq(void)
+{
+ int i;
+
+ for(i = IOP310_IRQ_OFS; i < NR_IOP310_IRQS; i++)
+ {
+ irq_desc[i].valid = 1;
+ irq_desc[i].probe_ok = 1;
+ irq_desc[i].mask_ack = iop310_irq_mask;
+ irq_desc[i].mask = iop310_irq_mask;
+ irq_desc[i].unmask = iop310_irq_unmask;
+ }
+
+ xs80200_init_irq();
+}
+
diff --git a/arch/arm/mach-iop310/iop310-pci.c b/arch/arm/mach-iop310/iop310-pci.c
new file mode 100644
index 000000000..33f3718e6
--- /dev/null
+++ b/arch/arm/mach-iop310/iop310-pci.c
@@ -0,0 +1,500 @@
+/*
+ * arch/arm/mach-iop310/iop310-pci.c
+ *
+ * PCI support for the Intel IOP310 chipset
+ *
+ * Matt Porter <mporter@mvista.com>
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach/pci.h>
+
+#include <asm/arch/iop310.h>
+
+/*
+ * *** Special note - why the IOP310 should NOT be used ***
+ *
+ * The PCI ATU is a brain dead implementation, only allowing 32-bit
+ * accesses to PCI configuration space. This is especially brain
+ * dead for writes to this space. A simple for-instance:
+ *
+ * You want to modify the command register *without* corrupting the
+ * status register.
+ *
+ * To perform this, you need to read *32* bits of data from offset 4,
+ * mask off the low 16, replace them with the new data, and write *32*
+ * bits back.
+ *
+ * Writing the status register at offset 6 with status bits set *clears*
+ * the status.
+ *
+ * Hello? Could we have a *SANE* implementation of a PCI ATU some day
+ * *PLEASE*?
+ */
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+extern int (*external_fault)(unsigned long, struct pt_regs *);
+
+static u32 iop310_cfg_address(struct pci_dev *dev, int where)
+{
+ struct pci_sys_data *sys = dev->sysdata;
+ u32 addr;
+
+ where &= ~3;
+
+ if (sys->busnr == dev->bus->number)
+ addr = 1 << (PCI_SLOT(dev->devfn) + 16);
+ else
+ addr = dev->bus->number << 16 |
+ PCI_SLOT(dev->devfn) << 11 | 1;
+
+ addr |= PCI_FUNC(dev->devfn) << 8 | where;
+
+ return addr;
+}
+
+/*
+ * Primary PCI interface support.
+ */
+static int iop310_pri_pci_status(void)
+{
+ unsigned int status;
+ int ret = 0;
+
+ status = *IOP310_PATUSR;
+ if (status & 0xf900) {
+ *IOP310_PATUSR = status & 0xf900;
+ ret = 1;
+ }
+ status = *IOP310_PATUISR;
+ if (status & 0x0000018f) {
+ *IOP310_PATUISR = status & 0x0000018f;
+ ret = 1;
+ }
+ status = *IOP310_PSR;
+ if (status & 0xf900) {
+ *IOP310_PSR = status & 0xf900;
+ ret = 1;
+ }
+ status = *IOP310_PBISR;
+ if (status & 0x003f) {
+ *IOP310_PBISR = status & 0x003f;
+ ret = 1;
+ }
+ return ret;
+}
+
+static int
+iop310_pri_rd_cfg_byte(struct pci_dev *dev, int where, u8 *p)
+{
+ int ret;
+ u8 val;
+
+ *IOP310_POCCAR = iop310_cfg_address(dev, where);
+
+ val = (*IOP310_POCCDR) >> ((where & 3) * 8);
+ __asm__ __volatile__("nop; nop; nop; nop");
+
+ ret = iop310_pri_pci_status();
+ if (ret)
+ val = 0xff;
+
+ *p = val;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_pri_rd_cfg_word(struct pci_dev *dev, int where, u16 *p)
+{
+ int ret;
+ u16 val;
+
+ *IOP310_POCCAR = iop310_cfg_address(dev, where);
+
+ val = (*IOP310_POCCDR) >> ((where & 2) * 8);
+ __asm__ __volatile__("nop; nop; nop; nop");
+
+ ret = iop310_pri_pci_status();
+ if (ret)
+ val = 0xffff;
+
+ *p = val;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_pri_rd_cfg_dword(struct pci_dev *dev, int where, u32 *p)
+{
+ int ret;
+ u32 val;
+
+ *IOP310_POCCAR = iop310_cfg_address(dev, where);
+
+ val = *IOP310_POCCDR;
+ __asm__ __volatile__("nop; nop; nop; nop");
+
+ ret = iop310_pri_pci_status();
+ if (ret)
+ val = 0xffffffff;
+
+ *p = val;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_pri_wr_cfg_byte(struct pci_dev *dev, int where, u8 v)
+{
+ int ret;
+ u32 val;
+
+ *IOP310_POCCAR = iop310_cfg_address(dev, where);
+
+ val = *IOP310_POCCDR;
+ __asm__ __volatile__("nop; nop; nop; nop");
+
+ ret = iop310_pri_pci_status();
+ if (ret == 0) {
+ where = (where & 3) * 8;
+ val &= ~(0xff << where);
+ val |= v << where;
+ *IOP310_POCCDR = val;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_pri_wr_cfg_word(struct pci_dev *dev, int where, u16 v)
+{
+ int ret;
+ u32 val;
+
+ *IOP310_POCCAR = iop310_cfg_address(dev, where);
+
+ val = *IOP310_POCCDR;
+ __asm__ __volatile__("nop; nop; nop; nop");
+
+ ret = iop310_pri_pci_status();
+ if (ret == 0) {
+ where = (where & 2) * 8;
+ val &= ~(0xffff << where);
+ val |= v << where;
+ *IOP310_POCCDR = val;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_pri_wr_cfg_dword(struct pci_dev *dev, int where, u32 v)
+{
+ *IOP310_POCCAR = iop310_cfg_address(dev, where);
+ *IOP310_POCCDR = v;
+ __asm__ __volatile__("nop; nop; nop; nop");
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops iop310_primary_ops = {
+ iop310_pri_rd_cfg_byte,
+ iop310_pri_rd_cfg_word,
+ iop310_pri_rd_cfg_dword,
+ iop310_pri_wr_cfg_byte,
+ iop310_pri_wr_cfg_word,
+ iop310_pri_wr_cfg_dword,
+};
+
+/*
+ * Secondary PCI interface support.
+ */
+static int iop310_sec_pci_status(void)
+{
+ unsigned int usr, uisr;
+ int ret = 0;
+
+ usr = *IOP310_SATUSR;
+ uisr = *IOP310_SATUISR;
+ if (usr & 0xf900) {
+ *IOP310_SATUSR = usr & 0xf900;
+ ret = 1;
+ }
+ if (uisr & 0x0000069f) {
+ *IOP310_SATUISR = uisr & 0x0000069f;
+ ret = 1;
+ }
+//if (ret) printk("ERROR (%08lx %08lx)", usr, uisr);
+ return ret;
+}
+
+static int
+iop310_sec_rd_cfg_byte(struct pci_dev *dev, int where, u8 *p)
+{
+ int ret;
+ u8 val;
+//printk("rdb: %d:%02x.%x %02x ", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where);
+ *IOP310_SOCCAR = iop310_cfg_address(dev, where);
+
+ val = (*IOP310_SOCCDR) >> ((where & 3) * 8);
+ __asm__ __volatile__("nop; nop; nop; nop");
+//printk(">= %08lx ", val);
+ ret = iop310_sec_pci_status();
+ if (ret)
+ val = 0xff;
+//printk("\n");
+ *p = val;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_sec_rd_cfg_word(struct pci_dev *dev, int where, u16 *p)
+{
+ int ret;
+ u16 val;
+//printk("rdw: %d:%02x.%x %02x ", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where);
+ *IOP310_SOCCAR = iop310_cfg_address(dev, where);
+
+ val = (*IOP310_SOCCDR) >> ((where & 3) * 8);
+ __asm__ __volatile__("nop; nop; nop; nop");
+//printk(">= %08lx ", val);
+ ret = iop310_sec_pci_status();
+ if (ret)
+ val = 0xffff;
+//printk("\n");
+ *p = val;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_sec_rd_cfg_dword(struct pci_dev *dev, int where, u32 *p)
+{
+ int ret;
+ u32 val;
+//printk("rdl: %d:%02x.%x %02x ", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where);
+ *IOP310_SOCCAR = iop310_cfg_address(dev, where);
+
+ val = *IOP310_SOCCDR;
+ __asm__ __volatile__("nop; nop; nop; nop");
+//printk(">= %08lx ", val);
+ ret = iop310_sec_pci_status();
+ if (ret)
+ val = 0xffffffff;
+//printk("\n");
+ *p = val;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_sec_wr_cfg_byte(struct pci_dev *dev, int where, u8 v)
+{
+ int ret;
+ u32 val;
+//printk("wrb: %d:%02x.%x %02x ", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where);
+ *IOP310_SOCCAR = iop310_cfg_address(dev, where);
+
+ val = *IOP310_SOCCDR;
+ __asm__ __volatile__("nop; nop; nop; nop");
+//printk("<= %08lx", v);
+ ret = iop310_sec_pci_status();
+ if (ret == 0) {
+ where = (where & 3) * 8;
+ val &= ~(0xff << where);
+ val |= v << where;
+ *IOP310_SOCCDR = val;
+ }
+//printk("\n");
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_sec_wr_cfg_word(struct pci_dev *dev, int where, u16 v)
+{
+ int ret;
+ u32 val;
+//printk("wrw: %d:%02x.%x %02x ", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where);
+ *IOP310_SOCCAR = iop310_cfg_address(dev, where);
+
+ val = *IOP310_SOCCDR;
+ __asm__ __volatile__("nop; nop; nop; nop");
+//printk("<= %08lx", v);
+ ret = iop310_sec_pci_status();
+ if (ret == 0) {
+ where = (where & 2) * 8;
+ val &= ~(0xffff << where);
+ val |= v << where;
+ *IOP310_SOCCDR = val;
+ }
+//printk("\n");
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop310_sec_wr_cfg_dword(struct pci_dev *dev, int where, u32 v)
+{
+//printk("wrl: %d:%02x.%x %02x ", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where);
+ *IOP310_SOCCAR = iop310_cfg_address(dev, where);
+ *IOP310_SOCCDR = v;
+ __asm__ __volatile__("nop; nop; nop; nop");
+//printk("<= %08lx\n", v);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops iop310_secondary_ops = {
+ iop310_sec_rd_cfg_byte,
+ iop310_sec_rd_cfg_word,
+ iop310_sec_rd_cfg_dword,
+ iop310_sec_wr_cfg_byte,
+ iop310_sec_wr_cfg_word,
+ iop310_sec_wr_cfg_dword,
+};
+
+/*
+ * When a PCI device does not exist during config cycles, the 80200 gets a
+ * bus error instead of returning 0xffffffff. This handler simply returns.
+ */
+int iop310_pci_abort_handler(unsigned long addr, struct pt_regs *regs)
+{
+// printk("PCI abort: address = %08x PC = %08x LR = %08lx\n",
+// addr, regs->ARM_pc, regs->ARM_lr);
+ return 0;
+}
+
+/*
+ * Scan an IOP310 PCI bus. sys->bus defines which bus we scan.
+ */
+struct pci_bus *iop310_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ struct pci_ops *ops;
+
+ if (nr)
+ ops = &iop310_secondary_ops;
+ else
+ ops = &iop310_primary_ops;
+
+ return pci_scan_bus(sys->busnr, ops, sys);
+}
+
+/*
+ * Setup the system data for controller 'nr'. Return 0 if none found,
+ * 1 if found, or negative error.
+ *
+ * We can alter:
+ * io_offset - offset between IO resources and PCI bus BARs
+ * mem_offset - offset between mem resources and PCI bus BARs
+ * resource[0] - parent IO resource
+ * resource[1] - parent non-prefetchable memory resource
+ * resource[2] - parent prefetchable memory resource
+ * swizzle - bridge swizzling function
+ * map_irq - irq mapping function
+ *
+ * Note that 'io_offset' and 'mem_offset' are left as zero since
+ * the IOP310 doesn't attempt to perform any address translation
+ * on accesses from the host to the bus.
+ */
+int iop310_setup(int nr, struct pci_sys_data *sys)
+{
+ struct resource *res;
+
+ if (nr >= 2)
+ return 0;
+
+ res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+ if (!res)
+ panic("PCI: unable to alloc resources");
+
+ switch (nr) {
+ case 0:
+ res[0].start = IOP310_PCIPRI_LOWER_IO + 0x6e000000;
+ res[0].end = IOP310_PCIPRI_LOWER_IO + 0x6e00ffff;
+ res[0].name = "PCI IO Primary";
+
+ res[1].start = IOP310_PCIPRI_LOWER_MEM;
+ res[1].end = IOP310_PCIPRI_LOWER_MEM + IOP310_PCI_WINDOW_SIZE;
+ res[1].name = "PCI Memory Primary";
+ break;
+
+ case 1:
+ res[0].start = IOP310_PCISEC_LOWER_IO + 0x6e000000;
+ res[0].end = IOP310_PCISEC_LOWER_IO + 0x6e00ffff;
+ res[0].name = "PCI IO Primary";
+
+ res[1].start = IOP310_PCISEC_LOWER_MEM;
+ res[1].end = IOP310_PCISEC_LOWER_MEM + IOP310_PCI_WINDOW_SIZE;
+ res[1].name = "PCI Memory Primary";
+ break;
+ }
+
+ request_resource(&ioport_resource, &res[0]);
+ request_resource(&iomem_resource, &res[1]);
+
+ sys->resource[0] = &res[0];
+ sys->resource[1] = &res[1];
+ sys->resource[2] = NULL;
+ sys->io_offset = 0x6e000000;
+
+ return 1;
+}
+
+void iop310_init(void)
+{
+ DBG("PCI: Intel 80312 PCI-to-PCI init code.\n");
+ DBG(" ATU secondary: IOP310_SOMWVR=0x%04x, IOP310_SOIOWVR=0x%04x\n",
+ *IOP310_SOMWVR,
+ *IOP310_SOIOWVR);
+ DBG(" ATU secondary: IOP310_ATUCR=0x%08x\n", *IOP310_ATUCR);
+ DBG(" ATU secondary: IOP310_SIABAR=0x%08x IOP310_SIALR=0x%08x IOP310_SIATVR=%08x\n", *IOP310_SIABAR, *IOP310_SIALR, *IOP310_SIATVR);
+
+ DBG(" ATU primary: IOP310_POMWVR=0x%04x, IOP310_POIOWVR=0x%04x\n",
+ *IOP310_POMWVR,
+ *IOP310_POIOWVR);
+ DBG(" ATU secondary: IOP310_PIABAR=0x%08x IOP310_PIALR=0x%08x IOP310_PIATVR=%08x\n", *IOP310_PIABAR, *IOP310_PIALR, *IOP310_PIATVR);
+
+ DBG(" P2P: IOP310_PCR=0x%04x IOP310_BCR=0x%04x IOP310_EBCR=0x%04x\n", *IOP310_PCR, *IOP310_BCR, *IOP310_EBCR);
+
+ /*
+ * Windows have to be carefully opened via a nice set of calls
+ * here or just some direct register fiddling in the board
+ * specific init when we want transactions to occur between the
+ * two PCI hoses.
+ *
+ * To do this, we will have manage RETRY assertion between the
+ * firmware and the kernel. This will ensure that the host
+ * system's enumeration code is held off until we have tweaked
+ * the interrupt routing and public/private IDSELs.
+ *
+ * For now we will simply default to disabling the integrated type
+ * 81 P2P bridge.
+ */
+ *IOP310_PCR &= 0xfff8;
+
+ external_fault = iop310_pci_abort_handler;
+
+}
+
diff --git a/arch/arm/mach-iop310/iq80310-irq.c b/arch/arm/mach-iop310/iq80310-irq.c
new file mode 100644
index 000000000..4347f13fb
--- /dev/null
+++ b/arch/arm/mach-iop310/iq80310-irq.c
@@ -0,0 +1,172 @@
+/*
+ * linux/arch/arm/mach-iop310/iq80310-irq.c
+ *
+ * IRQ hadling/demuxing for IQ80310 board
+ *
+ * Author: Nicolas Pitre
+ * Copyright: (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 2.4.7-rmk1-iop310.1
+ * Moved demux from asm to C - DS
+ * Fixes for various revision boards - DS
+ */
+
+#include <linux/config.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware.h>
+#include <asm/system.h>
+
+#include <asm/mach-types.h>
+
+extern void xs80200_irq_mask(unsigned int);
+extern void xs80200_irq_unmask(unsigned int);
+extern void xs80200_init_irq(void);
+
+extern void do_IRQ(int, struct pt_regs *);
+
+extern u32 iop310_mask;
+
+extern void iop310_irq_demux(int, void *, struct pt_regs *);
+
+extern int iop310_init_irq(void);
+
+static void
+iq80310_irq_mask (unsigned int irq)
+{
+ volatile char *mask = (volatile char *)IQ80310_INT_MASK;
+ *mask |= (1 << (irq - IQ80310_IRQ_OFS));
+
+ /*
+ * There's no mask for PCI INT A-C, so we just mask out all
+ * external interrupts on the CPU.
+ *
+ * We set a bit of the iop310 mask so that the iop310_irq_mask
+ * function does not unmask EXTINT
+ */
+ if (irq > IRQ_IQ80310_INTD)
+ {
+ xs80200_irq_mask(IRQ_XS80200_EXTIRQ);
+ iop310_mask |= (0x80000000 >> (irq - IRQ_IQ80310_INTD));
+ }
+}
+
+static void
+iq80310_irq_unmask (unsigned int irq)
+{
+ volatile char *mask = (volatile char *)IQ80310_INT_MASK;
+ *mask &= ~(1 << (irq - IQ80310_IRQ_OFS));
+
+ /*
+ * See comment above
+ */
+ if (irq > IRQ_IQ80310_INTD)
+ {
+ xs80200_irq_unmask(IRQ_XS80200_EXTIRQ);
+ iop310_mask &= ~((0x80000000 >> (irq - IRQ_IQ80310_INTD)));
+ }
+}
+
+static void iq80310_cpld_irq_demux(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ u8 irq_stat = *((volatile u8*)IQ80310_INT_STAT);
+ u8 irq_mask = *((volatile u8*)IQ80310_INT_MASK);
+ unsigned int irqno = 0xffffffff;
+
+ // Needed? If IRQ is masked, it shouldn't get through...
+ irq_stat &= ~irq_mask;
+
+
+ if(irq_stat & 0x01)
+ irqno = IRQ_IQ80310_TIMER;
+ else if(irq_stat & 0x02)
+ irqno = IRQ_IQ80310_I82559;
+ else if(irq_stat & 0x04)
+ irqno = IRQ_IQ80310_UART1;
+ else if(irq_stat & 0x08)
+ irqno = IRQ_IQ80310_UART2;
+ else if(irq_stat & 0x10)
+ irqno = IRQ_IQ80310_INTD;
+ else if(system_rev)
+ {
+ irq_stat = *((volatile u8*)IQ80310_PCI_INT_STAT) & 0xf;
+
+ if(irq_stat & 0x1)
+ irqno = IRQ_IQ80310_INTA;
+ else if(irq_stat & 0x2)
+ irqno = IRQ_IQ80310_INTB;
+ else if(irq_stat & 0x4)
+ irqno = IRQ_IQ80310_INTC;
+ }
+ else /* Running on a REV D.1 or older, assume PCI INTA */
+ irqno = IRQ_IQ80310_INTA;
+
+ /*
+ * If we didn't read a CPLD interrupt, we assume it's from
+ * a device on the chipset itself.
+ */
+ if(irqno == 0xffffffff)
+ {
+ iop310_irq_demux(irq, dev_id, regs);
+ return;
+ }
+
+ /*
+ * If on a REV D.1 or lower board, we just assumed INTA since
+ * PCI is not routed, and it may actually be an on-chip interrupt.
+ *
+ * Note that we're giving on-chip interrupts slightly higher
+ * priority than PCI by handling them first.
+ */
+ if(irqno == IRQ_IQ80310_INTA && !system_rev)
+ iop310_irq_demux(irq, dev_id, regs);
+
+ do_IRQ(irqno, regs);
+}
+
+
+static struct irqaction iq80310_cpld_irq = {
+ name: "CPLD_IRQ",
+ handler: iq80310_cpld_irq_demux,
+ flags: SA_INTERRUPT
+};
+
+extern int setup_arm_irq(int, struct irqaction *);
+
+void __init iq80310_init_irq(void)
+{
+ volatile char *mask = (volatile char *)IQ80310_INT_MASK;
+ unsigned int i;
+
+ iop310_init_irq();
+
+ /*
+ * Setup PIRSR to route PCI interrupts into xs80200
+ */
+ *IOP310_PIRSR = 0xff;
+
+ for (i = IQ80310_IRQ_OFS; i < NR_IRQS; i++) {
+ irq_desc[i].valid = 1;
+ irq_desc[i].probe_ok = 1;
+ irq_desc[i].mask_ack = iq80310_irq_mask;
+ irq_desc[i].mask = iq80310_irq_mask;
+ irq_desc[i].unmask = iq80310_irq_unmask;
+ }
+
+ *mask = 0xff; /* mask all sources */
+ setup_arm_irq(IRQ_XS80200_EXTIRQ, &iq80310_cpld_irq);
+
+ /* enable only external IRQ in the INTCTL for now */
+ asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (1<<1));
+}
diff --git a/arch/arm/mach-iop310/iq80310-pci.c b/arch/arm/mach-iop310/iq80310-pci.c
new file mode 100644
index 000000000..a26a8e1e5
--- /dev/null
+++ b/arch/arm/mach-iop310/iq80310-pci.c
@@ -0,0 +1,149 @@
+/*
+ * arch/arm/mach-iop310/iq80310-pci.c
+ *
+ * PCI support for the Intel IQ80310 reference board
+ *
+ * Matt Porter <mporter@mvista.com>
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+
+/*
+ * The following macro is used to lookup irqs in a standard table
+ * format for those systems that do not already have PCI
+ * interrupts properly routed. We assume 1 <= pin <= 4
+ */
+#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
+({ int _ctl_ = -1; \
+ if (idsel >= minid && idsel <= maxid && pin >= 1 && pin <= 4) \
+ _ctl_ = pci_irq_table[idsel - minid][pin-1]; \
+ _ctl_; })
+
+#define INTA IRQ_IQ80310_INTA
+#define INTB IRQ_IQ80310_INTB
+#define INTC IRQ_IQ80310_INTC
+#define INTD IRQ_IQ80310_INTD
+
+#define INTE IRQ_IQ80310_I82559
+
+typedef u8 irq_table[4];
+
+/*
+ * IRQ tables for primary bus.
+ *
+ * On a Rev D.1 and older board, INT A-C are not routed, so we
+ * just fake it as INTA and than we take care of handling it
+ * correctly in the IRQ demux routine.
+ */
+static irq_table pci_pri_d_irq_table[] = {
+/* Pin: A B C D */
+ { INTA, INTD, INTA, INTA }, /* PCI Slot J3 */
+ { INTD, INTA, INTA, INTA }, /* PCI Slot J4 */
+};
+
+static irq_table pci_pri_f_irq_table[] = {
+/* Pin: A B C D */
+ { INTC, INTD, INTA, INTB }, /* PCI Slot J3 */
+ { INTD, INTA, INTB, INTC }, /* PCI Slot J4 */
+};
+
+static int __init
+iq80310_pri_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+ irq_table *pci_irq_table;
+
+ if (!system_rev) {
+ pci_irq_table = pci_pri_d_irq_table;
+ } else {
+ pci_irq_table = pci_pri_f_irq_table;
+ }
+
+ return PCI_IRQ_TABLE_LOOKUP(2, 3);
+}
+
+/*
+ * IRQ tables for secondary bus.
+ *
+ * On a Rev D.1 and older board, INT A-C are not routed, so we
+ * just fake it as INTA and than we take care of handling it
+ * correctly in the IRQ demux routine.
+ */
+static irq_table pci_sec_d_irq_table[] = {
+/* Pin: A B C D */
+ { INTA, INTA, INTA, INTD }, /* PCI Slot J1 */
+ { INTA, INTA, INTD, INTA }, /* PCI Slot J5 */
+ { INTE, INTE, INTE, INTE }, /* P2P Bridge */
+};
+
+static irq_table pci_sec_f_irq_table[] = {
+/* Pin: A B C D */
+ { INTA, INTB, INTC, INTD }, /* PCI Slot J1 */
+ { INTB, INTC, INTD, INTA }, /* PCI Slot J5 */
+ { INTE, INTE, INTE, INTE }, /* P2P Bridge */
+};
+
+static int __init
+iq80310_sec_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+ irq_table *pci_irq_table;
+
+ if (!system_rev) {
+ pci_irq_table = pci_sec_d_irq_table;
+ } else {
+ pci_irq_table = pci_sec_f_irq_table;
+ }
+
+ return PCI_IRQ_TABLE_LOOKUP(0, 2);
+}
+
+static int iq80310_pri_host;
+
+static int iq80310_setup(int nr, struct pci_sys_data *sys)
+{
+ switch (nr) {
+ case 0:
+ if (!iq80310_pri_host)
+ return 0;
+
+ sys->map_irq = iq80310_pri_map_irq;
+ break;
+
+ case 1:
+ sys->map_irq = iq80310_sec_map_irq;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return iop310_setup(nr, sys);
+}
+
+static void iq80310_preinit(void)
+{
+ iq80310_pri_host = *(volatile u32 *)IQ80310_BACKPLANE & 1;
+
+ printk(KERN_INFO "PCI: IQ80310 is a%s\n",
+ iq80310_pri_host ? " system controller" : "n agent");
+
+ iop310_init();
+}
+
+struct hw_pci iq80310_pci __initdata = {
+ swizzle: pci_std_swizzle,
+ nr_controllers: 2,
+ setup: iq80310_setup,
+ scan: iop310_scan_bus,
+ preinit: iq80310_preinit,
+};
diff --git a/arch/arm/mach-iop310/iq80310-time.c b/arch/arm/mach-iop310/iq80310-time.c
new file mode 100644
index 000000000..04040ab85
--- /dev/null
+++ b/arch/arm/mach-iop310/iq80310-time.c
@@ -0,0 +1,125 @@
+/*
+ * linux/arch/arm/mach-iop310/time-iq80310.c
+ *
+ * Timer functions for IQ80310 onboard timer
+ *
+ * Author: Nicolas Pitre
+ * Copyright: (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/timex.h>
+#include <asm/hardware.h>
+
+#include <asm/mach-types.h>
+
+static void iq80310_write_timer (u_long val)
+{
+ volatile u_char *la0 = (volatile u_char *)IQ80310_TIMER_LA0;
+ volatile u_char *la1 = (volatile u_char *)IQ80310_TIMER_LA1;
+ volatile u_char *la2 = (volatile u_char *)IQ80310_TIMER_LA2;
+
+ *la0 = val;
+ *la1 = val >> 8;
+ *la2 = (val >> 16) & 0x3f;
+}
+
+static u_long iq80310_read_timer (void)
+{
+ volatile u_char *la0 = (volatile u_char *)IQ80310_TIMER_LA0;
+ volatile u_char *la1 = (volatile u_char *)IQ80310_TIMER_LA1;
+ volatile u_char *la2 = (volatile u_char *)IQ80310_TIMER_LA2;
+ volatile u_char *la3 = (volatile u_char *)IQ80310_TIMER_LA3;
+ u_long b0, b1, b2, b3, val;
+
+ b0 = *la0; b1 = *la1; b2 = *la2; b3 = *la3;
+ b0 = (((b0 & 0x20) >> 1) | (b0 & 0x1f));
+ b1 = (((b1 & 0x20) >> 1) | (b1 & 0x1f));
+ b2 = (((b2 & 0x20) >> 1) | (b2 & 0x1f));
+ b3 = (b3 & 0x0f);
+ val = ((b0 << 0) | (b1 << 6) | (b2 << 12) | (b3 << 18));
+ return val;
+}
+
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long iq80310_gettimeoffset (void)
+{
+ unsigned long elapsed, usec;
+
+ /* We need elapsed timer ticks since last interrupt */
+ elapsed = iq80310_read_timer();
+
+ /* Now convert them to usec */
+ usec = (unsigned long)(elapsed*tick)/LATCH;
+
+ return usec;
+}
+
+
+static void iq80310_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ volatile u_char *timer_en = (volatile u_char *)IQ80310_TIMER_EN;
+
+ /* clear timer interrupt */
+ *timer_en &= ~2;
+ *timer_en |= 2;
+
+ /*
+ * AHEM..HACK
+ *
+ * Since the timer interrupt is cascaded through the CPLD and
+ * the 80312 and the demux code calls do_IRQ, the irq count is
+ * going to be atleast 2 when we get here and this will cause the
+ * kernel to increment the system tick counter even if we're
+ * idle. This causes it to look like there's always 100% system
+ * time, which is not the case. To get around it, we just decrement
+ * the IRQ count before calling do_timer. We increment it again
+ * b/c otherwise it will go negative and than bad things happen.
+ *
+ * -DS
+ */
+ irq_exit(smp_processor_id(), irq);
+ do_timer(regs);
+ irq_enter(smp_processor_id(), irq);
+}
+
+extern unsigned long (*gettimeoffset)(void);
+
+static struct irqaction timer_irq = {
+ name: "timer",
+ handler: iq80310_timer_interrupt,
+};
+
+
+extern int setup_arm_irq(int, struct irqaction*);
+
+void __init time_init(void)
+{
+ volatile u_char *timer_en = (volatile u_char *)IQ80310_TIMER_EN;
+
+ gettimeoffset = iq80310_gettimeoffset;
+ setup_arm_irq(IRQ_IQ80310_TIMER, &timer_irq);
+ *timer_en = 0;
+ iq80310_write_timer(LATCH);
+ *timer_en |= 2;
+ *timer_en |= 1;
+}
+
diff --git a/arch/arm/mach-iop310/mm.c b/arch/arm/mach-iop310/mm.c
new file mode 100644
index 000000000..4ef0c65ba
--- /dev/null
+++ b/arch/arm/mach-iop310/mm.c
@@ -0,0 +1,71 @@
+/*
+ * linux/arch/arm/mach-iop310/mm.c
+ *
+ * Low level memory intialization for IOP310 based systems
+ *
+ * Author: Nicolas Pitre <npitre@mvista.com>
+ *
+ * Copyright 2000-2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+#ifdef CONFIG_IOP310_MU
+#include "message.h"
+#endif
+
+/*
+ * Standard IO mapping for all IOP310 based systems
+ */
+static struct map_desc iop80310_std_desc[] __initdata = {
+ /* virtual physical length domain r w c b */
+ // IOP310 Memory Mapped Registers
+ { 0xe8001000, 0x00001000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
+ // PCI I/O Space
+ { 0xfe000000, 0x90000000, 0x00020000, DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+void __init iop310_map_io(void)
+{
+ iotable_init(iop80310_std_desc);
+}
+
+/*
+ * IQ80310 specific IO mappings
+ */
+#ifdef CONFIG_ARCH_IQ80310
+static struct map_desc iq80310_io_desc[] __initdata = {
+ /* virtual physical length domain r w c b */
+ // IQ80310 On-Board Devices
+ { 0xfe800000, 0xfe800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+void __init iq80310_map_io(void)
+{
+#ifdef CONFIG_IOP310_MU
+ /* acquiring 1MB of memory aligned on 1MB boundary for MU */
+ mu_mem = __alloc_bootmem(0x100000, 0x100000, 0);
+#endif
+
+ iop310_map_io();
+
+ iotable_init(iq80310_io_desc);
+}
+#endif // CONFIG_ARCH_IQ80310
+
diff --git a/arch/arm/mach-iop310/xs80200-irq.c b/arch/arm/mach-iop310/xs80200-irq.c
new file mode 100644
index 000000000..bc0fbf7e6
--- /dev/null
+++ b/arch/arm/mach-iop310/xs80200-irq.c
@@ -0,0 +1,66 @@
+/*
+ * linux/arch/arm/mach-iop310/xs80200-irq.c
+ *
+ * Generic IRQ handling for the XS80200 XScale core.
+ *
+ * Author: Nicolas Pitre
+ * Copyright: (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/mach-types.h>
+
+void
+xs80200_irq_mask (unsigned int irq)
+{
+ long INTCTL;
+ asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (INTCTL));
+ switch (irq) {
+ case IRQ_XS80200_BCU: INTCTL &= ~(1<<3); break;
+ case IRQ_XS80200_PMU: INTCTL &= ~(1<<2); break;
+ case IRQ_XS80200_EXTIRQ: INTCTL &= ~(1<<1); break;
+ case IRQ_XS80200_EXTFIQ: INTCTL &= ~(1<<0); break;
+ }
+ asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (INTCTL));
+}
+
+void
+xs80200_irq_unmask (unsigned int irq)
+{
+ long INTCTL;
+ asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (INTCTL));
+ switch (irq) {
+ case IRQ_XS80200_BCU: INTCTL |= (1<<3); break;
+ case IRQ_XS80200_PMU: INTCTL |= (1<<2); break;
+ case IRQ_XS80200_EXTIRQ: INTCTL |= (1<<1); break;
+ case IRQ_XS80200_EXTFIQ: INTCTL |= (1<<0); break;
+ }
+ asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (INTCTL));
+}
+
+void __init xs80200_init_irq(void)
+{
+ int i;
+
+ for (i = 0; i < NR_XS80200_IRQS; i++) {
+ irq_desc[i].valid = 1;
+ irq_desc[i].probe_ok = 0;
+ irq_desc[i].mask_ack = xs80200_irq_mask;
+ irq_desc[i].mask = xs80200_irq_mask;
+ irq_desc[i].unmask = xs80200_irq_unmask;
+ }
+}
+
+
diff --git a/arch/arm/mach-l7200/Makefile b/arch/arm/mach-l7200/Makefile
new file mode 100644
index 000000000..b2b356cc7
--- /dev/null
+++ b/arch/arm/mach-l7200/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := l7200.o
+
+# Object file lists.
+
+obj-y := core.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs :=
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c
new file mode 100644
index 000000000..8c91b16b0
--- /dev/null
+++ b/arch/arm/mach-l7200/core.c
@@ -0,0 +1,114 @@
+/*
+ * linux/arch/arm/mm/mm-lusl7200.c
+ *
+ * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
+ *
+ * Extra MM routines for L7200 architecture
+ */
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include <asm/proc/domain.h>
+
+#include <asm/mach/map.h>
+#include <asm/arch/hardware.h>
+
+/*
+ * IRQ base register
+ */
+#define IRQ_BASE (IO_BASE_2 + 0x1000)
+
+/*
+ * Normal IRQ registers
+ */
+#define IRQ_STATUS (*(volatile unsigned long *) (IRQ_BASE + 0x000))
+#define IRQ_RAWSTATUS (*(volatile unsigned long *) (IRQ_BASE + 0x004))
+#define IRQ_ENABLE (*(volatile unsigned long *) (IRQ_BASE + 0x008))
+#define IRQ_ENABLECLEAR (*(volatile unsigned long *) (IRQ_BASE + 0x00c))
+#define IRQ_SOFT (*(volatile unsigned long *) (IRQ_BASE + 0x010))
+#define IRQ_SOURCESEL (*(volatile unsigned long *) (IRQ_BASE + 0x018))
+
+/*
+ * Fast IRQ registers
+ */
+#define FIQ_STATUS (*(volatile unsigned long *) (IRQ_BASE + 0x100))
+#define FIQ_RAWSTATUS (*(volatile unsigned long *) (IRQ_BASE + 0x104))
+#define FIQ_ENABLE (*(volatile unsigned long *) (IRQ_BASE + 0x108))
+#define FIQ_ENABLECLEAR (*(volatile unsigned long *) (IRQ_BASE + 0x10c))
+#define FIQ_SOFT (*(volatile unsigned long *) (IRQ_BASE + 0x110))
+#define FIQ_SOURCESEL (*(volatile unsigned long *) (IRQ_BASE + 0x118))
+
+static void l7200_mask_irq(unsigned int irq)
+{
+ IRQ_ENABLECLEAR = 1 << irq;
+}
+
+static void l7200_unmask_irq(unsigned int irq)
+{
+ IRQ_ENABLE = 1 << irq;
+}
+
+static void __init l7200_init_irq(void)
+{
+ int irq;
+
+ IRQ_ENABLECLEAR = 0xffffffff; /* clear all interrupt enables */
+ FIQ_ENABLECLEAR = 0xffffffff; /* clear all fast interrupt enables */
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = l7200_mask_irq;
+ irq_desc[irq].mask = l7200_mask_irq;
+ irq_desc[irq].unmask = l7200_unmask_irq;
+ }
+
+ init_FIQ();
+}
+
+static struct map_desc l7200_io_desc[] __initdata = {
+ { IO_BASE, IO_START, IO_SIZE, DOMAIN_IO, 0, 1 ,0 ,0},
+ { IO_BASE_2, IO_START_2, IO_SIZE_2, DOMAIN_IO, 0, 1 ,0 ,0},
+ { AUX_BASE, AUX_START, AUX_SIZE, DOMAIN_IO, 0, 1 ,0 ,0},
+ { FLASH1_BASE, FLASH1_START, FLASH1_SIZE, DOMAIN_IO, 0, 1 ,0 ,0},
+ { FLASH2_BASE, FLASH2_START, FLASH2_SIZE, DOMAIN_IO, 0, 1 ,0 ,0},
+ LAST_DESC
+};
+
+static void __init l7200_map_io(void)
+{
+ iotable_init(l7200_io_desc);
+}
+
+static void __init
+fixup_l7200(struct machine_desc *desc, struct param_struct *unused,
+ char **cmdline, struct meminfo *mi)
+{
+ mi->nr_banks = 1;
+ mi->bank[0].start = PHYS_OFFSET;
+ mi->bank[0].size = (32*1024*1024);
+ mi->bank[0].node = 0;
+
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+ setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE);
+ setup_initrd( __phys_to_virt(0xf1000000), 0x005dac7b);
+
+ /* Serial Console COM2 and LCD */
+ strcpy( *cmdline, "console=tty0 console=ttyLU1,115200");
+
+ /* Serial Console COM1 and LCD */
+ //strcpy( *cmdline, "console=tty0 console=ttyLU0,115200");
+
+ /* Console on LCD */
+ //strcpy( *cmdline, "console=tty0");
+}
+
+MACHINE_START(L7200, "LinkUp Systems L7200")
+ MAINTAINER("Steve Hill / Scott McConnell")
+ BOOT_MEM(0xf0000000, 0x80040000, 0xd0000000)
+ FIXUP(fixup_l7200)
+ MAPIO(l7200_map_io)
+ INITIRQ(l7200_init_irq)
+MACHINE_END
+
diff --git a/arch/arm/mach-rpc/Makefile b/arch/arm/mach-rpc/Makefile
new file mode 100644
index 000000000..637ce5dc3
--- /dev/null
+++ b/arch/arm/mach-rpc/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := rpc.o
+
+# Object file lists.
+
+obj-y := dma.o irq.o riscpc.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs :=
+
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c
new file mode 100644
index 000000000..de88d4fba
--- /dev/null
+++ b/arch/arm/mach-rpc/irq.c
@@ -0,0 +1,142 @@
+#include <linux/init.h>
+
+#include <asm/mach/irq.h>
+#include <asm/hardware/iomd.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+static void rpc_mask_irq_ack_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ val = iomd_readb(IOMD_IRQMASKA);
+ iomd_writeb(val & ~mask, IOMD_IRQMASKA);
+ iomd_writeb(mask, IOMD_IRQCLRA);
+}
+
+static void rpc_mask_irq_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ val = iomd_readb(IOMD_IRQMASKA);
+ iomd_writeb(val & ~mask, IOMD_IRQMASKA);
+}
+
+static void rpc_unmask_irq_a(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << irq;
+ val = iomd_readb(IOMD_IRQMASKA);
+ iomd_writeb(val | mask, IOMD_IRQMASKA);
+}
+
+static void rpc_mask_irq_b(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_IRQMASKB);
+ iomd_writeb(val & ~mask, IOMD_IRQMASKB);
+}
+
+static void rpc_unmask_irq_b(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_IRQMASKB);
+ iomd_writeb(val | mask, IOMD_IRQMASKB);
+}
+
+static void rpc_mask_irq_dma(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_DMAMASK);
+ iomd_writeb(val & ~mask, IOMD_DMAMASK);
+}
+
+static void rpc_unmask_irq_dma(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_DMAMASK);
+ iomd_writeb(val | mask, IOMD_DMAMASK);
+}
+
+static void rpc_mask_irq_fiq(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_FIQMASK);
+ iomd_writeb(val & ~mask, IOMD_FIQMASK);
+}
+
+static void rpc_unmask_irq_fiq(unsigned int irq)
+{
+ unsigned int val, mask;
+
+ mask = 1 << (irq & 7);
+ val = iomd_readb(IOMD_FIQMASK);
+ iomd_writeb(val | mask, IOMD_FIQMASK);
+}
+
+void __init rpc_init_irq(void)
+{
+ int irq;
+
+ iomd_writeb(0, IOMD_IRQMASKA);
+ iomd_writeb(0, IOMD_IRQMASKB);
+ iomd_writeb(0, IOMD_FIQMASK);
+ iomd_writeb(0, IOMD_DMAMASK);
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ switch (irq) {
+ case 0 ... 6:
+ irq_desc[irq].probe_ok = 1;
+ case 7:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = rpc_mask_irq_ack_a;
+ irq_desc[irq].mask = rpc_mask_irq_a;
+ irq_desc[irq].unmask = rpc_unmask_irq_a;
+ break;
+
+ case 9 ... 15:
+ irq_desc[irq].probe_ok = 1;
+ case 8:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = rpc_mask_irq_b;
+ irq_desc[irq].mask = rpc_mask_irq_b;
+ irq_desc[irq].unmask = rpc_unmask_irq_b;
+ break;
+
+ case 16 ... 19:
+ case 21:
+ irq_desc[irq].noautoenable = 1;
+ case 20:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = rpc_mask_irq_dma;
+ irq_desc[irq].mask = rpc_mask_irq_dma;
+ irq_desc[irq].unmask = rpc_unmask_irq_dma;
+ break;
+
+ case 64 ... 71:
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = rpc_mask_irq_fiq;
+ irq_desc[irq].mask = rpc_mask_irq_fiq;
+ irq_desc[irq].unmask = rpc_unmask_irq_fiq;
+ break;
+ }
+ }
+
+ irq_desc[IRQ_KEYBOARDTX].noautoenable = 1;
+
+ init_FIQ();
+}
+
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
new file mode 100644
index 000000000..4fef733ed
--- /dev/null
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -0,0 +1,94 @@
+/*
+ * linux/arch/arm/mach-rpc/riscpc.c
+ *
+ * Copyright (C) 1998-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Architecture specific fixups.
+ */
+#include <linux/tty.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+
+#include <asm/elf.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include <asm/proc/domain.h>
+#include <asm/setup.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+extern void rpc_init_irq(void);
+
+extern unsigned int vram_size;
+
+#if 0
+
+unsigned int memc_ctrl_reg;
+unsigned int number_mfm_drives;
+
+static int __init parse_tag_acorn(const struct tag *tag)
+{
+ memc_ctrl_reg = tag->u.acorn.memc_control_reg;
+ number_mfm_drives = tag->u.acorn.adfsdrives;
+
+ switch (tag->u.acorn.vram_pages) {
+ case 512:
+ vram_size += PAGE_SIZE * 256;
+ case 256:
+ vram_size += PAGE_SIZE * 256;
+ default:
+ break;
+ }
+#if 0
+ if (vram_size) {
+ desc->video_start = 0x02000000;
+ desc->video_end = 0x02000000 + vram_size;
+ }
+#endif
+ return 0;
+}
+
+__tagtable(ATAG_ACORN, parse_tag_acorn);
+
+#endif
+
+static void __init
+fixup_riscpc(struct machine_desc *desc, struct param_struct *unusd,
+ char **cmdline, struct meminfo *mi)
+{
+ /*
+ * RiscPC can't handle half-word loads and stores
+ */
+ elf_hwcap &= ~HWCAP_HALF;
+}
+
+static struct map_desc rpc_io_desc[] __initdata = {
+ { SCREEN_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1, 0, 0 }, /* VRAM */
+ { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, /* IO space */
+ { EASI_BASE, EASI_START, EASI_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* EASI space */
+ LAST_DESC
+};
+
+void __init rpc_map_io(void)
+{
+ iotable_init(rpc_io_desc);
+}
+
+MACHINE_START(RISCPC, "Acorn-RiscPC")
+ MAINTAINER("Russell King")
+ BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
+ BOOT_PARAMS(0x10000100)
+ DISABLE_PARPORT(0)
+ DISABLE_PARPORT(1)
+ FIXUP(fixup_riscpc)
+ MAPIO(rpc_map_io)
+ INITIRQ(rpc_init_irq)
+MACHINE_END
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index 99b75fe3c..975cbe4be 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -9,20 +9,15 @@ USE_STANDARD_AS_RULE := true
O_TARGET := sa1100.o
-obj-y :=
+# Common support (must be linked before board specific support)
+obj-y := generic.o irq.o dma.o
obj-m :=
obj-n :=
obj- :=
-export-objs := assabet.o dma-sa1100.o dma-sa1111.o freebird.o generic.o \
- h3600.o huw_webpanel.o irq.o pcipool.o sa1111-pcibuf.o \
- yopy.o
-
-# These aren't present yet, and prevents a plain -ac kernel building.
-# hwtimer.o usb_ctl.o usb_recv.o usb_send.o
-
-# Common support (must be linked before board specific support)
-obj-y += generic.o irq.o dma-sa1100.o
+export-objs := assabet.o dma.o flexanet.o freebird.o generic.o h3600.o \
+ huw_webpanel.o irq.o pcipool.o sa1111.o sa1111-pcibuf.o \
+ yopy.o usb_ctl.o usb_recv.o usb_send.o
# This needs to be cleaned up. We probably need to have SA1100
# and SA1110 config symbols.
@@ -31,11 +26,12 @@ obj-y += generic.o irq.o dma-sa1100.o
ifeq ($(CONFIG_CPU_FREQ),y)
obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
+obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o
obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o
endif
# Next, the SA1111 stuff.
-obj-$(CONFIG_SA1111) += sa1111.o dma-sa1111.o
+obj-$(CONFIG_SA1111) += sa1111.o
obj-$(CONFIG_USB_OHCI_SA1111) += sa1111-pcibuf.o pcipool.o
# Specific board support
@@ -59,7 +55,9 @@ obj-$(CONFIG_SA1100_OMNIMETER) += omnimeter.o
obj-$(CONFIG_SA1100_PANGOLIN) += pangolin.o
obj-$(CONFIG_SA1100_PFS168) += pfs168.o
obj-$(CONFIG_SA1100_PLEB) += pleb.o
+obj-$(CONFIG_SA1100_SHANNON) += shannon.o
obj-$(CONFIG_SA1100_SHERMAN) += sherman.o
+obj-$(CONFIG_SA1100_PT_SYSTEM3) += system3.o
obj-$(CONFIG_SA1100_SIMPAD) += simpad.o
obj-$(CONFIG_SA1100_VICTOR) += victor.o
obj-$(CONFIG_SA1100_XP860) += xp860.o
@@ -77,9 +75,21 @@ leds-$(CONFIG_SA1100_GRAPHICSMASTER) += leds-graphicsmaster.o
leds-$(CONFIG_SA1100_LART) += leds-lart.o
leds-$(CONFIG_SA1100_PFS168) += leds-pfs168.o
leds-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o
+leds-$(CONFIG_SA1100_PT_SYSTEM3) += leds-system3.o
obj-$(CONFIG_LEDS) += $(leds-y)
+# SA1110 USB client support
+list-multi += sa1100usb_core.o
+sa1100usb_core-objs := usb_ctl.o usb_ep0.o usb_recv.o usb_send.o
+obj-$(CONFIG_SA1100_USB) += sa1100usb_core.o
+obj-$(CONFIG_SA1100_USB_NETLINK) += usb-eth.o
+obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o
+
# Miscelaneous functions
obj-$(CONFIG_PM) += pm.o sleep.o
include $(TOPDIR)/Rules.make
+
+sa1100usb_core.o: $(sa1100usb_core-objs)
+ $(LD) -r -o $@ $(sa1100usb_core-objs)
+
diff --git a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c
index 8ccb69450..c2acd141e 100644
--- a/arch/arm/mach-sa1100/adsbitsy.c
+++ b/arch/arm/mach-sa1100/adsbitsy.c
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
+#include <linux/ioport.h>
#include <linux/serial_core.h>
#include <asm/hardware.h>
@@ -53,7 +54,7 @@ static int __init adsbitsy_init(void)
/*
* Probe for SA1111.
*/
- ret = sa1111_probe();
+ ret = sa1111_probe(0x18000000);
if (ret < 0)
return ret;
@@ -94,7 +95,7 @@ static int __init adsbitsy_init(void)
sa1110_mb_enable();
set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_RISING_EDGE);
- sa1111_init_irq(SA1100_GPIO_TO_IRQ(0));
+ sa1111_init_irq(IRQ_GPIO0);
return 0;
}
@@ -126,7 +127,6 @@ fixup_adsbitsy(struct machine_desc *desc, struct param_struct *params,
static struct map_desc adsbitsy_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
{ 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1111 */
LAST_DESC
};
@@ -135,24 +135,15 @@ static int adsbitsy_uart_open(struct uart_port *port, struct uart_info *info)
{
if (port->mapbase == _Ser1UTCR0) {
Ser1SDCR0 |= SDCR0_UART;
- // Set RTS Output and High (should be done in the set_mctrl fn)
- GPDR |= GPIO_GPIO15;
- GPCR |= GPIO_GPIO15;
- // Set CTS Input
- GPDR &= ~GPIO_GPIO14;
+#error Fixme // Set RTS High (should be done in the set_mctrl fn)
+ GPCR = GPIO_GPIO15;
} else if (port->mapbase == _Ser2UTCR0) {
Ser2UTCR4 = Ser2HSCR0 = 0;
- // Set RTS Output and High (should be done in the set_mctrl fn)
- GPDR |= GPIO_GPIO17;
- GPCR |= GPIO_GPIO17;
- // Set CTS Input
- GPDR &= ~GPIO_GPIO16;
+#error Fixme // Set RTS High (should be done in the set_mctrl fn)
+ GPCR = GPIO_GPIO17;
} else if (port->mapbase == _Ser2UTCR0) {
- // Set RTS Output and High (should be done in the set_mctrl fn)
- GPDR |= GPIO_GPIO19;
- GPCR |= GPIO_GPIO19;
- // Set CTS Input
- GPDR &= ~GPIO_GPIO18;
+#error Fixme // Set RTS High (should be done in the set_mctrl fn)
+ GPCR = GPIO_GPIO19;
}
return 0;
}
@@ -166,10 +157,12 @@ static void __init adsbitsy_map_io(void)
sa1100_map_io();
iotable_init(adsbitsy_io_desc);
- sa1110_register_uart_fns(&adsbitsy_port_fns);
+ sa1100_register_uart_fns(&adsbitsy_port_fns);
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
sa1100_register_uart(2, 2);
+ GPDR |= GPIO_GPIO15 | GPIO_GPIO17 | GPIO_GPIO19;
+ GPDR &= ~(GPIO_GPIO14 | GPIO_GPIO16 | GPIO_GPIO18);
}
MACHINE_START(ADSBITSY, "ADS Bitsy")
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index b59221b11..e6cd1bdfd 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -31,16 +31,70 @@
#include "generic.h"
+#define ASSABET_BCR_DB1110 \
+ (ASSABET_BCR_SPK_OFF | ASSABET_BCR_QMUTE | \
+ ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \
+ ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \
+ ASSABET_BCR_IRDA_MD0)
+
+#define ASSABET_BCR_DB1111 \
+ (ASSABET_BCR_SPK_OFF | ASSABET_BCR_QMUTE | \
+ ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \
+ ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \
+ ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \
+ ASSABET_BCR_IRDA_MD0 | ASSABET_BCR_CF_RST)
-unsigned long BCR_value = ASSABET_BCR_DB1110;
unsigned long SCR_value = ASSABET_SCR_INIT;
-EXPORT_SYMBOL(BCR_value);
EXPORT_SYMBOL(SCR_value);
+static unsigned long BCR_value = ASSABET_BCR_DB1110;
+
+void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ BCR_value = (BCR_value & ~mask) | val;
+ ASSABET_BCR = BCR_value;
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(ASSABET_BCR_frob);
+
+static void assabet_backlight_power(int on)
+{
+#ifndef ASSABET_PAL_VIDEO
+ if (on)
+ ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
+ else
+#endif
+ ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
+}
+
+static void assabet_lcd_power(int on)
+{
+#ifndef ASSABET_PAL_VIDEO
+ if (on)
+ ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
+ else
+#endif
+ ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
+}
static int __init assabet_init(void)
{
- if (machine_is_assabet() && machine_has_neponset()) {
+ if (!machine_is_assabet())
+ return -EINVAL;
+
+ /*
+ * Set the IRQ edges
+ */
+ set_GPIO_IRQ_edge(GPIO_GPIO23, GPIO_RISING_EDGE); /* UCB1300 */
+
+ sa1100fb_lcd_power = assabet_lcd_power;
+ sa1100fb_backlight_power = assabet_backlight_power;
+
+ if (machine_has_neponset()) {
/*
* Angel sets this, but other bootloaders may not.
*
@@ -55,6 +109,7 @@ static int __init assabet_init(void)
"hasn't been configured in the kernel\n" );
#endif
}
+
return 0;
}
@@ -87,18 +142,18 @@ static void __init map_sa1100_gpio_regs( void )
* repeat it here because the kernel may not be loaded as a zImage, and
* also because it's a hassle to communicate the SCR value to the kernel
* from the decompressor.
+ *
+ * Note that IRQs are guaranteed to be disabled.
*/
static void __init get_assabet_scr(void)
{
- unsigned long flags, scr, i;
+ unsigned long scr, i;
- local_irq_save(flags);
GPDR |= 0x3fc; /* Configure GPIO 9:2 as outputs */
GPSR = 0x3fc; /* Write 0xFF to GPIO 9:2 */
GPDR &= ~(0x3fc); /* Configure GPIO 9:2 as inputs */
for(i = 100; i--; scr = GPLR); /* Read GPIO 9:2 */
GPDR |= 0x3fc; /* restore correct pin direction */
- local_irq_restore(flags);
scr &= 0x3fc; /* save as system configuration byte. */
SCR_value = scr;
}
@@ -174,7 +229,6 @@ fixup_assabet(struct machine_desc *desc, struct param_struct *params,
static struct map_desc assabet_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
{ 0xf1000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
{ 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
/* f3000000 - neponset system registers */
@@ -186,19 +240,18 @@ static void assabet_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
{
if (port->mapbase == _Ser1UTCR0) {
if (state)
- ASSABET_BCR_clear(ASSABET_BCR_RS232EN);
+ ASSABET_BCR_clear(ASSABET_BCR_RS232EN |
+ ASSABET_BCR_COM_RTS |
+ ASSABET_BCR_COM_DTR);
else
- ASSABET_BCR_set(ASSABET_BCR_RS232EN);
+ ASSABET_BCR_set(ASSABET_BCR_RS232EN |
+ ASSABET_BCR_COM_RTS |
+ ASSABET_BCR_COM_DTR);
}
}
/*
- * Note! this can be called from IRQ context.
- * FIXME: You _need_ to handle ASSABET_BCR carefully, which doesn't
- * happen at the moment. Suggest putting interrupt save/restore
- * in ASSABET_BCR_set/clear.
- *
- * NB: Assabet uses COM_RTS and COM_DTR for both UART1 (com port)
+ * Assabet uses COM_RTS and COM_DTR for both UART1 (com port)
* and UART3 (radio module). We only handle them for UART1 here.
*/
static void assabet_set_mctrl(struct uart_port *port, u_int mctrl)
@@ -207,21 +260,21 @@ static void assabet_set_mctrl(struct uart_port *port, u_int mctrl)
u_int set = 0, clear = 0;
if (mctrl & TIOCM_RTS)
- set |= ASSABET_BCR_COM_RTS;
- else
clear |= ASSABET_BCR_COM_RTS;
+ else
+ set |= ASSABET_BCR_COM_RTS;
if (mctrl & TIOCM_DTR)
- set |= ASSABET_BCR_COM_DTR;
- else
clear |= ASSABET_BCR_COM_DTR;
+ else
+ set |= ASSABET_BCR_COM_DTR;
ASSABET_BCR_clear(clear);
ASSABET_BCR_set(set);
}
}
-static int assabet_get_mctrl(struct uart_port *port)
+static u_int assabet_get_mctrl(struct uart_port *port)
{
u_int ret = 0;
u_int bsr = ASSABET_BSR;
@@ -312,11 +365,7 @@ static void __init assabet_map_io(void)
PWER = PWER_GPIO0;
PGSR = 0;
PCFR = 0;
-
- /*
- * Clear all possible wakeup reasons.
- */
- RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
+ PSDR = 0;
}
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index 2015f5b94..73868b2eb 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -16,20 +16,22 @@
#include "generic.h"
-static void __init cerf_init_irq (void)
+static void __init cerf_init_irq(void)
{
- sa1100_init_irq();
+ sa1100_init_irq();
- /* Need to register these as rising edge interrupts
- * For standard 16550 serial driver support
- * Basically - I copied it from pfs168.c :)
- */
+ /* Need to register these as rising edge interrupts
+ * For standard 16550 serial driver support
+ * Basically - I copied it from pfs168.c :)
+ */
#ifdef CONFIG_SA1100_CERF_CPLD
- set_GPIO_IRQ_edge(GPIO_GPIO(3), GPIO_RISING_EDGE); /* PDA Full serial port */
- set_GPIO_IRQ_edge(GPIO_GPIO(2), GPIO_RISING_EDGE); /* PDA Bluetooth */
- GPDR &= ~(GPIO_GPIO(3)); /* Set the direction of serial port GPIO pin to in */
- GPDR &= ~(GPIO_GPIO(2)); /* Set the direction of bluetooth GPIO pin to in */
+ /* PDA Full serial port */
+ set_GPIO_IRQ_edge(GPIO_GPIO3, GPIO_RISING_EDGE);
+ /* PDA Bluetooth */
+ set_GPIO_IRQ_edge(GPIO_GPIO2, GPIO_RISING_EDGE);
#endif /* CONFIG_SA1100_CERF_CPLD */
+
+ set_GPIO_IRQ_edge(GPIO_UCB1200_IRQ, GPIO_RISING_EDGE);
}
static void __init
@@ -37,22 +39,20 @@ fixup_cerf(struct machine_desc *desc, struct param_struct *params,
char **cmdline, struct meminfo *mi)
{
#if defined(CONFIG_SA1100_CERF_64MB)
- // 64MB RAM
- SET_BANK( 0, 0xc0000000, 64*1024*1024 );
- mi->nr_banks = 1;
-#elif defined(CONFIG_SA1100_CERF_32MB) // 32MB RAM
+ SET_BANK( 0, 0xc0000000, 64*1024*1024 );
+ mi->nr_banks = 1;
+#elif defined(CONFIG_SA1100_CERF_32MB)
SET_BANK( 0, 0xc0000000, 32*1024*1024 );
mi->nr_banks = 1;
-#elif defined(CONFIG_SA1100_CERF_16MB) // 16Meg Ram.
+#elif defined(CONFIG_SA1100_CERF_16MB)
SET_BANK( 0, 0xc0000000, 8*1024*1024 );
SET_BANK( 1, 0xc8000000, 8*1024*1024 );
mi->nr_banks = 2;
#elif defined(CONFIG_SA1100_CERF_8MB)
- // 8Meg Ram.
- SET_BANK( 0, 0xc0000000, 8*1024*1024 );
- mi->nr_banks = 1;
+ SET_BANK( 0, 0xc0000000, 8*1024*1024 );
+ mi->nr_banks = 1;
#else
- #error "Undefined memory size for Cerfboard."
+#error "Undefined memory size for Cerfboard."
#endif
// ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
@@ -62,8 +62,7 @@ fixup_cerf(struct machine_desc *desc, struct param_struct *params,
}
static struct map_desc cerf_io_desc[] __initdata = {
- /* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+ /* virtual physical length domain r w c b */
{ 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Crystal Ethernet Chip */
#ifdef CONFIG_SA1100_CERF_CPLD
{ 0xf1000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* CPLD Chip */
@@ -78,13 +77,19 @@ static void __init cerf_map_io(void)
sa1100_map_io();
iotable_init(cerf_io_desc);
- sa1100_register_uart(0, 3);
+ sa1100_register_uart(0, 3);
#ifdef CONFIG_SA1100_CERF_IRDA_ENABLED
sa1100_register_uart(1, 1);
#else
sa1100_register_uart(1, 2);
sa1100_register_uart(2, 1);
#endif
+
+ /* set some GPDR bits here while it's safe */
+ GPDR |= GPIO_CF_RESET;
+#ifdef CONFIG_SA1100_CERF_CPLD
+ GPDR |= GPIO_PWR_SHUTDOWN;
+#endif
}
MACHINE_START(CERF, "Intrinsyc's Cerf Family of Products")
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index 8acce705e..a0fece054 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -90,7 +90,8 @@
#include <asm/hardware.h>
-
+extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
+extern unsigned int sa11x0_validatespeed(unsigned int khz);
typedef struct {
@@ -219,14 +220,22 @@ static struct notifier_block sa1100_dram_block = {
};
-
+static void sa1100_setspeed(unsigned int khz)
+{
+ PPCR = sa11x0_freq_to_ppcr(khz);
+}
static int __init sa1100_dram_init(void)
{
- return cpufreq_register_notifier(&sa1100_dram_block);
-}
+ int ret = -ENODEV;
+ if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
+ ret = cpufreq_register_notifier(&sa1100_dram_block);
+ cpufreq_setfunctions(sa11x0_validatespeed, sa1100_setspeed);
+ }
+ return ret;
+}
__initcall(sa1100_dram_init);
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 56d9c0ad2..ed8015502 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001 Russell King
*
- * $Id: cpu-sa1110.c,v 1.5 2001/09/10 13:25:58 rmk Exp $
+ * $Id: cpu-sa1110.c,v 1.6 2001/10/22 11:53:47 rmk Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -29,14 +29,8 @@
#undef DEBUG
-extern u_int processor_id;
-
-#define CPU_REVISION (processor_id & 15)
-#define CPU_SA1110_A0 (0)
-#define CPU_SA1110_B0 (4)
-#define CPU_SA1110_B1 (5)
-#define CPU_SA1110_B2 (6)
-#define CPU_SA1110_B4 (8)
+extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
+extern unsigned int sa11x0_validatespeed(unsigned int khz);
struct sdram_params {
u_char rows; /* bits */
@@ -48,6 +42,12 @@ struct sdram_params {
u_short refresh; /* refresh time for array (us) */
};
+struct sdram_info {
+ u_int mdcnfg;
+ u_int mdrefr;
+ u_int mdcas[3];
+};
+
static struct sdram_params tc59sm716_cl2_params __initdata = {
rows: 12,
tck: 10,
@@ -68,6 +68,16 @@ static struct sdram_params tc59sm716_cl3_params __initdata = {
cas_latency: 3,
};
+static struct sdram_params samsung_k4s641632d_tc75 __initdata = {
+ rows: 14,
+ tck: 9,
+ trcd: 27,
+ trp: 20,
+ twr: 9,
+ refresh: 64000,
+ cas_latency: 3,
+};
+
static struct sdram_params sdram_params;
/*
@@ -95,10 +105,11 @@ static inline void set_mdcas(u_int *mdcas, int delayed, u_int rcd)
mdcas[1] = mdcas[2] = 0x55555555 << (shift & 1);
}
-static void sdram_update_timing(u_int cpu_khz, struct sdram_params *sdram)
+static void
+sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz,
+ struct sdram_params *sdram)
{
- u_int mdcnfg, mdrefr, mdcas[3], mem_khz, sd_khz, trp, twr;
- unsigned long flags;
+ u_int mem_khz, sd_khz, trp, twr;
mem_khz = cpu_khz / 2;
sd_khz = mem_khz;
@@ -114,7 +125,7 @@ static void sdram_update_timing(u_int cpu_khz, struct sdram_params *sdram)
(CPU_REVISION < CPU_SA1110_B2 && sd_khz < 62000))
sd_khz /= 2;
- mdcnfg = MDCNFG & 0x007f007f;
+ sd->mdcnfg = MDCNFG & 0x007f007f;
twr = ns_to_cycles(sdram->twr, mem_khz);
@@ -123,53 +134,26 @@ static void sdram_update_timing(u_int cpu_khz, struct sdram_params *sdram)
if (trp < 1)
trp = 1;
- mdcnfg |= trp << 8;
- mdcnfg |= trp << 24;
- mdcnfg |= sdram->cas_latency << 12;
- mdcnfg |= sdram->cas_latency << 28;
- mdcnfg |= twr << 14;
- mdcnfg |= twr << 30;
+ sd->mdcnfg |= trp << 8;
+ sd->mdcnfg |= trp << 24;
+ sd->mdcnfg |= sdram->cas_latency << 12;
+ sd->mdcnfg |= sdram->cas_latency << 28;
+ sd->mdcnfg |= twr << 14;
+ sd->mdcnfg |= twr << 30;
- mdrefr = MDREFR & 0xffbffff0;
- mdrefr |= 7;
+ sd->mdrefr = MDREFR & 0xffbffff0;
+ sd->mdrefr |= 7;
if (sd_khz != mem_khz)
- mdrefr |= MDREFR_K1DB2;
+ sd->mdrefr |= MDREFR_K1DB2;
/* initial number of '1's in MDCAS + 1 */
- set_mdcas(mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
+ set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
#ifdef DEBUG
- mdelay(250);
printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
- mdcnfg, mdrefr, mdcas[0], mdcas[1], mdcas[2]);
+ sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]);
#endif
-
- /*
- * Reprogram the DRAM timings with interrupts disabled, and
- * ensure that we are doing this within a complete cache line.
- * This means that we won't access SDRAM for the duration of
- * the programming.
- */
- local_irq_save(flags);
- asm("mcr p15, 0, %0, c10, c4" : : "r" (0));
- udelay(10);
- __asm__("
- b 1f
- .align 5
-1: str %3, [%1, #28] @ MDREFR
- str %4, [%1, #4] @ MDCAS0
- str %5, [%1, #8] @ MDCAS1
- str %6, [%1, #12] @ MDCAS2
- str %2, [%1, #0] @ MDCNFG
- ldr %0, [%1, #0]
- nop
- nop"
- : "=&r" (mdcnfg)
- : "r" (io_p2v(_MDCNFG)),
- "0" (mdcnfg), "r" (mdrefr),
- "r" (mdcas[0]), "r" (mdcas[1]), "r" (mdcas[2]));
- local_irq_restore(flags);
}
/*
@@ -203,65 +187,93 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
sdram_set_refresh(dri);
}
-static int
-sdram_notifier(struct notifier_block *nb, unsigned long val, void *data)
+/*
+ * Ok, set the CPU frequency. Since we've done the validation
+ * above, we can match for an exact frequency. If we don't find
+ * an exact match, we will to set the lowest frequency to be safe.
+ */
+static void sa1110_setspeed(unsigned int khz)
{
- struct cpufreq_info *ci = data;
struct sdram_params *sdram = &sdram_params;
+ struct sdram_info sd;
+ unsigned long flags;
+ unsigned int ppcr, unused;
- /* were we initialised? */
- if (sdram->cas_latency == 0) {
- struct cpufreq_minmax *m = data;
- m->min_freq = m->max_freq = m->cur_freq;
- return 0;
- }
+ ppcr = sa11x0_freq_to_ppcr(khz);
+ sdram_calculate_timing(&sd, khz, sdram);
- switch (val) {
- case CPUFREQ_MINMAX:
- /*
- * until we work out why the assabet
- * crashes below 147.5MHz...
- */
- cpufreq_updateminmax(data, 147500, -1);
- break;
-
- case CPUFREQ_PRECHANGE:
- /*
- * The clock could be going away for some time.
- * Set the SDRAMs to refresh rapidly (every 64
- * memory clock cycles). To get through the
- * whole array, we need to wait 262144 mclk cycles.
- * We wait 20ms to be safe.
- */
- sdram_set_refresh(2);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(20 * HZ / 1000);
-
- if (ci->old_freq < ci->new_freq)
- sdram_update_timing(ci->new_freq, sdram);
- break;
-
- case CPUFREQ_POSTCHANGE:
- if (ci->old_freq > ci->new_freq)
- sdram_update_timing(ci->new_freq, sdram);
- sdram_update_refresh(ci->new_freq, sdram);
- break;
+#if 0
+ /*
+ * These values are wrong according to the SA1110 documentation
+ * and errata, but they seem to work. Need to get a storage
+ * scope on to the SDRAM signals to work out why.
+ */
+ if (khz < 147500) {
+ sd.mdrefr |= MDREFR_K1DB2;
+ sd.mdcas[0] = 0xaaaaaa7f;
+ } else {
+ sd.mdrefr &= ~MDREFR_K1DB2;
+ sd.mdcas[0] = 0xaaaaaa9f;
}
- return 0;
-}
+ sd.mdcas[1] = 0xaaaaaaaa;
+ sd.mdcas[2] = 0xaaaaaaaa;
+#endif
+ /*
+ * The clock could be going away for some time. Set the SDRAMs
+ * to refresh rapidly (every 64 memory clock cycles). To get
+ * through the whole array, we need to wait 262144 mclk cycles.
+ * We wait 20ms to be safe.
+ */
+ sdram_set_refresh(2);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(20 * HZ / 1000);
-static struct notifier_block sa1110_clkchg_block = {
- notifier_call: sdram_notifier,
-};
+ /*
+ * Reprogram the DRAM timings with interrupts disabled, and
+ * ensure that we are doing this within a complete cache line.
+ * This means that we won't access SDRAM for the duration of
+ * the programming.
+ */
+ local_irq_save(flags);
+ asm("mcr p15, 0, %0, c10, c4" : : "r" (0));
+ udelay(10);
+ __asm__ __volatile__("
+ b 2f
+ .align 5
+1: str %3, [%1, #0] @ MDCNFG
+ str %4, [%1, #28] @ MDREFR
+ str %5, [%1, #4] @ MDCAS0
+ str %6, [%1, #8] @ MDCAS1
+ str %7, [%1, #12] @ MDCAS2
+ str %8, [%2, #0] @ PPCR
+ ldr %0, [%1, #0]
+ b 3f
+2: b 1b
+3: nop
+ nop"
+ : "=&r" (unused)
+ : "r" (&MDCNFG), "r" (&PPCR), "0" (sd.mdcnfg),
+ "r" (sd.mdrefr), "r" (sd.mdcas[0]),
+ "r" (sd.mdcas[1]), "r" (sd.mdcas[2]), "r" (ppcr));
+ local_irq_restore(flags);
-static int __init sa1110_sdram_init(void)
+ /*
+ * Now, return the SDRAM refresh back to normal.
+ */
+ sdram_update_refresh(khz, sdram);
+}
+
+static int __init sa1110_clk_init(void)
{
struct sdram_params *sdram = NULL;
- unsigned int cur_freq = cpufreq_get(smp_processor_id());
if (machine_is_assabet())
sdram = &tc59sm716_cl3_params;
+ if (machine_is_pt_system3())
+ sdram = &samsung_k4s641632d_tc75;
+
+
if (sdram) {
printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
" twr: %d refresh: %d cas_latency: %d\n",
@@ -270,11 +282,11 @@ static int __init sa1110_sdram_init(void)
memcpy(&sdram_params, sdram, sizeof(sdram_params));
- sdram_update_timing(cur_freq, &sdram_params);
- sdram_update_refresh(cur_freq, &sdram_params);
+ sa1110_setspeed(cpufreq_get(0));
+ cpufreq_setfunctions(sa11x0_validatespeed, sa1110_setspeed);
}
- return cpufreq_register_notifier(&sa1110_clkchg_block);
+ return 0;
}
-__initcall(sa1110_sdram_init);
+__initcall(sa1110_clk_init);
diff --git a/arch/arm/mach-sa1100/dma-sa1100.c b/arch/arm/mach-sa1100/dma-sa1100.c
deleted file mode 100644
index 2b7cf98e0..000000000
--- a/arch/arm/mach-sa1100/dma-sa1100.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * arch/arm/kernel/dma-sa1100.c
- *
- * Support functions for the SA11x0 internal DMA channels.
- * (see also Documentation/arm/SA1100/DMA)
- *
- * Copyright (C) 2000 Nicolas Pitre
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/mach/dma.h>
-
-
-#undef DEBUG
-#ifdef DEBUG
-#define DPRINTK( s, arg... ) printk( "dma<%s>: " s, dma->device_id , ##arg )
-#else
-#define DPRINTK( x... )
-#endif
-
-
-/*
- * DMA control register structure
- */
-typedef struct {
- volatile u_long DDAR;
- volatile u_long SetDCSR;
- volatile u_long ClrDCSR;
- volatile u_long RdDCSR;
- volatile dma_addr_t DBSA;
- volatile u_long DBTA;
- volatile dma_addr_t DBSB;
- volatile u_long DBTB;
-} dma_regs_t;
-
-#include "dma.h"
-
-sa1100_dma_t dma_chan[MAX_SA1100_DMA_CHANNELS];
-
-/*
- * Maximum physical DMA buffer size
- */
-#define MAX_DMA_SIZE 0x1fff
-#define MAX_DMA_ORDER 12
-
-
-/*
- * DMA processing...
- */
-
-static inline int start_sa1100_dma(sa1100_dma_t * dma, dma_addr_t dma_ptr, int size)
-{
- dma_regs_t *regs = dma->regs;
- int status;
-
- status = regs->RdDCSR;
-
- /* If both DMA buffers are started, there's nothing else we can do. */
- if ((status & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB)) {
- DPRINTK("start: st %#x busy\n", status);
- return -EBUSY;
- }
-
- if (((status & DCSR_BIU) && (status & DCSR_STRTB)) ||
- (!(status & DCSR_BIU) && !(status & DCSR_STRTA))) {
- if (status & DCSR_DONEA) {
- /* give a chance for the interrupt to be processed */
- goto irq_pending;
- }
- regs->DBSA = dma_ptr;
- regs->DBTA = size;
- regs->SetDCSR = DCSR_STRTA | DCSR_IE | DCSR_RUN;
- DPRINTK("start a=%#x s=%d on A\n", dma_ptr, size);
- } else {
- if (status & DCSR_DONEB) {
- /* give a chance for the interrupt to be processed */
- goto irq_pending;
- }
- regs->DBSB = dma_ptr;
- regs->DBTB = size;
- regs->SetDCSR = DCSR_STRTB | DCSR_IE | DCSR_RUN;
- DPRINTK("start a=%#x s=%d on B\n", dma_ptr, size);
- }
-
- return 0;
-
-irq_pending:
- return -EAGAIN;
-}
-
-
-static int start_dma(sa1100_dma_t *dma, dma_addr_t dma_ptr, int size)
-{
- if (channel_is_sa1111_sac(dma - dma_chan))
- return start_sa1111_sac_dma(dma, dma_ptr, size);
- return start_sa1100_dma(dma, dma_ptr, size);
-}
-
-
-/* This must be called with IRQ disabled */
-static void process_dma(sa1100_dma_t * dma)
-{
- dma_buf_t *buf;
- int chunksize;
-
- for (;;) {
- buf = dma->tail;
-
- if (!buf || dma->stopped) {
- /* no more data available */
- DPRINTK("process: no more buf (dma %s)\n",
- dma->curr ? "active" : "inactive");
- /*
- * Some devices may require DMA still sending data
- * at any time for clock reference, etc.
- * Note: if there is still a data buffer being
- * processed then the ref count is negative. This
- * allows for the DMA termination to be accounted in
- * the proper order.
- */
- if (dma->spin_size && dma->spin_ref >= 0) {
- chunksize = dma->spin_size;
- if (chunksize > MAX_DMA_SIZE)
- chunksize = (1 << MAX_DMA_ORDER);
- while (start_dma(dma, dma->spin_addr, chunksize) == 0)
- dma->spin_ref++;
- if (dma->curr != NULL)
- dma->spin_ref = -dma->spin_ref;
- }
- break;
- }
-
- /*
- * Let's try to start DMA on the current buffer.
- * If DMA is busy then we break here.
- */
- chunksize = buf->size;
- if (chunksize > MAX_DMA_SIZE)
- chunksize = (1 << MAX_DMA_ORDER);
- DPRINTK("process: b=%#x s=%d\n", (int) buf->id, buf->size);
- if (start_dma(dma, buf->dma_ptr, chunksize) != 0)
- break;
- if (!dma->curr)
- dma->curr = buf;
- buf->ref++;
- buf->dma_ptr += chunksize;
- buf->size -= chunksize;
- if (buf->size == 0) {
- /* current buffer is done: move tail to the next one */
- dma->tail = buf->next;
- DPRINTK("process: next b=%#x\n", (int) dma->tail);
- }
- }
-}
-
-
-/* This must be called with IRQ disabled */
-void sa1100_dma_done (sa1100_dma_t *dma)
-{
- dma_buf_t *buf = dma->curr;
-
- if (dma->spin_ref > 0) {
- dma->spin_ref--;
- } else if (buf) {
- buf->ref--;
- if (buf->ref == 0 && buf->size == 0) {
- /*
- * Current buffer is done.
- * Move current reference to the next one and send
- * the processed buffer to the callback function,
- * then discard it.
- */
- DPRINTK("IRQ: buf done\n");
- dma->curr = buf->next;
- if (dma->curr == NULL)
- dma->spin_ref = -dma->spin_ref;
- if (dma->head == buf)
- dma->head = NULL;
- if (dma->callback) {
- int size = buf->dma_ptr - buf->dma_start;
- dma->callback(buf->id, size);
- }
- kfree(buf);
- }
- }
-
- process_dma(dma);
-}
-
-
-static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
- sa1100_dma_t *dma = (sa1100_dma_t *) dev_id;
- int status = dma->regs->RdDCSR;
-
- DPRINTK("IRQ: b=%#x st=%#x\n", (int) dma->curr->id, status);
-
- if (status & (DCSR_ERROR)) {
- printk(KERN_ERR "DMA on \"%s\" caused an error\n", dma->device_id);
- dma->regs->ClrDCSR = DCSR_ERROR;
- }
-
- dma->regs->ClrDCSR = status & (DCSR_DONEA | DCSR_DONEB);
- if (status & DCSR_DONEA)
- sa1100_dma_done (dma);
- if (status & DCSR_DONEB)
- sa1100_dma_done (dma);
-}
-
-
-/*
- * DMA interface functions
- */
-
-static spinlock_t dma_list_lock;
-
-int sa1100_request_dma (dmach_t * channel, const char *device_id,
- dma_device_t device)
-{
- sa1100_dma_t *dma = NULL;
- dma_regs_t *regs;
- int i, err;
-
- *channel = -1; /* to be sure we catch the freeing of a misregistered channel */
-
- err = 0;
- spin_lock(&dma_list_lock);
- for (i = 0; i < SA1100_DMA_CHANNELS; i++) {
- if (dma_chan[i].in_use) {
- if (dma_chan[i].device == device) {
- err = -EBUSY;
- break;
- }
- } else if (!dma) {
- dma = &dma_chan[i];
- }
- }
- if (!err) {
- if (dma)
- dma->in_use = 1;
- else
- err = -ENOSR;
- }
- spin_unlock(&dma_list_lock);
- if (err)
- return err;
-
- err = request_irq(dma->irq, dma_irq_handler, SA_INTERRUPT,
- device_id, (void *) dma);
- if (err) {
- printk(KERN_ERR
- "%s: unable to request IRQ %d for DMA channel\n",
- device_id, dma->irq);
- return err;
- }
-
- *channel = dma - dma_chan;
- dma->device_id = device_id;
- dma->device = device;
- dma->callback = NULL;
- dma->spin_size = 0;
-
- regs = dma->regs;
- regs->ClrDCSR =
- (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
- DCSR_IE | DCSR_ERROR | DCSR_RUN);
- regs->DDAR = device;
- DPRINTK("requested\n");
- return 0;
-}
-
-
-int sa1100_dma_set_callback(dmach_t channel, dma_callback_t cb)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
-
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
- return -EINVAL;
-
- dma->callback = cb;
- DPRINTK("cb = %p\n", cb);
- return 0;
-}
-
-
-int sa1100_dma_set_spin(dmach_t channel, dma_addr_t addr, int size)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- int flags;
-
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
- return -EINVAL;
-
- DPRINTK("set spin %d at %#x\n", size, addr);
- local_irq_save(flags);
- dma->spin_addr = addr;
- dma->spin_size = size;
- if (size)
- process_dma(dma);
- local_irq_restore(flags);
- return 0;
-}
-
-
-int sa1100_dma_queue_buffer(dmach_t channel, void *buf_id,
- dma_addr_t data, int size)
-{
- sa1100_dma_t *dma;
- dma_buf_t *buf;
- int flags;
-
- dma = &dma_chan[channel];
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
- return -EINVAL;
-
- buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
- if (!buf)
- return -ENOMEM;
-
- buf->next = NULL;
- buf->ref = 0;
- buf->dma_ptr = buf->dma_start = data;
- buf->size = size;
- buf->id = buf_id;
- DPRINTK("queueing b=%#x a=%#x s=%d\n", (int) buf_id, data, size);
-
- local_irq_save(flags);
- if (dma->head)
- dma->head->next = buf;
- dma->head = buf;
- if (!dma->tail)
- dma->tail = buf;
- process_dma(dma);
- local_irq_restore(flags);
-
- return 0;
-}
-
-
-int sa1100_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- dma_regs_t *regs;
- int flags, ret;
-
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
- return -EINVAL;
-
- if (channel_is_sa1111_sac(channel))
- return sa1111_dma_get_current(channel, buf_id, addr);
-
- regs = dma->regs;
- local_irq_save(flags);
- if (dma->curr && dma->spin_ref <= 0) {
- dma_buf_t *buf = dma->curr;
- int status, using_bufa;
-
- status = regs->RdDCSR;
- /*
- * If we got here, that's because there is, or recently was, a
- * buffer being processed. We must determine whether buffer
- * A or B is active. Two possibilities: either we are
- * in the middle of a buffer, or the DMA controller just
- * switched to the next toggle but the interrupt hasn't been
- * serviced yet. The former case is straight forward. In
- * the later case, we'll do like if DMA is just at the end
- * of the previous toggle since all registers haven't been
- * reset yet. This goes around the edge case and since we're
- * always a little behind anyways it shouldn't make a big
- * difference. If DMA has been stopped prior calling this
- * then the position is always exact.
- */
- using_bufa = ((!(status & DCSR_BIU) && (status & DCSR_STRTA)) ||
- ( (status & DCSR_BIU) && !(status & DCSR_STRTB)));
- if (buf_id)
- *buf_id = buf->id;
- *addr = (using_bufa) ? regs->DBSA : regs->DBSB;
- /*
- * Clamp funky pointers sometimes returned by the hardware
- * on completed DMA transfers
- */
- if (*addr < buf->dma_start ||
- *addr > buf->dma_ptr)
- *addr = buf->dma_ptr;
- DPRINTK("curr_pos: b=%#x a=%#x\n", (int)dma->curr->id, *addr);
- ret = 0;
- } else if (dma->tail && dma->stopped) {
- dma_buf_t *buf = dma->tail;
- if (buf_id)
- *buf_id = buf->id;
- *addr = buf->dma_ptr;
- ret = 0;
- } else {
- if (buf_id)
- *buf_id = NULL;
- *addr = 0;
- ret = -ENXIO;
- }
- local_irq_restore(flags);
- return ret;
-}
-
-
-int sa1100_dma_stop(dmach_t channel)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- int flags;
-
- if (channel_is_sa1111_sac(channel))
- return sa1111_dma_stop(channel);
-
- if (dma->stopped)
- return 0;
- local_irq_save(flags);
- dma->stopped = 1;
- /*
- * Stop DMA and tweak state variables so everything could restart
- * from there when resume/wakeup occurs.
- */
- dma->regs->ClrDCSR = DCSR_RUN | DCSR_IE;
- if (dma->curr) {
- dma_buf_t *buf = dma->curr;
- if (dma->spin_ref <= 0) {
- dma_addr_t curpos;
- sa1100_dma_get_current(channel, NULL, &curpos);
- buf->size += buf->dma_ptr - curpos;
- buf->dma_ptr = curpos;
- }
- buf->ref = 0;
- dma->tail = buf;
- dma->curr = NULL;
- }
- dma->spin_ref = 0;
- dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB|DCSR_DONEA|DCSR_DONEB;
- process_dma(dma);
- local_irq_restore(flags);
- return 0;
-}
-
-
-int sa1100_dma_resume(dmach_t channel)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
-
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
- return -EINVAL;
-
- if (channel_is_sa1111_sac(channel))
- return sa1111_dma_resume(channel);
-
- if (dma->stopped) {
- int flags;
- save_flags_cli(flags);
- dma->stopped = 0;
- dma->spin_ref = 0;
- process_dma(dma);
- restore_flags(flags);
- }
- return 0;
-}
-
-
-int sa1100_dma_flush_all(dmach_t channel)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- dma_buf_t *buf, *next_buf;
- int flags;
-
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
- return -EINVAL;
-
- local_irq_save(flags);
- if (channel_is_sa1111_sac(channel))
- sa1111_reset_sac_dma(channel);
- else
- dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB|DCSR_DONEA|DCSR_DONEB|DCSR_RUN|DCSR_IE;
- buf = dma->curr;
- if (!buf)
- buf = dma->tail;
- dma->head = dma->tail = dma->curr = NULL;
- dma->stopped = 0;
- dma->spin_ref = 0;
- process_dma(dma);
- local_irq_restore(flags);
- while (buf) {
- next_buf = buf->next;
- kfree(buf);
- buf = next_buf;
- }
- DPRINTK("flushed\n");
- return 0;
-}
-
-
-void sa1100_free_dma(dmach_t channel)
-{
- sa1100_dma_t *dma;
-
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS)
- return;
-
- dma = &dma_chan[channel];
- if (!dma->in_use) {
- printk(KERN_ERR "Trying to free free DMA%d\n", channel);
- return;
- }
-
- sa1100_dma_set_spin(channel, 0, 0);
- sa1100_dma_flush_all(channel);
-
- if (channel_is_sa1111_sac(channel)) {
- sa1111_cleanup_sac_dma(channel);
- } else {
- free_irq(IRQ_DMA0 + channel, (void *) dma);
- }
- dma->in_use = 0;
-
- DPRINTK("freed\n");
-}
-
-
-EXPORT_SYMBOL(sa1100_request_dma);
-EXPORT_SYMBOL(sa1100_dma_set_callback);
-EXPORT_SYMBOL(sa1100_dma_set_spin);
-EXPORT_SYMBOL(sa1100_dma_queue_buffer);
-EXPORT_SYMBOL(sa1100_dma_get_current);
-EXPORT_SYMBOL(sa1100_dma_stop);
-EXPORT_SYMBOL(sa1100_dma_resume);
-EXPORT_SYMBOL(sa1100_dma_flush_all);
-EXPORT_SYMBOL(sa1100_free_dma);
-
-
-#ifdef CONFIG_PM
-/* Drivers should call this from their PM callback function */
-
-int sa1100_dma_sleep(dmach_t channel)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- int orig_state;
-
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
- return -EINVAL;
-
- if (channel_is_sa1111_sac(channel)) {
- /* We'll cheat a little until someone actually
- * write the real thing.
- */
- sa1111_reset_sac_dma(channel);
- return 0;
- }
-
- orig_state = dma->stopped;
- sa1100_dma_stop(channel);
- dma->regs->ClrDCSR = DCSR_RUN | DCSR_IE | DCSR_STRTA | DCSR_STRTB;
- dma->stopped = orig_state;
- dma->spin_ref = 0;
- return 0;
-}
-
-int sa1100_dma_wakeup(dmach_t channel)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- dma_regs_t *regs;
- int flags;
-
- if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
- return -EINVAL;
-
- if (channel_is_sa1111_sac(channel)) {
- /* We'll cheat a little until someone actually
- * write the real thing.
- */
- return 0;
- }
-
- regs = dma->regs;
- regs->ClrDCSR =
- (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
- DCSR_IE | DCSR_ERROR | DCSR_RUN);
- regs->DDAR = dma->device;
- local_irq_save(flags);
- process_dma(dma);
- local_irq_restore(flags);
- return 0;
-}
-
-EXPORT_SYMBOL(sa1100_dma_sleep);
-EXPORT_SYMBOL(sa1100_dma_wakeup);
-
-#endif
-
-
-static int __init sa1100_init_dma(void)
-{
- int channel;
- for (channel = 0; channel < SA1100_DMA_CHANNELS; channel++) {
- dma_chan[channel].regs =
- (dma_regs_t *) &DDAR(channel);
- dma_chan[channel].irq = IRQ_DMA0 + channel;
- }
- return 0;
-}
-
-__initcall(sa1100_init_dma);
diff --git a/arch/arm/mach-sa1100/dma-sa1111.c b/arch/arm/mach-sa1100/dma-sa1111.c
deleted file mode 100644
index 1f086fa20..000000000
--- a/arch/arm/mach-sa1100/dma-sa1111.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/dma-sa1111.c
- *
- * Copyright (C) 2000 John Dorsey
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 4 September 2000 - created.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-// #define DEBUG
-#ifdef DEBUG
-#define DPRINTK( s, arg... ) printk( "dma<%s>: " s, dma->device_id , ##arg )
-#else
-#define DPRINTK( x... )
-#endif
-
-
-/*
- * Control register structure for the SA1111 SAC DMA
- */
-
-typedef struct {
- volatile u_long SAD_CS;
- volatile dma_addr_t SAD_SA;
- volatile u_long SAD_CA;
- volatile dma_addr_t SAD_SB;
- volatile u_long SAD_CB;
-} dma_regs_t;
-
-#include "dma.h"
-
-
-void sa1111_reset_sac_dma(dmach_t channel)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- dma->regs->SAD_CS = 0;
- mdelay(1);
- dma->dma_a = dma->dma_b = 0;
-}
-
-
-int start_sa1111_sac_dma(sa1100_dma_t *dma, dma_addr_t dma_ptr, size_t size)
-{
- dma_regs_t *sac_regs = dma->regs;
-
- DPRINTK(" SAC DMA %cCS %02x at %08x (%d)\n",
- (sac_regs==&SADTCS)?'T':'R', sac_regs->SAD_CS, dma_ptr, size);
-
- /* The minimum transfer length requirement has not yet been
- * verified:
- */
- if( size < SA1111_SAC_DMA_MIN_XFER )
- printk(KERN_WARNING "Warning: SAC xfers below %u bytes may be buggy!"
- " (%u bytes)\n", SA1111_SAC_DMA_MIN_XFER, size);
-
- if( dma->dma_a && dma->dma_b ){
- DPRINTK(" neither engine available! (A %d, B %d)\n",
- dma->dma_a, dma->dma_b);
- return -1;
- }
-
- if( sa1111_check_dma_bug(dma_ptr) )
- printk(KERN_WARNING "Warning: DMA address %08x is buggy!\n",
- dma_ptr);
-
- if( (dma->last_dma || dma->dma_b) && dma->dma_a == 0 ){
- if( sac_regs->SAD_CS & SAD_CS_DBDB ){
- DPRINTK(" awaiting \"done B\" interrupt, not starting\n");
- return -1;
- }
- sac_regs->SAD_SA = SA1111_DMA_ADDR((u_int)dma_ptr);
- sac_regs->SAD_CA = size;
- sac_regs->SAD_CS = SAD_CS_DSTA | SAD_CS_DEN;
- ++dma->dma_a;
- DPRINTK(" with A [%02lx %08lx %04lx]\n", sac_regs->SAD_CS,
- sac_regs->SAD_SA, sac_regs->SAD_CA);
- } else {
- if( sac_regs->SAD_CS & SAD_CS_DBDA ){
- DPRINTK(" awaiting \"done A\" interrupt, not starting\n");
- return -1;
- }
- sac_regs->SAD_SB = SA1111_DMA_ADDR((u_int)dma_ptr);
- sac_regs->SAD_CB = size;
- sac_regs->SAD_CS = SAD_CS_DSTB | SAD_CS_DEN;
- ++dma->dma_b;
- DPRINTK(" with B [%02lx %08lx %04lx]\n", sac_regs->SAD_CS,
- sac_regs->SAD_SB, sac_regs->SAD_CB);
- }
-
- /* Additional delay to avoid DMA engine lockup during record: */
- if( sac_regs == (dma_regs_t*)&SADRCS )
- mdelay(1); /* NP : wouuuh! ugly... */
-
- return 0;
-}
-
-
-static void sa1111_sac_dma_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- sa1100_dma_t *dma = (sa1100_dma_t *) dev_id;
-
- DPRINTK("irq %d, last DMA serviced was %c, CS %02x\n", irq,
- dma->last_dma?'B':'A', dma->regs->SAD_CS);
-
- /* Occasionally, one of the DMA engines (A or B) will
- * lock up. We try to deal with this by quietly kicking
- * the control register for the afflicted transfer
- * direction.
- *
- * Note for the debugging-inclined: we currently aren't
- * properly flushing the DMA engines during channel
- * shutdown. A slight hiccup at the beginning of playback
- * after a channel has been stopped can be heard as
- * evidence of this. Programmatically, this shows up
- * as either a locked engine, or a spurious interrupt. -jd
- */
-
- if(irq==AUDXMTDMADONEA || irq==AUDRCVDMADONEA){
-
- if(dma->last_dma == 0){
- DPRINTK("DMA B has locked up!\n");
- dma->regs->SAD_CS = 0;
- mdelay(1);
- dma->dma_a = dma->dma_b = 0;
- } else {
- if(dma->dma_a == 0)
- DPRINTK("spurious SAC IRQ %d\n", irq);
- else {
- --dma->dma_a;
-
- /* Servicing the SAC DMA engines too quickly
- * after they issue a DONE interrupt causes
- * them to lock up.
- */
- if(irq==AUDRCVDMADONEA || irq==AUDRCVDMADONEB)
- mdelay(1);
- }
- }
-
- dma->regs->SAD_CS = SAD_CS_DBDA | SAD_CS_DEN; /* w1c */
- dma->last_dma = 0;
-
- } else {
-
- if(dma->last_dma == 1){
- DPRINTK("DMA A has locked up!\n");
- dma->regs->SAD_CS = 0;
- mdelay(1);
- dma->dma_a = dma->dma_b = 0;
- } else {
- if(dma->dma_b == 0)
- DPRINTK("spurious SAC IRQ %d\n", irq);
- else {
- --dma->dma_b;
-
- /* See lock-up note above. */
- if(irq==AUDRCVDMADONEA || irq==AUDRCVDMADONEB)
- mdelay(1);
- }
- }
-
- dma->regs->SAD_CS = SAD_CS_DBDB | SAD_CS_DEN; /* w1c */
- dma->last_dma = 1;
-
- }
-
- /* NP: maybe this shouldn't be called in all cases? */
- sa1100_dma_done (dma);
-}
-
-
-int sa1111_sac_request_dma(dmach_t *channel, const char *device_id,
- unsigned int direction)
-{
- sa1100_dma_t *dma = NULL;
- int ch, irq, err;
-
- *channel = -1; /* to be sure we catch the freeing of a misregistered channel */
-
- ch = SA1111_SAC_DMA_BASE + direction;
-
- if (!channel_is_sa1111_sac(ch)) {
- printk(KERN_ERR "%s: invalid SA-1111 SAC DMA channel (%d)\n",
- device_id, ch);
- return -1;
- }
-
- dma = &dma_chan[ch];
-
- if (xchg(&dma->in_use, 1) == 1) {
- printk(KERN_ERR "%s: SA-1111 SAC DMA channel %d in use\n",
- device_id, ch);
- return -EBUSY;
- }
-
- irq = AUDXMTDMADONEA + direction;
- err = request_irq(irq, sa1111_sac_dma_irq, SA_INTERRUPT,
- device_id, (void *) dma);
- if (err) {
- printk(KERN_ERR
- "%s: unable to request IRQ %d for DMA channel %d (A)\n",
- device_id, irq, ch);
- dma->in_use = 0;
- return err;
- }
-
- irq = AUDXMTDMADONEB + direction;
- err = request_irq(irq, sa1111_sac_dma_irq, SA_INTERRUPT,
- device_id, (void *) dma);
- if (err) {
- printk(KERN_ERR
- "%s: unable to request IRQ %d for DMA channel %d (B)\n",
- device_id, irq, ch);
- dma->in_use = 0;
- return err;
- }
-
- *channel = ch;
- dma->device_id = device_id;
- dma->callback = NULL;
- dma->spin_size = 0;
-
- return 0;
-}
-
-
-/* FIXME: need to complete the three following functions */
-
-int sa1111_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- int flags, ret;
-
- local_irq_save(flags);
- if (dma->curr && dma->spin_ref <= 0) {
- dma_buf_t *buf = dma->curr;
- if (buf_id)
- *buf_id = buf->id;
- /* not fully accurate but still... */
- *addr = buf->dma_ptr;
- ret = 0;
- } else {
- if (buf_id)
- *buf_id = NULL;
- *addr = 0;
- ret = -ENXIO;
- }
- local_irq_restore(flags);
- return ret;
-}
-
-int sa1111_dma_stop(dmach_t channel)
-{
- return 0;
-}
-
-int sa1111_dma_resume(dmach_t channel)
-{
- return 0;
-}
-
-
-void sa1111_cleanup_sac_dma(dmach_t channel)
-{
- sa1100_dma_t *dma = &dma_chan[channel];
- free_irq(AUDXMTDMADONEA + (channel - SA1111_SAC_DMA_BASE), (void*) dma);
- free_irq(AUDXMTDMADONEB + (channel - SA1111_SAC_DMA_BASE), (void*) dma);
-}
-
-
-/* According to the "Intel StrongARM SA-1111 Microprocessor Companion
- * Chip Specification Update" (June 2000), erratum #7, there is a
- * significant bug in Serial Audio Controller DMA. If the SAC is
- * accessing a region of memory above 1MB relative to the bank base,
- * it is important that address bit 10 _NOT_ be asserted. Depending
- * on the configuration of the RAM, bit 10 may correspond to one
- * of several different (processor-relative) address bits.
- *
- * This routine only identifies whether or not a given DMA address
- * is susceptible to the bug.
- */
-int sa1111_check_dma_bug(dma_addr_t addr){
- unsigned int physaddr=SA1111_DMA_ADDR((unsigned int)addr);
-
- /* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
- * User's Guide" mentions that jumpers R51 and R52 control the
- * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
- * SDRAM bank 1 on Neponset). The default configuration selects
- * Assabet, so any address in bank 1 is necessarily invalid.
- */
- if((machine_is_assabet() || machine_is_pfs168()) && addr >= 0xc8000000)
- return -1;
-
- /* The bug only applies to buffers located more than one megabyte
- * above the start of the target bank:
- */
- if(physaddr<(1<<20))
- return 0;
-
- switch(FExtr(SBI_SMCR, SMCR_DRAC)){
- case 01: /* 10 row + bank address bits, A<20> must not be set */
- if(physaddr & (1<<20))
- return -1;
- break;
- case 02: /* 11 row + bank address bits, A<23> must not be set */
- if(physaddr & (1<<23))
- return -1;
- break;
- case 03: /* 12 row + bank address bits, A<24> must not be set */
- if(physaddr & (1<<24))
- return -1;
- break;
- case 04: /* 13 row + bank address bits, A<25> must not be set */
- if(physaddr & (1<<25))
- return -1;
- break;
- case 05: /* 14 row + bank address bits, A<20> must not be set */
- if(physaddr & (1<<20))
- return -1;
- break;
- case 06: /* 15 row + bank address bits, A<20> must not be set */
- if(physaddr & (1<<20))
- return -1;
- break;
- default:
- printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%lo\n",
- __FUNCTION__, FExtr(SBI_SMCR, SMCR_DRAC));
- return -1;
- }
-
- return 0;
-}
-
-
-EXPORT_SYMBOL(sa1111_sac_request_dma);
-EXPORT_SYMBOL(sa1111_check_dma_bug);
-
-
-static int __init sa1111_init_sac_dma(void)
-{
- int channel = SA1111_SAC_DMA_BASE;
- dma_chan[channel++].regs = (dma_regs_t *) &SADTCS;
- dma_chan[channel++].regs = (dma_regs_t *) &SADRCS;
- return 0;
-}
-
-__initcall(sa1111_init_sac_dma);
diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c
new file mode 100644
index 000000000..930d1bfa6
--- /dev/null
+++ b/arch/arm/mach-sa1100/dma.c
@@ -0,0 +1,343 @@
+/*
+ * arch/arm/kernel/dma-sa1100.c
+ *
+ * Support functions for the SA11x0 internal DMA channels.
+ *
+ * Copyright (C) 2000, 2001 by Nicolas Pitre
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK( s, arg... ) printk( "dma<%p>: " s, regs , ##arg )
+#else
+#define DPRINTK( x... )
+#endif
+
+
+typedef struct {
+ const char *device_id; /* device name */
+ u_long device; /* this channel device, 0 if unused*/
+ dma_callback_t callback; /* to call when DMA completes */
+ void *data; /* ... with private data ptr */
+} sa1100_dma_t;
+
+static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
+
+static spinlock_t dma_list_lock;
+
+
+static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ dma_regs_t *dma_regs = dev_id;
+ sa1100_dma_t *dma = dma_chan + (((u_int)dma_regs >> 5) & 7);
+ int status = dma_regs->RdDCSR;
+
+ if (status & (DCSR_ERROR)) {
+ printk(KERN_CRIT "DMA on \"%s\" caused an error\n", dma->device_id);
+ dma_regs->ClrDCSR = DCSR_ERROR;
+ }
+
+ dma_regs->ClrDCSR = status & (DCSR_DONEA | DCSR_DONEB);
+ if (dma->callback) {
+ if (status & DCSR_DONEA)
+ dma->callback(dma->data);
+ if (status & DCSR_DONEB)
+ dma->callback(dma->data);
+ }
+}
+
+
+/**
+ * sa1100_request_dma - allocate one of the SA11x0's DMA chanels
+ * @device: The SA11x0 peripheral targeted by this request
+ * @device_id: An ascii name for the claiming device
+ * @callback: Function to be called when the DMA completes
+ * @data: A cookie passed back to the callback function
+ * @dma_regs: Pointer to the location of the allocated channel's identifier
+ *
+ * This function will search for a free DMA channel and returns the
+ * address of the hardware registers for that channel as the channel
+ * identifier. This identifier is written to the location pointed by
+ * @dma_regs. The list of possible values for @device are listed into
+ * linux/include/asm-arm/arch-sa1100/dma.h as a dma_device_t enum.
+ *
+ * Note that reading from a port and writing to the same port are
+ * actually considered as two different streams requiring separate
+ * DMA registrations.
+ *
+ * The @callback function is called from interrupt context when one
+ * of the two possible DMA buffers in flight has terminated. That
+ * function has to be small and efficient while posponing more complex
+ * processing to a lower priority execution context.
+ *
+ * If no channels are available, or if the desired @device is already in
+ * use by another DMA channel, then an error code is returned. This
+ * function must be called before any other DMA calls.
+ **/
+
+int sa1100_request_dma (dma_device_t device, const char *device_id,
+ dma_callback_t callback, void *data,
+ dma_regs_t **dma_regs)
+{
+ sa1100_dma_t *dma = NULL;
+ dma_regs_t *regs;
+ int i, err;
+
+ *dma_regs = NULL;
+
+ err = 0;
+ spin_lock(&dma_list_lock);
+ for (i = 0; i < SA1100_DMA_CHANNELS; i++) {
+ if (dma_chan[i].device == device) {
+ err = -EBUSY;
+ break;
+ } else if (!dma_chan[i].device && !dma) {
+ dma = &dma_chan[i];
+ }
+ }
+ if (!err) {
+ if (dma)
+ dma->device = device;
+ else
+ err = -ENOSR;
+ }
+ spin_unlock(&dma_list_lock);
+ if (err)
+ return err;
+
+ i = dma - dma_chan;
+ regs = (dma_regs_t *)&DDAR(i);
+ err = request_irq(IRQ_DMA0 + i, dma_irq_handler, SA_INTERRUPT,
+ device_id, regs);
+ if (err) {
+ printk(KERN_ERR __FUNCTION__
+ "unable to request IRQ %d for %s\n",
+ IRQ_DMA0 + i, device_id);
+ dma->device = 0;
+ return err;
+ }
+
+ *dma_regs = regs;
+ dma->device_id = device_id;
+ dma->callback = callback;
+ dma->data = data;
+
+ regs->ClrDCSR =
+ (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
+ DCSR_IE | DCSR_ERROR | DCSR_RUN);
+ regs->DDAR = device;
+
+ return 0;
+}
+
+
+/**
+ * sa1100_free_dma - free a SA11x0 DMA channel
+ * @regs: identifier for the channel to free
+ *
+ * This clears all activities on a given DMA channel and releases it
+ * for future requests. The @regs identifier is provided by a
+ * successful call to sa1100_request_dma().
+ **/
+
+void sa1100_free_dma(dma_regs_t *regs)
+{
+ int i;
+
+ for (i = 0; i < SA1100_DMA_CHANNELS; i++)
+ if (regs == (dma_regs_t *)&DDAR(i))
+ break;
+ if (i >= SA1100_DMA_CHANNELS) {
+ printk(KERN_ERR __FUNCTION__ ": bad DMA identifier\n");
+ return;
+ }
+
+ if (!dma_chan[i].device) {
+ printk(KERN_ERR __FUNCTION__ "Trying to free free DMA\n");
+ return;
+ }
+
+ regs->ClrDCSR =
+ (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
+ DCSR_IE | DCSR_ERROR | DCSR_RUN);
+ free_irq(IRQ_DMA0 + i, regs);
+ dma_chan[i].device = 0;
+}
+
+
+/**
+ * sa1100_start_dma - submit a data buffer for DMA
+ * @regs: identifier for the channel to use
+ * @dma_ptr: buffer physical (or bus) start address
+ * @size: buffer size
+ *
+ * This function hands the given data buffer to the hardware for DMA
+ * access. If another buffer is already in flight then this buffer
+ * will be queued so the DMA engine will switch to it automatically
+ * when the previous one is done. The DMA engine is actually toggling
+ * between two buffers so at most 2 successful calls can be made before
+ * one of them terminates and the callback function is called.
+ *
+ * The @regs identifier is provided by a successful call to
+ * sa1100_request_dma().
+ *
+ * The @size must not be larger than %MAX_DMA_SIZE. If a given buffer
+ * is larger than that then it's the caller's responsibility to split
+ * it into smaller chunks and submit them separately. If this is the
+ * case then a @size of %CUT_DMA_SIZE is recommended to avoid ending
+ * up with too small chunks. The callback function can be used to chain
+ * submissions of buffer chunks.
+ *
+ * Error return values:
+ * %-EOVERFLOW: Given buffer size is too big.
+ * %-EBUSY: Both DMA buffers are already in use.
+ * %-EAGAIN: Both buffers were busy but one of them just completed
+ * but the interrupt handler has to execute first.
+ *
+ * This function returs 0 on success.
+ **/
+
+int sa1100_start_dma(dma_regs_t *regs, dma_addr_t dma_ptr, u_int size)
+{
+ long flags;
+ u_long status;
+ int ret;
+
+ if (size > MAX_DMA_SIZE)
+ return -EOVERFLOW;
+
+ local_irq_save(flags);
+ status = regs->RdDCSR;
+
+ /* If both DMA buffers are started, there's nothing else we can do. */
+ if ((status & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB)) {
+ DPRINTK("start: st %#x busy\n", status);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (((status & DCSR_BIU) && (status & DCSR_STRTB)) ||
+ (!(status & DCSR_BIU) && !(status & DCSR_STRTA))) {
+ if (status & DCSR_DONEA) {
+ /* give a chance for the interrupt to be processed */
+ ret = -EAGAIN;
+ goto out;
+ }
+ regs->DBSA = dma_ptr;
+ regs->DBTA = size;
+ regs->SetDCSR = DCSR_STRTA | DCSR_IE | DCSR_RUN;
+ DPRINTK("start a=%#x s=%d on A\n", dma_ptr, size);
+ } else {
+ if (status & DCSR_DONEB) {
+ /* give a chance for the interrupt to be processed */
+ ret = -EAGAIN;
+ goto out;
+ }
+ regs->DBSB = dma_ptr;
+ regs->DBTB = size;
+ regs->SetDCSR = DCSR_STRTB | DCSR_IE | DCSR_RUN;
+ DPRINTK("start a=%#x s=%d on B\n", dma_ptr, size);
+ }
+ ret = 0;
+
+out:
+ local_irq_restore(flags);
+ return ret;
+}
+
+
+/**
+ * sa1100_get_dma_pos - return current DMA position
+ * @regs: identifier for the channel to use
+ *
+ * This function returns the current physical (or bus) address for the
+ * given DMA channel. If the channel is running i.e. not in a stopped
+ * state then the caller must disable interrupts prior calling this
+ * function and process the returned value before re-enabling them to
+ * prevent races with the completion interrupt handler and the callback
+ * function. The validation of the returned value is the caller's
+ * responsibility as well -- the hardware seems to return out of range
+ * values when the DMA engine completes a buffer.
+ *
+ * The @regs identifier is provided by a successful call to
+ * sa1100_request_dma().
+ **/
+
+dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs)
+{
+ int status;
+
+ /*
+ * We must determine whether buffer A or B is active.
+ * Two possibilities: either we are in the middle of
+ * a buffer, or the DMA controller just switched to the
+ * next toggle but the interrupt hasn't been serviced yet.
+ * The former case is straight forward. In the later case,
+ * we'll do like if DMA is just at the end of the previous
+ * toggle since all registers haven't been reset yet.
+ * This goes around the edge case and since we're always
+ * a little behind anyways it shouldn't make a big difference.
+ * If DMA has been stopped prior calling this then the
+ * position is exact.
+ */
+ status = regs->RdDCSR;
+ if ((!(status & DCSR_BIU) && (status & DCSR_STRTA)) ||
+ ( (status & DCSR_BIU) && !(status & DCSR_STRTB)))
+ return regs->DBSA;
+ else
+ return regs->DBSB;
+}
+
+
+/**
+ * sa1100_reset_dma - reset a DMA channel
+ * @regs: identifier for the channel to use
+ *
+ * This function resets and reconfigure the given DMA channel. This is
+ * particularly useful after a sleep/wakeup event.
+ *
+ * The @regs identifier is provided by a successful call to
+ * sa1100_request_dma().
+ **/
+
+void sa1100_reset_dma(dma_regs_t *regs)
+{
+ int i;
+
+ for (i = 0; i < SA1100_DMA_CHANNELS; i++)
+ if (regs == (dma_regs_t *)&DDAR(i))
+ break;
+ if (i >= SA1100_DMA_CHANNELS) {
+ printk(KERN_ERR __FUNCTION__ ": bad DMA identifier\n");
+ return;
+ }
+
+ regs->ClrDCSR =
+ (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
+ DCSR_IE | DCSR_ERROR | DCSR_RUN);
+ regs->DDAR = dma_chan[i].device;
+}
+
+
+EXPORT_SYMBOL(sa1100_request_dma);
+EXPORT_SYMBOL(sa1100_free_dma);
+EXPORT_SYMBOL(sa1100_start_dma);
+EXPORT_SYMBOL(sa1100_get_dma_pos);
+EXPORT_SYMBOL(sa1100_reset_dma);
+
diff --git a/arch/arm/mach-sa1100/dma.h b/arch/arm/mach-sa1100/dma.h
deleted file mode 100644
index 22b08cd84..000000000
--- a/arch/arm/mach-sa1100/dma.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Definitions shared between dma-sa1100.c and dma-sa1111.c
- * (C) 2000 Nicolas Pitre <nico@cam.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/config.h>
-
-/*
- * DMA buffer structure
- */
-
-typedef struct dma_buf_s {
- int size; /* buffer size */
- dma_addr_t dma_start; /* starting DMA address */
- dma_addr_t dma_ptr; /* next DMA pointer to use */
- int ref; /* number of DMA references */
- void *id; /* to identify buffer from outside */
- struct dma_buf_s *next; /* next buffer to process */
-} dma_buf_t;
-
-
-/*
- * DMA channel structure.
- */
-
-typedef struct {
- unsigned int in_use; /* Device is allocated */
- const char *device_id; /* Device name */
- dma_device_t device; /* ... to which this channel is attached */
- dma_buf_t *head; /* where to insert buffers */
- dma_buf_t *tail; /* where to remove buffers */
- dma_buf_t *curr; /* buffer currently DMA'ed */
- int stopped; /* 1 if DMA is stalled */
- dma_regs_t *regs; /* points to appropriate DMA registers */
- int irq; /* IRQ used by the channel */
- dma_callback_t callback; /* ... to call when buffers are done */
- int spin_size; /* > 0 when DMA should spin when no more buffer */
- dma_addr_t spin_addr; /* DMA address to spin onto */
- int spin_ref; /* number of spinning references */
-#ifdef CONFIG_SA1111
- int dma_a, dma_b, last_dma; /* SA-1111 specific */
-#endif
-} sa1100_dma_t;
-
-extern sa1100_dma_t dma_chan[MAX_SA1100_DMA_CHANNELS];
-
-
-int start_sa1111_sac_dma(sa1100_dma_t *dma, dma_addr_t dma_ptr, size_t size);
-int sa1111_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr);
-int sa1111_dma_stop(dmach_t channel);
-int sa1111_dma_resume(dmach_t channel);
-void sa1111_reset_sac_dma(dmach_t channel);
-void sa1111_cleanup_sac_dma(dmach_t channel);
-
-void sa1100_dma_done (sa1100_dma_t *dma);
-
-
-#ifdef CONFIG_SA1111
-#define channel_is_sa1111_sac(ch) \
- ((ch) >= SA1111_SAC_DMA_BASE && \
- (ch) < SA1111_SAC_DMA_BASE + SA1111_SAC_DMA_CHANNELS)
-#else
-#define channel_is_sa1111_sac(ch) (0)
-#endif
-
diff --git a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c
index 7cd574519..fb7d57ea9 100644
--- a/arch/arm/mach-sa1100/flexanet.c
+++ b/arch/arm/mach-sa1100/flexanet.c
@@ -27,22 +27,142 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h>
+#include <linux/serial_core.h>
#include "generic.h"
-unsigned long BCR_value = BCR_POWERUP;
-unsigned long flexanet_GUI_type = 0x0000000F;
+unsigned long flexanet_BCR = FHH_BCR_POWERUP;
-EXPORT_SYMBOL(BCR_value);
-EXPORT_SYMBOL(flexanet_GUI_type);
+EXPORT_SYMBOL(flexanet_BCR);
+
+/* physical addresses */
+#define _RCNR 0x90010004
+#define _GPLR 0x90040000
+#define _Ser4SSCR0 0x80070060
+
+/*
+ * Get the modem-control register of the UARTs
+ *
+ */
+static int flexanet_get_mctrl(struct uart_port *port)
+{
+ int stat = 0;
+ unsigned long bsr;
+
+ /* only DSR and CTS are implemented in UART1 & 3 */
+ if (port->membase == (void *)&Ser1UTCR0)
+ {
+ bsr = FHH_BSR;
+
+ if ((bsr & FHH_BSR_DSR1) != 0)
+ stat |= TIOCM_DSR;
+ if ((bsr & FHH_BSR_CTS1) != 0)
+ stat |= TIOCM_CTS;
+ }
+ else if (port->membase == (void *)&Ser3UTCR0)
+ {
+ bsr = FHH_BSR;
+
+ if ((bsr & FHH_BSR_DSR3) != 0)
+ stat |= TIOCM_DSR;
+ if ((bsr & FHH_BSR_CTS3) != 0)
+ stat |= TIOCM_CTS;
+ }
+
+ return stat;
+}
+
+/*
+ * Set the modem-control register of the UARTs
+ *
+ */
+static void flexanet_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ unsigned long flags;
+
+ /* only the RTS signal is implemented in UART1 & 3 */
+ if (port->membase == (void *)&Ser1UTCR0)
+ {
+ local_irq_save(flags);
+
+ if (mctrl & TIOCM_RTS)
+ flexanet_BCR |= FHH_BCR_RTS1;
+ else
+ flexanet_BCR &= ~FHH_BCR_RTS1;
+
+ FHH_BCR = flexanet_BCR;
+ local_irq_restore(flags);
+ }
+ else if (port->membase == (void *)&Ser3UTCR0)
+ {
+ local_irq_save(flags);
+
+ if (mctrl & TIOCM_RTS)
+ flexanet_BCR |= FHH_BCR_RTS3;
+ else
+ flexanet_BCR &= ~FHH_BCR_RTS3;
+
+ FHH_BCR = flexanet_BCR;
+ local_irq_restore(flags);
+ }
+}
+
+/*
+ * machine-specific serial port functions
+ *
+ * get_mctrl : set state of modem control lines
+ * set_mctrl : set the modem control lines
+ * enable_ms : enable modem-status interrupts
+ * pm : power-management. Turn device on/off.
+ *
+ */
+static struct sa1100_port_fns flexanet_port_fns __initdata =
+{
+ set_mctrl : flexanet_set_mctrl,
+ get_mctrl : flexanet_get_mctrl,
+ enable_ms : NULL,
+ pm : NULL,
+};
+
+
+/*
+ * Initialization and serial port mapping
+ *
+ */
+
+static int flexanet_serial_init(void)
+{
+ /* register low-level functions */
+ sa1100_register_uart_fns(&flexanet_port_fns);
+
+ /* UART port number mapping */
+ sa1100_register_uart(0, 1); /* RS232 */
+ sa1100_register_uart(1, 3); /* Radio */
+
+ /* Select UART function in Serial port 1 */
+ Ser1SDCR0 |= SDCR0_UART;
+
+ return 0;
+}
+
+
+static int __init flexanet_init(void)
+{
+ return 0;
+}
+
+__initcall(flexanet_init);
-static unsigned long probe_gui_board (void);
static void __init
fixup_flexanet(struct machine_desc *desc, struct param_struct *params,
char **cmdline, struct meminfo *mi)
{
+ int status;
+ unsigned long now;
+
+
/* fixed RAM size, by now (64MB) */
SET_BANK( 0, 0xc0000000, 64*1024*1024 );
mi->nr_banks = 1;
@@ -56,8 +176,10 @@ fixup_flexanet(struct machine_desc *desc, struct param_struct *params,
static struct map_desc flexanet_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
{ 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
+ { 0xf1000000, 0x18000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Ethernet controller */
+ { 0xD0000000, 0x40000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Instrument boards */
+ { 0xD8000000, 0x48000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* External peripherals */
LAST_DESC
};
@@ -65,9 +187,27 @@ static void __init flexanet_map_io(void)
{
sa1100_map_io();
iotable_init(flexanet_io_desc);
+ flexanet_serial_init();
- sa1100_register_uart(0, 1);
- Ser1SDCR0 |= SDCR0_UART;
+ /* wakeup source is GPIO-0 only */
+ PWER = PWER_GPIO0;
+
+ /* GPIOs set to zero during sleep */
+ PGSR = 0;
+
+ /*
+ * stop the 3.68 MHz oscillator and float control busses
+ * during sleep, since peripherals are powered off.
+ */
+ PCFR = PCFR_OPDE | PCFR_FP | PCFR_FS;
+
+ /* deassert the GUI reset */
+ FLEXANET_BCR_set(FHH_BCR_GUI_NRST);
+
+ /*
+ * Set IRQ edges
+ */
+ set_GPIO_IRQ_edge(GPIO_GUI_IRQ, GPIO_RISING_EDGE);
}
@@ -78,3 +218,4 @@ MACHINE_START(FLEXANET, "FlexaNet")
MAPIO(flexanet_map_io)
INITIRQ(sa1100_init_irq)
MACHINE_END
+
diff --git a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c
index faa93cba9..3ba93785a 100644
--- a/arch/arm/mach-sa1100/freebird.c
+++ b/arch/arm/mach-sa1100/freebird.c
@@ -21,6 +21,35 @@
unsigned long BCR_value = BCR_DB1110;
EXPORT_SYMBOL(BCR_value);
+static void freebird_backlight_power(int on)
+{
+#error FIXME
+ if (on) {
+ BCR_set(BCR_FREEBIRD_LCD_PWR | BCR_FREEBIRD_LCD_DISP);
+ /* Turn on backlight, Chester */
+ BCR_set(BCR_FREEBIRD_LCD_BACKLIGHT);
+ } else {
+ BCR_clear(BCR_FREEBIRD_LCD_PWR | BCR_FREEBIRD_LCD_DISP
+ /* | BCR_FREEBIRD_LCD_BACKLIGHT */);
+ }
+}
+
+static void freebird_lcd_power(int on)
+{
+}
+
+static int __init freebird_init(void)
+{
+ if (machine_is_freebird()) {
+ sa1100fb_backlight_power = freebird_backlight_power;
+ sa1100fb_lcd_power = freebird_lcd_power;
+
+ set_GPIO_IRQ_edge(GPIO_FREEBIRD_UCB1300, GPIO_RISING_EDGE);
+ }
+ return 0;
+}
+
+__initcall(freebird_init);
static void __init
fixup_freebird(struct machine_desc *desc, struct param_struct *params,
@@ -37,7 +66,6 @@ fixup_freebird(struct machine_desc *desc, struct param_struct *params,
static struct map_desc freebird_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
{ 0xf0000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
{ 0xf2000000, 0x19000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0},
LAST_DESC
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 0df112c1e..a0cf741be 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -53,23 +53,8 @@ static const unsigned short cclk_frequency_100khz[NR_FREQS] = {
2802 /* 280.2 MHz */
};
-/*
- * Return the current CPU clock frequency in units of 100kHz
- */
-unsigned short get_cclk_frequency(void)
-{
- return cclk_frequency_100khz[PPCR & 0xf];
-}
-
-EXPORT_SYMBOL(get_cclk_frequency);
-
#ifdef CONFIG_CPU_FREQ
-
-/*
- * Validate the speed in khz. If we can't generate the precise
- * frequency requested, round it down (to be on the safe side).
- */
-unsigned int sa1100_validatespeed(unsigned int khz)
+unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
{
int i;
@@ -79,35 +64,34 @@ unsigned int sa1100_validatespeed(unsigned int khz)
if (cclk_frequency_100khz[i] <= khz)
break;
- return cclk_frequency_100khz[i] * 100;
+ return i;
}
/*
- * Ok, set the CPU frequency. Since we've done the validation
- * above, we can match for an exact frequency. If we don't find
- * an exact match, we will to set the lowest frequency to be safe.
+ * Validate the speed in khz. If we can't generate the precise
+ * frequency requested, round it down (to be on the safe side).
*/
-void sa1100_setspeed(unsigned int khz)
+unsigned int sa11x0_validatespeed(unsigned int khz)
{
- int i;
-
- khz /= 100;
-
- for (i = NR_FREQS - 1; i > 0; i--)
- if (cclk_frequency_100khz[i] == khz)
- break;
-//printk("setting ppcr to %d\n", i);
- PPCR = i;
+ return cclk_frequency_100khz[sa11x0_freq_to_ppcr(khz)] * 100;
}
-static int __init sa1100_init_clock(void)
+static int __init sa11x0_init_clock(void)
{
- cpufreq_init(get_cclk_frequency() * 100);
- cpufreq_setfunctions(sa1100_validatespeed, sa1100_setspeed);
+ cpufreq_init(cclk_frequency_100khz[PPCR & 0xf] * 100);
return 0;
}
-__initcall(sa1100_init_clock);
+__initcall(sa11x0_init_clock);
+#else
+/*
+ * We still need to provide this so building without cpufreq works.
+ */
+unsigned int cpufreq_get(int cpu)
+{
+ return cclk_frequency_100khz[PPCR & 0xf] * 100;
+}
+EXPORT_SYMBOL(cpufreq_get);
#endif
/*
@@ -130,13 +114,19 @@ static void sa1100_power_off(void)
PMCR = PMCR_SF;
}
-static int __init sa1100_set_poweroff(void)
+static int __init sa1100_init(void)
{
pm_power_off = sa1100_power_off;
return 0;
}
-__initcall(sa1100_set_poweroff);
+__initcall(sa1100_init);
+
+void (*sa1100fb_backlight_power)(int on);
+void (*sa1100fb_lcd_power)(int on);
+
+EXPORT_SYMBOL(sa1100fb_backlight_power);
+EXPORT_SYMBOL(sa1100fb_lcd_power);
/*
@@ -149,7 +139,9 @@ __initcall(sa1100_set_poweroff);
* 0xf0000000-0xf3ffffff: miscellaneous stuff (CPLDs, etc.)
* 0xf4000000-0xf4ffffff: SA-1111
* 0xf5000000-0xf5ffffff: reserved (used by cache flushing area)
- * 0xf6000000-0xffffffff: reserved (internal SA1100 IO defined above)
+ * 0xf6000000-0xfffeffff: reserved (internal SA1100 IO defined above)
+ * 0xffff0000-0xffff0fff: SA1100 exception vectors
+ * 0xffff2000-0xffff2fff: Minicache copy_user_page area
*
* Below 0xe8000000 is reserved for vm allocation.
*
@@ -159,8 +151,6 @@ __initcall(sa1100_set_poweroff);
static struct map_desc standard_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf6000000, 0x20000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA0 IO */
- { 0xf7000000, 0x30000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA1 IO */
{ 0xf8000000, 0x80000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */
{ 0xfa000000, 0x90000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */
{ 0xfc000000, 0xa0000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index 23fecb666..2af306ab0 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -12,3 +12,6 @@ extern void __init sa1100_init_irq(void);
mi->bank[__nr].size = (__size), \
mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
+extern void (*sa1100fb_backlight_power)(int on);
+extern void (*sa1100fb_lcd_power)(int on);
+
diff --git a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c
index 48d4dc0d8..037e950c2 100644
--- a/arch/arm/mach-sa1100/graphicsclient.c
+++ b/arch/arm/mach-sa1100/graphicsclient.c
@@ -113,7 +113,6 @@ static void __init graphicsclient_init_irq(void)
irq_desc[irq].mask = ADS_mask_irq1;
irq_desc[irq].unmask = ADS_unmask_irq1;
}
- GPDR &= ~GPIO_GPIO0;
set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
}
@@ -138,7 +137,6 @@ fixup_graphicsclient(struct machine_desc *desc, struct param_struct *params,
static struct map_desc graphicsclient_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x08000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
{ 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
{ 0xf1000000, 0x18000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CAN */
LAST_DESC
@@ -193,12 +191,8 @@ graphicsclient_uart_open(struct uart_port *port, struct uart_info *info)
if (port->mapbase == _Ser1UTCR0) {
Ser1SDCR0 |= SDCR0_UART;
/* Set RTS Output */
- GPDR |= GPIO_GC_UART0_RTS;
GPSR = GPIO_GC_UART0_RTS;
- /* Set CTS Input */
- GPDR &= ~GPIO_GC_UART0_CTS;
-
gc_uart_ctrl_data[0].cts_prev_state = 0;
gc_uart_ctrl_data[0].info = info;
gc_uart_ctrl_data[0].port = port;
@@ -210,12 +204,8 @@ graphicsclient_uart_open(struct uart_port *port, struct uart_info *info)
} else if (port->mapbase == _Ser2UTCR0) {
Ser2UTCR4 = Ser2HSCR0 = 0;
/* Set RTS Output */
- GPDR |= GPIO_GC_UART1_RTS;
GPSR = GPIO_GC_UART1_RTS;
- /* Set CTS Input */
- GPDR &= ~GPIO_GC_UART1_RTS;
-
gc_uart_ctrl_data[1].cts_prev_state = 0;
gc_uart_ctrl_data[1].info = info;
gc_uart_ctrl_data[1].port = port;
@@ -226,12 +216,8 @@ graphicsclient_uart_open(struct uart_port *port, struct uart_info *info)
&gc_uart_ctrl_data[1]);
} else if (port->mapbase == _Ser3UTCR0) {
/* Set RTS Output */
- GPDR |= GPIO_GC_UART2_RTS;
GPSR = GPIO_GC_UART2_RTS;
- /* Set CTS Input */
- GPDR &= ~GPIO_GC_UART2_RTS;
-
gc_uart_ctrl_data[2].cts_prev_state = 0;
gc_uart_ctrl_data[2].info = info;
gc_uart_ctrl_data[2].port = port;
@@ -258,9 +244,9 @@ graphicsclient_uart_close(struct uart_port *port, struct uart_info *info)
return 0;
}
-static int graphicsclient_get_mctrl(struct uart_port *port)
+static u_int graphicsclient_get_mctrl(struct uart_port *port)
{
- int result = TIOCM_CD | TIOCM_DSR;
+ u_int result = TIOCM_CD | TIOCM_DSR;
if (port->mapbase == _Ser1UTCR0) {
if (!(GPLR & GPIO_GC_UART0_CTS))
@@ -326,6 +312,8 @@ static void __init graphicsclient_map_io(void)
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
sa1100_register_uart(2, 2);
+ GPDR |= GPIO_GC_UART0_RTS | GPIO_GC_UART1_RTS | GPIO_GC_UART2_RTS;
+ GPDR &= ~(GPIO_GC_UART0_CTS | GPIO_GC_UART1_RTS | GPIO_GC_UART2_RTS);
}
MACHINE_START(GRAPHICSCLIENT, "ADS GraphicsClient")
diff --git a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c
index 5f6fb0970..9972bdbf6 100644
--- a/arch/arm/mach-sa1100/graphicsmaster.c
+++ b/arch/arm/mach-sa1100/graphicsmaster.c
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
+#include <linux/ioport.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@@ -43,7 +44,7 @@ static int __init graphicsmaster_init(void)
/*
* Probe for SA1111.
*/
- ret = sa1111_probe();
+ ret = sa1111_probe(0x18000000);
if (ret < 0)
return ret;
@@ -174,7 +175,6 @@ static void __init graphicsmaster_init_irq(void)
irq_desc[irq].mask = ADS_mask_irq1;
irq_desc[irq].unmask = ADS_unmask_irq1;
}
- GPDR &= ~GPIO_GPIO0;
set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
}
@@ -200,7 +200,6 @@ fixup_graphicsmaster(struct machine_desc *desc, struct param_struct *params,
static struct map_desc graphicsmaster_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x08000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
{ 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* CPLD */
{ 0xf1000000, 0x40000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* CAN */
{ 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
@@ -215,31 +214,22 @@ static int graphicsmaster_uart_open(struct uart_port *port, struct uart_info *in
Ser1SDCR0 |= SDCR0_UART;
/* Set RTS Output */
GPSR = GPIO_GPIO15;
- GPDR |= GPIO_GPIO15;
- /* Set CTS Input */
- GPDR &= ~GPIO_GPIO14;
}
else if (port->mapbase == _Ser2UTCR0) {
Ser2UTCR4 = Ser2HSCR0 = 0;
/* Set RTS Output */
GPSR = GPIO_GPIO17;
- GPDR |= GPIO_GPIO17;
- /* Set CTS Input */
- GPDR &= ~GPIO_GPIO16;
}
else if (port->mapbase == _Ser3UTCR0) {
/* Set RTS Output */
GPSR = GPIO_GPIO19;
- GPDR |= GPIO_GPIO19;
- /* Set CTS Input */
- GPDR &= ~GPIO_GPIO18;
}
return ret;
}
-static int graphicsmaster_get_mctrl(struct uart_port *port)
+static u_int graphicsmaster_get_mctrl(struct uart_port *port)
{
- int result = TIOCM_CD | TIOCM_DSR;
+ u_int result = TIOCM_CD | TIOCM_DSR;
if (port->mapbase == _Ser1UTCR0) {
if (!(GPLR & GPIO_GPIO14))
@@ -304,6 +294,10 @@ static void __init graphicsmaster_map_io(void)
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
sa1100_register_uart(2, 2);
+
+ /* set GPDR now */
+ GPDR |= GPIO_GPIO15 | GPIO_GPIO17 | GPIO_GPIO19;
+ GPDR &= ~(GPIO_GPIO14 | GPIO_GPIO16 | GPIO_GPIO18);
}
MACHINE_START(GRAPHICSMASTER, "ADS GraphicsMaster")
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index ecfbf5fae..af6fef821 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -1,5 +1,23 @@
/*
- * linux/arch/arm/mach-sa1100/h3600.c
+ * Hardware definitions for Compaq iPAQ H3xxx Handheld Computers
+ *
+ * Copyright 2000,1 Compaq Computer Corporation.
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Author: Jamey Hicks.
+ *
+ * History:
+ *
+ * 2001-10-?? Andrew Christian Added support for iPAQ H3800
+ * and abstracted EGPIO interface.
+ *
*/
#include <linux/config.h>
@@ -17,84 +35,345 @@
#include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h>
#include <linux/serial_core.h>
+#include <asm/arch/h3600_gpio.h>
#include "generic.h"
-
/*
- * Bitsy has extended, write-only memory-mapped GPIO's
+ * H3600 has extended, write-only memory-mapped GPIO's
+ * H3100 has 1/2 extended, write-only GPIO and 1/2 on
+ * regular GPIO lines.
+ * H3800 has memory-mapped GPIO through ASIC1 & 2
*/
-static int h3600_egpio = EGPIO_H3600_RS232_ON;
-
-void init_h3600_egpio(void)
-{
-#ifdef CONFIG_IPAQ_H3100
- int h3100_controls = (GPIO_H3100_BT_ON
- | GPIO_H3100_QMUTE
- | GPIO_H3100_LCD_3V_ON
- | GPIO_H3100_AUD_ON
- | GPIO_H3100_AUD_PWR_ON
- | GPIO_H3100_IR_ON
- | GPIO_H3100_IR_FSEL);
- GPDR |= h3100_controls;
- GPCR = h3100_controls;
- GAFR = GPIO_SSP_CLK;
-#endif
-}
-
-void clr_h3600_egpio(unsigned long x)
-{
-#ifdef CONFIG_IPAQ_H3100
- unsigned long gpcr = 0;
- if (x&EGPIO_H3600_QMUTE)
- gpcr |= GPIO_H3100_QMUTE;
- if (x&EGPIO_H3600_LCD_ON)
- gpcr |= GPIO_H3100_LCD_3V_ON;
- if (x&EGPIO_H3600_AUD_AMP_ON)
- gpcr |= GPIO_H3100_AUD_ON;
- if (x&EGPIO_H3600_AUD_PWR_ON)
- gpcr |= GPIO_H3100_AUD_PWR_ON;
- if (x&EGPIO_H3600_IR_ON)
- gpcr |= GPIO_H3100_IR_ON;
- if (x&EGPIO_H3600_IR_FSEL)
- gpcr |= GPIO_H3100_IR_FSEL;
- GPCR = gpcr;
-#endif
- h3600_egpio &= ~x;
+#define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
+
+static unsigned int h3600_egpio;
+
+/************************* H3100 *************************/
+
+#define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \
+ | GPIO_H3100_GPIO3 \
+ | GPIO_H3100_QMUTE \
+ | GPIO_H3100_LCD_3V_ON \
+ | GPIO_H3100_AUD_ON \
+ | GPIO_H3100_AUD_PWR_ON \
+ | GPIO_H3100_IR_ON \
+ | GPIO_H3100_IR_FSEL)
+
+void h3100_init_egpio( void )
+{
+ GPDR |= H3100_DIRECT_EGPIO;
+ GPCR = H3100_DIRECT_EGPIO; /* Initially all off */
+
+ /* Older bootldrs put GPIO2-9 in alternate mode on the
+ assumption that they are used for video */
+ GAFR &= ~H3100_DIRECT_EGPIO;
+
+ h3600_egpio = EGPIO_H3600_RS232_ON;
H3600_EGPIO = h3600_egpio;
}
-void set_h3600_egpio(unsigned long x)
-{
-#ifdef CONFIG_IPAQ_H3100
- unsigned long gpsr = 0;
- if (x&EGPIO_H3600_QMUTE)
- gpsr |= GPIO_H3100_QMUTE;
- if (x&EGPIO_H3600_LCD_ON)
- gpsr |= GPIO_H3100_LCD_3V_ON;
- if (x&EGPIO_H3600_AUD_AMP_ON)
- gpsr |= GPIO_H3100_AUD_ON;
- if (x&EGPIO_H3600_AUD_PWR_ON)
- gpsr |= GPIO_H3100_AUD_PWR_ON;
- if (x&EGPIO_H3600_IR_ON)
- gpsr |= GPIO_H3100_IR_ON;
- if (x&EGPIO_H3600_IR_FSEL)
- gpsr |= GPIO_H3100_IR_FSEL;
- GPSR = gpsr;
-#endif
- h3600_egpio |= x;
+void h3100_control_egpio( enum ipaq_egpio_type x, int setp )
+{
+ unsigned int egpio = 0;
+ long gpio = 0;
+ unsigned long flags;
+
+ switch (x) {
+ case IPAQ_EGPIO_LCD_ON:
+ egpio |= EGPIO_H3600_LCD_ON;
+ gpio |= GPIO_H3100_LCD_3V_ON;
+ break;
+ case IPAQ_EGPIO_CODEC_NRESET:
+ egpio |= EGPIO_H3600_CODEC_NRESET;
+ break;
+ case IPAQ_EGPIO_AUDIO_ON:
+ gpio |= GPIO_H3100_AUD_PWR_ON
+ | GPIO_H3100_AUD_ON;
+ break;
+ case IPAQ_EGPIO_QMUTE:
+ gpio |= GPIO_H3100_QMUTE;
+ break;
+ case IPAQ_EGPIO_OPT_NVRAM_ON:
+ egpio |= EGPIO_H3600_OPT_NVRAM_ON;
+ break;
+ case IPAQ_EGPIO_OPT_ON:
+ egpio |= EGPIO_H3600_OPT_ON;
+ break;
+ case IPAQ_EGPIO_CARD_RESET:
+ egpio |= EGPIO_H3600_CARD_RESET;
+ break;
+ case IPAQ_EGPIO_OPT_RESET:
+ egpio |= EGPIO_H3600_OPT_RESET;
+ break;
+ case IPAQ_EGPIO_IR_ON:
+ gpio |= GPIO_H3100_IR_ON;
+ break;
+ case IPAQ_EGPIO_IR_FSEL:
+ gpio |= GPIO_H3100_IR_FSEL;
+ break;
+ case IPAQ_EGPIO_RS232_ON:
+ egpio |= EGPIO_H3600_RS232_ON;
+ break;
+ case IPAQ_EGPIO_VPP_ON:
+ egpio |= EGPIO_H3600_VPP_ON;
+ break;
+ }
+
+ local_irq_save(flags);
+ if ( setp ) {
+ h3600_egpio |= egpio;
+ GPSR = gpio;
+ } else {
+ h3600_egpio &= ~egpio;
+ GPCR = gpio;
+ }
H3600_EGPIO = h3600_egpio;
+ local_irq_restore(flags);
+
+ /*
+ if ( x != IPAQ_EGPIO_VPP_ON ) {
+ printk(__FUNCTION__ " : type=%d (%s) gpio=0x%x (0x%x) egpio=0x%x (0x%x) setp=%d\n",
+ x, egpio_names[x], GPLR, gpio, h3600_egpio, egpio, setp );
+ }
+ */
}
-EXPORT_SYMBOL(clr_h3600_egpio);
-EXPORT_SYMBOL(set_h3600_egpio);
+unsigned long h3100_read_egpio( void )
+{
+ return h3600_egpio;
+}
+static struct ipaq_model_ops h3100_model_ops __initdata = {
+ model : IPAQ_H3100,
+ generic_name : "3100",
+ initialize : h3100_init_egpio,
+ control : h3100_control_egpio,
+ read : h3100_read_egpio
+};
+
+
+/************************* H3600 *************************/
+
+void h3600_init_egpio( void )
+{
+ h3600_egpio = EGPIO_H3600_RS232_ON;
+ H3600_EGPIO = h3600_egpio;
+}
+
+void h3600_control_egpio( enum ipaq_egpio_type x, int setp )
+{
+ unsigned int egpio = 0;
+ unsigned long flags;
+
+ switch (x) {
+ case IPAQ_EGPIO_LCD_ON:
+ egpio |= EGPIO_H3600_LCD_ON |
+ EGPIO_H3600_LCD_PCI |
+ EGPIO_H3600_LCD_5V_ON |
+ EGPIO_H3600_LVDD_ON;
+ break;
+ case IPAQ_EGPIO_CODEC_NRESET:
+ egpio |= EGPIO_H3600_CODEC_NRESET;
+ break;
+ case IPAQ_EGPIO_AUDIO_ON:
+ egpio |= EGPIO_H3600_AUD_AMP_ON |
+ EGPIO_H3600_AUD_PWR_ON;
+ break;
+ case IPAQ_EGPIO_QMUTE:
+ egpio |= EGPIO_H3600_QMUTE;
+ break;
+ case IPAQ_EGPIO_OPT_NVRAM_ON:
+ egpio |= EGPIO_H3600_OPT_NVRAM_ON;
+ break;
+ case IPAQ_EGPIO_OPT_ON:
+ egpio |= EGPIO_H3600_OPT_ON;
+ break;
+ case IPAQ_EGPIO_CARD_RESET:
+ egpio |= EGPIO_H3600_CARD_RESET;
+ break;
+ case IPAQ_EGPIO_OPT_RESET:
+ egpio |= EGPIO_H3600_OPT_RESET;
+ break;
+ case IPAQ_EGPIO_IR_ON:
+ egpio |= EGPIO_H3600_IR_ON;
+ break;
+ case IPAQ_EGPIO_IR_FSEL:
+ egpio |= EGPIO_H3600_IR_FSEL;
+ break;
+ case IPAQ_EGPIO_RS232_ON:
+ egpio |= EGPIO_H3600_RS232_ON;
+ break;
+ case IPAQ_EGPIO_VPP_ON:
+ egpio |= EGPIO_H3600_VPP_ON;
+ break;
+ }
+
+ local_irq_save(flags);
+ if ( setp )
+ h3600_egpio |= egpio;
+ else
+ h3600_egpio &= ~egpio;
+ H3600_EGPIO = h3600_egpio;
+ local_irq_restore(flags);
+}
+
+unsigned long h3600_read_egpio( void )
+{
+ return h3600_egpio;
+}
+
+static struct ipaq_model_ops h3600_model_ops __initdata = {
+ model : IPAQ_H3600,
+ generic_name : "3600",
+ initialize : h3600_init_egpio,
+ control : h3600_control_egpio,
+ read : h3600_read_egpio
+};
+
+/************************* H3800 *************************/
+
+#define ASIC1_OUTPUTS 0x7fff /* First 15 bits are used */
+
+static unsigned int h3800_asic1_gpio;
+static unsigned int h3800_asic2_gpio;
+
+void h3800_init_egpio(void)
+{
+ /* Set up ASIC #1 */
+ H3800_ASIC1_GPIO_Direction = ASIC1_OUTPUTS; /* All outputs */
+ H3800_ASIC1_GPIO_Mask = ASIC1_OUTPUTS; /* No interrupts */
+ H3800_ASIC1_GPIO_SleepMask = ASIC1_OUTPUTS;
+ H3800_ASIC1_GPIO_SleepDir = ASIC1_OUTPUTS;
+ H3800_ASIC1_GPIO_SleepOut = GPIO_H3800_ASIC1_EAR_ON_N;
+ H3800_ASIC1_GPIO_BattFaultDir = ASIC1_OUTPUTS;
+ H3800_ASIC1_GPIO_BattFaultOut = GPIO_H3800_ASIC1_EAR_ON_N;
+
+ h3800_asic1_gpio = GPIO_H3800_ASIC1_IR_ON_N /* TODO: Check IR level */
+ | GPIO_H3800_ASIC1_RS232_ON
+ | GPIO_H3800_ASIC1_EAR_ON_N;
+
+ H3800_ASIC1_GPIO_Out = h3800_asic1_gpio;
+
+ /* Set up ASIC #2 */
+ H3800_ASIC2_GPIO_Direction = GPIO_H3800_ASIC2_PEN_IRQ
+ | GPIO_H3800_ASIC2_SD_DETECT
+ | GPIO_H3800_ASIC2_EAR_IN_N
+ | GPIO_H3800_ASIC2_USB_DETECT_N
+ | GPIO_H3800_ASIC2_SD_CON_SLT;
+
+ h3800_asic2_gpio = GPIO_H3800_ASIC2_IN_Y1_N | GPIO_H3800_ASIC2_IN_X1_N;
+ H3800_ASIC2_GPIO_Data = h3800_asic2_gpio;
+ H3800_ASIC2_GPIO_BattFaultOut = h3800_asic2_gpio;
+
+ /* TODO : Set sleep states & battery fault states */
+
+ /* Clear VPP Enable */
+ H3800_ASIC1_FlashWP_VPP_ON = 0;
+}
+
+void h3800_control_egpio( enum ipaq_egpio_type x, int setp )
+{
+ unsigned int set_asic1_egpio = 0;
+ unsigned int clear_asic1_egpio = 0;
+ unsigned long flags;
+
+ switch (x) {
+ case IPAQ_EGPIO_LCD_ON:
+ set_asic1_egpio |= GPIO_H3800_ASIC1_LCD_5V_ON
+ | GPIO_H3800_ASIC1_LCD_ON
+ | GPIO_H3800_ASIC1_LCD_PCI
+ | GPIO_H3800_ASIC1_VGH_ON
+ | GPIO_H3800_ASIC1_VGL_ON;
+ break;
+ case IPAQ_EGPIO_CODEC_NRESET:
+ break;
+ case IPAQ_EGPIO_AUDIO_ON:
+ break;
+ case IPAQ_EGPIO_QMUTE:
+ break;
+ case IPAQ_EGPIO_OPT_NVRAM_ON:
+ break;
+ case IPAQ_EGPIO_OPT_ON:
+ break;
+ case IPAQ_EGPIO_CARD_RESET:
+ break;
+ case IPAQ_EGPIO_OPT_RESET:
+ break;
+ case IPAQ_EGPIO_IR_ON:
+ clear_asic1_egpio |= GPIO_H3800_ASIC1_IR_ON_N; /* TODO : This is backwards? */
+ break;
+ case IPAQ_EGPIO_IR_FSEL:
+ break;
+ case IPAQ_EGPIO_RS232_ON:
+ set_asic1_egpio |= GPIO_H3800_ASIC1_RS232_ON;
+ break;
+ case IPAQ_EGPIO_VPP_ON:
+ H3800_ASIC1_FlashWP_VPP_ON = setp;
+ break;
+ }
+
+ local_irq_save(flags);
+ if ( setp ) {
+ h3800_asic1_gpio |= set_asic1_egpio;
+ h3800_asic1_gpio &= ~clear_asic1_egpio;
+ }
+ else {
+ h3800_asic1_gpio &= ~set_asic1_egpio;
+ h3800_asic1_gpio |= clear_asic1_egpio;
+ }
+ H3800_ASIC1_GPIO_Out = h3800_asic1_gpio;
+ local_irq_restore(flags);
+}
+
+unsigned long h3800_read_egpio( void )
+{
+ return h3800_asic1_gpio | (h3800_asic2_gpio << 16);
+}
+
+static struct ipaq_model_ops h3800_model_ops __initdata = {
+ model : IPAQ_H3800,
+ generic_name : "3800",
+ initialize : h3800_init_egpio,
+ control : h3800_control_egpio,
+ read : h3800_read_egpio
+};
+
+
+static void h3600_lcd_power(int on)
+{
+ if (on)
+ set_h3600_egpio(IPAQ_EGPIO_LCD_ON);
+ else
+ clr_h3600_egpio(IPAQ_EGPIO_LCD_ON);
+}
+
+
+struct ipaq_model_ops ipaq_model_ops;
+EXPORT_SYMBOL(ipaq_model_ops);
+
+static int __init h3600_init_model_ops(void)
+{
+ if (machine_is_h3xxx()) {
+ sa1100fb_lcd_power = h3600_lcd_power;
+
+ if (machine_is_h3100()) {
+ ipaq_model_ops = h3100_model_ops;
+ } else if (machine_is_h3600()) {
+ ipaq_model_ops = h3600_model_ops;
+ } else if (machine_is_h3800()) {
+ ipaq_model_ops = h3800_model_ops;
+ }
+ init_h3600_egpio();
+ }
+ return 0;
+}
+
+__initcall(h3600_init_model_ops);
/*
- * Low-level UART features.
- *
- * Note that RTS, CTS and DCD are all active low.
+ * low-level UART features
*/
static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
@@ -107,9 +386,9 @@ static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
}
}
-static int h3600_uart_get_mctrl(struct uart_port *port)
+static u_int h3600_uart_get_mctrl(struct uart_port *port)
{
- int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
+ u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
if (port->mapbase == _Ser3UTCR0) {
int gplr = GPLR;
@@ -126,31 +405,45 @@ static void h3600_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct uart_info *info = dev_id;
/* Note: should only call this if something has changed */
+ spin_lock_irq(&info->lock);
uart_handle_dcd_change(info, !(GPLR & GPIO_H3600_COM_DCD));
+ spin_unlock_irq(&info->lock);
}
static void h3600_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct uart_info *info = dev_id;
/* Note: should only call this if something has changed */
+ spin_lock_irq(&info->lock);
uart_handle_cts_change(info, !(GPLR & GPIO_H3600_COM_CTS));
+ spin_unlock_irq(&info->lock);
}
static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
{
if (port->mapbase == _Ser2UTCR0) {
- if (state == 0) {
- set_h3600_egpio(EGPIO_H3600_IR_ON);
- } else {
- clr_h3600_egpio(EGPIO_H3600_IR_ON);
- }
+ assign_h3600_egpio( IPAQ_EGPIO_IR_ON, !state );
} else if (port->mapbase == _Ser3UTCR0) {
- if (state == 0) {
- set_h3600_egpio(EGPIO_H3600_RS232_ON);
- } else {
- clr_h3600_egpio(EGPIO_H3600_RS232_ON);
- }
+ assign_h3600_egpio( IPAQ_EGPIO_RS232_ON, !state );
+ }
+}
+
+/*
+ * Enable/Disable wake up events for this serial port.
+ * Obviously, we only support this on the normal COM port.
+ */
+static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
+{
+ int err = -EINVAL;
+
+ if (port->mapbase == _Ser3UTCR0) {
+ if (enable)
+ PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */
+ else
+ PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
+ err = 0;
}
+ return err;
}
static int h3600_uart_open(struct uart_port *port, struct uart_info *info)
@@ -163,8 +456,6 @@ static int h3600_uart_open(struct uart_port *port, struct uart_info *info)
Ser2HSSR0 = HSSR0_EIF | HSSR0_TUR |
HSSR0_RAB | HSSR0_FRE;
} else if (port->mapbase == _Ser3UTCR0) {
- GPDR &= ~(GPIO_H3600_COM_DCD|GPIO_H3600_COM_CTS);
- GPDR |= GPIO_H3600_COM_RTS;
set_GPIO_IRQ_edge(GPIO_H3600_COM_DCD|GPIO_H3600_COM_CTS,
GPIO_BOTH_EDGES);
@@ -193,16 +484,16 @@ static struct sa1100_port_fns h3600_port_fns __initdata = {
set_mctrl: h3600_uart_set_mctrl,
get_mctrl: h3600_uart_get_mctrl,
pm: h3600_uart_pm,
+ set_wake: h3600_uart_set_wake,
open: h3600_uart_open,
close: h3600_uart_close,
};
static struct map_desc h3600_io_desc[] __initdata = {
- /* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf0000000, 0x49000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 */
- { 0xf1000000, 0x10000000, 0x02800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 */
- { 0xf3800000, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 */
+ /* virtual physical length domain r w c b */
+ { H3600_EGPIO_VIRT, 0x49000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 CS#5 */
+ { H3600_BANK_2_VIRT, 0x10000000, 0x02800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 CS#2 */
+ { H3600_BANK_4_VIRT, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 CS#4 */
LAST_DESC
};
@@ -214,13 +505,19 @@ static void __init h3600_map_io(void)
sa1100_register_uart_fns(&h3600_port_fns);
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1); /* isn't this one driven elsewhere? */
- init_h3600_egpio();
/*
- * Default GPIO settings.
+ * Default GPIO settings. Should be set by machine
*/
GPCR = 0x0fffffff;
- GPDR = 0x0401f3fc;
+// GPDR = 0x0401f3fc;
+ GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
+ GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
+ GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
+ GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
+ GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
+
+ init_h3600_egpio();
/*
* Ensure those pins are outputs and driving low.
@@ -230,11 +527,24 @@ static void __init h3600_map_io(void)
/* Configure suspend conditions */
PGSR = 0;
- PWER = 0x1 | (1 << 31);
- PCFR = PCFR_OPDE | PCFR_FP | PCFR_FS;
+ PWER = PWER_GPIO0 | PWER_RTC;
+ PCFR = PCFR_OPDE;
+ PSDR = 0;
}
-MACHINE_START(H3600, "Compaq iPAQ")
+MACHINE_START(H3600, "Compaq iPAQ H3600")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ BOOT_PARAMS(0xc0000100)
+ MAPIO(h3600_map_io)
+ INITIRQ(sa1100_init_irq)
+MACHINE_END
+MACHINE_START(H3100, "Compaq iPAQ H3100")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ BOOT_PARAMS(0xc0000100)
+ MAPIO(h3600_map_io)
+ INITIRQ(sa1100_init_irq)
+MACHINE_END
+MACHINE_START(H3800, "Compaq iPAQ H3800")
BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
BOOT_PARAMS(0xc0000100)
MAPIO(h3600_map_io)
diff --git a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c
index e51a335bc..969e7c84c 100644
--- a/arch/arm/mach-sa1100/huw_webpanel.c
+++ b/arch/arm/mach-sa1100/huw_webpanel.c
@@ -22,11 +22,35 @@
unsigned long BCR_value;
EXPORT_SYMBOL(BCR_value);
+static void huw_lcd_power(int on)
+{
+ if (on)
+ BCR_clear(BCR_TFT_NPWR);
+ else
+ BCR_set(BCR_TFT_NPWR);
+}
+
+static void huw_backlight_power(int on)
+{
+#error FIXME
+ if (on) {
+ BCR_set(BCR_CCFL_POW | BCR_PWM_BACKLIGHT);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_task(200 * HZ / 1000);
+ BCR_set(BCR_TFT_ENA);
+ }
+}
-static void __init init_huw_cs3(void)
+static int __init init_huw_cs3(void)
{
// here we can place some initcode
// BCR_value = 0x1045bf70; //*((volatile unsigned long*)0xf1fffff0);
+ if (machine_is_huw_webpanel()) {
+ sa1100fb_lcd_power = huw_lcd_power;
+ sa1100fb_backlight_power = huw_backlight_power;
+ }
+
+ return 0;
}
__initcall(init_huw_cs3);
@@ -55,7 +79,6 @@ fixup_huw_webpanel(struct machine_desc *desc, struct param_struct *params,
**/
static struct map_desc huw_webpanel_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0, neccessary for mtd */
{ 0xf0000000, 0xc1fb8000, 0x00048000, DOMAIN_IO, 1, 1, 0, 0 }, /* Parameter */
{ 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Paules CS3, write only */
LAST_DESC
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 9d7fc1c59..8c0412148 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <linux/ioport.h>
#include <linux/ptrace.h>
#include <asm/hardware.h>
@@ -37,6 +38,9 @@ static int GPIO_IRQ_falling_edge;
void set_GPIO_IRQ_edge( int gpio_mask, int edge )
{
+ int flags;
+
+ local_irq_save(flags);
if (edge & GPIO_FALLING_EDGE)
GPIO_IRQ_falling_edge |= gpio_mask;
else
@@ -45,6 +49,9 @@ void set_GPIO_IRQ_edge( int gpio_mask, int edge )
GPIO_IRQ_rising_edge |= gpio_mask;
else
GPIO_IRQ_rising_edge &= ~gpio_mask;
+ GPDR &= ~gpio_mask;
+ GAFR &= ~gpio_mask;
+ restore_flags(flags);
}
EXPORT_SYMBOL(set_GPIO_IRQ_edge);
@@ -121,7 +128,7 @@ static void sa1100_GPIO11_27_demux(int irq, void *dev_id,
for (i = 11; i <= 27; ++i) {
if (irq & (1<<i)) {
- do_IRQ (IRQ_GPIO_11_27(i), regs);
+ do_IRQ(IRQ_GPIO11 + i - 11, regs);
}
}
}
@@ -175,11 +182,18 @@ static void sa1100_unmask_GPIO11_27_irq(unsigned int irq)
GFER = (GFER & ~mask) | (GPIO_IRQ_falling_edge & mask);
}
+static struct resource irq_resource = {
+ name: "irqs",
+ start: 0x90050000,
+ end: 0x9005ffff,
+};
void __init sa1100_init_irq(void)
{
int irq;
+ request_resource(&iomem_resource, &irq_resource);
+
/* disable all IRQs */
ICMR = 0;
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 243ea20ec..973ed400a 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/delay.h>
+#include <linux/ioport.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@@ -37,20 +38,17 @@ static int __init jornada720_init(void)
SKCR = JORSKCR_INIT; /* Turn on the PLL, enable Ready and enable nOE assertion from DC */
mdelay(100);
- SKCR = JORSKCR_RCLK; /* turn on the RCLOCK */
- SMCR = 0x35; /* initialize the SMC (debug SA-1111 reset */
- PCCR = 0; /* initialize the S2MC (debug SA-1111 reset) */
+ SBI_SKCR = JORSKCR_RCLK;/* turn on the RCLOCK */
+ SBI_SMCR = 0x35; /* initialize the SMC (debug SA-1111 reset */
+ PCCR = 0; /* initialize the S2MC (debug SA-1111 reset) */
/* LDD4 is speaker, LDD3 is microphone */
PPSR &= ~(PPC_LDD3 | PPC_LDD4);
PPDR |= PPC_LDD3 | PPC_LDD4;
/* initialize extra IRQs */
- set_GPIO_IRQ_edge(GPIO_GPIO(1), GPIO_RISING_EDGE);
- sa1111_init_irq(SA1100_GPIO_TO_IRQ(1)); /* chained on GPIO 1 */
-
- sa1100_register_uart(0, 3);
- sa1100_register_uart(1, 1);
+ set_GPIO_IRQ_edge(GPIO_GPIO1, GPIO_RISING_EDGE);
+ sa1111_init_irq(IRQ_GPIO1)); /* chained on GPIO 1 */
return 0;
}
@@ -68,7 +66,6 @@ fixup_jornada720(struct machine_desc *desc, struct param_struct *params,
static struct map_desc jornada720_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
{ 0xf0000000, 0x48000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Epson registers */
{ 0xf1000000, 0x48200000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Epson frame buffer */
{ 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
@@ -79,6 +76,9 @@ static void __init jornada720_map_io(void)
{
sa1100_map_io();
iotable_init(jornada720_io_desc);
+
+ sa1100_register_uart(0, 3);
+ sa1100_register_uart(1, 1);
}
MACHINE_START(JORNADA720, "HP Jornada 720")
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 5594d6ebe..fd1895dd4 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -31,6 +31,7 @@ static void __init lart_map_io(void)
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
sa1100_register_uart(2, 2);
+
GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
GPDR |= GPIO_UART_TXD;
GPDR &= ~GPIO_UART_RXD;
diff --git a/arch/arm/mach-sa1100/leds-assabet.c b/arch/arm/mach-sa1100/leds-assabet.c
index 7a5da72c4..e9aa9dff2 100644
--- a/arch/arm/mach-sa1100/leds-assabet.c
+++ b/arch/arm/mach-sa1100/leds-assabet.c
@@ -42,6 +42,8 @@ void assabet_leds_event(led_event_t evt)
case led_stop:
led_state &= ~LED_STATE_ENABLED;
+ hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN;
+ ASSABET_BCR_frob(ASSABET_BCR_LED_MASK, hw_led_state);
break;
case led_claim:
@@ -107,8 +109,7 @@ void assabet_leds_event(led_event_t evt)
}
if (led_state & LED_STATE_ENABLED)
- ASSABET_BCR = BCR_value = (BCR_value & ~ASSABET_BCR_LED_MASK) |
- hw_led_state;
+ ASSABET_BCR_frob(ASSABET_BCR_LED_MASK, hw_led_state);
local_irq_restore(flags);
}
diff --git a/arch/arm/mach-sa1100/leds-flexanet.c b/arch/arm/mach-sa1100/leds-flexanet.c
index 1be57f034..af7fabe93 100644
--- a/arch/arm/mach-sa1100/leds-flexanet.c
+++ b/arch/arm/mach-sa1100/leds-flexanet.c
@@ -35,7 +35,7 @@ void flexanet_leds_event(led_event_t evt)
switch (evt) {
case led_start:
/* start using LEDs and enable its hardware */
- hw_led_bcr = BCR_LED_GREEN;
+ hw_led_bcr = FHH_BCR_LED_GREEN;
hw_led_gpio = GPIO_LED_RED;
led_state = LED_STATE_ENABLED;
break;
@@ -71,13 +71,13 @@ void flexanet_leds_event(led_event_t evt)
case led_idle_start:
/* turn off CPU load LED */
if (!(led_state & LED_STATE_CLAIMED))
- hw_led_bcr &= ~BCR_LED_GREEN;
+ hw_led_bcr &= ~FHH_BCR_LED_GREEN;
break;
case led_idle_end:
/* turn on CPU load LED */
if (!(led_state & LED_STATE_CLAIMED))
- hw_led_bcr |= BCR_LED_GREEN;
+ hw_led_bcr |= FHH_BCR_LED_GREEN;
break;
#endif
@@ -88,12 +88,12 @@ void flexanet_leds_event(led_event_t evt)
/* direct LED access (must be previously claimed) */
case led_green_on:
if (led_state & LED_STATE_CLAIMED)
- hw_led_bcr |= BCR_LED_GREEN;
+ hw_led_bcr |= FHH_BCR_LED_GREEN;
break;
case led_green_off:
if (led_state & LED_STATE_CLAIMED)
- hw_led_bcr &= ~BCR_LED_GREEN;
+ hw_led_bcr &= ~FHH_BCR_LED_GREEN;
break;
case led_amber_on:
@@ -119,7 +119,7 @@ void flexanet_leds_event(led_event_t evt)
if (led_state & LED_STATE_ENABLED)
{
/* update LEDs */
- BCR = BCR_value = (BCR_value & ~BCR_LED_GREEN) | hw_led_bcr;
+ FHH_BCR = flexanet_BCR = (flexanet_BCR & ~FHH_BCR_LED_GREEN) | hw_led_bcr;
GPSR = hw_led_gpio;
GPCR = hw_led_gpio ^ GPIO_LED_RED;
}
diff --git a/arch/arm/mach-sa1100/leds-system3.c b/arch/arm/mach-sa1100/leds-system3.c
new file mode 100644
index 000000000..f9b68a1f0
--- /dev/null
+++ b/arch/arm/mach-sa1100/leds-system3.c
@@ -0,0 +1,49 @@
+/*
+ * linux/arch/arm/mach-sa1100/leds-system3.c
+ *
+ * Copyright (C) 2001 Stefan Eletzhofer <stefan.eletzhofer@gmx.de>
+ *
+ * Original (leds-footbridge.c) by Russell King
+ *
+ * $Id: leds-system3.c,v 1.1.6.1 2001/12/04 15:19:26 seletz Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * $Log: leds-system3.c,v $
+ * Revision 1.1.6.1 2001/12/04 15:19:26 seletz
+ * - merged from linux_2_4_13_ac5_rmk2
+ *
+ * Revision 1.1.4.2 2001/11/19 17:58:53 seletz
+ * - cleanup
+ *
+ * Revision 1.1.4.1 2001/11/16 13:49:54 seletz
+ * - dummy LED support for PT Digital Board
+ *
+ * Revision 1.1.2.1 2001/10/15 16:03:39 seletz
+ * - dummy function
+ *
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include "leds.h"
+
+
+#define LED_STATE_ENABLED 1
+#define LED_STATE_CLAIMED 2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+void system3_leds_event(led_event_t evt)
+{
+
+ /* TODO: support LEDs */
+}
diff --git a/arch/arm/mach-sa1100/leds.c b/arch/arm/mach-sa1100/leds.c
index b7f76c44c..8e3a7ab50 100644
--- a/arch/arm/mach-sa1100/leds.c
+++ b/arch/arm/mach-sa1100/leds.c
@@ -34,6 +34,8 @@ sa1100_leds_init(void)
leds_event = graphicsmaster_leds_event;
if (machine_is_adsbitsy())
leds_event = adsbitsy_leds_event;
+ if (machine_is_pt_system3())
+ leds_event = system3_leds_event;
leds_event(led_start);
return 0;
diff --git a/arch/arm/mach-sa1100/leds.h b/arch/arm/mach-sa1100/leds.h
index dc84b1af6..bb9ad9c8a 100644
--- a/arch/arm/mach-sa1100/leds.h
+++ b/arch/arm/mach-sa1100/leds.h
@@ -7,3 +7,4 @@ extern void lart_leds_event(led_event_t evt);
extern void pfs168_leds_event(led_event_t evt);
extern void graphicsmaster_leds_event(led_event_t evt);
extern void adsbitsy_leds_event(led_event_t evt);
+extern void system3_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 2ad7da7e3..e734ba81e 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -7,6 +7,8 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
#include <linux/serial_core.h>
#include <asm/hardware.h>
@@ -16,6 +18,7 @@
#include <asm/arch/irq.h>
#include <asm/mach/serial_sa1100.h>
#include <asm/arch/assabet.h>
+#include <asm/hardware/sa1111.h>
#include "sa1111.h"
@@ -40,10 +43,10 @@ static void neponset_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
if (!irr) break;
if( irr & IRR_ETHERNET )
- do_IRQ(NEPONSET_ETHERNET_IRQ, regs);
+ do_IRQ(IRQ_NEPONSET_SMC9196, regs);
if( irr & IRR_USAR )
- do_IRQ(NEPONSET_USAR_IRQ, regs);
+ do_IRQ(IRQ_NEPONSET_USAR, regs);
if( irr & IRR_SA1111 )
sa1111_IRQ_demux(irq, dev_id, regs);
@@ -58,19 +61,16 @@ static struct irqaction neponset_irq = {
static void __init neponset_init_irq(void)
{
- int irq;
-
sa1111_init_irq(-1); /* SA1111 IRQ not routed to a GPIO */
/* setup extra Neponset IRQs */
- irq = NEPONSET_ETHERNET_IRQ;
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
- irq = NEPONSET_USAR_IRQ;
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
- set_GPIO_IRQ_edge(ASSABET_GPIO_NEP_IRQ, GPIO_RISING_EDGE);
- setup_arm_irq(ASSABET_IRQ_GPIO_NEP_IRQ, &neponset_irq);
+ irq_desc[IRQ_NEPONSET_SMC9196].valid = 1;
+ irq_desc[IRQ_NEPONSET_SMC9196].probe_ok = 1;
+ irq_desc[IRQ_NEPONSET_USAR].valid = 1;
+ irq_desc[IRQ_NEPONSET_USAR].probe_ok = 1;
+
+ set_GPIO_IRQ_edge(GPIO_GPIO25, GPIO_RISING_EDGE);
+ setup_arm_irq(IRQ_GPIO25, &neponset_irq);
}
static int __init neponset_init(void)
@@ -102,6 +102,11 @@ static int __init neponset_init(void)
}
/*
+ * Disable GPIO 0/1 drivers so the buttons work on the module.
+ */
+ NCR_0 |= NCR_GP01_OFF;
+
+ /*
* Neponset has SA1111 connected to CS4. We know that after
* reset the chip will be configured for variable latency IO.
*/
@@ -110,7 +115,7 @@ static int __init neponset_init(void)
/*
* Probe for a SA1111.
*/
- ret = sa1111_probe();
+ ret = sa1111_probe(0x40000000);
if (ret < 0)
return ret;
@@ -184,7 +189,7 @@ static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
MDM_CTL_0 = mdm_ctl0;
}
-static int neponset_get_mctrl(struct uart_port *port)
+static u_int neponset_get_mctrl(struct uart_port *port)
{
u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
u_int mdm_ctl1 = MDM_CTL_1;
diff --git a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c
index 0e6f049bc..8258fdc19 100644
--- a/arch/arm/mach-sa1100/omnimeter.c
+++ b/arch/arm/mach-sa1100/omnimeter.c
@@ -15,6 +15,30 @@
#include "generic.h"
+static void omnimeter_backlight_power(int on)
+{
+ if (on)
+ LEDBacklightOn();
+ else
+ LEDBacklightOff();
+}
+
+static void omnimeter_lcd_power(int on)
+{
+ if (on)
+ LCDPowerOn();
+}
+
+static int __init omnimeter_init(void)
+{
+ if (machine_is_omnimeter()) {
+ sa1100fb_backlight_power = omnimeter_backlight_power;
+ sa1100fb_lcd_power = omnimeter_lcd_power;
+ }
+ return 0;
+}
+
+__initcall(omnimeter_init);
static void __init
fixup_omnimeter(struct machine_desc *desc, struct param_struct *params,
diff --git a/arch/arm/mach-sa1100/pangolin.c b/arch/arm/mach-sa1100/pangolin.c
index 99128a49f..a9637352a 100644
--- a/arch/arm/mach-sa1100/pangolin.c
+++ b/arch/arm/mach-sa1100/pangolin.c
@@ -30,7 +30,6 @@ fixup_pangolin(struct machine_desc *desc, struct param_struct *params,
static struct map_desc pangolin_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
{ 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
LAST_DESC
};
@@ -43,6 +42,12 @@ static void __init pangolin_map_io(void)
sa1100_register_uart(0, 1);
sa1100_register_uart(1, 3);
Ser1SDCR0 |= SDCR0_UART;
+
+ /* set some GPDR bits while it's safe */
+ GPDR |= GPIO_PCMCIA_RESET;
+#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
+ GPDR |= GPIO_PCMCIA_BUS_ON;
+#endif
}
MACHINE_START(PANGOLIN, "Dialogue-Pangolin")
diff --git a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c
index cfe3a1d42..19085bffb 100644
--- a/arch/arm/mach-sa1100/pfs168.c
+++ b/arch/arm/mach-sa1100/pfs168.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/errno.h>
+#include <linux/ioport.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@@ -34,7 +35,7 @@ static int __init pfs168_init(void)
/*
* Probe for SA1111.
*/
- ret = sa1111_probe();
+ ret = sa1111_probe(0x40000000);
if (ret < 0)
return ret;
@@ -65,8 +66,7 @@ static int __init pfs168_init(void)
*/
sa1110_mb_enable();
- set_GPIO_IRQ_edge(GPIO_GPIO(25), GPIO_RISING_EDGE);
- sa1111_init_irq(SA1100_GPIO_TO_IRQ(25)); /* SA1111 IRQ on GPIO 25 */
+ sa1111_init_irq(IRQ_GPIO25); /* SA1111 IRQ on GPIO 25 */
return 0;
}
@@ -84,6 +84,8 @@ static void __init pfs168_init_irq(void)
*/
set_GPIO_IRQ_edge(GPIO_GPIO(19), GPIO_RISING_EDGE);
set_GPIO_IRQ_edge(GPIO_GPIO(20), GPIO_RISING_EDGE);
+ set_GPIO_IRQ_edge(GPIO_GPIO(25), GPIO_RISING_EDGE);
+ set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE);
}
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index cab24f7b8..e1de84d73 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -19,30 +19,27 @@
* Cleaned up, pushed platform dependent stuff
* in the platform specific files.
*/
-
-/*
- * Debug macros
- */
-#define DEBUG 1
-#ifdef DEBUG
-# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
-#else
-# define DPRINTK(fmt, args...)
-#endif
-
-
+#include <linux/config.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
#include <linux/sysctl.h>
-#include <linux/acpi.h>
+#include <linux/errno.h>
#include <asm/hardware.h>
#include <asm/memory.h>
#include <asm/system.h>
+#include <asm/leds.h>
#include "sleep.h"
+/*
+ * Debug macros
+ */
+#undef DEBUG
+
extern void sa1100_cpu_suspend(void);
extern void sa1100_cpu_resume(void);
@@ -57,19 +54,16 @@ int pm_do_suspend(void)
int retval;
/* set up pointer to sleep parameters */
- sleep_save = kmalloc (SLEEP_SAVE_SIZE*sizeof(long), GFP_ATOMIC);
+ sleep_save = kmalloc(SLEEP_SAVE_SIZE*sizeof(long), GFP_ATOMIC);
if (!sleep_save)
return -ENOMEM;
- sleep_save_p = virt_to_phys(sleep_save);
- retval = pm_send_all(PM_SUSPEND, (void *)2);
- if (retval) {
- kfree(sleep_save);
- return retval;
- }
+ sleep_save_p = virt_to_phys(sleep_save);
cli();
+ leds_event(led_stop);
+
/* preserve current time */
RCNR = xtime.tv_sec;
@@ -112,7 +106,9 @@ int pm_do_suspend(void)
/* ensure not to come back here if it wasn't intended */
PSPR = 0;
- DPRINTK("*** made it back from resume\n");
+#ifdef DEBUG
+ printk("*** made it back from resume\n");
+#endif
/* restore registers */
RESTORE(GPDR);
@@ -146,21 +142,61 @@ int pm_do_suspend(void)
/* restore current time */
xtime.tv_sec = RCNR;
+ leds_event(led_start);
+
sti();
kfree (sleep_save);
- retval = pm_send_all(PM_RESUME, (void *)0);
- if (retval)
- return retval;
+ /*
+ * Restore the CPU frequency settings.
+ */
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_restore();
+#endif
return 0;
}
+#ifdef CONFIG_SYSCTL
+/*
+ * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
+ * linux/sysctl.h.
+ *
+ * This means our interface here won't survive long - it needs a new
+ * interface. Quick hack to get this working - use sysctl id 9999.
+ */
+#warning ACPI broke the kernel, this interface needs to be fixed up.
+#define CTL_ACPI 9999
+#define ACPI_S1_SLP_TYP 19
+
+/*
+ * Send us to sleep. We must not be called from IRQ context.
+ */
+static int sysctl_pm_do_suspend(void)
+{
+ int retval;
+
+ if (in_interrupt()) {
+ printk(KERN_CRIT "pm_do_suspend() called from IRQ\n");
+ return -EINVAL;
+ }
+
+ retval = pm_send_all(PM_SUSPEND, (void *)3);
+
+ if (retval == 0) {
+ retval = __pm_do_suspend();
+
+ pm_send_all(PM_RESUME, (void *)0);
+ }
+
+ return retval;
+}
+
static struct ctl_table pm_table[] =
{
- {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&pm_do_suspend},
+ {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
{0}
};
@@ -181,3 +217,4 @@ static int __init pm_init(void)
__initcall(pm_init);
+#endif
diff --git a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c
index 394e3fe74..481e2a643 100644
--- a/arch/arm/mach-sa1100/sa1111.c
+++ b/arch/arm/mach-sa1100/sa1111.c
@@ -9,12 +9,12 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * This file contains all generic SA1111 support, except for DMA which is
- * provided separately in dma-sa1111.c.
+ * This file contains all generic SA1111 support.
*
* All initialization functions provided here are intended to be called
* from machine specific code with proper arguments when required.
*/
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
@@ -22,57 +22,80 @@
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
+#include <linux/ioport.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/arch/irq.h>
+#include <asm/hardware/sa1111.h>
+
#include "sa1111.h"
+struct resource sa1111_resource = {
+ name: "SA1111",
+};
+
+EXPORT_SYMBOL(sa1111_resource);
+
/*
- * SA1111 Interrupt support
+ * SA1111 interrupt support
*/
-
-void sa1111_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+void sa1111_IRQ_demux(int irq, void *dev_id, struct pt_regs *regs)
{
- int i;
unsigned long stat0, stat1;
- for(;;) {
- stat0 = INTSTATCLR0, stat1 = INTSTATCLR1;
- if( !stat0 && !stat1 ) break;
- if( stat0 )
- for( i = 0; i < 32; i++ )
- if( stat0 & (1<<i) )
- do_IRQ( SA1111_IRQ(i), regs );
-
- if( stat1 )
- for( i = 32; i < 55; i++ )
- if( stat1 & (1<<(i-32)) )
- do_IRQ( SA1111_IRQ(i), regs );
+ while (1) {
+ int i;
+
+ stat0 = INTSTATCLR0;
+ stat1 = INTSTATCLR1;
+
+ if (stat0 == 0 && stat1 == 0)
+ break;
+
+ for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1)
+ if (stat0 & 1)
+ do_IRQ(i, regs);
+
+ for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
+ if (stat1 & 1)
+ do_IRQ(i, regs);
}
}
-static struct irqaction sa1111_irq = {
- name: "SA1111",
- handler: sa1111_IRQ_demux,
- flags: SA_INTERRUPT
-};
+#define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START))
+#define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32))
+/*
+ * A note about masking IRQs:
+ *
+ * The GPIO IRQ edge detection only functions while the IRQ itself is
+ * enabled; edges are not detected while the IRQ is disabled.
+ *
+ * This is especially important for the PCMCIA signals, where we must
+ * pick up every transition. We therefore do not disable the IRQs
+ * while processing them.
+ *
+ * However, since we are changed to a GPIO on the host processor,
+ * all SA1111 IRQs will be disabled while we're processing any SA1111
+ * IRQ.
+ *
+ * Note also that changing INTPOL while an IRQ is enabled will itself
+ * trigger an IRQ.
+ */
static void sa1111_mask_and_ack_lowirq(unsigned int irq)
{
- unsigned int mask = 1 << (irq - SA1111_IRQ(0));
+ unsigned int mask = SA1111_IRQMASK_LO(irq);
- // broken hardware: interrupt events are lost if they occur
- // while the interrupts are disabled.
//INTEN0 &= ~mask;
INTSTATCLR0 = mask;
}
static void sa1111_mask_and_ack_highirq(unsigned int irq)
{
- unsigned int mask = 1 << (irq - SA1111_IRQ(32));
+ unsigned int mask = SA1111_IRQMASK_HI(irq);
//INTEN1 &= ~mask;
INTSTATCLR1 = mask;
@@ -80,27 +103,29 @@ static void sa1111_mask_and_ack_highirq(unsigned int irq)
static void sa1111_mask_lowirq(unsigned int irq)
{
- //INTEN0 &= ~(1 << (irq - SA1111_IRQ(0)));
+ INTEN0 &= ~SA1111_IRQMASK_LO(irq);
}
static void sa1111_mask_highirq(unsigned int irq)
{
- //INTEN1 &= ~(1 << (irq - SA1111_IRQ(32)));
+ INTEN1 &= ~SA1111_IRQMASK_HI(irq);
}
static void sa1111_unmask_lowirq(unsigned int irq)
{
- INTEN0 |= 1 << (irq - SA1111_IRQ(0));
+ INTEN0 |= SA1111_IRQMASK_LO(irq);
}
static void sa1111_unmask_highirq(unsigned int irq)
{
- INTEN1 |= 1 << ((irq - SA1111_IRQ(32)));
+ INTEN1 |= SA1111_IRQMASK_HI(irq);
}
void __init sa1111_init_irq(int irq_nr)
{
- int irq;
+ int irq, ret;
+
+ request_mem_region(_INTTEST0, 512, "irqs");
/* disable all IRQs */
INTEN0 = 0;
@@ -111,21 +136,21 @@ void __init sa1111_init_irq(int irq_nr)
* specifies that S0ReadyInt and S1ReadyInt should be '1'.
*/
INTPOL0 = 0;
- INTPOL1 = 1 << (S0_READY_NINT - SA1111_IRQ(32)) |
- 1 << (S1_READY_NINT - SA1111_IRQ(32));
+ INTPOL1 = SA1111_IRQMASK_HI(S0_READY_NINT) |
+ SA1111_IRQMASK_HI(S1_READY_NINT);
/* clear all IRQs */
INTSTATCLR0 = -1;
INTSTATCLR1 = -1;
- for (irq = SA1111_IRQ(0); irq <= SA1111_IRQ(26); irq++) {
+ for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
irq_desc[irq].valid = 1;
irq_desc[irq].probe_ok = 0;
irq_desc[irq].mask_ack = sa1111_mask_and_ack_lowirq;
irq_desc[irq].mask = sa1111_mask_lowirq;
irq_desc[irq].unmask = sa1111_unmask_lowirq;
}
- for (irq = SA1111_IRQ(32); irq <= SA1111_IRQ(54); irq++) {
+ for (irq = AUDXMTDMADONEA; irq <= S1_BVD1_STSCHG; irq++) {
irq_desc[irq].valid = 1;
irq_desc[irq].probe_ok = 0;
irq_desc[irq].mask_ack = sa1111_mask_and_ack_highirq;
@@ -134,28 +159,60 @@ void __init sa1111_init_irq(int irq_nr)
}
/* Register SA1111 interrupt */
- if (irq_nr >= 0)
- setup_arm_irq(irq_nr, &sa1111_irq);
+ if (irq_nr < 0)
+ return;
+
+ ret = request_irq(irq_nr, sa1111_IRQ_demux, SA_INTERRUPT,
+ "SA1111", NULL);
+ if (ret < 0)
+ printk(KERN_ERR "SA1111: unable to claim IRQ%d: %d\n",
+ irq_nr, ret);
}
-/*
- * Probe for a SA1111 chip.
+/**
+ * sa1111_probe - probe for a single SA1111 chip.
+ * @phys_addr: physical address of device.
+ *
+ * Probe for a SA1111 chip. This must be called
+ * before any other SA1111-specific code.
+ *
+ * Returns:
+ * %-ENODEV device not found.
+ * %-EBUSY physical address already marked in-use.
+ * %0 successful.
*/
-
-int __init sa1111_probe(void)
+int __init sa1111_probe(unsigned long phys_addr)
{
- unsigned long id = SBI_SKID;
+ unsigned long id;
int ret = -ENODEV;
- if ((id & SKID_ID_MASK) == SKID_SA1111_ID) {
- printk(KERN_INFO "SA-1111 Microprocessor Companion Chip: "
- "silicon revision %lx, metal revision %lx\n",
- (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
- ret = 0;
- } else {
+ sa1111_resource.start = phys_addr;
+ sa1111_resource.end = phys_addr + 0x2000;
+
+ if (request_resource(&iomem_resource, &sa1111_resource)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /*
+ * Probe for the chip. Only touch the SBI registers.
+ */
+ id = SBI_SKID;
+ if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
printk(KERN_DEBUG "SA-1111 not detected: ID = %08lx\n", id);
+ ret = -ENODEV;
+ goto release;
}
+ printk(KERN_INFO "SA-1111 Microprocessor Companion Chip: "
+ "silicon revision %lx, metal revision %lx\n",
+ (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
+
+ return 0;
+
+ release:
+ release_resource(&sa1111_resource);
+ out:
return ret;
}
@@ -175,6 +232,10 @@ int __init sa1111_probe(void)
*/
void sa1111_wake(void)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
/*
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
* (SA-1110 Developer's Manual, section 9.1.2.1)
@@ -210,6 +271,8 @@ void sa1111_wake(void)
* Ensure all clocks are initially off.
*/
SKPCR = 0;
+
+ local_irq_restore(flags);
}
void sa1111_doze(void)
@@ -242,12 +305,17 @@ void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency
*/
void __init sa1110_mb_disable(void)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
PGSR &= ~GPIO_MBGNT;
GPCR = GPIO_MBGNT;
GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
GAFR &= ~(GPIO_MBGNT | GPIO_MBREQ);
+ local_irq_restore(flags);
}
/*
@@ -256,10 +324,85 @@ void __init sa1110_mb_disable(void)
*/
void __init sa1110_mb_enable(void)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
PGSR &= ~GPIO_MBGNT;
GPCR = GPIO_MBGNT;
GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
GAFR |= (GPIO_MBGNT | GPIO_MBREQ);
TUCR |= TUCR_MR;
+
+ local_irq_restore(flags);
}
+
+EXPORT_SYMBOL(sa1111_wake);
+EXPORT_SYMBOL(sa1111_doze);
+
+/* According to the "Intel StrongARM SA-1111 Microprocessor Companion
+ * Chip Specification Update" (June 2000), erratum #7, there is a
+ * significant bug in Serial Audio Controller DMA. If the SAC is
+ * accessing a region of memory above 1MB relative to the bank base,
+ * it is important that address bit 10 _NOT_ be asserted. Depending
+ * on the configuration of the RAM, bit 10 may correspond to one
+ * of several different (processor-relative) address bits.
+ *
+ * This routine only identifies whether or not a given DMA address
+ * is susceptible to the bug.
+ */
+int sa1111_check_dma_bug(dma_addr_t addr)
+{
+ unsigned int physaddr=SA1111_DMA_ADDR((unsigned int)addr);
+
+ /* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
+ * User's Guide" mentions that jumpers R51 and R52 control the
+ * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
+ * SDRAM bank 1 on Neponset). The default configuration selects
+ * Assabet, so any address in bank 1 is necessarily invalid.
+ */
+ if ((machine_is_assabet() || machine_is_pfs168()) && addr >= 0xc8000000)
+ return -1;
+
+ /* The bug only applies to buffers located more than one megabyte
+ * above the start of the target bank:
+ */
+ if (physaddr<(1<<20))
+ return 0;
+
+ switch (FExtr(SBI_SMCR, SMCR_DRAC)) {
+ case 01: /* 10 row + bank address bits, A<20> must not be set */
+ if (physaddr & (1<<20))
+ return -1;
+ break;
+ case 02: /* 11 row + bank address bits, A<23> must not be set */
+ if (physaddr & (1<<23))
+ return -1;
+ break;
+ case 03: /* 12 row + bank address bits, A<24> must not be set */
+ if (physaddr & (1<<24))
+ return -1;
+ break;
+ case 04: /* 13 row + bank address bits, A<25> must not be set */
+ if (physaddr & (1<<25))
+ return -1;
+ break;
+ case 05: /* 14 row + bank address bits, A<20> must not be set */
+ if (physaddr & (1<<20))
+ return -1;
+ break;
+ case 06: /* 15 row + bank address bits, A<20> must not be set */
+ if (physaddr & (1<<20))
+ return -1;
+ break;
+ default:
+ printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%lo\n",
+ __FUNCTION__, FExtr(SBI_SMCR, SMCR_DRAC));
+ return -1;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL(sa1111_check_dma_bug);
diff --git a/arch/arm/mach-sa1100/sa1111.h b/arch/arm/mach-sa1100/sa1111.h
index c26034771..52a44f928 100644
--- a/arch/arm/mach-sa1100/sa1111.h
+++ b/arch/arm/mach-sa1100/sa1111.h
@@ -11,7 +11,7 @@ extern void sa1110_mb_disable(void);
/*
* Probe for a SA1111 chip.
*/
-extern int sa1111_probe(void);
+extern int sa1111_probe(unsigned long phys);
/*
* Wake up a SA1111 chip.
@@ -30,5 +30,5 @@ extern void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_
extern void sa1111_init_irq(int irq_nr);
-extern void sa1111_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs );
+extern void sa1111_IRQ_demux(int irq, void *dev_id, struct pt_regs *regs);
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
new file mode 100644
index 000000000..5b9f5b22f
--- /dev/null
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -0,0 +1,40 @@
+/*
+ * linux/arch/arm/mach-sa1100/shannon.c
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include "generic.h"
+
+
+static void __init shannon_map_io(void)
+{
+ sa1100_map_io();
+
+ sa1100_register_uart(0, 3);
+ sa1100_register_uart(1, 1);
+ Ser1SDCR0 |= SDCR0_SUS;
+ GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
+ GPDR |= GPIO_UART_TXD;
+ GPDR &= ~GPIO_UART_RXD;
+ PPAR |= PPAR_UPR;
+
+ set_GPIO_IRQ_edge(SHANNON_GPIO_IRQ_CODEC);
+}
+
+MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ BOOT_PARAMS(0xc0000100)
+ MAPIO(shannon_map_io)
+ INITIRQ(sa1100_init_irq)
+MACHINE_END
diff --git a/arch/arm/mach-sa1100/sherman.c b/arch/arm/mach-sa1100/sherman.c
index 254ac3af4..658d16423 100644
--- a/arch/arm/mach-sa1100/sherman.c
+++ b/arch/arm/mach-sa1100/sherman.c
@@ -29,16 +29,9 @@ fixup_sherman(struct machine_desc *desc, struct param_struct *params,
// setup_initrd( 0xc0400000, 8*1024*1024 );
}
-static struct map_desc sherman_io_desc[] __initdata = {
- /* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash*/
- LAST_DESC
-};
-
static void __init sherman_map_io(void)
{
sa1100_map_io();
- iotable_init(sherman_io_desc);
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 0dec67128..514d6ca37 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -23,18 +23,6 @@
long cs3_shadow;
-static int __init simpad_init(void)
-{
- PSPR = 0xc0008000;
- GPDR &= ~GPIO_GPIO0;
- cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
- ENABLE_5V | RESET_SIMCARD);
- *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
- return 0;
-}
-
-__initcall(simpad_init);
-
long get_cs3_shadow()
{
return cs3_shadow;
@@ -70,7 +58,6 @@ fixup_simpad(struct machine_desc *desc, struct param_struct *params,
static struct map_desc simpad_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 },
{ 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
{ 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Paules CS3, write only */
LAST_DESC
@@ -96,11 +83,17 @@ static void __init simpad_map_io(void)
sa1100_map_io();
iotable_init(simpad_io_desc);
-#ifndef CONFIG_SERIAL_SA1100_OLD
+ PSPR = 0xc0008000;
+ GPDR &= ~GPIO_GPIO0;
+ cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
+ ENABLE_5V | RESET_SIMCARD);
+ *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+
//It is only possible to register 3 UART in serial_sa1100.c
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
-#endif
+
+ set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ);
}
#ifdef CONFIG_PROC_FS
diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S
index a7c633661..2b5e81e08 100644
--- a/arch/arm/mach-sa1100/sleep.S
+++ b/arch/arm/mach-sa1100/sleep.S
@@ -176,7 +176,7 @@ sa1110_sdram_controller_fix:
ENTRY(sa1100_cpu_resume)
@ set SVC, irqs off
- mov r0, #I_BIT | MODE_SVC
+ mov r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
msr cpsr_c, r0
@ load physical address of sleep_save
diff --git a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
new file mode 100644
index 000000000..028558a56
--- /dev/null
+++ b/arch/arm/mach-sa1100/system3.c
@@ -0,0 +1,479 @@
+/*
+ * linux/arch/arm/mach-sa1100/system3.c
+ *
+ * Copyright (C) 2001 Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>
+ *
+ * $Id: system3.c,v 1.1.6.1 2001/12/04 17:28:06 seletz Exp $
+ *
+ * This file contains all PT Sytsem 3 tweaks. Based on original work from
+ * Nicolas Pitre's assabet fixes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * $Log: system3.c,v $
+ * Revision 1.1.6.1 2001/12/04 17:28:06 seletz
+ * - merged from previous branch
+ *
+ * Revision 1.1.4.3 2001/12/04 15:16:31 seletz
+ * - merged from linux_2_4_13_ac5_rmk2
+ *
+ * Revision 1.1.4.2 2001/11/19 17:18:57 seletz
+ * - more code cleanups
+ *
+ * Revision 1.1.4.1 2001/11/16 13:52:05 seletz
+ * - PT Digital Board Support Code
+ *
+ * Revision 1.1.2.2 2001/11/05 16:46:18 seletz
+ * - cleanups
+ *
+ * Revision 1.1.2.1 2001/10/15 16:00:43 seletz
+ * - first revision working with new board
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/cpufreq.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <asm/arch/irq.h>
+
+#include <linux/serial_core.h>
+
+#include "generic.h"
+#include "sa1111.h"
+
+#define DEBUG 1
+
+#ifdef DEBUG
+# define DPRINTK( x, args... ) printk( "%s: line %d: "x, __FUNCTION__, __LINE__, ## args );
+#else
+# define DPRINTK( x, args... ) /* nix */
+#endif
+
+/**********************************************************************
+ * prototypes
+ */
+
+/* init funcs */
+static void __init fixup_system3(struct machine_desc *desc,
+ struct param_struct *params, char **cmdline, struct meminfo *mi);
+static void __init get_system3_scr(void);
+static int __init system3_init(void);
+static void __init system3_init_irq(void);
+static void __init system3_map_io(void);
+
+static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs );
+static int system3_get_mctrl(struct uart_port *port);
+static void system3_set_mctrl(struct uart_port *port, u_int mctrl);
+static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
+static int sdram_notifier(struct notifier_block *nb, unsigned long event, void *data);
+
+static int system3_lcd_power(int on);
+static int system3_backlight_power(int on);
+
+extern void convert_to_tag_list(struct param_struct *params, int mem_init);
+
+
+/**********************************************************************
+ * global data
+ */
+
+/**********************************************************************
+ * static data
+ */
+
+static struct map_desc system3_io_desc[] __initdata = {
+ /* virtual physical length domain r w c b */
+ { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
+ { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ LAST_DESC
+};
+
+static struct sa1100_port_fns system3_port_fns __initdata = {
+ set_mctrl: system3_set_mctrl,
+ get_mctrl: system3_get_mctrl,
+ pm: system3_uart_pm,
+};
+
+static struct irqaction system3_irq = {
+ name: "PT Digital Board SA1111 IRQ",
+ handler: system3_IRQ_demux,
+ flags: SA_INTERRUPT
+};
+
+static struct notifier_block system3_clkchg_block = {
+ notifier_call: sdram_notifier,
+};
+
+/**********************************************************************
+ * Static functions
+ */
+
+static void __init system3_map_io(void)
+{
+ DPRINTK( "%s\n", "START" );
+ sa1100_map_io();
+ iotable_init(system3_io_desc);
+
+ sa1100_register_uart_fns(&system3_port_fns);
+ sa1100_register_uart(0, 1); /* com port */
+ sa1100_register_uart(1, 2);
+ sa1100_register_uart(2, 3); /* radio module */
+
+ Ser1SDCR0 |= SDCR0_SUS;
+}
+
+
+/*********************************************************************
+ * Install IRQ handler
+ */
+static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+{
+ u_char irr;
+
+ for(;;){
+ //irr = PTCPLD_REG_IRQSR & (PT_IRQ_LAN | PT_IRQ_USAR | PT_IRQ_SA1111);
+ irr = PT_IRQSR & (PT_IRQ_LAN | PT_IRQ_SA1111);
+
+ irr ^= (PT_IRQ_LAN);
+ if (!irr) break;
+
+ if( irr & PT_IRQ_LAN )
+ do_IRQ(IRQ_SYSTEM3_SMC9196, regs);
+
+#if 0
+ /* Highspeed Serial Bus not yet used */
+ if( irr & PT_IRQ_USAR )
+ do_IRQ(PT_USAR_IRQ, regs);
+#endif
+
+ if( irr & PT_IRQ_SA1111 )
+ sa1111_IRQ_demux(irq, dev_id, regs);
+ }
+}
+
+
+static void __init system3_init_irq(void)
+{
+ int irq;
+
+ DPRINTK( "%s\n", "START" );
+
+ /* SA1111 IRQ not routed to a GPIO. */
+ sa1111_init_irq(-1);
+
+ /* setup extra IRQs */
+ irq = IRQ_SYSTEM3_SMC9196;
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+
+#if 0
+ /* Highspeed Serial Bus not yet used */
+ irq = PT_USAR_IRQ;
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+#endif
+
+ /* IRQ by CPLD */
+ set_GPIO_IRQ_edge( GPIO_GPIO(25), GPIO_RISING_EDGE );
+ setup_arm_irq( IRQ_GPIO25, &system3_irq );
+}
+
+/**********************************************************************
+ * On system 3 limit cpu frequency to 206 Mhz
+ */
+static int sdram_notifier(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ switch (event) {
+ case CPUFREQ_MINMAX:
+ cpufreq_updateminmax(data, 147500, 206000);
+ break;
+
+ }
+ return 0;
+}
+
+/**
+ * fixup_system3 - fixup function for system 3 board
+ * @desc: machine description
+ * @param: kernel params
+ * @cmdline: kernel cmdline
+ * @mi: memory info struct
+ *
+ */
+static void __init fixup_system3(struct machine_desc *desc,
+ struct param_struct *params, char **cmdline, struct meminfo *mi)
+{
+ DPRINTK( "%s\n", "START" );
+
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+ setup_ramdisk( 1, 0, 0, 8192 );
+ setup_initrd( 0xc0800000, 8*1024*1024 );
+}
+
+
+/**
+ * system3_uart_pm - powermgmt callback function for system 3 UART
+ * @port: uart port structure
+ * @state: pm state
+ * @oldstate: old pm state
+ *
+ */
+static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
+{
+ /* TODO: switch on/off uart in powersave mode */
+}
+
+/*
+ * Note! this can be called from IRQ context.
+ * FIXME: Handle PT Digital Board CTRL regs irq-safe.
+ *
+ * NB: system3 uses COM_RTS and COM_DTR for both UART1 (com port)
+ * and UART3 (radio module). We only handle them for UART1 here.
+ */
+static void system3_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ if (port->mapbase == _Ser1UTCR0) {
+ u_int set = 0, clear = 0;
+
+ if (mctrl & TIOCM_RTS)
+ set |= PT_CTRL2_RS1_RTS;
+ else
+ clear |= PT_CTRL2_RS1_RTS;
+
+ if (mctrl & TIOCM_DTR)
+ set |= PT_CTRL2_RS1_DTR;
+ else
+ clear |= PT_CTRL2_RS1_DTR;
+
+ PTCTRL2_clear(clear);
+ PTCTRL2_set(set);
+ }
+}
+
+static int system3_get_mctrl(struct uart_port *port)
+{
+ u_int ret = 0;
+ u_int irqsr = PT_IRQSR;
+
+ /* need 2 reads to read current value */
+ irqsr = PT_IRQSR;
+
+ /* TODO: check IRQ source register for modem/com
+ status lines and set them correctly. */
+
+ ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
+
+ return ret;
+}
+
+/**
+ * system3_lcd_backlight_on - switch system 3 lcd backlight on
+ *
+ */
+int system3_lcd_backlight_on( void )
+{
+ PTCTRL0_set( PT_CTRL0_LCD_BL );
+ return 0;
+}
+
+/**
+ * system3_lcd_backlight_off - switch system 3 lcd backlight off
+ *
+ */
+static void system3_lcd_backlight_off(void)
+{
+ PTCTRL0_clear( PT_CTRL0_LCD_BL );
+}
+
+/**
+ * system3_lcd_on - switch system 3 lcd on
+ *
+ */
+static void system3_lcd_on(void)
+{
+ DPRINTK( "%s\n", "START" );
+ PTCTRL0_set( PT_CTRL0_LCD_EN );
+
+ /* brightness / contrast */
+ SKPCR |= SKPCR_PWMCLKEN;
+ PB_DDR = 0xFFFFFFFF;
+ SKPEN0 = 1;
+ SKPEN1 = 1;
+}
+
+/**
+ * system3_lcd_off - switch system 3 lcd off
+ *
+ */
+static void system3_lcd_off(void)
+{
+ DPRINTK( "%s\n", "START" );
+ PTCTRL0_clear( PT_CTRL0_LCD_EN );
+ SKPEN0 = 0;
+ SKPEN1 = 0;
+ SKPCR &= ~SKPCR_PWMCLKEN;
+}
+
+/**
+ * system3_lcd_contrast - set system 3 contrast
+ * @value: the new contrast
+ *
+ */
+static void system3_lcd_contrast(unsigned char value)
+{
+ DPRINTK( "value=0x%02x\n", value );
+ SYS3LCDCONTR = value;
+}
+
+/**
+ * system3_lcd_brightness - set system 3 brightness
+ * @value: the new brightness
+ *
+ */
+static void system3_lcd_brightness(unsigned char value)
+{
+ DPRINTK( "value=0x%02x\n", value );
+ SYS3LCDBRIGHT = value;
+}
+
+static void system3_lcd_power(int on)
+{
+#error why is backlight stuff here???
+ if (on) {
+ system3_lcd_on();
+ system3_lcd_backlight_on();
+ system3_lcd_contrast(0x95);
+ system3_lcd_brightness(240);
+ } else {
+ system3_lcd_off();
+ }
+}
+
+static void system3_backlight_power(int on)
+{
+ if (on) {
+ system3_lcd_backlight_on();
+ system3_lcd_contrast(0x95);
+ system3_lcd_brightness(240);
+ } else {
+ system3_lcd_backlight_off();
+ }
+}
+
+static int __init system3_init(void)
+{
+ int ret = 0;
+ DPRINTK( "%s\n", "START" );
+
+ if ( !machine_is_pt_system3() ) {
+ ret = -EINVAL;
+ goto DONE;
+ }
+
+ sa1100fb_lcd_power = system3_lcd_power;
+ sa1100fb_backlight_power = system3_backlight_power;
+
+ /* init control register */
+ PT_CTRL0 = PT_CTRL0_INIT;
+ PT_CTRL1 = 0x02;
+ PT_CTRL2 = 0x00;
+ DPRINTK( "CTRL[0]=0x%02x\n", PT_CTRL0 );
+ DPRINTK( "CTRL[1]=0x%02x\n", PT_CTRL1 );
+ DPRINTK( "CTRL[2]=0x%02x\n", PT_CTRL2 );
+
+ /*
+ * Ensure that the memory bus request/grant signals are setup,
+ * and the grant is held in its inactive state.
+ */
+ sa1110_mb_disable();
+
+ /*
+ * Probe for a SA1111.
+ */
+ ret = sa1111_probe(0x40000000);
+ if (ret < 0) {
+ printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" );
+ goto DONE;
+ }
+
+ /*
+ * We found it. Wake the chip up.
+ */
+ sa1111_wake();
+
+ /*
+ * The SDRAM configuration of the SA1110 and the SA1111 must
+ * match. This is very important to ensure that SA1111 accesses
+ * don't corrupt the SDRAM. Note that this ungates the SA1111's
+ * MBGNT signal, so we must have called sa1110_mb_disable()
+ * beforehand.
+ */
+ sa1111_configure_smc(1,
+ FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
+ FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
+
+ /*
+ * We only need to turn on DCLK whenever we want to use the
+ * DMA. It can otherwise be held firmly in the off position.
+ */
+ SKPCR |= SKPCR_DCLKEN;
+
+ /*
+ * Enable the SA1110 memory bus request and grant signals.
+ */
+ sa1110_mb_enable();
+
+ system3_init_irq();
+
+#if defined( CONFIG_CPU_FREQ )
+ ret = cpufreq_register_notifier(&system3_clkchg_block);
+ if ( ret != 0 ) {
+ printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" );
+ goto DONE;
+ }
+#endif
+
+ ret = 0;
+DONE:
+ DPRINTK( "ret=%d\n", ret );
+ return ret;
+}
+
+/**********************************************************************
+ * Exported Functions
+ */
+
+/**********************************************************************
+ * kernel magic macros
+ */
+__initcall(system3_init);
+
+MACHINE_START(PT_SYSTEM3, "PT System 3")
+ BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+ BOOT_PARAMS(0xc0000100)
+ FIXUP(fixup_system3)
+ MAPIO(system3_map_io)
+ INITIRQ(sa1100_init_irq)
+MACHINE_END
diff --git a/arch/arm/mach-sa1100/xp860.c b/arch/arm/mach-sa1100/xp860.c
index 89d54d7c0..4e9f38b56 100644
--- a/arch/arm/mach-sa1100/xp860.c
+++ b/arch/arm/mach-sa1100/xp860.c
@@ -7,6 +7,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/tty.h>
+#include <linux/ioport.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@@ -21,6 +22,7 @@
static void xp860_power_off(void)
{
+ cli();
GPDR |= GPIO_GPIO20;
GPSR = GPIO_GPIO20;
mdelay(1000);
@@ -40,7 +42,7 @@ static int __init xp860_init(void)
/*
* Probe for SA1111.
*/
- ret = sa1111_probe();
+ ret = sa1111_probe(0x40000000);
if (ret < 0)
return ret;
diff --git a/arch/arm/mach-sa1100/yopy.c b/arch/arm/mach-sa1100/yopy.c
index 0441c9bea..770636e14 100644
--- a/arch/arm/mach-sa1100/yopy.c
+++ b/arch/arm/mach-sa1100/yopy.c
@@ -52,14 +52,16 @@ EXPORT_SYMBOL(yopy_gpio_set);
static int __init yopy_hw_init(void)
{
- YOPY_EGPIO = yopy_egpio;
+ if (machine_is_yopy()) {
+ YOPY_EGPIO = yopy_egpio;
- /* Enable Output */
- PPDR |= PPC_L_BIAS;
- PSDR &= ~PPC_L_BIAS;
- PPSR |= PPC_L_BIAS;
+ /* Enable Output */
+ PPDR |= PPC_L_BIAS;
+ PSDR &= ~PPC_L_BIAS;
+ PPSR |= PPC_L_BIAS;
- YOPY_EGPIO = yopy_egpio;
+ YOPY_EGPIO = yopy_egpio;
+ }
return 0;
}
@@ -82,6 +84,8 @@ static void __init yopy_map_io(void)
iotable_init(yopy_io_desc);
sa1100_register_uart(0, 3);
+
+ set_GPIO_IRQ_edge(GPIO_UCB1200_IRQ, GPIO_RISING_EDGE);
}
diff --git a/arch/arm/mach-shark/Makefile b/arch/arm/mach-shark/Makefile
index b813d1a8b..d82c44316 100644
--- a/arch/arm/mach-shark/Makefile
+++ b/arch/arm/mach-shark/Makefile
@@ -11,7 +11,7 @@ O_TARGET := shark.o
# Object file lists.
-obj-y := arch.o dma.o mm.o pci.o
+obj-y := core.o dma.o irq.o pci.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-shark/arch.c b/arch/arm/mach-shark/core.c
index 2249e6a92..1e89a8dc1 100644
--- a/arch/arm/mach-shark/arch.c
+++ b/arch/arm/mach-shark/core.c
@@ -6,22 +6,36 @@
#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
#include <linux/init.h>
-#include <asm/hardware/dec21285.h>
#include <asm/elf.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
#include <asm/mach/arch.h>
-extern void shark_map_io(void);
-extern void genarch_init_irq(void);
+extern void shark_init_irq(void);
+
+static struct map_desc shark_io_desc[] __initdata = {
+ { IO_BASE , IO_START , IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+static void __init shark_map_io(void)
+{
+ iotable_init(shark_io_desc);
+}
MACHINE_START(SHARK, "Shark")
MAINTAINER("Alexander Schulz")
BOOT_MEM(0x08000000, 0x40000000, 0xe0000000)
BOOT_PARAMS(0x08003000)
MAPIO(shark_map_io)
- INITIRQ(genarch_init_irq)
+ INITIRQ(shark_init_irq)
MACHINE_END
diff --git a/arch/arm/mach-shark/irq.c b/arch/arm/mach-shark/irq.c
new file mode 100644
index 000000000..5ca894ae3
--- /dev/null
+++ b/arch/arm/mach-shark/irq.c
@@ -0,0 +1,124 @@
+/*
+ * linux/arch/arm/mach-shark/irq.c
+ *
+ * by Alexander Schulz
+ *
+ * derived from linux/arch/ppc/kernel/i8259.c and:
+ * include/asm-arm/arch-ebsa110/irq.h
+ * Copyright (C) 1996-1998 Russell King
+ */
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+
+/*
+ * 8259A PIC functions to handle ISA devices:
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ * Let through the cascade-interrupt no. 2 (ff-(1<<2)==fb)
+ */
+static unsigned char cached_irq_mask[2] = { 0xfb, 0xff };
+
+/*
+ * These have to be protected by the irq controller spinlock
+ * before being called.
+ */
+static void shark_disable_8259A_irq(unsigned int irq)
+{
+ unsigned int mask;
+ if (irq<8) {
+ mask = 1 << irq;
+ cached_irq_mask[0] |= mask;
+ } else {
+ mask = 1 << (irq-8);
+ cached_irq_mask[1] |= mask;
+ }
+ outb(cached_irq_mask[1],0xA1);
+ outb(cached_irq_mask[0],0x21);
+}
+
+static void shark_enable_8259A_irq(unsigned int irq)
+{
+ unsigned int mask;
+ if (irq<8) {
+ mask = ~(1 << irq);
+ cached_irq_mask[0] &= mask;
+ } else {
+ mask = ~(1 << (irq-8));
+ cached_irq_mask[1] &= mask;
+ }
+ outb(cached_irq_mask[1],0xA1);
+ outb(cached_irq_mask[0],0x21);
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+static void shark_mask_and_ack_8259A_irq(unsigned int irq)
+{
+ if (irq & 8) {
+ cached_irq_mask[1] |= 1 << (irq-8);
+ inb(0xA1); /* DUMMY */
+ outb(cached_irq_mask[1],0xA1);
+ } else {
+ cached_irq_mask[0] |= 1 << irq;
+ outb(cached_irq_mask[0],0x21);
+ }
+}
+
+static void bogus_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ printk("Got interrupt %i!\n",irq);
+}
+
+static struct irqaction cascade;
+
+void __init shark_init_irq(void)
+{
+ int irq;
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = shark_mask_and_ack_8259A_irq;
+ irq_desc[irq].mask = shark_disable_8259A_irq;
+ irq_desc[irq].unmask = shark_enable_8259A_irq;
+ }
+
+ /* The PICs are initialized to level triggered and auto eoi!
+ * If they are set to edge triggered they lose some IRQs,
+ * if they are set to manual eoi they get locked up after
+ * a short time
+ */
+
+ /* init master interrupt controller */
+ outb(0x19, 0x20); /* Start init sequence, level triggered */
+ outb(0x00, 0x21); /* Vector base */
+ outb(0x04, 0x21); /* Cascade (slave) on IRQ2 */
+ outb(0x03, 0x21); /* Select 8086 mode , auto eoi*/
+ outb(0x0A, 0x20);
+ /* init slave interrupt controller */
+ outb(0x19, 0xA0); /* Start init sequence, level triggered */
+ outb(0x08, 0xA1); /* Vector base */
+ outb(0x02, 0xA1); /* Cascade (slave) on IRQ2 */
+ outb(0x03, 0xA1); /* Select 8086 mode, auto eoi */
+ outb(0x0A, 0xA0);
+ outb(cached_irq_mask[1],0xA1);
+ outb(cached_irq_mask[0],0x21);
+ //request_region(0x20,0x2,"pic1");
+ //request_region(0xA0,0x2,"pic2");
+
+ cascade.handler = bogus_int;
+ cascade.flags = 0;
+ cascade.mask = 0;
+ cascade.name = "cascade";
+ cascade.next = NULL;
+ cascade.dev_id = NULL;
+ setup_arm_irq(2,&cascade);
+}
+
diff --git a/arch/arm/mach-shark/mm.c b/arch/arm/mach-shark/mm.c
deleted file mode 100644
index ec1cbe3ff..000000000
--- a/arch/arm/mach-shark/mm.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * linux/arch/arm/mach-shark/mm.c
- *
- * by Alexander Schulz
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/io.h>
-
-#include <asm/mach/map.h>
-
-static struct map_desc shark_io_desc[] __initdata = {
- { IO_BASE , IO_START , IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
- LAST_DESC
-};
-
-void __init shark_map_io(void)
-{
- iotable_init(shark_io_desc);
-}
diff --git a/arch/arm/mach-tbox/Makefile b/arch/arm/mach-tbox/Makefile
new file mode 100644
index 000000000..6103debb3
--- /dev/null
+++ b/arch/arm/mach-tbox/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET := tbox.o
+
+# Object file lists.
+
+obj-y := core.o
+obj-m :=
+obj-n :=
+obj- :=
+
+export-objs :=
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/arm/mach-tbox/core.c b/arch/arm/mach-tbox/core.c
new file mode 100644
index 000000000..ee0fa6ed0
--- /dev/null
+++ b/arch/arm/mach-tbox/core.c
@@ -0,0 +1,75 @@
+/*
+ * linux/arch/arm/mm/mm-tbox.c
+ *
+ * Copyright (C) 1998, 1999, 2000 Phil Blundell
+ * Copyright (C) 1998-1999 Russell King
+ *
+ * Extra MM routines for the Tbox architecture
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/elf.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+extern unsigned long soft_irq_mask;
+
+static void tbox_mask_irq(unsigned int irq)
+{
+ __raw_writel(0, INTCONT + (irq << 2));
+ soft_irq_mask &= ~(1<<irq);
+}
+
+static void tbox_unmask_irq(unsigned int irq)
+{
+ soft_irq_mask |= (1<<irq);
+ __raw_writel(1, INTCONT + (irq << 2));
+}
+
+static void tbox_init_irq(void)
+{
+ unsigned int i;
+
+ /* Disable all interrupts initially. */
+ for (i = 0; i < NR_IRQS; i++) {
+ if (i <= 10 || (i >= 12 && i <= 13)) {
+ irq_desc[i].valid = 1;
+ irq_desc[i].probe_ok = 0;
+ irq_desc[i].mask_ack = tbox_mask_irq;
+ irq_desc[i].mask = tbox_mask_irq;
+ irq_desc[i].unmask = tbox_unmask_irq;
+ tbox_mask_irq(i);
+ } else {
+ irq_desc[i].valid = 0;
+ irq_desc[i].probe_ok = 0;
+ }
+ }
+}
+
+static struct map_desc tbox_io_desc[] __initdata = {
+ /* See hardware.h for details */
+ { IO_BASE, IO_START, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+static void __init tbox_map_io(void)
+{
+ iotable_init(tbox_io_desc);
+}
+
+MACHINE_START(TBOX, "unknown-TBOX")
+ MAINTAINER("Philip Blundell")
+ BOOT_MEM(0x80000000, 0x00400000, 0xe0000000)
+ MAPIO(tbox_map_io)
+ INITIRQ(tbox_init_irq)
+MACHINE_END
+
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index b9282be0d..a612d027d 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -13,38 +13,32 @@ O_TARGET := mm.o
# Object file lists.
-obj-y := init.o
+obj-y := init.o extable.o fault-common.o
obj-m :=
obj-n :=
obj- :=
export-objs := proc-syms.o discontig.o
-cpu32-y := consistent.o fault-armv.o ioremap.o mm-armv.o
-cpu32-$(CONFIG_MODULES) += proc-syms.o
-
-obj-y += extable.o fault-common.o
-obj-$(CONFIG_CPU_26) += fault-armo.o mm-armo.o small_page.o
-obj-$(CONFIG_CPU_32) += $(cpu32-y)
+ifeq ($(CONFIG_CPU_32),y)
+obj-y += consistent.o fault-armv.o ioremap.o mm-armv.o
+obj-$(CONFIG_MODULES) += proc-syms.o
+endif
+obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
obj-$(CONFIG_DISCONTIGMEM) += discontig.o
# Select the processor-specific files
p-$(CONFIG_CPU_26) += proc-arm2,3.o
p-$(CONFIG_CPU_ARM610) += proc-arm6,7.o
p-$(CONFIG_CPU_ARM710) += proc-arm6,7.o
-p-$(CONFIG_CPU_ARM720T) += proc-arm720.o
-p-$(CONFIG_CPU_ARM920T) += proc-arm920.o
-p-$(CONFIG_CPU_ARM926T) += proc-arm926.o
-p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o
-p-$(CONFIG_CPU_SA110) += proc-sa110.o
-p-$(CONFIG_CPU_SA1100) += proc-sa110.o
-
-# Integrator follows "new style"
-# Soon, others will do too, and we can get rid of this
-MMMACH := mm-$(MACHINE).c
-ifeq ($(MMMACH),$(wildcard $(MMMACH)))
-obj-$(CONFIG_CPU_32) += $(MMMACH:.c=.o)
-endif
+p-$(CONFIG_CPU_ARM720T) += proc-arm720.o armv4t-late-abort.o
+p-$(CONFIG_CPU_ARM920T) += proc-arm920.o armv4t-early-abort.o
+p-$(CONFIG_CPU_ARM922T) += proc-arm922.o armv4t-early-abort.o
+p-$(CONFIG_CPU_ARM926T) += proc-arm926.o armv5ej-early-abort.o
+p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o armv4t-early-abort.o
+p-$(CONFIG_CPU_SA110) += proc-sa110.o armv4-early-abort.o
+p-$(CONFIG_CPU_SA1100) += proc-sa110.o armv4-early-abort.o minicache.o
+p-$(CONFIG_CPU_XSCALE) += proc-xscale.o armv4t-early-abort.o minicache.o
obj-y += $(sort $(p-y))
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
new file mode 100644
index 000000000..6ff2d5385
--- /dev/null
+++ b/arch/arm/mm/alignment.c
@@ -0,0 +1,578 @@
+/*
+ * linux/arch/arm/mm/alignment.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Modifications for ARM processor (c) 1995-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/bitops.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/unaligned.h>
+
+/*
+ * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
+ * /proc/sys/debug/alignment, modified and integrated into
+ * Linux 2.1 by Russell King
+ *
+ * Speed optimisations and better fault handling by Russell King.
+ *
+ * *** NOTE ***
+ * This code is not portable to processors with late data abort handling.
+ */
+#define CODING_BITS(i) (i & 0x0e000000)
+
+#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */
+#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */
+#define LDST_U_BIT(i) (i & (1 << 23)) /* Add offset */
+#define LDST_W_BIT(i) (i & (1 << 21)) /* Writeback */
+#define LDST_L_BIT(i) (i & (1 << 20)) /* Load */
+
+#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
+
+#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */
+#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
+
+#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
+#define RD_BITS(i) ((i >> 12) & 15) /* Rd */
+#define RM_BITS(i) (i & 15) /* Rm */
+
+#define REGMASK_BITS(i) (i & 0xffff)
+#define OFFSET_BITS(i) (i & 0x0fff)
+
+#define IS_SHIFT(i) (i & 0x0ff0)
+#define SHIFT_BITS(i) ((i >> 7) & 0x1f)
+#define SHIFT_TYPE(i) (i & 0x60)
+#define SHIFT_LSL 0x00
+#define SHIFT_LSR 0x20
+#define SHIFT_ASR 0x40
+#define SHIFT_RORRRX 0x60
+
+static unsigned long ai_user;
+static unsigned long ai_sys;
+static unsigned long ai_skipped;
+static unsigned long ai_half;
+static unsigned long ai_word;
+static unsigned long ai_multi;
+static int ai_usermode;
+
+#ifdef CONFIG_PROC_FS
+static const char *usermode_action[] = {
+ "ignored",
+ "warn",
+ "fixup",
+ "fixup+warn",
+ "signal",
+ "signal+warn"
+};
+
+static int
+proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
+ void *data)
+{
+ char *p = page;
+ int len;
+
+ p += sprintf(p, "User:\t\t%lu\n", ai_user);
+ p += sprintf(p, "System:\t\t%lu\n", ai_sys);
+ p += sprintf(p, "Skipped:\t%lu\n", ai_skipped);
+ p += sprintf(p, "Half:\t\t%lu\n", ai_half);
+ p += sprintf(p, "Word:\t\t%lu\n", ai_word);
+ p += sprintf(p, "Multi:\t\t%lu\n", ai_multi);
+ p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode,
+ usermode_action[ai_usermode]);
+
+ len = (p - page) - off;
+ if (len < 0)
+ len = 0;
+
+ *eof = (len <= count) ? 1 : 0;
+ *start = page + off;
+
+ return len;
+}
+
+static int proc_alignment_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int mode;
+
+ if (count > 0) {
+ if (get_user(mode, buffer))
+ return -EFAULT;
+ if (mode >= '0' && mode <= '5')
+ ai_usermode = mode - '0';
+ }
+ return count;
+}
+
+/*
+ * This needs to be done after sysctl_init, otherwise sys/ will be
+ * overwritten. Actually, this shouldn't be in sys/ at all since
+ * it isn't a sysctl, and it doesn't contain sysctl information.
+ * We now locate it in /proc/cpu/alignment instead.
+ */
+static int __init alignment_init(void)
+{
+ struct proc_dir_entry *res;
+
+ res = proc_mkdir("cpu", NULL);
+ if (!res)
+ return -ENOMEM;
+
+ res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
+ if (!res)
+ return -ENOMEM;
+
+ res->read_proc = proc_alignment_read;
+ res->write_proc = proc_alignment_write;
+
+ return 0;
+}
+
+__initcall(alignment_init);
+#endif /* CONFIG_PROC_FS */
+
+union offset_union {
+ unsigned long un;
+ signed long sn;
+};
+
+#define TYPE_ERROR 0
+#define TYPE_FAULT 1
+#define TYPE_LDST 2
+#define TYPE_DONE 3
+
+#define get8_unaligned_check(val,addr,err) \
+ __asm__( \
+ "1: ldrb %1, [%2], #1\n" \
+ "2:\n" \
+ " .section .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "3: mov %0, #1\n" \
+ " b 2b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 3b\n" \
+ " .previous\n" \
+ : "=r" (err), "=&r" (val), "=r" (addr) \
+ : "0" (err), "2" (addr))
+
+#define get8t_unaligned_check(val,addr,err) \
+ __asm__( \
+ "1: ldrbt %1, [%2], #1\n" \
+ "2:\n" \
+ " .section .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "3: mov %0, #1\n" \
+ " b 2b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 3b\n" \
+ " .previous\n" \
+ : "=r" (err), "=&r" (val), "=r" (addr) \
+ : "0" (err), "2" (addr))
+
+#define get16_unaligned_check(val,addr) \
+ do { \
+ unsigned int err = 0, v, a = addr; \
+ get8_unaligned_check(val,a,err); \
+ get8_unaligned_check(v,a,err); \
+ val |= v << 8; \
+ if (err) \
+ goto fault; \
+ } while (0)
+
+#define put16_unaligned_check(val,addr) \
+ do { \
+ unsigned int err = 0, v = val, a = addr; \
+ __asm__( \
+ "1: strb %1, [%2], #1\n" \
+ " mov %1, %1, lsr #8\n" \
+ "2: strb %1, [%2]\n" \
+ "3:\n" \
+ " .section .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "4: mov %0, #1\n" \
+ " b 3b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 4b\n" \
+ " .long 2b, 4b\n" \
+ " .previous\n" \
+ : "=r" (err), "=&r" (v), "=&r" (a) \
+ : "0" (err), "1" (v), "2" (a)); \
+ if (err) \
+ goto fault; \
+ } while (0)
+
+#define __put32_unaligned_check(ins,val,addr) \
+ do { \
+ unsigned int err = 0, v = val, a = addr; \
+ __asm__( \
+ "1: "ins" %1, [%2], #1\n" \
+ " mov %1, %1, lsr #8\n" \
+ "2: "ins" %1, [%2], #1\n" \
+ " mov %1, %1, lsr #8\n" \
+ "3: "ins" %1, [%2], #1\n" \
+ " mov %1, %1, lsr #8\n" \
+ "4: "ins" %1, [%2]\n" \
+ "5:\n" \
+ " .section .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "6: mov %0, #1\n" \
+ " b 5b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 6b\n" \
+ " .long 2b, 6b\n" \
+ " .long 3b, 6b\n" \
+ " .long 4b, 6b\n" \
+ " .previous\n" \
+ : "=r" (err), "=&r" (v), "=&r" (a) \
+ : "0" (err), "1" (v), "2" (a)); \
+ if (err) \
+ goto fault; \
+ } while (0)
+
+#define get32_unaligned_check(val,addr) \
+ do { \
+ unsigned int err = 0, v, a = addr; \
+ get8_unaligned_check(val,a,err); \
+ get8_unaligned_check(v,a,err); \
+ val |= v << 8; \
+ get8_unaligned_check(v,a,err); \
+ val |= v << 16; \
+ get8_unaligned_check(v,a,err); \
+ val |= v << 24; \
+ if (err) \
+ goto fault; \
+ } while (0)
+
+#define put32_unaligned_check(val,addr) \
+ __put32_unaligned_check("strb", val, addr)
+
+#define get32t_unaligned_check(val,addr) \
+ do { \
+ unsigned int err = 0, v, a = addr; \
+ get8t_unaligned_check(val,a,err); \
+ get8t_unaligned_check(v,a,err); \
+ val |= v << 8; \
+ get8t_unaligned_check(v,a,err); \
+ val |= v << 16; \
+ get8t_unaligned_check(v,a,err); \
+ val |= v << 24; \
+ if (err) \
+ goto fault; \
+ } while (0)
+
+#define put32t_unaligned_check(val,addr) \
+ __put32_unaligned_check("strbt", val, addr)
+
+static void
+do_alignment_finish_ldst(unsigned long addr, unsigned long instr, struct pt_regs *regs, union offset_union offset)
+{
+ if (!LDST_U_BIT(instr))
+ offset.un = -offset.un;
+
+ if (!LDST_P_BIT(instr))
+ addr += offset.un;
+
+ if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
+ regs->uregs[RN_BITS(instr)] = addr;
+}
+
+static int
+do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs)
+{
+ unsigned int rd = RD_BITS(instr);
+
+ if ((instr & 0x01f00ff0) == 0x01000090)
+ goto swp;
+
+ if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0)
+ goto bad;
+
+ ai_half += 1;
+
+ if (LDST_L_BIT(instr)) {
+ unsigned long val;
+ get16_unaligned_check(val, addr);
+
+ /* signed half-word? */
+ if (instr & 0x40)
+ val = (signed long)((signed short) val);
+
+ regs->uregs[rd] = val;
+ } else
+ put16_unaligned_check(regs->uregs[rd], addr);
+
+ return TYPE_LDST;
+
+swp:
+ printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
+bad:
+ return TYPE_ERROR;
+
+fault:
+ return TYPE_FAULT;
+}
+
+static int
+do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *regs)
+{
+ unsigned int rd = RD_BITS(instr);
+
+ ai_word += 1;
+
+ if (!LDST_P_BIT(instr) && LDST_W_BIT(instr))
+ goto trans;
+
+ if (LDST_L_BIT(instr))
+ get32_unaligned_check(regs->uregs[rd], addr);
+ else
+ put32_unaligned_check(regs->uregs[rd], addr);
+ return TYPE_LDST;
+
+trans:
+ if (LDST_L_BIT(instr))
+ get32t_unaligned_check(regs->uregs[rd], addr);
+ else
+ put32t_unaligned_check(regs->uregs[rd], addr);
+ return TYPE_LDST;
+
+fault:
+ return TYPE_FAULT;
+}
+
+/*
+ * LDM/STM alignment handler.
+ *
+ * There are 4 variants of this instruction:
+ *
+ * B = rn pointer before instruction, A = rn pointer after instruction
+ * ------ increasing address ----->
+ * | | r0 | r1 | ... | rx | |
+ * PU = 01 B A
+ * PU = 11 B A
+ * PU = 00 A B
+ * PU = 10 A B
+ */
+static int
+do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *regs)
+{
+ unsigned int rd, rn, correction, nr_regs, regbits;
+ unsigned long eaddr, newaddr;
+
+ if (LDM_S_BIT(instr))
+ goto bad;
+
+ correction = 4; /* processor implementation defined */
+ regs->ARM_pc += correction;
+
+ ai_multi += 1;
+
+ /* count the number of registers in the mask to be transferred */
+ nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
+
+ rn = RN_BITS(instr);
+ newaddr = eaddr = regs->uregs[rn];
+
+ if (!LDST_U_BIT(instr))
+ nr_regs = -nr_regs;
+ newaddr += nr_regs;
+ if (!LDST_U_BIT(instr))
+ eaddr = newaddr;
+
+ if (LDST_P_EQ_U(instr)) /* U = P */
+ eaddr += 4;
+
+ /*
+ * For alignment faults on the ARM922T the MMU makes
+ * the FSR (and hence addr) equal to the updated base address
+ * of the multiple access rather than the restored value.
+ * Switch this messsage off if we've got a ARM922, otherwise
+ * [ls]dm alignment faults are noisy!
+ */
+#if !(defined CONFIG_CPU_ARM922T)
+ /*
+ * This is a "hint" - we already have eaddr worked out by the
+ * processor for us.
+ */
+ if (addr != eaddr) {
+ printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
+ "addr = %08lx, eaddr = %08lx\n",
+ instruction_pointer(regs), instr, addr, eaddr);
+ show_regs(regs);
+ }
+#endif
+
+ for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1)
+ if (regbits & 1) {
+ if (LDST_L_BIT(instr))
+ get32_unaligned_check(regs->uregs[rd], eaddr);
+ else
+ put32_unaligned_check(regs->uregs[rd], eaddr);
+ eaddr += 4;
+ }
+
+ if (LDST_W_BIT(instr))
+ regs->uregs[rn] = newaddr;
+ if (!LDST_L_BIT(instr) || !(REGMASK_BITS(instr) & (1 << 15)))
+ regs->ARM_pc -= correction;
+ return TYPE_DONE;
+
+fault:
+ regs->ARM_pc -= correction;
+ return TYPE_FAULT;
+
+bad:
+ printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n");
+ return TYPE_ERROR;
+}
+
+int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
+{
+ union offset_union offset;
+ unsigned long instr, instrptr;
+ int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
+ unsigned int type;
+
+ instrptr = instruction_pointer(regs);
+ instr = *(unsigned long *)instrptr;
+
+ if (user_mode(regs))
+ goto user;
+
+ ai_sys += 1;
+
+ fixup:
+
+ regs->ARM_pc += 4;
+
+ switch (CODING_BITS(instr)) {
+ case 0x00000000: /* ldrh or strh */
+ if (LDSTH_I_BIT(instr))
+ offset.un = (instr & 0xf00) >> 4 | (instr & 15);
+ else
+ offset.un = regs->uregs[RM_BITS(instr)];
+ handler = do_alignment_ldrhstrh;
+ break;
+
+ case 0x04000000: /* ldr or str immediate */
+ offset.un = OFFSET_BITS(instr);
+ handler = do_alignment_ldrstr;
+ break;
+
+ case 0x06000000: /* ldr or str register */
+ offset.un = regs->uregs[RM_BITS(instr)];
+
+ if (IS_SHIFT(instr)) {
+ unsigned int shiftval = SHIFT_BITS(instr);
+
+ switch(SHIFT_TYPE(instr)) {
+ case SHIFT_LSL:
+ offset.un <<= shiftval;
+ break;
+
+ case SHIFT_LSR:
+ offset.un >>= shiftval;
+ break;
+
+ case SHIFT_ASR:
+ offset.sn >>= shiftval;
+ break;
+
+ case SHIFT_RORRRX:
+ if (shiftval == 0) {
+ offset.un >>= 1;
+ if (regs->ARM_cpsr & PSR_C_BIT)
+ offset.un |= 1 << 31;
+ } else
+ offset.un = offset.un >> shiftval |
+ offset.un << (32 - shiftval);
+ break;
+ }
+ }
+ handler = do_alignment_ldrstr;
+ break;
+
+ case 0x08000000: /* ldm or stm */
+ handler = do_alignment_ldmstm;
+ break;
+
+ default:
+ goto bad;
+ }
+
+ type = handler(addr, instr, regs);
+
+ if (type == TYPE_ERROR || type == TYPE_FAULT)
+ goto bad_or_fault;
+
+ if (type == TYPE_LDST)
+ do_alignment_finish_ldst(addr, instr, regs, offset);
+
+ return 0;
+
+bad_or_fault:
+ if (type == TYPE_ERROR)
+ goto bad;
+ regs->ARM_pc -= 4;
+ /*
+ * We got a fault - fix it up, or die.
+ */
+ do_bad_area(current, current->mm, addr, error_code, regs);
+ return 0;
+
+bad:
+ /*
+ * Oops, we didn't handle the instruction.
+ */
+ printk(KERN_ERR "Alignment trap: not handling instruction "
+ "%08lx at [<%08lx>]\n", instr, instrptr);
+ ai_skipped += 1;
+ return 1;
+
+ user:
+ ai_user += 1;
+
+ if (ai_usermode & 1)
+ printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%08lx "
+ "Address=0x%08lx Code 0x%02x\n", current->comm,
+ current->pid, instrptr, instr, addr, error_code);
+
+ if (ai_usermode & 2)
+ goto fixup;
+
+ if (ai_usermode & 4)
+ force_sig(SIGBUS, current);
+ else
+ set_cr(cr_no_alignment);
+
+ return 0;
+}
diff --git a/arch/arm/mm/armv4-early-abort.S b/arch/arm/mm/armv4-early-abort.S
new file mode 100644
index 000000000..8b3e66797
--- /dev/null
+++ b/arch/arm/mm/armv4-early-abort.S
@@ -0,0 +1,29 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: armv4_early_abort
+ *
+ * Params : r2 = address of aborted instruction
+ * : r3 = saved SPSR
+ *
+ * Returns : r0 = address of abort
+ * : r1 = FSR, bit 8 = write
+ * : r2-r8 = corrupted
+ * : r9 = preserved
+ * : sp = pointer to registers
+ *
+ * Purpose : obtain information about current aborted instruction.
+ * Note: we read user space. This means we might cause a data
+ * abort here if the I-TLB and D-TLB aren't seeing the same
+ * picture. Unfortunately, this does happen. We live with it.
+ */
+ .align 5
+ENTRY(armv4_early_abort)
+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+ ldr r3, [r2] @ read aborted ARM instruction
+ tst r3, #1 << 20 @ L = 1 -> write?
+ orreq r1, r1, #1 << 8 @ yes.
+ mov pc, lr
+
+
diff --git a/arch/arm/mm/armv4t-early-abort.S b/arch/arm/mm/armv4t-early-abort.S
new file mode 100644
index 000000000..dd72ad8c1
--- /dev/null
+++ b/arch/arm/mm/armv4t-early-abort.S
@@ -0,0 +1,31 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: armv4t_early_abort
+ *
+ * Params : r2 = address of aborted instruction
+ * : r3 = saved SPSR
+ *
+ * Returns : r0 = address of abort
+ * : r1 = FSR, bit 8 = write
+ * : r2-r8 = corrupted
+ * : r9 = preserved
+ * : sp = pointer to registers
+ *
+ * Purpose : obtain information about current aborted instruction.
+ * Note: we read user space. This means we might cause a data
+ * abort here if the I-TLB and D-TLB aren't seeing the same
+ * picture. Unfortunately, this does happen. We live with it.
+ */
+ .align 5
+ENTRY(armv4t_early_abort)
+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+ tst r3, #PSR_T_BIT
+ ldrneh r3, [r2] @ read aborted thumb instruction
+ ldreq r3, [r2] @ read aborted ARM instruction
+ bic r1, r1, #1 << 8
+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
+ tst r3, #1 << 20 @ check write
+ orreq r1, r1, #1 << 8
+ mov pc, lr
diff --git a/arch/arm/mm/armv4t-late-abort.S b/arch/arm/mm/armv4t-late-abort.S
new file mode 100644
index 000000000..6cbe9e349
--- /dev/null
+++ b/arch/arm/mm/armv4t-late-abort.S
@@ -0,0 +1,224 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: armv4t_late_abort
+ *
+ * Params : r2 = address of aborted instruction
+ * : r3 = saved SPSR
+ *
+ * Returns : r0 = address of abort
+ * : r1 = FSR, bit 8 = writing
+ * : r2-r8 = corrupted
+ * : r9 = preserved
+ * : sp = pointer to registers
+ *
+ * Purpose : obtain information about current aborted instruction.
+ * Note: we read user space. This means we might cause a data
+ * abort here if the I-TLB and D-TLB aren't seeing the same
+ * picture. Unfortunately, this does happen. We live with it.
+ */
+ENTRY(armv4t_late_abort)
+ tst r3, #PSR_T_BIT @ check for thumb mode
+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+ ldreq r8, [r2] @ read arm instruction
+ bne .data_thumb_abort
+ tst r8, #1 << 20 @ L = 1 -> write?
+ orreq r1, r1, #1 << 8 @ yes.
+ and r7, r8, #15 << 24
+ add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
+ nop
+
+/* 0 */ b .data_arm_lateldrhpost @ ldrh rd, [rn], #m/rm
+/* 1 */ b .data_arm_lateldrhpre @ ldrh rd, [rn, #m/rm]
+/* 2 */ b .data_unknown
+/* 3 */ b .data_unknown
+/* 4 */ b .data_arm_lateldrpostconst @ ldr rd, [rn], #m
+/* 5 */ b .data_arm_lateldrpreconst @ ldr rd, [rn, #m]
+/* 6 */ b .data_arm_lateldrpostreg @ ldr rd, [rn], rm
+/* 7 */ b .data_arm_lateldrprereg @ ldr rd, [rn, rm]
+/* 8 */ b .data_arm_ldmstm @ ldm*a rn, <rlist>
+/* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist>
+/* a */ b .data_unknown
+/* b */ b .data_unknown
+/* c */ mov pc, lr @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
+/* d */ mov pc, lr @ ldc rd, [rn, #m]
+/* e */ b .data_unknown
+/* f */
+.data_unknown: @ Part of jumptable
+ mov r0, r2
+ mov r1, r8
+ mov r2, sp
+ bl baddataabort
+ b ret_from_exception
+
+.data_arm_ldmstm:
+ tst r8, #1 << 21 @ check writeback bit
+ moveq pc, lr @ no writeback -> no fixup
+ mov r7, #0x11
+ orr r7, r7, #0x1100
+ and r6, r8, r7
+ and r2, r8, r7, lsl #1
+ add r6, r6, r2, lsr #1
+ and r2, r8, r7, lsl #2
+ add r6, r6, r2, lsr #2
+ and r2, r8, r7, lsl #3
+ add r6, r6, r2, lsr #3
+ add r6, r6, r6, lsr #8
+ add r6, r6, r6, lsr #4
+ and r6, r6, #15 @ r7 = no. of registers to transfer.
+ and r5, r8, #15 << 16 @ Extract 'n' form instruction
+ ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ tst r8, #1 << 23 @ Check U bit
+ subne r7, r7, r6, lsl #2 @ Undo increment
+ addeq r7, r7, r6, lsl #2 @ Undo decrement
+ str r7, [sp, r5, lsr #14] @ Put register 'Rn'
+ mov pc, lr
+
+.data_arm_lateldrhpre:
+ tst r8, #1 << 21 @ Check writeback bit
+ moveq pc, lr @ No writeback -> no fixup
+.data_arm_lateldrhpost:
+ and r5, r8, #0x00f @ get Rm / low nibble of immediate value
+ tst r8, #1 << 22 @ if (immediate offset)
+ andne r6, r8, #0xf00 @ { immediate high nibble
+ orrne r6, r5, r6, lsr #4 @ combine nibbles } else
+ ldreq r6, [sp, r5, lsl #2] @ { load Rm value }
+.data_arm_apply_r6_and_rn:
+ and r5, r8, #15 << 16 @ Extract 'n' from instruction
+ ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ tst r8, #1 << 23 @ Check U bit
+ subne r7, r7, r6 @ Undo incrmenet
+ addeq r7, r7, r6 @ Undo decrement
+ str r7, [sp, r5, lsr #14] @ Put register 'Rn'
+ mov pc, lr
+
+.data_arm_lateldrpreconst:
+ tst r8, #1 << 21 @ check writeback bit
+ moveq pc, lr @ no writeback -> no fixup
+.data_arm_lateldrpostconst:
+ movs r2, r8, lsl #20 @ Get offset
+ moveq pc, lr @ zero -> no fixup
+ and r5, r8, #15 << 16 @ Extract 'n' from instruction
+ ldr r7, [sp, r5, lsr #14] @ Get register 'Rn'
+ tst r8, #1 << 23 @ Check U bit
+ subne r7, r7, r2, lsr #20 @ Undo increment
+ addeq r7, r7, r2, lsr #20 @ Undo decrement
+ str r7, [sp, r5, lsr #14] @ Put register 'Rn'
+ mov pc, lr
+
+.data_arm_lateldrprereg:
+ tst r8, #1 << 21 @ check writeback bit
+ moveq pc, lr @ no writeback -> no fixup
+.data_arm_lateldrpostreg:
+ and r7, r8, #15 @ Extract 'm' from instruction
+ ldr r6, [sp, r7, lsl #2] @ Get register 'Rm'
+ mov r5, r8, lsr #7 @ get shift count
+ ands r5, r5, #31
+ and r7, r8, #0x70 @ get shift type
+ orreq r7, r7, #8 @ shift count = 0
+ add pc, pc, r7
+ nop
+
+ mov r6, r6, lsl r5 @ 0: LSL #!0
+ b .data_arm_apply_r6_and_rn
+ b .data_arm_apply_r6_and_rn @ 1: LSL #0
+ nop
+ b .data_unknown @ 2: MUL?
+ nop
+ b .data_unknown @ 3: MUL?
+ nop
+ mov r6, r6, lsr r5 @ 4: LSR #!0
+ b .data_arm_apply_r6_and_rn
+ mov r6, r6, lsr #32 @ 5: LSR #32
+ b .data_arm_apply_r6_and_rn
+ b .data_unknown @ 6: MUL?
+ nop
+ b .data_unknown @ 7: MUL?
+ nop
+ mov r6, r6, asr r5 @ 8: ASR #!0
+ b .data_arm_apply_r6_and_rn
+ mov r6, r6, asr #32 @ 9: ASR #32
+ b .data_arm_apply_r6_and_rn
+ b .data_unknown @ A: MUL?
+ nop
+ b .data_unknown @ B: MUL?
+ nop
+ mov r6, r6, ror r5 @ C: ROR #!0
+ b .data_arm_apply_r6_and_rn
+ mov r6, r6, rrx @ D: RRX
+ b .data_arm_apply_r6_and_rn
+ b .data_unknown @ E: MUL?
+ nop
+ b .data_unknown @ F: MUL?
+
+.data_thumb_abort:
+ ldrh r8, [r2] @ read instruction
+ tst r8, #1 << 11 @ L = 1 -> write?
+ orreq r1, r1, #1 << 8 @ yes
+ and r7, r8, #15 << 12
+ add pc, pc, r7, lsr #10 @ lookup in table
+ nop
+
+/* 0 */ b .data_unknown
+/* 1 */ b .data_unknown
+/* 2 */ b .data_unknown
+/* 3 */ b .data_unknown
+/* 4 */ b .data_unknown
+/* 5 */ b .data_thumb_reg
+/* 6 */ mov pc, lr
+/* 7 */ mov pc, lr
+/* 8 */ mov pc, lr
+/* 9 */ mov pc, lr
+/* A */ b .data_unknown
+/* B */ b .data_thumb_pushpop
+/* C */ b .data_thumb_ldmstm
+/* D */ b .data_unknown
+/* E */ b .data_unknown
+/* F */ b .data_unknown
+
+.data_thumb_reg:
+ tst r8, #1 << 9
+ moveq pc, lr
+ tst r8, #1 << 10 @ If 'S' (signed) bit is set
+ movne r1, #0 @ it must be a load instr
+ mov pc, lr
+
+.data_thumb_pushpop:
+ tst r8, #1 << 10
+ beq .data_unknown
+ mov r7, #0x11
+ and r6, r8, r7
+ and r2, r8, r7, lsl #1
+ add r6, r6, r2, lsr #1
+ and r2, r8, r7, lsl #2
+ add r6, r6, r2, lsr #2
+ and r2, r8, r7, lsl #3
+ add r6, r6, r2, lsr #3
+ add r6, r6, r6, lsr #4
+ and r2, r8, #0x0100 @ catch 'R' bit for push/pop
+ add r6, r6, r2, lsr #8
+ and r6, r6, #15 @ number of regs to transfer
+ ldr r7, [sp, #13 << 2]
+ tst r8, #1 << 11
+ addne r7, r7, r6, lsl #2 @ increment SP if PUSH
+ subeq r7, r7, r6, lsr #2 @ decrement SP if POP
+ str r7, [sp, #13 << 2]
+ mov pc, lr
+
+.data_thumb_ldmstm:
+ mov r7, #0x11
+ and r6, r8, r7
+ and r2, r8, r7, lsl #1
+ add r6, r6, r2, lsr #1
+ and r2, r8, r7, lsl #2
+ add r6, r6, r2, lsr #2
+ and r2, r8, r7, lsl #3
+ add r6, r6, r2, lsr #3
+ add r6, r6, r6, lsr #4
+ and r6, r6, #15 @ number of regs to transfer
+ and r5, r8, #7 << 8
+ ldr r7, [sp, r5, lsr #6]
+ sub r7, r7, r6, lsr #2 @ always decrement
+ str r7, [sp, r5, lsr #6]
+ mov pc, lr
diff --git a/arch/arm/mm/armv5ej-early-abort.S b/arch/arm/mm/armv5ej-early-abort.S
new file mode 100644
index 000000000..618a6cb1f
--- /dev/null
+++ b/arch/arm/mm/armv5ej-early-abort.S
@@ -0,0 +1,35 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: armv5ej_early_abort
+ *
+ * Params : r2 = address of aborted instruction
+ * : r3 = saved SPSR
+ *
+ * Returns : r0 = address of abort
+ * : r1 = FSR, bit 8 = write
+ * : r2-r8 = corrupted
+ * : r9 = preserved
+ * : sp = pointer to registers
+ *
+ * Purpose : obtain information about current aborted instruction.
+ * Note: we read user space. This means we might cause a data
+ * abort here if the I-TLB and D-TLB aren't seeing the same
+ * picture. Unfortunately, this does happen. We live with it.
+ */
+ .align 5
+ENTRY(armv5ej_early_abort)
+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+ tst r3, #PSR_J_BIT
+ orrne r1, r1, #1 << 8 @ always assume write
+ bne 1f
+ tst r3, #PSR_T_BIT
+ ldrneh r3, [r2] @ read aborted thumb instruction
+ ldreq r3, [r2] @ read aborted ARM instruction
+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
+ tst r2, #1 << 20 @ L = 1 -> write
+ orreq r1, r1, #1 << 8 @ yes.
+1: mov pc, lr
+
+
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 5778909dc..bb07b1fd9 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
#include <linux/config.h>
+#include <linux/compiler.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -27,7 +28,6 @@
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
-#include <asm/unaligned.h>
extern void die_if_kernel(const char *str, struct pt_regs *regs, int err);
extern void show_pte(struct mm_struct *mm, unsigned long addr);
@@ -40,499 +40,15 @@ extern void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
struct pt_regs *regs);
#ifdef CONFIG_ALIGNMENT_TRAP
-/*
- * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
- * /proc/sys/debug/alignment, modified and integrated into
- * Linux 2.1 by Russell King
- *
- * Speed optimisations and better fault handling by Russell King.
- *
- * *** NOTE ***
- * This code is not portable to processors with late data abort handling.
- */
-#define CODING_BITS(i) (i & 0x0e000000)
-
-#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */
-#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */
-#define LDST_U_BIT(i) (i & (1 << 23)) /* Add offset */
-#define LDST_W_BIT(i) (i & (1 << 21)) /* Writeback */
-#define LDST_L_BIT(i) (i & (1 << 20)) /* Load */
-
-#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
-
-#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */
-#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
-
-#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
-#define RD_BITS(i) ((i >> 12) & 15) /* Rd */
-#define RM_BITS(i) (i & 15) /* Rm */
-
-#define REGMASK_BITS(i) (i & 0xffff)
-#define OFFSET_BITS(i) (i & 0x0fff)
-
-#define IS_SHIFT(i) (i & 0x0ff0)
-#define SHIFT_BITS(i) ((i >> 7) & 0x1f)
-#define SHIFT_TYPE(i) (i & 0x60)
-#define SHIFT_LSL 0x00
-#define SHIFT_LSR 0x20
-#define SHIFT_ASR 0x40
-#define SHIFT_RORRRX 0x60
-
-static unsigned long ai_user;
-static unsigned long ai_sys;
-static unsigned long ai_skipped;
-static unsigned long ai_half;
-static unsigned long ai_word;
-static unsigned long ai_multi;
-
-#ifdef CONFIG_SYSCTL
-static int proc_alignment_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- char *p = page;
- int len;
-
- p += sprintf(p, "User:\t\t%li\n", ai_user);
- p += sprintf(p, "System:\t\t%li\n", ai_sys);
- p += sprintf(p, "Skipped:\t%li\n", ai_skipped);
- p += sprintf(p, "Half:\t\t%li\n", ai_half);
- p += sprintf(p, "Word:\t\t%li\n", ai_word);
- p += sprintf(p, "Multi:\t\t%li\n", ai_multi);
-
- len = (p - page) - off;
- if (len < 0)
- len = 0;
-
- *eof = (len <= count) ? 1 : 0;
- *start = page + off;
-
- return len;
-}
-
-/*
- * This needs to be done after sysctl_init, otherwise sys/
- * will be overwritten.
- */
-static int __init alignment_init(void)
-{
- create_proc_read_entry("sys/debug/alignment", 0, NULL,
- proc_alignment_read, NULL);
- return 0;
-}
-
-__initcall(alignment_init);
-#endif /* CONFIG_SYSCTL */
-
-union offset_union {
- unsigned long un;
- signed long sn;
-};
-
-#define TYPE_ERROR 0
-#define TYPE_FAULT 1
-#define TYPE_LDST 2
-#define TYPE_DONE 3
-
-#define get8_unaligned_check(val,addr,err) \
- __asm__( \
- "1: ldrb %1, [%2], #1\n" \
- "2:\n" \
- " .section .fixup,\"ax\"\n" \
- " .align 2\n" \
- "3: mov %0, #1\n" \
- " b 2b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous\n" \
- : "=r" (err), "=&r" (val), "=r" (addr) \
- : "0" (err), "2" (addr))
-
-#define get8t_unaligned_check(val,addr,err) \
- __asm__( \
- "1: ldrbt %1, [%2], #1\n" \
- "2:\n" \
- " .section .fixup,\"ax\"\n" \
- " .align 2\n" \
- "3: mov %0, #1\n" \
- " b 2b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous\n" \
- : "=r" (err), "=&r" (val), "=r" (addr) \
- : "0" (err), "2" (addr))
-
-#define get16_unaligned_check(val,addr) \
- do { \
- unsigned int err = 0, v, a = addr; \
- get8_unaligned_check(val,a,err); \
- get8_unaligned_check(v,a,err); \
- val |= v << 8; \
- if (err) \
- goto fault; \
- } while (0)
-
-#define put16_unaligned_check(val,addr) \
- do { \
- unsigned int err = 0, v = val, a = addr; \
- __asm__( \
- "1: strb %1, [%2], #1\n" \
- " mov %1, %1, lsr #8\n" \
- "2: strb %1, [%2]\n" \
- "3:\n" \
- " .section .fixup,\"ax\"\n" \
- " .align 2\n" \
- "4: mov %0, #1\n" \
- " b 3b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 4b\n" \
- " .long 2b, 4b\n" \
- " .previous\n" \
- : "=r" (err), "=&r" (v), "=&r" (a) \
- : "0" (err), "1" (v), "2" (a)); \
- if (err) \
- goto fault; \
- } while (0)
-
-#define __put32_unaligned_check(ins,val,addr) \
- do { \
- unsigned int err = 0, v = val, a = addr; \
- __asm__( \
- "1: "ins" %1, [%2], #1\n" \
- " mov %1, %1, lsr #8\n" \
- "2: "ins" %1, [%2], #1\n" \
- " mov %1, %1, lsr #8\n" \
- "3: "ins" %1, [%2], #1\n" \
- " mov %1, %1, lsr #8\n" \
- "4: "ins" %1, [%2]\n" \
- "5:\n" \
- " .section .fixup,\"ax\"\n" \
- " .align 2\n" \
- "6: mov %0, #1\n" \
- " b 5b\n" \
- " .previous\n" \
- " .section __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 6b\n" \
- " .long 2b, 6b\n" \
- " .long 3b, 6b\n" \
- " .long 4b, 6b\n" \
- " .previous\n" \
- : "=r" (err), "=&r" (v), "=&r" (a) \
- : "0" (err), "1" (v), "2" (a)); \
- if (err) \
- goto fault; \
- } while (0)
-
-#define get32_unaligned_check(val,addr) \
- do { \
- unsigned int err = 0, v, a = addr; \
- get8_unaligned_check(val,a,err); \
- get8_unaligned_check(v,a,err); \
- val |= v << 8; \
- get8_unaligned_check(v,a,err); \
- val |= v << 16; \
- get8_unaligned_check(v,a,err); \
- val |= v << 24; \
- if (err) \
- goto fault; \
- } while (0)
-
-#define put32_unaligned_check(val,addr) \
- __put32_unaligned_check("strb", val, addr)
-
-#define get32t_unaligned_check(val,addr) \
- do { \
- unsigned int err = 0, v, a = addr; \
- get8t_unaligned_check(val,a,err); \
- get8t_unaligned_check(v,a,err); \
- val |= v << 8; \
- get8t_unaligned_check(v,a,err); \
- val |= v << 16; \
- get8t_unaligned_check(v,a,err); \
- val |= v << 24; \
- if (err) \
- goto fault; \
- } while (0)
-
-#define put32t_unaligned_check(val,addr) \
- __put32_unaligned_check("strbt", val, addr)
-
-static void
-do_alignment_finish_ldst(unsigned long addr, unsigned long instr, struct pt_regs *regs, union offset_union offset)
-{
- if (!LDST_U_BIT(instr))
- offset.un = -offset.un;
-
- if (!LDST_P_BIT(instr))
- addr += offset.un;
-
- if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
- regs->uregs[RN_BITS(instr)] = addr;
-}
-
-static int
-do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs)
-{
- unsigned int rd = RD_BITS(instr);
-
- if ((instr & 0x01f00ff0) == 0x01000090)
- goto swp;
-
- if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0)
- goto bad;
-
- ai_half += 1;
-
- if (LDST_L_BIT(instr)) {
- unsigned long val;
- get16_unaligned_check(val, addr);
-
- /* signed half-word? */
- if (instr & 0x40)
- val = (signed long)((signed short) val);
-
- regs->uregs[rd] = val;
- } else
- put16_unaligned_check(regs->uregs[rd], addr);
-
- return TYPE_LDST;
-
-swp:
- printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
-bad:
- return TYPE_ERROR;
-
-fault:
- return TYPE_FAULT;
-}
-
-static int
-do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *regs)
-{
- unsigned int rd = RD_BITS(instr);
-
- ai_word += 1;
-
- if (!LDST_P_BIT(instr) && LDST_W_BIT(instr))
- goto trans;
-
- if (LDST_L_BIT(instr))
- get32_unaligned_check(regs->uregs[rd], addr);
- else
- put32_unaligned_check(regs->uregs[rd], addr);
- return TYPE_LDST;
-
-trans:
- if (LDST_L_BIT(instr))
- get32t_unaligned_check(regs->uregs[rd], addr);
- else
- put32t_unaligned_check(regs->uregs[rd], addr);
- return TYPE_LDST;
-
-fault:
- return TYPE_FAULT;
-}
-
-/*
- * LDM/STM alignment handler.
- *
- * There are 4 variants of this instruction:
- *
- * B = rn pointer before instruction, A = rn pointer after instruction
- * ------ increasing address ----->
- * | | r0 | r1 | ... | rx | |
- * PU = 01 B A
- * PU = 11 B A
- * PU = 00 A B
- * PU = 10 A B
- */
-static int
-do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *regs)
-{
- unsigned int rd, rn, correction, nr_regs, regbits;
- unsigned long eaddr, newaddr;
-
- if (LDM_S_BIT(instr))
- goto bad;
-
- correction = 4; /* processor implementation defined */
- regs->ARM_pc += correction;
-
- ai_multi += 1;
-
- /* count the number of registers in the mask to be transferred */
- nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
-
- rn = RN_BITS(instr);
- newaddr = eaddr = regs->uregs[rn];
-
- if (!LDST_U_BIT(instr))
- nr_regs = -nr_regs;
- newaddr += nr_regs;
- if (!LDST_U_BIT(instr))
- eaddr = newaddr;
-
- if (LDST_P_EQ_U(instr)) /* U = P */
- eaddr += 4;
-
- /*
- * This is a "hint" - we already have eaddr worked out by the
- * processor for us.
- */
- if (addr != eaddr) {
- printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
- "addr = %08lx, eaddr = %08lx\n",
- instruction_pointer(regs), instr, addr, eaddr);
- show_regs(regs);
- }
-
- for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1)
- if (regbits & 1) {
- if (LDST_L_BIT(instr))
- get32_unaligned_check(regs->uregs[rd], eaddr);
- else
- put32_unaligned_check(regs->uregs[rd], eaddr);
- eaddr += 4;
- }
-
- if (LDST_W_BIT(instr))
- regs->uregs[rn] = newaddr;
- if (!LDST_L_BIT(instr) || !(REGMASK_BITS(instr) & (1 << 15)))
- regs->ARM_pc -= correction;
- return TYPE_DONE;
-
-fault:
- regs->ARM_pc -= correction;
- return TYPE_FAULT;
-
-bad:
- printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n");
- return TYPE_ERROR;
-}
-
-static int
-do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
-{
- union offset_union offset;
- unsigned long instr, instrptr;
- int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
- unsigned int type;
-
- if (user_mode(regs))
- goto user;
-
- ai_sys += 1;
-
- instrptr = instruction_pointer(regs);
- instr = *(unsigned long *)instrptr;
-
- regs->ARM_pc += 4;
-
- switch (CODING_BITS(instr)) {
- case 0x00000000: /* ldrh or strh */
- if (LDSTH_I_BIT(instr))
- offset.un = (instr & 0xf00) >> 4 | (instr & 15);
- else
- offset.un = regs->uregs[RM_BITS(instr)];
- handler = do_alignment_ldrhstrh;
- break;
-
- case 0x04000000: /* ldr or str immediate */
- offset.un = OFFSET_BITS(instr);
- handler = do_alignment_ldrstr;
- break;
-
- case 0x06000000: /* ldr or str register */
- offset.un = regs->uregs[RM_BITS(instr)];
-
- if (IS_SHIFT(instr)) {
- unsigned int shiftval = SHIFT_BITS(instr);
-
- switch(SHIFT_TYPE(instr)) {
- case SHIFT_LSL:
- offset.un <<= shiftval;
- break;
-
- case SHIFT_LSR:
- offset.un >>= shiftval;
- break;
-
- case SHIFT_ASR:
- offset.sn >>= shiftval;
- break;
-
- case SHIFT_RORRRX:
- if (shiftval == 0) {
- offset.un >>= 1;
- if (regs->ARM_cpsr & CC_C_BIT)
- offset.un |= 1 << 31;
- } else
- offset.un = offset.un >> shiftval |
- offset.un << (32 - shiftval);
- break;
- }
- }
- handler = do_alignment_ldrstr;
- break;
-
- case 0x08000000: /* ldm or stm */
- handler = do_alignment_ldmstm;
- break;
-
- default:
- goto bad;
- }
-
- type = handler(addr, instr, regs);
-
- if (type == TYPE_ERROR || type == TYPE_FAULT)
- goto bad_or_fault;
-
- if (type == TYPE_LDST)
- do_alignment_finish_ldst(addr, instr, regs, offset);
-
- return 0;
-
-bad_or_fault:
- if (type == TYPE_ERROR)
- goto bad;
- regs->ARM_pc -= 4;
- /*
- * We got a fault - fix it up, or die.
- */
- do_bad_area(current, current->mm, addr, error_code, regs);
- return 0;
-
-bad:
- /*
- * Oops, we didn't handle the instruction.
- */
- printk(KERN_ERR "Alignment trap: not handling instruction "
- "%08lx at [<%08lx>]\n", instr, instrptr);
- ai_skipped += 1;
- return 1;
-
-user:
- set_cr(cr_no_alignment);
- ai_user += 1;
- return 0;
-}
-
+extern int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs);
#else
-
-#define do_alignment NULL
-
+#define do_alignment do_bad
#endif
+
/*
- * Some section permission faults need to be handled gracefully, for
- * instance, when they happen due to a __{get,put}_user during an oops).
+ * Some section permission faults need to be handled gracefully.
+ * They can happen due to a __{get,put}_user during an oops.
*/
static int
do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
@@ -557,73 +73,54 @@ do_external_fault(unsigned long addr, int error_code, struct pt_regs *regs)
return 1;
}
+/*
+ * This abort handler always returns "fault".
+ */
+static int
+do_bad(unsigned long addr, int error_code, struct pt_regs *regs)
+{
+ return 1;
+}
+
static const struct fsr_info {
int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
int sig;
- char *name;
+ const char *name;
} fsr_info[] = {
- { NULL, SIGSEGV, "vector exception" },
+ { do_bad, SIGSEGV, "vector exception" },
{ do_alignment, SIGILL, "alignment exception" },
- { NULL, SIGKILL, "terminal exception" },
+ { do_bad, SIGKILL, "terminal exception" },
{ do_alignment, SIGILL, "alignment exception" },
{ do_external_fault, SIGBUS, "external abort on linefetch" },
{ do_translation_fault, SIGSEGV, "section translation fault" },
{ do_external_fault, SIGBUS, "external abort on linefetch" },
{ do_page_fault, SIGSEGV, "page translation fault" },
{ do_external_fault, SIGBUS, "external abort on non-linefetch" },
- { NULL, SIGSEGV, "section domain fault" },
+ { do_bad, SIGSEGV, "section domain fault" },
{ do_external_fault, SIGBUS, "external abort on non-linefetch" },
- { NULL, SIGSEGV, "page domain fault" },
- { NULL, SIGBUS, "external abort on translation" },
+ { do_bad, SIGSEGV, "page domain fault" },
+ { do_bad, SIGBUS, "external abort on translation" },
{ do_sect_fault, SIGSEGV, "section permission fault" },
- { NULL, SIGBUS, "external abort on translation" },
+ { do_bad, SIGBUS, "external abort on translation" },
{ do_page_fault, SIGSEGV, "page permission fault" }
};
/*
- * Currently dropped down to debug level
+ * Dispatch a data abort to the relevant handler.
*/
asmlinkage void
-do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr)
+do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
const struct fsr_info *inf = fsr_info + (fsr & 15);
-#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) || defined(CONFIG_DEBUG_ERRORS)
- if (addr == regs->ARM_pc)
- goto sa1_weirdness;
-#endif
-
- if (!inf->fn)
- goto bad;
-
- if (!inf->fn(addr, error_code, regs))
+ if (!inf->fn(addr, fsr, regs))
return;
-bad:
+
printk(KERN_ALERT "Unhandled fault: %s (%X) at 0x%08lx\n",
inf->name, fsr, addr);
- show_pte(current->mm, addr);
force_sig(inf->sig, current);
+ show_pte(current->mm, addr);
die_if_kernel("Oops", regs, 0);
- return;
-
-#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) || defined(CONFIG_DEBUG_ERRORS)
-sa1_weirdness:
- if (user_mode(regs)) {
- static int first = 1;
- if (first) {
- printk(KERN_DEBUG "Fixing up bad data abort at %08lx\n", addr);
-#ifdef CONFIG_DEBUG_ERRORS
- show_pte(current->mm, addr);
-#endif
- }
- first = 0;
- return;
- }
-
- if (!inf->fn || inf->fn(addr, error_code, regs))
- goto bad;
- return;
-#endif
}
asmlinkage void
@@ -727,7 +224,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
* Note that we intentionally don't mask out the VMA
* that we are fixing up.
*/
- if (mpnt->vm_mm != mm && mpnt != vma)
+ if (mpnt->vm_mm != mm || mpnt == vma)
continue;
/*
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index b633a5597..3e1c663dd 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -39,8 +39,8 @@
* of the 26-bit machines, and also means that we avoid the horrible
* gcc code for "int val = !other_val;".
*/
-#define DO_COW(m) (m)
-#define READ_FAULT(m) (!(m))
+#define DO_COW(code) ((code) & (1 << 8))
+#define READ_FAULT(code) (!DO_COW(code))
#endif
NORET_TYPE void die(const char *msg, struct pt_regs *regs, int err) ATTRIB_NORET;
diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c
new file mode 100644
index 000000000..3decad8a6
--- /dev/null
+++ b/arch/arm/mm/minicache.c
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/arm/mm/minicache.c
+ *
+ * Copyright (C) 2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This handles the mini data cache, as found on SA11x0 and XScale
+ * processors. When we copy a user page page, we map it in such a way
+ * that accesses to this page will not touch the main data cache, but
+ * will be cached in the mini data cache. This prevents us thrashing
+ * the main data cache on page faults.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#define minicache_address (0xffff2000)
+#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
+ L_PTE_CACHEABLE)
+
+static pte_t *minicache_pte;
+
+/*
+ * Note that this is intended to be called only from the copy_user_page
+ * asm code; anything else will require special locking to prevent the
+ * mini-cache space being re-used. (Note: probably preempt unsafe).
+ *
+ * We rely on the fact that the minicache is 2K, and we'll be pushing
+ * 4K of data through it, so we don't actually have to specifically
+ * flush the minicache when we change the mapping.
+ *
+ * Note also: assert(PAGE_OFFSET <= virt < high_memory).
+ * Unsafe: preempt, kmap.
+ */
+unsigned long map_page_minicache(unsigned long virt)
+{
+ set_pte(minicache_pte, mk_pte_phys(__pa(virt), minicache_pgprot));
+ cpu_tlb_invalidate_page(minicache_address, 0);
+
+ return minicache_address;
+}
+
+static int __init minicache_init(void)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+
+ pgd = pgd_offset_k(minicache_address);
+ pmd = pmd_alloc(&init_mm, pgd, minicache_address);
+ if (!pmd)
+ BUG();
+ minicache_pte = pte_alloc(&init_mm, pmd, minicache_address);
+ if (!minicache_pte)
+ BUG();
+
+ return 0;
+}
+
+__initcall(minicache_init);
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index ba6133da7..10605d6aa 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -30,8 +30,8 @@
*/
static int __init nocache_setup(char *__unused)
{
- cr_alignment &= ~4;
- cr_no_alignment &= ~4;
+ cr_alignment &= ~CR1_C;
+ cr_no_alignment &= ~CR1_C;
flush_cache_all();
set_cr(cr_alignment);
return 1;
@@ -39,8 +39,8 @@ static int __init nocache_setup(char *__unused)
static int __init nowrite_setup(char *__unused)
{
- cr_alignment &= ~(8|4);
- cr_no_alignment &= ~(8|4);
+ cr_alignment &= ~(CR1_W|CR1_C);
+ cr_no_alignment &= ~(CR1_W|CR1_C);
flush_cache_all();
set_cr(cr_alignment);
return 1;
@@ -48,8 +48,8 @@ static int __init nowrite_setup(char *__unused)
static int __init noalign_setup(char *__unused)
{
- cr_alignment &= ~2;
- cr_no_alignment &= ~2;
+ cr_alignment &= ~CR1_A;
+ cr_no_alignment &= ~CR1_A;
set_cr(cr_alignment);
return 1;
}
diff --git a/arch/arm/mm/mm-clps7500.c b/arch/arm/mm/mm-clps7500.c
deleted file mode 100644
index 8c592aa6b..000000000
--- a/arch/arm/mm/mm-clps7500.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * linux/arch/arm/mm/mm-cl7500.c
- *
- * Copyright (C) 1998 Russell King
- * Copyright (C) 1999 Nexus Electronics Ltd
- *
- * Extra MM routines for CL7500 architecture
- */
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/page.h>
-#include <asm/proc/domain.h>
-#include <asm/setup.h>
-
-#include <asm/mach/map.h>
-
-static struct map_desc cl7500_io_desc[] __initdata = {
- { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1 }, /* IO space */
- { ISA_BASE, ISA_START, ISA_SIZE , DOMAIN_IO, 0, 1 }, /* ISA space */
- { FLASH_BASE, FLASH_START, FLASH_SIZE, DOMAIN_IO, 0, 1 }, /* Flash */
- { LED_BASE, LED_START, LED_SIZE , DOMAIN_IO, 0, 1 }, /* LED */
- LAST_DESC
-};
-
-void __init clps7500_map_io(void)
-{
- iotable_init(cl7500_io_desc);
-}
diff --git a/arch/arm/mm/mm-ftvpci.c b/arch/arm/mm/mm-ftvpci.c
deleted file mode 100644
index 31d619433..000000000
--- a/arch/arm/mm/mm-ftvpci.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * linux/arch/arm/mm/mm-nexuspci.c
- * from linux/arch/arm/mm/mm-ebsa110.c
- *
- * Copyright (C) 1998-1999 Phil Blundell
- * Copyright (C) 1998-1999 Russell King
- *
- * Extra MM routines for the FTV/PCI architecture
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/io.h>
-
-#include <asm/mach/map.h>
-
-static struct map_desc nexuspci_io_desc[] __initdata = {
- { INTCONT_BASE, INTCONT_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { PLX_BASE, PLX_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { PCIO_BASE, PLX_IO_START, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
- { DUART_BASE, DUART_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- { STATUS_BASE, STATUS_START, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
- LAST_DESC
-};
-
-void __init nexuspci_map_io(void)
-{
- iotable_init(nexuspci_io_desc);
-}
diff --git a/arch/arm/mm/mm-l7200.c b/arch/arm/mm/mm-l7200.c
deleted file mode 100644
index 1902d23fe..000000000
--- a/arch/arm/mm/mm-l7200.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * linux/arch/arm/mm/mm-lusl7200.c
- *
- * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
- *
- * Extra MM routines for L7200 architecture
- */
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/page.h>
-#include <asm/proc/domain.h>
-
-#include <asm/mach/map.h>
-
-static struct map_desc l7200_io_desc[] __initdata = {
- { IO_BASE, IO_START, IO_SIZE, DOMAIN_IO, 0, 1 ,0 ,0},
- { IO_BASE_2, IO_START_2, IO_SIZE_2, DOMAIN_IO, 0, 1 ,0 ,0},
- { AUX_BASE, AUX_START, AUX_SIZE, DOMAIN_IO, 0, 1 ,0 ,0},
- { FLASH1_BASE, FLASH1_START, FLASH1_SIZE, DOMAIN_IO, 0, 1 ,0 ,0},
- { FLASH2_BASE, FLASH2_START, FLASH2_SIZE, DOMAIN_IO, 0, 1 ,0 ,0},
- LAST_DESC
-};
-
-void __init l7200_map_io(void)
-{
- iotable_init(l7200_io_desc);
-}
diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c
deleted file mode 100644
index 5695b2ede..000000000
--- a/arch/arm/mm/mm-rpc.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * linux/arch/arm/mm/mm-rpc.c
- *
- * Copyright (C) 1998-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Extra MM routines for RiscPC architecture
- */
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/page.h>
-#include <asm/proc/domain.h>
-#include <asm/setup.h>
-
-#include <asm/mach/map.h>
-
-static struct map_desc rpc_io_desc[] __initdata = {
- { SCREEN_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1, 0, 0 }, /* VRAM */
- { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, /* IO space */
- { EASI_BASE, EASI_START, EASI_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* EASI space */
- LAST_DESC
-};
-
-void __init rpc_map_io(void)
-{
- iotable_init(rpc_io_desc);
-}
diff --git a/arch/arm/mm/mm-tbox.c b/arch/arm/mm/mm-tbox.c
deleted file mode 100644
index e927d05d3..000000000
--- a/arch/arm/mm/mm-tbox.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * linux/arch/arm/mm/mm-tbox.c
- *
- * Copyright (C) 1998, 1999, 2000 Phil Blundell
- * Copyright (C) 1998-1999 Russell King
- *
- * Extra MM routines for the Tbox architecture
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-static struct map_desc tbox_io_desc[] __initdata = {
- /* See hardware.h for details */
- { IO_BASE, IO_START, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 },
- LAST_DESC
-};
-
-void __init tbox_map_io(void)
-{
- iotable_init(tbox_io_desc);
-}
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 055d52c2e..195aca4d9 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -51,35 +51,12 @@
#define PAGESIZE 4096
.text
-
-/*
- * cpu_arm1020_data_abort()
- *
- * obtain information about current aborted instruction
- *
- * r0 = address of aborted instruction
- *
- * Returns:
- * r0 = address of abort
- * r1 != 0 if writing
- * r3 = FSR
- */
- .align 5
-ENTRY(cpu_arm1020_data_abort)
- ldr r1, [r0] @ read aborted instruction
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
- tst r1, r1, lsr #21 @ C = bit 20
- mrc p15, 0, r3, c5, c0, 0 @ get FSR
- sbc r1, r1, r1 @ r1 = C - 1
- and r3, r3, #255
- mov pc, lr
-
/*
* cpu_arm1020_check_bugs()
*/
ENTRY(cpu_arm1020_check_bugs)
mrs ip, cpsr
- bic ip, ip, #F_BIT
+ bic ip, ip, #PSR_F_BIT
msr cpsr, ip
mov pc, lr
@@ -94,7 +71,7 @@ ENTRY(cpu_arm1020_proc_init)
*/
ENTRY(cpu_arm1020_proc_fin)
stmfd sp!, {lr}
- mov ip, #F_BIT | I_BIT | SVC_MODE
+ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, ip
bl cpu_arm1020_cache_clean_invalidate_all
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
@@ -696,7 +673,7 @@ __arm1020_setup:
*/
.type arm1020_processor_functions, #object
arm1020_processor_functions:
- .word cpu_arm1020_data_abort
+ .word armv4t_early_abort
.word cpu_arm1020_check_bugs
.word cpu_arm1020_proc_init
.word cpu_arm1020_proc_fin
@@ -727,6 +704,11 @@ arm1020_processor_functions:
.word cpu_arm1020_set_pgd
.word cpu_arm1020_set_pmd
.word cpu_arm1020_set_pte
+
+ /* misc */
+ .word armv4_clear_user_page
+ .word armv4_copy_user_page
+
.size arm1020_processor_functions, . - arm1020_processor_functions
.type cpu_arm1020_info, #object
diff --git a/arch/arm/mm/proc-arm2,3.S b/arch/arm/mm/proc-arm2,3.S
index a550ac9d8..20405f25f 100644
--- a/arch/arm/mm/proc-arm2,3.S
+++ b/arch/arm/mm/proc-arm2,3.S
@@ -234,7 +234,7 @@ _arm2_proc_init:
*/
_arm3_proc_fin: mov r0, #2
mcr p15, 0, r0, c2, c0
-_arm2_proc_fin: orrs pc, lr, #I_BIT|F_BIT
+_arm2_proc_fin: orrs pc, lr, #PSR_I_BIT|PSR_F_BIT
/*
* Function: *_xchg_1 (int new, volatile void *ptr)
@@ -244,7 +244,7 @@ _arm2_proc_fin: orrs pc, lr, #I_BIT|F_BIT
* Returns : Original byte data at 'ptr'
*/
_arm2_xchg_1: mov r2, pc
- orr r2, r2, #I_BIT
+ orr r2, r2, #PSR_I_BIT
teqp r2, #0
ldrb r2, [r1]
strb r0, [r1]
@@ -262,7 +262,7 @@ _arm3_xchg_1: swpb r0, r0, [r1]
* Returns : Original word data at 'ptr'
*/
_arm2_xchg_4: mov r2, pc
- orr r2, r2, #I_BIT
+ orr r2, r2, #PSR_I_BIT
teqp r2, #0
ldr r2, [r1]
str r0, [r1]
diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S
index 1aefbbda7..b81cb3680 100644
--- a/arch/arm/mm/proc-arm6,7.S
+++ b/arch/arm/mm/proc-arm6,7.S
@@ -240,7 +240,7 @@ Ldata_lateldrpostreg:
ENTRY(cpu_arm6_check_bugs)
ENTRY(cpu_arm7_check_bugs)
mrs ip, cpsr
- bic ip, ip, #F_BIT
+ bic ip, ip, #PSR_F_BIT
msr cpsr, ip
mov pc, lr
@@ -250,7 +250,7 @@ ENTRY(cpu_arm7_proc_init)
ENTRY(cpu_arm6_proc_fin)
ENTRY(cpu_arm7_proc_fin)
- mov r0, #F_BIT | I_BIT | SVC_MODE
+ mov r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, r0
mov r0, #0x31 @ ....S..DP...M
mcr p15, 0, r0, c1, c0, 0 @ disable caches
@@ -418,6 +418,11 @@ ENTRY(arm6_processor_functions)
.word cpu_arm6_set_pgd
.word cpu_arm6_set_pmd
.word cpu_arm6_set_pte
+
+ /* other */
+ .word armv3_clear_user_page
+ .word armv3_copy_user_page
+
.size arm6_processor_functions, . - arm6_processor_functions
/*
@@ -457,6 +462,11 @@ ENTRY(arm7_processor_functions)
.word cpu_arm7_set_pgd
.word cpu_arm7_set_pmd
.word cpu_arm7_set_pte
+
+ /* other */
+ .word armv3_clear_user_page
+ .word armv3_copy_user_page
+
.size arm7_processor_functions, . - arm7_processor_functions
.type cpu_arm6_info, #object
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 5c96ce324..878dc7319 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -105,231 +105,6 @@ ENTRY(cpu_arm720_tlb_invalidate_page)
mov pc, lr
/*
- * Function: arm720_data_abort ()
- *
- * Params : r0 = address of aborted instruction
- * : r3 = saved SPSR
- *
- * Purpose : obtain information about current aborted instruction
- *
- * Returns : r0 = address of abort
- * : r1 != 0 if writing
- * : r3 = FSR
- * : sp = pointer to registers
- */
-
-Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit
- beq Ldata_simple
- mov r7, #0x11
- orr r7, r7, r7, lsl #8
- and r0, r4, r7
- and r2, r4, r7, lsl #1
- add r0, r0, r2, lsr #1
- and r2, r4, r7, lsl #2
- add r0, r0, r2, lsr #2
- and r2, r4, r7, lsl #3
- add r0, r0, r2, lsr #3
- add r0, r0, r0, lsr #8
- add r0, r0, r0, lsr #4
- and r7, r0, #15 @ r7 = no. of registers to transfer.
- and r5, r4, #15 << 16 @ Get Rn
- ldr r0, [sp, r5, lsr #14] @ Get register
- tst r4, #1 << 23 @ U bit
- subne r7, r0, r7, lsl #2
- addeq r7, r0, r7, lsl #2 @ Do correction (signed)
-Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
-Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
- mrc p15, 0, r3, c5, c0, 0 @ get FSR
- and r3, r3, #255
- mov pc, lr
-
-ENTRY(cpu_arm720_data_abort)
- tst r3, #T_BIT
- bne .data_thumb_abort
- ldr r4, [r0] @ read instruction causing problem
- tst r4, r4, lsr #21 @ C = bit 20
- sbc r1, r1, r1 @ r1 = C - 1
- and r2, r4, #15 << 24
- add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
- movs pc, lr
-
- b Ldata_lateldrhpost @ ldrh rd, [rn], #m/rm
- b Ldata_lateldrhpre @ ldrh rd, [rn, #m/rm]
- b Ldata_unknown
- b Ldata_unknown
- b Ldata_lateldrpostconst @ ldr rd, [rn], #m
- b Ldata_lateldrpreconst @ ldr rd, [rn, #m]
- b Ldata_lateldrpostreg @ ldr rd, [rn], rm
- b Ldata_lateldrprereg @ ldr rd, [rn, rm]
- b Ldata_ldmstm @ ldm*a rn, <rlist>
- b Ldata_ldmstm @ ldm*b rn, <rlist>
- b Ldata_unknown
- b Ldata_unknown
- b Ldata_simple @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
- b Ldata_simple @ ldc rd, [rn, #m]
- b Ldata_unknown
-
-Ldata_unknown: @ Part of jumptable
- mov r0, r2
- mov r1, r4
- mov r2, sp
- bl baddataabort
- b ret_from_exception
-
-Ldata_lateldrhpre:
- tst r4, #1 << 21 @ check writeback bit
- beq Ldata_simple
-Ldata_lateldrhpost:
- and r5, r4, #0x00f @ get Rm / low nibble of immediate value
- tst r4, #1 << 22 @ if (immediate offset)
- andne r2, r4, #0xf00 @ { immediate high nibble
- orrne r2, r5, r2, lsr #4 @ combine nibbles } else
- ldreq r2, [sp, r5, lsl #2] @ { load Rm value }
- and r5, r4, #15 << 16 @ get Rn
- ldr r0, [sp, r5, lsr #14] @ load Rn value
- tst r4, #1 << 23 @ U bit
- subne r7, r0, r2
- addeq r7, r0, r2
- b Ldata_saver7
-
-Ldata_lateldrpreconst:
- tst r4, #1 << 21 @ check writeback bit
- beq Ldata_simple
-Ldata_lateldrpostconst:
- movs r2, r4, lsl #20 @ Get offset
- beq Ldata_simple
- and r5, r4, #15 << 16 @ Get Rn
- ldr r0, [sp, r5, lsr #14]
- tst r4, #1 << 23 @ U bit
- subne r7, r0, r2, lsr #20
- addeq r7, r0, r2, lsr #20
- b Ldata_saver7
-
-Ldata_lateldrprereg:
- tst r4, #1 << 21 @ check writeback bit
- beq Ldata_simple
-Ldata_lateldrpostreg:
- and r5, r4, #15
- ldr r2, [sp, r5, lsl #2] @ Get Rm
- mov r3, r4, lsr #7
- ands r3, r3, #31
- and r6, r4, #0x70
- orreq r6, r6, #8
- add pc, pc, r6
- mov r0, r0
-
- mov r2, r2, lsl r3 @ 0: LSL #!0
- b 1f
- b 1f @ 1: LSL #0
- mov r0, r0
- b 1f @ 2: MUL?
- mov r0, r0
- b 1f @ 3: MUL?
- mov r0, r0
- mov r2, r2, lsr r3 @ 4: LSR #!0
- b 1f
- mov r2, r2, lsr #32 @ 5: LSR #32
- b 1f
- b 1f @ 6: MUL?
- mov r0, r0
- b 1f @ 7: MUL?
- mov r0, r0
- mov r2, r2, asr r3 @ 8: ASR #!0
- b 1f
- mov r2, r2, asr #32 @ 9: ASR #32
- b 1f
- b 1f @ A: MUL?
- mov r0, r0
- b 1f @ B: MUL?
- mov r0, r0
- mov r2, r2, ror r3 @ C: ROR #!0
- b 1f
- mov r2, r2, rrx @ D: RRX
- b 1f
- mov r0, r0 @ E: MUL?
- mov r0, r0
- mov r0, r0 @ F: MUL?
-
-
-1: and r5, r4, #15 << 16 @ Get Rn
- ldr r0, [sp, r5, lsr #14]
- tst r4, #1 << 23 @ U bit
- subne r7, r0, r2
- addeq r7, r0, r2
- b Ldata_saver7
-
-.data_thumb_abort:
- ldrh r4, [r0] @ read instruction
- tst r4, r4, lsr #12 @ C = bit 11
- sbc r1, r1, r1 @ r1 = C - 1
- and r2, r4, #15 << 12
- add pc, pc, r2, lsr #10 @ lookup in table
- nop
-
-/* 0 */ b Ldata_unknown
-/* 1 */ b Ldata_unknown
-/* 2 */ b Ldata_unknown
-/* 3 */ b Ldata_unknown
-/* 4 */ b Ldata_unknown
-/* 5 */ b .data_thumb_reg
-/* 6 */ b Ldata_simple
-/* 7 */ b Ldata_simple
-/* 8 */ b Ldata_simple
-/* 9 */ b Ldata_simple
-/* A */ b Ldata_unknown
-/* B */ b .data_thumb_pushpop
-/* C */ b .data_thumb_ldmstm
-/* D */ b Ldata_unknown
-/* E */ b Ldata_unknown
-/* F */ b Ldata_unknown
-
-.data_thumb_reg:
- tst r4, #1 << 9
- beq Ldata_simple
- tst r4, #1 << 10 @ If 'S' (signed) bit is set
- movne r1, #0 @ it must be a load instr
- b Ldata_simple
-
-.data_thumb_pushpop:
- tst r4, #1 << 10
- beq Ldata_unknown
- mov r7, #0x11
- and r0, r4, r7
- and r2, r4, r7, lsl #1
- add r0, r0, r2, lsr #1
- and r2, r4, r7, lsl #2
- add r0, r0, r2, lsr #2
- and r2, r4, r7, lsl #3
- add r0, r0, r2, lsr #3
- add r0, r0, r0, lsr #4
- and r2, r4, #0x0100 @ catch 'R' bit for push/pop
- add r0, r0, r2, lsr #8
- and r0, r0, #15 @ number of regs to transfer
- ldr r7, [sp, #13 << 2]
- tst r4, #1 << 11
- addne r7, r7, r0, lsl #2 @ increment SP if PUSH
- subeq r7, r7, r0, lsr #2 @ decrement SP if POP
- str r7, [sp, #13 << 2]
- b Ldata_simple
-
-.data_thumb_ldmstm:
- mov r7, #0x11
- and r0, r4, r7
- and r2, r4, r7, lsl #1
- add r0, r0, r2, lsr #1
- and r2, r4, r7, lsl #2
- add r0, r0, r2, lsr #2
- and r2, r4, r7, lsl #3
- add r0, r0, r2, lsr #3
- add r0, r0, r0, lsr #4
- and r0, r0, #15 @ number of regs to transfer
- and r5, r4, #7 << 8
- ldr r7, [sp, r5, lsr #6]
- sub r7, r7, r0, lsr #2 @ always decrement
- str r7, [sp, r5, lsr #6]
- b Ldata_simple
-
-/*
* Function: arm720_check_bugs (void)
* : arm720_proc_init (void)
* : arm720_proc_fin (void)
@@ -338,7 +113,7 @@ Ldata_lateldrpostreg:
*/
ENTRY(cpu_arm720_check_bugs)
mrs ip, cpsr
- bic ip, ip, #F_BIT
+ bic ip, ip, #PSR_F_BIT
msr cpsr, ip
mov pc, lr
@@ -347,7 +122,7 @@ ENTRY(cpu_arm720_proc_init)
ENTRY(cpu_arm720_proc_fin)
stmfd sp!, {lr}
- mov ip, #F_BIT | I_BIT | SVC_MODE
+ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, ip
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x1000 @ ...i............
@@ -462,7 +237,7 @@ __arm720_setup: mov r0, #0
*/
.type arm720_processor_functions, #object
ENTRY(arm720_processor_functions)
- .word cpu_arm720_data_abort
+ .word armv4t_late_abort
.word cpu_arm720_check_bugs
.word cpu_arm720_proc_init
.word cpu_arm720_proc_fin
@@ -493,6 +268,11 @@ ENTRY(arm720_processor_functions)
.word cpu_arm720_set_pgd
.word cpu_arm720_set_pmd
.word cpu_arm720_set_pte
+
+ /* misc */
+ .word armv4_clear_user_page
+ .word armv4_copy_user_page
+
.size arm720_processor_functions, . - arm720_processor_functions
.type cpu_arm720_info, #object
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 7481ae6ec..d09b7360a 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -51,35 +51,12 @@
#define PAGESIZE 4096
.text
-
-/*
- * cpu_arm920_data_abort()
- *
- * obtain information about current aborted instruction
- *
- * r0 = address of aborted instruction
- *
- * Returns:
- * r0 = address of abort
- * r1 != 0 if writing
- * r3 = FSR
- */
- .align 5
-ENTRY(cpu_arm920_data_abort)
- ldr r1, [r0] @ read aborted instruction
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
- tst r1, r1, lsr #21 @ C = bit 20
- mrc p15, 0, r3, c5, c0, 0 @ get FSR
- sbc r1, r1, r1 @ r1 = C - 1
- and r3, r3, #255
- mov pc, lr
-
/*
* cpu_arm920_check_bugs()
*/
ENTRY(cpu_arm920_check_bugs)
mrs ip, cpsr
- bic ip, ip, #F_BIT
+ bic ip, ip, #PSR_F_BIT
msr cpsr, ip
mov pc, lr
@@ -94,7 +71,7 @@ ENTRY(cpu_arm920_proc_init)
*/
ENTRY(cpu_arm920_proc_fin)
stmfd sp!, {lr}
- mov ip, #F_BIT | I_BIT | SVC_MODE
+ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, ip
bl cpu_arm920_cache_clean_invalidate_all
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
@@ -590,7 +567,7 @@ __arm920_setup:
*/
.type arm920_processor_functions, #object
arm920_processor_functions:
- .word cpu_arm920_data_abort
+ .word armv4t_early_abort
.word cpu_arm920_check_bugs
.word cpu_arm920_proc_init
.word cpu_arm920_proc_fin
@@ -621,6 +598,11 @@ arm920_processor_functions:
.word cpu_arm920_set_pgd
.word cpu_arm920_set_pmd
.word cpu_arm920_set_pte
+
+ /* misc */
+ .word armv4_clear_user_page
+ .word armv4_copy_user_page
+
.size arm920_processor_functions, . - arm920_processor_functions
.type cpu_arm920_info, #object
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
new file mode 100644
index 000000000..194698860
--- /dev/null
+++ b/arch/arm/mm/proc-arm922.S
@@ -0,0 +1,639 @@
+/*
+ * linux/arch/arm/mm/arm922.S: MMU functions for ARM922
+ *
+ * Copyright (C) 1999,2000 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ * Copyright (C) 2001 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * These are the low level assembler for performing cache and TLB
+ * functions on the arm922.
+ */
+#include <linux/linkage.h>
+#include <linux/config.h>
+#include <asm/assembler.h>
+#include <asm/constants.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+
+/*
+ * This is the maximum size of an area which will be invalidated
+ * using the single invalidate entry instructions. Anything larger
+ * than this, and we go for the whole cache.
+ *
+ * This value should be chosen such that we choose the cheapest
+ * alternative.
+ */
+#define MAX_AREA_SIZE 8192
+
+/*
+ * the cache line size of the I and D cache
+ */
+#define DCACHELINESIZE 32
+#define ICACHELINESIZE 32
+
+/*
+ * and the page size
+ */
+#define PAGESIZE 4096
+
+ .text
+/*
+ * cpu_arm922_check_bugs()
+ */
+ENTRY(cpu_arm922_check_bugs)
+ mrs ip, cpsr
+ bic ip, ip, #PSR_F_BIT
+ msr cpsr, ip
+ mov pc, lr
+
+/*
+ * cpu_arm922_proc_init()
+ */
+ENTRY(cpu_arm922_proc_init)
+ mov pc, lr
+
+/*
+ * cpu_arm922_proc_fin()
+ */
+ENTRY(cpu_arm922_proc_fin)
+ stmfd sp!, {lr}
+ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+ msr cpsr_c, ip
+ bl cpu_arm922_cache_clean_invalidate_all
+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
+ bic r0, r0, #0x1000 @ ...i............
+ bic r0, r0, #0x000e @ ............wca.
+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
+ ldmfd sp!, {pc}
+
+/*
+ * cpu_arm922_reset(loc)
+ *
+ * Perform a soft reset of the system. Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+ .align 5
+ENTRY(cpu_arm922_reset)
+ mov ip, #0
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
+ bic ip, ip, #0x000f @ ............wcam
+ bic ip, ip, #0x1100 @ ...i...s........
+ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
+ mov pc, r0
+
+/*
+ * cpu_arm922_do_idle()
+ */
+ .align 5
+ENTRY(cpu_arm922_do_idle)
+#if defined(CONFIG_CPU_ARM922_CPU_IDLE)
+ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
+#endif
+ mov pc, lr
+
+/* ================================= CACHE ================================ */
+
+
+/*
+ * cpu_arm922_cache_clean_invalidate_all()
+ *
+ * clean and invalidate all cache lines
+ *
+ * Note:
+ * 1. we should preserve r0 at all times
+ */
+ .align 5
+ENTRY(cpu_arm922_cache_clean_invalidate_all)
+ mov r2, #1
+cpu_arm922_cache_clean_invalidate_all_r2:
+ mov ip, #0
+#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
+#else
+/*
+ * 'Clean & Invalidate whole DCache'
+ * Re-written to use Index Ops.
+ * Uses registers r1, r3 and ip
+ */
+ mov r1, #3 << 5 @ 4 segments
+1: orr r3, r1, #63 << 26 @ 64 entries
+2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index
+ subs r3, r3, #1 << 26
+ bcs 2b @ entries 63 to 0
+ subs r1, r1, #1 << 5
+ bcs 1b @ segments 7 to 0
+#endif
+ teq r2, #0
+ mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/*
+ * cpu_arm922_cache_clean_invalidate_range(start, end, flags)
+ *
+ * clean and invalidate all cache lines associated with this area of memory
+ *
+ * start: Area start address
+ * end: Area end address
+ * flags: nonzero for I cache as well
+ */
+ .align 5
+ENTRY(cpu_arm922_cache_clean_invalidate_range)
+ bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM
+ bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
+ sub r3, r1, r0
+ cmp r3, #MAX_AREA_SIZE
+ bgt cpu_arm922_cache_clean_invalidate_all_r2
+1: teq r2, #0
+#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #DCACHELINESIZE
+#else
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #DCACHELINESIZE
+#endif
+ cmp r0, r1
+ blt 1b
+
+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/*
+ * cpu_arm922_flush_ram_page(page)
+ *
+ * clean and invalidate all cache lines associated with this area of memory
+ *
+ * page: page to clean and invalidate
+ */
+ .align 5
+ENTRY(cpu_arm922_flush_ram_page)
+ mov r1, #PAGESIZE
+#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+#else
+1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+#endif
+ subs r1, r1, #2 * DCACHELINESIZE
+ bne 1b
+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/* ================================ D-CACHE =============================== */
+
+/*
+ * cpu_arm922_dcache_invalidate_range(start, end)
+ *
+ * throw away all D-cached data in specified region without an obligation
+ * to write them back. Note however that we must clean the D-cached entries
+ * around the boundaries if the start and/or end address are not cache
+ * aligned.
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_arm922_dcache_invalidate_range)
+#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
+ tst r0, #DCACHELINESIZE - 1
+ mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
+ tst r1, #DCACHELINESIZE - 1
+ mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
+#endif @ clean D entry
+ bic r0, r0, #DCACHELINESIZE - 1
+ bic r1, r1, #DCACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
+ add r0, r0, #DCACHELINESIZE
+ cmp r0, r1
+ blt 1b
+ mov pc, lr
+
+/*
+ * cpu_arm922_dcache_clean_range(start, end)
+ *
+ * For the specified virtual address range, ensure that all caches contain
+ * clean data, such that peripheral accesses to the physical RAM fetch
+ * correct data.
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_arm922_dcache_clean_range)
+#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
+ bic r0, r0, #DCACHELINESIZE - 1
+ sub r1, r1, r0
+ cmp r1, #MAX_AREA_SIZE
+ mov r2, #0
+ bgt cpu_arm922_cache_clean_invalidate_all_r2
+
+ bic r1, r1, #DCACHELINESIZE -1
+ add r1, r1, #DCACHELINESIZE
+
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #DCACHELINESIZE
+ subs r1, r1, #DCACHELINESIZE
+ bpl 1b
+#endif
+ mcr p15, 0, r2, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/*
+ * cpu_arm922_dcache_clean_page(page)
+ *
+ * Cleans a single page of dcache so that if we have any future aliased
+ * mappings, they will be consistent at the time that they are created.
+ *
+ * page: virtual address of page to clean from dcache
+ *
+ * Note:
+ * 1. we don't need to flush the write buffer in this case.
+ * 2. we don't invalidate the entries since when we write the page
+ * out to disk, the entries may get reloaded into the cache.
+ */
+ .align 5
+ENTRY(cpu_arm922_dcache_clean_page)
+#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
+ mov r1, #PAGESIZE
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #DCACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #DCACHELINESIZE
+ subs r1, r1, #2 * DCACHELINESIZE
+ bne 1b
+#endif
+ mov pc, lr
+
+/*
+ * cpu_arm922_dcache_clean_entry(addr)
+ *
+ * Clean the specified entry of any caches such that the MMU
+ * translation fetches will obtain correct data.
+ *
+ * addr: cache-unaligned virtual address
+ */
+ .align 5
+ENTRY(cpu_arm922_dcache_clean_entry)
+#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+#endif
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/* ================================ I-CACHE =============================== */
+
+/*
+ * cpu_arm922_icache_invalidate_range(start, end)
+ *
+ * invalidate a range of virtual addresses from the Icache
+ *
+ * This is a little misleading, it is not intended to clean out
+ * the i-cache but to make sure that any data written to the
+ * range is made consistant. This means that when we execute code
+ * in that region, everything works as we expect.
+ *
+ * This generally means writing back data in the Dcache and
+ * write buffer and flushing the Icache over that region
+ *
+ * start: virtual start address
+ * end: virtual end address
+ *
+ * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
+ * loop twice, once for i-cache, once for d-cache)
+ */
+ .align 5
+ENTRY(cpu_arm922_icache_invalidate_range)
+ bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
+ sub r1, r1, r0
+ cmp r1, #MAX_AREA_SIZE
+ bgt cpu_arm922_cache_clean_invalidate_all_r2
+
+ bic r1, r1, #ICACHELINESIZE - 1
+ add r1, r1, #ICACHELINESIZE
+
+1: mcr p15, 0, r0, c7, c5, 1 @ Clean I entry
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
+ add r0, r0, #ICACHELINESIZE
+ subs r1, r1, #ICACHELINESIZE
+ bne 1b
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+ENTRY(cpu_arm922_icache_invalidate_page)
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
+ mov pc, lr
+
+/* ================================== TLB ================================= */
+
+/*
+ * cpu_arm922_tlb_invalidate_all()
+ *
+ * Invalidate all TLB entries
+ */
+ .align 5
+ENTRY(cpu_arm922_tlb_invalidate_all)
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D TLBs
+ mov pc, lr
+
+/*
+ * cpu_arm922_tlb_invalidate_range(start, end)
+ *
+ * invalidate TLB entries covering the specified range
+ *
+ * start: range start address
+ * end: range end address
+ */
+ .align 5
+ENTRY(cpu_arm922_tlb_invalidate_range)
+ mov r3, #0
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+
+ mov r3, #PAGESIZE
+ sub r3, r3, #1
+ bic r0, r0, r3
+ bic r1, r1, r3
+
+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
+ add r0, r0, #PAGESIZE
+ cmp r0, r1
+ blt 1b
+ mov pc, lr
+
+/*
+ * cpu_arm922_tlb_invalidate_page(page, flags)
+ *
+ * invalidate the TLB entries for the specified page.
+ *
+ * page: page to invalidate
+ * flags: non-zero if we include the I TLB
+ */
+ .align 5
+ENTRY(cpu_arm922_tlb_invalidate_page)
+ mov r3, #0
+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
+ teq r1, #0
+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
+ mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
+ mov pc, lr
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_arm922_set_pgd(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+ .align 5
+ENTRY(cpu_arm922_set_pgd)
+ mov ip, #0
+#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+ /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
+ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
+#else
+@ && 'Clean & Invalidate whole DCache'
+@ && Re-written to use Index Ops.
+@ && Uses registers r1, r3 and ip
+
+ mov r1, #3 << 5 @ 4 segments
+1: orr r3, r1, #63 << 26 @ 64 entries
+2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index
+ subs r3, r3, #1 << 26
+ bcs 2b @ entries 63 to 0
+ subs r1, r1, #1 << 5
+ bcs 1b @ segments 7 to 0
+#endif
+ mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mov pc, lr
+
+/*
+ * cpu_arm922_set_pmd(pmdp, pmd)
+ *
+ * Set a level 1 translation table entry, and clean it out of
+ * any caches such that the MMUs can load it correctly.
+ *
+ * pmdp: pointer to PMD entry
+ * pmd: PMD value to store
+ */
+ .align 5
+ENTRY(cpu_arm922_set_pmd)
+#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+ eor r2, r1, #0x0a @ C & Section
+ tst r2, #0x0b
+ biceq r1, r1, #4 @ clear bufferable bit
+#endif
+ str r1, [r0]
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+/*
+ * cpu_arm922_set_pte(ptep, pte)
+ *
+ * Set a PTE and flush it out
+ */
+ .align 5
+ENTRY(cpu_arm922_set_pte)
+ str r1, [r0], #-1024 @ linux version
+
+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
+
+ bic r2, r1, #0xff0
+ bic r2, r2, #3
+ orr r2, r2, #HPTE_TYPE_SMALL
+
+ tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
+ orrne r2, r2, #HPTE_AP_READ
+
+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #HPTE_AP_WRITE
+
+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
+ movne r2, #0
+
+#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+ eor r3, r2, #0x0a @ C & small page?
+ tst r3, #0x0b
+ biceq r2, r2, #4
+#endif
+ str r2, [r0] @ hardware version
+ mov r0, r0
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+
+cpu_manu_name:
+ .asciz "ARM/ALTERA"
+ENTRY(cpu_arm922_name)
+ .ascii "Arm922T"
+#if defined(CONFIG_CPU_ARM922_CPU_IDLE)
+ .ascii "s"
+#endif
+#if defined(CONFIG_CPU_ARM922_I_CACHE_ON)
+ .ascii "i"
+#endif
+#if defined(CONFIG_CPU_ARM922_D_CACHE_ON)
+ .ascii "d"
+#if defined(CONFIG_CPU_ARM922_WRITETHROUGH)
+ .ascii "(wt)"
+#else
+ .ascii "(wb)"
+#endif
+#endif
+ .ascii "\0"
+ .align
+
+ .section ".text.init", #alloc, #execinstr
+
+__arm922_setup:
+ mov r0, #0
+ mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
+ mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
+ mcr p15, 0, r4, c2, c0 @ load page table pointer
+ mov r0, #0x1f @ Domains 0, 1 = client
+ mcr p15, 0, r0, c3, c0 @ load domain access register
+ mrc p15, 0, r0, c1, c0 @ get control register v4
+/*
+ * Clear out 'unwanted' bits (then put them in if we need them)
+ */
+ @ VI ZFRS BLDP WCAM
+ bic r0, r0, #0x0e00
+ bic r0, r0, #0x0002
+ bic r0, r0, #0x000c
+ bic r0, r0, #0x1000 @ ...0 000. .... 000.
+/*
+ * Turn on what we want
+ */
+ orr r0, r0, #0x0031
+ orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1
+
+#ifdef CONFIG_CPU_ARM922_D_CACHE_ON
+ orr r0, r0, #0x0004 @ .... .... .... .1..
+#endif
+#ifdef CONFIG_CPU_ARM922_I_CACHE_ON
+ orr r0, r0, #0x1000 @ ...1 .... .... ....
+#endif
+ mov pc, lr
+
+ .text
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ * come through these
+ */
+ .type arm922_processor_functions, #object
+arm922_processor_functions:
+ .word armv4t_early_abort
+ .word cpu_arm922_check_bugs
+ .word cpu_arm922_proc_init
+ .word cpu_arm922_proc_fin
+ .word cpu_arm922_reset
+ .word cpu_arm922_do_idle
+
+ /* cache */
+ .word cpu_arm922_cache_clean_invalidate_all
+ .word cpu_arm922_cache_clean_invalidate_range
+ .word cpu_arm922_flush_ram_page
+
+ /* dcache */
+ .word cpu_arm922_dcache_invalidate_range
+ .word cpu_arm922_dcache_clean_range
+ .word cpu_arm922_dcache_clean_page
+ .word cpu_arm922_dcache_clean_entry
+
+ /* icache */
+ .word cpu_arm922_icache_invalidate_range
+ .word cpu_arm922_icache_invalidate_page
+
+ /* tlb */
+ .word cpu_arm922_tlb_invalidate_all
+ .word cpu_arm922_tlb_invalidate_range
+ .word cpu_arm922_tlb_invalidate_page
+
+ /* pgtable */
+ .word cpu_arm922_set_pgd
+ .word cpu_arm922_set_pmd
+ .word cpu_arm922_set_pte
+
+ /* misc */
+ .word armv4_clear_user_page
+ .word armv4_copy_user_page
+
+ .size arm922_processor_functions, . - arm922_processor_functions
+
+ .type cpu_arm922_info, #object
+cpu_arm922_info:
+ .long cpu_manu_name
+ .long cpu_arm922_name
+ .size cpu_arm922_info, . - cpu_arm922_info
+
+ .type cpu_arch_name, #object
+cpu_arch_name:
+ .asciz "armv4"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name:
+ .asciz "v4"
+ .size cpu_elf_name, . - cpu_elf_name
+ .align
+
+ .section ".proc.info", #alloc, #execinstr
+
+ .type __arm922_proc_info,#object
+__arm922_proc_info:
+ .long 0x41009220
+ .long 0xff00fff0
+ .long 0x00000c1e @ mmuflags
+ b __arm922_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+ .long cpu_arm922_info
+ .long arm922_processor_functions
+ .size __arm922_proc_info, . - __arm922_proc_info
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index d3ecda0ca..27b9a6f51 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -56,35 +56,39 @@
* cpu_arm926_data_abort()
*
* obtain information about current aborted instruction
+ * Note: we read user space. This means we might cause a data
+ * abort here if the I-TLB and D-TLB aren't seeing the same
+ * picture. Unfortunately, this does happen. We live with it.
*
* Inputs:
- * r0 = address of abort
- * r1 = cpsr of abort
+ * r2 = address of abort
+ * r3 = cpsr of abort
*
* Returns:
* r0 = address of abort
* r1 != 0 if writing
* r3 = FSR
+ * r4 = corrupted
*/
.align 5
ENTRY(cpu_arm926_data_abort)
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+ mrc p15, 0, r4, c5, c0, 0 @ get FSR
+
tst r1, #1<<24 @ Check for Jbit (NE -> found)
movne r1, #-1 @ Mark as writing
bne 2f
- tst r1, #1<<5 @ Check for Thumb-bit (NE -> found)
- ldrneh r1, [r0] @ Read aborted Thumb instruction
+ tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
+ ldrneh r1, [r2] @ Read aborted Thumb instruction
tstne r1, r1, lsr #12 @ C = bit 11
- ldreq r1, [r0] @ Read aborted ARM instruction
+ ldreq r1, [r2] @ Read aborted ARM instruction
tsteq r1, r1, lsr #21 @ C = bit 20
sbc r1, r1, r1 @ r1 = C - 1
2:
- mrc p15, 0, r3, c5, c0, 0 @ get FSR
- and r3, r3, #255
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-
+ and r3, r4, #255
mov pc, lr
/*
@@ -92,7 +96,7 @@ ENTRY(cpu_arm926_data_abort)
*/
ENTRY(cpu_arm926_check_bugs)
mrs ip, cpsr
- bic ip, ip, #F_BIT
+ bic ip, ip, #PSR_F_BIT
msr cpsr, ip
mov pc, lr
@@ -107,7 +111,7 @@ ENTRY(cpu_arm926_proc_init)
*/
ENTRY(cpu_arm926_proc_fin)
stmfd sp!, {lr}
- mov ip, #F_BIT | I_BIT | SVC_MODE
+ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, ip
bl cpu_arm926_cache_clean_invalidate_all
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
@@ -601,7 +605,7 @@ __arm926_setup:
*/
.type arm926_processor_functions, #object
arm926_processor_functions:
- .word cpu_arm926_data_abort
+ .word armv5ej_early_abort
.word cpu_arm926_check_bugs
.word cpu_arm926_proc_init
.word cpu_arm926_proc_fin
@@ -632,6 +636,11 @@ arm926_processor_functions:
.word cpu_arm926_set_pgd
.word cpu_arm926_set_pmd
.word cpu_arm926_set_pte
+
+ /* misc */
+ .word armv4_clear_user_page
+ .word armv4_copy_user_page
+
.size arm926_processor_functions, . - arm926_processor_functions
.type cpu_arm926_info, #object
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index e12f6cace..16dc37e7c 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -22,6 +22,7 @@
#include <asm/constants.h>
#include <asm/procinfo.h>
#include <asm/hardware.h>
+#include <asm/proc/pgtable.h>
/* This is the maximum size of an area which will be flushed. If the area
* is larger than this, then we flush the whole cache
@@ -41,6 +42,10 @@
#define FLUSH_OFFSET 32768
.macro flush_110_dcache rd, ra, re
+ ldr \rd, =flush_base
+ ldr \ra, [\rd]
+ eor \ra, \ra, #FLUSH_OFFSET
+ str \ra, [\rd]
add \re, \ra, #16384 @ only necessary for 16k
1001: ldr \rd, [\ra], #DCACHELINESIZE
teq \re, \ra
@@ -48,6 +53,10 @@
.endm
.macro flush_1100_dcache rd, ra, re
+ ldr \rd, =flush_base
+ ldr \ra, [\rd]
+ eor \ra, \ra, #FLUSH_OFFSET
+ str \ra, [\rd]
add \re, \ra, #8192 @ only necessary for 8k
1001: ldr \rd, [\ra], #DCACHELINESIZE
teq \re, \ra
@@ -62,40 +71,16 @@
.endm
.data
-Lclean_switch: .long 0
+flush_base: .long FLUSH_BASE
.text
-
-/*
- * cpu_sa110_data_abort()
- *
- * obtain information about current aborted instruction
- *
- * r0 = address of aborted instruction
- *
- * Returns:
- * r0 = address of abort
- * r1 != 0 if writing
- * r3 = FSR
- */
- .align 5
-ENTRY(cpu_sa110_data_abort)
-ENTRY(cpu_sa1100_data_abort)
- ldr r1, [r0] @ read aborted instruction
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
- tst r1, r1, lsr #21 @ C = bit 20
- mrc p15, 0, r3, c5, c0, 0 @ get FSR
- sbc r1, r1, r1 @ r1 = C - 1
- and r3, r3, #255
- mov pc, lr
-
/*
* cpu_sa110_check_bugs()
*/
ENTRY(cpu_sa110_check_bugs)
ENTRY(cpu_sa1100_check_bugs)
mrs ip, cpsr
- bic ip, ip, #F_BIT
+ bic ip, ip, #PSR_F_BIT
msr cpsr, ip
mov pc, lr
@@ -113,7 +98,7 @@ ENTRY(cpu_sa1100_proc_init)
*/
ENTRY(cpu_sa110_proc_fin)
stmfd sp!, {lr}
- mov ip, #F_BIT | I_BIT | SVC_MODE
+ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, ip
bl cpu_sa110_cache_clean_invalidate_all @ clean caches
1: mov r0, #0
@@ -126,7 +111,7 @@ ENTRY(cpu_sa110_proc_fin)
ENTRY(cpu_sa1100_proc_fin)
stmfd sp!, {lr}
- mov ip, #F_BIT | I_BIT | SVC_MODE
+ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, ip
bl cpu_sa1100_cache_clean_invalidate_all @ clean caches
b 1b
@@ -224,13 +209,6 @@ ENTRY(cpu_sa1100_do_idle)
ENTRY(cpu_sa110_cache_clean_invalidate_all)
mov r2, #1
cpu_sa110_cache_clean_invalidate_all_r2:
- ldr r3, =Lclean_switch
- ldr ip, =FLUSH_BASE
- ldr r1, [r3]
- ands r1, r1, #1
- eor r1, r1, #1
- str r1, [r3]
- addne ip, ip, #FLUSH_OFFSET
flush_110_dcache r3, ip, r1
mov ip, #0
teq r2, #0
@@ -242,13 +220,6 @@ cpu_sa110_cache_clean_invalidate_all_r2:
ENTRY(cpu_sa1100_cache_clean_invalidate_all)
mov r2, #1
cpu_sa1100_cache_clean_invalidate_all_r2:
- ldr r3, =Lclean_switch
- ldr ip, =FLUSH_BASE
- ldr r1, [r3]
- ands r1, r1, #1
- eor r1, r1, #1
- str r1, [r3]
- addne ip, ip, #FLUSH_OFFSET
flush_1100_dcache r3, ip, r1
mov ip, #0
teq r2, #0
@@ -501,13 +472,6 @@ ENTRY(cpu_sa1100_tlb_invalidate_page)
*/
.align 5
ENTRY(cpu_sa110_set_pgd)
- ldr r3, =Lclean_switch
- ldr ip, =FLUSH_BASE
- ldr r2, [r3]
- ands r2, r2, #1
- eor r2, r2, #1
- str r2, [r3]
- addne ip, ip, #FLUSH_OFFSET
flush_110_dcache r3, ip, r1
mov r1, #0
mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache
@@ -525,13 +489,6 @@ ENTRY(cpu_sa110_set_pgd)
*/
.align 5
ENTRY(cpu_sa1100_set_pgd)
- ldr r3, =Lclean_switch
- ldr ip, =FLUSH_BASE
- ldr r2, [r3]
- ands r2, r2, #1
- eor r2, r2, #1
- str r2, [r3]
- addne ip, ip, #FLUSH_OFFSET
flush_1100_dcache r3, ip, r1
mov ip, #0
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
@@ -568,19 +525,19 @@ ENTRY(cpu_sa110_set_pte)
ENTRY(cpu_sa1100_set_pte)
str r1, [r0], #-1024 @ linux version
- eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
+ eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
bic r2, r1, #0xff0
bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
+ orr r2, r2, #PTE_TYPE_SMALL
- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
- orrne r2, r2, #HPTE_AP_READ
+ tst r1, #L_PTE_USER | L_PTE_EXEC @ User or Exec?
+ orrne r2, r2, #PTE_SMALL_AP_URO_SRW
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
- orreq r2, r2, #HPTE_AP_WRITE
+ tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #PTE_SMALL_AP_UNO_SRW
- tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
+ tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
movne r2, #0
str r2, [r0] @ hardware version
@@ -636,7 +593,7 @@ __setup_common:
.type sa110_processor_functions, #object
ENTRY(sa110_processor_functions)
- .word cpu_sa110_data_abort
+ .word armv4_early_abort
.word cpu_sa110_check_bugs
.word cpu_sa110_proc_init
.word cpu_sa110_proc_fin
@@ -667,6 +624,11 @@ ENTRY(sa110_processor_functions)
.word cpu_sa110_set_pgd
.word cpu_sa110_set_pmd
.word cpu_sa110_set_pte
+
+ /* misc */
+ .word armv4_clear_user_page
+ .word armv4_copy_user_page
+
.size sa110_processor_functions, . - sa110_processor_functions
.type cpu_sa110_info, #object
@@ -681,7 +643,7 @@ cpu_sa110_info:
*/
.type sa1100_processor_functions, #object
ENTRY(sa1100_processor_functions)
- .word cpu_sa1100_data_abort
+ .word armv4_early_abort
.word cpu_sa1100_check_bugs
.word cpu_sa1100_proc_init
.word cpu_sa1100_proc_fin
@@ -712,6 +674,11 @@ ENTRY(sa1100_processor_functions)
.word cpu_sa1100_set_pgd
.word cpu_sa1100_set_pmd
.word cpu_sa1100_set_pte
+
+ /* misc */
+ .word armv4_clear_user_page
+ .word armv4_copy_user_page
+
.size sa1100_processor_functions, . - sa1100_processor_functions
cpu_sa1100_info:
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
new file mode 100644
index 000000000..bfd447213
--- /dev/null
+++ b/arch/arm/mm/proc-xscale.S
@@ -0,0 +1,812 @@
+/*
+ * linux/arch/arm/mm/proc-xscale.S
+ *
+ * Author: Nicolas Pitre
+ * Created: November 2000
+ * Copyright: (C) 2000, 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * MMU functions for the Intel XScale CPUs
+ *
+ * 2001 Aug 21:
+ * some contributions by Brett Gaines <brett.w.gaines@intel.com>
+ * Copyright 2001 by Intel Corp.
+ *
+ * 2001 Sep 08:
+ * Completely revisited, many important fixes
+ * Nicolas Pitre <nico@cam.org>
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/constants.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+#include <asm/proc/pgtable.h>
+
+/*
+ * This is the maximum size of an area which will be flushed. If the area
+ * is larger than this, then we flush the whole cache
+ */
+#define MAX_AREA_SIZE 32768
+
+/*
+ * the cache line size of the I and D cache
+ */
+#define CACHELINESIZE 32
+
+/*
+ * the size of the data cache
+ */
+#define CACHESIZE 32768
+
+/*
+ * and the page size
+ */
+#define PAGESIZE 4096
+
+/*
+ * Virtual address used to allocate the cache when flushed
+ *
+ * This must be an address range which is _never_ used. It should
+ * apparently have a mapping in the corresponding page table for
+ * compatibility with future CPUs that _could_ require it. For instance we
+ * don't care.
+ *
+ * This must be aligned on a 2*CACHESIZE boundary. The code selects one of
+ * the 2 areas in alternance each time the clean_d_cache macro is used.
+ * Without this the XScale core exhibits cache eviction problems and no one
+ * knows why.
+ *
+ * Reminder: the vector table is located at 0xffff0000-0xffff0fff.
+ */
+#define CLEAN_ADDR 0xfffe0000
+
+/*
+ * This macro is used to wait for a CP15 write and is needed
+ * when we have to ensure that the last operation to the co-pro
+ * was completed before continuing with operation.
+ */
+ .macro cpwait, rd
+ mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
+ mov \rd, \rd @ wait for completion
+ sub pc, pc, #4 @ flush instruction pipeline
+ .endm
+
+ .macro cpwait_ret, lr, rd
+ mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
+ sub pc, \lr, \rd, LSR #32 @ wait for completion and
+ @ flush instruction pipeline
+ .endm
+
+/*
+ * This macro cleans the entire dcache using line allocate.
+ * The main loop has been unrolled to reduce loop overhead.
+ * rd and rs are two scratch registers.
+ */
+ .macro clean_d_cache, rd, rs
+ ldr \rs, =clean_addr
+ ldr \rd, [\rs]
+ eor \rd, \rd, #CACHESIZE
+ str \rd, [\rs]
+ add \rs, \rd, #CACHESIZE
+1: mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
+ add \rd, \rd, #CACHELINESIZE
+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
+ add \rd, \rd, #CACHELINESIZE
+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
+ add \rd, \rd, #CACHELINESIZE
+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
+ add \rd, \rd, #CACHELINESIZE
+ teq \rd, \rs
+ bne 1b
+ .endm
+
+ .data
+clean_addr: .word CLEAN_ADDR
+
+ .text
+
+/*
+ * cpu_xscale_check_bugs()
+ */
+ENTRY(cpu_xscale_check_bugs)
+ mrs ip, cpsr
+ bic ip, ip, #PSR_F_BIT
+ msr cpsr, ip
+ mov pc, lr
+
+/*
+ * cpu_xscale_proc_init()
+ *
+ * Nothing too exciting at the moment
+ */
+ENTRY(cpu_xscale_proc_init)
+ mov pc, lr
+
+/*
+ * cpu_xscale_proc_fin()
+ */
+ENTRY(cpu_xscale_proc_fin)
+ str lr, [sp, #-4]!
+ mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r0
+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
+ bic r0, r0, #0x1800 @ ...IZ...........
+ bic r0, r0, #0x0006 @ .............CA.
+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
+ bl cpu_xscale_cache_clean_invalidate_all @ clean caches
+ ldr pc, [sp], #4
+
+/*
+ * cpu_xscale_reset(loc)
+ *
+ * Perform a soft reset of the system. Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+ .align 5
+ENTRY(cpu_xscale_reset)
+ mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r1 @ reset CPSR
+ mrc p15, 0, r1, c1, c0, 0 @ ctrl register
+ bic r1, r1, #0x0086 @ ........B....CA.
+ bic r1, r1, #0x1900 @ ...IZ..S........
+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB
+ bic r1, r1, #0x0001 @ ...............M
+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
+ @ CAUTION: MMU turned off from this point. We count on the pipeline
+ @ already containing those two last instructions to survive.
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mov pc, r0
+
+/*
+ * cpu_xscale_do_idle(type)
+ *
+ * Cause the processor to idle
+ *
+ * type:
+ * 0 = slow idle
+ * 1 = fast idle
+ * 2 = switch to slow processor clock
+ * 3 = switch to fast processor clock
+ *
+ * For now we do nothing but go to idle mode for every case
+ *
+ * XScale supports clock switching, but using idle mode support
+ * allows external hardware to react to system state changes.
+ */
+ .align 5
+
+ENTRY(cpu_xscale_do_idle)
+ mov r0, #1
+ mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE
+ mov pc, lr
+
+/* ================================= CACHE ================================ */
+
+/*
+ * cpu_xscale_cache_clean_invalidate_all (void)
+ *
+ * clean and invalidate all cache lines
+ *
+ * Note:
+ * 1. We should preserve r0 at all times.
+ * 2. Even if this function implies cache "invalidation" by its name,
+ * we don't need to actually use explicit invalidation operations
+ * since the goal is to discard all valid references from the cache
+ * and the cleaning of it already has that effect.
+ * 3. Because of 2 above and the fact that kernel space memory is always
+ * coherent across task switches there is no need to worry about
+ * inconsistencies due to interrupts, ence no irq disabling.
+ */
+ .align 5
+ENTRY(cpu_xscale_cache_clean_invalidate_all)
+ mov r2, #1
+cpu_xscale_cache_clean_invalidate_all_r2:
+ clean_d_cache r0, r1
+ teq r2, #0
+ mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov pc, lr
+
+/*
+ * cpu_xscale_cache_clean_invalidate_range(start, end, flags)
+ *
+ * clean and invalidate all cache lines associated with this area of memory
+ *
+ * start: Area start address
+ * end: Area end address
+ * flags: nonzero for I cache as well
+ */
+ .align 5
+ENTRY(cpu_xscale_cache_clean_invalidate_range)
+ bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line
+ sub r3, r1, r0
+ cmp r3, #MAX_AREA_SIZE
+ bhi cpu_xscale_cache_clean_invalidate_all_r2
+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ teq r2, #0
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ moveq pc, lr
+ sub r0, r0, r3
+1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB
+ mov pc, lr
+
+/*
+ * cpu_xscale_flush_ram_page(page)
+ *
+ * clean all cache lines associated with this memory page
+ *
+ * page: page to clean
+ */
+ .align 5
+ENTRY(cpu_xscale_flush_ram_page)
+ mov r1, #PAGESIZE
+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ add r0, r0, #CACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ add r0, r0, #CACHELINESIZE
+ subs r1, r1, #2 * CACHELINESIZE
+ bne 1b
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov pc, lr
+
+/* ================================ D-CACHE =============================== */
+
+/*
+ * cpu_xscale_dcache_invalidate_range(start, end)
+ *
+ * throw away all D-cached data in specified region without an obligation
+ * to write them back. Note however that on XScale we must clean all
+ * entries also due to hardware errata (80200 A0 & A1 only).
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_xscale_dcache_invalidate_range)
+ mrc p15, 0, r2, c0, c0, 0 @ Read part no.
+ eor r2, r2, #0x69000000
+ eor r2, r2, #0x00052000 @ 80200 XX part no.
+ bics r2, r2, #0x1 @ Clear LSB in revision field
+ moveq r2, #0
+ beq cpu_xscale_cache_clean_invalidate_range @ An 80200 A0 or A1
+
+ tst r0, #CACHELINESIZE - 1
+ mcrne p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ tst r1, #CACHELINESIZE - 1
+ mcrne p15, 0, r1, c7, c10, 1 @ Clean D cache line
+ bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line
+1: mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mov pc, lr
+
+/*
+ * cpu_xscale_dcache_clean_range(start, end)
+ *
+ * For the specified virtual address range, ensure that all caches contain
+ * clean data, such that peripheral accesses to the physical RAM fetch
+ * correct data.
+ *
+ * start: virtual start address
+ * end: virtual end address
+ */
+ .align 5
+ENTRY(cpu_xscale_dcache_clean_range)
+ bic r0, r0, #CACHELINESIZE - 1
+ sub r2, r1, r0
+ cmp r2, #MAX_AREA_SIZE
+ movhi r2, #0
+ bhi cpu_xscale_cache_clean_invalidate_all_r2
+
+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ add r0, r0, #CACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov pc, lr
+
+/*
+ * cpu_xscale_clean_dcache_page(page)
+ *
+ * Cleans a single page of dcache so that if we have any future aliased
+ * mappings, they will be consistent at the time that they are created.
+ *
+ * Note:
+ * 1. we don't need to flush the write buffer in this case. [really? -Nico]
+ * 2. we don't invalidate the entries since when we write the page
+ * out to disk, the entries may get reloaded into the cache.
+ */
+ .align 5
+ENTRY(cpu_xscale_dcache_clean_page)
+ mov r1, #PAGESIZE
+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ add r0, r0, #CACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ add r0, r0, #CACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ add r0, r0, #CACHELINESIZE
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ add r0, r0, #CACHELINESIZE
+ subs r1, r1, #4 * CACHELINESIZE
+ bne 1b
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov pc, lr
+
+/*
+ * cpu_xscale_dcache_clean_entry(addr)
+ *
+ * Clean the specified entry of any caches such that the MMU
+ * translation fetches will obtain correct data.
+ *
+ * addr: cache-unaligned virtual address
+ */
+ .align 5
+ENTRY(cpu_xscale_dcache_clean_entry)
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov pc, lr
+
+/* ================================ I-CACHE =============================== */
+
+/*
+ * cpu_xscale_icache_invalidate_range(start, end)
+ *
+ * invalidate a range of virtual addresses from the Icache
+ *
+ * start: virtual start address
+ * end: virtual end address
+ *
+ * Note: This is vaguely defined as supposed to bring the dcache and the
+ * icache in sync by the way this function is used.
+ */
+ .align 5
+ENTRY(cpu_xscale_icache_invalidate_range)
+ bic r0, r0, #CACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov pc, lr
+
+/*
+ * cpu_xscale_icache_invalidate_page(page)
+ *
+ * invalidate all Icache lines associated with this area of memory
+ *
+ * page: page to invalidate
+ */
+ .align 5
+ENTRY(cpu_xscale_icache_invalidate_page)
+ mov r1, #PAGESIZE
+1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
+ add r0, r0, #CACHELINESIZE
+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
+ add r0, r0, #CACHELINESIZE
+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
+ add r0, r0, #CACHELINESIZE
+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
+ add r0, r0, #CACHELINESIZE
+ subs r1, r1, #4 * CACHELINESIZE
+ bne 1b
+ mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB
+ mov pc, lr
+
+/* ================================ CACHE LOCKING============================
+ *
+ * The XScale MicroArchitecture implements support for locking entries into
+ * the data and instruction cache. The following functions implement the core
+ * low level instructions needed to accomplish the locking. The developer's
+ * manual states that the code that performs the locking must be in non-cached
+ * memory. To accomplish this, the code in xscale-cache-lock.c copies the
+ * following functions from the cache into a non-cached memory region that
+ * is allocated through consistent_alloc().
+ *
+ */
+ .align 5
+/*
+ * xscale_icache_lock
+ *
+ * r0: starting address to lock
+ * r1: end address to lock
+ */
+ENTRY(xscale_icache_lock)
+
+iLockLoop:
+ bic r0, r0, #CACHELINESIZE - 1
+ mcr p15, 0, r0, c9, c1, 0 @ lock into cache
+ cmp r0, r1 @ are we done?
+ add r0, r0, #CACHELINESIZE @ advance to next cache line
+ bls iLockLoop
+ mov pc, lr
+
+/*
+ * xscale_icache_unlock
+ */
+ENTRY(xscale_icache_unlock)
+ mcr p15, 0, r0, c9, c1, 1 @ Unlock icache
+ mov pc, lr
+
+/*
+ * xscale_dcache_lock
+ *
+ * r0: starting address to lock
+ * r1: end address to lock
+ */
+ENTRY(xscale_dcache_lock)
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov r2, #1
+ mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode
+ cpwait ip @ Wait for completion
+
+ mrs r2, cpsr
+ orr r3, r2, #PSR_F_BIT | PSR_I_BIT
+dLockLoop:
+ msr cpsr_c, r3
+ mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty
+ mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line
+ msr cpsr_c, r2
+ ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from
+ @ location [r0]. Post-increment
+ @ r3 to next cache line
+ cmp r0, r1 @ Are we done?
+ bls dLockLoop
+
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov r2, #0
+ mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode
+ cpwait_ret lr, ip
+
+/*
+ * xscale_dcache_unlock
+ */
+ENTRY(xscale_dcache_unlock)
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mcr p15, 0, ip, c9, c2, 1 @ Unlock cache
+ mov pc, lr
+
+/*
+ * Needed to determine the length of the code that needs to be copied.
+ */
+ .align 5
+ENTRY(xscale_cache_dummy)
+ mov pc, lr
+
+/* ================================== TLB ================================= */
+
+/*
+ * cpu_xscale_tlb_invalidate_all()
+ *
+ * Invalidate all TLB entries
+ */
+ .align 5
+ENTRY(cpu_xscale_tlb_invalidate_all)
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ cpwait_ret lr, ip
+
+/*
+ * cpu_xscale_tlb_invalidate_range(start, end)
+ *
+ * invalidate TLB entries covering the specified range
+ *
+ * start: range start address
+ * end: range end address
+ */
+ .align 5
+ENTRY(cpu_xscale_tlb_invalidate_range)
+ bic r0, r0, #(PAGESIZE - 1) & 0x00ff
+ bic r0, r0, #(PAGESIZE - 1) & 0xff00
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
+ add r0, r0, #PAGESIZE
+ cmp r0, r1
+ blo 1b
+ cpwait_ret lr, ip
+
+/*
+ * cpu_xscale_tlb_invalidate_page(page, flags)
+ *
+ * invalidate the TLB entries for the specified page.
+ *
+ * page: page to invalidate
+ * flags: non-zero if we include the I TLB
+ */
+ .align 5
+ENTRY(cpu_xscale_tlb_invalidate_page)
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ teq r1, #0
+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
+ mcrne p15, 0, r3, c8, c5, 1 @ invalidate I TLB entry
+ cpwait_ret lr, ip
+
+/* ================================ TLB LOCKING==============================
+ *
+ * The XScale MicroArchitecture implements support for locking entries into
+ * the Instruction and Data TLBs. The following functions provide the
+ * low level support for supporting these under Linux. xscale-lock.c
+ * implements some higher level management code. Most of the following
+ * is taken straight out of the Developer's Manual.
+ */
+
+/*
+ * Lock I-TLB entry
+ *
+ * r0: Virtual address to translate and lock
+ */
+ .align 5
+ENTRY(xscale_itlb_lock)
+ mrs r2, cpsr
+ orr r3, r2, #PSR_F_BIT | PSR_I_BIT
+ msr cpsr_c, r3 @ Disable interrupts
+ mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry
+ mcr p15, 0, r0, c10, c4, 0 @ Translate and lock
+ msr cpsr_c, r2 @ Restore interrupts
+ cpwait_ret lr, ip
+
+/*
+ * Lock D-TLB entry
+ *
+ * r0: Virtual address to translate and lock
+ */
+ .align 5
+ENTRY(xscale_dtlb_lock)
+ mrs r2, cpsr
+ orr r3, r2, #PSR_F_BIT | PSR_I_BIT
+ msr cpsr_c, r3 @ Disable interrupts
+ mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry
+ mcr p15, 0, r0, c10, c8, 0 @ Translate and lock
+ msr cpsr_c, r2 @ Restore interrupts
+ cpwait_ret lr, ip
+
+/*
+ * Unlock all I-TLB entries
+ */
+ .align 5
+ENTRY(xscale_itlb_unlock)
+ mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB
+ mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB
+ cpwait_ret lr, ip
+
+/*
+ * Unlock all D-TLB entries
+ */
+ENTRY(xscale_dtlb_unlock)
+ mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL
+ mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB
+ cpwait_ret lr, ip
+
+/* =============================== PageTable ============================== */
+
+#define PMD_CACHE_WRITE_ALLOCATE 0
+#define PTE_CACHE_WRITE_ALLOCATE 0
+
+/*
+ * cpu_xscale_set_pgd(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+ .align 5
+ENTRY(cpu_xscale_set_pgd)
+ clean_d_cache r1, r2
+ mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ cpwait_ret lr, ip
+
+/*
+ * cpu_xscale_set_pmd(pmdp, pmd)
+ *
+ * Set a level 1 translation table entry, and clean it out of
+ * any caches such that the MMUs can load it correctly.
+ *
+ * pmdp: pointer to PMD entry
+ * pmd: PMD value to store
+ */
+ .align 5
+ENTRY(cpu_xscale_set_pmd)
+#if PMD_CACHE_WRITE_ALLOCATE
+ and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
+ cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
+ orreq r1, r1, #PMD_SECT_TEX(1)
+#endif
+ str r1, [r0]
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov pc, lr
+
+/*
+ * cpu_xscale_set_pte(ptep, pte)
+ *
+ * Set a PTE and flush it out
+ */
+ .align 5
+ENTRY(cpu_xscale_set_pte)
+ str r1, [r0], #-1024 @ linux version
+
+ bic r2, r1, #0xff0
+ orr r2, r2, #PTE_TYPE_EXT @ extended page
+
+ eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+
+ tst r1, #L_PTE_USER | L_PTE_EXEC @ User or Exec?
+ orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
+
+ tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
+ @ combined with user -> user r/w
+
+#if PTE_CACHE_WRITE_ALLOCATE
+ tst r1, #L_PTE_CACHEABLE @ cacheable?
+ orrne r2, r2, #PTE_EXT_TEX(1)
+#else
+ eor r1, r1, #L_PTE_CACHEABLE
+ tst r1, #L_PTE_CACHEABLE | L_PTE_BUFFERABLE @ C = 1 B = 0?
+ orreq r2, r2, #PTE_EXT_TEX(1) @ yes -> set X (minicache)
+#endif
+
+ tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
+ movne r2, #0 @ no -> fault
+
+ str r2, [r0] @ hardware version
+ mov r0, r0
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mov pc, lr
+
+
+ .ltorg
+
+cpu_manu_name:
+ .asciz "Intel"
+
+cpu_80200_name:
+ .asciz "XScale-80200"
+
+cpu_cotulla_name:
+ .asciz "XScale-Cotulla"
+
+ .align
+
+ .section ".text.init", #alloc, #execinstr
+
+__xscale_setup:
+ mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r0
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs
+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
+ mov r0, #0x1f @ Domains 0, 1 = client
+ mcr p15, 0, r0, c3, c0, 0 @ load domain access register
+ mrc p15, 0, r0, c1, c0, 0 @ get control register
+ bic r0, r0, #0x0200 @ .... ..R. .... ....
+ bic r0, r0, #0x0082 @ .... .... B... ..A.
+ orr r0, r0, #0x0005 @ .... .... .... .C.M
+ orr r0, r0, #0x3900 @ ..VI Z..S .... ....
+ mov pc, lr
+
+ .text
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ * come through these
+ */
+
+ .type xscale_processor_functions, #object
+ENTRY(xscale_processor_functions)
+ .word armv4t_early_abort
+ .word cpu_xscale_check_bugs
+ .word cpu_xscale_proc_init
+ .word cpu_xscale_proc_fin
+ .word cpu_xscale_reset
+ .word cpu_xscale_do_idle
+
+ /* cache */
+ .word cpu_xscale_cache_clean_invalidate_all
+ .word cpu_xscale_cache_clean_invalidate_range
+ .word cpu_xscale_flush_ram_page
+
+ /* dcache */
+ .word cpu_xscale_dcache_invalidate_range
+ .word cpu_xscale_dcache_clean_range
+ .word cpu_xscale_dcache_clean_page
+ .word cpu_xscale_dcache_clean_entry
+
+ /* icache */
+ .word cpu_xscale_icache_invalidate_range
+ .word cpu_xscale_icache_invalidate_page
+
+ /* tlb */
+ .word cpu_xscale_tlb_invalidate_all
+ .word cpu_xscale_tlb_invalidate_range
+ .word cpu_xscale_tlb_invalidate_page
+
+ /* pgtable */
+ .word cpu_xscale_set_pgd
+ .word cpu_xscale_set_pmd
+ .word cpu_xscale_set_pte
+
+ /* misc */
+ .word armv5te_clear_user_page
+ .word armv5te_copy_user_page
+
+ .size xscale_processor_functions, . - xscale_processor_functions
+
+ .type cpu_80200_info, #object
+cpu_80200_info:
+ .long cpu_manu_name
+ .long cpu_80200_name
+ .size cpu_80200_info, . - cpu_80200_info
+
+ .type cpu_cotulla_info, #object
+cpu_cotulla_info:
+ .long cpu_manu_name
+ .long cpu_cotulla_name
+ .size cpu_cotulla_info, . - cpu_cotulla_info
+
+ .type cpu_arch_name, #object
+cpu_arch_name:
+ .asciz "armv5"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name:
+ .asciz "v5"
+ .size cpu_elf_name, . - cpu_elf_name
+ .align
+
+ .section ".proc.info", #alloc, #execinstr
+
+ .type __80200_proc_info,#object
+__80200_proc_info:
+ .long 0x69052000
+ .long 0xfffffff0
+ .long 0x00000c0e
+ b __xscale_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+ .long cpu_80200_info
+ .long xscale_processor_functions
+ .size __80200_proc_info, . - __80200_proc_info
+
+ .type __cotulla_proc_info,#object
+__cotulla_proc_info:
+ .long 0x69052100
+ .long 0xfffffff0
+ .long 0x00000c0e
+ b __xscale_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+ .long cpu_cotulla_info
+ .long xscale_processor_functions
+ .size __cotulla_proc_info, . - __cotulla_proc_info
+
diff --git a/arch/arm/nwfpe/ARM-gcc.h b/arch/arm/nwfpe/ARM-gcc.h
index d726aa452..e6598470b 100644
--- a/arch/arm/nwfpe/ARM-gcc.h
+++ b/arch/arm/nwfpe/ARM-gcc.h
@@ -1,11 +1,3 @@
-
-/*
--------------------------------------------------------------------------------
-One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
--------------------------------------------------------------------------------
-*/
-#define LITTLEENDIAN
-
/*
-------------------------------------------------------------------------------
The macro `BITS64' can be defined to indicate that 64-bit integer types are
diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S
index 3b1869042..2ae75a194 100644
--- a/arch/arm/nwfpe/entry.S
+++ b/arch/arm/nwfpe/entry.S
@@ -50,11 +50,10 @@ want it.
This routine does three things:
-1) It saves SP into a variable called userRegisters. The kernel has
-created a struct pt_regs on the stack and saved the user registers
-into it. See /usr/include/asm/proc/ptrace.h for details. The
-emulator code uses userRegisters as the base of an array of words from
-which the contents of the registers can be extracted.
+1) The kernel has created a struct pt_regs on the stack and saved the
+user registers into it. See /usr/include/asm/proc/ptrace.h for details.
+The emulator code uses userRegisters as the base of an array of words
+from which the contents of the registers can be extracted.
2) It calls EmulateAll to emulate a floating point instruction.
EmulateAll returns 1 if the emulation was successful, or 0 if not.
@@ -78,16 +77,18 @@ nwfpe_enter:
of stealing two regs from the register allocator. Not sure if
it's worth it. */
str sp, [r10] @ Store the user registers pointer in the fpa11 structure.
- mov r4, sp @ use r4 for local pointer
- mov r10, lr @ save the failure-return addresses
+ mov r4, lr @ save the failure-return addresses
- ldr r5, [r4, #60] @ get contents of PC;
+ mov r0, r10
+ bl FPA11_CheckInit @ check to see if we are initialised
+
+ ldr r5, [sp, #60] @ get contents of PC;
sub r8, r5, #4
.Lx2: ldrt r0, [r8] @ get actual instruction into r0
emulate:
bl EmulateAll @ emulate the instruction
cmp r0, #0 @ was emulation successful
- moveq pc, r10 @ no, return failure
+ moveq pc, r4 @ no, return failure
next:
.Lx1: ldrt r6, [r5], #4 @ get the next instruction and
@@ -99,10 +100,10 @@ next:
teqne r2, #0x0E000000
movne pc, r9 @ return ok if not a fp insn
- str r5, [r4, #60] @ update PC copy in regs
+ str r5, [sp, #60] @ update PC copy in regs
mov r0, r6 @ save a copy
- ldr r1, [r4, #64] @ fetch the condition codes
+ ldr r1, [sp, #64] @ fetch the condition codes
bl checkCondition @ check the condition
cmp r0, #0 @ r0 = 0 ==> condition failed
diff --git a/arch/arm/nwfpe/entry26.S b/arch/arm/nwfpe/entry26.S
index 8554094b6..ed4aeac8b 100644
--- a/arch/arm/nwfpe/entry26.S
+++ b/arch/arm/nwfpe/entry26.S
@@ -26,7 +26,7 @@
It is called from the kernel with code similar to this:
mov fp, #0
- teqp pc, #I_BIT | MODE_SVC
+ teqp pc, #PSR_I_BIT | MODE_SVC
ldr r4, .LC2
ldr pc, [r4] @ Call FP module USR entry point
diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c
index bf07b6dd4..28f41f77b 100644
--- a/arch/arm/nwfpe/fpa11.c
+++ b/arch/arm/nwfpe/fpa11.c
@@ -18,7 +18,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#include <linux/compiler.h>
#include <asm/system.h>
#include "fpa11.h"
@@ -123,47 +123,57 @@ void SetRoundingPrecision(const unsigned int opcode)
}
}
-/* Emulate the instruction in the opcode. */
-unsigned int EmulateAll(unsigned int opcode)
+void FPA11_CheckInit(FPA11 *fpa11)
{
- unsigned int nRc = 0;
- unsigned long flags;
- FPA11 *fpa11;
- save_flags(flags); sti();
-
- fpa11 = GET_FPA11();
-
- if (fpa11->initflag == 0) /* good place for __builtin_expect */
+ if (unlikely(fpa11->initflag == 0))
{
resetFPA11();
SetRoundingMode(ROUND_TO_NEAREST);
SetRoundingPrecision(ROUND_EXTENDED);
fpa11->initflag = 1;
}
+}
- if (TEST_OPCODE(opcode,MASK_CPRT))
- {
- /* Emulate conversion opcodes. */
- /* Emulate register transfer opcodes. */
- /* Emulate comparison opcodes. */
- nRc = EmulateCPRT(opcode);
- }
- else if (TEST_OPCODE(opcode,MASK_CPDO))
- {
- /* Emulate monadic arithmetic opcodes. */
- /* Emulate dyadic arithmetic opcodes. */
- nRc = EmulateCPDO(opcode);
- }
- else if (TEST_OPCODE(opcode,MASK_CPDT))
- {
- /* Emulate load/store opcodes. */
- /* Emulate load/store multiple opcodes. */
- nRc = EmulateCPDT(opcode);
- }
- else
+/* Emulate the instruction in the opcode. */
+unsigned int EmulateAll(unsigned int opcode)
+{
+ unsigned int nRc = 1, code;
+ unsigned long flags;
+
+ save_flags(flags); sti();
+
+ code = opcode & 0x00000f00;
+ if (code == 0x00000100 || code == 0x00000200)
{
- /* Invalid instruction detected. Return FALSE. */
- nRc = 0;
+ /* For coprocessor 1 or 2 (FPA11) */
+ code = opcode & 0x0e000000;
+ if (code == 0x0e000000)
+ {
+ if (opcode & 0x00000010)
+ {
+ /* Emulate conversion opcodes. */
+ /* Emulate register transfer opcodes. */
+ /* Emulate comparison opcodes. */
+ nRc = EmulateCPRT(opcode);
+ }
+ else
+ {
+ /* Emulate monadic arithmetic opcodes. */
+ /* Emulate dyadic arithmetic opcodes. */
+ nRc = EmulateCPDO(opcode);
+ }
+ }
+ else if (code == 0x0c000000)
+ {
+ /* Emulate load/store opcodes. */
+ /* Emulate load/store multiple opcodes. */
+ nRc = EmulateCPDT(opcode);
+ }
+ else
+ {
+ /* Invalid instruction detected. Return FALSE. */
+ nRc = 0;
+ }
}
restore_flags(flags);
diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
index c5d7626be..8326ca1fa 100644
--- a/arch/arm/nwfpe/fpa11_cpdt.c
+++ b/arch/arm/nwfpe/fpa11_cpdt.c
@@ -45,7 +45,7 @@ void loadDouble(const unsigned int Fn,const unsigned int *pMem)
fpa11->fType[Fn] = typeDouble;
get_user(p[0], &pMem[1]);
get_user(p[1], &pMem[0]); /* sign & exponent */
-}
+}
static inline
void loadExtended(const unsigned int Fn,const unsigned int *pMem)
@@ -57,7 +57,7 @@ void loadExtended(const unsigned int Fn,const unsigned int *pMem)
get_user(p[0], &pMem[0]); /* sign & exponent */
get_user(p[1], &pMem[2]); /* ls bits */
get_user(p[2], &pMem[1]); /* ms bits */
-}
+}
static inline
void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
@@ -69,7 +69,7 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
p = (unsigned int*)&(fpa11->fpreg[Fn]);
get_user(x, &pMem[0]);
fpa11->fType[Fn] = (x >> 14) & 0x00000003;
-
+
switch (fpa11->fType[Fn])
{
case typeSingle:
@@ -79,13 +79,13 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
get_user(p[1], &pMem[1]); /* double msw */
p[2] = 0; /* empty */
}
- break;
-
+ break;
+
case typeExtended:
{
get_user(p[1], &pMem[2]);
get_user(p[2], &pMem[1]); /* msw */
- p[0] = (x & 0x80003fff);
+ p[0] = (x & 0x80003fff);
}
break;
}
@@ -95,82 +95,92 @@ static inline
void storeSingle(const unsigned int Fn,unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
- float32 val;
- register unsigned int *p = (unsigned int*)&val;
-
+ union
+ {
+ float32 f;
+ unsigned int i[1];
+ } val;
+
switch (fpa11->fType[Fn])
{
- case typeDouble:
- val = float64_to_float32(fpa11->fpreg[Fn].fDouble);
+ case typeDouble:
+ val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
break;
- case typeExtended:
- val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
+ case typeExtended:
+ val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
break;
- default: val = fpa11->fpreg[Fn].fSingle;
+ default: val.f = fpa11->fpreg[Fn].fSingle;
}
-
- put_user(p[0], pMem);
-}
+
+ put_user(val.i[0], pMem);
+}
static inline
void storeDouble(const unsigned int Fn,unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
- float64 val;
- register unsigned int *p = (unsigned int*)&val;
+ union
+ {
+ float64 f;
+ unsigned int i[2];
+ } val;
switch (fpa11->fType[Fn])
{
- case typeSingle:
- val = float32_to_float64(fpa11->fpreg[Fn].fSingle);
+ case typeSingle:
+ val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
break;
case typeExtended:
- val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
+ val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
break;
- default: val = fpa11->fpreg[Fn].fDouble;
+ default: val.f = fpa11->fpreg[Fn].fDouble;
}
- put_user(p[1], &pMem[0]); /* msw */
- put_user(p[0], &pMem[1]); /* lsw */
-}
+
+ put_user(val.i[1], &pMem[0]); /* msw */
+ put_user(val.i[0], &pMem[1]); /* lsw */
+}
static inline
void storeExtended(const unsigned int Fn,unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
- floatx80 val;
- register unsigned int *p = (unsigned int*)&val;
-
+ union
+ {
+ floatx80 f;
+ unsigned int i[3];
+ } val;
+
switch (fpa11->fType[Fn])
{
- case typeSingle:
- val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
+ case typeSingle:
+ val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
break;
- case typeDouble:
- val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
+ case typeDouble:
+ val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
break;
- default: val = fpa11->fpreg[Fn].fExtended;
+ default: val.f = fpa11->fpreg[Fn].fExtended;
}
-
- put_user(p[0], &pMem[0]); /* sign & exp */
- put_user(p[1], &pMem[2]);
- put_user(p[2], &pMem[1]); /* msw */
-}
+
+ put_user(val.i[0], &pMem[0]); /* sign & exp */
+ put_user(val.i[1], &pMem[2]);
+ put_user(val.i[2], &pMem[1]); /* msw */
+}
static inline
void storeMultiple(const unsigned int Fn,unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
register unsigned int nType, *p;
-
+
p = (unsigned int*)&(fpa11->fpreg[Fn]);
nType = fpa11->fType[Fn];
-
+
switch (nType)
{
case typeSingle:
@@ -180,8 +190,8 @@ void storeMultiple(const unsigned int Fn,unsigned int *pMem)
put_user(p[1], &pMem[1]); /* double msw */
put_user(nType << 14, &pMem[0]);
}
- break;
-
+ break;
+
case typeExtended:
{
put_user(p[2], &pMem[1]); /* msw */
@@ -221,7 +231,7 @@ unsigned int PerformLDF(const unsigned int opcode)
case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
default: nRc = 0;
}
-
+
if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
return nRc;
}
@@ -230,10 +240,10 @@ unsigned int PerformSTF(const unsigned int opcode)
{
unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
write_back = WRITE_BACK(opcode);
-
+
//printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
SetRoundingMode(ROUND_TO_NEAREST);
-
+
pBase = (unsigned int*)readRegister(getRn(opcode));
if (REG_PC == getRn(opcode))
{
@@ -256,7 +266,7 @@ unsigned int PerformSTF(const unsigned int opcode)
case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
default: nRc = 0;
}
-
+
if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
return nRc;
}
@@ -297,14 +307,14 @@ unsigned int PerformSFM(const unsigned int opcode)
{
unsigned int i, Fd, *pBase, *pAddress, *pFinal,
write_back = WRITE_BACK(opcode);
-
+
pBase = (unsigned int*)readRegister(getRn(opcode));
if (REG_PC == getRn(opcode))
{
pBase += 2;
write_back = 0;
}
-
+
pFinal = pBase;
if (BIT_UP_SET(opcode))
pFinal += getOffset(opcode);
@@ -331,7 +341,7 @@ unsigned int EmulateCPDT(const unsigned int opcode)
unsigned int nRc = 0;
//printk("EmulateCPDT(0x%08x)\n",opcode);
-
+
if (LDF_OP(opcode))
{
nRc = PerformLDF(opcode);
@@ -343,7 +353,7 @@ unsigned int EmulateCPDT(const unsigned int opcode)
else if (STF_OP(opcode))
{
nRc = PerformSTF(opcode);
- }
+ }
else if (SFM_OP(opcode))
{
nRc = PerformSFM(opcode);
@@ -352,7 +362,7 @@ unsigned int EmulateCPDT(const unsigned int opcode)
{
nRc = 0;
}
-
+
return nRc;
}
#endif
diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile
index 4c9c03120..e34c443d0 100644
--- a/arch/arm/tools/Makefile
+++ b/arch/arm/tools/Makefile
@@ -15,13 +15,17 @@ $(TOPDIR)/include/asm-arm/mach-types.h: mach-types gen-mach-types
# what we want. We do this in several stages so make picks up on
# any errors that occur along the way.
-$(TOPDIR)/include/asm-arm/constants.h: constants-hdr getconstants.c
- $(CC) $(CFLAGS) -S -o - getconstants.c > $@.tmp.1
+constants.h: constants-hdr getconstants.c
+ $(CC) $(CFLAGS) -S -o $@.tmp.1 getconstants.c
sed 's/^\(#define .* \)[#$$]\(.*\)/\1\2/;/^#define/!d' $@.tmp.1 > $@.tmp.2
- cat constants-hdr $@.tmp.2 > $@.tmp
- cmp $@.tmp $@ >/dev/null 2>&1 || mv $@.tmp $@
+ cat constants-hdr $@.tmp.2 > $@
$(RM) $@.tmp*
+# Only update include/asm-arm/constants.h when it has actually changed.
+
+$(TOPDIR)/include/asm-arm/constants.h: constants.h
+ cmp constants.h $@ >/dev/null 2>&1 || cp -p constants.h $@
+
# Build our dependencies, and then generate the constants and
# mach-types header files. If we do it now, mkdep will pick
# the dependencies up later on when it runs through the other
@@ -29,7 +33,7 @@ $(TOPDIR)/include/asm-arm/constants.h: constants-hdr getconstants.c
dep:
$(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS) -- getconstants.c |\
- sed s,getconstants.o,$(TOPDIR)/include/asm-arm/constants.h, > .depend
+ sed s,getconstants.o,constants.h, > .depend
$(MAKE) all
.PHONY: all dep
diff --git a/arch/arm/tools/getconstants.c b/arch/arm/tools/getconstants.c
index 2cdbb8b9d..6b9eab4c5 100644
--- a/arch/arm/tools/getconstants.c
+++ b/arch/arm/tools/getconstants.c
@@ -18,10 +18,17 @@
* Make sure that the compiler and target are compatible.
*/
#if defined(__APCS_32__) && defined(CONFIG_CPU_26)
-#error Your compiler targets APCS-32 but this kernel requires APCS-26
+#error Sorry, your compiler targets APCS-32 but this kernel requires APCS-26
#endif
#if defined(__APCS_26__) && defined(CONFIG_CPU_32)
-#error Your compiler targets APCS-26 but this kernel requires APCS-32
+#error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
+#endif
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95)
+#error Sorry, your compiler is known to miscompile kernels. Only use gcc 2.95.3 and later.
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ == 95
+/* shame we can't detect the .1 or .2 releases */
+#warning GCC 2.95.2 and earlier miscompiles kernels.
#endif
#define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n)
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 8d3b013b7..fa39ca99b 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
-# Last update: Fri Oct 26 17:37:13 2001
+# Last update: Fri Jan 4 10:27:21 2002
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -137,3 +137,28 @@ puppy ARCH_PUPPY PUPPY 125
elroy SA1100_ELROY ELROY 126
gms720 ARCH_GMS720 GMS720 127
s24x ARCH_S24X S24X 128
+jtel_clep7312 ARCH_JTEL_CLEP7312 JTEL_CLEP7312 129
+cx821xx ARCH_CX821XX CX821XX 130
+edb7312 ARCH_EDB7312 EDB7312 131
+bsa1110 SA1100_BSA1110 BSA1110 132
+powerpin ARCH_POWERPIN POWERPIN 133
+openarm ARCH_OPENARM OPENARM 134
+whitechapel SA1100_WHITECHAPEL WHITECHAPEL 135
+h3100 SA1100_H3100 H3100 136
+h3800 SA1100_H3800 H3800 137
+blue_v1 ARCH_BLUE_V1 BLUE_V1 138
+xscale_cerf ARCH_XSCALE_CERF XSCALE_CERF 139
+arm7tevb ARCH_ARM7TEVB ARM7TEVB 140
+d7400 ARCH_D7400 D7400 141
+piranha ARCH_PIRANHA PIRANHA 142
+sbcamelot SA1100_SBCAMELOT SBCAMELOT 143
+kings SA1100_KINGS KINGS 144
+smdk2400 ARCH_SMDK2400 SMDK2400 145
+collie ARCH_COLLIE COLLIE 146
+idr ARCH_IDR IDR 147
+badge4 SA1100_BADGE4 BADGE4 148
+webnet ARCH_WEBNET WEBNET 149
+d7300 SA1100_D7300 D7300 150
+cep SA1100_CEP CEP 151
+fortunet ARCH_FORTUNET FORTUNET 152
+vc547x ARCH_VC547X VC547X 153
diff --git a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
index 8c963788b..4581c2a0b 100644
--- a/arch/arm/vmlinux-armo.lds.in
+++ b/arch/arm/vmlinux-armo.lds.in
@@ -48,7 +48,6 @@ SECTIONS
*(.text)
*(.fixup)
*(.gnu.warning)
- *(.text.lock) /* out-of-line lock text */
*(.rodata)
*(.rodata.*)
*(.glue_7)
diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
index 3dd5a3b09..6585b766d 100644
--- a/arch/arm/vmlinux-armv.lds.in
+++ b/arch/arm/vmlinux-armv.lds.in
@@ -43,7 +43,6 @@ SECTIONS
*(.text)
*(.fixup)
*(.gnu.warning)
- *(.text.lock) /* out-of-line lock text */
*(.rodata)
*(.rodata.*)
*(.glue_7)
diff --git a/arch/cris/drivers/usb-host.c b/arch/cris/drivers/usb-host.c
index 19d876931..233fdbbae 100644
--- a/arch/cris/drivers/usb-host.c
+++ b/arch/cris/drivers/usb-host.c
@@ -196,7 +196,7 @@ static urb_t *URB_List[NBR_OF_EP_DESC];
static kmem_cache_t *usb_desc_cache;
static struct usb_bus *etrax_usb_bus;
-static void dump_urb (purb_t purb);
+static void dump_urb (struct urb *urb);
static void init_rx_buffers(void);
static int etrax_rh_unlink_urb (urb_t *urb);
static void etrax_rh_send_irq(urb_t *urb);
@@ -240,24 +240,24 @@ static struct usb_operations etrax_usb_device_operations =
};
#ifdef USB_DEBUG_DESC
-static void dump_urb(purb_t purb)
+static void dump_urb(struct urb *urb)
{
- printk("\nurb :0x%08X\n", purb);
- printk("next :0x%08X\n", purb->next);
- printk("dev :0x%08X\n", purb->dev);
- printk("pipe :0x%08X\n", purb->pipe);
- printk("status :%d\n", purb->status);
- printk("transfer_flags :0x%08X\n", purb->transfer_flags);
- printk("transfer_buffer :0x%08X\n", purb->transfer_buffer);
- printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
- printk("actual_length :%d\n", purb->actual_length);
- printk("setup_packet :0x%08X\n", purb->setup_packet);
- printk("start_frame :%d\n", purb->start_frame);
- printk("number_of_packets :%d\n", purb->number_of_packets);
- printk("interval :%d\n", purb->interval);
- printk("error_count :%d\n", purb->error_count);
- printk("context :0x%08X\n", purb->context);
- printk("complete :0x%08X\n\n", purb->complete);
+ printk("\nurb :0x%08X\n", urb);
+ printk("next :0x%08X\n", urb->next);
+ printk("dev :0x%08X\n", urb->dev);
+ printk("pipe :0x%08X\n", urb->pipe);
+ printk("status :%d\n", urb->status);
+ printk("transfer_flags :0x%08X\n", urb->transfer_flags);
+ printk("transfer_buffer :0x%08X\n", urb->transfer_buffer);
+ printk("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
+ printk("actual_length :%d\n", urb->actual_length);
+ printk("setup_packet :0x%08X\n", urb->setup_packet);
+ printk("start_frame :%d\n", urb->start_frame);
+ printk("number_of_packets :%d\n", urb->number_of_packets);
+ printk("interval :%d\n", urb->interval);
+ printk("error_count :%d\n", urb->error_count);
+ printk("context :0x%08X\n", urb->context);
+ printk("complete :0x%08X\n\n", urb->complete);
}
static void dump_in_desc(USB_IN_Desc_t *in)
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 82ee4579f..00be67c79 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -119,7 +119,6 @@ void enable_hlt(void)
int cpu_idle(void *unused)
{
while(1) {
- current->counter = -100;
schedule();
}
}
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 76c3a2dba..68a6cc9ca 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -141,18 +141,21 @@ if [ "$CONFIG_MWINCHIPC6" = "y" ]; then
define_int CONFIG_X86_L1_CACHE_SHIFT 5
define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+ define_bool CONFIG_X86_OOSTORE y
fi
if [ "$CONFIG_MWINCHIP2" = "y" ]; then
define_int CONFIG_X86_L1_CACHE_SHIFT 5
define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+ define_bool CONFIG_X86_OOSTORE y
fi
if [ "$CONFIG_MWINCHIP3D" = "y" ]; then
define_int CONFIG_X86_L1_CACHE_SHIFT 5
define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+ define_bool CONFIG_X86_OOSTORE y
fi
tristate 'Toshiba Laptop support' CONFIG_TOSHIBA
tristate 'Dell laptop support' CONFIG_I8K
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index c73c7bb74..88b531035 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -409,6 +409,7 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
+# CONFIG_DE2104X is not set
# CONFIG_TULIP is not set
# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
@@ -624,7 +625,7 @@ CONFIG_AUTOFS4_FS=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_TMPFS=y
-# CONFIG_RAMFS is not set
+CONFIG_RAMFS=y
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
@@ -727,8 +728,9 @@ CONFIG_USB=y
# CONFIG_USB_LONG_TIMEOUT is not set
#
-# USB Controllers
+# USB Host Controller Drivers
#
+# CONFIG_USB_EHCI_HCD is not set
CONFIG_USB_UHCI_ALT=y
# CONFIG_USB_OHCI is not set
@@ -799,6 +801,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
# CONFIG_USB_SERIAL_IR is not set
# CONFIG_USB_SERIAL_EDGEPORT is not set
# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
@@ -812,6 +815,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_KLSI is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 789604e6f..d7fd9193d 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -39,6 +39,9 @@ obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o acpitable.o
+ifdef CONFIG_VISWS
+obj-y += setup-visws.o
obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
+endif
include $(TOPDIR)/Rules.make
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index c7bff7b28..dbd211d6a 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -56,6 +56,14 @@ void clear_local_APIC(void)
maxlvt = get_maxlvt();
/*
+ * Masking an LVT entry on a P6 can trigger a local APIC error
+ * if the vector is zero. Mask LVTERR first to prevent this.
+ */
+ if (maxlvt >= 3) {
+ v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
+ apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
+ }
+ /*
* Careful: we have to set masks only first to deassert
* any level-triggered sources.
*/
@@ -65,10 +73,6 @@ void clear_local_APIC(void)
apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
v = apic_read(APIC_LVT1);
apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
- if (maxlvt >= 3) {
- v = apic_read(APIC_LVTERR);
- apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
- }
if (maxlvt >= 4) {
v = apic_read(APIC_LVTPC);
apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
@@ -84,6 +88,8 @@ void clear_local_APIC(void)
apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
if (maxlvt >= 4)
apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
+ apic_write(APIC_ESR, 0);
+ v = apic_read(APIC_ESR);
}
void __init connect_bsp_APIC(void)
@@ -480,6 +486,7 @@ static void apic_pm_resume(void *data)
l &= ~MSR_IA32_APICBASE_BASE;
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
wrmsr(MSR_IA32_APICBASE, l, h);
+ apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
apic_write(APIC_ID, apic_pm_state.apic_id);
apic_write(APIC_DFR, apic_pm_state.apic_dfr);
apic_write(APIC_LDR, apic_pm_state.apic_ldr);
@@ -487,15 +494,15 @@ static void apic_pm_resume(void *data)
apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
+ apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
+ apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
+ apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
+ apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
- apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
- apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
- apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
- apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
__restore_flags(flags);
if (apic_pm_state.perfctr_pmdev)
pm_send(apic_pm_state.perfctr_pmdev, PM_RESUME, data);
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 6fb3f9172..2686bc9bc 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -101,7 +101,7 @@ static ssize_t cpuid_read(struct file * file, char * buf,
u32 data[4];
size_t rv;
u32 reg = *ppos;
- int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+ int cpu = minor(file->f_dentry->d_inode->i_rdev);
if ( count % 16 )
return -EINVAL; /* Invalid chunk size */
@@ -119,7 +119,7 @@ static ssize_t cpuid_read(struct file * file, char * buf,
static int cpuid_open(struct inode *inode, struct file *file)
{
- int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+ int cpu = minor(file->f_dentry->d_inode->i_rdev);
struct cpuinfo_x86 *c = &(cpu_data)[cpu];
if ( !(cpu_online_map & (1UL << cpu)) )
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index feee5b67e..5445ca5ac 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -181,7 +181,7 @@ static ssize_t msr_read(struct file * file, char * buf,
u32 data[2];
size_t rv;
u32 reg = *ppos;
- int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+ int cpu = minor(file->f_dentry->d_inode->i_rdev);
int err;
if ( count % 8 )
@@ -206,7 +206,7 @@ static ssize_t msr_write(struct file * file, const char * buf,
u32 data[2];
size_t rv;
u32 reg = *ppos;
- int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+ int cpu = minor(file->f_dentry->d_inode->i_rdev);
int err;
if ( count % 8 )
@@ -226,7 +226,7 @@ static ssize_t msr_write(struct file * file, const char * buf,
static int msr_open(struct inode *inode, struct file *file)
{
- int cpu = MINOR(file->f_dentry->d_inode->i_rdev);
+ int cpu = minor(file->f_dentry->d_inode->i_rdev);
struct cpuinfo_x86 *c = &(cpu_data)[cpu];
if ( !(cpu_online_map & (1UL << cpu)) )
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index bf3fad221..5abb2259c 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -30,7 +30,7 @@ int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32
* This interrupt-safe spinlock protects all accesses to PCI
* configuration space.
*/
-spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
/*
@@ -1109,17 +1109,15 @@ static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
}
/*
- * Nobody seems to know what this does. Damn.
- *
- * But it does seem to fix some unspecified problem
- * with 'movntq' copies on Athlons.
+ * Addresses issues with problems in the memory write queue timer in
+ * certain VIA Northbridges. This bugfix is per VIA's specifications.
*
* VIA 8363,8622,8361 Northbridges:
* - bits 5, 6, 7 at offset 0x55 need to be turned off
* VIA 8367 (KT266x) Northbridges:
* - bits 5, 6, 7 at offset 0x95 need to be turned off
*/
-static void __init pci_fixup_via_athlon_bug(struct pci_dev *d)
+static void __init pci_fixup_via_northbridge_bug(struct pci_dev *d)
{
u8 v;
int where = 0x55;
@@ -1131,7 +1129,7 @@ static void __init pci_fixup_via_athlon_bug(struct pci_dev *d)
pci_read_config_byte(d, where, &v);
if (v & 0xe0) {
- printk("Trying to stomp on Athlon bug...\n");
+ printk("Disabling broken memory write queue.\n");
v &= 0x1f; /* clear bits 5, 6, 7 */
pci_write_config_byte(d, where, v);
}
@@ -1146,10 +1144,10 @@ struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi },
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_athlon_bug },
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_athlon_bug },
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_athlon_bug },
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_athlon_bug },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug },
{ 0 }
};
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 51fc52a84..c212e1da6 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -125,7 +125,6 @@ void cpu_idle (void)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
while (1) {
void (*idle)(void) = pm_idle;
diff --git a/arch/i386/kernel/setup-visws.c b/arch/i386/kernel/setup-visws.c
new file mode 100644
index 000000000..1c8220b82
--- /dev/null
+++ b/arch/i386/kernel/setup-visws.c
@@ -0,0 +1,126 @@
+/*
+ * Unmaintained SGI Visual Workstation support.
+ * Split out from setup.c by davej@suse.de
+ */
+
+char visws_board_type = -1;
+char visws_board_rev = -1;
+
+#define PIIX_PM_START 0x0F80
+
+#define SIO_GPIO_START 0x0FC0
+
+#define SIO_PM_START 0x0FC8
+
+#define PMBASE PIIX_PM_START
+#define GPIREG0 (PMBASE+0x30)
+#define GPIREG(x) (GPIREG0+((x)/8))
+#define PIIX_GPI_BD_ID1 18
+#define PIIX_GPI_BD_REG GPIREG(PIIX_GPI_BD_ID1)
+
+#define PIIX_GPI_BD_SHIFT (PIIX_GPI_BD_ID1 % 8)
+
+#define SIO_INDEX 0x2e
+#define SIO_DATA 0x2f
+
+#define SIO_DEV_SEL 0x7
+#define SIO_DEV_ENB 0x30
+#define SIO_DEV_MSB 0x60
+#define SIO_DEV_LSB 0x61
+
+#define SIO_GP_DEV 0x7
+
+#define SIO_GP_BASE SIO_GPIO_START
+#define SIO_GP_MSB (SIO_GP_BASE>>8)
+#define SIO_GP_LSB (SIO_GP_BASE&0xff)
+
+#define SIO_GP_DATA1 (SIO_GP_BASE+0)
+
+#define SIO_PM_DEV 0x8
+
+#define SIO_PM_BASE SIO_PM_START
+#define SIO_PM_MSB (SIO_PM_BASE>>8)
+#define SIO_PM_LSB (SIO_PM_BASE&0xff)
+#define SIO_PM_INDEX (SIO_PM_BASE+0)
+#define SIO_PM_DATA (SIO_PM_BASE+1)
+
+#define SIO_PM_FER2 0x1
+
+#define SIO_PM_GP_EN 0x80
+
+void __init visws_get_board_type_and_rev(void)
+{
+ int raw;
+
+ visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
+ >> PIIX_GPI_BD_SHIFT;
+/*
+ * Get Board rev.
+ * First, we have to initialize the 307 part to allow us access
+ * to the GPIO registers. Let's map them at 0x0fc0 which is right
+ * after the PIIX4 PM section.
+ */
+ outb_p(SIO_DEV_SEL, SIO_INDEX);
+ outb_p(SIO_GP_DEV, SIO_DATA); /* Talk to GPIO regs. */
+
+ outb_p(SIO_DEV_MSB, SIO_INDEX);
+ outb_p(SIO_GP_MSB, SIO_DATA); /* MSB of GPIO base address */
+
+ outb_p(SIO_DEV_LSB, SIO_INDEX);
+ outb_p(SIO_GP_LSB, SIO_DATA); /* LSB of GPIO base address */
+
+ outb_p(SIO_DEV_ENB, SIO_INDEX);
+ outb_p(1, SIO_DATA); /* Enable GPIO registers. */
+
+/*
+ * Now, we have to map the power management section to write
+ * a bit which enables access to the GPIO registers.
+ * What lunatic came up with this shit?
+ */
+ outb_p(SIO_DEV_SEL, SIO_INDEX);
+ outb_p(SIO_PM_DEV, SIO_DATA); /* Talk to GPIO regs. */
+
+ outb_p(SIO_DEV_MSB, SIO_INDEX);
+ outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */
+
+ outb_p(SIO_DEV_LSB, SIO_INDEX);
+ outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */
+
+ outb_p(SIO_DEV_ENB, SIO_INDEX);
+ outb_p(1, SIO_DATA); /* Enable PM registers. */
+
+/*
+ * Now, write the PM register which enables the GPIO registers.
+ */
+ outb_p(SIO_PM_FER2, SIO_PM_INDEX);
+ outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
+
+/*
+ * Now, initialize the GPIO registers.
+ * We want them all to be inputs which is the
+ * power on default, so let's leave them alone.
+ * So, let's just read the board rev!
+ */
+ raw = inb_p(SIO_GP_DATA1);
+ raw &= 0x7f; /* 7 bits of valid board revision ID. */
+
+ if (visws_board_type == VISWS_320) {
+ if (raw < 0x6) {
+ visws_board_rev = 4;
+ } else if (raw < 0xc) {
+ visws_board_rev = 5;
+ } else {
+ visws_board_rev = 6;
+ }
+ } else if (visws_board_type == VISWS_540) {
+ visws_board_rev = 2;
+ } else {
+ visws_board_rev = raw;
+ }
+
+ printk(KERN_INFO "Silicon Graphics %s (rev %d)\n",
+ visws_board_type == VISWS_320 ? "320" :
+ (visws_board_type == VISWS_540 ? "540" :
+ "unknown"), visws_board_rev);
+ }
+}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index c05ffe05d..35372e1de 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -158,6 +158,7 @@ extern void mcheck_init(struct cpuinfo_x86 *c);
extern int root_mountflags;
extern char _text, _etext, _edata, _end;
extern int blk_nohighio;
+void __init visws_get_board_type_and_rev(void);
static int disable_x86_serial_nr __initdata = 1;
static int disable_x86_fxsr __initdata = 0;
@@ -191,131 +192,6 @@ int enable_acpi_smp_table;
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
-#ifdef CONFIG_VISWS
-char visws_board_type = -1;
-char visws_board_rev = -1;
-
-#define PIIX_PM_START 0x0F80
-
-#define SIO_GPIO_START 0x0FC0
-
-#define SIO_PM_START 0x0FC8
-
-#define PMBASE PIIX_PM_START
-#define GPIREG0 (PMBASE+0x30)
-#define GPIREG(x) (GPIREG0+((x)/8))
-#define PIIX_GPI_BD_ID1 18
-#define PIIX_GPI_BD_REG GPIREG(PIIX_GPI_BD_ID1)
-
-#define PIIX_GPI_BD_SHIFT (PIIX_GPI_BD_ID1 % 8)
-
-#define SIO_INDEX 0x2e
-#define SIO_DATA 0x2f
-
-#define SIO_DEV_SEL 0x7
-#define SIO_DEV_ENB 0x30
-#define SIO_DEV_MSB 0x60
-#define SIO_DEV_LSB 0x61
-
-#define SIO_GP_DEV 0x7
-
-#define SIO_GP_BASE SIO_GPIO_START
-#define SIO_GP_MSB (SIO_GP_BASE>>8)
-#define SIO_GP_LSB (SIO_GP_BASE&0xff)
-
-#define SIO_GP_DATA1 (SIO_GP_BASE+0)
-
-#define SIO_PM_DEV 0x8
-
-#define SIO_PM_BASE SIO_PM_START
-#define SIO_PM_MSB (SIO_PM_BASE>>8)
-#define SIO_PM_LSB (SIO_PM_BASE&0xff)
-#define SIO_PM_INDEX (SIO_PM_BASE+0)
-#define SIO_PM_DATA (SIO_PM_BASE+1)
-
-#define SIO_PM_FER2 0x1
-
-#define SIO_PM_GP_EN 0x80
-
-static void __init visws_get_board_type_and_rev(void)
-{
- int raw;
-
- visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
- >> PIIX_GPI_BD_SHIFT;
-/*
- * Get Board rev.
- * First, we have to initialize the 307 part to allow us access
- * to the GPIO registers. Let's map them at 0x0fc0 which is right
- * after the PIIX4 PM section.
- */
- outb_p(SIO_DEV_SEL, SIO_INDEX);
- outb_p(SIO_GP_DEV, SIO_DATA); /* Talk to GPIO regs. */
-
- outb_p(SIO_DEV_MSB, SIO_INDEX);
- outb_p(SIO_GP_MSB, SIO_DATA); /* MSB of GPIO base address */
-
- outb_p(SIO_DEV_LSB, SIO_INDEX);
- outb_p(SIO_GP_LSB, SIO_DATA); /* LSB of GPIO base address */
-
- outb_p(SIO_DEV_ENB, SIO_INDEX);
- outb_p(1, SIO_DATA); /* Enable GPIO registers. */
-
-/*
- * Now, we have to map the power management section to write
- * a bit which enables access to the GPIO registers.
- * What lunatic came up with this shit?
- */
- outb_p(SIO_DEV_SEL, SIO_INDEX);
- outb_p(SIO_PM_DEV, SIO_DATA); /* Talk to GPIO regs. */
-
- outb_p(SIO_DEV_MSB, SIO_INDEX);
- outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */
-
- outb_p(SIO_DEV_LSB, SIO_INDEX);
- outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */
-
- outb_p(SIO_DEV_ENB, SIO_INDEX);
- outb_p(1, SIO_DATA); /* Enable PM registers. */
-
-/*
- * Now, write the PM register which enables the GPIO registers.
- */
- outb_p(SIO_PM_FER2, SIO_PM_INDEX);
- outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
-
-/*
- * Now, initialize the GPIO registers.
- * We want them all to be inputs which is the
- * power on default, so let's leave them alone.
- * So, let's just read the board rev!
- */
- raw = inb_p(SIO_GP_DATA1);
- raw &= 0x7f; /* 7 bits of valid board revision ID. */
-
- if (visws_board_type == VISWS_320) {
- if (raw < 0x6) {
- visws_board_rev = 4;
- } else if (raw < 0xc) {
- visws_board_rev = 5;
- } else {
- visws_board_rev = 6;
-
- }
- } else if (visws_board_type == VISWS_540) {
- visws_board_rev = 2;
- } else {
- visws_board_rev = raw;
- }
-
- printk(KERN_INFO "Silicon Graphics %s (rev %d)\n",
- visws_board_type == VISWS_320 ? "320" :
- (visws_board_type == VISWS_540 ? "540" :
- "unknown"),
- visws_board_rev);
- }
-#endif
-
static char command_line[COMMAND_LINE_SIZE];
char saved_command_line[COMMAND_LINE_SIZE];
@@ -1290,7 +1166,6 @@ static int __init init_amd(struct cpuinfo_x86 *c)
break;
case 6: /* An Athlon/Duron */
- mcheck_init(c);
/* Bit 15 of Athlon specific MSR 15, needs to be 0
* to enable SSE on Palomino/Morgan CPU's.
@@ -1298,15 +1173,12 @@ static int __init init_amd(struct cpuinfo_x86 *c)
* here.
*/
if (c->x86_model == 6 || c->x86_model == 7) {
- if (!test_bit(X86_FEATURE_XMM,
- &c->x86_capability)) {
- printk(KERN_INFO
- "Enabling Disabled K7/SSE Support...\n");
+ if (!test_bit(X86_FEATURE_XMM, &c->x86_capability)) {
+ printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
rdmsr(MSR_K7_HWCR, l, h);
l &= ~0x00008000;
wrmsr(MSR_K7_HWCR, l, h);
- set_bit(X86_FEATURE_XMM,
- &c->x86_capability);
+ set_bit(X86_FEATURE_XMM, &c->x86_capability);
}
}
break;
@@ -1937,7 +1809,6 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
c->x86_cache_size = (cc>>24)+(dd>>24);
}
sprintf( c->x86_model_id, "WinChip %s", name );
- mcheck_init(c);
break;
case 6:
@@ -2223,7 +2094,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
strcpy(c->x86_model_id, p);
#ifdef CONFIG_SMP
- if (test_bit(X86_FEATURE_HT, &c->x86_capability[0])) {
+ if (test_bit(X86_FEATURE_HT, &c->x86_capability)) {
extern int phys_proc_id[NR_CPUS];
u32 eax, ebx, ecx, edx;
@@ -2245,7 +2116,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
*/
#define NR_SIBLINGS 2
if (smp_num_siblings != NR_SIBLINGS) {
- printk(KERN_WARNING "CPU: Unsuppored number of the siblings %d", smp_num_siblings);
+ printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
smp_num_siblings = 1;
goto too_many_siblings;
}
@@ -2271,8 +2142,6 @@ static void __init init_intel(struct cpuinfo_x86 *c)
}
too_many_siblings:
#endif
- /* Enable MCA if available */
- mcheck_init(c);
}
void __init get_cpu_vendor(struct cpuinfo_x86 *c)
@@ -2652,7 +2521,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
init_rise(c);
break;
}
-
+
printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
c->x86_capability[0],
c->x86_capability[1],
@@ -2679,6 +2548,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
/* Disable the PN if appropriate */
squash_the_stupid_serial_number(c);
+ /* Init Machine Check Exception if available. */
+ mcheck_init(c);
+
/* If the model name is still unset, do table lookup. */
if ( !c->x86_model_id[0] ) {
char *p;
diff --git a/arch/ia64/hp/hpsim_console.c b/arch/ia64/hp/hpsim_console.c
index 4f56dc829..4782748eb 100644
--- a/arch/ia64/hp/hpsim_console.c
+++ b/arch/ia64/hp/hpsim_console.c
@@ -24,14 +24,12 @@
static int simcons_init (struct console *, char *);
static void simcons_write (struct console *, const char *, unsigned);
-static int simcons_wait_key (struct console *);
static kdev_t simcons_console_device (struct console *);
struct console hpsim_cons = {
name: "simcons",
write: simcons_write,
device: simcons_console_device,
- wait_key: simcons_wait_key,
setup: simcons_init,
flags: CON_PRINTBUFFER,
index: -1,
@@ -56,17 +54,6 @@ simcons_write (struct console *cons, const char *buf, unsigned count)
}
}
-static int
-simcons_wait_key (struct console *cons)
-{
- char ch;
-
- do {
- ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR);
- } while (ch == '\0');
- return ch;
-}
-
static kdev_t
simcons_console_device (struct console *c)
{
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index b66b6ec9e..82eb84428 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -114,8 +114,6 @@ cpu_idle (void *unused)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
-
while (1) {
#ifdef CONFIG_SMP
diff --git a/arch/ia64/sn/io/hcl.c b/arch/ia64/sn/io/hcl.c
index a05abc327..a8bb78824 100644
--- a/arch/ia64/sn/io/hcl.c
+++ b/arch/ia64/sn/io/hcl.c
@@ -1049,16 +1049,22 @@ hwgraph_char_device_get(devfs_handle_t de)
struct file_operations *
hwgraph_cdevsw_get(devfs_handle_t de)
{
- return(devfs_get_ops(de));
+ struct file_operations *fops = devfs_get_ops(de);
+
+ devfs_put_ops(de); /* FIXME: this may need to be moved to callers */
+ return(fops);
}
/*
* hwgraph_bdevsw_get - returns the fops of the given devfs entry.
*/
-struct file_operations *
+struct file_operations * /* FIXME: shouldn't this be a blkdev? */
hwgraph_bdevsw_get(devfs_handle_t de)
{
- return(devfs_get_ops(de));
+ struct file_operations *fops = devfs_get_ops(de);
+
+ devfs_put_ops(de); /* FIXME: this may need to be moved to callers */
+ return(fops);
}
/*
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 5dc8ca17b..4c8bb2769 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -98,7 +98,6 @@ extern void amiga_mksound( unsigned int count, unsigned int ticks );
extern void amiga_floppy_setup(char *, int *);
#endif
static void amiga_reset (void);
-static int amiga_wait_key (struct console *co);
extern void amiga_init_sound(void);
static void amiga_savekmsg_init(void);
static void amiga_mem_console_write(struct console *co, const char *b,
@@ -112,7 +111,6 @@ static void amiga_heartbeat(int on);
static struct console amiga_console_driver = {
name: "debug",
- wait_key: amiga_wait_key,
flags: CON_PRINTBUFFER,
index: -1,
};
@@ -742,33 +740,6 @@ static int amiga_set_clock_mmss (unsigned long nowtime)
return 0;
}
-static int amiga_wait_key (struct console *co)
-{
- int i;
-
- while (1) {
- while (ciaa.pra & 0x40);
-
- /* debounce */
- for (i = 0; i < 1000; i++);
-
- if (!(ciaa.pra & 0x40))
- break;
- }
-
- /* wait for button up */
- while (1) {
- while (!(ciaa.pra & 0x40));
-
- /* debounce */
- for (i = 0; i < 1000; i++);
-
- if (ciaa.pra & 0x40)
- break;
- }
- return 0;
-}
-
static NORET_TYPE void amiga_reset( void )
ATTRIB_NORET;
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index c62ca9f00..520a1ea26 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -81,7 +81,6 @@ void cpu_idle(void)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
idle();
}
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
index 93e7486af..c23e912b7 100644
--- a/arch/m68k/mac/debug.c
+++ b/arch/m68k/mac/debug.c
@@ -248,17 +248,6 @@ int mac_sccb_console_wait_key(struct console *co)
return( scc.cha_b_data );
}
-int mac_scca_console_wait_key(struct console *co)
-{
- int i;
- do {
- for( i = uSEC; i > 0; --i )
- barrier();
- } while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */
- for( i = uSEC; i > 0; --i )
- barrier();
- return( scc.cha_a_data );
-}
#endif
/* The following two functions do a quick'n'dirty initialization of the MFP or
@@ -395,9 +384,6 @@ void __init mac_debug_init(void)
/* Mac modem port */
mac_init_scc_port( B9600|CS8, 0 );
mac_console_driver.write = mac_scca_console_write;
-#ifdef CONFIG_SERIAL_CONSOLE
- mac_console_driver.wait_key = mac_scca_console_wait_key;
-#endif
scc_port = 0;
}
else if (!strcmp( m68k_debug_device, "ser2" )) {
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 4a85a6e1c..e0fc27d8a 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -241,31 +241,7 @@ void m147_scc_write (struct console *co, const char *str, unsigned count)
restore_flags(flags);
}
-
-static int m147_scc_wait_key (struct console *co)
-{
- volatile unsigned char *p = (volatile char *)M147_SCC_A_ADDR;
- unsigned long flags;
- int c;
-
- /* wait for rx buf filled */
- while ((*p & 0x01) == 0)
- ;
-
- save_flags(flags);
- cli();
-
- *p = 8;
- scc_delay();
- c = *p;
-
- restore_flags(flags);
- return c;
-}
-
-
void mvme147_init_console_port (struct console *co, int cflag)
{
co->write = m147_scc_write;
- co->wait_key = m147_scc_wait_key;
}
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 4989e67bc..d361b8f54 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -72,10 +72,8 @@ static void q40_mem_console_write(struct console *co, const char *b,
extern int ql_ticks;
-static int q40_wait_key(struct console *co){return 0;}
static struct console q40_console_driver = {
name: "debug",
- wait_key: q40_wait_key,
flags: CON_PRINTBUFFER,
index: -1,
};
diff --git a/arch/m68k/sun3x/prom.c b/arch/m68k/sun3x/prom.c
index 124def67d..8baa5ab56 100644
--- a/arch/m68k/sun3x/prom.c
+++ b/arch/m68k/sun3x/prom.c
@@ -96,7 +96,6 @@ static struct console sun3x_debug = {
sun3x_prom_write, /* write */
NULL, /* read */
NULL, /* device */
- NULL, /* wait_key */
NULL, /* unblank */
NULL, /* setup */
CON_PRINTBUFFER,
diff --git a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c
index 439a33288..cbf01a405 100644
--- a/arch/mips/au1000/common/serial.c
+++ b/arch/mips/au1000/common/serial.c
@@ -2922,35 +2922,6 @@ static void serial_console_write(struct console *co, const char *s,
serial_out(info, UART_IER, ier);
}
-/*
- * Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
- static struct async_struct *info;
- int ier, c;
-
- info = &async_sercons;
-
- /*
- * First save the IER then disable the interrupts so
- * that the real driver for the port does not get the
- * character.
- */
- ier = serial_in(info, UART_IER);
- serial_out(info, UART_IER, 0x00);
-
- while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0);
- c = serial_in(info, UART_RX);
-
- /*
- * Restore the interrupts
- */
- serial_out(info, UART_IER, ier);
-
- return c;
-}
-
static kdev_t serial_console_device(struct console *c)
{
return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -3075,7 +3046,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/arch/mips/baget/vacserial.c b/arch/mips/baget/vacserial.c
index 85329f1a8..f2fbcabcd 100644
--- a/arch/mips/baget/vacserial.c
+++ b/arch/mips/baget/vacserial.c
@@ -2622,43 +2622,6 @@ static void serial_console_write(struct console *co, const char *s,
serial_outp(&scr_info, VAC_UART_INT_MASK, ier);
}
-/*
- * Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
- struct serial_state *ser;
- int ier;
- int lsr;
- int c;
- struct async_struct scr_info; /* serial_{in,out} because HUB6 */
-
- ser = rs_table + co->index;
- scr_info.magic = SERIAL_MAGIC;
- scr_info.port = ser->port;
- scr_info.flags = ser->flags;
-
- /*
- * First save the IER then disable the interrupts so
- * that the real driver for the port does not get the
- * character.
- */
- ier = serial_inp(&scr_info, VAC_UART_INT_MASK);
- serial_outp(&scr_info, VAC_UART_INT_MASK, 0x00);
-
- do {
- lsr = serial_inp(&scr_info, VAC_UART_INT_STATUS);
- } while (!(lsr & VAC_UART_STATUS_RX_READY));
- c = serial_inp(&scr_info, VAC_UART_RX);
-
- /*
- * Restore the interrupts
- */
- serial_outp(&scr_info, VAC_UART_INT_MASK, ier);
-
- return c;
-}
-
static kdev_t serial_console_device(struct console *c)
{
return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -2812,7 +2775,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/arch/mips/dec/promcon.c b/arch/mips/dec/promcon.c
index 2c8ba4d7f..1a777869d 100644
--- a/arch/mips/dec/promcon.c
+++ b/arch/mips/dec/promcon.c
@@ -30,11 +30,6 @@ static void prom_console_write(struct console *co, const char *s,
}
}
-static int prom_console_wait_key(struct console *co)
-{
- return prom_getchar();
-}
-
static int __init prom_console_setup(struct console *co, char *options)
{
return 0;
@@ -50,7 +45,6 @@ static struct console sercons =
name: "ttyS",
write: prom_console_write,
device: prom_console_device,
- wait_key: prom_console_wait_key,
setup: prom_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 9ae656291..248c51d94 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -36,7 +36,6 @@ void cpu_idle(void)
{
/* endless idle loop with no priority at all */
current->nice = 20;
- current->counter = -100;
init_idle();
while (1) {
diff --git a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c
index 7060ce768..595b39670 100644
--- a/arch/mips64/kernel/process.c
+++ b/arch/mips64/kernel/process.c
@@ -34,7 +34,6 @@ asmlinkage int cpu_idle(void)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
while (1) {
while (!current->need_resched)
if (wait_available)
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 87567e6a1..e88ee409c 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -105,10 +105,6 @@ static int pdc_console_setup(struct console *co, char *options)
static struct console pdc_cons = {
name: "ttyB",
write: pdc_console_write,
- read: NULL,
- device: NULL,
- wait_key: pdc_console_wait_key,
- unblank: NULL,
setup: pdc_console_setup,
flags: CON_PRINTBUFFER|CON_ENABLED, // |CON_CONSDEV,
index: -1,
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index d699f5dab..aae398f1e 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -71,7 +71,6 @@ void cpu_idle(void)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
while (1) {
while (!current->need_resched) {
diff --git a/arch/ppc/8260_io/uart.c b/arch/ppc/8260_io/uart.c
index 800401c90..419a38c36 100644
--- a/arch/ppc/8260_io/uart.c
+++ b/arch/ppc/8260_io/uart.c
@@ -1732,7 +1732,7 @@ static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
#endif
current->state = TASK_INTERRUPTIBLE;
-/* current->counter = 0; make us low-priority */
+/* current->dyn_prio = 0; make us low-priority */
schedule_timeout(char_time);
if (signal_pending(current))
break;
@@ -2216,54 +2216,6 @@ static void serial_console_write(struct console *c, const char *s,
info->tx_cur = (cbd_t *)bdp;
}
-/*
- * Receive character from the serial port. This only works well
- * before the port is initialize for real use.
- */
-static int serial_console_wait_key(struct console *co)
-{
- struct serial_state *ser;
- u_char c, *cp;
- ser_info_t *info;
- volatile cbd_t *bdp;
- volatile smc_uart_t *up;
-
- ser = rs_table + co->index;
-
- /* Pointer to UART in parameter ram.
- */
- up = (smc_uart_t *)&immr->im_dprambase[ser->port];
-
- /* Get the address of the host memory buffer.
- * If the port has been initialized for general use, we must
- * use information from the port structure.
- */
- if ((info = (ser_info_t *)ser->info))
- bdp = info->rx_cur;
- else
- bdp = (cbd_t *)&immr->im_dprambase[up->smc_rbase];
-
- /*
- * We need to gracefully shut down the receiver, disable
- * interrupts, then read the input.
- */
- while (bdp->cbd_sc & BD_SC_EMPTY); /* Wait for a character */
- cp = __va(bdp->cbd_bufaddr);
-
- if (info) {
- if (bdp->cbd_sc & BD_SC_WRAP) {
- bdp = info->rx_bd_base;
- }
- else {
- bdp++;
- }
- info->rx_cur = (cbd_t *)bdp;
- }
-
- c = *cp;
- return((int)c);
-}
-
static kdev_t serial_console_device(struct console *c)
{
return MKDEV(TTYAUX_MAJOR, 64 + c->index);
@@ -2274,7 +2226,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: CONFIG_SERIAL_CONSOLE_PORT,
diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
index ab4d9d192..71207e3b6 100644
--- a/arch/ppc/8xx_io/uart.c
+++ b/arch/ppc/8xx_io/uart.c
@@ -97,7 +97,6 @@ static int serial_console_setup(struct console *co, char *options);
static void serial_console_write(struct console *c, const char *s,
unsigned count);
static kdev_t serial_console_device(struct console *c);
-static int serial_console_wait_key(struct console *co);
#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
static unsigned long break_pressed; /* break, really ... */
@@ -218,7 +217,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: CONFIG_SERIAL_CONSOLE_PORT,
@@ -1798,7 +1796,7 @@ static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
#endif
current->state = TASK_INTERRUPTIBLE;
-/* current->counter = 0; make us low-priority */
+/* current->dyn_prio = 0; make us low-priority */
schedule_timeout(char_time);
if (signal_pending(current))
break;
@@ -2402,11 +2400,6 @@ static int my_console_wait_key(int idx, int xmon, char *obuf)
return((int)c);
}
-static int serial_console_wait_key(struct console *co)
-{
- return(my_console_wait_key(co->index, 0, NULL));
-}
-
#ifdef CONFIG_XMON
int
xmon_8xx_read_poll(void)
diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
index c26b6fdd3..90b4f2e49 100644
--- a/arch/ppc/amiga/config.c
+++ b/arch/ppc/amiga/config.c
@@ -104,7 +104,6 @@ extern void amiga_mksound( unsigned int count, unsigned int ticks );
extern void amiga_floppy_setup(char *, int *);
#endif
static void amiga_reset (void);
-static int amiga_wait_key (struct console *co);
extern void amiga_init_sound(void);
static void amiga_savekmsg_init(void);
static void amiga_mem_console_write(struct console *co, const char *b,
@@ -118,7 +117,6 @@ static void amiga_heartbeat(int on);
static struct console amiga_console_driver = {
name: "debug",
- wait_key: amiga_wait_key,
flags: CON_PRINTBUFFER,
index: -1,
};
@@ -736,33 +734,6 @@ static int amiga_set_clock_mmss (unsigned long nowtime)
return 0;
}
-static int amiga_wait_key (struct console *co)
-{
- int i;
-
- while (1) {
- while (ciaa.pra & 0x40);
-
- /* debounce */
- for (i = 0; i < 1000; i++);
-
- if (!(ciaa.pra & 0x40))
- break;
- }
-
- /* wait for button up */
- while (1) {
- while (!(ciaa.pra & 0x40));
-
- /* debounce */
- for (i = 0; i < 1000; i++);
-
- if (ciaa.pra & 0x40)
- break;
- }
- return 0;
-}
-
static NORET_TYPE void amiga_reset( void )
ATTRIB_NORET;
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 73a929b10..3fff2ebb6 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -54,7 +54,6 @@ int idled(void)
/* endless loop with no priority at all */
current->nice = 20;
- current->counter = -100;
init_idle();
for (;;) {
#ifdef CONFIG_SMP
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 13f9ab1f2..978c6647b 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -57,7 +57,6 @@ int cpu_idle(void *unused)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
wait_psw.mask = _WAIT_PSW_MASK;
wait_psw.addr = (unsigned long) &&idle_wakeup | 0x80000000L;
while(1) {
diff --git a/arch/s390x/kernel/process.c b/arch/s390x/kernel/process.c
index 07e216330..c54bb41e7 100644
--- a/arch/s390x/kernel/process.c
+++ b/arch/s390x/kernel/process.c
@@ -57,7 +57,6 @@ int cpu_idle(void *unused)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
wait_psw.mask = _WAIT_PSW_MASK;
wait_psw.addr = (unsigned long) &&idle_wakeup;
while(1) {
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 540838107..ae0dfa9b8 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -41,7 +41,6 @@ void cpu_idle(void *unused)
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
- current->counter = -100;
while (1) {
if (hlt_counter) {
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index a6ce692e6..bc0ed96a4 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -140,15 +140,6 @@ static void sh_console_write(struct console *co, const char *s,
sh_bios_console_write(s, count);
}
-/*
- * Receive character from the serial port
- */
-static int sh_console_wait_key(struct console *co)
-{
- /* Not implemented yet */
- return 0;
-}
-
static kdev_t sh_console_device(struct console *c)
{
/* TODO: this is totally bogus */
@@ -183,7 +174,6 @@ static struct console sh_console = {
name: "bios",
write: sh_console_write,
device: sh_console_device,
- wait_key: sh_console_wait_key,
setup: sh_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 3b230278d..d81137570 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.158 2001-11-26 23:45:00 davem Exp $
+/* $Id: process.c,v 1.159 2002-01-08 16:00:14 davem Exp $
* linux/arch/sparc/kernel/process.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -61,7 +61,6 @@ int cpu_idle(void)
/* endless idle loop with no priority at all */
current->nice = 20;
- current->counter = -100;
init_idle();
for (;;) {
@@ -110,7 +109,6 @@ int cpu_idle(void)
{
/* endless idle loop with no priority at all */
current->nice = 20;
- current->counter = -100;
init_idle();
while(1) {
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index 4e2fc3641..315e1ad37 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.135 2001-08-13 14:40:10 davem Exp $
+/* $Id: sys_sunos.c,v 1.136 2002-01-08 16:00:14 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -90,8 +90,8 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
* SunOS is so stupid some times... hmph!
*/
if (file) {
- if(MAJOR(file->f_dentry->d_inode->i_rdev) == MEM_MAJOR &&
- MINOR(file->f_dentry->d_inode->i_rdev) == 5) {
+ if(major(file->f_dentry->d_inode->i_rdev) == MEM_MAJOR &&
+ minor(file->f_dentry->d_inode->i_rdev) == 5) {
flags |= MAP_ANONYMOUS;
fput(file);
file = 0;
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 67abc31f0..7fa81bfca 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -599,7 +599,7 @@ CONFIG_EFS_FS=m
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_TMPFS is not set
-CONFIG_RAMFS=m
+CONFIG_RAMFS=y
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
@@ -739,8 +739,9 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_LONG_TIMEOUT is not set
#
-# USB Controllers
+# USB Host Controller Drivers
#
+CONFIG_USB_EHCI_HCD=m
CONFIG_USB_UHCI=y
# CONFIG_USB_UHCI_ALT is not set
CONFIG_USB_OHCI=y
@@ -785,6 +786,8 @@ CONFIG_USB_IBMCAM=m
CONFIG_USB_OV511=m
CONFIG_USB_PWC=m
CONFIG_USB_SE401=m
+CONFIG_USB_STV680=m
+CONFIG_USB_VICAM=m
CONFIG_USB_DSBR=m
CONFIG_USB_DABUSB=m
@@ -813,6 +816,7 @@ CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
# CONFIG_USB_SERIAL_IR is not set
CONFIG_USB_SERIAL_EDGEPORT=m
CONFIG_USB_SERIAL_KEYSPAN_PDA=m
@@ -826,6 +830,7 @@ CONFIG_USB_SERIAL_KEYSPAN=m
# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c
index 8520c4541..5d1744493 100644
--- a/arch/sparc64/kernel/chmc.c
+++ b/arch/sparc64/kernel/chmc.c
@@ -1,4 +1,4 @@
-/* $Id: chmc.c,v 1.3 2001-04-03 12:49:47 davem Exp $
+/* $Id: chmc.c,v 1.4 2002-01-08 16:00:14 davem Exp $
* memctrlr.c: Driver for UltraSPARC-III memory controller.
*
* Copyright (C) 2001 David S. Miller (davem@redhat.com)
@@ -9,6 +9,10 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
#include <linux/init.h>
#include <asm/spitfire.h>
#include <asm/chmctrl.h>
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 74beb6c38..6355d71c1 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.126 2001-12-18 19:42:33 davem Exp $
+/* $Id: process.c,v 1.127 2002-01-08 16:00:14 davem Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -54,7 +54,6 @@ int cpu_idle(void)
/* endless idle loop with no priority at all */
current->nice = 20;
- current->counter = -100;
init_idle();
for (;;) {
@@ -84,7 +83,6 @@ int cpu_idle(void)
int cpu_idle(void)
{
current->nice = 20;
- current->counter = -100;
init_idle();
while(1) {
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 35c5d29b3..9823338fc 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.61 2001-08-13 14:40:07 davem Exp $
+/* $Id: sys_sunos32.c,v 1.62 2002-01-08 16:00:14 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -68,7 +68,7 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
struct file *file = NULL;
unsigned long retval, ret_type;
- if(flags & MAP_NORESERVE) {
+ if (flags & MAP_NORESERVE) {
static int cnt;
if (cnt++ < 10)
printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
@@ -76,15 +76,15 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
flags &= ~MAP_NORESERVE;
}
retval = -EBADF;
- if(!(flags & MAP_ANONYMOUS)) {
+ if (!(flags & MAP_ANONYMOUS)) {
struct inode * inode;
- if(fd >= SUNOS_NR_OPEN)
+ if (fd >= SUNOS_NR_OPEN)
goto out;
file = fget(fd);
if (!file)
goto out;
inode = file->f_dentry->d_inode;
- if(MAJOR(inode->i_rdev)==MEM_MAJOR && MINOR(inode->i_rdev)==5) {
+ if (minor(inode->i_rdev) == MEM_MAJOR && minor(inode->i_rdev) == 5) {
flags |= MAP_ANONYMOUS;
fput(file);
file = NULL;
@@ -92,7 +92,7 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
}
retval = -EINVAL;
- if(!(flags & MAP_FIXED))
+ if (!(flags & MAP_FIXED))
addr = 0;
else if (len > 0xf0000000 || addr > 0xf0000000 - len)
goto out_putf;
@@ -106,7 +106,7 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
(unsigned long) prot, (unsigned long) flags,
(unsigned long) off);
up_write(&current->mm->mmap_sem);
- if(!ret_type)
+ if (!ret_type)
retval = ((retval < 0xf0000000) ? 0 : retval);
out_putf:
if (file)
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index 8973594f5..24758d5bf 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -1,4 +1,4 @@
-/* $Id: fs.c,v 1.25 2001-09-19 00:04:30 davem Exp $
+/* $Id: fs.c,v 1.26 2002-01-08 16:00:21 davem Exp $
* fs.c: fs related syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -429,7 +429,7 @@ static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
__put_user (s.f_files, &ss->f_files) ||
__put_user (s.f_ffree, &ss->f_ffree) ||
__put_user (s.f_ffree, &ss->f_favail) ||
- __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
+ __put_user (R4_DEV(kdev_t_to_nr(inode->i_sb->s_dev)), &ss->f_fsid) ||
__copy_to_user (ss->f_basetype,p,j) ||
__put_user (0, (char *)&ss->f_basetype[j]) ||
__put_user (s.f_namelen, &ss->f_namemax) ||
@@ -463,7 +463,7 @@ static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
__put_user (s.f_files, &ss->f_files) ||
__put_user (s.f_ffree, &ss->f_ffree) ||
__put_user (s.f_ffree, &ss->f_favail) ||
- __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
+ __put_user (R4_DEV(kdev_t_to_nr(inode->i_sb->s_dev)), &ss->f_fsid) ||
__copy_to_user (ss->f_basetype,p,j) ||
__put_user (0, (char *)&ss->f_basetype[j]) ||
__put_user (s.f_namelen, &ss->f_namemax) ||
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 8071cec21..427de755f 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.34 2001-12-11 04:55:51 davem Exp $
+/* $Id: misc.c,v 1.35 2002-01-08 16:00:21 davem Exp $
* misc.c: Miscelaneous syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -75,8 +75,8 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
goto out;
else {
struct inode * inode = file->f_dentry->d_inode;
- if(MAJOR(inode->i_rdev) == MEM_MAJOR &&
- MINOR(inode->i_rdev) == 5) {
+ if(major(inode->i_rdev) == MEM_MAJOR &&
+ minor(inode->i_rdev) == 5) {
flags |= MAP_ANONYMOUS;
fput(file);
file = NULL;
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index 70c1969e3..d5f3c857d 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.19 2001-12-11 04:55:51 davem Exp $
+/* $Id: socksys.c,v 1.20 2002-01-08 16:00:21 davem Exp $
* socksys.c: /dev/inet/ stuff for Solaris emulation.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -61,14 +61,14 @@ static int socksys_open(struct inode * inode, struct file * filp)
(int (*)(int,int,int))SUNOS(97);
struct sol_socket_struct * sock;
- family = ((MINOR(inode->i_rdev) >> 4) & 0xf);
+ family = ((minor(inode->i_rdev) >> 4) & 0xf);
switch (family) {
case AF_UNIX:
type = SOCK_STREAM;
protocol = 0;
break;
case AF_INET:
- protocol = af_inet_protocols[MINOR(inode->i_rdev) & 0xf];
+ protocol = af_inet_protocols[minor(inode->i_rdev) & 0xf];
switch (protocol) {
case IPPROTO_TCP: type = SOCK_STREAM; break;
case IPPROTO_UDP: type = SOCK_DGRAM; break;
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index 2b113bb71..9ae729da7 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -1,4 +1,4 @@
-/* $Id: timod.c,v 1.17 2001-12-11 06:11:52 davem Exp $
+/* $Id: timod.c,v 1.18 2002-01-08 16:00:21 davem Exp $
* timod.c: timod emulation.
*
* Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
@@ -921,7 +921,7 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
if (!ino) goto out;
if (!ino->i_sock &&
- (MAJOR(ino->i_rdev) != 30 || MINOR(ino->i_rdev) != 1))
+ (major(ino->i_rdev) != 30 || minor(ino->i_rdev) != 1))
goto out;
ctlptr = (struct strbuf *)A(arg1);
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index c53ce346a..9ad0510cc 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -1311,10 +1311,8 @@ static struct gendisk mfm_gendisk = {
major: MAJOR_NR,
major_name: "mfm",
minor_shift: 6,
- max_p: 1 << 6,
part: mfm,
sizes: mfm_sizes,
- real_devices: (void *)mfm_info,
};
static struct block_device_operations mfm_fops =
@@ -1473,7 +1471,7 @@ static int mfm_reread_partitions(kdev_t dev)
mfm_info[target].busy = 1;
restore_flags (flags);
- maxp = mfm_gendisk.max_p;
+ maxp = 1 << mfm_gendisk.minor_shift;
start = target << mfm_gendisk.minor_shift;
for (i = maxp - 1; i >= 0; i--) {
diff --git a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c
index 6149d73ef..9e86ea983 100644
--- a/drivers/acorn/scsi/acornscsi.c
+++ b/drivers/acorn/scsi/acornscsi.c
@@ -3142,18 +3142,17 @@ static Scsi_Host_Template acornscsi_template = {
static int __init acornscsi_init(void)
{
- acornscsi_template.module = THIS_MODULE;
- scsi_register_module(MODULE_SCSI_HA, &acornscsi_template);
+ scsi_register_host(&acornscsi_template);
if (acornscsi_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template);
+ scsi_unregister_host(&acornscsi_template);
return -ENODEV;
}
static void __exit acornscsi_exit(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template);
+ scsi_unregister_host(&acornscsi_template);
}
module_init(acornscsi_init);
diff --git a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c
index 7874cad48..f26ab9f70 100644
--- a/drivers/acorn/scsi/arxescsi.c
+++ b/drivers/acorn/scsi/arxescsi.c
@@ -423,17 +423,17 @@ static Scsi_Host_Template arxescsi_template = ARXEScsi;
static int __init init_arxe_scsi_driver(void)
{
arxescsi_template.module = THIS_MODULE;
- scsi_register_module(MODULE_SCSI_HA, &arxescsi_template);
+ scsi_register_host(&arxescsi_template);
if (arxescsi_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &arxescsi_template);
+ scsi_unregister_host(&arxescsi_template);
return -ENODEV;
}
static void __exit exit_arxe_scsi_driver(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &arxescsi_template);
+ scsi_unregister_host(&arxescsi_template);
}
module_init(init_arxe_scsi_driver);
diff --git a/drivers/acorn/scsi/cumana_1.c b/drivers/acorn/scsi/cumana_1.c
index 1b490e90c..0f9d3663a 100644
--- a/drivers/acorn/scsi/cumana_1.c
+++ b/drivers/acorn/scsi/cumana_1.c
@@ -409,17 +409,17 @@ static Scsi_Host_Template cumanascsi_template = {
static int __init cumanascsi_init(void)
{
- scsi_register_module(MODULE_SCSI_HA, &cumanascsi_template);
+ scsi_register_host(&cumanascsi_template);
if (cumanascsi_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
+ scsi_unregister_host(&cumanascsi_template);
return -ENODEV;
}
static void __exit cumanascsi_exit(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
+ scsi_unregister_host(&cumanascsi_template);
}
module_init(cumanascsi_init);
diff --git a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c
index c5a9ce6cc..874d053fb 100644
--- a/drivers/acorn/scsi/cumana_2.c
+++ b/drivers/acorn/scsi/cumana_2.c
@@ -579,17 +579,17 @@ static Scsi_Host_Template cumanascsi2_template = {
static int __init cumanascsi2_init(void)
{
- scsi_register_module(MODULE_SCSI_HA, &cumanascsi2_template);
+ scsi_register_host(&cumanascsi2_template);
if (cumanascsi2_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi2_template);
+ scsi_unregister_host(&cumanascsi2_template);
return -ENODEV;
}
static void __exit cumanascsi2_exit(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi2_template);
+ scsi_unregister_host(&cumanascsi2_template);
}
module_init(cumanascsi2_init);
diff --git a/drivers/acorn/scsi/ecoscsi.c b/drivers/acorn/scsi/ecoscsi.c
index 62fdc6db2..a605212d2 100644
--- a/drivers/acorn/scsi/ecoscsi.c
+++ b/drivers/acorn/scsi/ecoscsi.c
@@ -276,17 +276,17 @@ static Scsi_Host_Template ecoscsi_template = {
static int __init ecoscsi_init(void)
{
- scsi_register_module(MODULE_SCSI_HA, &ecoscsi_template);
+ scsi_register_host(&ecoscsi_template);
if (ecoscsi_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &ecoscsi_template);
+ scsi_unregister_host(&ecoscsi_template);
return -ENODEV;
}
static void __exit ecoscsi_exit(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &ecoscsi_template);
+ scsi_unregister_host(&ecoscsi_template);
}
module_init(ecoscsi_init);
diff --git a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c
index bb19890ed..c79551a09 100644
--- a/drivers/acorn/scsi/eesox.c
+++ b/drivers/acorn/scsi/eesox.c
@@ -581,17 +581,17 @@ static Scsi_Host_Template eesox_template = {
static int __init eesox_init(void)
{
- scsi_register_module(MODULE_SCSI_HA, &eesox_template);
+ scsi_register_host(&eesox_template);
if (eesox_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &eesox_template);
+ scsi_unregister_host(&eesox_template);
return -ENODEV;
}
static void __exit eesox_exit(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &eesox_template);
+ scsi_unregister_host(&eesox_template);
}
module_init(eesox_init);
diff --git a/drivers/acorn/scsi/oak.c b/drivers/acorn/scsi/oak.c
index c53a83521..8be076da6 100644
--- a/drivers/acorn/scsi/oak.c
+++ b/drivers/acorn/scsi/oak.c
@@ -270,17 +270,17 @@ static Scsi_Host_Template oakscsi_template = {
static int __init oakscsi_init(void)
{
- scsi_register_module(MODULE_SCSI_HA, &oakscsi_template);
+ scsi_register_host(&oakscsi_template);
if (oakscsi_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &oakscsi_template);
+ scsi_unregister_host(&oakscsi_template);
return -ENODEV;
}
static void __exit oakscsi_exit(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &oakscsi_template);
+ scsi_unregister_host(&oakscsi_template);
}
module_init(oakscsi_init);
diff --git a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c
index 06a3c3043..8892b80fb 100644
--- a/drivers/acorn/scsi/powertec.c
+++ b/drivers/acorn/scsi/powertec.c
@@ -481,17 +481,17 @@ static Scsi_Host_Template powertecscsi_template = {
static int __init powertecscsi_init(void)
{
- scsi_register_module(MODULE_SCSI_HA, &powertecscsi_template);
+ scsi_register_host(&powertecscsi_template);
if (powertecscsi_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &powertecscsi_template);
+ scsi_unregister_host(&powertecscsi_template);
return -ENODEV;
}
static void __exit powertecscsi_exit(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &powertecscsi_template);
+ scsi_unregister_host(&powertecscsi_template);
}
module_init(powertecscsi_init);
diff --git a/drivers/acpi/ospm/ac_adapter/ac_osl.c b/drivers/acpi/ospm/ac_adapter/ac_osl.c
index cd206c3e5..863df8474 100644
--- a/drivers/acpi/ospm/ac_adapter/ac_osl.c
+++ b/drivers/acpi/ospm/ac_adapter/ac_osl.c
@@ -35,6 +35,7 @@
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - AC Adapter Driver");
+MODULE_LICENSE("GPL");
#define AC_PROC_ROOT "ac_adapter"
diff --git a/drivers/acpi/ospm/battery/bt_osl.c b/drivers/acpi/ospm/battery/bt_osl.c
index 6ee917995..5306d1633 100644
--- a/drivers/acpi/ospm/battery/bt_osl.c
+++ b/drivers/acpi/ospm/battery/bt_osl.c
@@ -44,6 +44,7 @@
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Control Method Battery Driver");
+MODULE_LICENSE("GPL");
#define BT_PROC_ROOT "battery"
diff --git a/drivers/acpi/ospm/busmgr/bm_osl.c b/drivers/acpi/ospm/busmgr/bm_osl.c
index 268fe258c..57db24961 100644
--- a/drivers/acpi/ospm/busmgr/bm_osl.c
+++ b/drivers/acpi/ospm/busmgr/bm_osl.c
@@ -38,6 +38,7 @@
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - ACPI Bus Manager");
+MODULE_LICENSE("GPL");
/*****************************************************************************
diff --git a/drivers/acpi/ospm/button/bn_osl.c b/drivers/acpi/ospm/button/bn_osl.c
index 4ad3a685e..8c8b2d7ba 100644
--- a/drivers/acpi/ospm/button/bn_osl.c
+++ b/drivers/acpi/ospm/button/bn_osl.c
@@ -35,6 +35,7 @@
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Button Driver");
+MODULE_LICENSE("GPL");
#define BN_PROC_ROOT "button"
diff --git a/drivers/acpi/ospm/ec/ec_osl.c b/drivers/acpi/ospm/ec/ec_osl.c
index 649647dd9..14341ef6a 100644
--- a/drivers/acpi/ospm/ec/ec_osl.c
+++ b/drivers/acpi/ospm/ec/ec_osl.c
@@ -36,6 +36,7 @@
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Embedded Controller Driver");
+MODULE_LICENSE("GPL");
extern struct proc_dir_entry *bm_proc_root;
diff --git a/drivers/acpi/ospm/processor/pr_osl.c b/drivers/acpi/ospm/processor/pr_osl.c
index 36d6c984b..55f70e03b 100644
--- a/drivers/acpi/ospm/processor/pr_osl.c
+++ b/drivers/acpi/ospm/processor/pr_osl.c
@@ -37,6 +37,7 @@
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - IA32 Processor Driver");
+MODULE_LICENSE("GPL");
#define PR_PROC_ROOT "processor"
diff --git a/drivers/acpi/ospm/system/sm_osl.c b/drivers/acpi/ospm/system/sm_osl.c
index fa0649e67..6a6a601d3 100644
--- a/drivers/acpi/ospm/system/sm_osl.c
+++ b/drivers/acpi/ospm/system/sm_osl.c
@@ -42,6 +42,7 @@
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - ACPI System Driver");
+MODULE_LICENSE("GPL");
#define SM_PROC_INFO "info"
diff --git a/drivers/acpi/ospm/thermal/tz_osl.c b/drivers/acpi/ospm/thermal/tz_osl.c
index 905a27229..7529df7e7 100644
--- a/drivers/acpi/ospm/thermal/tz_osl.c
+++ b/drivers/acpi/ospm/thermal/tz_osl.c
@@ -35,6 +35,7 @@
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Thermal Zone Driver");
+MODULE_LICENSE("GPL");
int TZP = 0;
MODULE_PARM(TZP, "i");
diff --git a/drivers/acpi/ospm/thermal/tzpolicy.c b/drivers/acpi/ospm/thermal/tzpolicy.c
index 3c4ebbb2d..83608fab2 100644
--- a/drivers/acpi/ospm/thermal/tzpolicy.c
+++ b/drivers/acpi/ospm/thermal/tzpolicy.c
@@ -31,6 +31,7 @@
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#include <linux/pm.h>
+#include <linux/sched.h>
#include <acpi.h>
#include <bm.h>
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 4176eb9f2..1a29332ad 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -39,7 +39,6 @@
#include <linux/atm_suni.h>
#include <asm/io.h>
#include <asm/string.h>
-#include <asm/segment.h>
#include <asm/page.h>
#include <asm/irq.h>
#include <asm/dma.h>
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 0f0060dbb..c5b61f436 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -45,7 +45,6 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include "DAC960.h"
@@ -1974,9 +1973,7 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
Controller->GenericDiskInfo.major = MajorNumber;
Controller->GenericDiskInfo.major_name = "rd";
Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
- Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
Controller->GenericDiskInfo.nr_real = DAC960_MaxLogicalDrives;
- Controller->GenericDiskInfo.real_devices = Controller;
Controller->GenericDiskInfo.next = NULL;
Controller->GenericDiskInfo.fops = &DAC960_BlockDeviceOperations;
/*
@@ -2025,10 +2022,9 @@ static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
Information Partition Sector Counts and Block Sizes.
*/
-static void DAC960_ComputeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo)
+static void DAC960_ComputeGenericDiskInfo(DAC960_Controller_T *Controller)
{
- DAC960_Controller_T *Controller =
- (DAC960_Controller_T *) GenericDiskInfo->real_devices;
+ GenericDiskInfo_T *GenericDiskInfo = &Controller->GenericDiskInfo;
int LogicalDriveNumber, i;
for (LogicalDriveNumber = 0;
LogicalDriveNumber < DAC960_MaxLogicalDrives;
@@ -2659,7 +2655,7 @@ static int DAC960_Initialize(void)
int LogicalDriveNumber;
if (Controller == NULL) continue;
DAC960_InitializeController(Controller);
- DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
+ DAC960_ComputeGenericDiskInfo(Controller);
for (LogicalDriveNumber = 0;
LogicalDriveNumber < DAC960_MaxLogicalDrives;
LogicalDriveNumber++)
@@ -3162,7 +3158,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
Controller->ControllerNumber,
LogicalDriveNumber);
Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
- DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
+ DAC960_ComputeGenericDiskInfo(Controller);
}
if (NewEnquiry->NumberOfLogicalDrives < Controller->LogicalDriveCount)
{
@@ -3174,7 +3170,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
Controller->ControllerNumber,
LogicalDriveNumber);
Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
- DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
+ DAC960_ComputeGenericDiskInfo(Controller);
}
if (NewEnquiry->StatusFlags.DeferredWriteError !=
OldEnquiry->StatusFlags.DeferredWriteError)
@@ -4514,7 +4510,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
{
memset(LogicalDeviceInfo, 0,
sizeof(DAC960_V2_LogicalDeviceInfo_T));
- DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
+ DAC960_ComputeGenericDiskInfo(Controller);
}
}
if (LogicalDeviceInfo != NULL)
@@ -4631,7 +4627,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
kfree(LogicalDeviceInfo);
Controller->LogicalDriveInitiallyAccessible
[LogicalDriveNumber] = false;
- DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
+ DAC960_ComputeGenericDiskInfo(Controller);
}
Controller->V2.NeedLogicalDeviceInformation = false;
}
@@ -5300,7 +5296,7 @@ static int DAC960_Open(Inode_T *Inode, File_T *File)
if (!Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber])
{
Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true;
- DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
+ DAC960_ComputeGenericDiskInfo(Controller);
DAC960_RegisterDisk(Controller, LogicalDriveNumber);
}
if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index 760037053..eb5c2027a 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -2054,13 +2054,13 @@ extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument);
*/
#define DAC960_ControllerNumber(Device) \
- (MAJOR(Device) - DAC960_MAJOR)
+ (major(Device) - DAC960_MAJOR)
#define DAC960_LogicalDriveNumber(Device) \
- (MINOR(Device) >> DAC960_MaxPartitionsBits)
+ (minor(Device) >> DAC960_MaxPartitionsBits)
#define DAC960_PartitionNumber(Device) \
- (MINOR(Device) & (DAC960_MaxPartitions - 1))
+ (minor(Device) & (DAC960_MaxPartitions - 1))
#define DAC960_MajorNumber(ControllerNumber) \
(DAC960_MAJOR + (ControllerNumber))
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 28e5ae8e0..7ff7d7656 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -1386,10 +1386,8 @@ static struct gendisk acsi_gendisk = {
major: MAJOR_NR,
major_name: "ad",
minor_shift: 4,
- max_p: 1 << 4,
part: acsi_part,
sizes: acsi_sizes,
- real_devices: (void *)acsi_info,
fops: &acsi_fops,
};
diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c
index 579e2513b..9d1fdf03a 100644
--- a/drivers/block/blkpg.c
+++ b/drivers/block/blkpg.c
@@ -85,14 +85,16 @@ int add_partition(kdev_t dev, struct blkpg_partition *p)
return -ENXIO;
/* existing drive? */
- drive = (MINOR(dev) >> g->minor_shift);
+ drive = (minor(dev) >> g->minor_shift);
first_minor = (drive << g->minor_shift);
- end_minor = first_minor + g->max_p;
+ end_minor = first_minor + (1 << g->minor_shift);
if (drive >= g->nr_real)
return -ENXIO;
/* drive and partition number OK? */
- if (first_minor != MINOR(dev) || p->pno <= 0 || p->pno >= g->max_p)
+ if (first_minor != minor(dev))
+ return -EINVAL;
+ if (p->pno <= 0 || p->pno >= (1 << g->minor_shift))
return -EINVAL;
/* partition number in use? */
@@ -136,10 +138,13 @@ int del_partition(kdev_t dev, struct blkpg_partition *p)
return -ENXIO;
/* drive and partition number OK? */
- drive = (MINOR(dev) >> g->minor_shift);
+ drive = (minor(dev) >> g->minor_shift);
first_minor = (drive << g->minor_shift);
- if (first_minor != MINOR(dev) || p->pno <= 0 || p->pno >= g->max_p)
+
+ if (first_minor != minor(dev))
return -EINVAL;
+ if (p->pno <= 0 || p->pno >= (1 << g->minor_shift))
+ return -EINVAL;
/* existing drive and partition? */
minor = first_minor + p->pno;
@@ -147,7 +152,7 @@ int del_partition(kdev_t dev, struct blkpg_partition *p)
return -ENXIO;
/* partition in use? Incomplete check for now. */
- devp = MKDEV(MAJOR(dev), minor);
+ devp = mk_kdev(major(dev), minor);
if (is_mounted(devp) || is_swap_partition(devp))
return -EBUSY;
@@ -201,8 +206,9 @@ int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
struct gendisk *g;
u64 ullval = 0;
int intval, *iptr;
+ unsigned short usval;
- if (!dev)
+ if (kdev_none(dev))
return -EINVAL;
intval = block_ioctl(dev, cmd, arg);
@@ -226,30 +232,33 @@ int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
return -EACCES;
if(arg > 0xff)
return -EINVAL;
- read_ahead[MAJOR(dev)] = arg;
+ read_ahead[major(dev)] = arg;
return 0;
case BLKRAGET:
if (!arg)
return -EINVAL;
- return put_user(read_ahead[MAJOR(dev)], (long *) arg);
+ return put_user(read_ahead[major(dev)], (long *) arg);
case BLKFRASET:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (!(iptr = max_readahead[MAJOR(dev)]))
+ if (!(iptr = max_readahead[major(dev)]))
return -EINVAL;
- iptr[MINOR(dev)] = arg;
+ iptr[minor(dev)] = arg;
return 0;
case BLKFRAGET:
- if (!(iptr = max_readahead[MAJOR(dev)]))
+ if (!(iptr = max_readahead[major(dev)]))
return -EINVAL;
- return put_user(iptr[MINOR(dev)], (long *) arg);
+ return put_user(iptr[minor(dev)], (long *) arg);
case BLKSECTGET:
- if ((q = blk_get_queue(dev)))
- return put_user(q->max_sectors, (unsigned short *)arg);
- return -EINVAL;
+ if ((q = blk_get_queue(dev)) == NULL)
+ return -EINVAL;
+
+ usval = q->max_sectors;
+ blk_put_queue(q);
+ return put_user(usval, (unsigned short *)arg);
case BLKFLSBUF:
if (!capable(CAP_SYS_ADMIN))
@@ -267,7 +276,7 @@ int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
case BLKGETSIZE64:
g = get_gendisk(dev);
if (g)
- ullval = g->part[MINOR(dev)].nr_sects;
+ ullval = g->part[minor(dev)].nr_sects;
if (cmd == BLKGETSIZE)
return put_user((unsigned long)ullval, (unsigned long *)arg);
@@ -291,9 +300,7 @@ int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
case BLKBSZGET:
/* get the logical block size (cf. BLKSSZGET) */
- intval = BLOCK_SIZE;
- if (blksize_size[MAJOR(dev)])
- intval = blksize_size[MAJOR(dev)][MINOR(dev)];
+ intval = block_size(dev);
return put_user(intval, (int *) arg);
case BLKBSZSET:
diff --git a/drivers/block/block_ioctl.c b/drivers/block/block_ioctl.c
index c9c57e882..e206157da 100644
--- a/drivers/block/block_ioctl.c
+++ b/drivers/block/block_ioctl.c
@@ -76,9 +76,7 @@ int block_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
err = -ENOTTY;
}
-#if 0
blk_put_queue(q);
-#endif
return err;
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index b038dde8b..e2792736f 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -317,8 +317,8 @@ static void cciss_geninit( int ctlr)
*/
static int cciss_open(struct inode *inode, struct file *filep)
{
- int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
- int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT;
+ int ctlr = major(inode->i_rdev) - MAJOR_NR;
+ int dsk = minor(inode->i_rdev) >> NWD_SHIFT;
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk);
@@ -327,7 +327,7 @@ static int cciss_open(struct inode *inode, struct file *filep)
if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
return -ENXIO;
- if (!suser() && hba[ctlr]->sizes[ MINOR(inode->i_rdev)] == 0)
+ if (!suser() && hba[ctlr]->sizes[minor(inode->i_rdev)] == 0)
return -ENXIO;
/*
@@ -337,8 +337,8 @@ static int cciss_open(struct inode *inode, struct file *filep)
* for "raw controller".
*/
if (suser()
- && (hba[ctlr]->sizes[MINOR(inode->i_rdev)] == 0)
- && (MINOR(inode->i_rdev)!= 0))
+ && (hba[ctlr]->sizes[minor(inode->i_rdev)] == 0)
+ && (minor(inode->i_rdev)!= 0))
return -ENXIO;
hba[ctlr]->drv[dsk].usage_count++;
@@ -350,8 +350,8 @@ static int cciss_open(struct inode *inode, struct file *filep)
*/
static int cciss_release(struct inode *inode, struct file *filep)
{
- int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
- int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT;
+ int ctlr = major(inode->i_rdev) - MAJOR_NR;
+ int dsk = minor(inode->i_rdev) >> NWD_SHIFT;
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk);
@@ -370,8 +370,8 @@ static int cciss_release(struct inode *inode, struct file *filep)
static int cciss_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg)
{
- int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
- int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT;
+ int ctlr = major(inode->i_rdev) - MAJOR_NR;
+ int dsk = minor(inode->i_rdev) >> NWD_SHIFT;
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg);
@@ -696,8 +696,8 @@ static int revalidate_logvol(kdev_t dev, int maxusage)
unsigned long flags;
int res;
- target = MINOR(dev) >> NWD_SHIFT;
- ctlr = MAJOR(dev) - MAJOR_NR;
+ target = minor(dev) >> NWD_SHIFT;
+ ctlr = major(dev) - MAJOR_NR;
gdev = &(hba[ctlr]->gendisk);
spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
@@ -746,8 +746,8 @@ static int revalidate_allvol(kdev_t dev)
int ctlr, i;
unsigned long flags;
- ctlr = MAJOR(dev) - MAJOR_NR;
- if (MINOR(dev) != 0)
+ ctlr = major(dev) - MAJOR_NR;
+ if (minor(dev) != 0)
return -ENXIO;
spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
@@ -781,9 +781,11 @@ static int revalidate_allvol(kdev_t dev)
hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_ON);
cciss_geninit(ctlr);
- for(i=0; i<NWD; i++)
+ for(i=0; i<NWD; i++) {
+ kdev_t kdev = mk_kdev(major(dev), i << NWD_SHIFT);
if (hba[ctlr]->sizes[ i<<NWD_SHIFT ])
- revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
+ revalidate_logvol(kdev, 2);
+ }
hba[ctlr]->usage_count--;
return 0;
@@ -1205,7 +1207,6 @@ static void do_cciss_request(request_queue_t *q)
ctlr_info_t *h= q->queuedata;
CommandList_struct *c;
int log_unit, start_blk, seg;
- struct list_head *queue_head = &q->queue_head;
struct request *creq;
u64bit temp64;
struct scatterlist tmp_sg[MAXSGENTRIES];
@@ -1215,17 +1216,17 @@ static void do_cciss_request(request_queue_t *q)
goto startio;
queue:
- if (list_empty(queue_head))
+ if (blk_queue_empty(q))
goto startio;
creq = elv_next_request(q);
if (creq->nr_phys_segments > MAXSGENTRIES)
BUG();
- if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR )
+ if (h->ctlr != major(creq->rq_dev)-MAJOR_NR )
{
printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
- h->ctlr, creq->rq_dev, creq);
+ h->ctlr, major(creq->rq_dev), creq);
blkdev_dequeue_request(creq);
complete_buffers(creq->bio, 0);
end_that_request_last(creq);
@@ -1243,7 +1244,7 @@ queue:
c->rq = creq;
/* fill in the request */
- log_unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
+ log_unit = minor(creq->rq_dev) >> NWD_SHIFT;
c->Header.ReplyQueue = 0; // unused in simple mode
c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag
c->Header.LUN.LogDev.VolId= hba[h->ctlr]->drv[log_unit].LunID;
@@ -1886,7 +1887,6 @@ static int __init cciss_init_one(struct pci_dev *pdev,
hba[i]->gendisk.major = MAJOR_NR + i;
hba[i]->gendisk.major_name = "cciss";
hba[i]->gendisk.minor_shift = NWD_SHIFT;
- hba[i]->gendisk.max_p = MAX_PART;
hba[i]->gendisk.part = hba[i]->hd;
hba[i]->gendisk.sizes = hba[i]->sizes;
hba[i]->gendisk.nr_real = hba[i]->num_luns;
@@ -1897,7 +1897,7 @@ static int __init cciss_init_one(struct pci_dev *pdev,
cciss_geninit(i);
for(j=0; j<NWD; j++)
register_disk(&(hba[i]->gendisk),
- MKDEV(MAJOR_NR+i, j <<4),
+ mk_kdev(MAJOR_NR+i, j <<4),
MAX_PART, &cciss_fops,
hba[i]->drv[j].nr_blocks);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 03afe43da..1dafe1ec5 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -8,7 +8,7 @@
#define NWD 16
#define NWD_SHIFT 4
-#define MAX_PART 16
+#define MAX_PART (1 << NWD_SHIFT)
#define IO_OK 0
#define IO_ERROR 1
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index 544b047c5..7faf6f05c 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -7,7 +7,7 @@
//general boundary defintions
#define SENSEINFOBYTES 32//note that this value may vary between host implementations
-#define MAXSGENTRIES 32
+#define MAXSGENTRIES 31
#define MAXREPLYQS 256
//Command Status value
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 5f2298ba9..6a92fa4f5 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -483,7 +483,6 @@ int __init cpqarray_init(void)
ida_gendisk[i].major = MAJOR_NR + i;
ida_gendisk[i].major_name = "ida";
ida_gendisk[i].minor_shift = NWD_SHIFT;
- ida_gendisk[i].max_p = 16;
ida_gendisk[i].part = ida + (i*256);
ida_gendisk[i].sizes = ida_sizes + (i*256);
ida_gendisk[i].nr_real = 0;
@@ -500,7 +499,7 @@ int __init cpqarray_init(void)
ida_geninit(i);
for(j=0; j<NWD; j++)
register_disk(&ida_gendisk[i],
- MKDEV(MAJOR_NR+i,j<<4),
+ mk_kdev(MAJOR_NR+i,j<<4),
16, &ida_fops, hba[i]->drv[j].nr_blks);
}
@@ -777,15 +776,15 @@ DBGINFO(
*/
static int ida_open(struct inode *inode, struct file *filep)
{
- int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
- int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT;
+ int ctlr = major(inode->i_rdev) - MAJOR_NR;
+ int dsk = minor(inode->i_rdev) >> NWD_SHIFT;
DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
return -ENXIO;
if (!suser() && ida_sizes[(ctlr << CTLR_SHIFT) +
- MINOR(inode->i_rdev)] == 0)
+ minor(inode->i_rdev)] == 0)
return -ENXIO;
/*
@@ -795,8 +794,8 @@ static int ida_open(struct inode *inode, struct file *filep)
* for "raw controller".
*/
if (suser()
- && ida_sizes[(ctlr << CTLR_SHIFT) + MINOR(inode->i_rdev)] == 0
- && MINOR(inode->i_rdev) != 0)
+ && ida_sizes[(ctlr << CTLR_SHIFT) + minor(inode->i_rdev)] == 0
+ && minor(inode->i_rdev) != 0)
return -ENXIO;
hba[ctlr]->drv[dsk].usage_count++;
@@ -809,8 +808,8 @@ static int ida_open(struct inode *inode, struct file *filep)
*/
static int ida_release(struct inode *inode, struct file *filep)
{
- int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
- int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT;
+ int ctlr = major(inode->i_rdev) - MAJOR_NR;
+ int dsk = minor(inode->i_rdev) >> NWD_SHIFT;
DBGINFO(printk("ida_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
@@ -858,7 +857,6 @@ static void do_ida_request(request_queue_t *q)
{
ctlr_info_t *h = q->queuedata;
cmdlist_t *c;
- struct list_head * queue_head = &q->queue_head;
struct request *creq;
struct scatterlist tmp_sg[SG_MAX];
int i, dir, seg;
@@ -867,17 +865,17 @@ static void do_ida_request(request_queue_t *q)
goto startio;
queue_next:
- if (list_empty(queue_head))
+ if (blk_queue_empty(q))
goto startio;
creq = elv_next_request(q);
if (creq->nr_phys_segments > SG_MAX)
BUG();
- if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
+ if (h->ctlr != major(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
{
printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
- h->ctlr, creq->rq_dev, creq);
+ h->ctlr, minor(creq->rq_dev), creq);
blkdev_dequeue_request(creq);
complete_buffers(creq->bio, 0);
end_that_request_last(creq);
@@ -892,7 +890,7 @@ queue_next:
spin_unlock_irq(q->queue_lock);
c->ctlr = h->ctlr;
- c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
+ c->hdr.unit = minor(creq->rq_dev) >> NWD_SHIFT;
c->hdr.size = sizeof(rblk_t) >> 2;
c->size += sizeof(rblk_t);
@@ -1110,8 +1108,8 @@ static void ida_timer(unsigned long tdata)
*/
static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
{
- int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
- int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT;
+ int ctlr = major(inode->i_rdev) - MAJOR_NR;
+ int dsk = minor(inode->i_rdev) >> NWD_SHIFT;
int error;
int diskinfo[4];
struct hd_geometry *geo = (struct hd_geometry *)arg;
@@ -1493,8 +1491,8 @@ static int revalidate_allvol(kdev_t dev)
int ctlr, i;
unsigned long flags;
- ctlr = MAJOR(dev) - MAJOR_NR;
- if (MINOR(dev) != 0)
+ ctlr = major(dev) - MAJOR_NR;
+ if (minor(dev) != 0)
return -ENXIO;
spin_lock_irqsave(IDA_LOCK(ctlr), flags);
@@ -1527,9 +1525,11 @@ static int revalidate_allvol(kdev_t dev)
hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY);
ida_geninit(ctlr);
- for(i=0; i<NWD; i++)
+ for(i=0; i<NWD; i++) {
+ kdev_t kdev = mk_kdev(major(dev), i << NWD_SHIFT);
if (ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)])
- revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
+ revalidate_logvol(kdev, 2);
+ }
hba[ctlr]->usage_count--;
return 0;
@@ -1544,7 +1544,7 @@ static int revalidate_logvol(kdev_t dev, int maxusage)
int res;
target = DEVICE_NR(dev);
- ctlr = MAJOR(dev) - MAJOR_NR;
+ ctlr = major(dev) - MAJOR_NR;
gdev = &ida_gendisk[ctlr];
spin_lock_irqsave(IDA_LOCK(ctlr), flags);
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 2dfeae410..8fcdc77fa 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -70,7 +70,7 @@ inline int bio_rq_in_between(struct bio *bio, struct request *rq,
* if the device is different (not a normal case) just check if
* bio is after rq
*/
- if (next_rq->rq_dev != rq->rq_dev)
+ if (!kdev_same(next_rq->rq_dev, rq->rq_dev))
return bio->bi_sector > rq->sector;
/*
@@ -101,7 +101,7 @@ inline int bio_rq_in_between(struct bio *bio, struct request *rq,
*/
inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
{
- if (!(rq->flags & REQ_CMD))
+ if (!rq_mergeable(rq))
return 0;
/*
@@ -109,13 +109,11 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
*/
if (bio_data_dir(bio) != rq_data_dir(rq))
return 0;
- if (rq->flags & REQ_NOMERGE)
- return 0;
/*
* same device and no special stuff set, merge is ok
*/
- if (rq->rq_dev == bio->bi_dev && !rq->waiting && !rq->special)
+ if (kdev_same(rq->rq_dev, bio->bi_dev) && !rq->waiting && !rq->special)
return 1;
return 0;
@@ -123,66 +121,78 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
inline int elv_try_merge(struct request *__rq, struct bio *bio)
{
- unsigned int count = bio_sectors(bio);
-
- if (!elv_rq_merge_ok(__rq, bio))
- return ELEVATOR_NO_MERGE;
+ int ret = ELEVATOR_NO_MERGE;
/*
* we can merge and sequence is ok, check if it's possible
*/
- if (__rq->sector + __rq->nr_sectors == bio->bi_sector) {
- return ELEVATOR_BACK_MERGE;
- } else if (__rq->sector - count == bio->bi_sector) {
- __rq->elevator_sequence -= count;
- return ELEVATOR_FRONT_MERGE;
+ if (elv_rq_merge_ok(__rq, bio)) {
+ if (__rq->sector + __rq->nr_sectors == bio->bi_sector)
+ ret = ELEVATOR_BACK_MERGE;
+ else if (__rq->sector - bio_sectors(bio) == bio->bi_sector)
+ ret = ELEVATOR_FRONT_MERGE;
}
- return ELEVATOR_NO_MERGE;
+ return ret;
}
-int elevator_linus_merge(request_queue_t *q, struct request **req,
- struct bio *bio)
+inline int elv_try_last_merge(request_queue_t *q, struct request **req,
+ struct bio *bio)
{
- struct list_head *entry;
- struct request *__rq;
- int ret;
+ int ret = ELEVATOR_NO_MERGE;
/*
* give a one-shot try to merging with the last touched
* request
*/
if (q->last_merge) {
- __rq = list_entry_rq(q->last_merge);
+ struct request *__rq = list_entry_rq(q->last_merge);
BUG_ON(__rq->flags & REQ_STARTED);
- if ((ret = elv_try_merge(__rq, bio))) {
+ if ((ret = elv_try_merge(__rq, bio)))
*req = __rq;
- return ret;
- }
}
+ return ret;
+}
+
+/*
+ * elevator_linux starts here
+ */
+int elevator_linus_merge(request_queue_t *q, struct request **req,
+ struct bio *bio)
+{
+ struct list_head *entry;
+ struct request *__rq;
+ int ret;
+
+ if ((ret = elv_try_last_merge(q, req, bio)))
+ return ret;
+
entry = &q->queue_head;
ret = ELEVATOR_NO_MERGE;
while ((entry = entry->prev) != &q->queue_head) {
__rq = list_entry_rq(entry);
+ if (__rq->flags & (REQ_BARRIER | REQ_STARTED))
+ break;
+
/*
* simply "aging" of requests in queue
*/
- if (__rq->elevator_sequence-- <= 0)
- break;
- if (__rq->flags & (REQ_BARRIER | REQ_STARTED))
+ if (elv_linus_sequence(__rq)-- <= 0)
break;
if (!(__rq->flags & REQ_CMD))
continue;
- if (__rq->elevator_sequence < 0)
+ if (elv_linus_sequence(__rq) < bio_sectors(bio))
break;
if (!*req && bio_rq_in_between(bio, __rq, &q->queue_head))
*req = __rq;
if ((ret = elv_try_merge(__rq, bio))) {
+ if (ret == ELEVATOR_FRONT_MERGE)
+ elv_linus_sequence(__rq) -= bio_sectors(bio);
*req = __rq;
q->last_merge = &__rq->queuelist;
break;
@@ -205,19 +215,27 @@ void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int c
while ((entry = entry->next) != &q->queue_head) {
struct request *tmp;
tmp = list_entry_rq(entry);
- tmp->elevator_sequence -= count;
+ elv_linus_sequence(tmp) -= count;
}
}
void elevator_linus_merge_req(struct request *req, struct request *next)
{
- if (next->elevator_sequence < req->elevator_sequence)
- req->elevator_sequence = next->elevator_sequence;
+ if (elv_linus_sequence(next) < elv_linus_sequence(req))
+ elv_linus_sequence(req) = elv_linus_sequence(next);
}
-void elv_add_request_fn(request_queue_t *q, struct request *rq,
- struct list_head *insert_here)
+void elevator_linus_add_request(request_queue_t *q, struct request *rq,
+ struct list_head *insert_here)
{
+ elevator_t *e = &q->elevator;
+ int lat = 0, *latency = e->elevator_data;
+
+ if (!(rq->flags & REQ_BARRIER))
+ lat = latency[rq_data_dir(rq)];
+
+ elv_linus_sequence(rq) = lat;
+
list_add(&rq->queuelist, insert_here);
/*
@@ -229,24 +247,29 @@ void elv_add_request_fn(request_queue_t *q, struct request *rq,
q->last_merge = &rq->queuelist;
}
-struct request *elv_next_request_fn(request_queue_t *q)
+int elevator_linus_init(request_queue_t *q, elevator_t *e)
{
- if (!blk_queue_empty(q))
- return list_entry_rq(q->queue_head.next);
+ int *latency;
- return NULL;
-}
+ latency = kmalloc(2 * sizeof(int), GFP_KERNEL);
+ if (!latency)
+ return -ENOMEM;
-int elv_linus_init(request_queue_t *q, elevator_t *e)
-{
+ latency[READ] = 8192;
+ latency[WRITE] = 16384;
+
+ e->elevator_data = latency;
return 0;
}
-void elv_linus_exit(request_queue_t *q, elevator_t *e)
+void elevator_linus_exit(request_queue_t *q, elevator_t *e)
{
+ kfree(e->elevator_data);
}
/*
+ * elevator noop
+ *
* See if we can find a request that this buffer can be coalesced with.
*/
int elevator_noop_merge(request_queue_t *q, struct request **req,
@@ -256,15 +279,8 @@ int elevator_noop_merge(request_queue_t *q, struct request **req,
struct request *__rq;
int ret;
- if (q->last_merge) {
- __rq = list_entry_rq(q->last_merge);
- BUG_ON(__rq->flags & REQ_STARTED);
-
- if ((ret = elv_try_merge(__rq, bio))) {
- *req = __rq;
- return ret;
- }
- }
+ if ((ret = elv_try_last_merge(q, req, bio)))
+ return ret;
while ((entry = entry->prev) != &q->queue_head) {
__rq = list_entry_rq(entry);
@@ -285,10 +301,31 @@ int elevator_noop_merge(request_queue_t *q, struct request **req,
return ELEVATOR_NO_MERGE;
}
-void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {}
+void elevator_noop_add_request(request_queue_t *q, struct request *rq,
+ struct list_head *insert_here)
+{
+ list_add_tail(&rq->queuelist, &q->queue_head);
+
+ /*
+ * new merges must not precede this barrier
+ */
+ if (rq->flags & REQ_BARRIER)
+ q->last_merge = NULL;
+ else if (!q->last_merge)
+ q->last_merge = &rq->queuelist;
+}
+
+struct request *elevator_noop_next_request(request_queue_t *q)
+{
+ if (!blk_queue_empty(q))
+ return list_entry_rq(q->queue_head.next);
-void elevator_noop_merge_req(struct request *req, struct request *next) {}
+ return NULL;
+}
+/*
+ * general block -> elevator interface starts here
+ */
int elevator_init(request_queue_t *q, elevator_t *e, elevator_t type)
{
*e = type;
@@ -313,4 +350,77 @@ int elevator_global_init(void)
return 0;
}
+void elv_merge_cleanup(request_queue_t *q, struct request *rq,
+ int nr_sectors)
+{
+ elevator_t *e = &q->elevator;
+
+ if (e->elevator_merge_cleanup_fn)
+ e->elevator_merge_cleanup_fn(q, rq, nr_sectors);
+}
+
+int elv_merge(request_queue_t *q, struct request **rq, struct bio *bio)
+{
+ elevator_t *e = &q->elevator;
+
+ if (e->elevator_merge_fn)
+ return e->elevator_merge_fn(q, rq, bio);
+
+ return ELEVATOR_NO_MERGE;
+}
+
+void elv_merge_requests(request_queue_t *q, struct request *rq,
+ struct request *next)
+{
+ elevator_t *e = &q->elevator;
+
+ if (e->elevator_merge_req_fn)
+ e->elevator_merge_req_fn(rq, next);
+}
+
+/*
+ * add_request and next_request are required to be supported, naturally
+ */
+void __elv_add_request(request_queue_t *q, struct request *rq,
+ struct list_head *insert_here)
+{
+ q->elevator.elevator_add_req_fn(q, rq, insert_here);
+}
+
+struct request *__elv_next_request(request_queue_t *q)
+{
+ return q->elevator.elevator_next_req_fn(q);
+}
+
+void elv_remove_request(request_queue_t *q, struct request *rq)
+{
+ elevator_t *e = &q->elevator;
+
+ if (e->elevator_remove_req_fn)
+ e->elevator_remove_req_fn(q, rq);
+}
+
+elevator_t elevator_linus = {
+ elevator_merge_fn: elevator_linus_merge,
+ elevator_merge_cleanup_fn: elevator_linus_merge_cleanup,
+ elevator_merge_req_fn: elevator_linus_merge_req,
+ elevator_next_req_fn: elevator_noop_next_request,
+ elevator_add_req_fn: elevator_linus_add_request,
+ elevator_init_fn: elevator_linus_init,
+ elevator_exit_fn: elevator_linus_exit,
+};
+
+elevator_t elevator_noop = {
+ elevator_merge_fn: elevator_noop_merge,
+ elevator_next_req_fn: elevator_noop_next_request,
+ elevator_add_req_fn: elevator_noop_add_request,
+};
+
module_init(elevator_global_init);
+
+EXPORT_SYMBOL(elevator_linus);
+EXPORT_SYMBOL(elevator_noop);
+
+EXPORT_SYMBOL(__elv_add_request);
+EXPORT_SYMBOL(__elv_next_request);
+EXPORT_SYMBOL(elv_remove_request);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 2fcdcc59a..641b6868a 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -270,10 +270,10 @@ static unsigned long fake_change;
static int initialising=1;
static inline int TYPE(kdev_t x) {
- return (MINOR(x)>>2) & 0x1f;
+ return (minor(x)>>2) & 0x1f;
}
static inline int DRIVE(kdev_t x) {
- return (MINOR(x)&0x03) | ((MINOR(x)&0x80) >> 5);
+ return (minor(x)&0x03) | ((minor(x)&0x80) >> 5);
}
#define ITYPE(x) (((x)>>2) & 0x1f)
#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
@@ -2906,7 +2906,7 @@ static void redo_fd_request(void)
unlock_fdc();
return;
}
- if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
+ if (major(CURRENT->rq_dev) != MAJOR_NR)
panic(DEVICE_NAME ": request list destroyed");
device = CURRENT->rq_dev;
@@ -3332,7 +3332,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
if (ITYPE(drive_state[cnt].fd_device) == type &&
drive_state[cnt].fd_ref)
check_disk_change(
- MKDEV(FLOPPY_MAJOR,
+ mk_kdev(FLOPPY_MAJOR,
drive_state[cnt].fd_device));
}
} else {
@@ -3717,7 +3717,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
if (TYPE(inode->i_rdev) >= NUMBER(floppy_type))
return -ENXIO;
old_dev = UDRS->fd_device;
- if (UDRS->fd_ref && old_dev != MINOR(inode->i_rdev))
+ if (UDRS->fd_ref && old_dev != minor(inode->i_rdev))
return -EBUSY;
if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
@@ -3768,11 +3768,11 @@ static int floppy_open(struct inode * inode, struct file * filp)
}
}
- UDRS->fd_device = MINOR(inode->i_rdev);
- if (old_dev != -1 && old_dev != MINOR(inode->i_rdev)) {
+ UDRS->fd_device = minor(inode->i_rdev);
+ if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
if (buffer_drive == drive)
buffer_track = -1;
- invalidate_buffers(MKDEV(FLOPPY_MAJOR,old_dev));
+ invalidate_buffers(mk_kdev(FLOPPY_MAJOR,old_dev));
}
/* Allow ioctls if we have write-permissions even if read-only open.
@@ -3806,7 +3806,7 @@ static int check_floppy_change(kdev_t dev)
{
int drive = DRIVE(dev);
- if (MAJOR(dev) != MAJOR_NR) {
+ if (major(dev) != MAJOR_NR) {
DPRINT("check_floppy_change: not a floppy\n");
return 0;
}
@@ -3868,7 +3868,7 @@ static int floppy_revalidate(kdev_t dev)
UDRS->generation++;
if (NO_GEOM){
/* auto-sensing */
- int size = floppy_blocksizes[MINOR(dev)];
+ int size = floppy_blocksizes[minor(dev)];
if (!size)
size = 1024;
if (!(bh = getblk(dev,0,size))){
@@ -4275,7 +4275,7 @@ int __init floppy_init(void)
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue;
for (i = 0; i<NUMBER(floppy_type); i++)
- register_disk(NULL, MKDEV(MAJOR_NR,TOMINOR(drive)+i*4),
+ register_disk(NULL, mk_kdev(MAJOR_NR,TOMINOR(drive)+i*4),
1, &floppy_fops, 0);
}
return have_no_fdc;
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 2ecc7c6d3..bf0cec7f6 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -103,7 +103,7 @@ struct gendisk *
get_gendisk(kdev_t dev)
{
struct gendisk *gp = NULL;
- int maj = MAJOR(dev);
+ int maj = major(dev);
read_lock(&gendisk_lock);
for (gp = gendisk_head; gp; gp = gp->next)
@@ -124,7 +124,7 @@ get_start_sect(kdev_t dev)
gp = get_gendisk(dev);
if (gp)
- return gp->part[MINOR(dev)].start_sect;
+ return gp->part[minor(dev)].start_sect;
return 0;
}
@@ -137,7 +137,7 @@ get_nr_sects(kdev_t dev)
gp = get_gendisk(dev);
if (gp)
- return gp->part[MINOR(dev)].nr_sects;
+ return gp->part[minor(dev)].nr_sects;
return 0;
}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 6112b5b52..f98c41e49 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -109,12 +109,12 @@ int blk_nohighio = 0;
**/
inline request_queue_t *blk_get_queue(kdev_t dev)
{
- struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
+ struct blk_dev_struct *bdev = blk_dev + major(dev);
if (bdev->queue)
return bdev->queue(dev);
else
- return &blk_dev[MAJOR(dev)].request_queue;
+ return &blk_dev[major(dev)].request_queue;
}
void blk_queue_prep_rq(request_queue_t *q, prep_rq_fn *pfn)
@@ -155,6 +155,11 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
blk_queue_max_sectors(q, MAX_SECTORS);
blk_queue_hardsect_size(q, 512);
+ /*
+ * by default assume old behaviour and bounce for any highmem page
+ */
+ blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
+
init_waitqueue_head(&q->queue_wait);
}
@@ -304,7 +309,7 @@ void blk_dump_rq_flags(struct request *rq, char *msg)
{
int bit;
- printk("%s: dev %x: ", msg, rq->rq_dev);
+ printk("%s: dev %02x:%02x: ", msg, major(rq->rq_dev), minor(rq->rq_dev));
bit = 0;
do {
if (rq->flags & (1 << bit))
@@ -481,7 +486,7 @@ int blk_rq_map_sg(request_queue_t *q, struct request *rq, struct scatterlist *sg
sg[nsegs - 1].length += nbytes;
} else {
new_segment:
- memset(&sg[nsegs], 0, sizeof(struct scatterlist));
+ memset(&sg[nsegs],0,sizeof(struct scatterlist));
sg[nsegs].page = bvec->bv_page;
sg[nsegs].length = nbytes;
sg[nsegs].offset = bvec->bv_offset;
@@ -508,6 +513,7 @@ static inline int ll_new_mergeable(request_queue_t *q,
if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
req->flags |= REQ_NOMERGE;
+ q->last_merge = NULL;
return 0;
}
@@ -524,9 +530,12 @@ static inline int ll_new_hw_segment(request_queue_t *q,
struct bio *bio)
{
int nr_hw_segs = bio_hw_segments(q, bio);
+ int nr_phys_segs = bio_phys_segments(q, bio);
- if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments) {
+ if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments
+ || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
req->flags |= REQ_NOMERGE;
+ q->last_merge = NULL;
return 0;
}
@@ -535,7 +544,7 @@ static inline int ll_new_hw_segment(request_queue_t *q,
* counters.
*/
req->nr_hw_segments += nr_hw_segs;
- req->nr_phys_segments += bio_phys_segments(q, bio);
+ req->nr_phys_segments += nr_phys_segs;
return 1;
}
@@ -603,9 +612,6 @@ static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
return 0;
/* Merge is OK... */
- if (q->last_merge == &next->queuelist)
- q->last_merge = NULL;
-
req->nr_phys_segments = total_phys_segments;
req->nr_hw_segments = total_hw_segments;
return 1;
@@ -797,7 +803,7 @@ int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
if (blk_init_free_list(q))
return -ENOMEM;
- if ((ret = elevator_init(q, &q->elevator, ELEVATOR_LINUS))) {
+ if ((ret = elevator_init(q, &q->elevator, elevator_linus))) {
blk_cleanup_queue(q);
return ret;
}
@@ -812,16 +818,15 @@ int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
q->plug_tq.data = q;
q->queue_flags = (1 << QUEUE_FLAG_CLUSTER);
q->queue_lock = lock;
+ q->last_merge = NULL;
- /*
- * by default assume old behaviour and bounce for any highmem page
- */
- blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
-
blk_queue_segment_boundary(q, 0xffffffff);
blk_queue_make_request(q, __make_request);
blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
+
+ blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
+ blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
return 0;
}
@@ -881,11 +886,19 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
BUG_ON(rw != READ && rw != WRITE);
+ spin_lock_irq(q->queue_lock);
rq = get_request(q, rw);
+ spin_unlock_irq(q->queue_lock);
if (!rq && (gfp_mask & __GFP_WAIT))
rq = get_request_wait(q, rw);
+ if (rq) {
+ rq->flags = 0;
+ rq->buffer = NULL;
+ rq->bio = rq->biotail = NULL;
+ rq->waiting = NULL;
+ }
return rq;
}
@@ -902,8 +915,8 @@ int is_read_only(kdev_t dev)
{
int minor,major;
- major = MAJOR(dev);
- minor = MINOR(dev);
+ major = major(dev);
+ minor = minor(dev);
if (major < 0 || major >= MAX_BLKDEV) return 0;
return ro_bits[major][minor >> 5] & (1 << (minor & 31));
}
@@ -912,8 +925,8 @@ void set_device_ro(kdev_t dev,int flag)
{
int minor,major;
- major = MAJOR(dev);
- minor = MINOR(dev);
+ major = major(dev);
+ minor = minor(dev);
if (major < 0 || major >= MAX_BLKDEV) return;
if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31);
else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
@@ -921,7 +934,7 @@ void set_device_ro(kdev_t dev,int flag)
void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
{
- unsigned int major = MAJOR(rq->rq_dev);
+ unsigned int major = major(rq->rq_dev);
int rw = rq_data_dir(rq);
unsigned int index;
@@ -951,19 +964,16 @@ static inline void add_request(request_queue_t * q, struct request * req,
drive_stat_acct(req, req->nr_sectors, 1);
/*
- * debug stuff...
+ * it's a bug to let this rq preempt an already started request
*/
- if (insert_here == &q->queue_head) {
- struct request *__rq = __elv_next_request(q);
-
- BUG_ON(__rq && (__rq->flags & REQ_STARTED));
- }
+ if (insert_here->next != &q->queue_head)
+ BUG_ON(list_entry_rq(insert_here->next)->flags & REQ_STARTED);
/*
* elevator indicated where it wants this request to be
* inserted at elevator_merge time
*/
- q->elevator.elevator_add_req_fn(q, req, insert_here);
+ __elv_add_request(q, req, insert_here);
}
/*
@@ -972,11 +982,17 @@ static inline void add_request(request_queue_t * q, struct request * req,
void blkdev_release_request(struct request *req)
{
struct request_list *rl = req->rl;
+ request_queue_t *q = req->q;
req->rq_status = RQ_INACTIVE;
req->q = NULL;
req->rl = NULL;
+ if (q) {
+ if (q->last_merge == &req->queuelist)
+ q->last_merge = NULL;
+ }
+
/*
* Request may not have originated from ll_rw_blk. if not,
* it didn't come out of our reserved rq pools
@@ -992,14 +1008,10 @@ void blkdev_release_request(struct request *req)
/*
* Has to be called with the request spinlock acquired
*/
-static void attempt_merge(request_queue_t *q, struct request *req)
+static void attempt_merge(request_queue_t *q, struct request *req,
+ struct request *next)
{
- struct request *next = blkdev_next_request(req);
-
- /*
- * not a rw command
- */
- if (!(next->flags & REQ_CMD))
+ if (!rq_mergeable(req) || !rq_mergeable(next))
return;
/*
@@ -1008,26 +1020,20 @@ static void attempt_merge(request_queue_t *q, struct request *req)
if (req->sector + req->nr_sectors != next->sector)
return;
- /*
- * don't touch NOMERGE rq, or one that has been started by driver
- */
- if (next->flags & (REQ_NOMERGE | REQ_STARTED))
- return;
-
if (rq_data_dir(req) != rq_data_dir(next)
- || req->rq_dev != next->rq_dev
+ || !kdev_same(req->rq_dev, next->rq_dev)
|| req->nr_sectors + next->nr_sectors > q->max_sectors
|| next->waiting || next->special)
return;
/*
- * If we are not allowed to merge these requests, then
- * return. If we are allowed to merge, then the count
- * will have been updated to the appropriate number,
- * and we shouldn't do it here too.
+ * If we are allowed to merge, then append bio list
+ * from next to rq and release next. merge_requests_fn
+ * will have updated segment counts, update sector
+ * counts here.
*/
if (q->merge_requests_fn(q, req, next)) {
- q->elevator.elevator_merge_req_fn(req, next);
+ elv_merge_requests(q, req, next);
blkdev_dequeue_request(next);
@@ -1042,8 +1048,10 @@ static void attempt_merge(request_queue_t *q, struct request *req)
static inline void attempt_back_merge(request_queue_t *q, struct request *rq)
{
- if (&rq->queuelist != q->queue_head.prev)
- attempt_merge(q, rq);
+ struct list_head *next = rq->queuelist.next;
+
+ if (next != &q->queue_head)
+ attempt_merge(q, rq, list_entry_rq(next));
}
static inline void attempt_front_merge(request_queue_t *q, struct request *rq)
@@ -1051,13 +1059,7 @@ static inline void attempt_front_merge(request_queue_t *q, struct request *rq)
struct list_head *prev = rq->queuelist.prev;
if (prev != &q->queue_head)
- attempt_merge(q, blkdev_entry_to_request(prev));
-}
-
-static inline void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
-{
- if (rq->queuelist.next != &q->queue_head)
- attempt_merge(q, rq);
+ attempt_merge(q, list_entry_rq(prev), rq);
}
/**
@@ -1078,16 +1080,15 @@ void blk_attempt_remerge(request_queue_t *q, struct request *rq)
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
- __blk_attempt_remerge(q, rq);
+ attempt_back_merge(q, rq);
spin_unlock_irqrestore(q->queue_lock, flags);
}
static int __make_request(request_queue_t *q, struct bio *bio)
{
struct request *req, *freereq = NULL;
- int el_ret, latency = 0, rw, nr_sectors, cur_nr_sectors, barrier;
- struct list_head *insert_here = &q->queue_head;
- elevator_t *elevator = &q->elevator;
+ int el_ret, rw, nr_sectors, cur_nr_sectors, barrier;
+ struct list_head *insert_here;
sector_t sector;
sector = bio->bi_sector;
@@ -1104,29 +1105,26 @@ static int __make_request(request_queue_t *q, struct bio *bio)
spin_lock_prefetch(q->queue_lock);
- latency = elevator_request_latency(elevator, rw);
barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw);
spin_lock_irq(q->queue_lock);
+again:
+ req = NULL;
+ insert_here = q->queue_head.prev;
if (blk_queue_empty(q) || barrier) {
blk_plug_device(q);
goto get_rq;
}
-again:
- req = NULL;
- insert_here = q->queue_head.prev;
-
- el_ret = elevator->elevator_merge_fn(q, &req, bio);
+ el_ret = elv_merge(q, &req, bio);
switch (el_ret) {
case ELEVATOR_BACK_MERGE:
- BUG_ON(req->flags & REQ_STARTED);
- BUG_ON(req->flags & REQ_NOMERGE);
+ BUG_ON(!rq_mergeable(req));
if (!q->back_merge_fn(q, req, bio))
break;
- elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
+ elv_merge_cleanup(q, req, nr_sectors);
req->biotail->bi_next = bio;
req->biotail = bio;
@@ -1136,12 +1134,11 @@ again:
goto out;
case ELEVATOR_FRONT_MERGE:
- BUG_ON(req->flags & REQ_STARTED);
- BUG_ON(req->flags & REQ_NOMERGE);
+ BUG_ON(!rq_mergeable(req));
if (!q->front_merge_fn(q, req, bio))
break;
- elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
+ elv_merge_cleanup(q, req, nr_sectors);
bio->bi_next = req->bio;
req->bio = bio;
@@ -1203,11 +1200,6 @@ get_rq:
}
/*
- * fill up the request-info, and add it to the queue
- */
- req->elevator_sequence = latency;
-
- /*
* first three bits are identical in rq->flags and bio->bi_rw,
* see bio.h and blkdev.h
*/
@@ -1251,14 +1243,14 @@ static inline void blk_partition_remap(struct bio *bio)
struct gendisk *g;
kdev_t dev0;
- major = MAJOR(bio->bi_dev);
+ major = major(bio->bi_dev);
if ((g = get_gendisk(bio->bi_dev))) {
- minor = MINOR(bio->bi_dev);
+ minor = minor(bio->bi_dev);
drive = (minor >> g->minor_shift);
minor0 = (drive << g->minor_shift); /* whole disk device */
/* that is, minor0 = (minor & ~((1<<g->minor_shift)-1)); */
- dev0 = MKDEV(major, minor0);
- if (dev0 != bio->bi_dev) {
+ dev0 = mk_kdev(major, minor0);
+ if (!kdev_same(dev0, bio->bi_dev)) {
bio->bi_dev = dev0;
bio->bi_sector += g->part[minor].start_sect;
}
@@ -1293,11 +1285,11 @@ static inline void blk_partition_remap(struct bio *bio)
* */
void generic_make_request(struct bio *bio)
{
- int major = MAJOR(bio->bi_dev);
- int minor = MINOR(bio->bi_dev);
+ int major = major(bio->bi_dev);
+ int minor = minor(bio->bi_dev);
request_queue_t *q;
sector_t minorsize = 0;
- int nr_sectors = bio_sectors(bio);
+ int ret, nr_sectors = bio_sectors(bio);
/* Test device or partition size, when known. */
if (blk_size[major])
@@ -1351,7 +1343,10 @@ end_io:
*/
blk_partition_remap(bio);
- } while (q->make_request_fn(q, bio));
+ ret = q->make_request_fn(q, bio);
+ blk_put_queue(q);
+
+ } while (ret);
}
/*
@@ -1480,7 +1475,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
if (!nr)
return;
- major = MAJOR(bhs[0]->b_dev);
+ major = major(bhs[0]->b_dev);
/* Determine correct block size for this device. */
correct_size = get_hardsect_size(bhs[0]->b_dev);
@@ -1571,21 +1566,23 @@ inline void blk_recalc_rq_segments(struct request *rq)
inline void blk_recalc_rq_sectors(struct request *rq, int nsect)
{
- rq->hard_sector += nsect;
- rq->hard_nr_sectors -= nsect;
- rq->sector = rq->hard_sector;
- rq->nr_sectors = rq->hard_nr_sectors;
+ if (rq->flags & REQ_CMD) {
+ rq->hard_sector += nsect;
+ rq->hard_nr_sectors -= nsect;
+ rq->sector = rq->hard_sector;
+ rq->nr_sectors = rq->hard_nr_sectors;
- rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
- rq->hard_cur_sectors = rq->current_nr_sectors;
+ rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
+ rq->hard_cur_sectors = rq->current_nr_sectors;
- /*
- * if total number of sectors is less than the first segment
- * size, something has gone terribly wrong
- */
- if (rq->nr_sectors < rq->current_nr_sectors) {
- printk("blk: request botched\n");
- rq->nr_sectors = rq->current_nr_sectors;
+ /*
+ * if total number of sectors is less than the first segment
+ * size, something has gone terribly wrong
+ */
+ if (rq->nr_sectors < rq->current_nr_sectors) {
+ printk("blk: request botched\n");
+ rq->nr_sectors = rq->current_nr_sectors;
+ }
}
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index abc402359..2ef6fc465 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -155,8 +155,8 @@ static unsigned long compute_loop_size(struct loop_device *lo, struct dentry * l
{
if (S_ISREG(lo_dentry->d_inode->i_mode))
return (lo_dentry->d_inode->i_size - lo->lo_offset) >> BLOCK_SIZE_BITS;
- if (blk_size[MAJOR(lodev)])
- return blk_size[MAJOR(lodev)][MINOR(lodev)] -
+ if (blk_size[major(lodev)])
+ return blk_size[major(lodev)][minor(lodev)] -
(lo->lo_offset >> BLOCK_SIZE_BITS);
return MAX_DISK_SIZE;
}
@@ -284,14 +284,7 @@ static int lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t
static inline int loop_get_bs(struct loop_device *lo)
{
- int bs = 0;
-
- if (blksize_size[MAJOR(lo->lo_device)])
- bs = blksize_size[MAJOR(lo->lo_device)][MINOR(lo->lo_device)];
- if (!bs)
- bs = BLOCK_SIZE;
-
- return bs;
+ return block_size(lo->lo_device);
}
static inline unsigned long loop_get_iv(struct loop_device *lo,
@@ -386,12 +379,11 @@ static struct bio *loop_get_bio(struct loop_device *lo)
*/
static int loop_end_io_transfer(struct bio *bio, int nr_sectors)
{
- struct loop_device *lo = &loop_dev[MINOR(bio->bi_dev)];
+ struct bio *rbh = bio->bi_private;
+ struct loop_device *lo = &loop_dev[minor(rbh->bi_dev)];
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
if (!uptodate || bio_rw(bio) == WRITE) {
- struct bio *rbh = bio->bi_private;
-
bio_endio(rbh, uptodate, nr_sectors);
if (atomic_dec_and_test(&lo->lo_pending))
up(&lo->lo_bh_mutex);
@@ -436,10 +428,10 @@ static int loop_make_request(request_queue_t *q, struct bio *rbh)
unsigned long IV;
int rw = bio_rw(rbh);
- if (MINOR(rbh->bi_dev) >= max_loop)
+ if (minor(rbh->bi_dev) >= max_loop)
goto out;
- lo = &loop_dev[MINOR(rbh->bi_dev)];
+ lo = &loop_dev[minor(rbh->bi_dev)];
spin_lock_irq(&lo->lo_lock);
if (lo->lo_state != Lo_bound)
goto inactive;
@@ -559,6 +551,8 @@ static int loop_thread(void *data)
atomic_inc(&lo->lo_pending);
spin_unlock_irq(&lo->lo_lock);
+ current->flags |= PF_NOIO;
+
/*
* up sem, we are running
*/
@@ -600,7 +594,6 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, kdev_t dev,
kdev_t lo_device;
int lo_flags = 0;
int error;
- int bs;
MOD_INC_USE_COUNT;
@@ -621,6 +614,10 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, kdev_t dev,
if (S_ISBLK(inode->i_mode)) {
lo_device = inode->i_rdev;
+ if (kdev_same(lo_device, dev)) {
+ error = -EBUSY;
+ goto out;
+ }
} else if (S_ISREG(inode->i_mode)) {
struct address_space_operations *aops = inode->i_mapping->a_ops;
/*
@@ -656,13 +653,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, kdev_t dev,
lo->old_gfp_mask = inode->i_mapping->gfp_mask;
inode->i_mapping->gfp_mask = GFP_NOIO;
- bs = 0;
- if (blksize_size[MAJOR(lo_device)])
- bs = blksize_size[MAJOR(lo_device)][MINOR(lo_device)];
- if (!bs)
- bs = BLOCK_SIZE;
-
- set_blocksize(dev, bs);
+ set_blocksize(dev, block_size(lo_device));
lo->lo_bio = lo->lo_biotail = NULL;
kernel_thread(loop_thread, lo, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
@@ -733,7 +724,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
loop_release_xfer(lo);
lo->transfer = NULL;
lo->ioctl = NULL;
- lo->lo_device = 0;
+ lo->lo_device = NODEV;
lo->lo_encrypt_type = 0;
lo->lo_offset = 0;
lo->lo_encrypt_key_size = 0;
@@ -826,12 +817,12 @@ static int lo_ioctl(struct inode * inode, struct file * file,
if (!inode)
return -EINVAL;
- if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+ if (major(inode->i_rdev) != MAJOR_NR) {
printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n",
MAJOR_NR);
return -ENODEV;
}
- dev = MINOR(inode->i_rdev);
+ dev = minor(inode->i_rdev);
if (dev >= max_loop)
return -ENODEV;
lo = &loop_dev[dev];
@@ -881,11 +872,11 @@ static int lo_open(struct inode *inode, struct file *file)
if (!inode)
return -EINVAL;
- if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+ if (major(inode->i_rdev) != MAJOR_NR) {
printk(KERN_WARNING "lo_open: pseudo-major != %d\n", MAJOR_NR);
return -ENODEV;
}
- dev = MINOR(inode->i_rdev);
+ dev = minor(inode->i_rdev);
if (dev >= max_loop)
return -ENODEV;
@@ -908,12 +899,12 @@ static int lo_release(struct inode *inode, struct file *file)
if (!inode)
return 0;
- if (MAJOR(inode->i_rdev) != MAJOR_NR) {
+ if (major(inode->i_rdev) != MAJOR_NR) {
printk(KERN_WARNING "lo_release: pseudo-major != %d\n",
MAJOR_NR);
return 0;
}
- dev = MINOR(inode->i_rdev);
+ dev = minor(inode->i_rdev);
if (dev >= max_loop)
return 0;
@@ -1024,7 +1015,7 @@ int __init loop_init(void)
blk_size[MAJOR_NR] = loop_sizes;
blksize_size[MAJOR_NR] = loop_blksizes;
for (i = 0; i < max_loop; i++)
- register_disk(NULL, MKDEV(MAJOR_NR, i), 1, &lo_fops, 0);
+ register_disk(NULL, mk_kdev(MAJOR_NR, i), 1, &lo_fops, 0);
printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
return 0;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 38b2514d7..49b2e7dc1 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -45,7 +45,6 @@
#include <linux/devfs_fs_kernel.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <asm/types.h>
@@ -79,7 +78,7 @@ static int nbd_open(struct inode *inode, struct file *file)
if (!inode)
return -EINVAL;
- dev = MINOR(inode->i_rdev);
+ dev = minor(inode->i_rdev);
if (dev >= MAX_NBD)
return -ENODEV;
@@ -254,7 +253,7 @@ void nbd_do_it(struct nbd_device *lo)
if (req != blkdev_entry_prev_request(&lo->queue_head)) {
printk(KERN_ALERT "NBD: I have problem...\n");
}
- if (lo != &nbd_dev[MINOR(req->rq_dev)]) {
+ if (lo != &nbd_dev[minor(req->rq_dev)]) {
printk(KERN_ALERT "NBD: request corrupted!\n");
continue;
}
@@ -292,7 +291,7 @@ void nbd_clear_que(struct nbd_device *lo)
printk( KERN_ALERT "NBD: panic, panic, panic\n" );
break;
}
- if (lo != &nbd_dev[MINOR(req->rq_dev)]) {
+ if (lo != &nbd_dev[minor(req->rq_dev)]) {
printk(KERN_ALERT "NBD: request corrupted when clearing!\n");
continue;
}
@@ -329,7 +328,7 @@ static void do_nbd_request(request_queue_t * q)
if (!req)
FAIL("que not empty but no request?");
#endif
- dev = MINOR(req->rq_dev);
+ dev = minor(req->rq_dev);
#ifdef PARANOIA
if (dev >= MAX_NBD)
FAIL("Minor too big."); /* Probably can not happen */
@@ -382,7 +381,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
return -EPERM;
if (!inode)
return -EINVAL;
- dev = MINOR(inode->i_rdev);
+ dev = minor(inode->i_rdev);
if (dev >= MAX_NBD)
return -ENODEV;
@@ -474,7 +473,7 @@ static int nbd_release(struct inode *inode, struct file *file)
if (!inode)
return -ENODEV;
- dev = MINOR(inode->i_rdev);
+ dev = minor(inode->i_rdev);
if (dev >= MAX_NBD)
return -ENODEV;
lo = &nbd_dev[dev];
@@ -529,7 +528,7 @@ static int __init nbd_init(void)
nbd_blksize_bits[i] = 10;
nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
nbd_sizes[i] = nbd_bytesizes[i] >> BLOCK_SIZE_BITS;
- register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &nbd_fops,
+ register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &nbd_fops,
nbd_bytesizes[i]>>9);
}
devfs_handle = devfs_mk_dir (NULL, "nbd", NULL);
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 9604464e3..75e6f694b 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -182,7 +182,7 @@ MODULE_PARM(drive3,"1-6i");
#define MAJOR_NR major
#define DEVICE_NAME "PCD"
#define DEVICE_REQUEST do_pcd_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
@@ -325,7 +325,7 @@ static void pcd_init_units( void )
PCD.info.ops = &pcd_dops;
PCD.info.handle = NULL;
- PCD.info.dev = MKDEV(major,unit);
+ PCD.info.dev = mk_kdev(major,unit);
PCD.info.speed = 0;
PCD.info.capacity = 1;
PCD.info.mask = 0;
@@ -771,7 +771,7 @@ static void do_pcd_request (request_queue_t * q)
if (QUEUE_EMPTY || (CURRENT->rq_status == RQ_INACTIVE)) return;
INIT_REQUEST;
if (rq_data_dir(CURRENT) == READ) {
- unit = MINOR(CURRENT->rq_dev);
+ unit = minor(CURRENT->rq_dev);
if (unit != pcd_unit) {
pcd_bufblk = -1;
pcd_unit = unit;
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 8e1374c18..dbf1c91f2 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -206,7 +206,7 @@ MODULE_PARM(drive3,"1-8i");
#define MAJOR_NR major
#define DEVICE_NAME "PD"
#define DEVICE_REQUEST do_pd_request
-#define DEVICE_NR(device) (MINOR(device)>>PD_BITS)
+#define DEVICE_NR(device) (minor(device)>>PD_BITS)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
@@ -347,7 +347,6 @@ static struct gendisk pd_gendisk = {
major: PD_MAJOR,
major_name: PD_NAME,
minor_shift: PD_BITS,
- max_p: PD_PARTNS,
part: pd_hd,
sizes: pd_sizes,
fops: &pd_fops,
@@ -446,7 +445,7 @@ static int pd_ioctl(struct inode *inode,struct file *file,
struct hd_geometry *geo = (struct hd_geometry *) arg;
int err, unit;
- if (!inode || !inode->i_rdev)
+ if (!inode || kdev_none(inode->i_rdev))
return -EINVAL;
unit = DEVICE_NR(inode->i_rdev);
if (!PD.present)
@@ -815,7 +814,7 @@ static int pd_detect( void )
} else pi_release(PI);
}
for (unit=0;unit<PD_UNITS;unit++)
- register_disk(&pd_gendisk,MKDEV(MAJOR_NR,unit<<PD_BITS),
+ register_disk(&pd_gendisk,mk_kdev(MAJOR_NR,unit<<PD_BITS),
PD_PARTNS,&pd_fops,
PD.present?PD.capacity:0);
@@ -848,7 +847,7 @@ repeat:
if (QUEUE_EMPTY || (CURRENT->rq_status == RQ_INACTIVE)) return;
INIT_REQUEST;
- pd_dev = MINOR(CURRENT->rq_dev);
+ pd_dev = minor(CURRENT->rq_dev);
pd_unit = unit = DEVICE_NR(CURRENT->rq_dev);
pd_block = CURRENT->sector;
pd_run = CURRENT->nr_sectors;
@@ -887,7 +886,7 @@ static void pd_next_buf( int unit )
if (QUEUE_EMPTY ||
(rq_data_dir(CURRENT) != pd_cmd) ||
- (MINOR(CURRENT->rq_dev) != pd_dev) ||
+ (minor(CURRENT->rq_dev) != pd_dev) ||
(CURRENT->rq_status == RQ_INACTIVE) ||
(CURRENT->sector != pd_block))
printk("%s: OUCH: request list changed unexpectedly\n",
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index c83901c70..0088d7938 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -202,7 +202,7 @@ MODULE_PARM(drive3,"1-7i");
#define MAJOR_NR major
#define DEVICE_NAME "PF"
#define DEVICE_REQUEST do_pf_request
-#define DEVICE_NR(device) MINOR(device)
+#define DEVICE_NR(device) minor(device)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
@@ -368,7 +368,7 @@ int pf_init (void) /* preliminary initialisation */
for (i=0;i<PF_UNITS;i++) pf_blocksizes[i] = 1024;
blksize_size[MAJOR_NR] = pf_blocksizes;
for (i=0;i<PF_UNITS;i++)
- register_disk(NULL, MKDEV(MAJOR_NR, i), 1, &pf_fops, 0);
+ register_disk(NULL, mk_kdev(MAJOR_NR, i), 1, &pf_fops, 0);
return 0;
}
@@ -399,7 +399,7 @@ static int pf_ioctl(struct inode *inode,struct file *file,
{ int err, unit;
struct hd_geometry *geo = (struct hd_geometry *) arg;
- if ((!inode) || (!inode->i_rdev)) return -EINVAL;
+ if ((!inode) || kdev_none(inode->i_rdev)) return -EINVAL;
unit = DEVICE_NR(inode->i_rdev);
if (unit >= PF_UNITS) return -EINVAL;
if (!PF.present) return -ENODEV;
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index bf680c022..bf98ec1de 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -565,7 +565,7 @@ static int pg_detect( void )
return -1;
}
-#define DEVICE_NR(dev) (MINOR(dev) % 128)
+#define DEVICE_NR(dev) (minor(dev) & 0x7F)
static int pg_open (struct inode *inode, struct file *file)
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 725960050..9e9e59238 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -688,7 +688,7 @@ static int pt_detect( void )
return -1;
}
-#define DEVICE_NR(dev) (MINOR(dev) % 128)
+#define DEVICE_NR(dev) (minor(dev) & 0x7F)
static int pt_open (struct inode *inode, struct file *file)
@@ -713,7 +713,7 @@ static int pt_open (struct inode *inode, struct file *file)
return -EROFS;
}
- if (!(MINOR(inode->i_rdev) & 128))
+ if (!(minor(inode->i_rdev) & 128))
PT.flags |= PT_REWIND;
PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
@@ -732,7 +732,7 @@ static int pt_ioctl(struct inode *inode,struct file *file,
int unit;
struct mtop mtop;
- if (!inode || !inode->i_rdev)
+ if (!inode || kdev_none(inode->i_rdev))
return -EINVAL;
unit = DEVICE_NR(inode->i_rdev);
if (unit >= PT_UNITS)
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index b4af9d7ec..881ef1555 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -51,7 +51,6 @@
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/dma.h>
#include <asm/mca_dma.h>
#include <asm/uaccess.h>
@@ -161,10 +160,8 @@ static struct gendisk ps2esdi_gendisk =
major: MAJOR_NR,
major_name: "ed",
minor_shift: 6,
- max_p: 1 << 6,
part: ps2esdi,
sizes: ps2esdi_sizes,
- real_devices: (void *)ps2esdi_info,
fops: &ps2esdi_fops,
};
@@ -953,10 +950,10 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
break;
}
if(ending != -1) {
- spin_lock_irqsave(ps2esdi_LOCK, flags);
+ spin_lock_irqsave(&ps2esdi_lock, flags);
end_request(ending);
do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
- spin_unlock_irqrestore(ps2esdi_LOCK, flags);
+ spin_unlock_irqrestore(&ps2esdi_lock, flags);
}
} /* handle interrupts */
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 13f2351f4..c2c352d4d 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -246,7 +246,7 @@ static int rd_make_request(request_queue_t * q, struct bio *sbh)
unsigned long offset, len;
int rw = sbh->bi_rw;
- minor = MINOR(sbh->bi_dev);
+ minor = minor(sbh->bi_dev);
if (minor >= NUM_RAMDISKS)
goto fail;
@@ -280,10 +280,10 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
int error = -EINVAL;
unsigned int minor;
- if (!inode || !inode->i_rdev)
+ if (!inode || kdev_none(inode->i_rdev))
goto out;
- minor = MINOR(inode->i_rdev);
+ minor = minor(inode->i_rdev);
switch (cmd) {
case BLKFLSBUF:
@@ -407,7 +407,7 @@ static void __exit rd_cleanup (void)
rd_bdev[i] = NULL;
if (bdev)
blkdev_put(bdev, BDEV_FILE);
- destroy_buffers(MKDEV(MAJOR_NR, i));
+ destroy_buffers(mk_kdev(MAJOR_NR, i));
}
devfs_unregister (devfs_handle);
@@ -449,11 +449,11 @@ static int __init rd_init (void)
&rd_bd_op, NULL);
for (i = 0; i < NUM_RAMDISKS; i++)
- register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
+ register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
#ifdef CONFIG_BLK_DEV_INITRD
/* We ought to separate initrd operations here */
- register_disk(NULL, MKDEV(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1);
+ register_disk(NULL, mk_kdev(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1);
devfs_register(devfs_handle, "initrd", DEVFS_FL_DEFAULT, MAJOR_NR,
INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL);
#endif
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 55587b464..9cdaf6d7e 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -130,10 +130,8 @@ static struct gendisk xd_gendisk = {
major: MAJOR_NR,
major_name: "xd",
minor_shift: 6,
- max_p: 1 << 6,
part: xd_struct,
sizes: xd_sizes,
- real_devices: (void *)xd_info,
fops: &xd_fops,
};
@@ -251,7 +249,8 @@ static void __init xd_geninit (void)
for (i = 0; i < xd_drives; i++) {
xd_valid[i] = 1;
- register_disk(&xd_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6, &xd_fops,
+ register_disk(&xd_gendisk, mk_kdev(MAJOR_NR,i<<6), 1<<6,
+ &xd_fops,
xd_info[i].heads * xd_info[i].cylinders *
xd_info[i].sectors);
}
@@ -289,8 +288,9 @@ static void do_xd_request (request_queue_t * q)
INIT_REQUEST; /* do some checking on the request structure */
if (CURRENT_DEV < xd_drives
+ && (CURRENT->flags & REQ_CMD)
&& CURRENT->sector + CURRENT->nr_sectors
- <= xd_struct[MINOR(CURRENT->rq_dev)].nr_sects) {
+ <= xd_struct[minor(CURRENT->rq_dev)].nr_sects) {
block = CURRENT->sector;
count = CURRENT->nr_sectors;
@@ -314,7 +314,7 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
{
int dev;
- if ((!inode) || !(inode->i_rdev))
+ if ((!inode) || kdev_none(inode->i_rdev))
return -EINVAL;
dev = DEVICE_NR(inode->i_rdev);
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index e99818753..543796102 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -229,7 +229,7 @@ static int aztcd_blocksizes[1] = { 2048 };
#endif
#define CURRENT_VALID \
- (!QUEUE_EMPTY && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
+ (!QUEUE_EMPTY && major(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
&& CURRENT -> sector != -1)
#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
@@ -309,6 +309,8 @@ static unsigned char aztIndatum;
static unsigned long aztTimeOutCount;
static int aztCmd = 0;
+static spinlock_t aztSpin = SPIN_LOCK_UNLOCKED;
+
/*###########################################################################
Function Prototypes
###########################################################################
@@ -1599,10 +1601,6 @@ static void do_aztcd_request(request_queue_t * q)
}
azt_transfer_is_active = 1;
while (CURRENT_VALID) {
- if (CURRENT->bh) {
- if (!buffer_locked(CURRENT->bh))
- panic(DEVICE_NAME ": block not locked");
- }
azt_transfer();
if (CURRENT->nr_sectors == 0) {
end_request(1);
@@ -1927,10 +1925,10 @@ int __init aztcd_init(void)
MAJOR_NR);
return -EIO;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST, &aztSpin);
blksize_size[MAJOR_NR] = aztcd_blocksizes;
read_ahead[MAJOR_NR] = 4;
- register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &azt_fops, 0);
+ register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &azt_fops, 0);
if ((azt_port == 0x1f0) || (azt_port == 0x170))
request_region(azt_port, 8, "aztcd"); /*IDE-interface */
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index ac2d341b7..229df11fe 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -266,7 +266,6 @@
#include <linux/init.h>
#include <asm/fcntl.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
/* used to tell the module to turn on full debugging messages */
@@ -338,7 +337,7 @@ static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
int register_cdrom(struct cdrom_device_info *cdi)
{
static char banner_printed;
- int major = MAJOR(cdi->dev);
+ int major = major(cdi->dev);
struct cdrom_device_ops *cdo = cdi->ops;
int *change_capability = (int *)&cdo->capability; /* hack */
@@ -409,7 +408,7 @@ int register_cdrom(struct cdrom_device_info *cdi)
int unregister_cdrom(struct cdrom_device_info *unreg)
{
struct cdrom_device_info *cdi, *prev;
- int major = MAJOR(unreg->dev);
+ int major = major(unreg->dev);
cdinfo(CD_OPEN, "entering unregister_cdrom\n");
@@ -418,7 +417,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
prev = NULL;
cdi = topCdromPtr;
- while (cdi != NULL && cdi->dev != unreg->dev) {
+ while (cdi != NULL && !kdev_same(cdi->dev, unreg->dev)) {
prev = cdi;
cdi = cdi->next;
}
@@ -441,7 +440,7 @@ struct cdrom_device_info *cdrom_find_device(kdev_t dev)
struct cdrom_device_info *cdi;
cdi = topCdromPtr;
- while (cdi != NULL && cdi->dev != dev)
+ while (cdi != NULL && !kdev_same(cdi->dev, dev))
cdi = cdi->next;
return cdi;
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index 94c94fd9a..20a80e42e 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -237,6 +237,7 @@ static volatile unsigned short sony_cd_result_reg;
static volatile unsigned short sony_cd_read_reg;
static volatile unsigned short sony_cd_fifost_reg;
+static spinlock_t cdu31a_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
static int sony_spun_up = 0; /* Has the drive been spun up? */
@@ -1586,7 +1587,7 @@ static void do_cdu31a_request(request_queue_t * q)
/*
* jens: driver has lots of races
*/
- spin_unlock_irq(&q->queue_lock);
+ spin_unlock_irq(q->queue_lock);
/* Make sure the timer is cancelled. */
del_timer(&cdu31a_abort_timer);
@@ -1605,17 +1606,7 @@ static void do_cdu31a_request(request_queue_t * q)
scd_spinup();
}
- /* I don't use INIT_REQUEST because it calls return, which would
- return without unlocking the device. It shouldn't matter,
- but just to be safe... */
- if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) {
- panic(DEVICE_NAME ": request list destroyed");
- }
- if (CURRENT->bh) {
- if (!buffer_locked(CURRENT->bh)) {
- panic(DEVICE_NAME ": block not locked");
- }
- }
+ INIT_REQUEST;
block = CURRENT->sector;
nblock = CURRENT->nr_sectors;
@@ -1626,114 +1617,107 @@ static void do_cdu31a_request(request_queue_t * q)
goto cdu31a_request_startover;
}
- switch (CURRENT->cmd) {
- case READ:
- /*
- * If the block address is invalid or the request goes beyond the end of
- * the media, return an error.
- */
-#if 0
- if ((block / 4) < sony_toc.start_track_lba) {
- printk
- ("CDU31A: Request before beginning of media\n");
- end_request(0);
- goto cdu31a_request_startover;
- }
-#endif
- if ((block / 4) >= sony_toc.lead_out_start_lba) {
- printk
- ("CDU31A: Request past end of media\n");
- end_request(0);
- goto cdu31a_request_startover;
- }
- if (((block + nblock) / 4) >=
- sony_toc.lead_out_start_lba) {
- printk
- ("CDU31A: Request past end of media\n");
- end_request(0);
- goto cdu31a_request_startover;
- }
-
- num_retries = 0;
-
- try_read_again:
- while (handle_sony_cd_attention());
-
- if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
- end_request(0);
- goto cdu31a_request_startover;
- }
-
- /* If no data is left to be read from the drive, start the
- next request. */
- if (sony_blocks_left == 0) {
- if (start_request
- (block / 4, CDU31A_READAHEAD / 4, 0)) {
- end_request(0);
- goto cdu31a_request_startover;
- }
- }
- /* If the requested block is not the next one waiting in
- the driver, abort the current operation and start a
- new one. */
- else if (block != sony_next_block) {
-#if DEBUG
- printk
- ("CDU31A Warning: Read for block %d, expected %d\n",
- block, sony_next_block);
-#endif
- abort_read();
- if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
+ if(CURRENT->flags & REQ_CMD) {
+ switch (rq_data_dir(CURRENT)) {
+ case READ:
+ /*
+ * If the block address is invalid or the request goes beyond the end of
+ * the media, return an error.
+ */
+ if ((block / 4) >= sony_toc.lead_out_start_lba) {
+ printk
+ ("CDU31A: Request past end of media\n");
end_request(0);
goto cdu31a_request_startover;
}
- if (start_request
- (block / 4, CDU31A_READAHEAD / 4, 0)) {
+ if (((block + nblock) / 4) >=
+ sony_toc.lead_out_start_lba) {
printk
- ("CDU31a: start request failed\n");
+ ("CDU31A: Request past end of media\n");
end_request(0);
goto cdu31a_request_startover;
}
- }
- read_data_block(CURRENT->buffer, block, nblock,
- res_reg, &res_size);
- if (res_reg[0] == 0x20) {
- if (num_retries > MAX_CDU31A_RETRIES) {
+ num_retries = 0;
+
+ try_read_again:
+ while (handle_sony_cd_attention());
+
+ if (!sony_toc_read) {
+ printk("CDU31A: TOC not read\n");
end_request(0);
goto cdu31a_request_startover;
}
- num_retries++;
- if (res_reg[1] == SONY_NOT_SPIN_ERR) {
- do_sony_cd_cmd(SONY_SPIN_UP_CMD,
- NULL, 0, res_reg,
- &res_size);
- } else {
+ /* If no data is left to be read from the drive, start the
+ next request. */
+ if (sony_blocks_left == 0) {
+ if (start_request
+ (block / 4, CDU31A_READAHEAD / 4, 0)) {
+ end_request(0);
+ goto cdu31a_request_startover;
+ }
+ }
+ /* If the requested block is not the next one waiting in
+ the driver, abort the current operation and start a
+ new one. */
+ else if (block != sony_next_block) {
+#if DEBUG
printk
- ("CDU31A: %s error for block %d, nblock %d\n",
- translate_error(res_reg[1]),
- block, nblock);
+ ("CDU31A Warning: Read for block %d, expected %d\n",
+ block, sony_next_block);
+#endif
+ abort_read();
+ if (!sony_toc_read) {
+ printk("CDU31A: TOC not read\n");
+ end_request(0);
+ goto cdu31a_request_startover;
+ }
+ if (start_request
+ (block / 4, CDU31A_READAHEAD / 4, 0)) {
+ printk
+ ("CDU31a: start request failed\n");
+ end_request(0);
+ goto cdu31a_request_startover;
+ }
}
- goto try_read_again;
- } else {
- end_request(1);
- }
- break;
- case WRITE:
- end_request(0);
- break;
+ read_data_block(CURRENT->buffer, block, nblock,
+ res_reg, &res_size);
+ if (res_reg[0] == 0x20) {
+ if (num_retries > MAX_CDU31A_RETRIES) {
+ end_request(0);
+ goto cdu31a_request_startover;
+ }
- default:
- panic("CDU31A: Unknown cmd");
+ num_retries++;
+ if (res_reg[1] == SONY_NOT_SPIN_ERR) {
+ do_sony_cd_cmd(SONY_SPIN_UP_CMD,
+ NULL, 0, res_reg,
+ &res_size);
+ } else {
+ printk
+ ("CDU31A: %s error for block %d, nblock %d\n",
+ translate_error(res_reg[1]),
+ block, nblock);
+ }
+ goto try_read_again;
+ } else {
+ end_request(1);
+ }
+ break;
+
+ case WRITE:
+ end_request(0);
+ break;
+
+ default:
+ panic("CDU31A: Unknown cmd");
+ }
}
}
-
end_do_cdu31a_request:
- spin_lock_irq(&q->queue_lock);
+ spin_lock_irq(q->queue_lock);
#if 0
/* After finished, cancel any pending operations. */
abort_read();
@@ -3456,7 +3440,8 @@ int __init cdu31a_init(void)
strcmp("CD-ROM CDU31A", drive_config.product_id) == 0;
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR),
- DEVICE_REQUEST);
+ DEVICE_REQUEST,
+ &cdu31a_lock);
read_ahead[MAJOR_NR] = CDU31A_READAHEAD;
cdu31a_block_size = 1024; /* 1kB default block size */
/* use 'mount -o block=2048' */
@@ -3465,7 +3450,7 @@ int __init cdu31a_init(void)
init_timer(&cdu31a_abort_timer);
cdu31a_abort_timer.function = handle_abort_timeout;
- scd_info.dev = MKDEV(MAJOR_NR, 0);
+ scd_info.dev = mk_kdev(MAJOR_NR, 0);
scd_info.mask = deficiency;
strncpy(scd_info.name, "cdu31a", sizeof(scd_info.name));
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index f9b1af285..411103ead 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -302,6 +302,7 @@ struct cm206_struct {
#define PLAY_TO cd->toc[0] /* toc[0] records end-time in play */
static struct cm206_struct *cd; /* the main memory structure */
+static spinlock_t cm206_lock = SPIN_LOCK_UNLOCKED;
/* First, we define some polling functions. These are actually
only being used in the initialization. */
@@ -866,7 +867,7 @@ static void do_cm206_request(request_queue_t * q)
end_request(0);
continue;
}
- spin_unlock_irq(&q->queue_lock);
+ spin_unlock_irq(q->queue_lock);
error = 0;
for (i = 0; i < CURRENT->nr_sectors; i++) {
int e1, e2;
@@ -893,7 +894,7 @@ static void do_cm206_request(request_queue_t * q)
debug(("cm206_request: %d %d\n", e1, e2));
}
}
- spin_lock_irq(&q->queue_lock);
+ spin_lock_irq(q->queue_lock);
end_request(!error);
}
}
@@ -1491,7 +1492,7 @@ int __init cm206_init(void)
cleanup(3);
return -EIO;
}
- cm206_info.dev = MKDEV(MAJOR_NR, 0);
+ cm206_info.dev = mk_kdev(MAJOR_NR, 0);
if (register_cdrom(&cm206_info) != 0) {
printk(KERN_INFO "Cannot register for cdrom %d!\n",
MAJOR_NR);
@@ -1499,7 +1500,8 @@ int __init cm206_init(void)
return -EIO;
}
devfs_plain_cdrom(&cm206_info, &cm206_bdops);
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST,
+ &cm206_lock);
blksize_size[MAJOR_NR] = cm206_blocksizes;
read_ahead[MAJOR_NR] = 16; /* reads ahead what? */
init_bh(CM206_BH, cm206_bh);
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index c216dfe96..616ce21f2 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -162,6 +162,7 @@ static int AudioEnd_m;
static int AudioEnd_f;
static struct timer_list gscd_timer;
+static spinlock_t gscd_lock = SPIN_LOCK_UNLOCKED;
static struct block_device_operations gscd_fops = {
owner:THIS_MODULE,
@@ -180,7 +181,7 @@ static int check_gscd_med_chg(kdev_t full_dev)
int target;
- target = MINOR(full_dev);
+ target = minor(full_dev);
if (target > 0) {
printk
@@ -283,7 +284,7 @@ static void __do_gscd_request(unsigned long dummy)
if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE)
goto out;
INIT_REQUEST;
- dev = MINOR(CURRENT->rq_dev);
+ dev = minor(CURRENT->rq_dev);
block = CURRENT->sector;
nsect = CURRENT->nr_sectors;
@@ -296,7 +297,7 @@ static void __do_gscd_request(unsigned long dummy)
goto repeat;
}
- if (MINOR(CURRENT->rq_dev) != 0) {
+ if (dev != 0) {
printk("GSCD: this version supports only one device\n");
end_request(0);
goto repeat;
@@ -1019,7 +1020,7 @@ int __init my_gscd_init(void)
devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST, &gscd_lock);
blksize_size[MAJOR_NR] = gscd_blocksizes;
read_ahead[MAJOR_NR] = 4;
@@ -1027,7 +1028,7 @@ int __init my_gscd_init(void)
gscdPresent = 1;
request_region(gscd_port, 4, "gscd");
- register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &gscd_fops, 0);
+ register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &gscd_fops, 0);
printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
return 0;
diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
index 8fd86a653..e8145bf93 100644
--- a/drivers/cdrom/mcd.c
+++ b/drivers/cdrom/mcd.c
@@ -123,7 +123,7 @@ static int mcdPresent;
#define QUICK_LOOP_COUNT 20
#define CURRENT_VALID \
-(!QUEUE_EMPTY && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
+(!QUEUE_EMPTY && major(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
&& CURRENT -> sector != -1)
#define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
@@ -185,6 +185,7 @@ static int mcd_open(struct cdrom_device_info *cdi, int purpose);
static void mcd_release(struct cdrom_device_info *cdi);
static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr);
static int mcd_tray_move(struct cdrom_device_info *cdi, int position);
+static spinlock_t mcd_spinlock = SPIN_LOCK_UNLOCKED;
int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
void *arg);
int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
@@ -617,10 +618,6 @@ static void do_mcd_request(request_queue_t * q)
mcd_transfer_is_active = 1;
while (CURRENT_VALID) {
- if (CURRENT->bh) {
- if (!buffer_locked(CURRENT->bh))
- panic(DEVICE_NAME ": block not locked");
- }
mcd_transfer();
if (CURRENT->nr_sectors == 0) {
end_request(1);
@@ -1076,7 +1073,8 @@ int __init mcd_init(void)
}
blksize_size[MAJOR_NR] = mcd_blocksizes;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST,
+ &mcd_spinlock);
read_ahead[MAJOR_NR] = 4;
/* check for card */
@@ -1150,7 +1148,7 @@ int __init mcd_init(void)
mcd_invalidate_buffers();
mcdPresent = 1;
- mcd_info.dev = MKDEV(MAJOR_NR, 0);
+ mcd_info.dev = mk_kdev(MAJOR_NR, 0);
if (register_cdrom(&mcd_info) != 0) {
printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n");
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index 9963409fa..8fa24e0ab 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -291,6 +291,7 @@ static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
static struct s_drive_stuff *mcdx_irq_map[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
+static spinlock_t mcdx_lock = SPIN_LOCK_UNLOCKED;
MODULE_PARM(mcdx, "1-4i");
static struct cdrom_device_ops mcdx_dops = {
@@ -318,7 +319,7 @@ static struct cdrom_device_info mcdx_info = {
static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
unsigned int cmd, void *arg)
{
- struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
+ struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)];
if (!stuffp->present)
return -ENXIO;
@@ -575,7 +576,7 @@ void do_mcdx_request(request_queue_t * q)
INIT_REQUEST;
- dev = MINOR(CURRENT->rq_dev);
+ dev = minor(CURRENT->rq_dev);
stuffp = mcdx_stuffp[dev];
if ((dev < 0)
@@ -598,14 +599,13 @@ void do_mcdx_request(request_queue_t * q)
xtrace(REQUEST, "do_request() (%lu + %lu)\n",
CURRENT->sector, CURRENT->nr_sectors);
- switch (CURRENT->cmd) {
- case WRITE:
- xwarn("do_request(): attempt to write to cd!!\n");
+ if (CURRENT->cmd != READ) {
+ xwarn("do_request(): non-read command to cd!!\n");
xtrace(REQUEST, "end_request(0): write\n");
end_request(0);
return;
-
- case READ:
+ }
+ else {
stuffp->status = 0;
while (CURRENT->nr_sectors) {
int i;
@@ -628,11 +628,6 @@ void do_mcdx_request(request_queue_t * q)
xtrace(REQUEST, "end_request(1)\n");
end_request(1);
- break;
-
- default:
- panic(MCDX "do_request: unknown command.\n");
- break;
}
goto again;
@@ -642,7 +637,7 @@ static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
{
struct s_drive_stuff *stuffp;
xtrace(OPENCLOSE, "open()\n");
- stuffp = mcdx_stuffp[MINOR(cdi->dev)];
+ stuffp = mcdx_stuffp[minor(cdi->dev)];
if (!stuffp->present)
return -ENXIO;
@@ -791,7 +786,7 @@ static void mcdx_close(struct cdrom_device_info *cdi)
xtrace(OPENCLOSE, "close()\n");
- stuffp = mcdx_stuffp[MINOR(cdi->dev)];
+ stuffp = mcdx_stuffp[minor(cdi->dev)];
--stuffp->users;
}
@@ -805,7 +800,7 @@ static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
xinfo("mcdx_media_changed called for device %s\n",
kdevname(cdi->dev));
- stuffp = mcdx_stuffp[MINOR(cdi->dev)];
+ stuffp = mcdx_stuffp[minor(cdi->dev)];
mcdx_getstatus(stuffp, 1);
if (stuffp->yyy == 0)
@@ -1187,7 +1182,8 @@ int __init mcdx_init_drive(int drive)
return 1;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST,
+ &mcdx_lock);
read_ahead[MAJOR_NR] = READ_AHEAD;
blksize_size[MAJOR_NR] = mcdx_blocksizes;
@@ -1228,7 +1224,7 @@ int __init mcdx_init_drive(int drive)
stuffp->wreg_data, stuffp->irq, version.code, version.ver);
mcdx_stuffp[drive] = stuffp;
xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
- mcdx_info.dev = MKDEV(MAJOR_NR, 0);
+ mcdx_info.dev = mk_kdev(MAJOR_NR, 0);
if (register_cdrom(&mcdx_info) != 0) {
printk("Cannot register Mitsumi CD-ROM!\n");
release_region((unsigned long) stuffp->wreg_data,
@@ -1698,7 +1694,7 @@ mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
{
- struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
+ struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)];
if (!stuffp->present)
return -ENXIO;
@@ -1888,7 +1884,7 @@ static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tr
static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
{
- struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
+ struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)];
char cmd[2] = { 0xfe };
if (!(stuffp->present & DOOR))
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
index d8ee1c68c..176c6ce4e 100644
--- a/drivers/cdrom/optcd.c
+++ b/drivers/cdrom/optcd.c
@@ -109,7 +109,6 @@ static void debug(int debug_this, const char* fmt, ...)
#endif
static int blksize = 2048;
-static int hsecsize = 2048;
/* Drive hardware/firmware characteristics
@@ -267,6 +266,7 @@ static int sleep_timeout; /* max # of ticks to sleep */
static DECLARE_WAIT_QUEUE_HEAD(waitq);
static void sleep_timer(unsigned long data);
static struct timer_list delay_timer = {function: sleep_timer};
+spinlock_t optcd_lock = SPIN_LOCK_UNLOCKED;
/* Timer routine: wake up when desired flag goes low,
@@ -977,7 +977,7 @@ static int update_toc(void)
#define CURRENT_VALID \
- (!QUEUE_EMPTY && MAJOR(CURRENT -> rq_dev) == MAJOR_NR \
+ (!QUEUE_EMPTY && major(CURRENT -> rq_dev) == MAJOR_NR \
&& CURRENT -> cmd == READ && CURRENT -> sector != -1)
@@ -1371,10 +1371,6 @@ static void do_optcd_request(request_queue_t * q)
transfer_is_active = 1;
while (CURRENT_VALID) {
- if (CURRENT->bh) {
- if (!buffer_locked(CURRENT->bh))
- panic(DEVICE_NAME ": block not locked");
- }
transfer(); /* First try to transfer block from buffers */
if (CURRENT -> nr_sectors == 0) {
end_request(1);
@@ -2063,12 +2059,12 @@ int __init optcd_init(void)
}
devfs_register (NULL, "optcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO, &opt_fops, NULL);
- hardsect_size[MAJOR_NR] = &hsecsize;
blksize_size[MAJOR_NR] = &blksize;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST,
+ &optcd_lock);
read_ahead[MAJOR_NR] = 4;
request_region(optcd_port, 4, "optcd");
- register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &opt_fops, 0);
+ register_disk(NULL, mk_kdev(MAJOR_NR,0), 1, &opt_fops, 0);
printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
return 0;
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index b79c01f8b..f01343a99 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -2057,7 +2057,7 @@ static void switch_drive(int i);
static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
{
- int i = MINOR(cdi->dev);
+ int i = minor(cdi->dev);
if (i != d)
switch_drive(i);
@@ -2095,7 +2095,7 @@ static int DriveReset(void)
static int sbpcd_reset(struct cdrom_device_info *cdi)
{
- int i = MINOR(cdi->dev);
+ int i = minor(cdi->dev);
if (i != d)
switch_drive(i);
@@ -2376,7 +2376,7 @@ static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
{
int i;
int retval=0;
- i = MINOR(cdi->dev);
+ i = minor(cdi->dev);
switch_drive(i);
/* DUH! --AJK */
if(D_S[d].CD_changed != 0xFF) {
@@ -4061,13 +4061,13 @@ static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
#if 0
- if (!(D_S[MINOR(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN;
- if (D_S[MINOR(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK;
- if (D_S[MINOR(cdi->dev)].status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
+ if (!(D_S[minor(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN;
+ if (D_S[minor(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK;
+ if (D_S[minor(cdi->dev)].status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
return CDS_NO_DISC;
#else
- if (D_S[MINOR(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK;
+ if (D_S[minor(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK;
/* return CDS_TRAY_OPEN; */
return CDS_NO_DISC;
@@ -4203,8 +4203,8 @@ static int sbp_status(void)
static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
{
ms_infp->addr_format = CDROM_LBA;
- ms_infp->addr.lba = D_S[MINOR(cdi->dev)].lba_multi;
- if (D_S[MINOR(cdi->dev)].f_multisession)
+ ms_infp->addr.lba = D_S[minor(cdi->dev)].lba_multi;
+ if (D_S[minor(cdi->dev)].f_multisession)
ms_infp->xa_flag=1; /* valid redirection address */
else
ms_infp->xa_flag=0; /* invalid redirection address */
@@ -4223,8 +4223,8 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
int i;
msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08lX)\n",
- MINOR(cdi->dev), cmd, arg);
- i=MINOR(cdi->dev);
+ minor(cdi->dev), cmd, arg);
+ i=minor(cdi->dev);
if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
{
msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev);
@@ -4533,9 +4533,9 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
case BLKRASET:
if(!capable(CAP_SYS_ADMIN)) RETURN_UP(-EACCES);
- if(!(cdi->dev)) RETURN_UP(-EINVAL);
+ if(kdev_none(cdi->dev)) RETURN_UP(-EINVAL);
if(arg > 0xff) RETURN_UP(-EINVAL);
- read_ahead[MAJOR(cdi->dev)] = arg;
+ read_ahead[major(cdi->dev)] = arg;
RETURN_UP(0);
default:
msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
@@ -4549,8 +4549,8 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
int i, st, j;
msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n",
- MINOR(cdi->dev), cmd, arg);
- i=MINOR(cdi->dev);
+ minor(cdi->dev), cmd, arg);
+ i=minor(cdi->dev);
if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
{
msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev);
@@ -4930,7 +4930,7 @@ static void DO_SBPCD_REQUEST(request_queue_t * q)
sbpcd_end_request(req, 0);
if (req -> sector == -1)
sbpcd_end_request(req, 0);
- spin_unlock_irq(&q->queue_lock);
+ spin_unlock_irq(q->queue_lock);
down(&ioctl_read_sem);
if (req->cmd != READ)
@@ -4938,7 +4938,7 @@ static void DO_SBPCD_REQUEST(request_queue_t * q)
msg(DBG_INF, "bad cmd %d\n", req->cmd);
goto err_done;
}
- i = MINOR(req->rq_dev);
+ i = minor(req->rq_dev);
if ( (i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
{
msg(DBG_INF, "do_request: bad device: %s\n",
@@ -4970,7 +4970,7 @@ static void DO_SBPCD_REQUEST(request_queue_t * q)
xnr, req, req->sector, req->nr_sectors, jiffies);
#endif
up(&ioctl_read_sem);
- spin_lock_irq(&q->queue_lock);
+ spin_lock_irq(q->queue_lock);
sbpcd_end_request(req, 1);
goto request_loop;
}
@@ -5011,7 +5011,7 @@ static void DO_SBPCD_REQUEST(request_queue_t * q)
xnr, req, req->sector, req->nr_sectors, jiffies);
#endif
up(&ioctl_read_sem);
- spin_lock_irq(&q->queue_lock);
+ spin_lock_irq(q->queue_lock);
sbpcd_end_request(req, 1);
goto request_loop;
}
@@ -5027,7 +5027,7 @@ static void DO_SBPCD_REQUEST(request_queue_t * q)
#endif
up(&ioctl_read_sem);
sbp_sleep(0); /* wait a bit, try again */
- spin_lock_irq(&q->queue_lock);
+ spin_lock_irq(q->queue_lock);
sbpcd_end_request(req, 0);
goto request_loop;
}
@@ -5435,7 +5435,7 @@ static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
{
int i;
- i = MINOR(cdi->dev);
+ i = minor(cdi->dev);
down(&ioctl_read_sem);
switch_drive(i);
@@ -5474,7 +5474,7 @@ static void sbpcd_release(struct cdrom_device_info * cdi)
{
int i;
- i = MINOR(cdi->dev);
+ i = minor(cdi->dev);
if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
{
msg(DBG_INF, "release: bad device: %04X\n", cdi->dev);
@@ -6003,8 +6003,8 @@ static int sbpcd_chk_disk_change(kdev_t full_dev)
{
int i;
- msg(DBG_CHK,"media_check (%d) called\n", MINOR(full_dev));
- i=MINOR(full_dev);
+ i=minor(full_dev);
+ msg(DBG_CHK,"media_check (%d) called\n", i);
if (D_S[i].CD_changed==0xFF)
{
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index 4b350c2df..aaf3a3113 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -105,6 +105,7 @@ static volatile unsigned char sjcd_completion_status = 0;
static volatile unsigned char sjcd_completion_error = 0;
static unsigned short sjcd_command_is_in_progress = 0;
static unsigned short sjcd_error_reported = 0;
+static spinlock_t sjcd_lock = SPIN_LOCK_UNLOCKED;
static int sjcd_open_count;
@@ -458,7 +459,7 @@ static int sjcd_disk_change(kdev_t full_dev)
#if 0
printk("SJCD: sjcd_disk_change( 0x%x )\n", full_dev);
#endif
- if (MINOR(full_dev) > 0) {
+ if (minor(full_dev) > 0) {
printk("SJCD: request error: invalid device minor.\n");
return 0;
}
@@ -1074,7 +1075,7 @@ static void sjcd_invalidate_buffers(void)
*/
#define CURRENT_IS_VALID \
- ( !QUEUE_EMPTY && MAJOR( CURRENT->rq_dev ) == MAJOR_NR && \
+ ( !QUEUE_EMPTY && major( CURRENT->rq_dev ) == MAJOR_NR && \
CURRENT->cmd == READ && CURRENT->sector != -1 )
static void sjcd_transfer(void)
@@ -1497,12 +1498,6 @@ static void do_sjcd_request(request_queue_t * q)
#endif
sjcd_transfer_is_active = 1;
while (CURRENT_IS_VALID) {
- /*
- * Who of us are paranoiac?
- */
- if (CURRENT->bh && !buffer_locked(CURRENT->bh))
- panic(DEVICE_NAME ": block not locked");
-
sjcd_transfer();
if (CURRENT->nr_sectors == 0)
end_request(1);
@@ -1664,7 +1659,6 @@ static struct block_device_operations sjcd_fops = {
};
static int blksize = 2048;
-static int secsize = 2048;
/*
* Following stuff is intended for initialization of the cdrom. It
@@ -1692,7 +1686,6 @@ int __init sjcd_init(void)
printk("SJCD: sjcd=0x%x: ", sjcd_base);
#endif
- hardsect_size[MAJOR_NR] = &secsize;
blksize_size[MAJOR_NR] = &blksize;
if (devfs_register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {
@@ -1701,9 +1694,9 @@ int __init sjcd_init(void)
return (-EIO);
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST,&sjcd_lock);
read_ahead[MAJOR_NR] = 4;
- register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &sjcd_fops, 0);
+ register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &sjcd_fops, 0);
if (check_region(sjcd_base, 4)) {
printk
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index 2d1c1f6d2..5fb3a170f 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -217,6 +217,8 @@ static unsigned short command_reg;
static unsigned short read_status_reg;
static unsigned short data_reg;
+static spinlock_t sonycd535_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
+
static int initialized; /* Has the drive been initialized? */
static int sony_disc_changed = 1; /* Has the disk been changed
since the last check? */
@@ -279,7 +281,7 @@ cdu535_check_media_change(kdev_t full_dev)
{
int retval;
- if (MINOR(full_dev) != 0) {
+ if (minor(full_dev) != 0) {
printk(CDU535_MESSAGE_NAME " request error: invalid device.\n");
return 0;
}
@@ -808,130 +810,131 @@ do_cdu535_request(request_queue_t * q)
return;
}
INIT_REQUEST;
- dev = MINOR(CURRENT->rq_dev);
+ dev = minor(CURRENT->rq_dev);
block = CURRENT->sector;
nsect = CURRENT->nr_sectors;
if (dev != 0) {
end_request(0);
continue;
}
- switch (CURRENT->cmd) {
- case READ:
- /*
- * If the block address is invalid or the request goes beyond the end of
- * the media, return an error.
- */
-
- if (sony_toc->lead_out_start_lba <= (block / 4)) {
- end_request(0);
- return;
- }
- if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
- end_request(0);
- return;
- }
- while (0 < nsect) {
+ if(CURRENT->flags & REQ_CMD) {
+ switch (rq_data_dir(CURRENT)) {
+ case READ:
/*
- * If the requested sector is not currently in the read-ahead buffer,
- * it must be read in.
+ * If the block address is invalid or the request goes beyond the end of
+ * the media, return an error.
*/
- if ((block < sony_first_block) || (sony_last_block < block)) {
- sony_first_block = (block / 4) * 4;
- log_to_msf(block / 4, params);
-
- /*
- * If the full read-ahead would go beyond the end of the media, trim
- * it back to read just till the end of the media.
- */
- if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
- sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
- read_size = sony_toc->lead_out_start_lba - (block / 4);
- } else {
- sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
- read_size = sony_buffer_sectors;
- }
- size_to_buf(read_size, &params[3]);
-
+
+ if (sony_toc->lead_out_start_lba <= (block / 4)) {
+ end_request(0);
+ return;
+ }
+ if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
+ end_request(0);
+ return;
+ }
+ while (0 < nsect) {
/*
- * Read the data. If the drive was not spinning,
- * spin it up and try some more.
+ * If the requested sector is not currently in the read-ahead buffer,
+ * it must be read in.
*/
- for (spin_up_retry=0 ;; ++spin_up_retry) {
- /* This loop has been modified to support the Sony
- * CDU-510/515 series, thanks to Claudio Porfiri
- * <C.Porfiri@nisms.tei.ericsson.se>.
- */
+ if ((block < sony_first_block) || (sony_last_block < block)) {
+ sony_first_block = (block / 4) * 4;
+ log_to_msf(block / 4, params);
+
/*
- * This part is to deal with very slow hardware. We
- * try at most MAX_SPINUP_RETRY times to read the same
- * block. A check for seek_and_read_N_blocks' result is
- * performed; if the result is wrong, the CDROM's engine
- * is restarted and the operation is tried again.
+ * If the full read-ahead would go beyond the end of the media, trim
+ * it back to read just till the end of the media.
*/
+ if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
+ sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
+ read_size = sony_toc->lead_out_start_lba - (block / 4);
+ } else {
+ sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
+ read_size = sony_buffer_sectors;
+ }
+ size_to_buf(read_size, &params[3]);
+
/*
- * 1995-06-01: The system got problems when downloading
- * from Slackware CDROM, the problem seems to be:
- * seek_and_read_N_blocks returns BAD_STATUS and we
- * should wait for a while before retrying, so a new
- * part was added to discriminate the return value from
- * seek_and_read_N_blocks for the various cases.
+ * Read the data. If the drive was not spinning,
+ * spin it up and try some more.
*/
- int readStatus = seek_and_read_N_blocks(params, read_size,
- status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
- if (0 <= readStatus) /* Good data; common case, placed first */
- break;
- if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
- /* give up */
- if (readStatus == NO_ROOM)
- printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
- else
- printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
- status[0]);
- sony_first_block = -1;
- sony_last_block = -1;
- end_request(0);
- return;
- }
- if (readStatus == BAD_STATUS) {
- /* Sleep for a while, then retry */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
- }
+ for (spin_up_retry=0 ;; ++spin_up_retry) {
+ /* This loop has been modified to support the Sony
+ * CDU-510/515 series, thanks to Claudio Porfiri
+ * <C.Porfiri@nisms.tei.ericsson.se>.
+ */
+ /*
+ * This part is to deal with very slow hardware. We
+ * try at most MAX_SPINUP_RETRY times to read the same
+ * block. A check for seek_and_read_N_blocks' result is
+ * performed; if the result is wrong, the CDROM's engine
+ * is restarted and the operation is tried again.
+ */
+ /*
+ * 1995-06-01: The system got problems when downloading
+ * from Slackware CDROM, the problem seems to be:
+ * seek_and_read_N_blocks returns BAD_STATUS and we
+ * should wait for a while before retrying, so a new
+ * part was added to discriminate the return value from
+ * seek_and_read_N_blocks for the various cases.
+ */
+ int readStatus = seek_and_read_N_blocks(params, read_size,
+ status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
+ if (0 <= readStatus) /* Good data; common case, placed first */
+ break;
+ if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
+ /* give up */
+ if (readStatus == NO_ROOM)
+ printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
+ else
+ printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
+ status[0]);
+ sony_first_block = -1;
+ sony_last_block = -1;
+ end_request(0);
+ return;
+ }
+ if (readStatus == BAD_STATUS) {
+ /* Sleep for a while, then retry */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
+ }
#if DEBUG > 0
- printk(CDU535_MESSAGE_NAME
- " debug: calling spin up when reading data!\n");
+ printk(CDU535_MESSAGE_NAME
+ " debug: calling spin up when reading data!\n");
#endif
- cmd[0] = SONY535_SPIN_UP;
- do_sony_cmd(cmd, 1, status, NULL, 0, 0);
+ cmd[0] = SONY535_SPIN_UP;
+ do_sony_cmd(cmd, 1, status, NULL, 0, 0);
+ }
}
+ /*
+ * The data is in memory now, copy it to the buffer and advance to the
+ * next block to read.
+ */
+ copyoff = block - sony_first_block;
+ memcpy(CURRENT->buffer,
+ sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
+
+ block += 1;
+ nsect -= 1;
+ CURRENT->buffer += 512;
}
- /*
- * The data is in memory now, copy it to the buffer and advance to the
- * next block to read.
- */
- copyoff = block - sony_first_block;
- memcpy(CURRENT->buffer,
- sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
- block += 1;
- nsect -= 1;
- CURRENT->buffer += 512;
+ end_request(1);
+ break;
+
+ case WRITE:
+ end_request(0);
+ break;
+
+ default:
+ panic("Unknown SONY CD cmd");
}
-
- end_request(1);
- break;
-
- case WRITE:
- end_request(0);
- break;
-
- default:
- panic("Unknown SONY CD cmd");
}
}
}
-
/*
* Read the table of contents from the drive and set sony_toc_read if
* successful.
@@ -1086,7 +1089,7 @@ cdu_ioctl(struct inode *inode,
if (!inode) {
return -EINVAL;
}
- dev = MINOR(inode->i_rdev) >> 6;
+ dev = minor(inode->i_rdev) >> 6;
if (dev != 0) {
return -EINVAL;
}
@@ -1593,7 +1596,7 @@ sony535_init(void)
MAJOR_NR, CDU535_MESSAGE_NAME);
return -EIO;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST, &sonycd535_lock);
blksize_size[MAJOR_NR] = &sonycd535_block_size;
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
@@ -1641,7 +1644,7 @@ sony535_init(void)
return -EIO;
}
request_region(sony535_cd_base_io, 4, CDU535_HANDLE);
- register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &cdu_fops, 0);
+ register_disk(NULL, mk_kdev(MAJOR_NR,0), 1, &cdu_fops, 0);
return 0;
}
diff --git a/drivers/char/Config.in b/drivers/char/Config.in
index bbed2582b..eed80ec1a 100644
--- a/drivers/char/Config.in
+++ b/drivers/char/Config.in
@@ -16,7 +16,7 @@ if [ "$CONFIG_SERIAL" = "y" ]; then
tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
fi
fi
-if [ "$CONFIG_ACPI" = "y" ]; then
+if [ "$CONFIG_ACPI" = "y" -a "$CONFIG_IA64" = "y" ]; then
bool ' Support for serial ports defined by ACPI tables' CONFIG_SERIAL_ACPI
fi
dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c
index 0712b3322..df2938ade 100644
--- a/drivers/char/acquirewdt.c
+++ b/drivers/char/acquirewdt.c
@@ -117,7 +117,7 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static int acq_open(struct inode *inode, struct file *file)
{
- switch(MINOR(inode->i_rdev))
+ switch(minor(inode->i_rdev))
{
case WATCHDOG_MINOR:
spin_lock(&acq_lock);
@@ -141,7 +141,7 @@ static int acq_open(struct inode *inode, struct file *file)
static int acq_close(struct inode *inode, struct file *file)
{
- if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+ if(minor(inode->i_rdev)==WATCHDOG_MINOR)
{
spin_lock(&acq_lock);
#ifndef CONFIG_WATCHDOG_NOWAYOUT
diff --git a/drivers/char/advantechwdt.c b/drivers/char/advantechwdt.c
index dfb2663ec..b40df81ce 100644
--- a/drivers/char/advantechwdt.c
+++ b/drivers/char/advantechwdt.c
@@ -128,7 +128,7 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static int
advwdt_open(struct inode *inode, struct file *file)
{
- switch (MINOR(inode->i_rdev)) {
+ switch (minor(inode->i_rdev)) {
case WATCHDOG_MINOR:
spin_lock(&advwdt_lock);
if (advwdt_is_open) {
@@ -151,7 +151,7 @@ advwdt_open(struct inode *inode, struct file *file)
static int
advwdt_close(struct inode *inode, struct file *file)
{
- if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+ if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
spin_lock(&advwdt_lock);
#ifndef CONFIG_WATCHDOG_NOWAYOUT
inb_p(WDT_STOP);
diff --git a/drivers/char/agp/agpgart_fe.c b/drivers/char/agp/agpgart_fe.c
index 44eb6b755..2c6b9f9a5 100644
--- a/drivers/char/agp/agpgart_fe.c
+++ b/drivers/char/agp/agpgart_fe.c
@@ -694,7 +694,7 @@ static int agp_release(struct inode *inode, struct file *file)
static int agp_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
agp_file_private *priv;
agp_client *client;
int rc = -ENXIO;
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 32732dbcc..6a403e772 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1904,7 +1904,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
unsigned long page;
MOD_INC_USE_COUNT;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS)) {
MOD_DEC_USE_COUNT;
return -ENODEV;
@@ -2328,7 +2328,7 @@ static int serial_console_wait_key(struct console *co)
static kdev_t serial_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, 64);
+ return mk_kdev(TTY_MAJOR, 64);
}
static struct console sercons = {
diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c
index 95a66df49..c5ec68e38 100644
--- a/drivers/char/busmouse.c
+++ b/drivers/char/busmouse.c
@@ -51,7 +51,7 @@ struct busmouse_data {
#define NR_MICE 15
#define FIRST_MOUSE 0
-#define DEV_TO_MOUSE(dev) MINOR_TO_MOUSE(MINOR(dev))
+#define DEV_TO_MOUSE(dev) MINOR_TO_MOUSE(minor(dev))
#define MINOR_TO_MOUSE(minor) ((minor) - FIRST_MOUSE)
/*
diff --git a/drivers/char/console.c b/drivers/char/console.c
index e4247143f..6565004c8 100644
--- a/drivers/char/console.c
+++ b/drivers/char/console.c
@@ -2171,14 +2171,13 @@ quit:
static kdev_t vt_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, c->index ? c->index : fg_console + 1);
+ return mk_kdev(TTY_MAJOR, c->index ? c->index : fg_console + 1);
}
struct console vt_console_driver = {
name: "tty",
write: vt_console_print,
device: vt_console_device,
- wait_key: keyboard_wait_for_keypress,
unblank: unblank_screen,
flags: CON_PRINTBUFFER,
index: -1,
@@ -2326,7 +2325,7 @@ static void con_stop(struct tty_struct *tty)
int console_num;
if (!tty)
return;
- console_num = MINOR(tty->device) - (tty->driver.minor_start);
+ console_num = minor(tty->device) - (tty->driver.minor_start);
if (!vc_cons_allocated(console_num))
return;
set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
@@ -2341,7 +2340,7 @@ static void con_start(struct tty_struct *tty)
int console_num;
if (!tty)
return;
- console_num = MINOR(tty->device) - (tty->driver.minor_start);
+ console_num = minor(tty->device) - (tty->driver.minor_start);
if (!vc_cons_allocated(console_num))
return;
clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
@@ -2369,7 +2368,7 @@ static int con_open(struct tty_struct *tty, struct file * filp)
unsigned int currcons;
int i;
- currcons = MINOR(tty->device) - tty->driver.minor_start;
+ currcons = minor(tty->device) - tty->driver.minor_start;
i = vc_allocate(currcons);
if (i)
@@ -2392,7 +2391,7 @@ static void con_close(struct tty_struct *tty, struct file * filp)
if (!tty)
return;
if (tty->count != 1) return;
- vcs_make_devfs (MINOR (tty->device) - tty->driver.minor_start, 1);
+ vcs_make_devfs (minor(tty->device) - tty->driver.minor_start, 1);
tty->driver_data = 0;
}
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index edf5db8e1..47f973633 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2591,7 +2591,7 @@ cy_open(struct tty_struct *tty, struct file * filp)
unsigned long page;
MOD_INC_USE_COUNT;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (NR_PORTS <= line)){
MOD_DEC_USE_COUNT;
return -ENODEV;
diff --git a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h
index a4ee2537f..c7a9a45ad 100644
--- a/drivers/char/drm/drm_drv.h
+++ b/drivers/char/drm/drm_drv.h
@@ -719,7 +719,7 @@ int DRM(open)( struct inode *inode, struct file *filp )
int i;
for (i = 0; i < DRM(numdevs); i++) {
- if (MINOR(inode->i_rdev) == DRM(minor)[i]) {
+ if (minor(inode->i_rdev) == DRM(minor)[i]) {
dev = &(DRM(device)[i]);
break;
}
diff --git a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h
index 3656c5e9c..ec88ad27e 100644
--- a/drivers/char/drm/drm_fops.h
+++ b/drivers/char/drm/drm_fops.h
@@ -38,7 +38,7 @@
int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
{
- kdev_t minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
drm_file_t *priv;
if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
diff --git a/drivers/char/drm/drm_stub.h b/drivers/char/drm/drm_stub.h
index fe8a1bc9d..d37a01782 100644
--- a/drivers/char/drm/drm_stub.h
+++ b/drivers/char/drm/drm_stub.h
@@ -53,7 +53,7 @@ static struct drm_stub_info {
static int DRM(stub_open)(struct inode *inode, struct file *filp)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
int err = -ENODEV;
struct file_operations *old_fops;
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 9eac58218..c964b5698 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -37,7 +37,6 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/smp_lock.h>
-#include <asm/segment.h>
#include <asm/atarihw.h>
#include <asm/traps.h>
#include <asm/uaccess.h> /* For put_user and get_user */
@@ -208,7 +207,7 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- int dev = MINOR(inode->i_rdev) & 0x0f;
+ int dev = minor(inode->i_rdev) & 0x0f;
switch(dev)
{
@@ -271,7 +270,7 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- int dev = MINOR(inode->i_rdev) & 0x0f;
+ int dev = minor(inode->i_rdev) & 0x0f;
switch(dev)
{
@@ -332,7 +331,7 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
static int dsp56k_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int dev = MINOR(inode->i_rdev) & 0x0f;
+ int dev = minor(inode->i_rdev) & 0x0f;
switch(dev)
{
@@ -425,7 +424,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
#if 0
static unsigned int dsp56k_poll(struct file *file, poll_table *wait)
{
- int dev = MINOR(file->f_dentry->d_inode->i_rdev) & 0x0f;
+ int dev = minor(file->f_dentry->d_inode->i_rdev) & 0x0f;
switch(dev)
{
@@ -442,7 +441,7 @@ static unsigned int dsp56k_poll(struct file *file, poll_table *wait)
static int dsp56k_open(struct inode *inode, struct file *file)
{
- int dev = MINOR(inode->i_rdev) & 0x0f;
+ int dev = minor(inode->i_rdev) & 0x0f;
switch(dev)
{
@@ -473,7 +472,7 @@ static int dsp56k_open(struct inode *inode, struct file *file)
static int dsp56k_release(struct inode *inode, struct file *file)
{
- int dev = MINOR(inode->i_rdev) & 0x0f;
+ int dev = minor(inode->i_rdev) & 0x0f;
switch(dev)
{
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index 86299fbdc..92b0b9cdb 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -57,7 +57,6 @@
#include <linux/errno.h> /* for -EBUSY */
#include <linux/ioport.h> /* for check_region, request_region */
#include <linux/delay.h> /* for loops_per_jiffy */
-#include <asm/segment.h> /* for put_user_byte */
#include <asm/io.h> /* for inb_p, outb_p, inb, outb, etc. */
#include <asm/uaccess.h> /* for get_user, etc. */
#include <linux/wait.h> /* for wait_queue */
@@ -126,7 +125,7 @@ static void dtlk_timer_tick(unsigned long data);
static ssize_t dtlk_read(struct file *file, char *buf,
size_t count, loff_t * ppos)
{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
char ch;
int i = 0, retries;
@@ -186,7 +185,7 @@ static ssize_t dtlk_write(struct file *file, const char *buf,
if (ppos != &file->f_pos)
return -ESPIPE;
- if (MINOR(file->f_dentry->d_inode->i_rdev) != DTLK_MINOR)
+ if (minor(file->f_dentry->d_inode->i_rdev) != DTLK_MINOR)
return -EINVAL;
while (1) {
@@ -305,7 +304,7 @@ static int dtlk_open(struct inode *inode, struct file *file)
{
TRACE_TEXT("(dtlk_open");
- switch (MINOR(inode->i_rdev)) {
+ switch (minor(inode->i_rdev)) {
case DTLK_MINOR:
if (dtlk_busy)
return -EBUSY;
@@ -320,7 +319,7 @@ static int dtlk_release(struct inode *inode, struct file *file)
{
TRACE_TEXT("(dtlk_release");
- switch (MINOR(inode->i_rdev)) {
+ switch (minor(inode->i_rdev)) {
case DTLK_MINOR:
break;
diff --git a/drivers/char/dz.c b/drivers/char/dz.c
index 431e0fb34..0bc5f605a 100644
--- a/drivers/char/dz.c
+++ b/drivers/char/dz.c
@@ -75,7 +75,6 @@ extern int (*prom_printf) (char *,...);
DECLARE_TASK_QUEUE(tq_serial);
-extern wait_queue_head_t keypress_wait;
static struct dz_serial *lines[4];
static unsigned char tmp_buffer[256];
@@ -228,8 +227,6 @@ static inline void receive_chars (struct dz_serial *info_in)
if (info->is_console) {
if (ch == 0)
return; /* it's a break ... */
-
- wake_up (&keypress_wait); /* It is a 'keyboard interrupt' ;-) */
}
#endif
@@ -1276,7 +1273,7 @@ static int dz_open (struct tty_struct *tty, struct file *filp)
struct dz_serial *info;
int retval, line;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
/*
* The dz lines for the mouse/keyboard must be opened using their
@@ -1509,14 +1506,9 @@ static void dz_console_print (struct console *cons,
}
}
-static int dz_console_wait_key(struct console *co)
-{
- return 0;
-}
-
static kdev_t dz_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, 64 + c->index);
+ return mk_kdev(TTY_MAJOR, 64 + c->index);
}
static int __init dz_console_setup(struct console *co, char *options)
@@ -1614,7 +1606,6 @@ static struct console dz_sercons = {
name: "ttyS",
write: dz_console_print,
device: dz_console_device,
- wait_key: dz_console_wait_key,
setup: dz_console_setup,
flags: CON_CONSDEV | CON_PRINTBUFFER,
index: CONSOLE_LINE,
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index b90007a46..21f270d0d 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -897,7 +897,6 @@ static int pc_write(struct tty_struct * tty, int from_user,
inline void copy_from_user(void * to, const void * from,
unsigned long count);
- You must include <asm/segment.h>
I also think (Check hackers guide) that optimization must
be turned ON. (Which sounds strange to me...)
@@ -1385,7 +1384,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
return (0) ;
}
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if (line < 0 || line >= nbdevs)
{
printk(KERN_ERR "<Error> - pc_open : line out of range in pc_open\n");
@@ -2896,7 +2895,7 @@ static void receive_data(struct channel *ch)
if (bc->orun)
{
bc->orun = 0;
- printk(KERN_WARNING "overrun! DigiBoard device minor = %d\n",MINOR(tty->device));
+ printk(KERN_WARNING "overrun! DigiBoard device minor = %d\n",minor(tty->device));
}
rxwinon(ch);
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 073b28078..97f842cb2 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -60,7 +60,6 @@
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/dma.h>
@@ -2355,7 +2354,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
struct esp_struct *info;
int retval, line;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS))
return -ENODEV;
diff --git a/drivers/char/eurotechwdt.c b/drivers/char/eurotechwdt.c
index 3774c85aa..2907315b6 100644
--- a/drivers/char/eurotechwdt.c
+++ b/drivers/char/eurotechwdt.c
@@ -280,7 +280,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
static int eurwdt_open(struct inode *inode, struct file *file)
{
- switch (MINOR(inode->i_rdev)) {
+ switch (minor(inode->i_rdev)) {
case WATCHDOG_MINOR:
spin_lock(&eurwdt_lock);
if (eurwdt_is_open) {
@@ -322,7 +322,7 @@ static int eurwdt_open(struct inode *inode, struct file *file)
static int eurwdt_release(struct inode *inode, struct file *file)
{
- if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+ if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
#ifndef CONFIG_WATCHDOG_NOWAYOUT
eurwdt_disable_timer();
#endif
diff --git a/drivers/char/ftape/lowlevel/ftape-buffer.c b/drivers/char/ftape/lowlevel/ftape-buffer.c
index a18b86817..41da6cb17 100644
--- a/drivers/char/ftape/lowlevel/ftape-buffer.c
+++ b/drivers/char/ftape/lowlevel/ftape-buffer.c
@@ -24,7 +24,6 @@
* buffer.
*/
-#include <asm/segment.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
diff --git a/drivers/char/ftape/lowlevel/ftape-io.c b/drivers/char/ftape/lowlevel/ftape-io.c
index c13b8e3c8..bd3b2f117 100644
--- a/drivers/char/ftape/lowlevel/ftape-io.c
+++ b/drivers/char/ftape/lowlevel/ftape-io.c
@@ -29,7 +29,6 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/ioctl.h>
#include <linux/mtio.h>
diff --git a/drivers/char/ftape/lowlevel/ftape-read.c b/drivers/char/ftape/lowlevel/ftape-read.c
index e67f099fe..03d24e743 100644
--- a/drivers/char/ftape/lowlevel/ftape-read.c
+++ b/drivers/char/ftape/lowlevel/ftape-read.c
@@ -29,7 +29,6 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/mm.h>
-#include <asm/segment.h>
#include <linux/ftape.h>
#include <linux/qic117.h>
diff --git a/drivers/char/ftape/lowlevel/ftape-setup.c b/drivers/char/ftape/lowlevel/ftape-setup.c
index 1c590fde3..98aa1d6d3 100644
--- a/drivers/char/ftape/lowlevel/ftape-setup.c
+++ b/drivers/char/ftape/lowlevel/ftape-setup.c
@@ -29,7 +29,6 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/mm.h>
-#include <asm/segment.h>
#include <linux/ftape.h>
#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,16)
diff --git a/drivers/char/ftape/lowlevel/ftape-write.c b/drivers/char/ftape/lowlevel/ftape-write.c
index c4cb18779..45601ec80 100644
--- a/drivers/char/ftape/lowlevel/ftape-write.c
+++ b/drivers/char/ftape/lowlevel/ftape-write.c
@@ -28,7 +28,6 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/mm.h>
-#include <asm/segment.h>
#include <linux/ftape.h>
#include <linux/qic117.h>
diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c
index 58197e429..563f5d7c0 100644
--- a/drivers/char/ftape/zftape/zftape-buffers.c
+++ b/drivers/char/ftape/zftape/zftape-buffers.c
@@ -27,7 +27,6 @@
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#include <asm/segment.h>
#include <linux/zftape.h>
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index ee5e51fe0..bd5edce22 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -25,7 +25,6 @@
#include <linux/errno.h>
#include <linux/version.h>
#include <linux/fs.h>
-#include <asm/segment.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/major.h>
@@ -113,11 +112,11 @@ static int zft_open(struct inode *ino, struct file *filep)
int result;
TRACE_FUN(ft_t_flow);
- TRACE(ft_t_flow, "called for minor %d", MINOR(ino->i_rdev));
+ TRACE(ft_t_flow, "called for minor %d", minor(ino->i_rdev));
if ( test_and_set_bit(0,&busy_flag) ) {
TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
}
- if ((MINOR(ino->i_rdev) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
+ if ((minor(ino->i_rdev) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
>
FTAPE_SEL_D) {
clear_bit(0,&busy_flag);
@@ -125,7 +124,7 @@ static int zft_open(struct inode *ino, struct file *filep)
}
orig_sigmask = current->blocked;
sigfillset(&current->blocked);
- result = _zft_open(MINOR(ino->i_rdev), filep->f_flags & O_ACCMODE);
+ result = _zft_open(minor(ino->i_rdev), filep->f_flags & O_ACCMODE);
if (result < 0) {
current->blocked = orig_sigmask; /* restore mask */
clear_bit(0,&busy_flag);
@@ -147,7 +146,7 @@ static int zft_close(struct inode *ino, struct file *filep)
int result;
TRACE_FUN(ft_t_flow);
- if ( !test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit) {
+ if ( !test_bit(0,&busy_flag) || minor(ino->i_rdev) != zft_unit) {
TRACE(ft_t_err, "failed: not busy or wrong unit");
TRACE_EXIT 0;
}
@@ -170,7 +169,7 @@ static int zft_ioctl(struct inode *ino, struct file *filep,
sigset_t old_sigmask;
TRACE_FUN(ft_t_flow);
- if ( !test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+ if ( !test_bit(0,&busy_flag) || minor(ino->i_rdev) != zft_unit || ft_failure) {
TRACE_ABORT(-EIO, ft_t_err,
"failed: not busy, failure or wrong unit");
}
@@ -191,7 +190,7 @@ static int zft_mmap(struct file *filep, struct vm_area_struct *vma)
TRACE_FUN(ft_t_flow);
if ( !test_bit(0,&busy_flag) ||
- MINOR(filep->f_dentry->d_inode->i_rdev) != zft_unit ||
+ minor(filep->f_dentry->d_inode->i_rdev) != zft_unit ||
ft_failure)
{
TRACE_ABORT(-EIO, ft_t_err,
@@ -220,7 +219,7 @@ static ssize_t zft_read(struct file *fp, char *buff,
TRACE_FUN(ft_t_flow);
TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
- if (!test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+ if (!test_bit(0,&busy_flag) || minor(ino->i_rdev) != zft_unit || ft_failure) {
TRACE_ABORT(-EIO, ft_t_err,
"failed: not busy, failure or wrong unit");
}
@@ -243,7 +242,7 @@ static ssize_t zft_write(struct file *fp, const char *buff,
TRACE_FUN(ft_t_flow);
TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
- if (!test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+ if (!test_bit(0,&busy_flag) || minor(ino->i_rdev) != zft_unit || ft_failure) {
TRACE_ABORT(-EIO, ft_t_err,
"failed: not busy, failure or wrong unit");
}
diff --git a/drivers/char/ftape/zftape/zftape-rw.c b/drivers/char/ftape/zftape/zftape-rw.c
index 9e599530c..4ff2548c5 100644
--- a/drivers/char/ftape/zftape/zftape-rw.c
+++ b/drivers/char/ftape/zftape/zftape-rw.c
@@ -27,7 +27,6 @@
#include <linux/config.h> /* for CONFIG_ZFT_DFLT_BLK_SZ */
#include <linux/errno.h>
#include <linux/mm.h>
-#include <asm/segment.h>
#include <linux/zftape.h>
#include "../zftape/zftape-init.h"
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.c b/drivers/char/ftape/zftape/zftape-vtbl.c
index 8e2e0a2fb..8416be38e 100644
--- a/drivers/char/ftape/zftape/zftape-vtbl.c
+++ b/drivers/char/ftape/zftape/zftape-vtbl.c
@@ -31,7 +31,6 @@
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#include <asm/segment.h>
#include <linux/zftape.h>
#include "../zftape/zftape-init.h"
diff --git a/drivers/char/h8.c b/drivers/char/h8.c
index 611d2b5d4..438e44da7 100644
--- a/drivers/char/h8.c
+++ b/drivers/char/h8.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/types.h>
diff --git a/drivers/char/ib700wdt.c b/drivers/char/ib700wdt.c
index 51d8fdeb5..91fb96ca5 100644
--- a/drivers/char/ib700wdt.c
+++ b/drivers/char/ib700wdt.c
@@ -155,7 +155,7 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static int
ibwdt_open(struct inode *inode, struct file *file)
{
- switch (MINOR(inode->i_rdev)) {
+ switch (minor(inode->i_rdev)) {
case WATCHDOG_MINOR:
spin_lock(&ibwdt_lock);
if (ibwdt_is_open) {
@@ -179,7 +179,7 @@ static int
ibwdt_close(struct inode *inode, struct file *file)
{
lock_kernel();
- if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+ if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
spin_lock(&ibwdt_lock);
#ifndef CONFIG_WATCHDOG_NOWAYOUT
outb_p(WD_TIMO, WDT_STOP);
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index f46f5c6a7..cf5ebb306 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -142,7 +142,6 @@
// so blame them.
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,4)
-# include <asm/segment.h>
# define GET_USER(error,value,addr) error = get_user(value,addr)
# define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
# define PUT_USER(error,value,addr) error = put_user(value,addr)
@@ -1590,9 +1589,9 @@ ip2_open( PTTY tty, struct file *pFile )
wait_queue_t wait;
int rc = 0;
int do_clocal = 0;
- i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
+ i2ChanStrPtr pCh = DevTable[minor(tty->device)];
- ip2trace (MINOR(tty->device), ITRC_OPEN, ITRC_ENTER, 0 );
+ ip2trace (minor(tty->device), ITRC_OPEN, ITRC_ENTER, 0 );
if ( pCh == NULL ) {
return -ENODEV;
@@ -1605,7 +1604,7 @@ ip2_open( PTTY tty, struct file *pFile )
#ifdef IP2DEBUG_OPEN
printk(KERN_DEBUG \
"IP2:open(tty=%p,pFile=%p):dev=%x,maj=%d,min=%d,ch=%d,idx=%d\n",
- tty, pFile, tty->device, MAJOR(tty->device), MINOR(tty->device),
+ tty, pFile, tty->device, major(tty->device), minor(tty->device),
pCh->infl.hd.i2sChannel, pCh->port_index);
open_sanity_check ( pCh, pCh->pMyBord );
#endif
@@ -1797,7 +1796,7 @@ ip2_close( PTTY tty, struct file *pFile )
ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
#ifdef IP2DEBUG_OPEN
- printk(KERN_DEBUG "IP2:close ttyF%02X:\n",MINOR(tty->device));
+ printk(KERN_DEBUG "IP2:close ttyF%02X:\n",minor(tty->device));
#endif
if ( tty_hung_up_p ( pFile ) ) {
@@ -2206,7 +2205,7 @@ ip2_unthrottle ( PTTY tty )
static void
ip2_start ( PTTY tty )
{
- i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
+ i2ChanStrPtr pCh = DevTable[minor(tty->device)];
i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
@@ -2219,7 +2218,7 @@ ip2_start ( PTTY tty )
static void
ip2_stop ( PTTY tty )
{
- i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
+ i2ChanStrPtr pCh = DevTable[minor(tty->device)];
i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
#ifdef IP2DEBUG_WRITE
@@ -2247,7 +2246,7 @@ static int
ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
{
wait_queue_t wait;
- i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
+ i2ChanStrPtr pCh = DevTable[minor(tty->device)];
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct *p_cuser; /* user space */
int rc = 0;
@@ -3011,12 +3010,12 @@ static
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
int
ip2_ipl_read(struct inode *pInode, char *pData, size_t count, loff_t *off )
- unsigned int minor = MINOR( pInode->i_rdev );
+ unsigned int minor = minor( pInode->i_rdev );
#else
ssize_t
ip2_ipl_read(struct file *pFile, char *pData, size_t count, loff_t *off )
{
- unsigned int minor = MINOR( pFile->f_dentry->d_inode->i_rdev );
+ unsigned int minor = minor( pFile->f_dentry->d_inode->i_rdev );
#endif
int rc = 0;
@@ -3147,7 +3146,7 @@ ip2_ipl_write(struct file *pFile, const char *pData, size_t count, loff_t *off)
static int
ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
{
- unsigned int iplminor = MINOR(pInode->i_rdev);
+ unsigned int iplminor = minor(pInode->i_rdev);
int rc = 0;
ULONG *pIndex = (ULONG*)arg;
i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
@@ -3282,7 +3281,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
static int
ip2_ipl_open( struct inode *pInode, struct file *pFile )
{
- unsigned int iplminor = MINOR(pInode->i_rdev);
+ unsigned int iplminor = minor(pInode->i_rdev);
i2eBordStrPtr pB;
i2ChanStrPtr pCh;
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index bc070a90d..7ed6b1173 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -51,7 +51,6 @@
#include <linux/timer.h>
#include <linux/ioport.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -1022,7 +1021,7 @@ static int isicom_open(struct tty_struct * tty, struct file * filp)
#ifdef ISICOM_DEBUG
printk(KERN_DEBUG "ISICOM: open start!!!.\n");
#endif
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
#ifdef ISICOM_DEBUG
printk(KERN_DEBUG "line = %d.\n", line);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index b41f1770d..e50dd36f4 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -1034,7 +1034,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
(int) filp, tty->device);
#endif
- minordev = MINOR(tty->device);
+ minordev = minor(tty->device);
brdnr = MINOR2BRD(minordev);
if (brdnr >= stli_nrbrds)
return(-ENODEV);
@@ -4859,7 +4859,7 @@ static ssize_t stli_memread(struct file *fp, char *buf, size_t count, loff_t *of
(int) fp, (int) buf, count, (int) offp);
#endif
- brdnr = MINOR(fp->f_dentry->d_inode->i_rdev);
+ brdnr = minor(fp->f_dentry->d_inode->i_rdev);
if (brdnr >= stli_nrbrds)
return(-ENODEV);
brdp = stli_brds[brdnr];
@@ -4910,7 +4910,7 @@ static ssize_t stli_memwrite(struct file *fp, const char *buf, size_t count, lof
(int) fp, (int) buf, count, (int) offp);
#endif
- brdnr = MINOR(fp->f_dentry->d_inode->i_rdev);
+ brdnr = minor(fp->f_dentry->d_inode->i_rdev);
if (brdnr >= stli_nrbrds)
return(-ENODEV);
brdp = stli_brds[brdnr];
@@ -5247,7 +5247,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
* Now handle the board specific ioctls. These all depend on the
* minor number of the device they were called from.
*/
- brdnr = MINOR(ip->i_rdev);
+ brdnr = minor(ip->i_rdev);
if (brdnr >= STL_MAXBRDS)
return(-ENODEV);
brdp = stli_brds[brdnr];
diff --git a/drivers/char/ite_gpio.c b/drivers/char/ite_gpio.c
index 1029ba80e..a886720db 100644
--- a/drivers/char/ite_gpio.c
+++ b/drivers/char/ite_gpio.c
@@ -238,7 +238,7 @@ EXPORT_SYMBOL(ite_gpio_int_wait);
static int ite_gpio_open(struct inode *inode, struct file *file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
if (minor != GPIO_MINOR)
return -ENODEV;
diff --git a/drivers/char/joystick/serport.c b/drivers/char/joystick/serport.c
index 51e67edf1..efe94e679 100644
--- a/drivers/char/joystick/serport.c
+++ b/drivers/char/joystick/serport.c
@@ -149,9 +149,9 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
char name[32];
#ifdef CONFIG_DEVFS_FS
- sprintf(name, tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
+ sprintf(name, tty->driver.name, minor(tty->device) - tty->driver.minor_start);
#else
- sprintf(name, "%s%d", tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
+ sprintf(name, "%s%d", tty->driver.name, minor(tty->device) - tty->driver.minor_start);
#endif
serio_register_port(&serport->serio);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 0b8fe7d6d..9ede4e069 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -67,15 +67,8 @@ EXPORT_SYMBOL(kbd_ledfunc);
extern void ctrl_alt_del(void);
-DECLARE_WAIT_QUEUE_HEAD(keypress_wait);
struct console;
-int keyboard_wait_for_keypress(struct console *co)
-{
- sleep_on(&keypress_wait);
- return 0;
-}
-
/*
* global state includes the following, and various static variables
* in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
@@ -334,7 +327,6 @@ out:
void put_queue(int ch)
{
- wake_up(&keypress_wait);
if (tty) {
tty_insert_flip_char(tty, ch, 0);
con_schedule_flip(tty);
@@ -343,7 +335,6 @@ void put_queue(int ch)
static void puts_queue(char *cp)
{
- wake_up(&keypress_wait);
if (!tty)
return;
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index e4c0130c7..4c0acc344 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -294,7 +294,7 @@ static int lp_wait_ready(int minor)
static ssize_t lp_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
struct parport *port = lp_table[minor].dev->port;
char *kbuf = lp_table[minor].lp_buffer;
ssize_t retv = 0;
@@ -403,7 +403,7 @@ static ssize_t lp_write(struct file * file, const char * buf,
static ssize_t lp_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
- unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev);
+ unsigned int minor=minor(file->f_dentry->d_inode->i_rdev);
struct parport *port = lp_table[minor].dev->port;
ssize_t retval = 0;
char *kbuf = lp_table[minor].lp_buffer;
@@ -430,7 +430,7 @@ static ssize_t lp_read(struct file * file, char * buf,
static int lp_open(struct inode * inode, struct file * file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
if (minor >= LP_NO)
return -ENXIO;
@@ -488,7 +488,7 @@ static int lp_open(struct inode * inode, struct file * file)
static int lp_release(struct inode * inode, struct file * file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
lp_claim_parport_or_block (&lp_table[minor]);
parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
@@ -503,7 +503,7 @@ static int lp_release(struct inode * inode, struct file * file)
static int lp_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
int status;
int retval = 0;
@@ -683,7 +683,7 @@ static void lp_console_write (struct console *co, const char *s,
static kdev_t lp_console_device (struct console *c)
{
- return MKDEV(LP_MAJOR, CONSOLE_LP);
+ return mk_kdev(LP_MAJOR, CONSOLE_LP);
}
static struct console lpcons = {
diff --git a/drivers/char/machzwd.c b/drivers/char/machzwd.c
index 75a3b7470..8765b677a 100644
--- a/drivers/char/machzwd.c
+++ b/drivers/char/machzwd.c
@@ -378,7 +378,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static int zf_open(struct inode *inode, struct file *file)
{
- switch(MINOR(inode->i_rdev)){
+ switch(minor(inode->i_rdev)){
case WATCHDOG_MINOR:
spin_lock(&zf_lock);
if(zf_is_open){
@@ -403,7 +403,7 @@ static int zf_open(struct inode *inode, struct file *file)
static int zf_close(struct inode *inode, struct file *file)
{
- if(MINOR(inode->i_rdev) == WATCHDOG_MINOR){
+ if(minor(inode->i_rdev) == WATCHDOG_MINOR){
if(zf_expect_close){
zf_timer_off();
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 7ff82d118..e35edd69a 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -574,7 +574,7 @@ static struct file_operations full_fops = {
static int memory_open(struct inode * inode, struct file * filp)
{
- switch (MINOR(inode->i_rdev)) {
+ switch (minor(inode->i_rdev)) {
case 1:
filp->f_op = &mem_fops;
break;
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index ed17f3f29..bb45e919f 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -104,7 +104,7 @@ static int misc_read_proc(char *buf, char **start, off_t offset,
static int misc_open(struct inode * inode, struct file * file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct miscdevice *c;
int err = -ENODEV;
struct file_operations *old_fops, *new_fops = NULL;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index a128aad23..f341ceed8 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -53,7 +53,6 @@
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
@@ -190,7 +189,7 @@ static struct mxser_mstatus GMStatus[MAX_PORTS];
#define WAKEUP_CHARS 256
-#define PORTNO(x) (MINOR((x)->device) - (x)->driver.minor_start)
+#define PORTNO(x) (minor((x)->device) - (x)->driver.minor_start)
static int verbose = 0;
static int ttymajor = MOXAMAJOR;
@@ -649,7 +648,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
}
if (--ch->count < 0) {
printk("moxa_close: bad serial port count, minor=%d\n",
- MINOR(tty->device));
+ minor(tty->device));
ch->count = 0;
}
if (ch->count) {
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 1d75c4582..12a0fd3cc 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -58,7 +58,6 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
@@ -92,7 +91,7 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
-#define PORTNO(x) (MINOR((x)->device) - (x)->driver.minor_start)
+#define PORTNO(x) (minor((x)->device) - (x)->driver.minor_start)
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 5c81013da..6058bf878 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -112,7 +112,6 @@
#include <linux/kerneld.h>
#endif
-#include <asm/segment.h>
#define GET_USER(error,value,addr) error = get_user(value,addr)
#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
#define PUT_USER(error,value,addr) error = put_user(value,addr)
@@ -328,7 +327,7 @@ static int n_hdlc_tty_open (struct tty_struct *tty)
if (debuglevel >= DEBUG_LEVEL_INFO)
printk("%s(%d)n_hdlc_tty_open() called (major=%u,minor=%u)\n",
__FILE__,__LINE__,
- MAJOR(tty->device), MINOR(tty->device));
+ major(tty->device), minor(tty->device));
/* There should not be an existing table for this slot. */
if (n_hdlc) {
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 9f3bff5c8..815e8bb6d 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -45,8 +45,8 @@
#include <asm/system.h>
#include <asm/bitops.h>
-#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
-#define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1)
+#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0))
+#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1))
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -955,8 +955,8 @@ do_it_again:
/* NOTE: not yet done after every sleep pending a thorough
check of the logic of this change. -- jlc */
/* don't stop on /dev/console */
- if (file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
- file->f_dentry->d_inode->i_rdev != SYSCONS_DEV &&
+ if (!IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) &&
+ !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev) &&
current->tty == tty) {
if (tty->pgrp <= 0)
printk("read_chan: tty->pgrp <= 0!\n");
@@ -1135,8 +1135,8 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
/* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
if (L_TOSTOP(tty) &&
- file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
- file->f_dentry->d_inode->i_rdev != SYSCONS_DEV) {
+ !IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) &&
+ !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev)) {
retval = tty_check_change(tty);
if (retval)
return retval;
diff --git a/drivers/char/pc110pad.c b/drivers/char/pc110pad.c
index 9a9020ac7..51442e64d 100644
--- a/drivers/char/pc110pad.c
+++ b/drivers/char/pc110pad.c
@@ -590,7 +590,7 @@ static int close_pad(struct inode * inode, struct file * file)
spin_lock_irqsave(&pc110_lock, flags);
if (!--active_count)
outb(0x30, current_params.io+2); /* switch off digitiser */
- spin_unlock_irqrestore(&active_lock, flags);
+ spin_unlock_irqrestore(&pc110_lock, flags);
return 0;
}
diff --git a/drivers/char/pcwd.c b/drivers/char/pcwd.c
index c85da8a94..a0d4bdc29 100644
--- a/drivers/char/pcwd.c
+++ b/drivers/char/pcwd.c
@@ -400,7 +400,7 @@ static ssize_t pcwd_write(struct file *file, const char *buf, size_t len,
static int pcwd_open(struct inode *ino, struct file *filep)
{
- switch (MINOR(ino->i_rdev))
+ switch (minor(ino->i_rdev))
{
case WATCHDOG_MINOR:
if ( !atomic_dec_and_test(&open_allowed) )
@@ -433,7 +433,7 @@ static ssize_t pcwd_read(struct file *file, char *buf, size_t count,
/* Can't seek (pread) on this device */
if (ppos != &file->f_pos)
return -ESPIPE;
- switch(MINOR(file->f_dentry->d_inode->i_rdev))
+ switch(minor(file->f_dentry->d_inode->i_rdev))
{
case TEMP_MINOR:
/*
@@ -453,7 +453,7 @@ static ssize_t pcwd_read(struct file *file, char *buf, size_t count,
static int pcwd_close(struct inode *ino, struct file *filep)
{
- if (MINOR(ino->i_rdev)==WATCHDOG_MINOR)
+ if (minor(ino->i_rdev)==WATCHDOG_MINOR)
{
#ifndef CONFIG_WATCHDOG_NOWAYOUT
/* Disable the board */
diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c
index cce9eb64d..f246c469f 100644
--- a/drivers/char/pcxx.c
+++ b/drivers/char/pcxx.c
@@ -406,7 +406,7 @@ int pcxe_open(struct tty_struct *tty, struct file * filp)
int boardnum;
int retval;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if(line < 0 || line >= nbdevs) {
printk("line out of range in pcxe_open\n");
@@ -2080,7 +2080,7 @@ static void receive_data(struct channel *ch)
if(bc->orun) {
bc->orun = 0;
- printk("overrun! DigiBoard device minor=%d\n",MINOR(tty->device));
+ printk("overrun! DigiBoard device minor=%d\n",minor(tty->device));
}
rxwinon(ch);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 2a2dea8fa..6e976f28c 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -103,7 +103,7 @@ static inline void pp_enable_irq (struct pp_struct *pp)
static ssize_t pp_read (struct file * file, char * buf, size_t count,
loff_t * ppos)
{
- unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev);
+ unsigned int minor = minor (file->f_dentry->d_inode->i_rdev);
struct pp_struct *pp = file->private_data;
char * kbuffer;
ssize_t bytes_read = 0;
@@ -183,7 +183,7 @@ static ssize_t pp_read (struct file * file, char * buf, size_t count,
static ssize_t pp_write (struct file * file, const char * buf, size_t count,
loff_t * ppos)
{
- unsigned int minor = MINOR (file->f_dentry->d_inode->i_rdev);
+ unsigned int minor = minor (file->f_dentry->d_inode->i_rdev);
struct pp_struct *pp = file->private_data;
char * kbuffer;
ssize_t bytes_written = 0;
@@ -315,7 +315,7 @@ static enum ieee1284_phase init_phase (int mode)
static int pp_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct pp_struct *pp = file->private_data;
struct parport * port;
@@ -613,7 +613,7 @@ static int pp_ioctl(struct inode *inode, struct file *file,
static int pp_open (struct inode * inode, struct file * file)
{
- unsigned int minor = MINOR (inode->i_rdev);
+ unsigned int minor = minor (inode->i_rdev);
struct pp_struct *pp;
if (minor >= PARPORT_MAX)
@@ -642,7 +642,7 @@ static int pp_open (struct inode * inode, struct file * file)
static int pp_release (struct inode * inode, struct file * file)
{
- unsigned int minor = MINOR (inode->i_rdev);
+ unsigned int minor = minor (inode->i_rdev);
struct pp_struct *pp = file->private_data;
int compat_negot;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 2d99ea632..fc6d0fe36 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -88,14 +88,14 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
set_bit(TTY_OTHER_CLOSED, &tty->flags);
#ifdef CONFIG_UNIX98_PTYS
{
- unsigned int major = MAJOR(tty->device) - UNIX98_PTY_MASTER_MAJOR;
+ unsigned int major = major(tty->device) - UNIX98_PTY_MASTER_MAJOR;
if ( major < UNIX98_NR_MAJORS ) {
- devpts_pty_kill( MINOR(tty->device)
+ devpts_pty_kill( minor(tty->device)
- tty->driver.minor_start + tty->driver.name_base );
}
}
#endif
- tty_unregister_devfs (&tty->link->driver, MINOR (tty->device));
+ tty_unregister_devfs (&tty->link->driver, minor(tty->device));
tty_vhangup(tty->link);
}
}
@@ -239,7 +239,7 @@ static int pty_chars_in_buffer(struct tty_struct *tty)
#ifdef CONFIG_UNIX98_PTYS
static int pty_get_device_number(struct tty_struct *tty, unsigned int *value)
{
- unsigned int result = MINOR(tty->device)
+ unsigned int result = minor(tty->device)
- tty->driver.minor_start + tty->driver.name_base;
return put_user(result, value);
}
@@ -314,7 +314,7 @@ static int pty_open(struct tty_struct *tty, struct file * filp)
retval = -ENODEV;
if (!tty || !tty->link)
goto out;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PTYS))
goto out;
pty = (struct pty_struct *)(tty->driver.driver_state) + line;
@@ -336,7 +336,7 @@ static int pty_open(struct tty_struct *tty, struct file * filp)
tty_register_devfs(&tty->link->driver,
DEVFS_FL_CURRENT_OWNER | DEVFS_FL_WAIT,
tty->link->driver.minor_start +
- MINOR(tty->device)-tty->driver.minor_start);
+ minor(tty->device)-tty->driver.minor_start);
retval = 0;
out:
return retval;
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index e9a963319..79b5dfebb 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -74,7 +74,7 @@ int raw_open(struct inode *inode, struct file *filp)
int sector_size;
int sector_bits;
- minor = MINOR(inode->i_rdev);
+ minor = minor(inode->i_rdev);
/*
* Is it the control device?
@@ -117,21 +117,8 @@ int raw_open(struct inode *inode, struct file *filp)
if (raw_devices[minor].inuse++)
goto out;
- /*
- * Don't interfere with mounted devices: we cannot safely set
- * the blocksize on a device which is already mounted.
- */
-
- sector_size = 512;
- if (is_mounted(rdev)) {
- if (blksize_size[MAJOR(rdev)])
- sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];
- } else
- sector_size = get_hardsect_size(rdev);
-
- set_blocksize(rdev, sector_size);
+ sector_size = get_hardsect_size(rdev);
raw_devices[minor].sector_size = sector_size;
-
for (sector_bits = 0; !(sector_size & 1); )
sector_size>>=1, sector_bits++;
raw_devices[minor].sector_bits = sector_bits;
@@ -147,7 +134,7 @@ int raw_release(struct inode *inode, struct file *filp)
int minor;
struct block_device *bdev;
- minor = MINOR(inode->i_rdev);
+ minor = minor(inode->i_rdev);
down(&raw_devices[minor].mutex);
bdev = raw_devices[minor].binding;
raw_devices[minor].inuse--;
@@ -205,8 +192,8 @@ int raw_ctl_ioctl(struct inode *inode,
* major/minor numbers make sense.
*/
- if ((rq.block_major == NODEV &&
- rq.block_minor != NODEV) ||
+ if ((rq.block_major == 0 &&
+ rq.block_minor != 0) ||
rq.block_major > MAX_BLKDEV ||
rq.block_minor > MINORMASK) {
err = -EINVAL;
@@ -222,7 +209,7 @@ int raw_ctl_ioctl(struct inode *inode,
if (raw_devices[minor].binding)
bdput(raw_devices[minor].binding);
raw_devices[minor].binding =
- bdget(kdev_t_to_nr(MKDEV(rq.block_major, rq.block_minor)));
+ bdget(kdev_t_to_nr(mk_kdev(rq.block_major, rq.block_minor)));
up(&raw_devices[minor].mutex);
} else {
struct block_device *bdev;
@@ -231,8 +218,8 @@ int raw_ctl_ioctl(struct inode *inode,
bdev = raw_devices[minor].binding;
if (bdev) {
dev = to_kdev_t(bdev->bd_dev);
- rq.block_major = MAJOR(dev);
- rq.block_minor = MINOR(dev);
+ rq.block_major = major(dev);
+ rq.block_minor = minor(dev);
} else {
rq.block_major = rq.block_minor = 0;
}
@@ -284,7 +271,7 @@ ssize_t rw_raw_dev(int rw, struct file *filp, char *buf,
* First, a few checks on device size limits
*/
- minor = MINOR(filp->f_dentry->d_inode->i_rdev);
+ minor = minor(filp->f_dentry->d_inode->i_rdev);
new_iobuf = 0;
iobuf = filp->f_iobuf;
@@ -304,12 +291,12 @@ ssize_t rw_raw_dev(int rw, struct file *filp, char *buf,
sector_bits = raw_devices[minor].sector_bits;
sector_mask = sector_size- 1;
- if (blk_size[MAJOR(dev)])
- limit = (((loff_t) blk_size[MAJOR(dev)][MINOR(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
+ if (blk_size[major(dev)])
+ limit = (((loff_t) blk_size[major(dev)][minor(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
else
limit = INT_MAX;
dprintk ("rw_raw_dev: dev %d:%d (+%d)\n",
- MAJOR(dev), MINOR(dev), limit);
+ major(dev), minor(dev), limit);
err = -EINVAL;
if ((*offp & sector_mask) || (size & sector_mask))
diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h
index beb075780..26063cb6a 100644
--- a/drivers/char/rio/linux_compat.h
+++ b/drivers/char/rio/linux_compat.h
@@ -60,9 +60,6 @@ struct ttystatics {
#define getpid() (current->pid)
-#define major(dev) MAJOR(dev)
-#define minor(dev) MINOR(dev)
-
#define QSIZE SERIAL_XMIT_SIZE
#define pseterr(errno) return (- errno)
diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h
index 88aa1f342..13a993195 100644
--- a/drivers/char/rio/rio.h
+++ b/drivers/char/rio/rio.h
@@ -205,10 +205,10 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3";
#define RIO_MODEMOFFSET 0x200 /* doesn't mean anything */
#define RIO_MODEM_MASK 0x1FF
#define RIO_MODEM_BIT 0x200
-#define RIO_UNMODEM(DEV) (minor(DEV) & RIO_MODEM_MASK)
-#define RIO_ISMODEM(DEV) (minor(DEV) & RIO_MODEM_BIT)
-#define RIO_PORT(DEV,FIRST_MAJ) ( (major(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \
- + minor(DEV)
+#define RIO_UNMODEM(DEV) (MINOR(DEV) & RIO_MODEM_MASK)
+#define RIO_ISMODEM(DEV) (MINOR(DEV) & RIO_MODEM_BIT)
+#define RIO_PORT(DEV,FIRST_MAJ) ( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \
+ + MINOR(DEV)
#define splrio spltty
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 749bf1fb5..3b41b68f1 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -375,16 +375,16 @@ int RIODelay_ni (struct Port *PortP, int njiffies)
int rio_minor (kdev_t device)
{
- return MINOR (device) +
- 256 * ((MAJOR (device) == RIO_NORMAL_MAJOR1) ||
- (MAJOR (device) == RIO_CALLOUT_MAJOR1));
+ return minor (device) +
+ 256 * ((major (device) == RIO_NORMAL_MAJOR1) ||
+ (major (device) == RIO_CALLOUT_MAJOR1));
}
int rio_ismodem (kdev_t device)
{
- return (MAJOR (device) == RIO_NORMAL_MAJOR0) ||
- (MAJOR (device) == RIO_NORMAL_MAJOR1);
+ return (major (device) == RIO_NORMAL_MAJOR0) ||
+ (major (device) == RIO_NORMAL_MAJOR1);
}
@@ -424,7 +424,7 @@ static int rio_set_real_termios (void *ptr)
tty = ((struct Port *)ptr)->gs.tty;
- modem = (MAJOR(tty->device) == RIO_NORMAL_MAJOR0) || (MAJOR(tty->device) == RIO_NORMAL_MAJOR1);
+ modem = (major(tty->device) == RIO_NORMAL_MAJOR0) || (major(tty->device) == RIO_NORMAL_MAJOR1);
rv = RIOParam( (struct Port *) ptr, CONFIG, modem, 1);
diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h
index 23d8951c6..7c71bfc7a 100644
--- a/drivers/char/rio/rio_linux.h
+++ b/drivers/char/rio/rio_linux.h
@@ -178,10 +178,9 @@ static inline void *rio_memcpy_fromio (void *dest, void *source, int n)
#ifdef DEBUG
#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0)
-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n")
-#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit " __FUNCTION__ "\n")
-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \
- "(port %d)\n", port->line)
+#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __FUNCTION__)
+#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit %s\n", __FUNCTION__)
+#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__FUNCTION__, port->line)
#else
#define rio_dprintk(f, str...) /* nothing */
#define func_enter()
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
index 0c9fc092a..016985b21 100644
--- a/drivers/char/rio/rioctrl.c
+++ b/drivers/char/rio/rioctrl.c
@@ -1737,15 +1737,15 @@ RIO_DEBUG_CTRL, if (su)
switch ( (uint)arg & RIO_DEV_MASK ) {
case RIO_DEV_DIRECT:
- arg = (caddr_t)drv_makedev(major(dev), port);
+ arg = (caddr_t)drv_makedev(MAJOR(dev), port);
rio_dprintk (RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n",port, (int)arg);
return (int)arg;
case RIO_DEV_MODEM:
- arg = (caddr_t)drv_makedev(major(dev), (port|RIO_MODEM_BIT) );
+ arg = (caddr_t)drv_makedev(MAJOR(dev), (port|RIO_MODEM_BIT) );
rio_dprintk (RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n",port, (int)arg);
return (int)arg;
case RIO_DEV_XPRINT:
- arg = (caddr_t)drv_makedev(major(dev), port);
+ arg = (caddr_t)drv_makedev(MAJOR(dev), port);
rio_dprintk (RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n",port, (int)arg);
return (int)arg;
}
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index fa190b435..780e6bf85 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1089,12 +1089,12 @@ static int rc_open(struct tty_struct * tty, struct file * filp)
struct riscom_board * bp;
unsigned long flags;
- board = RC_BOARD(MINOR(tty->device));
+ board = RC_BOARD(minor(tty->device));
if (board > RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
return -ENODEV;
bp = &rc_board[board];
- port = rc_port + board * RC_NPORT + RC_PORT(MINOR(tty->device));
+ port = rc_port + board * RC_NPORT + RC_PORT(minor(tty->device));
if (rc_paranoia_check(port, tty->device, "rc_open"))
return -ENODEV;
diff --git a/drivers/char/sbc60xxwdt.c b/drivers/char/sbc60xxwdt.c
index e38516fc3..ff9a572b1 100644
--- a/drivers/char/sbc60xxwdt.c
+++ b/drivers/char/sbc60xxwdt.c
@@ -196,7 +196,7 @@ static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * p
static int fop_open(struct inode * inode, struct file * file)
{
- switch(MINOR(inode->i_rdev))
+ switch(minor(inode->i_rdev))
{
case WATCHDOG_MINOR:
/* Just in case we're already talking to someone... */
@@ -214,7 +214,7 @@ static int fop_open(struct inode * inode, struct file * file)
static int fop_close(struct inode * inode, struct file * file)
{
- if(MINOR(inode->i_rdev) == WATCHDOG_MINOR)
+ if(minor(inode->i_rdev) == WATCHDOG_MINOR)
{
if(wdt_expect_close)
wdt_turnoff();
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index c67730696..f37b50343 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -460,7 +460,7 @@ static int a2232_open(struct tty_struct * tty, struct file * filp)
int retval;
struct a2232_port *port;
- line = MINOR(tty->device);
+ line = minor(tty->device);
port = &a2232_ports[line];
tty->driver_data = port;
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index 604dfc34a..4018baa08 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -3145,7 +3145,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
unsigned long page;
MOD_INC_USE_COUNT;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS)) {
MOD_DEC_USE_COUNT;
return -ENODEV;
@@ -5821,38 +5821,9 @@ static void serial_console_write(struct console *co, const char *s,
serial_out(info, UART_IER, ier);
}
-/*
- * Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
- static struct async_struct *info;
- int ier, c;
-
- info = &async_sercons;
-
- /*
- * First save the IER then disable the interrupts so
- * that the real driver for the port does not get the
- * character.
- */
- ier = serial_in(info, UART_IER);
- serial_out(info, UART_IER, 0x00);
-
- while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0);
- c = serial_in(info, UART_RX);
-
- /*
- * Restore the interrupts
- */
- serial_out(info, UART_IER, ier);
-
- return c;
-}
-
static kdev_t serial_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, 64 + c->index);
+ return mk_kdev(TTY_MAJOR, 64 + c->index);
}
/*
@@ -5990,7 +5961,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index e4071a9dd..d194ff2eb 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -65,7 +65,6 @@
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/mvme16xhw.h>
#include <asm/bootinfo.h>
@@ -249,18 +248,18 @@ serial_paranoia_check(struct cyclades_port *info,
"Warning: cyclades_port out of range for (%d, %d) in %s\n";
if (!info) {
- printk(badinfo, MAJOR(device), MINOR(device), routine);
+ printk(badinfo, major(device), minor(device), routine);
return 1;
}
if( (long)info < (long)(&cy_port[0])
|| (long)(&cy_port[NR_PORTS]) < (long)info ){
- printk(badrange, MAJOR(device), MINOR(device), routine);
+ printk(badrange, major(device), minor(device), routine);
return 1;
}
if (info->magic != CYCLADES_MAGIC) {
- printk(badmagic, MAJOR(device), MINOR(device), routine);
+ printk(badmagic, major(device), minor(device), routine);
return 1;
}
#endif
@@ -2133,7 +2132,7 @@ cy_open(struct tty_struct *tty, struct file * filp)
int retval, line;
/* CP('O'); */
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (NR_PORTS <= line)){
return -ENODEV;
}
@@ -2806,61 +2805,9 @@ void serial167_console_write(struct console *co, const char *str, unsigned count
restore_flags(flags);
}
-/* This is a hack; if there are multiple chars waiting in the chip we
- * discard all but the last one, and return that. The cd2401 is not really
- * designed to be driven in polled mode.
- */
-
-int serial167_console_wait_key(struct console *co)
-{
- volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
- unsigned long flags;
- volatile u_char sink;
- u_char ier;
- int port;
- int keypress = 0;
-
- save_flags(flags); cli();
-
- /* Ensure receiver is enabled! */
-
- port = 0;
- base_addr[CyCAR] = (u_char)port;
- while (base_addr[CyCCR])
- ;
- base_addr[CyCCR] = CyENB_RCVR;
- ier = base_addr[CyIER];
- base_addr[CyIER] = CyRxData;
-
- while (!keypress) {
- if (pcc2chip[PccSCCRICR] & 0x20)
- {
- /* We have an Rx int. Acknowledge it */
- sink = pcc2chip[PccRPIACKR];
- if ((base_addr[CyLICR] >> 2) == port) {
- int cnt = base_addr[CyRFOC];
- while (cnt-- > 0)
- {
- keypress = base_addr[CyRDR];
- }
- base_addr[CyREOIR] = 0;
- }
- else
- base_addr[CyREOIR] = CyNOTRANS;
- }
- }
-
- base_addr[CyIER] = ier;
-
- restore_flags(flags);
-
- return keypress;
-}
-
-
static kdev_t serial167_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, 64 + c->index);
+ return mk_kdev(TTY_MAJOR, 64 + c->index);
}
@@ -2874,7 +2821,6 @@ static struct console sercons = {
name: "ttyS",
write: serial167_console_write,
device: serial167_console_device,
- wait_key: serial167_console_wait_key,
setup: serial167_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/char/serial_21285.c b/drivers/char/serial_21285.c
index 8acf2a1a4..62400a75f 100644
--- a/drivers/char/serial_21285.c
+++ b/drivers/char/serial_21285.c
@@ -264,7 +264,7 @@ static int rs285_open(struct tty_struct *tty, struct file *filp)
int line;
MOD_INC_USE_COUNT;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if (line) {
MOD_DEC_USE_COUNT;
return -ENODEV;
@@ -389,20 +389,9 @@ static void rs285_console_write(struct console *co, const char *s, u_int count)
enable_irq(IRQ_CONTX);
}
-static int rs285_console_wait_key(struct console *co)
-{
- int c;
-
- disable_irq(IRQ_CONRX);
- while (*CSR_UARTFLG & 0x10);
- c = *CSR_UARTDR;
- enable_irq(IRQ_CONRX);
- return c;
-}
-
static kdev_t rs285_console_device(struct console *c)
{
- return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
+ return mk_kdev(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
}
static int __init rs285_console_setup(struct console *co, char *options)
@@ -493,7 +482,6 @@ static struct console rs285_cons =
name: SERIAL_21285_NAME,
write: rs285_console_write,
device: rs285_console_device,
- wait_key: rs285_console_wait_key,
setup: rs285_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/char/serial_amba.c b/drivers/char/serial_amba.c
index 190f8c201..5eb8d815c 100644
--- a/drivers/char/serial_amba.c
+++ b/drivers/char/serial_amba.c
@@ -953,7 +953,7 @@ static void ambauart_flush_buffer(struct tty_struct *tty)
#if DEBUG
printk("ambauart_flush_buffer(%d) called\n",
- MINOR(tty->device) - tty->driver.minor_start);
+ minor(tty->device) - tty->driver.minor_start);
#endif
save_flags(flags); cli();
info->xmit.head = info->xmit.tail = 0;
@@ -1515,7 +1515,7 @@ static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout)
expire = jiffies + timeout;
#if DEBUG
printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n",
- MINOR(tty->device) - tty->driver.minor_start, jiffies,
+ minor(tty->device) - tty->driver.minor_start, jiffies,
expire);
#endif
while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) {
@@ -1690,7 +1690,7 @@ static struct amba_info *ambauart_get(int line)
static int ambauart_open(struct tty_struct *tty, struct file *filp)
{
struct amba_info *info;
- int retval, line = MINOR(tty->device) - tty->driver.minor_start;
+ int retval, line = minor(tty->device) - tty->driver.minor_start;
#if DEBUG
printk("ambauart_open(%d) called\n", line);
@@ -1921,25 +1921,9 @@ static void ambauart_console_write(struct console *co, const char *s, u_int coun
UART_PUT_CR(port, old_cr);
}
-/*
- * Receive character from the serial port
- */
-static int ambauart_console_wait_key(struct console *co)
-{
- struct amba_port *port = &amba_ports[co->index];
- unsigned int status;
- int c;
-
- do {
- status = UART_GET_FR(port);
- } while (!UART_RX_DATA(status));
- c = UART_GET_CHAR(port);
- return c;
-}
-
static kdev_t ambauart_console_device(struct console *c)
{
- return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
+ return mk_kdev(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
}
static int __init ambauart_console_setup(struct console *co, char *options)
@@ -2015,7 +1999,6 @@ static struct console ambauart_cons =
read: ambauart_console_read,
#endif
device: ambauart_console_device,
- wait_key: ambauart_console_wait_key,
setup: ambauart_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c
index d3601cc5f..d2b46ac44 100644
--- a/drivers/char/serial_tx3912.c
+++ b/drivers/char/serial_tx3912.c
@@ -548,7 +548,7 @@ static int rs_open (struct tty_struct * tty, struct file * filp)
return -EIO;
}
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
rs_dprintk (TX3912_UART_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p)\n",
(int) current->pid, line, tty, current->tty);
@@ -993,21 +993,6 @@ void serial_outc(unsigned char c)
IntEnable2 = int2;
}
-static int serial_console_wait_key(struct console *co)
-{
- unsigned int int2, res;
-
- int2 = IntEnable2;
- IntEnable2 = 0;
-
- while (!(UartA_Ctrl1 & UART_RX_HOLD_FULL));
- res = UartA_Data;
- udelay(10);
-
- IntEnable2 = int2;
- return res;
-}
-
static void serial_console_write(struct console *co, const char *s,
unsigned count)
{
@@ -1022,7 +1007,7 @@ static void serial_console_write(struct console *co, const char *s,
static kdev_t serial_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, 64 + c->index);
+ return mk_kdev(TTY_MAJOR, 64 + c->index);
}
static __init int serial_console_setup(struct console *co, char *options)
@@ -1065,7 +1050,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: -1
diff --git a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c
index 9e3410f03..7b5b22b30 100644
--- a/drivers/char/sh-sci.c
+++ b/drivers/char/sh-sci.c
@@ -813,7 +813,7 @@ static int sci_open(struct tty_struct * tty, struct file * filp)
struct sci_port *port;
int retval, line;
- line = MINOR(tty->device) - SCI_MINOR_START;
+ line = minor(tty->device) - SCI_MINOR_START;
if ((line < 0) || (line >= SCI_NPORTS))
return -ENODEV;
@@ -1181,18 +1181,9 @@ static void serial_console_write(struct console *co, const char *s,
put_string(sercons_port, s, count);
}
-/*
- * Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
- /* Not implemented yet */
- return 0;
-}
-
static kdev_t serial_console_device(struct console *c)
{
- return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index);
+ return mk_kdev(SCI_MAJOR, SCI_MINOR_START + c->index);
}
/*
@@ -1273,7 +1264,6 @@ static struct console sercons = {
name: "ttySC",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/char/shwdt.c b/drivers/char/shwdt.c
index d7bd9d3a5..abd566b83 100644
--- a/drivers/char/shwdt.c
+++ b/drivers/char/shwdt.c
@@ -131,7 +131,7 @@ static void sh_wdt_ping(unsigned long data)
*/
static int sh_wdt_open(struct inode *inode, struct file *file)
{
- switch (MINOR(inode->i_rdev)) {
+ switch (minor(inode->i_rdev)) {
case WATCHDOG_MINOR:
if (sh_is_open) {
return -EBUSY;
@@ -160,7 +160,7 @@ static int sh_wdt_close(struct inode *inode, struct file *file)
{
lock_kernel();
- if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
+ if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
#ifndef CONFIG_WATCHDOG_NOWAYOUT
sh_wdt_stop();
#endif
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index d4e8d6e5d..376e8b151 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -1455,17 +1455,17 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
struct specialix_board * bp;
unsigned long flags;
- board = SX_BOARD(MINOR(tty->device));
+ board = SX_BOARD(minor(tty->device));
if (board > SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT))
return -ENODEV;
bp = &sx_board[board];
- port = sx_port + board * SX_NPORT + SX_PORT(MINOR(tty->device));
+ port = sx_port + board * SX_NPORT + SX_PORT(minor(tty->device));
#ifdef DEBUG_SPECIALIX
printk (KERN_DEBUG "Board = %d, bp = %p, port = %p, portno = %d.\n",
- board, bp, port, SX_PORT(MINOR(tty->device)));
+ board, bp, port, SX_PORT(minor(tty->device)));
#endif
if (sx_paranoia_check(port, tty->device, "sx_open"))
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 510e2d5cf..1908bbcce 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1018,7 +1018,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
(int) filp, tty->device);
#endif
- minordev = MINOR(tty->device);
+ minordev = minor(tty->device);
brdnr = MINOR2BRD(minordev);
if (brdnr >= stl_nrbrds)
return(-ENODEV);
@@ -3133,7 +3133,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
(int) fp, cmd, (int) arg);
#endif
- brdnr = MINOR(ip->i_rdev);
+ brdnr = minor(ip->i_rdev);
if (brdnr >= STL_MAXBRDS)
return(-ENODEV);
rc = 0;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index a74df076d..3ff098490 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1420,7 +1420,7 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
return -EIO;
}
- line = MINOR(tty->device);
+ line = minor(tty->device);
sx_dprintk (SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, np=%d)\n",
current->pid, line, tty, current->tty, sx_nports);
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 721271198..f2afd4cf4 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -116,7 +116,6 @@
#endif
#endif
-#include <asm/segment.h>
#define GET_USER(error,value,addr) error = get_user(value,addr)
#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
#define PUT_USER(error,value,addr) error = put_user(value,addr)
@@ -3603,7 +3602,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
unsigned long flags;
/* verify range of specified line number */
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= mgsl_device_count)) {
printk("%s(%d):mgsl_open with illegal line #%d.\n",
__FILE__,__LINE__,line);
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5ba8a313a..9c28836d8 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -105,7 +105,7 @@ static struct sysrq_key_op sysrq_reboot_op = {
/* Guesses if the device is a local hard drive */
static int is_local_disk(kdev_t dev) {
unsigned int major;
- major = MAJOR(dev);
+ major = major(dev);
switch (major) {
case IDE0_MAJOR:
@@ -206,7 +206,7 @@ void do_emergency_sync(void) {
for (sb = sb_entry(super_blocks.next);
sb != sb_entry(&super_blocks);
sb = sb_entry(sb->s_list.next))
- if (!is_local_disk(sb->s_dev) && MAJOR(sb->s_dev))
+ if (!is_local_disk(sb->s_dev) && major(sb->s_dev))
go_sync(sb, remount_flag);
unlock_kernel();
diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
index 848e4da61..4e5cfcf6a 100644
--- a/drivers/char/tpqic02.c
+++ b/drivers/char/tpqic02.c
@@ -1830,7 +1830,7 @@ static ssize_t qic02_tape_read(struct file *filp, char *buf, size_t count,
/* can't print a ``long long'' (for filp->f_pos), so chop it */
printk(TPQIC02_NAME
": request READ, minor=%x, buf=%p, count=%lx"
- ", pos=%lx, flags=%x\n", MINOR(dev), buf,
+ ", pos=%lx, flags=%x\n", minor(dev), buf,
(long) count, (unsigned long) filp->f_pos, flags);
if (count % TAPE_BLKSIZE) { /* Only allow mod 512 bytes at a time. */
@@ -2027,7 +2027,7 @@ static ssize_t qic02_tape_write(struct file *filp, const char *buf,
/* can't print a ``long long'' (for filp->f_pos), so chop it */
printk(TPQIC02_NAME ": request WRITE, minor=%x, buf=%p"
", count=%lx, pos=%lx, flags=%x\n",
- MINOR(dev), buf,
+ minor(dev), buf,
(long) count, (unsigned long) filp->f_pos, flags);
}
@@ -2203,7 +2203,7 @@ static int qic02_tape_open_no_use_count(struct inode *inode,
kdevname(dev), flags);
}
- if (MINOR(dev) == 255) { /* special case for resetting */
+ if (minor(dev) == 255) { /* special case for resetting */
if (capable(CAP_SYS_ADMIN)) {
return (tape_reset(1) == TE_OK) ? -EAGAIN : -ENXIO;
} else {
@@ -2383,7 +2383,7 @@ static int qic02_tape_open_no_use_count(struct inode *inode,
}
if (s != 0) {
status_dead = YES; /* force reset */
- current_tape_dev = 0; /* earlier 0xff80 */
+ current_tape_dev = NODEV;/* earlier 0xff80 */
return -EIO;
}
@@ -2522,7 +2522,7 @@ static int qic02_tape_ioctl(struct inode *inode, struct file *filp,
unsigned int iocmd, unsigned long ioarg)
{
int error;
- int dev_maj = MAJOR(inode->i_rdev);
+ int dev_maj = major(inode->i_rdev);
int c;
struct mtop operation;
unsigned char blk_addr[6];
@@ -2828,7 +2828,7 @@ int __init qic02_tape_init(void)
return -ENODEV;
}
- current_tape_dev = MKDEV(QIC02_TAPE_MAJOR, 0);
+ current_tape_dev = mk_kdev(QIC02_TAPE_MAJOR, 0);
#ifndef CONFIG_QIC02_DYNCONF
printk(TPQIC02_NAME ": IRQ %d, DMA %d, IO 0x%x, IFC %s, %s, %s\n",
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index befe38e54..cea100d98 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -102,10 +102,10 @@
#include <linux/kmod.h>
-#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
-#define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
-#define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1)
-#define PTMX_DEV MKDEV(TTYAUX_MAJOR,2)
+#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0))
+#define IS_TTY_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,0))
+#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1))
+#define IS_PTMX_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,2))
#undef TTY_DEBUG_HANGUP
@@ -185,7 +185,7 @@ static inline void free_tty_struct(struct tty_struct *tty)
static char *
_tty_make_name(struct tty_struct *tty, const char *name, char *buf)
{
- int idx = (tty)?MINOR(tty->device) - tty->driver.minor_start:0;
+ int idx = (tty)? minor(tty->device) - tty->driver.minor_start:0;
if (!tty) /* Hmm. NULL pointer. That's fun. */
strcpy(buf, "NULL tty");
@@ -196,7 +196,7 @@ _tty_make_name(struct tty_struct *tty, const char *name, char *buf)
return buf;
}
-#define TTY_NUMBER(tty) (MINOR((tty)->device) - (tty)->driver.minor_start + \
+#define TTY_NUMBER(tty) (minor((tty)->device) - (tty)->driver.minor_start + \
(tty)->driver.name_base)
char *tty_name(struct tty_struct *tty, char *buf)
@@ -331,8 +331,8 @@ struct tty_driver *get_tty_driver(kdev_t device)
int major, minor;
struct tty_driver *p;
- minor = MINOR(device);
- major = MAJOR(device);
+ minor = minor(device);
+ major = major(device);
for (p = tty_drivers; p; p = p->next) {
if (p->major != major)
@@ -442,8 +442,8 @@ void do_tty_hangup(void *data)
file_list_lock();
for (l = tty->tty_files.next; l != &tty->tty_files; l = l->next) {
struct file * filp = list_entry(l, struct file, f_list);
- if (filp->f_dentry->d_inode->i_rdev == CONSOLE_DEV ||
- filp->f_dentry->d_inode->i_rdev == SYSCONS_DEV) {
+ if (IS_CONSOLE_DEV(filp->f_dentry->d_inode->i_rdev) ||
+ IS_SYSCONS_DEV(filp->f_dentry->d_inode->i_rdev)) {
cons_filp = filp;
continue;
}
@@ -597,12 +597,6 @@ void disassociate_ctty(int on_exit)
read_unlock(&tasklist_lock);
}
-void wait_for_keypress(void)
-{
- struct console *c = console_drivers;
- if (c) c->wait_key(c);
-}
-
void stop_tty(struct tty_struct *tty)
{
if (tty->stopped)
@@ -658,7 +652,7 @@ static ssize_t tty_read(struct file * file, char * buf, size_t count,
moved it to there. This should only be done for the N_TTY
line discipline, anyway. Same goes for write_chan(). -- jlc. */
#if 0
- if ((inode->i_rdev != CONSOLE_DEV) && /* don't stop on /dev/console */
+ if (!IS_CONSOLE_DEV(inode->i_rdev) && /* don't stop on /dev/console */
(tty->pgrp > 0) &&
(current->tty == tty) &&
(tty->pgrp != current->pgrp))
@@ -747,8 +741,8 @@ static ssize_t tty_write(struct file * file, const char * buf, size_t count,
* well as /dev/tty0.
*/
inode = file->f_dentry->d_inode;
- is_console = (inode->i_rdev == SYSCONS_DEV ||
- inode->i_rdev == CONSOLE_DEV);
+ is_console = IS_SYSCONS_DEV(inode->i_rdev) ||
+ IS_CONSOLE_DEV(inode->i_rdev);
if (is_console && redirect)
tty = redirect;
@@ -809,7 +803,7 @@ static int init_dev(kdev_t device, struct tty_struct **ret_tty)
if (!driver)
return -ENODEV;
- idx = MINOR(device) - driver->minor_start;
+ idx = minor(device) - driver->minor_start;
/*
* Check whether we need to acquire the tty semaphore to avoid
@@ -863,7 +857,7 @@ static int init_dev(kdev_t device, struct tty_struct **ret_tty)
if (!o_tty)
goto free_mem_out;
initialize_tty_struct(o_tty);
- o_tty->device = (kdev_t) MKDEV(driver->other->major,
+ o_tty->device = mk_kdev(driver->other->major,
driver->other->minor_start + idx);
o_tty->driver = *driver->other;
@@ -1055,7 +1049,7 @@ static void release_dev(struct file * filp)
tty_fasync(-1, filp, 0);
- idx = MINOR(tty->device) - tty->driver.minor_start;
+ idx = minor(tty->device) - tty->driver.minor_start;
pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
tty->driver.subtype == PTY_TYPE_MASTER);
o_tty = tty->link;
@@ -1291,7 +1285,7 @@ static int tty_open(struct inode * inode, struct file * filp)
retry_open:
noctty = filp->f_flags & O_NOCTTY;
device = inode->i_rdev;
- if (device == TTY_DEV) {
+ if (IS_TTY_DEV(device)) {
if (!current->tty)
return -ENXIO;
device = current->tty->device;
@@ -1299,13 +1293,13 @@ retry_open:
/* noctty = 1; */
}
#ifdef CONFIG_VT
- if (device == CONSOLE_DEV) {
+ if (IS_CONSOLE_DEV(device)) {
extern int fg_console;
- device = MKDEV(TTY_MAJOR, fg_console + 1);
+ device = mk_kdev(TTY_MAJOR, fg_console + 1);
noctty = 1;
}
#endif
- if (device == SYSCONS_DEV) {
+ if (IS_SYSCONS_DEV(device)) {
struct console *c = console_drivers;
while(c && !c->device)
c = c->next;
@@ -1316,7 +1310,7 @@ retry_open:
noctty = 1;
}
- if (device == PTMX_DEV) {
+ if (IS_PTMX_DEV(device)) {
#ifdef CONFIG_UNIX98_PTYS
/* find a free pty. */
@@ -1330,7 +1324,7 @@ retry_open:
for (minor = driver->minor_start ;
minor < driver->minor_start + driver->num ;
minor++) {
- device = MKDEV(driver->major, minor);
+ device = mk_kdev(driver->major, minor);
if (!init_dev(device, &tty)) goto ptmx_found; /* ok! */
}
}
@@ -1338,7 +1332,7 @@ retry_open:
ptmx_found:
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
minor -= driver->minor_start;
- devpts_pty_new(driver->other->name_base + minor, MKDEV(driver->other->major, minor + driver->other->minor_start));
+ devpts_pty_new(driver->other->name_base + minor, mk_kdev(driver->other->major, minor + driver->other->minor_start));
tty_register_devfs(&pts_driver[major], DEVFS_FL_DEFAULT,
pts_driver[major].minor_start + minor);
noctty = 1;
@@ -1511,8 +1505,8 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
static int tioccons(struct inode *inode,
struct tty_struct *tty, struct tty_struct *real_tty)
{
- if (inode->i_rdev == SYSCONS_DEV ||
- inode->i_rdev == CONSOLE_DEV) {
+ if (IS_SYSCONS_DEV(inode->i_rdev) ||
+ IS_CONSOLE_DEV(inode->i_rdev)) {
if (!suser())
return -EPERM;
redirect = NULL;
@@ -2008,19 +2002,15 @@ void tty_register_devfs (struct tty_driver *driver, unsigned int flags, unsigned
{
#ifdef CONFIG_DEVFS_FS
umode_t mode = S_IFCHR | S_IRUSR | S_IWUSR;
- kdev_t device = MKDEV (driver->major, minor);
+ kdev_t device = mk_kdev(driver->major, minor);
int idx = minor - driver->minor_start;
char buf[32];
- switch (device) {
- case TTY_DEV:
- case PTMX_DEV:
+ if (IS_TTY_DEV(device) || IS_PTMX_DEV(device))
+ mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+ else {
+ if (driver->major == PTY_MASTER_MAJOR)
mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
- break;
- default:
- if (driver->major == PTY_MASTER_MAJOR)
- mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
- break;
}
if ( (minor < driver->minor_start) ||
(minor >= driver->minor_start + driver->num) ) {
@@ -2295,8 +2285,8 @@ void __init tty_init(void)
dev_ptmx_driver = dev_tty_driver;
dev_ptmx_driver.driver_name = "/dev/ptmx";
dev_ptmx_driver.name = dev_ptmx_driver.driver_name + 5;
- dev_ptmx_driver.major= MAJOR(PTMX_DEV);
- dev_ptmx_driver.minor_start = MINOR(PTMX_DEV);
+ dev_ptmx_driver.major= TTYAUX_MAJOR;
+ dev_ptmx_driver.minor_start = 2;
dev_ptmx_driver.type = TTY_DRIVER_TYPE_SYSTEM;
dev_ptmx_driver.subtype = SYSTEM_TYPE_SYSPTMX;
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index a7e1f2d67..157ac0424 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -49,7 +49,8 @@ static int
vcs_size(struct inode *inode)
{
int size;
- int currcons = MINOR(inode->i_rdev) & 127;
+ int minor = minor(inode->i_rdev);
+ int currcons = minor & 127;
if (currcons == 0)
currcons = fg_console;
else
@@ -59,7 +60,7 @@ vcs_size(struct inode *inode)
size = video_num_lines * video_num_columns;
- if (MINOR(inode->i_rdev) & 128)
+ if (minor & 128)
size = 2*size + HEADER_SIZE;
return size;
}
@@ -97,7 +98,7 @@ static ssize_t
vcs_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- unsigned int currcons = MINOR(inode->i_rdev);
+ unsigned int currcons = minor(inode->i_rdev);
long pos = *ppos;
long viewed, attr, read;
int col, maxcol;
@@ -266,7 +267,7 @@ static ssize_t
vcs_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- unsigned int currcons = MINOR(inode->i_rdev);
+ unsigned int currcons = minor(inode->i_rdev);
long pos = *ppos;
long viewed, attr, size, written;
char *con_buf0;
@@ -449,7 +450,7 @@ unlock_out:
static int
vcs_open(struct inode *inode, struct file *filp)
{
- unsigned int currcons = (MINOR(inode->i_rdev) & 127);
+ unsigned int currcons = minor(inode->i_rdev) & 127;
if(currcons && !vc_cons_allocated(currcons-1))
return -ENXIO;
return 0;
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 63d764af9..45bbbc747 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -833,7 +833,7 @@ static void scc_send_xchar(struct tty_struct *tty, char ch)
static int scc_open (struct tty_struct * tty, struct file * filp)
{
- int line = MINOR(tty->device) - SCC_MINOR_BASE;
+ int line = minor(tty->device) - SCC_MINOR_BASE;
int retval;
struct scc_port *port = &scc_ports[line];
int i, channel = port->channel;
@@ -1065,44 +1065,9 @@ static void scc_console_write (struct console *co, const char *str, unsigned cou
restore_flags(flags);
}
-
-static int scc_console_wait_key(struct console *co)
-{
- unsigned long flags;
- volatile char *p = NULL;
- int c;
-
-#ifdef CONFIG_MVME147_SCC
- if (MACH_IS_MVME147)
- p = (volatile char *)M147_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_MVME162_SCC
- if (MACH_IS_MVME16x)
- p = (volatile char *)MVME_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_BVME6000_SCC
- if (MACH_IS_BVME6000)
- p = (volatile char *)BVME_SCC_A_ADDR;
-#endif
-
- save_flags(flags);
- cli();
-
- /* wait for rx buf filled */
- while ((*p & 0x01) == 0)
- ;
-
- *p = 8;
- scc_delay();
- c = *p;
- restore_flags(flags);
- return c;
-}
-
-
static kdev_t scc_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, SCC_MINOR_BASE + c->index);
+ return mk_kdev(TTY_MAJOR, SCC_MINOR_BASE + c->index);
}
@@ -1116,7 +1081,6 @@ static struct console sercons = {
name: "ttyS",
write: scc_console_write,
device: scc_console_device,
- wait_key: scc_console_wait_key,
setup: scc_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/char/w83877f_wdt.c b/drivers/char/w83877f_wdt.c
index f621c158f..0f1b815ec 100644
--- a/drivers/char/w83877f_wdt.c
+++ b/drivers/char/w83877f_wdt.c
@@ -196,7 +196,7 @@ static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * p
static int fop_open(struct inode * inode, struct file * file)
{
- switch(MINOR(inode->i_rdev))
+ switch(minor(inode->i_rdev))
{
case WATCHDOG_MINOR:
/* Just in case we're already talking to someone... */
@@ -214,7 +214,7 @@ static int fop_open(struct inode * inode, struct file * file)
static int fop_close(struct inode * inode, struct file * file)
{
- if(MINOR(inode->i_rdev) == WATCHDOG_MINOR)
+ if(minor(inode->i_rdev) == WATCHDOG_MINOR)
{
if(wdt_expect_close)
wdt_turnoff();
diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c
index fbf26d0a6..f98face6a 100644
--- a/drivers/char/wdt.c
+++ b/drivers/char/wdt.c
@@ -265,7 +265,7 @@ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr)
if (ptr != &file->f_pos)
return -ESPIPE;
- switch(MINOR(file->f_dentry->d_inode->i_rdev))
+ switch(minor(file->f_dentry->d_inode->i_rdev))
{
case TEMP_MINOR:
c*=11;
@@ -334,7 +334,7 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static int wdt_open(struct inode *inode, struct file *file)
{
- switch(MINOR(inode->i_rdev))
+ switch(minor(inode->i_rdev))
{
case WATCHDOG_MINOR:
if(test_and_set_bit(0, &wdt_is_open))
@@ -373,7 +373,7 @@ static int wdt_open(struct inode *inode, struct file *file)
static int wdt_release(struct inode *inode, struct file *file)
{
- if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+ if(minor(inode->i_rdev)==WATCHDOG_MINOR)
{
#ifndef CONFIG_WATCHDOG_NOWAYOUT
inb_p(WDT_DC); /* Disable counters */
diff --git a/drivers/char/wdt_pci.c b/drivers/char/wdt_pci.c
index 8dac309cf..872a5e453 100644
--- a/drivers/char/wdt_pci.c
+++ b/drivers/char/wdt_pci.c
@@ -281,7 +281,7 @@ static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *p
if (ptr != &file->f_pos)
return -ESPIPE;
- switch(MINOR(file->f_dentry->d_inode->i_rdev))
+ switch(minor(file->f_dentry->d_inode->i_rdev))
{
case TEMP_MINOR:
c*=11;
@@ -350,7 +350,7 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd
static int wdtpci_open(struct inode *inode, struct file *file)
{
- switch(MINOR(inode->i_rdev))
+ switch(minor(inode->i_rdev))
{
case WATCHDOG_MINOR:
if( test_and_set_bit(0,&wdt_is_open) )
@@ -410,7 +410,7 @@ static int wdtpci_open(struct inode *inode, struct file *file)
static int wdtpci_release(struct inode *inode, struct file *file)
{
- if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+ if(minor(inode->i_rdev)==WATCHDOG_MINOR)
{
#ifndef CONFIG_WATCHDOG_NOWAYOUT
inb_p(WDT_DC); /* Disable counters */
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 6d3ab3825..3b001b5db 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -382,7 +382,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
int i2cdev_open (struct inode *inode, struct file *file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct i2c_client *client;
if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) {
@@ -415,7 +415,7 @@ int i2cdev_open (struct inode *inode, struct file *file)
static int i2cdev_release (struct inode *inode, struct file *file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
kfree(file->private_data);
file->private_data=NULL;
#ifdef DEBUG
diff --git a/drivers/ide/ataraid.c b/drivers/ide/ataraid.c
index 60725a4d4..3c10b9fac 100644
--- a/drivers/ide/ataraid.c
+++ b/drivers/ide/ataraid.c
@@ -269,7 +269,6 @@ static __init int ataraid_init(void)
ataraid_gendisk.major = ATAMAJOR;
ataraid_gendisk.major_name = "ataraid";
ataraid_gendisk.minor_shift = 4;
- ataraid_gendisk.max_p = 15;
ataraid_gendisk.sizes = &ataraid_gendisk_sizes[0];
ataraid_gendisk.nr_real = 16;
ataraid_gendisk.fops = &ataraid_fops;
diff --git a/drivers/ide/hd.c b/drivers/ide/hd.c
index 08485cf66..7e9b1cd2f 100644
--- a/drivers/ide/hd.c
+++ b/drivers/ide/hd.c
@@ -693,7 +693,6 @@ static struct gendisk hd_gendisk = {
major: MAJOR_NR,
major_name: "hd",
minor_shift: 6,
- max_p: 1 << 6,
part: hd,
sizes: hd_sizes,
fops: &hd_fops,
diff --git a/drivers/ide/hptraid.c b/drivers/ide/hptraid.c
index d7d8b1a3a..b430e41fb 100644
--- a/drivers/ide/hptraid.c
+++ b/drivers/ide/hptraid.c
@@ -226,32 +226,20 @@ static int hptraid_make_request (request_queue_t *q, int rw, struct buffer_head
#include "hptraid.h"
-static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize)
+static int __init read_disk_sb(struct block_device *bdev,
+ struct highpoint_raid_conf *buf)
{
- int ret = -EINVAL;
- struct buffer_head *bh = NULL;
- kdev_t dev = MKDEV(major,minor);
-
- if (blksize_size[major]==NULL) /* device doesn't exist */
- return -EINVAL;
-
+ /* Superblock is at 9*512 bytes */
+ Sector sect;
+ unsigned char *p = read_dev_sector(bdev, 9, &sect);
- /* Superblock is at 4096+412 bytes */
- set_blocksize (dev, 4096);
- bh = bread (dev, 1, 4096);
-
-
- if (bh) {
- memcpy (buffer, bh->b_data, bufsize);
- } else {
- printk(KERN_ERR "hptraid: Error reading superblock.\n");
- goto abort;
+ if (p) {
+ memcpy(buf, p, 512);
+ put_dev_sector(&sect);
+ return 0;
}
- ret = 0;
-abort:
- if (bh)
- brelse (bh);
- return ret;
+ printk(KERN_ERR "hptraid: Error reading superblock.\n");
+ return -1;
}
static unsigned long maxsectors (int major,int minor)
@@ -276,55 +264,58 @@ static unsigned long maxsectors (int major,int minor)
return lba;
}
+static struct highpoint_raid_conf __initdata prom;
static void __init probedisk(int major, int minor,int device)
{
int i;
- struct highpoint_raid_conf *prom;
- static unsigned char block[4096];
- struct block_device *bdev;
-
- if (maxsectors(major,minor)==0)
+ struct block_device *bdev = bdget(MKDEV(major,minor));
+ struct gendisk *gd;
+
+ if (!bdev)
return;
-
- if (read_disk_sb(major,minor,(unsigned char*)&block,sizeof(block)))
- return;
-
- prom = (struct highpoint_raid_conf*)&block[512];
-
- if (prom->magic!= 0x5a7816f0)
- return;
- if (prom->type) {
+
+ if (blkdev_get(bdev,FMODE_READ|FMODE_WRITE,0,BDEV_RAW) < 0)
+ return;
+
+ if (maxsectors(major,minor)==0)
+ goto out;
+
+ if (read_disk_sb(bdev, &prom))
+ goto out;
+
+ if (prom.magic!= 0x5a7816f0)
+ goto out;
+ if (prom.type) {
printk(KERN_INFO "hptraid: only RAID0 is supported currently\n");
- return;
+ goto out;
}
- i = prom->disk_number;
+ i = prom.disk_number;
if (i<0)
- return;
+ goto out;
if (i>8)
- return;
+ goto out;
+
+ raid[device].disk[i].bdev = bdev;
+ /* This is supposed to prevent others from stealing our underlying disks */
+ /* now blank the /proc/partitions table for the wrong partition table,
+ so that scripts don't accidentally mount it and crash the kernel */
+ /* XXX: the 0 is an utter hack --hch */
+ gd=get_gendisk(MKDEV(major, 0));
+ if (gd!=NULL) {
+ int j;
+ for (j=1+(minor<<gd->minor_shift);j<((minor+1)<<gd->minor_shift);j++)
+ gd->part[j].nr_sects=0;
+ }
- bdev = bdget(MKDEV(major,minor));
- if (bdev && blkdev_get(bdev,FMODE_READ|FMODE_WRITE,0,BDEV_RAW) == 0) {
- int j=0;
- struct gendisk *gd;
- raid[device].disk[i].bdev = bdev;
- /* This is supposed to prevent others from stealing our underlying disks */
- /* now blank the /proc/partitions table for the wrong partition table,
- so that scripts don't accidentally mount it and crash the kernel */
- /* XXX: the 0 is an utter hack --hch */
- gd=get_gendisk(MKDEV(major, 0));
- if (gd!=NULL) {
- for (j=1+(minor<<gd->minor_shift);j<((minor+1)<<gd->minor_shift);j++)
- gd->part[j].nr_sects=0;
- }
- }
raid[device].disk[i].device = MKDEV(major,minor);
raid[device].disk[i].sectors = maxsectors(major,minor);
- raid[device].stride = (1<<prom->raid0_shift);
- raid[device].disks = prom->raid_disks;
- raid[device].sectors = prom->total_secs;
-
+ raid[device].stride = (1<<prom.raid0_shift);
+ raid[device].disks = prom.raid_disks;
+ raid[device].sectors = prom.total_secs;
+ return;
+out:
+ blkdev_put(bdev);
}
static void __init fill_cutoff(int device)
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 0fbb8d770..f563def57 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -27,6 +27,7 @@
#include <asm/io.h>
extern char *ide_xfer_verbose (byte xfer_rate);
+extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
/*
* Maximum number of interfaces per card
@@ -225,29 +226,18 @@ static iftype_t __init icside_identifyif (struct expansion_card *ec)
static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
{
- struct buffer_head *bh;
+ request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
struct scatterlist *sg = hwif->sg_table;
- int nents = 0;
+ int nents = blk_rq_map_sg(q, rq, sg);
- if (rq->cmd == READ)
+ if (rq->q && nents > rq->nr_phys_segments)
+ printk("icside: received %d segments, build %d\n",
+ rq->nr_phys_segments, nents);
+
+ if (rq_data_dir(rq) == READ)
hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
else
hwif->sg_dma_direction = PCI_DMA_TODEVICE;
- bh = rq->bh;
- do {
- unsigned char *virt_addr = bh->b_data;
- unsigned int size = bh->b_size;
-
- while ((bh = bh->b_reqnext) != NULL) {
- if ((virt_addr + size) != (unsigned char *)bh->b_data)
- break;
- size += bh->b_size;
- }
- memset(&sg[nents], 0, sizeof(*sg));
- sg[nents].address = virt_addr;
- sg[nents].length = size;
- nents++;
- } while (bh != NULL);
return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
}
@@ -267,39 +257,56 @@ static void icside_destroy_dmatable(ide_drive_t *drive)
pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
}
+/*
+ * Configure the IOMD to give the appropriate timings for the transfer
+ * mode being requested. We take the advice of the ATA standards, and
+ * calculate the cycle time based on the transfer mode, and the EIDE
+ * MW DMA specs that the drive provides in the IDENTIFY command.
+ *
+ * We have the following IOMD DMA modes to choose from:
+ *
+ * Type Active Recovery Cycle
+ * A 250 (250) 312 (550) 562 (800)
+ * B 187 250 437
+ * C 125 (125) 125 (375) 250 (500)
+ * D 62 125 187
+ *
+ * (figures in brackets are actual measured timings)
+ *
+ * However, we also need to take care of the read/write active and
+ * recovery timings:
+ *
+ * Read Write
+ * Mode Active -- Recovery -- Cycle IOMD type
+ * MW0 215 50 215 480 A
+ * MW1 80 50 50 150 C
+ * MW2 70 25 25 120 C
+ */
static int
icside_config_if(ide_drive_t *drive, int xfer_mode)
{
int func = ide_dma_off;
+ int cycle_time = 0, use_dma_info = 0;
switch (xfer_mode) {
- case XFER_MW_DMA_2:
- /*
- * The cycle time is limited to 250ns by the r/w
- * pulse width (90ns), however we should still
- * have a maximum burst transfer rate of 8MB/s.
- */
- drive->drive_data = 250;
- break;
-
- case XFER_MW_DMA_1:
- drive->drive_data = 250;
- break;
+ case XFER_MW_DMA_2: cycle_time = 250; use_dma_info = 1; break;
+ case XFER_MW_DMA_1: cycle_time = 250; use_dma_info = 1; break;
+ case XFER_MW_DMA_0: cycle_time = 480; break;
+ }
- case XFER_MW_DMA_0:
- drive->drive_data = 480;
- break;
+ /*
+ * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
+ * take care to note the values in the ID...
+ */
+ if (use_dma_info && drive->id->eide_dma_time > cycle_time)
+ cycle_time = drive->id->eide_dma_time;
- default:
- drive->drive_data = 0;
- break;
- }
+ drive->drive_data = cycle_time;
if (!drive->init_speed)
- drive->init_speed = (byte) xfer_mode;
+ drive->init_speed = xfer_mode;
- if (drive->drive_data &&
- ide_config_drive_speed(drive, (byte) xfer_mode) == 0)
+ if (cycle_time && ide_config_drive_speed(drive, xfer_mode) == 0)
func = ide_dma_on;
else
drive->drive_data = 480;
@@ -307,7 +314,7 @@ icside_config_if(ide_drive_t *drive, int xfer_mode)
printk("%s: %s selected (peak %dMB/s)\n", drive->name,
ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
- drive->current_speed = (byte) xfer_mode;
+ drive->current_speed = xfer_mode;
return func;
}
@@ -414,7 +421,7 @@ static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_
* This is setup to be called as an extern for future support
* to other special driver code.
*/
-static int check_drive_lists(ide_drive_t *drive, int good_bad)
+static int icside_check_drive_lists(ide_drive_t *drive, int good_bad)
{
struct hd_driveid *id = drive->id;
@@ -444,7 +451,7 @@ icside_dma_check(ide_drive_t *drive)
/*
* Consult the list of known "bad" drives
*/
- if (check_drive_lists(drive, 0)) {
+ if (icside_check_drive_lists(drive, 0)) {
func = ide_dma_off;
goto out;
}
@@ -469,7 +476,7 @@ icside_dma_check(ide_drive_t *drive)
/*
* Consult the list of known "good" drives
*/
- if (check_drive_lists(drive, 1)) {
+ if (icside_check_drive_lists(drive, 1)) {
if (id->eide_dma_time > 150)
goto out;
xfer_mode = XFER_MW_DMA_1;
@@ -502,6 +509,11 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_off_quietly:
case ide_dma_on:
+ /*
+ * We don't need any bouncing. Yes, this looks the
+ * wrong way around, but it is correct.
+ */
+ blk_queue_bounce_limit(&drive->queue, BLK_BOUNCE_ANY);
drive->using_dma = (func == ide_dma_on);
return 0;
@@ -553,7 +565,8 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_bad_drive:
case ide_dma_good_drive:
- return check_drive_lists(drive, (func == ide_dma_good_drive));
+ return icside_check_drive_lists(drive, (func ==
+ ide_dma_good_drive));
case ide_dma_verbose:
return icside_dma_verbose(drive);
@@ -591,6 +604,15 @@ failed:
printk(" -- ERROR, unable to allocate DMA table\n");
return 0;
}
+
+int ide_release_dma(ide_hwif_t *hwif)
+{
+ if (hwif->sg_table) {
+ kfree(hwif->sg_table);
+ hwif->sg_table = NULL;
+ }
+ return 1;
+}
#endif
static ide_hwif_t *
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index f2a087486..daf317775 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -2015,7 +2015,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
/* Now try to get the total cdrom capacity. */
minor = (drive->select.b.unit) << PARTN_BITS;
- dev = MKDEV(HWIF(drive)->major, minor);
+ dev = mk_kdev(HWIF(drive)->major, minor);
stat = cdrom_get_last_written(dev, &toc->capacity);
if (stat)
stat = cdrom_read_capacity(drive, &toc->capacity, sense);
@@ -2481,7 +2481,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
struct cdrom_device_info *devinfo = &info->devinfo;
int minor = (drive->select.b.unit) << PARTN_BITS;
- devinfo->dev = MKDEV (HWIF(drive)->major, minor);
+ devinfo->dev = mk_kdev(HWIF(drive)->major, minor);
devinfo->ops = &ide_cdrom_dops;
devinfo->mask = 0;
*(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed;
@@ -2588,6 +2588,13 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup)
CDROM_CONFIG_FLAGS (drive)->close_tray = 0;
+ /* Some drives used by Apple don't advertise audio play
+ * but they do support reading TOC & audio datas
+ */
+ if (strcmp (drive->id->model, "MATSHITADVD-ROM SR-8187") == 0 ||
+ strcmp (drive->id->model, "MATSHITADVD-ROM SR-8186") == 0)
+ CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
+
#if ! STANDARD_ATAPI
if (cdi->sanyo_slot > 0) {
CDROM_CONFIG_FLAGS (drive)->is_changer = 1;
@@ -2671,8 +2678,8 @@ int ide_cdrom_setup (ide_drive_t *drive)
/*
* default to read-only always and fix latter at the bottom
*/
- set_device_ro(MKDEV(HWIF(drive)->major, minor), 1);
- set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
+ set_device_ro(mk_kdev(HWIF(drive)->major, minor), 1);
+ set_blocksize(mk_kdev(HWIF(drive)->major, minor), CD_FRAMESIZE);
blk_queue_hardsect_size(&drive->queue, CD_FRAMESIZE);
blk_queue_prep_rq(&drive->queue, ll_10byte_cmd_build);
@@ -2794,7 +2801,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
nslots = ide_cdrom_probe_capabilities (drive);
if (CDROM_CONFIG_FLAGS(drive)->dvd_ram)
- set_device_ro(MKDEV(HWIF(drive)->major, minor), 0);
+ set_device_ro(mk_kdev(HWIF(drive)->major, minor), 0);
if (ide_cdrom_register (drive, nslots)) {
printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
@@ -2841,7 +2848,7 @@ void ide_cdrom_release (struct inode *inode, struct file *file,
static
int ide_cdrom_check_media_change (ide_drive_t *drive)
{
- return cdrom_media_changed(MKDEV (HWIF (drive)->major,
+ return cdrom_media_changed(mk_kdev (HWIF (drive)->major,
(drive->select.b.unit) << PARTN_BITS));
}
@@ -2869,7 +2876,7 @@ void ide_cdrom_revalidate (ide_drive_t *drive)
* 1024 even for CDROM's
*/
blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
- set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
+ set_blocksize(mk_kdev(HWIF(drive)->major, minor), CD_FRAMESIZE);
}
static
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 9206953f2..000fe8a45 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -30,7 +30,7 @@
* Version 1.11 Highmem I/O support, Jens Axboe <axboe@suse.de>
*/
-#define IDEDISK_VERSION "1.10"
+#define IDEDISK_VERSION "1.11"
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -70,7 +70,7 @@ static void idedisk_bswap_data (void *buffer, int wcount)
}
}
-static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
{
ide_input_data(drive, buffer, wcount);
if (drive->bswap)
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 3ed90eeaf..ca55f3b18 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -2029,9 +2029,10 @@ static void __exit idefloppy_exit (void)
printk ("%s: cleanup_module() called while still busy\n", drive->name);
failed++;
}
+
+#ifdef CONFIG_PROC_FS
/* We must remove proc entries defined in this module.
Otherwise we oops while accessing these entries */
-#ifdef CONFIG_PROC_FS
if (drive->proc)
ide_remove_proc_entries(drive->proc, idefloppy_proc);
#endif
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 3f93dcc90..abdfccd98 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -595,17 +595,18 @@ static void ide_init_queue(ide_drive_t *drive)
{
request_queue_t *q = &drive->queue;
int max_sectors;
+#ifdef CONFIG_BLK_DEV_PDC4030
+ int is_pdc4030_chipset = (HWIF(drive)->chipset == ide_pdc4030);
+#else
+ const int is_pdc4030_chipset = 0;
+#endif
q->queuedata = HWGROUP(drive);
blk_init_queue(q, do_ide_request, &ide_lock);
blk_queue_segment_boundary(q, 0xffff);
/* IDE can do up to 128K per request, pdc4030 needs smaller limit */
-#ifdef CONFIG_BLK_DEV_PDC4030
- max_sectors = 127;
-#else
- max_sectors = 255;
-#endif
+ max_sectors = (is_pdc4030_chipset ? 127 : 255);
blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */
@@ -796,9 +797,7 @@ static void init_gendisk (ide_hwif_t *hwif)
gd->major = hwif->major; /* our major device number */
gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */
gd->minor_shift = PARTN_BITS; /* num bits for partitions */
- gd->max_p = 1<<PARTN_BITS; /* 1 + max partitions / drive */
gd->nr_real = units; /* current num real drives */
- gd->real_devices= hwif; /* ptr to internal data */
gd->next = NULL; /* linked list of major devs */
gd->fops = ide_fops; /* file operations */
gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index 73fead8d8..c1196ce15 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -2,11 +2,9 @@
#define _IDE_TIMING_H
/*
- * $Id: ide-timing.h,v 1.5 2001/01/15 21:48:56 vojtech Exp $
+ * $Id: ide-timing.h,v 1.6 2001/12/23 22:47:56 vojtech Exp $
*
- * Copyright (c) 1999-2000 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
@@ -25,16 +23,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/hdreg.h>
-#ifndef XFER_PIO_5
#define XFER_PIO_5 0x0d
#define XFER_UDMA_SLOW 0x4f
-#endif
struct ide_timing {
short mode;
@@ -49,13 +45,15 @@ struct ide_timing {
};
/*
- * PIO 0-5, MWDMA 0-2 and UDMA 0-5 timings (in nanoseconds).
+ * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
* These were taken from ATA/ATAPI-6 standard, rev 0a, except
- * for PIO 5, which is a nonstandard extension.
+ * for PIO 5, which is a nonstandard extension and UDMA6, which
+ * is currently supported only by Maxtor drives.
*/
static struct ide_timing ide_timing[] = {
+ { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
{ XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
{ XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
{ XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
@@ -105,6 +103,7 @@ static struct ide_timing ide_timing[] = {
#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
#define XFER_MODE 0xf0
+#define XFER_UDMA_133 0x48
#define XFER_UDMA_100 0x44
#define XFER_UDMA_66 0x42
#define XFER_UDMA 0x40
@@ -123,6 +122,9 @@ static short ide_find_best_mode(ide_drive_t *drive, int map)
if ((map & XFER_UDMA) && (id->field_valid & 4)) { /* Want UDMA and UDMA bitmap valid */
+ if ((map & XFER_UDMA_133) == XFER_UDMA_133)
+ if ((best = (id->dma_ultra & 0x0040) ? XFER_UDMA_6 : 0)) return best;
+
if ((map & XFER_UDMA_100) == XFER_UDMA_100)
if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
@@ -174,14 +176,14 @@ static short ide_find_best_mode(ide_drive_t *drive, int map)
static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int T, int UT)
{
- q->setup = EZ(t->setup, T);
- q->act8b = EZ(t->act8b, T);
- q->rec8b = EZ(t->rec8b, T);
- q->cyc8b = EZ(t->cyc8b, T);
- q->active = EZ(t->active, T);
- q->recover = EZ(t->recover, T);
- q->cycle = EZ(t->cycle, T);
- q->udma = EZ(t->udma, UT);
+ q->setup = EZ(t->setup * 1000, T);
+ q->act8b = EZ(t->act8b * 1000, T);
+ q->rec8b = EZ(t->rec8b * 1000, T);
+ q->cyc8b = EZ(t->cyc8b * 1000, T);
+ q->active = EZ(t->active * 1000, T);
+ q->recover = EZ(t->recover * 1000, T);
+ q->cycle = EZ(t->cycle * 1000, T);
+ q->udma = EZ(t->udma * 1000, UT);
}
static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index c4eb0a4a3..344dddac2 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -580,7 +580,7 @@ inline int __ide_end_request(ide_hwgroup_t *hwgroup, int uptodate, int nr_secs)
}
if (!end_that_request_first(rq, uptodate, nr_secs)) {
- add_blkdev_randomness(MAJOR(rq->rq_dev));
+ add_blkdev_randomness(major(rq->rq_dev));
blkdev_dequeue_request(rq);
hwgroup->rq = NULL;
end_that_request_last(rq);
@@ -653,7 +653,7 @@ void ide_geninit (ide_hwif_t *hwif)
continue;
if (drive->media!=ide_disk && drive->media!=ide_floppy)
continue;
- register_disk(gd,MKDEV(hwif->major,unit<<PARTN_BITS),
+ register_disk(gd,mk_kdev(hwif->major,unit<<PARTN_BITS),
#ifdef CONFIG_BLK_DEV_ISAPNP
(drive->forced_geom && drive->noprobe) ? 1 :
#endif /* CONFIG_BLK_DEV_ISAPNP */
@@ -1223,7 +1223,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
unsigned long block;
- unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS;
+ unsigned int minor = minor(rq->rq_dev), unit = minor >> PARTN_BITS;
ide_hwif_t *hwif = HWIF(drive);
BUG_ON(!(rq->flags & REQ_STARTED));
@@ -1241,12 +1241,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
goto kill_rq;
}
-#ifdef DEBUG
- if (rq->bh && !buffer_locked(rq->bh)) {
- printk("%s: block not locked\n", drive->name);
- goto kill_rq;
- }
-#endif
block = rq->sector;
/* Strange disk manager remap */
@@ -1478,7 +1472,7 @@ static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
*/
request_queue_t *ide_get_queue (kdev_t dev)
{
- ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data;
+ ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[major(dev)].data;
return &hwif->drives[DEVICE_NR(dev) & 1].queue;
}
@@ -1784,7 +1778,7 @@ out_lock:
*/
ide_drive_t *get_info_ptr (kdev_t i_rdev)
{
- int major = MAJOR(i_rdev);
+ int major = major(i_rdev);
unsigned int h;
for (h = 0; h < MAX_HWIFS; ++h) {
@@ -1851,7 +1845,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
#endif
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;
- rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);
+ rq->rq_dev = mk_kdev(major,(drive->select.b.unit)<<PARTN_BITS);
if (action == ide_wait)
rq->waiting = &wait;
spin_lock_irqsave(&ide_lock, flags);
@@ -1880,7 +1874,7 @@ void ide_revalidate_drive (ide_drive_t *drive)
{
struct gendisk *g = HWIF(drive)->gd;
int minor = (drive->select.b.unit << g->minor_shift);
- kdev_t dev = MKDEV(g->major, minor);
+ kdev_t dev = mk_kdev(g->major, minor);
grok_partitions(dev, current_capacity(drive));
}
@@ -1939,7 +1933,7 @@ static void revalidate_drives (void)
if (drive->revalidate) {
drive->revalidate = 0;
if (!initializing)
- (void) ide_revalidate_disk(MKDEV(hwif->major, unit<<PARTN_BITS));
+ (void) ide_revalidate_disk(mk_kdev(hwif->major, unit<<PARTN_BITS));
}
}
}
@@ -2119,7 +2113,7 @@ void ide_unregister (unsigned int index)
minor = drive->select.b.unit << PARTN_BITS;
for (p = 0; p < (1<<PARTN_BITS); ++p) {
if (drive->part[p].nr_sects > 0) {
- kdev_t devp = MKDEV(hwif->major, minor+p);
+ kdev_t devp = mk_kdev(hwif->major, minor+p);
invalidate_device(devp, 0);
}
}
@@ -2624,9 +2618,8 @@ static int ide_ioctl (struct inode *inode, struct file *file,
kdev_t dev;
ide_settings_t *setting;
- if (!inode || !(dev = inode->i_rdev))
- return -EINVAL;
- major = MAJOR(dev); minor = MINOR(dev);
+ dev = inode->i_rdev;
+ major = major(dev); minor = minor(dev);
if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
return -ENODEV;
@@ -2635,7 +2628,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
err = ide_read_setting(drive, setting);
return err >= 0 ? put_user(err, (long *) arg) : err;
} else {
- if ((MINOR(inode->i_rdev) & PARTN_MASK))
+ if ((minor(inode->i_rdev) & PARTN_MASK))
return -EINVAL;
return ide_write_setting(drive, setting, arg);
}
@@ -2651,7 +2644,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT;
if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT;
if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT;
- if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,
+ if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
(unsigned long *) &loc->start)) return -EFAULT;
return 0;
}
@@ -2664,7 +2657,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT;
if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT;
if (put_user(drive->bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT;
- if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,
+ if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
(unsigned long *) &loc->start)) return -EFAULT;
return 0;
}
@@ -2676,7 +2669,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
if (put_user(drive->head, (byte *) &loc->heads)) return -EFAULT;
if (put_user(drive->sect, (byte *) &loc->sectors)) return -EFAULT;
if (put_user(drive->cyl, (unsigned int *) &loc->cylinders)) return -EFAULT;
- if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,
+ if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
(unsigned long *) &loc->start)) return -EFAULT;
return 0;
}
@@ -2687,7 +2680,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case HDIO_OBSOLETE_IDENTITY:
case HDIO_GET_IDENTITY:
- if (MINOR(inode->i_rdev) & PARTN_MASK)
+ if (minor(inode->i_rdev) & PARTN_MASK)
return -EINVAL;
if (drive->id == NULL)
return -ENOMSG;
diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c
index d4beef75a..abafb7afa 100644
--- a/drivers/ide/pdc4030.c
+++ b/drivers/ide/pdc4030.c
@@ -66,8 +66,10 @@
* some technical information which has shed a glimmer of light on some of the
* problems I was having, especially with writes.
*
- * There are still problems with the robustness and efficiency of this driver
- * because I still don't understand what the card is doing with interrupts.
+ * There are still potential problems with the robustness and efficiency of
+ * this driver because I still don't understand what the card is doing with
+ * interrupts, however, it has been stable for a while with no reports of ill
+ * effects.
*/
#define DEBUG_READ
@@ -308,7 +310,9 @@ static ide_startstop_t promise_read_intr (ide_drive_t *drive)
byte stat;
int total_remaining;
unsigned int sectors_left, sectors_avail, nsect;
+ unsigned long flags;
struct request *rq;
+ char *to;
if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
return ide_error(drive, "promise_read_intr", stat);
@@ -330,15 +334,15 @@ read_next:
if (nsect > sectors_avail)
nsect = sectors_avail;
sectors_avail -= nsect;
- ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
+ to = ide_map_buffer(rq, &flags);
+ idedisk_input_data(drive, to, nsect * SECTOR_WORDS);
#ifdef DEBUG_READ
printk(KERN_DEBUG "%s: promise_read: sectors(%ld-%ld), "
"buf=0x%08lx, rem=%ld\n", drive->name, rq->sector,
- rq->sector+nsect-1, (unsigned long) rq->buffer,
- rq->nr_sectors-nsect);
+ rq->sector+nsect-1, (unsigned long) to, rq->nr_sectors-nsect);
#endif
+ ide_unmap_buffer(to, &flags);
rq->sector += nsect;
- rq->buffer += nsect<<9;
rq->errors = 0;
rq->nr_sectors -= nsect;
total_remaining = rq->nr_sectors;
@@ -406,10 +410,7 @@ static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
#endif
- for (i = rq->nr_sectors; i > 0; ) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, hwgroup);
- }
+ __ide_end_request(hwgroup, 1, rq->nr_sectors);
return ide_stopped;
}
@@ -498,7 +499,15 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
unsigned long timeout;
byte stat;
- if (rq->cmd == READ) {
+/* Check that it's a regular command. If not, bomb out early. */
+ if (!(rq->flags & REQ_CMD)) {
+ blk_dump_rq_flags(rq, "pdc4030 bad flags");
+ ide_end_request(0, HWGROUP(drive));
+ return ide_stopped;
+ }
+
+ switch (rq_data_dir(rq)) {
+ case READ:
OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
/*
* The card's behaviour is odd at this point. If the data is
@@ -531,9 +540,18 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n",
drive->name);
return ide_stopped;
- } else if (rq->cmd == WRITE) {
+ break;
+
+ case WRITE:
ide_startstop_t startstop;
OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
+/*
+ * Strategy on write is:
+ * look for the DRQ that should have been immediately asserted
+ * copy the request into the hwgroup's scratchpad
+ * call the promise_write function to deal with writing the data out
+ * NOTE: No interrupts are generated on writes. Write completion must be polled
+ */
if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing "
"PROMISE_WRITE\n", drive->name);
@@ -543,11 +561,11 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
__cli(); /* local CPU only */
HWGROUP(drive)->wrq = *rq; /* scratchpad */
return promise_write(drive);
+ break;
- } else {
- printk("KERN_WARNING %s: bad command: %d\n",
- drive->name, rq->cmd);
+ default:
+ printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n");
ide_end_request(0, HWGROUP(drive));
- return ide_stopped;
+ break;
}
}
diff --git a/drivers/ide/pdcraid.c b/drivers/ide/pdcraid.c
index 7a2e093b3..5ad8d314c 100644
--- a/drivers/ide/pdcraid.c
+++ b/drivers/ide/pdcraid.c
@@ -387,18 +387,14 @@ static int pdcraid1_make_request (request_queue_t *q, int rw, struct buffer_head
#include "pdcraid.h"
-static unsigned long calc_pdcblock_offset (int major,int minor)
+static unsigned long calc_pdcblock_offset(struct block_device *bdev)
{
unsigned long lba = 0;
- kdev_t dev;
- ide_drive_t *ideinfo;
-
- dev = MKDEV(major,minor);
- ideinfo = get_info_ptr (dev);
+ ide_drive_t *ideinfo = get_info_ptr(to_kdev_t(bdev->bd_dev));
+
if (ideinfo==NULL)
return 0;
-
-
+
/* first sector of the last cluster */
if (ideinfo->head==0)
return 0;
@@ -412,42 +408,32 @@ static unsigned long calc_pdcblock_offset (int major,int minor)
}
-static int read_disk_sb (int major, int minor, unsigned char *buffer,int bufsize)
+static int read_disk_sb(struct block_device *bdev, struct promise_raid_conf *p)
{
- int ret = -EINVAL;
- struct buffer_head *bh = NULL;
- kdev_t dev = MKDEV(major,minor);
unsigned long sb_offset;
+ char *buffer;
+ int i;
- if (blksize_size[major]==NULL) /* device doesn't exist */
- return -EINVAL;
-
-
/*
* Calculate the position of the superblock,
* it's at first sector of the last cylinder
*/
- sb_offset = calc_pdcblock_offset(major,minor)/8;
- /* The /8 transforms sectors into 4Kb blocks */
+ sb_offset = calc_pdcblock_offset(bdev);
if (sb_offset==0)
return -1;
-
- set_blocksize (dev, 4096);
- bh = bread (dev, sb_offset, 4096);
-
- if (bh) {
- memcpy (buffer, bh->b_data, bufsize);
- } else {
- printk(KERN_ERR "pdcraid: Error reading superblock.\n");
- goto abort;
+ for (i = 0, buffer = (char*)p; i < 4; i++, buffer += 512) {
+ Sector sect;
+ char *q = read_dev_sector(bdev, sb_offset + i, &sect);
+ if (!p) {
+ printk(KERN_ERR "pdcraid: Error reading superblock.\n");
+ return -1;
+ }
+ memcpy(buffer, q, 512);
+ put_dev_sector(&sect);
}
- ret = 0;
-abort:
- if (bh)
- brelse (bh);
- return ret;
+ return 0;
}
static unsigned int calc_sb_csum (unsigned int* ptr)
@@ -464,12 +450,11 @@ static unsigned int calc_sb_csum (unsigned int* ptr)
static int cookie = 0;
+static struct promise_raid_conf __initdata prom;
static void __init probedisk(int devindex,int device, int raidlevel)
{
int i;
int major, minor;
- struct promise_raid_conf *prom;
- static unsigned char block[4096];
struct block_device *bdev;
if (devlist[devindex].device!=-1) /* already assigned to another array */
@@ -478,44 +463,48 @@ static void __init probedisk(int devindex,int device, int raidlevel)
major = devlist[devindex].major;
minor = devlist[devindex].minor;
- if (read_disk_sb(major,minor,(unsigned char*)&block,sizeof(block)))
- return;
-
- prom = (struct promise_raid_conf*)&block[512];
-
- /* the checksums must match */
- if (prom->checksum != calc_sb_csum((unsigned int*)prom))
- return;
- if (prom->raid.type!=raidlevel) /* different raidlevel */
+ bdev = bdget(MKDEV(major,minor));
+ if (!bdev)
return;
- if ((cookie!=0) && (cookie != prom->raid.magic_1)) /* different array */
+ if (blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW) != 0)
return;
+
+ if (read_disk_sb(bdev, &prom))
+ goto out;
+
+ /* the checksums must match */
+ if (prom.checksum != calc_sb_csum((unsigned int*)&prom))
+ goto out;
+ if (prom.raid.type!=raidlevel) /* different raidlevel */
+ goto out;
+
+ if ((cookie!=0) && (cookie != prom.raid.magic_1)) /* different array */
+ goto out;
- cookie = prom->raid.magic_1;
+ cookie = prom.raid.magic_1;
/* This looks evil. But basically, we have to search for our adapternumber
in the arraydefinition, both of which are in the superblock */
- for (i=0;(i<prom->raid.total_disks)&&(i<8);i++) {
- if ( (prom->raid.disk[i].channel== prom->raid.channel) &&
- (prom->raid.disk[i].device == prom->raid.device) ) {
-
- bdev = bdget(MKDEV(major,minor));
- if (bdev && blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW) == 0) {
- raid[device].disk[i].bdev = bdev;
- }
+ for (i=0;(i<prom.raid.total_disks)&&(i<8);i++) {
+ if ( (prom.raid.disk[i].channel== prom.raid.channel) &&
+ (prom.raid.disk[i].device == prom.raid.device) ) {
+
+ raid[device].disk[i].bdev = bdev;
raid[device].disk[i].device = MKDEV(major,minor);
- raid[device].disk[i].sectors = prom->raid.disk_secs;
- raid[device].stride = (1<<prom->raid.raid0_shift);
- raid[device].disks = prom->raid.total_disks;
- raid[device].sectors = prom->raid.total_secs;
- raid[device].geom.heads = prom->raid.heads+1;
- raid[device].geom.sectors = prom->raid.sectors;
- raid[device].geom.cylinders = prom->raid.cylinders+1;
+ raid[device].disk[i].sectors = prom.raid.disk_secs;
+ raid[device].stride = (1<<prom.raid.raid0_shift);
+ raid[device].disks = prom.raid.total_disks;
+ raid[device].sectors = prom.raid.total_secs;
+ raid[device].geom.heads = prom.raid.heads+1;
+ raid[device].geom.sectors = prom.raid.sectors;
+ raid[device].geom.cylinders = prom.raid.cylinders+1;
devlist[devindex].device=device;
- }
+ return;
+ }
}
-
+out:
+ blkdev_put(bdev, BDEV_RAW);
}
static void __init fill_cutoff(int device)
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index f956272be..d2cd5be30 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -1,5 +1,5 @@
/*
- * $Id: via82cxxx.c,v 3.29 2001/09/10 10:06:00 vojtech Exp $
+ * $Id: via82cxxx.c,v 3.33 2001/12/23 22:46:12 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
@@ -7,23 +7,21 @@
* Michel Aubry
* Jeff Garzik
* Andre Hedrick
- *
- * Sponsored by SuSE
*/
/*
* VIA IDE driver for Linux. Supports
*
* vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
- * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233
+ * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a
*
* southbridges, which can be found in
*
* VIA Apollo Master, VP, VP2, VP2/97, VP3, VPX, VPX/97, MVP3, MVP4, P6, Pro,
* ProII, ProPlus, Pro133, Pro133+, Pro133A, Pro133A Dual, Pro133T, Pro133Z,
* PLE133, PLE133T, Pro266, Pro266T, ProP4X266, PM601, PM133, PN133, PL133T,
- * PX266, PM266, KX133, KT133, KT133A, KLE133, KT266, KX266, KM133, KM133A,
- * KL133, KN133, KM266
+ * PX266, PM266, KX133, KT133, KT133A, KT133E, KLE133, KT266, KX266, KM133,
+ * KM133A, KL133, KN133, KM266
* PC-Chips VXPro, VXPro+, VXTwo, TXPro-III, TXPro-AGP, AGPPro, ViaGra, BXToo,
* BXTel, BXpert
* AMD 640, 640 AGP, 750 IronGate, 760, 760MP
@@ -32,9 +30,9 @@
*
* chipsets. Supports
*
- * PIO 0-5, MWDMA 0-2, SWDMA 0-2 and UDMA 0-5
+ * PIO 0-5, MWDMA 0-2, SWDMA 0-2 and UDMA 0-6
*
- * (this includes UDMA33, 66 and 100) modes. UDMA66 and higher modes are
+ * (this includes UDMA33, 66, 100 and 133) modes. UDMA66 and higher modes are
* autoenabled only in case the BIOS has detected a 80 wire cable. To ignore
* the BIOS data and assume the cable is present, use 'ide0=ata66' or
* 'ide1=ata66' on the kernel command line.
@@ -56,8 +54,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/config.h>
@@ -87,10 +85,12 @@
#define VIA_UDMA_33 0x001
#define VIA_UDMA_66 0x002
#define VIA_UDMA_100 0x003
+#define VIA_UDMA_133 0x004
#define VIA_BAD_PREQ 0x010 /* Crashes if PREQ# till DDACK# set */
#define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */
#define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */
#define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */
+#define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */
/*
* VIA SouthBridge chips.
@@ -104,10 +104,11 @@ static struct via_isa_bridge {
unsigned short flags;
} via_isa_bridges[] = {
#ifdef FUTURE_BRIDGES
- { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt8233c", PCI_DEVICE_ID_VIA_8233C, 0x00, 0x2f, VIA_UDMA_100 },
+ { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 },
+ { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 },
#endif
+ { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 },
+ { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 },
{ "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 },
{ "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 },
{ "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 },
@@ -121,6 +122,7 @@ static struct via_isa_bridge {
{ "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },
{ "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
{ "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },
+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
{ NULL }
};
@@ -128,7 +130,7 @@ static struct via_isa_bridge *via_config;
static unsigned char via_enabled;
static unsigned int via_80w;
static unsigned int via_clock;
-static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" };
+static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
/*
* VIA /proc entry.
@@ -151,7 +153,7 @@ static char *via_control3[] = { "No limit", "64", "128", "192" };
static int via_get_info(char *buffer, char **addr, off_t offset, int count)
{
- short speed[4], cycle[4], setup[4], active[4], recover[4], den[4],
+ int speed[4], cycle[4], setup[4], active[4], recover[4], den[4],
uen[4], udma[4], umul[4], active8b[4], recover8b[4];
struct pci_dev *dev = bmide_dev;
unsigned int v, u, i;
@@ -161,7 +163,7 @@ static int via_get_info(char *buffer, char **addr, off_t offset, int count)
via_print("----------VIA BusMastering IDE Configuration----------------");
- via_print("Driver Version: 3.29");
+ via_print("Driver Version: 3.33");
via_print("South Bridge: VIA %s", via_config->name);
pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t);
@@ -170,7 +172,7 @@ static int via_get_info(char *buffer, char **addr, off_t offset, int count)
via_print("Highest DMA rate: %s", via_dma[via_config->flags & VIA_UDMA]);
via_print("BM-DMA base: %#x", via_base);
- via_print("PCI clock: %dMHz", via_clock);
+ via_print("PCI clock: %d.%dMHz", via_clock / 1000, via_clock / 100 % 10);
pci_read_config_byte(dev, VIA_MISC_1, &t);
via_print("Master Read Cycle IRDY: %dws", (t & 64) >> 6);
@@ -218,40 +220,45 @@ static int via_get_info(char *buffer, char **addr, off_t offset, int count)
uen[i] = ((u >> ((3 - i) << 3)) & 0x20);
den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2));
- speed[i] = 20 * via_clock / (active[i] + recover[i]);
- cycle[i] = 1000 / via_clock * (active[i] + recover[i]);
+ speed[i] = 2 * via_clock / (active[i] + recover[i]);
+ cycle[i] = 1000000 * (active[i] + recover[i]) / via_clock;
if (!uen[i] || !den[i])
continue;
switch (via_config->flags & VIA_UDMA) {
-
- case VIA_UDMA_100:
- speed[i] = 60 * via_clock / udma[i];
- cycle[i] = 333 / via_clock * udma[i];
+
+ case VIA_UDMA_33:
+ speed[i] = 2 * via_clock / udma[i];
+ cycle[i] = 1000000 * udma[i] / via_clock;
break;
case VIA_UDMA_66:
- speed[i] = 40 * via_clock / (udma[i] * umul[i]);
- cycle[i] = 500 / via_clock * (udma[i] * umul[i]);
+ speed[i] = 4 * via_clock / (udma[i] * umul[i]);
+ cycle[i] = 500000 * (udma[i] * umul[i]) / via_clock;
break;
- case VIA_UDMA_33:
- speed[i] = 20 * via_clock / udma[i];
- cycle[i] = 1000 / via_clock * udma[i];
+ case VIA_UDMA_100:
+ speed[i] = 6 * via_clock / udma[i];
+ cycle[i] = 333333 * udma[i] / via_clock;
+ break;
+
+ case VIA_UDMA_133:
+ speed[i] = 8 * via_clock / udma[i];
+ cycle[i] = 250000 * udma[i] / via_clock;
break;
}
}
via_print_drive("Transfer Mode: ", "%10s", den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO");
- via_print_drive("Address Setup: ", "%8dns", (1000 / via_clock) * setup[i]);
- via_print_drive("Cmd Active: ", "%8dns", (1000 / via_clock) * active8b[i]);
- via_print_drive("Cmd Recovery: ", "%8dns", (1000 / via_clock) * recover8b[i]);
- via_print_drive("Data Active: ", "%8dns", (1000 / via_clock) * active[i]);
- via_print_drive("Data Recovery: ", "%8dns", (1000 / via_clock) * recover[i]);
+ via_print_drive("Address Setup: ", "%8dns", 1000000 * setup[i] / via_clock);
+ via_print_drive("Cmd Active: ", "%8dns", 1000000 * active8b[i] / via_clock);
+ via_print_drive("Cmd Recovery: ", "%8dns", 1000000 * recover8b[i] / via_clock);
+ via_print_drive("Data Active: ", "%8dns", 1000000 * active[i] / via_clock);
+ via_print_drive("Data Recovery: ", "%8dns", 1000000 * recover[i] / via_clock);
via_print_drive("Cycle Time: ", "%8dns", cycle[i]);
- via_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 10, speed[i] % 10);
+ via_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10);
return p - buffer; /* hoping it is less than 4K... */
}
@@ -280,6 +287,7 @@ static void via_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+ case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
default: return;
}
@@ -296,20 +304,21 @@ static int via_set_drive(ide_drive_t *drive, unsigned char speed)
{
ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
struct ide_timing t, p;
- int T, UT;
+ unsigned int T, UT;
if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
if (ide_config_drive_speed(drive, speed))
printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n",
drive->dn >> 1, drive->dn & 1);
- T = 1000 / via_clock;
+ T = 1000000000 / via_clock;
switch (via_config->flags & VIA_UDMA) {
case VIA_UDMA_33: UT = T; break;
case VIA_UDMA_66: UT = T/2; break;
case VIA_UDMA_100: UT = T/3; break;
- default: UT = T; break;
+ case VIA_UDMA_133: UT = T/4; break;
+ default: UT = T;
}
ide_timing_compute(drive, speed, &t, T, UT);
@@ -365,7 +374,8 @@ int via82cxxx_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
(via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
(w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
- (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0));
+ (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
+ (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
via_set_drive(drive, speed);
@@ -395,14 +405,16 @@ unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name)
*/
for (via_config = via_isa_bridges; via_config->id; via_config++)
- if ((isa = pci_find_device(PCI_VENDOR_ID_VIA, via_config->id, NULL))) {
+ if ((isa = pci_find_device(PCI_VENDOR_ID_VIA +
+ !!(via_config->flags & VIA_BAD_ID), via_config->id, NULL))) {
+
pci_read_config_byte(isa, PCI_REVISION_ID, &t);
if (t >= via_config->rev_min && t <= via_config->rev_max)
break;
}
if (!via_config->id) {
- printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, contact Vojtech Pavlik <vojtech@suse.cz>\n");
+ printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, contact Vojtech Pavlik <vojtech@ucw.cz>\n");
return -ENODEV;
}
@@ -412,22 +424,28 @@ unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name)
switch (via_config->flags & VIA_UDMA) {
- case VIA_UDMA_100:
-
- pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
- for (i = 24; i >= 0; i -= 8)
- if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 3)))
- via_80w |= (1 << (1 - (i >> 4))); /* BIOS 80-wire bit or UDMA w/ < 50ns/cycle */
- break;
-
case VIA_UDMA_66:
-
pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Enable Clk66 */
pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);
for (i = 24; i >= 0; i -= 8)
if (((u >> (i & 16)) & 8) && ((u >> i) & 0x20) && (((u >> i) & 7) < 2))
via_80w |= (1 << (1 - (i >> 4))); /* 2x PCI clock and UDMA w/ < 3T/cycle */
break;
+
+ case VIA_UDMA_100:
+ pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+ for (i = 24; i >= 0; i -= 8)
+ if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 4)))
+ via_80w |= (1 << (1 - (i >> 4))); /* BIOS 80-wire bit or UDMA w/ < 60ns/cycle */
+ break;
+
+ case VIA_UDMA_133:
+ pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+ for (i = 24; i >= 0; i -= 8)
+ if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 8)))
+ via_80w |= (1 << (1 - (i >> 4))); /* BIOS 80-wire bit or UDMA w/ < 60ns/cycle */
+ break;
+
}
if (via_config->flags & VIA_BAD_CLK66) { /* Disable Clk66 */
@@ -466,10 +484,17 @@ unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name)
* Determine system bus clock.
*/
- via_clock = system_bus_clock();
- if (via_clock < 20 || via_clock > 50) {
+ via_clock = system_bus_clock() * 1000;
+
+ switch (via_clock) {
+ case 33000: via_clock = 33333; break;
+ case 37000: via_clock = 37500; break;
+ case 41000: via_clock = 41666; break;
+ }
+
+ if (via_clock < 20000 || via_clock > 50000) {
printk(KERN_WARNING "VP_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", via_clock);
- printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want to force UDMA66/UDMA100.\n");
+ printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want to assume 80-wire cable.\n");
via_clock = 33;
}
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 970ec27a7..9f2816e99 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -99,7 +99,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
#include <linux/vmalloc.h>
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 670e3ea6e..4be8872a4 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -915,7 +915,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
{
struct file_info *fi;
- if (MINOR(inode->i_rdev)) {
+ if (minor(inode->i_rdev)) {
return -ENXIO;
}
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index c6a184248..fc362f7ea 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -2947,7 +2947,7 @@ static int sbp2_module_init(void)
* least one host, so we "nest" the registrations by calling
* sbp2_init from the detect function.
*/
- if (scsi_register_module(MODULE_SCSI_HA, &scsi_driver_template) ||
+ if (scsi_register_host(&scsi_driver_template) ||
!scsi_driver_template.present) {
SBP2_ERR("Please load the lower level IEEE-1394 driver "
"(e.g. ohci1394) before sbp2...");
@@ -2970,7 +2970,7 @@ static void __exit sbp2_module_exit(void)
*/
sbp2_cleanup();
- if (scsi_unregister_module(MODULE_SCSI_HA, &scsi_driver_template))
+ if (scsi_unregister_host(&scsi_driver_template))
SBP2_ERR("sbp2_module_exit: couldn't unregister scsi driver");
}
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 72f0fe00c..ff14786f5 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -43,7 +43,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
#include <linux/vmalloc.h>
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 531b07edd..62f5adcdd 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -119,7 +119,7 @@ static int evdev_release(struct inode * inode, struct file * file)
static int evdev_open(struct inode * inode, struct file * file)
{
struct evdev_list *list;
- int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE;
+ int i = minor(inode->i_rdev) - EVDEV_MINOR_BASE;
if (i >= EVDEV_MINORS || !evdev_table[i])
return -ENODEV;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 8c1775d60..eb7fe0f17 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -368,7 +368,7 @@ void input_unregister_handler(struct input_handler *handler)
static int input_open_file(struct inode *inode, struct file *file)
{
- struct input_handler *handler = input_table[MINOR(inode->i_rdev) >> 5];
+ struct input_handler *handler = input_table[minor(inode->i_rdev) >> 5];
struct file_operations *old_fops, *new_fops = NULL;
int err;
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index bf90692eb..f17165bdd 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -31,7 +31,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/joystick.h>
@@ -190,7 +189,7 @@ static int joydev_release(struct inode * inode, struct file * file)
static int joydev_open(struct inode *inode, struct file *file)
{
struct joydev_list *list;
- int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE;
+ int i = minor(inode->i_rdev) - JOYDEV_MINOR_BASE;
if (i >= JOYDEV_MINORS || !joydev_table[i])
return -ENODEV;
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index f9993eded..c37b6a0dd 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -214,7 +214,7 @@ static int mousedev_release(struct inode * inode, struct file * file)
static int mousedev_open(struct inode * inode, struct file * file)
{
struct mousedev_list *list;
- int i = MINOR(inode->i_rdev) - MOUSEDEV_MINOR_BASE;
+ int i = minor(inode->i_rdev) - MOUSEDEV_MINOR_BASE;
if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
return -ENODEV;
diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in
index 707940b33..77e8488ce 100644
--- a/drivers/isdn/Config.in
+++ b/drivers/isdn/Config.in
@@ -42,6 +42,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
fi
bool ' HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
bool ' HiSax Support for US NI1' CONFIG_HISAX_NI1
+ int ' Maximum number of cards supported by HiSax' CONFIG_HISAX_MAX_CARDS 8
comment ' HiSax supported cards'
bool ' Teles 16.0/8.0' CONFIG_HISAX_16_0
bool ' Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
@@ -81,7 +82,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA
dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA
dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
- dep_tristate 'Fritz!PCIv2 support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
+ dep_tristate 'AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
fi
endmenu
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h
index af991db4d..7f71f94dd 100644
--- a/drivers/isdn/act2000/act2000.h
+++ b/drivers/isdn/act2000/act2000.h
@@ -68,7 +68,6 @@ typedef struct act2000_fwid {
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
diff --git a/drivers/isdn/avmb1/avmcard.h b/drivers/isdn/avmb1/avmcard.h
index e33fb0d8d..15e4a2b9b 100644
--- a/drivers/isdn/avmb1/avmcard.h
+++ b/drivers/isdn/avmb1/avmcard.h
@@ -1,4 +1,4 @@
-/* $Id: avmcard.h,v 1.8.6.4 2001/09/23 22:24:33 kai Exp $
+/* $Id: avmcard.h,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
*
* Copyright 1999 by Carsten Paeth <calle@calle.de>
*
@@ -39,13 +39,21 @@ enum avmcardtype {
avm_c2
};
+typedef struct avmcard_dmabuf {
+ long size;
+ __u8 *dmabuf;
+ dma_addr_t dmaaddr;
+} avmcard_dmabuf;
+
typedef struct avmcard_dmainfo {
- __u32 recvlen;
- __u8 recvbuf[128+2048];
- struct sk_buff_head send_queue;
- __u8 sendbuf[128+2048];
-} avmcard_dmainfo;
+ __u32 recvlen;
+ avmcard_dmabuf recvbuf;
+
+ avmcard_dmabuf sendbuf;
+ struct sk_buff_head send_queue;
+ struct pci_dev *pcidev;
+} avmcard_dmainfo;
typedef struct avmcard {
char name[32];
@@ -544,6 +552,11 @@ void b1_handle_interrupt(avmcard * card);
int b1ctl_read_proc(char *page, char **start, off_t off,
int count, int *eof, struct capi_ctr *ctrl);
+avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *,
+ long rsize, long ssize);
+void avmcard_dma_free(avmcard_dmainfo *);
+
+
/* b1dma.c */
int b1pciv4_detect(avmcard *card);
int t1pci_detect(avmcard *card);
diff --git a/drivers/isdn/avmb1/b1.c b/drivers/isdn/avmb1/b1.c
index bf8a49bce..38430213f 100644
--- a/drivers/isdn/avmb1/b1.c
+++ b/drivers/isdn/avmb1/b1.c
@@ -1,4 +1,4 @@
-/* $Id: b1.c,v 1.20.6.7 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
*
* Common module for AVM B1 cards.
*
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/pci.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/mm.h>
@@ -27,7 +28,7 @@
#include "capicmd.h"
#include "capiutil.h"
-static char *revision = "$Revision: 1.20.6.7 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
/* ------------------------------------------------------------- */
@@ -639,6 +640,65 @@ int b1ctl_read_proc(char *page, char **start, off_t off,
/* ------------------------------------------------------------- */
+#ifdef CONFIG_PCI
+
+avmcard_dmainfo *
+avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize)
+{
+ avmcard_dmainfo *p;
+ void *buf;
+
+ p = kmalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
+ if (!p) {
+ printk(KERN_WARNING "%s: no memory.\n", name);
+ goto err;
+ }
+ memset(p, 0, sizeof(avmcard_dmainfo));
+
+ p->recvbuf.size = rsize;
+ buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr);
+ if (!buf) {
+ printk(KERN_WARNING "%s: allocation of receive dma buffer failed.\n", name);
+ goto err_kfree;
+ }
+ p->recvbuf.dmabuf = buf;
+
+ p->sendbuf.size = ssize;
+ buf = pci_alloc_consistent(pdev, ssize, &p->sendbuf.dmaaddr);
+ if (!buf) {
+ printk(KERN_WARNING "%s: allocation of send dma buffer failed.\n", name);
+ goto err_free_consistent;
+ }
+
+ p->sendbuf.dmabuf = buf;
+ skb_queue_head_init(&p->send_queue);
+
+ return p;
+
+ err_free_consistent:
+ pci_free_consistent(p->pcidev, p->recvbuf.size,
+ p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
+ err_kfree:
+ kfree(p);
+ err:
+ return 0;
+}
+
+void avmcard_dma_free(avmcard_dmainfo *p)
+{
+ pci_free_consistent(p->pcidev, p->recvbuf.size,
+ p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
+ pci_free_consistent(p->pcidev, p->sendbuf.size,
+ p->sendbuf.dmabuf, p->sendbuf.dmaaddr);
+ skb_queue_purge(&p->send_queue);
+ kfree(p);
+}
+
+EXPORT_SYMBOL(avmcard_dma_alloc);
+EXPORT_SYMBOL(avmcard_dma_free);
+
+#endif
+
EXPORT_SYMBOL(b1_irq_table);
EXPORT_SYMBOL(b1_detect);
diff --git a/drivers/isdn/avmb1/b1dma.c b/drivers/isdn/avmb1/b1dma.c
index c948463f6..f8b0320b3 100644
--- a/drivers/isdn/avmb1/b1dma.c
+++ b/drivers/isdn/avmb1/b1dma.c
@@ -1,4 +1,4 @@
-/* $Id: b1dma.c,v 1.11.6.8 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1dma.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
*
* Common module for AVM B1 cards that support dma with AMCC
*
@@ -32,7 +32,7 @@
#error FIXME: driver requires 32-bit platform
#endif
-static char *revision = "$Revision: 1.11.6.8 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
/* ------------------------------------------------------------- */
@@ -388,7 +388,7 @@ static void b1dma_dispatch_tx(avmcard *card)
cmd = CAPIMSG_COMMAND(skb->data);
subcmd = CAPIMSG_SUBCOMMAND(skb->data);
- p = dma->sendbuf;
+ p = dma->sendbuf.dmabuf;
if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
__u16 dlen = CAPIMSG_DATALEN(skb->data);
@@ -399,7 +399,7 @@ static void b1dma_dispatch_tx(avmcard *card)
_put_byte(&p, SEND_MESSAGE);
_put_slice(&p, skb->data, len);
}
- txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+ txlen = (__u8 *)p - (__u8 *)dma->sendbuf.dmabuf;
#ifdef CONFIG_B1DMA_DEBUG
printk(KERN_DEBUG "tx(%d): put msg len=%d\n",
inint, txlen);
@@ -414,11 +414,11 @@ static void b1dma_dispatch_tx(avmcard *card)
printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n",
inint, skb->data[2], txlen);
#endif
- memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+ memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
}
txlen = (txlen + 3) & ~3;
- b1dmaoutmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf));
+ b1dmaoutmeml(card->mbase+AMCC_TXPTR, dma->sendbuf.dmaaddr);
b1dmaoutmeml(card->mbase+AMCC_TXLEN, txlen);
card->csr |= EN_TX_TC_INT;
@@ -461,7 +461,7 @@ static void b1dma_handle_rx(avmcard *card)
avmcard_dmainfo *dma = card->dma;
struct capi_ctr *ctrl = cinfo->capi_ctrl;
struct sk_buff *skb;
- void *p = dma->recvbuf+4;
+ void *p = dma->recvbuf.dmabuf+4;
__u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
__u8 b1cmd = _get_byte(&p);
@@ -597,18 +597,19 @@ static void b1dma_handle_interrupt(avmcard *card)
b1dmaoutmeml(card->mbase+AMCC_INTCSR, newcsr);
if ((status & RX_TC_INT) != 0) {
- __u8 *recvbuf = card->dma->recvbuf;
+ struct avmcard_dmainfo *dma = card->dma;
__u32 rxlen;
if (card->dma->recvlen == 0) {
- card->dma->recvlen = *((__u32 *)recvbuf);
- rxlen = (card->dma->recvlen + 3) & ~3;
+ dma->recvlen = *((__u32 *)dma->recvbuf.dmabuf);
+ rxlen = (dma->recvlen + 3) & ~3;
b1dmaoutmeml(card->mbase+AMCC_RXPTR,
- virt_to_phys(recvbuf+4));
+ dma->recvbuf.dmaaddr+4);
b1dmaoutmeml(card->mbase+AMCC_RXLEN, rxlen);
} else {
b1dma_handle_rx(card);
- card->dma->recvlen = 0;
- b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf));
+ dma->recvlen = 0;
+ b1dmaoutmeml(card->mbase+AMCC_RXPTR,
+ dma->recvbuf.dmaaddr);
b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
}
}
@@ -744,7 +745,7 @@ int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
t1outp(card->port, 0x10, 0xF0);
card->dma->recvlen = 0;
- b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf));
+ b1dmaoutmeml(card->mbase+AMCC_RXPTR, card->dma->recvbuf.dmaaddr);
b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
card->csr |= EN_RX_TC_INT;
b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
@@ -855,7 +856,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
__u8 flag;
int len = 0;
char *s;
- __u32 txaddr, txlen, rxaddr, rxlen, csr;
+ __u32 txoff, txlen, rxoff, rxlen, csr;
len += sprintf(page+len, "%-16s %s\n", "name", card->name);
len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
@@ -911,13 +912,11 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
save_flags(flags);
cli();
- txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
- txaddr -= (__u32)card->dma->sendbuf;
- txlen = b1dmainmeml(card->mbase+0x30);
+ txoff = (dma_addr_t)b1dmainmeml(card->mbase+0x2c)-card->dma->sendbuf.dmaaddr;
+ txlen = b1dmainmeml(card->mbase+0x30);
- rxaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x24));
- rxaddr -= (__u32)card->dma->recvbuf;
- rxlen = b1dmainmeml(card->mbase+0x28);
+ rxoff = (dma_addr_t)b1dmainmeml(card->mbase+0x24)-card->dma->recvbuf.dmaaddr;
+ rxlen = b1dmainmeml(card->mbase+0x28);
csr = b1dmainmeml(card->mbase+AMCC_INTCSR);
@@ -928,11 +927,11 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
len += sprintf(page+len, "%-16s 0x%lx\n",
"csr", (unsigned long)csr);
len += sprintf(page+len, "%-16s %lu\n",
- "txoff", (unsigned long)txaddr);
+ "txoff", (unsigned long)txoff);
len += sprintf(page+len, "%-16s %lu\n",
"txlen", (unsigned long)txlen);
len += sprintf(page+len, "%-16s %lu\n",
- "rxoff", (unsigned long)rxaddr);
+ "rxoff", (unsigned long)rxoff);
len += sprintf(page+len, "%-16s %lu\n",
"rxlen", (unsigned long)rxlen);
diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c
index ef38a321e..7c378f031 100644
--- a/drivers/isdn/avmb1/b1pci.c
+++ b/drivers/isdn/avmb1/b1pci.c
@@ -1,4 +1,4 @@
-/* $Id: b1pci.c,v 1.29.6.5 2001/09/23 22:24:33 kai Exp $
+/* $Id: b1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
*
* Module for AVM B1 PCI-card.
*
@@ -26,7 +26,7 @@
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.29.6.5 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
/* ------------------------------------------------------------- */
@@ -108,7 +108,9 @@ static char *b1pci_procinfo(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
-static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int b1pci_add_card(struct capi_driver *driver,
+ struct capicardparams *p,
+ struct pci_dev *dev)
{
avmcard *card;
avmctrl_info *cinfo;
@@ -237,7 +239,7 @@ static void b1pciv4_remove_ctr(struct capi_ctr *ctrl)
release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
@@ -262,7 +264,9 @@ static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
-static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int b1pciv4_add_card(struct capi_driver *driver,
+ struct capicardparams *p,
+ struct pci_dev *dev)
{
avmcard *card;
avmctrl_info *cinfo;
@@ -278,18 +282,17 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
- card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+ card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
if (!card->dma) {
- printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ printk(KERN_WARNING "%s: dma alloc.\n", driver->name);
kfree(card);
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
- memset(card->dma, 0, sizeof(avmcard_dmainfo));
cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -ENOMEM;
@@ -308,7 +311,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
"%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EBUSY;
@@ -319,7 +322,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
driver->name, card->membase);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EIO;
@@ -332,7 +335,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
driver->name, card->port, retval);
iounmap(card->mbase);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EIO;
@@ -349,7 +352,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EBUSY;
@@ -362,15 +365,13 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EBUSY;
}
card->cardnr = cinfo->capi_ctrl->cnr;
- skb_queue_head_init(&card->dma->send_queue);
-
printk(KERN_INFO
"%s: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n",
driver->name, card->port, card->irq,
@@ -429,9 +430,9 @@ static int add_card(struct pci_dev *dev)
"%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
driver->name, param.port, param.irq, param.membase);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
- retval = b1pciv4_add_card(driver, &param);
+ retval = b1pciv4_add_card(driver, &param, dev);
#else
- retval = b1pci_add_card(driver, &param);
+ retval = b1pci_add_card(driver, &param, dev);
#endif
if (retval != 0) {
printk(KERN_ERR
@@ -445,7 +446,7 @@ static int add_card(struct pci_dev *dev)
printk(KERN_INFO
"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
driver->name, param.port, param.irq);
- retval = b1pci_add_card(driver, &param);
+ retval = b1pci_add_card(driver, &param, dev);
if (retval != 0) {
printk(KERN_ERR
"%s: no AVM-B1 at i/o %#x, irq %d detected\n",
diff --git a/drivers/isdn/avmb1/c4.c b/drivers/isdn/avmb1/c4.c
index b9d66d69d..6cbe16d18 100644
--- a/drivers/isdn/avmb1/c4.c
+++ b/drivers/isdn/avmb1/c4.c
@@ -1,4 +1,4 @@
-/* $Id: c4.c,v 1.20.6.11 2001/09/23 22:24:33 kai Exp $
+/* $Id: c4.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
*
* Module for AVM C4 & C2 card.
*
@@ -29,7 +29,7 @@
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.20.6.11 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
#undef CONFIG_C4_DEBUG
#undef CONFIG_C4_POLLDEBUG
@@ -439,7 +439,7 @@ static void c4_dispatch_tx(avmcard *card)
cmd = CAPIMSG_COMMAND(skb->data);
subcmd = CAPIMSG_SUBCOMMAND(skb->data);
- p = dma->sendbuf;
+ p = dma->sendbuf.dmabuf;
if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
__u16 dlen = CAPIMSG_DATALEN(skb->data);
@@ -450,7 +450,7 @@ static void c4_dispatch_tx(avmcard *card)
_put_byte(&p, SEND_MESSAGE);
_put_slice(&p, skb->data, len);
}
- txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+ txlen = (__u8 *)p - (__u8 *)dma->sendbuf.dmabuf;
#ifdef CONFIG_C4_DEBUG
printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
#endif
@@ -464,11 +464,11 @@ static void c4_dispatch_tx(avmcard *card)
printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
card->name, skb->data[2], txlen);
#endif
- memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+ memcpy(dma->sendbuf.dmabuf, skb->data+2, skb->len-2);
}
txlen = (txlen + 3) & ~3;
- c4outmeml(card->mbase+MBOX_DOWN_ADDR, virt_to_phys(dma->sendbuf));
+ c4outmeml(card->mbase+MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr);
c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);
card->csr |= DBELL_DOWN_ARM;
@@ -510,7 +510,7 @@ static void c4_handle_rx(avmcard *card)
struct capi_ctr *ctrl;
avmctrl_info *cinfo;
struct sk_buff *skb;
- void *p = dma->recvbuf;
+ void *p = dma->recvbuf.dmabuf;
__u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
__u8 b1cmd = _get_byte(&p);
__u32 cidx;
@@ -702,7 +702,7 @@ static void c4_handle_interrupt(avmcard *card)
c4outmeml(card->mbase+MBOX_UP_LEN, 0);
c4_handle_rx(card);
card->dma->recvlen = 0;
- c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+ c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
}
@@ -885,8 +885,8 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x08);
card->dma->recvlen = 0;
- c4outmeml(card->mbase+MBOX_UP_ADDR, virt_to_phys(card->dma->recvbuf));
- c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+ c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr);
+ c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
restore_flags(flags);
@@ -944,7 +944,7 @@ static void c4_remove_ctr(struct capi_ctr *ctrl)
release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
@@ -1123,6 +1123,7 @@ static int c4_read_proc(char *page, char **start, off_t off,
static int c4_add_card(struct capi_driver *driver,
struct capicardparams *p,
+ struct pci_dev *dev,
int nr)
{
avmctrl_info *cinfo;
@@ -1140,18 +1141,17 @@ static int c4_add_card(struct capi_driver *driver,
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
- card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+ card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
if (!card->dma) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
kfree(card);
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
- memset(card->dma, 0, sizeof(avmcard_dmainfo));
cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC);
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -ENOMEM;
@@ -1173,7 +1173,7 @@ static int c4_add_card(struct capi_driver *driver,
"%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EBUSY;
@@ -1184,7 +1184,7 @@ static int c4_add_card(struct capi_driver *driver,
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
driver->name, card->membase);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EIO;
@@ -1195,7 +1195,7 @@ static int c4_add_card(struct capi_driver *driver,
driver->name, card->port, retval);
iounmap(card->mbase);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EIO;
@@ -1211,7 +1211,7 @@ static int c4_add_card(struct capi_driver *driver,
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EBUSY;
@@ -1231,7 +1231,7 @@ static int c4_add_card(struct capi_driver *driver,
iounmap(card->mbase);
free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card->ctrlinfo);
kfree(card);
MOD_DEC_USE_COUNT;
@@ -1241,8 +1241,6 @@ static int c4_add_card(struct capi_driver *driver,
card->cardnr = cinfo->capi_ctrl->cnr;
}
- skb_queue_head_init(&card->dma->send_queue);
-
printk(KERN_INFO
"%s: AVM C%d at i/o %#x, irq %d, mem %#lx\n",
driver->name, nr, card->port, card->irq, card->membase);
@@ -1335,7 +1333,7 @@ static int __init search_cards(struct capi_driver * driver,
printk(KERN_INFO
"%s: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n",
driver->name, nr, param.port, param.irq, param.membase);
- retval = c4_add_card(driver, &param, nr);
+ retval = c4_add_card(driver, &param, dev, nr);
if (retval != 0) {
printk(KERN_ERR
"%s: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n",
diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c
index b453e3b9f..1559ba7fc 100644
--- a/drivers/isdn/avmb1/capi.c
+++ b/drivers/isdn/avmb1/capi.c
@@ -129,11 +129,9 @@ struct capincci {
};
struct capidev {
- struct capidev *next;
- struct file *file;
+ struct list_head list;
__u16 applid;
__u16 errcode;
- unsigned int minor;
unsigned userflags;
struct sk_buff_head recvqueue;
@@ -150,17 +148,18 @@ struct capidev {
/* -------- global variables ---------------------------------------- */
-static struct capi_interface *capifuncs = 0;
-static struct capidev *capidev_openlist = 0;
+static struct capi_interface *capifuncs;
+static rwlock_t capidev_list_lock;
+static LIST_HEAD(capidev_list);
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-static struct capiminor *minors = 0;
+static struct capiminor *minors;
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
-static kmem_cache_t *capidev_cachep = 0;
-static kmem_cache_t *capincci_cachep = 0;
+static kmem_cache_t *capidev_cachep;
+static kmem_cache_t *capincci_cachep;
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
-static kmem_cache_t *capiminor_cachep = 0;
-static kmem_cache_t *capidh_cachep = 0;
+static kmem_cache_t *capiminor_cachep;
+static kmem_cache_t *capidh_cachep;
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -318,9 +317,9 @@ static struct capincci *capincci_alloc(struct capidev *cdev, __u32 ncci)
printk(KERN_DEBUG "set mp->nccip\n");
#endif
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
- kdev = MKDEV(capi_rawmajor, mp->minor);
+ kdev = mk_kdev(capi_rawmajor, mp->minor);
capifs_new_ncci('r', mp->minor, kdev);
- kdev = MKDEV(capi_ttymajor, mp->minor);
+ kdev = mk_kdev(capi_ttymajor, mp->minor);
capifs_new_ncci(0, mp->minor, kdev);
#endif
}
@@ -391,48 +390,52 @@ struct capincci *capincci_find(struct capidev *cdev, __u32 ncci)
static struct capidev *capidev_alloc(struct file *file)
{
struct capidev *cdev;
- struct capidev **pp;
+ unsigned long flags;
cdev = (struct capidev *)kmem_cache_alloc(capidev_cachep, GFP_KERNEL);
if (!cdev)
return 0;
memset(cdev, 0, sizeof(struct capidev));
- cdev->file = file;
- cdev->minor = MINOR(file->f_dentry->d_inode->i_rdev);
skb_queue_head_init(&cdev->recvqueue);
init_waitqueue_head(&cdev->recvwait);
- pp=&capidev_openlist;
- while (*pp) pp = &(*pp)->next;
- *pp = cdev;
+ write_lock_irqsave(&capidev_list_lock, flags);
+ list_add_tail(&cdev->list, &capidev_list);
+ write_unlock_irqrestore(&capidev_list_lock, flags);
return cdev;
}
static void capidev_free(struct capidev *cdev)
{
- struct capidev **pp;
+ unsigned long flags;
if (cdev->applid)
(*capifuncs->capi_release) (cdev->applid);
cdev->applid = 0;
-
skb_queue_purge(&cdev->recvqueue);
-
- pp=&capidev_openlist;
- while (*pp && *pp != cdev) pp = &(*pp)->next;
- if (*pp)
- *pp = cdev->next;
-
+ write_lock_irqsave(&capidev_list_lock, flags);
+ list_del(&cdev->list);
+ write_unlock_irqrestore(&capidev_list_lock, flags);
kmem_cache_free(capidev_cachep, cdev);
}
static struct capidev *capidev_find(__u16 applid)
{
- struct capidev *p;
- for (p=capidev_openlist; p; p = p->next) {
+ // FIXME this doesn't guarantee that the device won't go away shortly
+ struct list_head *l;
+ struct capidev *p = NULL;
+
+ read_lock(&capidev_list_lock);
+ list_for_each(l, &capidev_list) {
+ p = list_entry(l, struct capidev, list);
if (p->applid == applid)
break;
}
+ read_unlock(&capidev_list_lock);
+
+ if (l == &capidev_list)
+ return NULL;
+
return p;
}
@@ -1090,7 +1093,7 @@ capinc_raw_open(struct inode *inode, struct file *file)
if (file->private_data)
return -EEXIST;
- if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)
+ if ((mp = capiminor_find(minor(file->f_dentry->d_inode->i_rdev))) == 0)
return -ENXIO;
if (mp->nccip == 0)
return -ENXIO;
@@ -1276,7 +1279,7 @@ int capinc_tty_open(struct tty_struct * tty, struct file * file)
{
struct capiminor *mp;
- if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)
+ if ((mp = capiminor_find(minor(file->f_dentry->d_inode->i_rdev))) == 0)
return -ENXIO;
if (mp->nccip == 0)
return -ENXIO;
@@ -1672,11 +1675,13 @@ static int proc_capidev_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct capidev *cdev;
+ struct list_head *l;
int len = 0;
- for (cdev=capidev_openlist; cdev; cdev = cdev->next) {
- len += sprintf(page+len, "%d %d %lu %lu %lu %lu\n",
- cdev->minor,
+ read_lock(&capidev_list_lock);
+ list_for_each(l, &capidev_list) {
+ cdev = list_entry(l, struct capidev, list);
+ len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n",
cdev->applid,
cdev->nrecvctlpkt,
cdev->nrecvdatapkt,
@@ -1690,11 +1695,13 @@ static int proc_capidev_read_proc(char *page, char **start, off_t off,
goto endloop;
}
}
+
endloop:
+ read_unlock(&capidev_list_lock);
if (len < count)
*eof = 1;
- if (len>count) len = count;
- if (len<0) len = 0;
+ if (len > count) len = count;
+ if (len < 0) len = 0;
return len;
}
@@ -1707,9 +1714,12 @@ static int proc_capincci_read_proc(char *page, char **start, off_t off,
{
struct capidev *cdev;
struct capincci *np;
+ struct list_head *l;
int len = 0;
- for (cdev=capidev_openlist; cdev; cdev = cdev->next) {
+ read_lock(&capidev_list_lock);
+ list_for_each(l, &capidev_list) {
+ cdev = list_entry(l, struct capidev, list);
for (np=cdev->nccis; np; np = np->next) {
len += sprintf(page+len, "%d 0x%x%s\n",
cdev->applid,
@@ -1729,6 +1739,7 @@ static int proc_capincci_read_proc(char *page, char **start, off_t off,
}
}
endloop:
+ read_unlock(&capidev_list_lock);
*start = page+off;
if (len < count)
*eof = 1;
diff --git a/drivers/isdn/avmb1/capidrv.c b/drivers/isdn/avmb1/capidrv.c
index d90606fe1..8b4ef8aed 100644
--- a/drivers/isdn/avmb1/capidrv.c
+++ b/drivers/isdn/avmb1/capidrv.c
@@ -29,7 +29,6 @@
#include <linux/kernelcapi.h>
#include <linux/ctype.h>
#include <linux/init.h>
-#include <asm/segment.h>
#include "capiutil.h"
#include "capicmd.h"
diff --git a/drivers/isdn/avmb1/capifs.c b/drivers/isdn/avmb1/capifs.c
index 745b6bd11..823b34737 100644
--- a/drivers/isdn/avmb1/capifs.c
+++ b/drivers/isdn/avmb1/capifs.c
@@ -430,7 +430,7 @@ void capifs_new_ncci(char type, unsigned int num, kdev_t device)
inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
inode->i_nlink = 1;
inode->i_ino = ino + 2;
- init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
+ init_special_inode(inode, sbi->mode|S_IFCHR, kdev_t_to_nr(np->kdev));
}
}
}
diff --git a/drivers/isdn/avmb1/capiutil.c b/drivers/isdn/avmb1/capiutil.c
index ce07a56cd..f41148ddc 100644
--- a/drivers/isdn/avmb1/capiutil.c
+++ b/drivers/isdn/avmb1/capiutil.c
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/init.h>
-#include <asm/segment.h>
#include <linux/config.h>
#include "capiutil.h"
diff --git a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c
index 12fd800b1..6ef1f9f33 100644
--- a/drivers/isdn/avmb1/kcapi.c
+++ b/drivers/isdn/avmb1/kcapi.c
@@ -17,7 +17,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <asm/segment.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/tqueue.h>
diff --git a/drivers/isdn/avmb1/t1pci.c b/drivers/isdn/avmb1/t1pci.c
index 79aa41a87..4aa72aa32 100644
--- a/drivers/isdn/avmb1/t1pci.c
+++ b/drivers/isdn/avmb1/t1pci.c
@@ -1,4 +1,4 @@
-/* $Id: t1pci.c,v 1.13.6.6 2001/09/23 22:24:34 kai Exp $
+/* $Id: t1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
*
* Module for AVM T1 PCI-card.
*
@@ -26,7 +26,7 @@
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.13.6.6 $";
+static char *revision = "$Revision: 1.1.4.1.2.1 $";
#undef CONFIG_T1PCI_DEBUG
#undef CONFIG_T1PCI_POLLDEBUG
@@ -62,7 +62,7 @@ static void t1pci_remove_ctr(struct capi_ctr *ctrl)
release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
@@ -70,7 +70,9 @@ static void t1pci_remove_ctr(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
-static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
+static int t1pci_add_card(struct capi_driver *driver,
+ struct capicardparams *p,
+ struct pci_dev *dev)
{
avmcard *card;
avmctrl_info *cinfo;
@@ -86,18 +88,17 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
- card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+ card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128);
if (!card->dma) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
kfree(card);
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
- memset(card->dma, 0, sizeof(avmcard_dmainfo));
cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -ENOMEM;
@@ -116,7 +117,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
"%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EBUSY;
@@ -127,7 +128,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
driver->name, card->membase);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EIO;
@@ -144,7 +145,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
driver->name, card->port, retval);
iounmap(card->mbase);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EIO;
@@ -160,7 +161,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EBUSY;
@@ -173,15 +174,13 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
- kfree(card->dma);
+ avmcard_dma_free(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EBUSY;
}
card->cardnr = cinfo->capi_ctrl->cnr;
- skb_queue_head_init(&card->dma->send_queue);
-
printk(KERN_INFO
"%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n",
driver->name, card->port, card->irq, card->membase);
@@ -271,7 +270,7 @@ static int __init t1pci_init(void)
printk(KERN_INFO
"%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
driver->name, param.port, param.irq, param.membase);
- retval = t1pci_add_card(driver, &param);
+ retval = t1pci_add_card(driver, &param, dev);
if (retval != 0) {
printk(KERN_ERR
"%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
diff --git a/drivers/isdn/eicon/eicon.h b/drivers/isdn/eicon/eicon.h
index cd7466596..5ab44971c 100644
--- a/drivers/isdn/eicon/eicon.h
+++ b/drivers/isdn/eicon/eicon.h
@@ -123,7 +123,6 @@ typedef struct {
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
diff --git a/drivers/isdn/eicon/lincfg.c b/drivers/isdn/eicon/lincfg.c
index 92d9e891f..671839cfc 100644
--- a/drivers/isdn/eicon/lincfg.c
+++ b/drivers/isdn/eicon/lincfg.c
@@ -11,7 +11,6 @@
#include <linux/fs.h>
#undef N_DATA /* Because we have our own definition */
-#include <asm/segment.h>
#include <asm/io.h>
#include "sys.h"
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index 0b49772e8..ef6aaca1a 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -4,6 +4,10 @@
O_TARGET := vmlinux-obj.o
+# Define maximum number of cards
+
+EXTRA_CFLAGS += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
+
# Objects that export symbols.
export-objs := config.o fsm.o hisax_isac.o
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index bc098205d..56f2e69be 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1,4 +1,4 @@
-/* $Id: config.c,v 2.57.6.20 2001/09/23 22:24:47 kai Exp $
+/* $Id: config.c,v 1.1.4.2.2.1 2001/12/09 20:18:40 kai Exp $
*
* Author Karsten Keil
* Copyright by Karsten Keil <keil@isdn4linux.de>
@@ -336,17 +336,8 @@ EXPORT_SYMBOL(HiSax_closecard);
NULL, \
}
-#define EMPTY_CARD {0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
-
struct IsdnCard cards[HISAX_MAX_CARDS] = {
FIRST_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
};
#define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
@@ -374,10 +365,7 @@ static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
static char *id __devinitdata = HiSaxID;
-/* string magic */
-#define h1(s) h2(s)
-#define h2(s) #s
-#define PARM_PARA "1-"h1(HISAX_MAX_CARDS)"i"
+#define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i"
MODULE_DESCRIPTION("ISDN4Linux: Driver for passive ISDN cards");
MODULE_AUTHOR("Karsten Keil");
@@ -454,6 +442,7 @@ static int __init HiSax_setup(char *line)
i = 0;
j = 1;
while (argc && (i < HISAX_MAX_CARDS)) {
+ cards[i].protocol = DEFAULT_PROTO;
if (argc) {
cards[i].typ = ints[j];
j++;
@@ -481,7 +470,7 @@ static int __init HiSax_setup(char *line)
}
i++;
}
- if (str && *str) {
+ if (str && *str) {
if (strlen(str) < HISAX_IDSIZE)
strcpy(HiSaxID, str);
else
@@ -1404,6 +1393,8 @@ static int __init HiSax_init(void)
if (protocol[i]) {
cards[j].protocol = protocol[i];
nzproto++;
+ } else {
+ cards[j].protocol = DEFAULT_PROTO;
}
switch (type[i]) {
case ISDN_CTYPE_16_0:
@@ -1481,15 +1472,22 @@ static int __init HiSax_init(void)
} else {
/* QUADRO is a 4 BRI card */
cards[j++].para[0] = 1;
- cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
- cards[j].protocol = protocol[i];
- cards[j++].para[0] = 2;
- cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
- cards[j].protocol = protocol[i];
- cards[j++].para[0] = 3;
- cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
- cards[j].protocol = protocol[i];
- cards[j].para[0] = 4;
+ /* we need to check if further cards can be added */
+ if (j < HISAX_MAX_CARDS) {
+ cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+ cards[j].protocol = protocol[i];
+ cards[j++].para[0] = 2;
+ }
+ if (j < HISAX_MAX_CARDS) {
+ cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+ cards[j].protocol = protocol[i];
+ cards[j++].para[0] = 3;
+ }
+ if (j < HISAX_MAX_CARDS) {
+ cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+ cards[j].protocol = protocol[i];
+ cards[j].para[0] = 4;
+ }
}
break;
}
@@ -1562,6 +1560,8 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
cards[i].typ = type[i];
if (protocol[i]) {
cards[i].protocol = protocol[i];
+ } else {
+ cards[i].protocol = DEFAULT_PROTO;
}
}
cards[0].para[0] = pcm_irq;
@@ -1602,6 +1602,8 @@ int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
cards[i].typ = type[i];
if (protocol[i]) {
cards[i].protocol = protocol[i];
+ } else {
+ cards[i].protocol = DEFAULT_PROTO;
}
}
cards[0].para[0] = pcm_irq;
@@ -1642,6 +1644,8 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
cards[i].typ = type[i];
if (protocol[i]) {
cards[i].protocol = protocol[i];
+ } else {
+ cards[i].protocol = DEFAULT_PROTO;
}
}
cards[0].para[0] = pcm_irq;
@@ -1682,6 +1686,8 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
cards[i].typ = type[i];
if (protocol[i]) {
cards[i].protocol = protocol[i];
+ } else {
+ cards[i].protocol = DEFAULT_PROTO;
}
}
cards[0].para[0] = pcm_irq;
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index fdab82576..cee7b10a2 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1,4 +1,4 @@
-/* $Id: hisax.h,v 2.52.6.9 2001/09/23 22:24:48 kai Exp $
+/* $Id: hisax.h,v 1.1.4.1.2.1 2001/12/09 20:18:40 kai Exp $
*
* Basic declarations, defines and prototypes
*
@@ -10,7 +10,6 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/kernel.h>
@@ -950,8 +949,6 @@ struct IsdnCardState {
#define MON0_TX 4
#define MON1_TX 8
-#define HISAX_MAX_CARDS 8
-
#define ISDN_CTYPE_16_0 1
#define ISDN_CTYPE_8_0 2
#define ISDN_CTYPE_16_3 3
diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h
index 82234568c..a8bbc4586 100644
--- a/drivers/isdn/icn/icn.h
+++ b/drivers/isdn/icn/icn.h
@@ -39,7 +39,6 @@ typedef struct icn_cdef {
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
diff --git a/drivers/isdn/isdn_bsdcomp.c b/drivers/isdn/isdn_bsdcomp.c
index 5daac5e35..6049970e1 100644
--- a/drivers/isdn/isdn_bsdcomp.c
+++ b/drivers/isdn/isdn_bsdcomp.c
@@ -71,7 +71,6 @@
#include <asm/system.h>
#include <asm/bitops.h>
-#include <asm/segment.h>
#include <asm/byteorder.h>
#include <asm/types.h>
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index a0749e798..2e78a0e3d 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -963,7 +963,7 @@ isdn_info_update(void)
static ssize_t
isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
{
- uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ uint minor = minor(file->f_dentry->d_inode->i_rdev);
int len = 0;
ulong flags;
int drvidx;
@@ -1077,7 +1077,7 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
static ssize_t
isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
{
- uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ uint minor = minor(file->f_dentry->d_inode->i_rdev);
int drvidx;
int chidx;
int retval;
@@ -1143,7 +1143,7 @@ static unsigned int
isdn_poll(struct file *file, poll_table * wait)
{
unsigned int mask = 0;
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
lock_kernel();
@@ -1184,7 +1184,7 @@ isdn_poll(struct file *file, poll_table * wait)
static int
isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
{
- uint minor = MINOR(inode->i_rdev);
+ uint minor = minor(inode->i_rdev);
isdn_ctrl c;
int drvidx;
int chidx;
@@ -1635,7 +1635,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
static int
isdn_open(struct inode *ino, struct file *filep)
{
- uint minor = MINOR(ino->i_rdev);
+ uint minor = minor(ino->i_rdev);
int drvidx;
int chidx;
int retval = -ENODEV;
@@ -1696,7 +1696,7 @@ isdn_open(struct inode *ino, struct file *filep)
static int
isdn_close(struct inode *ino, struct file *filep)
{
- uint minor = MINOR(ino->i_rdev);
+ uint minor = minor(ino->i_rdev);
lock_kernel();
if (minor == ISDN_MINOR_STATUS) {
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index c6ac0a6da..431683e13 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -586,7 +586,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
if (is->debug & 0x2)
printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
- MINOR(file->f_dentry->d_inode->i_rdev));
+ minor(file->f_dentry->d_inode->i_rdev));
/* just registers wait_queue hook. This doesn't really wait. */
poll_wait(file, &is->wq, wait);
diff --git a/drivers/isdn/isdn_tty.c b/drivers/isdn/isdn_tty.c
index c73a7d5b1..2f9a7c634 100644
--- a/drivers/isdn/isdn_tty.c
+++ b/drivers/isdn/isdn_tty.c
@@ -1019,12 +1019,12 @@ isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine)
#ifdef MODEM_PARANOIA_CHECK
if (!info) {
printk(KERN_WARNING "isdn_tty: null info_struct for (%d, %d) in %s\n",
- MAJOR(device), MINOR(device), routine);
+ major(device), minor(device), routine);
return 1;
}
if (info->magic != ISDN_ASYNC_MAGIC) {
printk(KERN_WARNING "isdn_tty: bad magic for modem struct (%d, %d) in %s\n",
- MAJOR(device), MINOR(device), routine);
+ major(device), minor(device), routine);
return 1;
}
#endif
@@ -1740,7 +1740,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp)
int retval,
line;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if (line < 0 || line > ISDN_MAX_CHANNELS)
return -ENODEV;
info = &dev->mdm.info[line];
diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h
index 138e4cae6..8fb7bc1bf 100644
--- a/drivers/isdn/isdnloop/isdnloop.h
+++ b/drivers/isdn/isdnloop/isdnloop.h
@@ -37,7 +37,6 @@ typedef struct isdnloop_sdef {
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
index 9c905f54f..6825512a4 100644
--- a/drivers/isdn/sc/command.c
+++ b/drivers/isdn/sc/command.c
@@ -95,7 +95,7 @@ int get_card_from_id(int driver)
if(adapter[i]->driverId == driver)
return i;
}
- return -NODEV;
+ return -ENODEV;
}
/*
diff --git a/drivers/isdn/sc/includes.h b/drivers/isdn/sc/includes.h
index c33bf6de3..4611da6e9 100644
--- a/drivers/isdn/sc/includes.h
+++ b/drivers/isdn/sc/includes.h
@@ -6,7 +6,6 @@
#include <linux/version.h>
#include <linux/errno.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/kernel.h>
diff --git a/drivers/macintosh/mac_keyb.c b/drivers/macintosh/mac_keyb.c
index 7b4075edf..bddf7dc09 100644
--- a/drivers/macintosh/mac_keyb.c
+++ b/drivers/macintosh/mac_keyb.c
@@ -256,7 +256,6 @@ int adb_button3_keycode = 0x7c; /* right option key */
#endif
extern struct kbd_struct kbd_table[];
-extern wait_queue_head_t keypress_wait;
extern void handle_scancode(unsigned char, int);
@@ -423,7 +422,6 @@ static void mac_put_queue(int ch)
struct tty_struct *tty;
tty = console_driver.table? console_driver.table[fg_console]: NULL;
- wake_up(&keypress_wait);
if (tty) {
tty_insert_flip_char(tty, ch, 0);
con_schedule_flip(tty);
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index 8c43e6434..7c3d6b0e6 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -38,7 +38,6 @@
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/feature.h>
#include <linux/adb.h>
@@ -2792,30 +2791,6 @@ static void serial_console_write(struct console *co, const char *s,
/* Don't disable the transmitter. */
}
-/*
- * Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
- struct mac_serial *info = zs_soft + co->index;
- int val;
-
- /* Turn of interrupts and enable the transmitter. */
- write_zsreg(info->zs_channel, R1, info->curregs[1] & ~INT_ALL_Rx);
- write_zsreg(info->zs_channel, R3, info->curregs[3] | RxENABLE);
-
- /* Wait for something in the receive buffer. */
- while((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0)
- eieio();
- val = read_zsdata(info->zs_channel);
-
- /* Restore the values in the registers. */
- write_zsreg(info->zs_channel, R1, info->curregs[1]);
- write_zsreg(info->zs_channel, R3, info->curregs[3]);
-
- return val;
-}
-
static kdev_t serial_console_device(struct console *c)
{
return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -3006,7 +2981,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/md/lvm-fs.c b/drivers/md/lvm-fs.c
index cf1f8d08a..680be8276 100644
--- a/drivers/md/lvm-fs.c
+++ b/drivers/md/lvm-fs.c
@@ -30,6 +30,7 @@
* 04/10/2001 - corrected devfs_register() call in lvm_init_fs()
* 11/04/2001 - don't devfs_register("lvm") as user-space always does it
* 10/05/2001 - show more of PV name in /proc/lvm/global
+ * 16/12/2001 - fix devfs unregister order and prevent duplicate unreg (REG)
*
*/
@@ -64,9 +65,7 @@ static int _pv_info(pv_t *pv_ptr, char *buf);
static void _show_uuid(const char *src, char *b, char *e);
-#if 0
static devfs_handle_t lvm_devfs_handle;
-#endif
static devfs_handle_t vg_devfs_handle[MAX_VG];
static devfs_handle_t ch_devfs_handle[MAX_VG];
static devfs_handle_t lv_devfs_handle[MAX_LV];
@@ -80,13 +79,11 @@ static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;
void __init lvm_init_fs() {
struct proc_dir_entry *pde;
-/* User-space has already registered this */
-#if 0
+ /* Must create device node. Think about "devfs=only" situation */
lvm_devfs_handle = devfs_register(
0 , "lvm", 0, LVM_CHAR_MAJOR, 0,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
&lvm_chr_fops, NULL);
-#endif
lvm_proc_dir = create_proc_entry(LVM_DIR, S_IFDIR, &proc_root);
if (lvm_proc_dir) {
@@ -98,9 +95,7 @@ void __init lvm_init_fs() {
}
void lvm_fin_fs() {
-#if 0
devfs_unregister (lvm_devfs_handle);
-#endif
remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
@@ -138,7 +133,7 @@ void lvm_fs_remove_vg(vg_t *vg_ptr) {
int i;
devfs_unregister(ch_devfs_handle[vg_ptr->vg_number]);
- devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]);
+ ch_devfs_handle[vg_ptr->vg_number] = NULL;
/* remove lv's */
for(i = 0; i < vg_ptr->lv_max; i++)
@@ -148,6 +143,10 @@ void lvm_fs_remove_vg(vg_t *vg_ptr) {
for(i = 0; i < vg_ptr->pv_max; i++)
if(vg_ptr->pv[i]) lvm_fs_remove_pv(vg_ptr, vg_ptr->pv[i]);
+ /* must not remove directory before leaf nodes */
+ devfs_unregister(vg_devfs_handle[vg_ptr->vg_number]);
+ vg_devfs_handle[vg_ptr->vg_number] = NULL;
+
if(vg_ptr->vg_dir_pde) {
remove_proc_entry(LVM_LV_SUBDIR, vg_ptr->vg_dir_pde);
vg_ptr->lv_subdir_pde = NULL;
@@ -173,9 +172,9 @@ devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) {
struct proc_dir_entry *pde;
const char *name = _basename(lv->lv_name);
- lv_devfs_handle[MINOR(lv->lv_dev)] = devfs_register(
+ lv_devfs_handle[minor(lv->lv_dev)] = devfs_register(
vg_devfs_handle[vg_ptr->vg_number], name,
- DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, MINOR(lv->lv_dev),
+ DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, minor(lv->lv_dev),
S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
&lvm_blk_dops, NULL);
@@ -184,11 +183,12 @@ devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) {
pde->read_proc = _proc_read_lv;
pde->data = lv;
}
- return lv_devfs_handle[MINOR(lv->lv_dev)];
+ return lv_devfs_handle[minor(lv->lv_dev)];
}
void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv) {
- devfs_unregister(lv_devfs_handle[MINOR(lv->lv_dev)]);
+ devfs_unregister(lv_devfs_handle[minor(lv->lv_dev)]);
+ lv_devfs_handle[minor(lv->lv_dev)] = NULL;
if(vg_ptr->lv_subdir_pde) {
const char *name = _basename(lv->lv_name);
@@ -283,7 +283,7 @@ static int _proc_read_lv(char *page, char **start, off_t off,
lv->lv_stripesize);
}
sz += sprintf(page + sz, "device: %02u:%02u\n",
- MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
+ major(lv->lv_dev), minor(lv->lv_dev));
return sz;
}
@@ -304,7 +304,7 @@ static int _proc_read_pv(char *page, char **start, off_t off,
sz += sprintf(page + sz, "PE total: %u\n", pv->pe_total);
sz += sprintf(page + sz, "PE allocated: %u\n", pv->pe_allocated);
sz += sprintf(page + sz, "device: %02u:%02u\n",
- MAJOR(pv->pv_dev), MINOR(pv->pv_dev));
+ major(pv->pv_dev), minor(pv->pv_dev));
_show_uuid(pv->pv_uuid, uuid, uuid + sizeof(uuid));
sz += sprintf(page + sz, "uuid: %s\n", uuid);
diff --git a/drivers/md/lvm-snap.c b/drivers/md/lvm-snap.c
index 9ec39b7a9..856ea31e4 100644
--- a/drivers/md/lvm-snap.c
+++ b/drivers/md/lvm-snap.c
@@ -68,7 +68,7 @@ static int _pv_get_number(vg_t * vg, kdev_t rdev, uint *pvn) {
if(vg->pv[p] == NULL)
continue;
- if(vg->pv[p]->pv_dev == rdev)
+ if(kdev_same(vg->pv[p]->pv_dev, rdev))
break;
}
@@ -77,7 +77,7 @@ static int _pv_get_number(vg_t * vg, kdev_t rdev, uint *pvn) {
/* bad news, the snapshot COW table is probably corrupt */
printk(KERN_ERR
"%s -- _pv_get_number failed for rdev = %u\n",
- lvm_name, rdev);
+ lvm_name, kdev_t_to_nr(rdev));
return -1;
}
@@ -105,7 +105,7 @@ lvm_find_exception_table(kdev_t org_dev, unsigned long org_start, lv_t * lv)
exception = list_entry(next, lv_block_exception_t, hash);
if (exception->rsector_org == org_start &&
- exception->rdev_org == org_dev)
+ kdev_same(exception->rdev_org, org_dev))
{
if (i)
{
@@ -169,8 +169,10 @@ void lvm_drop_snapshot(vg_t *vg, lv_t *lv_snap, const char *reason)
/* wipe the snapshot since it's inconsistent now */
_disable_snapshot(vg, lv_snap);
- for (i = last_dev = 0; i < lv_snap->lv_remap_ptr; i++) {
- if ( lv_snap->lv_block_exception[i].rdev_new != last_dev) {
+ last_dev = NODEV;
+ for (i = 0; i < lv_snap->lv_remap_ptr; i++) {
+ if ( !kdev_same(lv_snap->lv_block_exception[i].rdev_new,
+ last_dev)) {
last_dev = lv_snap->lv_block_exception[i].rdev_new;
invalidate_buffers(last_dev);
}
@@ -206,20 +208,6 @@ static inline int lvm_snapshot_prepare_blocks(unsigned long *blocks,
return 1;
}
-inline int lvm_get_blksize(kdev_t dev)
-{
- int correct_size = BLOCK_SIZE, i, major;
-
- major = MAJOR(dev);
- if (blksize_size[major])
- {
- i = blksize_size[major][MINOR(dev)];
- if (i)
- correct_size = i;
- }
- return correct_size;
-}
-
#ifdef DEBUG_SNAPSHOT
static inline void invalidate_snap_cache(unsigned long start, unsigned long nr,
kdev_t dev)
@@ -227,7 +215,7 @@ static inline void invalidate_snap_cache(unsigned long start, unsigned long nr,
struct buffer_head * bh;
int sectors_per_block, i, blksize, minor;
- minor = MINOR(dev);
+ minor = minor(dev);
blksize = lvm_blocksizes[minor];
sectors_per_block = blksize >> 9;
nr /= sectors_per_block;
@@ -256,7 +244,7 @@ int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
is--;
blksize_snap =
- lvm_get_blksize(lv_snap->lv_block_exception[is].rdev_new);
+ block_size(lv_snap->lv_block_exception[is].rdev_new);
is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t));
memset(lv_COW_table, 0, blksize_snap);
@@ -313,7 +301,8 @@ int lvm_snapshot_COW(kdev_t org_phys_dev,
vg_t *vg, lv_t* lv_snap)
{
const char * reason;
- unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off;
+ kdev_t snap_phys_dev;
+ unsigned long org_start, snap_start, virt_start, pe_off;
int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size;
struct kiobuf * iobuf;
int blksize_snap, blksize_org, min_blksize, max_blksize;
@@ -347,8 +336,8 @@ int lvm_snapshot_COW(kdev_t org_phys_dev,
iobuf = lv_snap->lv_iobuf;
- blksize_org = lvm_get_blksize(org_phys_dev);
- blksize_snap = lvm_get_blksize(snap_phys_dev);
+ blksize_org = block_size(org_phys_dev);
+ blksize_snap = block_size(snap_phys_dev);
max_blksize = max(blksize_org, blksize_snap);
min_blksize = min(blksize_org, blksize_snap);
max_sectors = LVM_MAX_SECTORS * (min_blksize>>9);
@@ -592,7 +581,7 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap,
snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
- blksize_snap = lvm_get_blksize(snap_phys_dev);
+ blksize_snap = block_size(snap_phys_dev);
COW_entries_per_block = blksize_snap / sizeof(lv_COW_table_disk_t);
idx_COW_table = idx % COW_entries_per_pe % COW_entries_per_block;
@@ -640,7 +629,7 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap,
idx++;
snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;
snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size;
- blksize_snap = lvm_get_blksize(snap_phys_dev);
+ blksize_snap = block_size(snap_phys_dev);
blocks[0] = snap_pe_start >> (blksize_snap >> 10);
} else blocks[0]++;
diff --git a/drivers/md/lvm.c b/drivers/md/lvm.c
index a3ab38cd3..87227a071 100644
--- a/drivers/md/lvm.c
+++ b/drivers/md/lvm.c
@@ -179,6 +179,9 @@
* (Jens Axboe)
* - Defer writes to an extent that is being moved [JT + AD]
* 28/05/2001 - implemented missing BLKSSZGET ioctl [AD]
+ * 28/12/2001 - buffer_head -> bio
+ * removed huge allocation of a lv_t on stack
+ * (Anders Gustafsson)
*
*/
@@ -209,7 +212,6 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/smp_lock.h>
#include <asm/ioctl.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#ifdef CONFIG_KERNELD
@@ -376,7 +378,6 @@ static struct gendisk lvm_gendisk =
major: MAJOR_NR,
major_name: LVM_NAME,
minor_shift: 0,
- max_p: 1,
part: lvm_hd_struct,
sizes: lvm_size,
nr_real: MAX_LV,
@@ -479,8 +480,8 @@ static void __init lvm_init_vars(void)
lvm_lock = lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
pe_lock_req.lock = UNLOCK_PE;
- pe_lock_req.data.lv_dev = 0;
- pe_lock_req.data.pv_dev = 0;
+ pe_lock_req.data.lv_dev = NODEV;
+ pe_lock_req.data.pv_dev = NODEV;
pe_lock_req.data.pv_offset = 0;
/* Initialize VG pointers */
@@ -511,7 +512,7 @@ static void __init lvm_init_vars(void)
*/
static int lvm_chr_open(struct inode *inode, struct file *file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
P_DEV("chr_open MINOR: %d VG#: %d mode: %s%s lock: %d\n",
minor, VG_CHR(minor), MODE_TO_STR(file->f_mode), lock);
@@ -545,7 +546,7 @@ static int lvm_chr_open(struct inode *inode, struct file *file)
static int lvm_chr_ioctl(struct inode *inode, struct file *file,
uint command, ulong a)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
uint extendable, l, v;
void *arg = (void *) a;
lv_t lv;
@@ -751,7 +752,7 @@ static int lvm_chr_ioctl(struct inode *inode, struct file *file,
static int lvm_chr_close(struct inode *inode, struct file *file)
{
P_DEV("chr_close MINOR: %d VG#: %d\n",
- MINOR(inode->i_rdev), VG_CHR(MINOR(inode->i_rdev)));
+ minor(inode->i_rdev), VG_CHR(minor(inode->i_rdev)));
#ifdef LVM_TOTAL_RESET
if (lvm_reset_spindown > 0) {
@@ -791,7 +792,7 @@ static int lvm_chr_close(struct inode *inode, struct file *file)
*/
static int lvm_blk_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
lv_t *lv_ptr;
vg_t *vg_ptr = vg[VG_BLK(minor)];
@@ -844,7 +845,7 @@ static int lvm_blk_open(struct inode *inode, struct file *file)
static int lvm_blk_ioctl(struct inode *inode, struct file *file,
uint command, ulong a)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
vg_t *vg_ptr = vg[VG_BLK(minor)];
lv_t *lv_ptr = vg_ptr->lv[LV_BLK(minor)];
void *arg = (void *) a;
@@ -984,7 +985,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
*/
static int lvm_blk_close(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
vg_t *vg_ptr = vg[VG_BLK(minor)];
lv_t *lv_ptr = vg_ptr->lv[LV_BLK(minor)];
@@ -1043,7 +1044,7 @@ static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result)
memset(&bio,0,sizeof(bio));
bio.bi_dev = inode->i_rdev;
- bio.bi_io_vec.bv_len = lvm_get_blksize(bio.bi_dev);
+ bio.bi_size = lvm_get_blksize(bio.bi_dev); /* NEEDED by bio_sectors */
bio.bi_sector = block * bio_sectors(&bio);
bio.bi_rw = READ;
if ((err=lvm_map(&bio)) < 0) {
@@ -1096,7 +1097,7 @@ static inline void _remap_snapshot(kdev_t rdev, ulong rsector,
*/
static inline int _should_defer(kdev_t pv, ulong sector, uint32_t pe_size) {
return ((pe_lock_req.lock == LOCK_PE) &&
- (pv == pe_lock_req.data.pv_dev) &&
+ kdev_same(pv, pe_lock_req.data.pv_dev) &&
(sector >= pe_lock_req.data.pv_offset) &&
(sector < (pe_lock_req.data.pv_offset + pe_size)));
}
@@ -1119,19 +1120,18 @@ static inline int _defer_extent(struct bio *bh, int rw,
return 0;
}
-static int lvm_map(struct bio *bh)
+static int lvm_map(struct bio *bi)
{
- int minor = MINOR(bh->bi_dev);
+ int minor = minor(bi->bi_dev);
ulong index;
ulong pe_start;
- ulong size = bio_sectors(bh);
- ulong rsector_org = bh->bi_sector;
+ ulong size = bio_sectors(bi);
+ ulong rsector_org = bi->bi_sector;
ulong rsector_map;
kdev_t rdev_map;
vg_t *vg_this = vg[VG_BLK(minor)];
lv_t *lv = vg_this->lv[LV_BLK(minor)];
- int rw = bio_data_dir(bh);
-
+ int rw = bio_rw(bi);
down_read(&lv->lv_lock);
if (!(lv->lv_status & LV_ACTIVE)) {
@@ -1151,7 +1151,7 @@ static int lvm_map(struct bio *bh)
P_MAP("%s - lvm_map minor: %d *rdev: %s *rsector: %lu size:%lu\n",
lvm_name, minor,
- kdevname(bh->bi_dev),
+ kdevname(bi->bi_dev),
rsector_org, size);
if (rsector_org + size > lv->lv_size) {
@@ -1205,7 +1205,7 @@ static int lvm_map(struct bio *bh)
* we need to queue this request, because this is in the fast path.
*/
if (rw == WRITE || rw == WRITEA) {
- if(_defer_extent(bh, rw, rdev_map,
+ if(_defer_extent(bi, rw, rdev_map,
rsector_map, vg_this->pe_size)) {
up_read(&lv->lv_lock);
@@ -1246,13 +1246,13 @@ static int lvm_map(struct bio *bh)
}
out:
- bh->bi_dev = rdev_map;
- bh->bi_sector = rsector_map;
+ bi->bi_dev = rdev_map;
+ bi->bi_sector = rsector_map;
up_read(&lv->lv_lock);
return 1;
bad:
- bio_io_error(bh);
+ bio_io_error(bi);
up_read(&lv->lv_lock);
return -1;
} /* lvm_map() */
@@ -1339,7 +1339,8 @@ static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
case LOCK_PE:
for (p = 0; p < vg_ptr->pv_max; p++) {
if (vg_ptr->pv[p] != NULL &&
- new_lock.data.pv_dev == vg_ptr->pv[p]->pv_dev)
+ kdev_same(new_lock.data.pv_dev,
+ vg_ptr->pv[p]->pv_dev))
break;
}
if (p == vg_ptr->pv_max) return -ENXIO;
@@ -1373,8 +1374,8 @@ static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
case UNLOCK_PE:
down_write(&_pe_lock);
pe_lock_req.lock = UNLOCK_PE;
- pe_lock_req.data.lv_dev = 0;
- pe_lock_req.data.pv_dev = 0;
+ pe_lock_req.data.lv_dev = NODEV;
+ pe_lock_req.data.pv_dev = NODEV;
pe_lock_req.data.pv_offset = 0;
bh = _dequeue_io();
up_write(&_pe_lock);
@@ -1409,8 +1410,8 @@ static int lvm_do_le_remap(vg_t *vg_ptr, void *arg)
strcmp(lv_ptr->lv_name,
le_remap_req.lv_name) == 0) {
for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
- if (lv_ptr->lv_current_pe[le].dev ==
- le_remap_req.old_dev &&
+ if (kdev_same(lv_ptr->lv_current_pe[le].dev,
+ le_remap_req.old_dev) &&
lv_ptr->lv_current_pe[le].pe ==
le_remap_req.old_pe) {
lv_ptr->lv_current_pe[le].dev =
@@ -1436,9 +1437,9 @@ static int lvm_do_vg_create(void *arg, int minor)
{
int ret = 0;
ulong l, ls = 0, p, size;
- lv_t lv;
vg_t *vg_ptr;
lv_t **snap_lv_ptr;
+ lv_t *tmplv;
if ((vg_ptr = kmalloc(sizeof(vg_t),GFP_KERNEL)) == NULL) {
printk(KERN_CRIT
@@ -1446,6 +1447,7 @@ static int lvm_do_vg_create(void *arg, int minor)
lvm_name, __LINE__);
return -ENOMEM;
}
+
/* get the volume group structure */
if (copy_from_user(vg_ptr, arg, sizeof(vg_t)) != 0) {
P_IOCTL("lvm_do_vg_create ERROR: copy VG ptr %p (%d bytes)\n",
@@ -1454,6 +1456,8 @@ static int lvm_do_vg_create(void *arg, int minor)
return -EFAULT;
}
+
+
/* VG_CREATE now uses minor number in VG structure */
if (minor == -1) minor = vg_ptr->vg_number;
@@ -1513,19 +1517,30 @@ static int lvm_do_vg_create(void *arg, int minor)
}
memset(snap_lv_ptr, 0, size);
+ if ((tmplv = kmalloc(sizeof(lv_t),GFP_KERNEL)) == NULL) {
+ printk(KERN_CRIT
+ "%s -- VG_CREATE: kmalloc error LV at line %d\n",
+ lvm_name, __LINE__);
+ vfree(snap_lv_ptr);
+ return -ENOMEM;
+ }
+
/* get the logical volume structures */
vg_ptr->lv_cur = 0;
for (l = 0; l < vg_ptr->lv_max; l++) {
lv_t *lvp;
+
/* user space address */
if ((lvp = vg_ptr->lv[l]) != NULL) {
- if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
+ if (copy_from_user(tmplv, lvp, sizeof(lv_t)) != 0) {
P_IOCTL("ERROR: copying LV ptr %p (%d bytes)\n",
lvp, sizeof(lv_t));
lvm_do_vg_remove(minor);
+ vfree(snap_lv_ptr);
+ kfree(tmplv);
return -EFAULT;
}
- if ( lv.lv_access & LV_SNAPSHOT) {
+ if ( tmplv->lv_access & LV_SNAPSHOT) {
snap_lv_ptr[ls] = lvp;
vg_ptr->lv[l] = NULL;
ls++;
@@ -1533,8 +1548,10 @@ static int lvm_do_vg_create(void *arg, int minor)
}
vg_ptr->lv[l] = NULL;
/* only create original logical volumes for now */
- if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) {
+ if (lvm_do_lv_create(minor, tmplv->lv_name, tmplv) != 0) {
lvm_do_vg_remove(minor);
+ vfree(snap_lv_ptr);
+ kfree(tmplv);
return -EFAULT;
}
}
@@ -1544,18 +1561,22 @@ static int lvm_do_vg_create(void *arg, int minor)
in place during first path above */
for (l = 0; l < ls; l++) {
lv_t *lvp = snap_lv_ptr[l];
- if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
+ if (copy_from_user(tmplv, lvp, sizeof(lv_t)) != 0) {
lvm_do_vg_remove(minor);
+ vfree(snap_lv_ptr);
+ kfree(tmplv);
return -EFAULT;
}
- if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) {
+ if (lvm_do_lv_create(minor, tmplv->lv_name, tmplv) != 0) {
lvm_do_vg_remove(minor);
+ vfree(snap_lv_ptr);
+ kfree(tmplv);
return -EFAULT;
}
}
vfree(snap_lv_ptr);
-
+ kfree(tmplv);
vg_count++;
@@ -1908,8 +1929,8 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
vg_ptr->pe_allocated++;
for (p = 0; p < vg_ptr->pv_cur; p++) {
- if (vg_ptr->pv[p]->pv_dev ==
- lv_ptr->lv_current_pe[le].dev)
+ if (kdev_same(vg_ptr->pv[p]->pv_dev,
+ lv_ptr->lv_current_pe[le].dev))
vg_ptr->pv[p]->pe_allocated++;
}
}
@@ -2009,11 +2030,11 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
} /* if ( vg[VG_CHR(minor)]->lv[l]->lv_access & LV_SNAPSHOT) */
lv_ptr = vg_ptr->lv[l];
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].start_sect = 0;
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = lv_ptr->lv_size;
- lvm_size[MINOR(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1;
- vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = vg_ptr->vg_number;
- vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = lv_ptr->lv_number;
+ lvm_gendisk.part[minor(lv_ptr->lv_dev)].start_sect = 0;
+ lvm_gendisk.part[minor(lv_ptr->lv_dev)].nr_sects = lv_ptr->lv_size;
+ lvm_size[minor(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1;
+ vg_lv_map[minor(lv_ptr->lv_dev)].vg_number = vg_ptr->vg_number;
+ vg_lv_map[minor(lv_ptr->lv_dev)].lv_number = lv_ptr->lv_number;
LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead);
vg_ptr->lv_cur++;
lv_ptr->lv_status = lv_status_save;
@@ -2061,7 +2082,7 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
lv_ptr->vg = vg_ptr;
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de =
+ lvm_gendisk.part[minor(lv_ptr->lv_dev)].de =
lvm_fs_create_lv(vg_ptr, lv_ptr);
return 0;
@@ -2141,14 +2162,14 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l)
invalidate_buffers(lv_ptr->lv_dev);
/* reset generic hd */
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].start_sect = -1;
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].nr_sects = 0;
- lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de = 0;
- lvm_size[MINOR(lv_ptr->lv_dev)] = 0;
+ lvm_gendisk.part[minor(lv_ptr->lv_dev)].start_sect = -1;
+ lvm_gendisk.part[minor(lv_ptr->lv_dev)].nr_sects = 0;
+ lvm_gendisk.part[minor(lv_ptr->lv_dev)].de = 0;
+ lvm_size[minor(lv_ptr->lv_dev)] = 0;
/* reset VG/LV mapping */
- vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = ABS_MAX_VG;
- vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = -1;
+ vg_lv_map[minor(lv_ptr->lv_dev)].vg_number = ABS_MAX_VG;
+ vg_lv_map[minor(lv_ptr->lv_dev)].lv_number = -1;
/* correct the PE count in PVs if this is not a snapshot
logical volume */
@@ -2159,8 +2180,8 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l)
for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
vg_ptr->pe_allocated--;
for (p = 0; p < vg_ptr->pv_cur; p++) {
- if (vg_ptr->pv[p]->pv_dev ==
- lv_ptr->lv_current_pe[le].dev)
+ if (kdev_same(vg_ptr->pv[p]->pv_dev,
+ lv_ptr->lv_current_pe[le].dev))
vg_ptr->pv[p]->pe_allocated--;
}
}
@@ -2237,8 +2258,8 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
for (l = 0; l < old_lv->lv_allocated_le; l++) {
vg_ptr->pe_allocated--;
for (p = 0; p < vg_ptr->pv_cur; p++) {
- if (vg_ptr->pv[p]->pv_dev ==
- old_lv->lv_current_pe[l].dev) {
+ if (kdev_same(vg_ptr->pv[p]->pv_dev,
+ old_lv->lv_current_pe[l].dev)) {
vg_ptr->pv[p]->pe_allocated--;
break;
}
@@ -2249,8 +2270,8 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
for (l = 0; l < new_lv->lv_allocated_le; l++) {
vg_ptr->pe_allocated++;
for (p = 0; p < vg_ptr->pv_cur; p++) {
- if (vg_ptr->pv[p]->pv_dev ==
- new_lv->lv_current_pe[l].dev) {
+ if (kdev_same(vg_ptr->pv[p]->pv_dev,
+ new_lv->lv_current_pe[l].dev)) {
vg_ptr->pv[p]->pe_allocated++;
break;
}
@@ -2358,9 +2379,9 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv)
old_lv->lv_allocated_le = new_lv->lv_allocated_le;
old_lv->lv_current_le = new_lv->lv_current_le;
old_lv->lv_current_pe = new_lv->lv_current_pe;
- lvm_gendisk.part[MINOR(old_lv->lv_dev)].nr_sects =
+ lvm_gendisk.part[minor(old_lv->lv_dev)].nr_sects =
old_lv->lv_size;
- lvm_size[MINOR(old_lv->lv_dev)] = old_lv->lv_size >> 1;
+ lvm_size[minor(old_lv->lv_dev)] = old_lv->lv_size >> 1;
if (old_lv->lv_access & LV_SNAPSHOT_ORG) {
lv_t *snap;
@@ -2373,9 +2394,9 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv)
snap->lv_current_le = old_lv->lv_current_le;
snap->lv_size = old_lv->lv_size;
- lvm_gendisk.part[MINOR(snap->lv_dev)].nr_sects
+ lvm_gendisk.part[minor(snap->lv_dev)].nr_sects
= old_lv->lv_size;
- lvm_size[MINOR(snap->lv_dev)] =
+ lvm_size[minor(snap->lv_dev)] =
old_lv->lv_size >> 1;
__update_hardsectsize(snap);
up_write(&snap->lv_lock);
@@ -2503,7 +2524,9 @@ static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) {
for ( l = 0; l < vg_ptr->lv_max; l++) {
if ( vg_ptr->lv[l] == NULL) continue;
- if ( vg_ptr->lv[l]->lv_dev == lv_status_bydev_req.dev) break;
+ if ( kdev_same(vg_ptr->lv[l]->lv_dev,
+ to_kdev_t(lv_status_bydev_req.dev)))
+ break;
}
if ( l == vg_ptr->lv_max) return -ENXIO;
@@ -2544,7 +2567,7 @@ static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, lv_t *lv)
for (l = 0; l < vg_ptr->lv_max; l++)
{
if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue;
- if (lv_ptr->lv_dev == lv->lv_dev)
+ if (kdev_same(lv_ptr->lv_dev, lv->lv_dev))
{
lvm_fs_remove_lv(vg_ptr, lv_ptr);
strncpy(lv_ptr->lv_name,
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 5e4cd3609..723000f28 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/config.h>
+#include <linux/linkage.h>
#include <linux/raid/md.h>
#include <linux/sysctl.h>
#include <linux/raid/xor.h>
@@ -118,11 +119,9 @@ static struct gendisk md_gendisk=
major: MD_MAJOR,
major_name: "md",
minor_shift: 0,
- max_p: 1,
part: md_hd_struct,
sizes: md_size,
nr_real: MAX_MD_DEVS,
- real_devices: NULL,
next: NULL,
fops: &md_fops,
};
@@ -141,9 +140,9 @@ dev_mapping_t mddev_map[MAX_MD_DEVS];
void add_mddev_mapping(mddev_t * mddev, kdev_t dev, void *data)
{
- unsigned int minor = MINOR(dev);
+ unsigned int minor = minor(dev);
- if (MAJOR(dev) != MD_MAJOR) {
+ if (major(dev) != MD_MAJOR) {
MD_BUG();
return;
}
@@ -157,9 +156,9 @@ void add_mddev_mapping(mddev_t * mddev, kdev_t dev, void *data)
void del_mddev_mapping(mddev_t * mddev, kdev_t dev)
{
- unsigned int minor = MINOR(dev);
+ unsigned int minor = minor(dev);
- if (MAJOR(dev) != MD_MAJOR) {
+ if (major(dev) != MD_MAJOR) {
MD_BUG();
return;
}
@@ -187,7 +186,7 @@ static mddev_t * alloc_mddev(kdev_t dev)
{
mddev_t *mddev;
- if (MAJOR(dev) != MD_MAJOR) {
+ if (major(dev) != MD_MAJOR) {
MD_BUG();
return 0;
}
@@ -197,7 +196,7 @@ static mddev_t * alloc_mddev(kdev_t dev)
memset(mddev, 0, sizeof(*mddev));
- mddev->__minor = MINOR(dev);
+ mddev->__minor = minor(dev);
init_MUTEX(&mddev->reconfig_sem);
init_MUTEX(&mddev->recovery_sem);
init_MUTEX(&mddev->resync_sem);
@@ -236,7 +235,7 @@ mdk_rdev_t * find_rdev(mddev_t * mddev, kdev_t dev)
mdk_rdev_t *rdev;
ITERATE_RDEV(mddev,rdev,tmp) {
- if (rdev->dev == dev)
+ if (kdev_same(rdev->dev, dev))
return rdev;
}
return NULL;
@@ -253,7 +252,7 @@ char * partition_name(kdev_t dev)
while (tmp != &device_names) {
dname = list_entry(tmp, dev_name_t, list);
- if (dname->dev == dev)
+ if (kdev_same(dname->dev, dev))
return dname->name;
tmp = tmp->next;
}
@@ -268,7 +267,7 @@ char * partition_name(kdev_t dev)
hd = get_gendisk (dev);
dname->name = NULL;
if (hd)
- dname->name = disk_name (hd, MINOR(dev), dname->namebuf);
+ dname->name = disk_name (hd, minor(dev), dname->namebuf);
if (!dname->name) {
sprintf (dname->namebuf, "[dev %s]", kdevname(dev));
dname->name = dname->namebuf;
@@ -286,8 +285,8 @@ static unsigned int calc_dev_sboffset(kdev_t dev, mddev_t *mddev,
{
unsigned int size = 0;
- if (blk_size[MAJOR(dev)])
- size = blk_size[MAJOR(dev)][MINOR(dev)];
+ if (blk_size[major(dev)])
+ size = blk_size[major(dev)][minor(dev)];
if (persistent)
size = MD_NEW_SIZE_BLOCKS(size);
return size;
@@ -469,40 +468,45 @@ static void free_disk_sb(mdk_rdev_t * rdev)
static int read_disk_sb(mdk_rdev_t * rdev)
{
- int ret = -EINVAL;
- struct buffer_head *bh = NULL;
- kdev_t dev = rdev->dev;
- mdp_super_t *sb;
+ struct address_space *mapping = rdev->bdev->bd_inode->i_mapping;
+ struct page *page;
+ char *p;
unsigned long sb_offset;
+ int n = PAGE_CACHE_SIZE / BLOCK_SIZE;
if (!rdev->sb) {
MD_BUG();
- goto abort;
+ return -EINVAL;
}
/*
* Calculate the position of the superblock,
- * it's at the end of the disk
+ * it's at the end of the disk.
+ *
+ * It also happens to be a multiple of 4Kb.
*/
sb_offset = calc_dev_sboffset(rdev->dev, rdev->mddev, 1);
rdev->sb_offset = sb_offset;
- fsync_dev(dev);
- set_blocksize (dev, MD_SB_BYTES);
- bh = bread (dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
-
- if (bh) {
- sb = (mdp_super_t *) bh->b_data;
- memcpy (rdev->sb, sb, MD_SB_BYTES);
- } else {
- printk(NO_SB,partition_name(rdev->dev));
- goto abort;
- }
+ page = read_cache_page(mapping, sb_offset/n,
+ (filler_t *)mapping->a_ops->readpage, NULL);
+ if (IS_ERR(page))
+ goto out;
+ wait_on_page(page);
+ if (!Page_Uptodate(page))
+ goto fail;
+ if (PageError(page))
+ goto fail;
+ p = (char *)page_address(page) + BLOCK_SIZE * (sb_offset % n);
+ memcpy((char*)rdev->sb, p, MD_SB_BYTES);
+ page_cache_release(page);
printk(KERN_INFO " [events: %08lx]\n", (unsigned long)rdev->sb->events_lo);
- ret = 0;
-abort:
- if (bh)
- brelse (bh);
- return ret;
+ return 0;
+
+fail:
+ page_cache_release(page);
+out:
+ printk(NO_SB,partition_name(rdev->dev));
+ return -EINVAL;
}
static unsigned int calc_sb_csum(mdp_super_t * sb)
@@ -556,10 +560,10 @@ static kdev_t dev_unit(kdev_t dev)
struct gendisk *hd = get_gendisk(dev);
if (!hd)
- return 0;
+ return NODEV;
mask = ~((1 << hd->minor_shift) - 1);
- return MKDEV(MAJOR(dev), MINOR(dev) & mask);
+ return mk_kdev(major(dev), minor(dev) & mask);
}
static mdk_rdev_t * match_dev_unit(mddev_t *mddev, kdev_t dev)
@@ -568,7 +572,7 @@ static mdk_rdev_t * match_dev_unit(mddev_t *mddev, kdev_t dev)
mdk_rdev_t *rdev;
ITERATE_RDEV(mddev,rdev,tmp)
- if (dev_unit(rdev->dev) == dev_unit(dev))
+ if (kdev_same(dev_unit(rdev->dev), dev_unit(dev)))
return rdev;
return NULL;
@@ -637,7 +641,7 @@ static int lock_rdev(mdk_rdev_t *rdev)
int err = 0;
struct block_device *bdev;
- bdev = bdget(rdev->dev);
+ bdev = bdget(kdev_t_to_nr(rdev->dev));
if (!bdev)
return -ENOMEM;
err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW);
@@ -675,7 +679,7 @@ static void export_rdev(mdk_rdev_t * rdev)
#ifndef MODULE
md_autodetect_dev(rdev->dev);
#endif
- rdev->dev = 0;
+ rdev->dev = NODEV;
rdev->faulty = 0;
kfree(rdev);
}
@@ -728,7 +732,7 @@ static void free_mddev(mddev_t *mddev)
while (atomic_read(&mddev->recovery_sem.count) != 1)
schedule();
- del_mddev_mapping(mddev, MKDEV(MD_MAJOR, mdidx(mddev)));
+ del_mddev_mapping(mddev, mk_kdev(MD_MAJOR, mdidx(mddev)));
list_del(&mddev->all_mddevs);
INIT_LIST_HEAD(&mddev->all_mddevs);
kfree(mddev);
@@ -743,7 +747,7 @@ static void free_mddev(mddev_t *mddev)
static void print_desc(mdp_disk_t *desc)
{
printk(" DISK<N:%d,%s(%d,%d),R:%d,S:%d>\n", desc->number,
- partition_name(MKDEV(desc->major,desc->minor)),
+ partition_name(mk_kdev(desc->major,desc->minor)),
desc->major,desc->minor,desc->raid_disk,desc->state);
}
@@ -877,22 +881,21 @@ static mdk_rdev_t * find_rdev_all(kdev_t dev)
tmp = all_raid_disks.next;
while (tmp != &all_raid_disks) {
rdev = list_entry(tmp, mdk_rdev_t, all);
- if (rdev->dev == dev)
+ if (kdev_same(rdev->dev, dev))
return rdev;
tmp = tmp->next;
}
return NULL;
}
-#define GETBLK_FAILED KERN_ERR \
-"md: getblk failed for device %s\n"
-
static int write_disk_sb(mdk_rdev_t * rdev)
{
- struct buffer_head *bh;
- kdev_t dev;
+ struct address_space *mapping = rdev->bdev->bd_inode->i_mapping;
+ struct page *page;
+ unsigned offs;
+ int error;
+ kdev_t dev = rdev->dev;
unsigned long sb_offset, size;
- mdp_super_t *sb;
if (!rdev->sb) {
MD_BUG();
@@ -907,7 +910,6 @@ static int write_disk_sb(mdk_rdev_t * rdev)
return 1;
}
- dev = rdev->dev;
sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1);
if (rdev->sb_offset != sb_offset) {
printk(KERN_INFO "%s's sb offset has changed from %ld to %ld, skipping\n",
@@ -928,26 +930,32 @@ static int write_disk_sb(mdk_rdev_t * rdev)
printk(KERN_INFO "(write) %s's sb offset: %ld\n", partition_name(dev), sb_offset);
fsync_dev(dev);
- set_blocksize(dev, MD_SB_BYTES);
- bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
- if (!bh) {
- printk(GETBLK_FAILED, partition_name(dev));
- return 1;
- }
- memset(bh->b_data,0,bh->b_size);
- sb = (mdp_super_t *) bh->b_data;
- memcpy(sb, rdev->sb, MD_SB_BYTES);
-
- mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh);
- ll_rw_block(WRITE, 1, &bh);
- wait_on_buffer(bh);
- brelse(bh);
+ page = grab_cache_page(mapping, sb_offset/(PAGE_CACHE_SIZE/BLOCK_SIZE));
+ offs = sb_offset % (PAGE_CACHE_SIZE/BLOCK_SIZE);
+ if (!page)
+ goto fail;
+ error = mapping->a_ops->prepare_write(NULL, page, offs,
+ offs + MD_SB_BYTES);
+ if (error)
+ goto unlock;
+ memcpy((char *)page_address(page) + offs, rdev->sb, MD_SB_BYTES);
+ error = mapping->a_ops->commit_write(NULL, page, offs,
+ offs + MD_SB_BYTES);
+ if (error)
+ goto unlock;
+ UnlockPage(page);
+ wait_on_page(page);
+ page_cache_release(page);
fsync_dev(dev);
skip:
return 0;
+unlock:
+ UnlockPage(page);
+ page_cache_release(page);
+fail:
+ printk("md: write_disk_sb failed for device %s\n", partition_name(dev));
+ return 1;
}
-#undef GETBLK_FAILED
static void set_this_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
@@ -958,12 +966,12 @@ static void set_this_disk(mddev_t *mddev, mdk_rdev_t *rdev)
desc = mddev->sb->disks + i;
#if 0
if (disk_faulty(desc)) {
- if (MKDEV(desc->major,desc->minor) == rdev->dev)
+ if (mk_kdev(desc->major,desc->minor) == rdev->dev)
ok = 1;
continue;
}
#endif
- if (MKDEV(desc->major,desc->minor) == rdev->dev) {
+ if (kdev_same(mk_kdev(desc->major,desc->minor), rdev->dev)) {
rdev->sb->this_disk = *desc;
rdev->desc_nr = desc->number;
ok = 1;
@@ -1098,8 +1106,8 @@ static int md_import_device(kdev_t newdev, int on_disk)
rdev->faulty = 0;
size = 0;
- if (blk_size[MAJOR(newdev)])
- size = blk_size[MAJOR(newdev)][MINOR(newdev)];
+ if (blk_size[major(newdev)])
+ size = blk_size[major(newdev)][minor(newdev)];
if (!size) {
printk(KERN_WARNING "md: %s has zero size, marking faulty!\n",
partition_name(newdev));
@@ -1120,11 +1128,11 @@ static int md_import_device(kdev_t newdev, int on_disk)
}
if (rdev->sb->level != -4) {
- rdev->old_dev = MKDEV(rdev->sb->this_disk.major,
+ rdev->old_dev = mk_kdev(rdev->sb->this_disk.major,
rdev->sb->this_disk.minor);
rdev->desc_nr = rdev->sb->this_disk.number;
} else {
- rdev->old_dev = MKDEV(0, 0);
+ rdev->old_dev = NODEV;
rdev->desc_nr = -1;
}
}
@@ -1290,7 +1298,7 @@ static int analyze_sbs(mddev_t * mddev)
ev2 = md_event(sb);
ev3 = ev2;
--ev3;
- if ((rdev->dev != rdev->old_dev) &&
+ if (!kdev_same(rdev->dev, rdev->old_dev) &&
((ev1 == ev2) || (ev1 == ev3))) {
mdp_disk_t *desc;
@@ -1301,15 +1309,15 @@ static int analyze_sbs(mddev_t * mddev)
goto abort;
}
desc = &sb->disks[rdev->desc_nr];
- if (rdev->old_dev != MKDEV(desc->major, desc->minor)) {
+ if (!kdev_same( rdev->old_dev, mk_kdev(desc->major, desc->minor))) {
MD_BUG();
goto abort;
}
- desc->major = MAJOR(rdev->dev);
- desc->minor = MINOR(rdev->dev);
+ desc->major = major(rdev->dev);
+ desc->minor = minor(rdev->dev);
desc = &rdev->sb->this_disk;
- desc->major = MAJOR(rdev->dev);
- desc->minor = MINOR(rdev->dev);
+ desc->major = major(rdev->dev);
+ desc->minor = minor(rdev->dev);
}
}
@@ -1327,7 +1335,7 @@ static int analyze_sbs(mddev_t * mddev)
kdev_t dev;
desc = sb->disks + i;
- dev = MKDEV(desc->major, desc->minor);
+ dev = mk_kdev(desc->major, desc->minor);
/*
* We kick faulty devices/descriptors immediately.
@@ -1349,7 +1357,7 @@ static int analyze_sbs(mddev_t * mddev)
break;
}
if (!found) {
- if (dev == MKDEV(0,0))
+ if (kdev_none(dev))
continue;
printk(KERN_WARNING "md%d: removing former faulty %s!\n",
mdidx(mddev), partition_name(dev));
@@ -1367,7 +1375,7 @@ static int analyze_sbs(mddev_t * mddev)
remove_descriptor(desc, sb);
}
- if (dev == MKDEV(0,0))
+ if (kdev_none(dev))
continue;
/*
* Is this device present in the rdev ring?
@@ -1380,8 +1388,9 @@ static int analyze_sbs(mddev_t * mddev)
* we cannot check rdev->number.
* We can check the device though.
*/
- if ((sb->level == -4) && (rdev->dev ==
- MKDEV(desc->major,desc->minor))) {
+ if ((sb->level == -4) &&
+ kdev_same(rdev->dev,
+ mk_kdev(desc->major,desc->minor))) {
found = 1;
break;
}
@@ -1408,9 +1417,9 @@ static int analyze_sbs(mddev_t * mddev)
kdev_t dev;
desc = sb->disks + i;
- dev = MKDEV(desc->major, desc->minor);
+ dev = mk_kdev(desc->major, desc->minor);
- if (dev == MKDEV(0,0))
+ if (kdev_none(dev))
continue;
if (disk_faulty(desc)) {
@@ -1474,8 +1483,8 @@ static int analyze_sbs(mddev_t * mddev)
* is the device unique?
*/
ITERATE_RDEV(mddev,rdev2,tmp2) {
- if ((rdev2 != rdev) &&
- (rdev2->dev == rdev->dev)) {
+ if (rdev2 != rdev &&
+ kdev_same(rdev2->dev, rdev->dev)) {
MD_BUG();
goto abort;
}
@@ -1725,7 +1734,7 @@ static int do_md_run(mddev_t * mddev)
* twice as large as sectors.
*/
md_hd_struct[mdidx(mddev)].start_sect = 0;
- register_disk(&md_gendisk, MKDEV(MAJOR_NR,mdidx(mddev)),
+ register_disk(&md_gendisk, mk_kdev(MAJOR_NR,mdidx(mddev)),
1, &md_fops, md_size[mdidx(mddev)]<<1);
read_ahead[MD_MAJOR] = 1024;
@@ -1945,7 +1954,7 @@ static void autorun_devices(kdev_t countdev)
* mostly sane superblocks. It's time to allocate the
* mddev.
*/
- md_kdev = MKDEV(MD_MAJOR, rdev0->sb->md_minor);
+ md_kdev = mk_kdev(MD_MAJOR, rdev0->sb->md_minor);
mddev = kdev_to_mddev(md_kdev);
if (mddev) {
printk(KERN_WARNING "md: md%d already running, cannot run %s\n",
@@ -1959,7 +1968,7 @@ static void autorun_devices(kdev_t countdev)
printk(KERN_ERR "md: cannot allocate memory for md drive.\n");
break;
}
- if (md_kdev == countdev)
+ if (kdev_same(md_kdev, countdev))
atomic_inc(&mddev->active);
printk(KERN_INFO "md: created md%d\n", mdidx(mddev));
ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) {
@@ -2042,11 +2051,11 @@ static int autostart_array(kdev_t startdev, kdev_t countdev)
kdev_t dev;
desc = sb->disks + i;
- dev = MKDEV(desc->major, desc->minor);
+ dev = mk_kdev(desc->major, desc->minor);
- if (dev == MKDEV(0,0))
+ if (kdev_none(dev))
continue;
- if (dev == startdev)
+ if (kdev_same(dev, startdev))
continue;
if (md_import_device(dev, 1)) {
printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n",
@@ -2171,7 +2180,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
mdk_rdev_t *rdev;
unsigned int nr;
kdev_t dev;
- dev = MKDEV(info->major,info->minor);
+ dev = mk_kdev(info->major,info->minor);
if (find_rdev_all(dev)) {
printk(KERN_WARNING "md: device %s already used in a RAID array!\n",
@@ -2443,8 +2452,8 @@ static int hot_add_disk(mddev_t * mddev, kdev_t dev)
}
disk->raid_disk = disk->number;
- disk->major = MAJOR(dev);
- disk->minor = MINOR(dev);
+ disk->major = major(dev);
+ disk->minor = minor(dev);
if (mddev->pers->diskop(mddev, &disk, DISKOP_HOT_ADD_DISK)) {
MD_BUG();
@@ -2570,7 +2579,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
return -EACCES;
dev = inode->i_rdev;
- minor = MINOR(dev);
+ minor = minor(dev);
if (minor >= MAX_MD_DEVS) {
MD_BUG();
return -EINVAL;
@@ -2686,10 +2695,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
/*
* possibly make it lock the array ...
*/
- err = autostart_array((kdev_t)arg, dev);
+ err = autostart_array(val_to_kdev(arg), dev);
if (err) {
printk(KERN_WARNING "md: autostart %s failed!\n",
- partition_name((kdev_t)arg));
+ partition_name(val_to_kdev(arg)));
goto abort;
}
goto done;
@@ -2794,14 +2803,14 @@ static int md_ioctl(struct inode *inode, struct file *file,
goto done_unlock;
}
case HOT_GENERATE_ERROR:
- err = hot_generate_error(mddev, (kdev_t)arg);
+ err = hot_generate_error(mddev, val_to_kdev(arg));
goto done_unlock;
case HOT_REMOVE_DISK:
- err = hot_remove_disk(mddev, (kdev_t)arg);
+ err = hot_remove_disk(mddev, val_to_kdev(arg));
goto done_unlock;
case HOT_ADD_DISK:
- err = hot_add_disk(mddev, (kdev_t)arg);
+ err = hot_add_disk(mddev, val_to_kdev(arg));
goto done_unlock;
case SET_DISK_INFO:
@@ -2821,7 +2830,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
goto done_unlock;
case SET_DISK_FAULTY:
- err = set_disk_faulty(mddev, (kdev_t)arg);
+ err = set_disk_faulty(mddev, val_to_kdev(arg));
goto done_unlock;
case RUN_ARRAY:
@@ -3039,7 +3048,7 @@ int md_error(mddev_t *mddev, kdev_t rdev)
mdk_rdev_t * rrdev;
dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
- MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev),
+ major(dev),minor(dev),major(rdev),minor(rdev),
__builtin_return_address(0),__builtin_return_address(1),
__builtin_return_address(2),__builtin_return_address(3));
@@ -3283,7 +3292,7 @@ mdp_disk_t *get_spare(mddev_t *mddev)
static unsigned int sync_io[DK_MAX_MAJOR][DK_MAX_DISK];
void md_sync_acct(kdev_t dev, unsigned long nr_sectors)
{
- unsigned int major = MAJOR(dev);
+ unsigned int major = major(dev);
unsigned int index;
index = disk_index(dev);
@@ -3302,7 +3311,7 @@ static int is_mddev_idle(mddev_t *mddev)
idle = 1;
ITERATE_RDEV(mddev,rdev,tmp) {
- int major = MAJOR(rdev->dev);
+ int major = major(rdev->dev);
int idx = disk_index(rdev->dev);
if ((idx >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
@@ -3526,7 +3535,7 @@ restart:
if (!spare)
continue;
printk(KERN_INFO "md%d: resyncing spare disk %s to replace failed disk\n",
- mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
+ mdidx(mddev), partition_name(mk_kdev(spare->major,spare->minor)));
if (!mddev->pers->diskop)
continue;
if (mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_WRITE))
@@ -3536,7 +3545,7 @@ restart:
err = md_do_sync(mddev, spare);
if (err == -EIO) {
printk(KERN_INFO "md%d: spare disk %s failed, skipping to next spare.\n",
- mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
+ mdidx(mddev), partition_name(mk_kdev(spare->major,spare->minor)));
if (!disk_faulty(spare)) {
mddev->pers->diskop(mddev,&spare,DISKOP_SPARE_INACTIVE);
mark_disk_faulty(spare);
@@ -3861,7 +3870,7 @@ void __init md_setup_drive(void)
if (handle != 0) {
unsigned major, minor;
devfs_get_maj_min(handle, &major, &minor);
- dev = MKDEV(major, minor);
+ dev = mk_kdev(major, minor);
}
if (!dev) {
printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
@@ -3886,7 +3895,7 @@ void __init md_setup_drive(void)
}
printk(KERN_INFO "md: Loading md%d: %s\n", minor, md_setup_args.device_names[minor]);
- mddev = alloc_mddev(MKDEV(MD_MAJOR,minor));
+ mddev = alloc_mddev(mk_kdev(MD_MAJOR,minor));
if (!mddev) {
printk(KERN_ERR "md: kmalloc failed - cannot start array %d\n", minor);
continue;
@@ -3913,8 +3922,8 @@ void __init md_setup_drive(void)
dinfo.number = i;
dinfo.raid_disk = i;
dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC);
- dinfo.major = MAJOR(dev);
- dinfo.minor = MINOR(dev);
+ dinfo.major = major(dev);
+ dinfo.minor = minor(dev);
mddev->sb->nr_disks++;
mddev->sb->raid_disks++;
mddev->sb->active_disks++;
@@ -3924,8 +3933,8 @@ void __init md_setup_drive(void)
} else {
/* persistent */
for (i = 0; (dev = devices[i]); i++) {
- dinfo.major = MAJOR(dev);
- dinfo.minor = MINOR(dev);
+ dinfo.major = major(dev);
+ dinfo.minor = minor(dev);
add_new_disk (mddev, &dinfo);
}
}
@@ -4033,4 +4042,4 @@ EXPORT_SYMBOL(md_interrupt_thread);
EXPORT_SYMBOL(mddev_map);
EXPORT_SYMBOL(md_check_ordering);
EXPORT_SYMBOL(get_spare);
-
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 5cbbd2c16..94d3cbb7c 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <linux/raid/multipath.h>
#include <asm/atomic.h>
@@ -353,7 +354,7 @@ static int multipath_error (mddev_t *mddev, kdev_t dev)
* which has just failed.
*/
for (i = 0; i < disks; i++) {
- if (multipaths[i].dev==dev && !multipaths[i].operational)
+ if (kdev_same(multipaths[i].dev, dev) && !multipaths[i].operational)
return 0;
}
printk (LAST_DISK);
@@ -362,7 +363,7 @@ static int multipath_error (mddev_t *mddev, kdev_t dev)
* Mark disk as unusable
*/
for (i = 0; i < disks; i++) {
- if (multipaths[i].dev==dev && multipaths[i].operational) {
+ if (kdev_same(multipaths[i].dev,dev) && multipaths[i].operational) {
mark_disk_bad(mddev, i);
break;
}
@@ -605,7 +606,7 @@ static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
*d = failed_desc;
- if (sdisk->dev == MKDEV(0,0))
+ if (kdev_none(sdisk->dev))
sdisk->used_slot = 0;
/*
* this really activates the spare.
@@ -630,7 +631,7 @@ static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
err = 1;
goto abort;
}
- rdisk->dev = MKDEV(0,0);
+ rdisk->dev = NODEV;
rdisk->used_slot = 0;
conf->nr_disks--;
break;
@@ -647,7 +648,7 @@ static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
adisk->number = added_desc->number;
adisk->raid_disk = added_desc->raid_disk;
- adisk->dev = MKDEV(added_desc->major,added_desc->minor);
+ adisk->dev = mk_kdev(added_desc->major,added_desc->minor);
adisk->operational = 0;
adisk->spare = 1;
@@ -710,7 +711,7 @@ static void multipathd (void *data)
dev = bh->b_dev;
multipath_map (mddev, &bh->b_dev);
- if (bh->b_dev == dev) {
+ if (kdev_same(bh->b_dev, dev)) {
printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr);
multipath_end_bh_io(mp_bh, 0);
} else {
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 998a8b589..3481c238f 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -611,7 +611,7 @@ static int error(mddev_t *mddev, kdev_t dev)
* else mark the drive as failed
*/
for (i = 0; i < disks; i++)
- if (mirrors[i].dev == dev && mirrors[i].operational)
+ if (kdev_same(mirrors[i].dev, dev) && mirrors[i].operational)
break;
if (i == disks)
return 0;
@@ -853,7 +853,7 @@ static int diskop(mddev_t *mddev, mdp_disk_t **d, int state)
*d = failed_desc;
- if (sdisk->dev == MKDEV(0,0))
+ if (kdev_none(sdisk->dev))
sdisk->used_slot = 0;
/*
* this really activates the spare.
@@ -879,7 +879,7 @@ static int diskop(mddev_t *mddev, mdp_disk_t **d, int state)
err = 1;
goto abort;
}
- rdisk->dev = MKDEV(0,0);
+ rdisk->dev = NODEV;
rdisk->used_slot = 0;
conf->nr_disks--;
break;
@@ -896,7 +896,7 @@ static int diskop(mddev_t *mddev, mdp_disk_t **d, int state)
adisk->number = added_desc->number;
adisk->raid_disk = added_desc->raid_disk;
- adisk->dev = MKDEV(added_desc->major, added_desc->minor);
+ adisk->dev = mk_kdev(added_desc->major, added_desc->minor);
adisk->operational = 0;
adisk->write_only = 0;
@@ -1098,7 +1098,7 @@ static void raid1d(void *data)
case READA:
dev = bio->bi_dev;
map(mddev, &bio->bi_dev);
- if (bio->bi_dev == dev) {
+ if (kdev_same(bio->bi_dev, dev)) {
printk(IO_ERROR, partition_name(bio->bi_dev), r1_bio->sector);
raid_end_bio_io(r1_bio, 0, 0);
break;
@@ -1428,7 +1428,7 @@ static int run(mddev_t *mddev)
disk->number = descriptor->number;
disk->raid_disk = disk_idx;
- disk->dev = MKDEV(0,0);
+ disk->dev = NODEV;
disk->operational = 0;
disk->write_only = 0;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 913b46f8e..6773bf201 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -487,7 +487,7 @@ static int raid5_error (mddev_t *mddev, kdev_t dev)
PRINTK("raid5_error called\n");
for (i = 0, disk = conf->disks; i < conf->raid_disks; i++, disk++) {
- if (disk->dev == dev) {
+ if (kdev_same(disk->dev, dev)) {
if (disk->operational) {
disk->operational = 0;
mark_disk_faulty(sb->disks+disk->number);
@@ -513,7 +513,7 @@ static int raid5_error (mddev_t *mddev, kdev_t dev)
*/
if (conf->spare) {
disk = conf->spare;
- if (disk->dev == dev) {
+ if (kdev_same(disk->dev, dev)) {
printk (KERN_ALERT
"raid5: Disk failure on spare %s\n",
partition_name (dev));
@@ -1226,23 +1226,6 @@ static int raid5_make_request (mddev_t *mddev, int rw, struct buffer_head * bh)
return 0;
}
-/*
- * Determine correct block size for this device.
- */
-unsigned int device_bsize (kdev_t dev)
-{
- unsigned int i, correct_size;
-
- correct_size = BLOCK_SIZE;
- if (blksize_size[MAJOR(dev)]) {
- i = blksize_size[MAJOR(dev)][MINOR(dev)];
- if (i)
- correct_size = i;
- }
-
- return correct_size;
-}
-
static int raid5_sync_request (mddev_t *mddev, unsigned long sector_nr)
{
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
@@ -1477,7 +1460,7 @@ static int raid5_run (mddev_t *mddev)
disk->number = desc->number;
disk->raid_disk = raid_disk;
- disk->dev = MKDEV(0,0);
+ disk->dev = NODEV;
disk->operational = 0;
disk->write_only = 0;
@@ -1936,7 +1919,7 @@ static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
*d = failed_desc;
- if (sdisk->dev == MKDEV(0,0))
+ if (kdev_none(sdisk->dev))
sdisk->used_slot = 0;
/*
@@ -1964,7 +1947,7 @@ static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
err = 1;
goto abort;
}
- rdisk->dev = MKDEV(0,0);
+ rdisk->dev = NODEV;
rdisk->used_slot = 0;
break;
@@ -1981,7 +1964,7 @@ static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
adisk->number = added_desc->number;
adisk->raid_disk = added_desc->raid_disk;
- adisk->dev = MKDEV(added_desc->major,added_desc->minor);
+ adisk->dev = mk_kdev(added_desc->major,added_desc->minor);
adisk->operational = 0;
adisk->write_only = 0;
diff --git a/drivers/md/xor.c b/drivers/md/xor.c
index 454ee9c13..af78ccd16 100644
--- a/drivers/md/xor.c
+++ b/drivers/md/xor.c
@@ -19,6 +19,7 @@
#define BH_TRACE 0
#include <linux/module.h>
#include <linux/raid/md.h>
+#include <linux/raid/md_compatible.h>
#include <linux/raid/xor.h>
#include <asm/xor.h>
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 32063589f..6aec77a8a 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -38,7 +38,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 7b5d7d7bd..e51721e71 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -40,7 +40,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 1b9cd7124..2023e9e6a 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -37,7 +37,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
#include <linux/interrupt.h>
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index e3eee0c76..3dfa777e5 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -2386,7 +2386,7 @@ static int reset_camera(struct cam_data *cam)
goto_high_power(cam);
do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
if (goto_low_power(cam))
- return -NODEV;
+ return -ENODEV;
}
/* procedure described in developer's guide p3-28 */
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 778f29d74..58cb99761 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -36,7 +36,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index ad8250401..977ac0851 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -37,7 +37,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <asm/types.h>
#include <linux/types.h>
#include <linux/wrapper.h>
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 60686c7d1..368a3b1fd 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -177,7 +177,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm
static int tvmixer_open(struct inode *inode, struct file *file)
{
- int i, minor = MINOR(inode->i_rdev);
+ int i, minor = minor(inode->i_rdev);
struct TVMIXER *mix = NULL;
struct i2c_client *client = NULL;
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index b73e38110..65183db93 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -70,7 +70,7 @@ LIST_HEAD(videodev_proc_list);
static ssize_t video_read(struct file *file,
char *buf, size_t count, loff_t *ppos)
{
- struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+ struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
if(vfl->read)
return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
else
@@ -86,7 +86,7 @@ static ssize_t video_read(struct file *file,
static ssize_t video_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
- struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+ struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
if(vfl->write)
return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
else
@@ -100,7 +100,7 @@ static ssize_t video_write(struct file *file, const char *buf,
static unsigned int video_poll(struct file *file, poll_table * wait)
{
- struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+ struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
if(vfl->poll)
return vfl->poll(vfl, file, wait);
else
@@ -114,7 +114,7 @@ static unsigned int video_poll(struct file *file, poll_table * wait)
static int video_open(struct inode *inode, struct file *file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
int err, retval = 0;
struct video_device *vfl;
@@ -170,7 +170,7 @@ static int video_release(struct inode *inode, struct file *file)
{
struct video_device *vfl;
lock_kernel();
- vfl=video_device[MINOR(inode->i_rdev)];
+ vfl=video_device[minor(inode->i_rdev)];
if(vfl->close)
vfl->close(vfl);
vfl->busy=0;
@@ -183,7 +183,7 @@ static int video_release(struct inode *inode, struct file *file)
static int video_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct video_device *vfl=video_device[MINOR(inode->i_rdev)];
+ struct video_device *vfl=video_device[minor(inode->i_rdev)];
int err=vfl->ioctl(vfl, cmd, (void *)arg);
if(err!=-ENOIOCTLCMD)
@@ -203,7 +203,7 @@ static int video_ioctl(struct inode *inode, struct file *file,
int video_mmap(struct file *file, struct vm_area_struct *vma)
{
int ret = -EINVAL;
- struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+ struct video_device *vfl=video_device[minor(file->f_dentry->d_inode->i_rdev)];
if(vfl->mmap) {
lock_kernel();
ret = vfl->mmap(vma, vfl, (char *)vma->vm_start,
diff --git a/drivers/media/video/zr36067.c b/drivers/media/video/zr36067.c
index 0cc3ea25a..998ea2352 100644
--- a/drivers/media/video/zr36067.c
+++ b/drivers/media/video/zr36067.c
@@ -58,7 +58,6 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
-#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index 6e57ebf6c..9f76cd8d2 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -35,7 +35,6 @@
#include <asm/page.h>
#include <linux/sched.h>
#include <linux/video_decoder.h>
-#include <asm/segment.h>
#include <linux/version.h>
#include <asm/uaccess.h>
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 84f135bd4..1ca4133e9 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -1780,7 +1780,6 @@ static struct gendisk i2ob_gendisk =
major: MAJOR_NR,
major_name: "i2o/hd",
minor_shift: 4,
- max_p: 1<<4,
part: i2ob,
sizes: i2ob_sizes,
nr_real: MAX_I2OB,
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
index 857753de9..a1fd4888b 100644
--- a/drivers/mtd/devices/blkmtd.c
+++ b/drivers/mtd/devices/blkmtd.c
@@ -63,7 +63,6 @@
#define CONFIG_MTD_BLKDEV_ERASESIZE 128
#define VERSION "1.1"
extern int *blk_size[];
-extern int *blksize_size[];
/* Info for the block device */
typedef struct mtd_raw_dev_data_s {
@@ -905,14 +904,7 @@ static int __init init_blkmtd(void)
DEBUG(1, "blkmtd: devname = %s\n", bdevname(rdev));
blocksize = BLOCK_SIZE;
- if(bs) {
- blocksize = bs;
- } else {
- if (blksize_size[maj] && blksize_size[maj][min]) {
- DEBUG(2, "blkmtd: blksize_size = %d\n", blksize_size[maj][min]);
- blocksize = blksize_size[maj][min];
- }
- }
+ blocksize = bs ? bs : block_size(rdev);
i = blocksize;
blocksize_bits = 0;
while(i != 1) {
diff --git a/drivers/mtd/devices/doc1000.c b/drivers/mtd/devices/doc1000.c
index e80985609..ff8375fb6 100644
--- a/drivers/mtd/devices/doc1000.c
+++ b/drivers/mtd/devices/doc1000.c
@@ -20,7 +20,6 @@
#include <linux/ioctl.h>
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <stdarg.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 2b42bdc12..cc647503b 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -98,7 +98,6 @@
#include <linux/ioctl.h>
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <stdarg.h>
#include <linux/pci.h>
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 6220e7366..bcb3d183d 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -20,7 +20,6 @@
#include <linux/init.h>
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <stdarg.h>
#include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index d15d74130..8e6ce8dab 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -72,33 +72,12 @@
#include <linux/hdreg.h>
#include <stdarg.h>
-#if (LINUX_VERSION_CODE >= 0x20100)
#include <linux/vmalloc.h>
-#endif
-#if (LINUX_VERSION_CODE >= 0x20303)
#include <linux/blkpg.h>
-#endif
#include <linux/mtd/ftl.h>
-/*====================================================================*/
-/* Stuff which really ought to be in compatmac.h */
-
-#if (LINUX_VERSION_CODE < 0x20328)
-#define register_disk(dev, drive, minors, ops, size) \
- do { (dev)->part[(drive)*(minors)].nr_sects = size; \
- if (size == 0) (dev)->part[(drive)*(minors)].start_sect = -1; \
- resetup_one_dev(dev, drive); } while (0);
-#endif
-#if (LINUX_VERSION_CODE < 0x20320)
-#define BLK_DEFAULT_QUEUE(n) blk_dev[n].request_fn
-#define blk_init_queue(q, req) q = (req)
-#define blk_cleanup_queue(q) q = NULL
-#define request_arg_t void
-#else
#define request_arg_t request_queue_t *q
-#endif
-
/*====================================================================*/
@@ -206,10 +185,6 @@ static struct gendisk ftl_gendisk = {
major: FTL_MAJOR,
major_name: "ftl",
minor_shift: PART_BITS,
- max_p: MAX_PART,
-#if (LINUX_VERSION_CODE < 0x20328)
- max_nr: MAX_DEV*MAX_PART,
-#endif
part: ftl_hd,
sizes: ftl_sizes,
};
@@ -224,23 +199,12 @@ static int ftl_reread_partitions(int minor);
static void ftl_erase_callback(struct erase_info *done);
-#if LINUX_VERSION_CODE < 0x20326
-static struct file_operations ftl_blk_fops = {
- open: ftl_open,
- release: ftl_close,
- ioctl: ftl_ioctl,
- read: block_read,
- write: block_write,
- fsync: block_fsync
-};
-#else
static struct block_device_operations ftl_blk_fops = {
owner: THIS_MODULE,
open: ftl_open,
release: ftl_close,
ioctl: ftl_ioctl,
};
-#endif
/*======================================================================
@@ -1177,22 +1141,11 @@ static int ftl_ioctl(struct inode *inode, struct file *file,
case BLKRRPART:
ret = ftl_reread_partitions(minor);
break;
-#if (LINUX_VERSION_CODE < 0x20303)
- case BLKFLSBUF:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-#endif
- fsync_dev(inode->i_rdev);
- invalidate_buffers(inode->i_rdev);
- break;
- RO_IOCTLS(inode->i_rdev, arg);
-#else
case BLKROSET:
case BLKROGET:
case BLKFLSBUF:
ret = blk_ioctl(inode->i_rdev, cmd, arg);
break;
-#endif
default:
ret = -EINVAL;
}
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index dc955e661..38718c70e 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -62,14 +62,9 @@ struct hd_struct part_table[256];
static struct gendisk nftl_gendisk = {
major: MAJOR_NR,
major_name: "nftl",
- minor_shift: NFTL_PARTN_BITS, /* Bits to shift to get real from partition */
- max_p: (1<<NFTL_PARTN_BITS)-1, /* Number of partitions per real */
-#if LINUX_VERSION_CODE < 0x20328
- max_nr: MAX_NFTLS, /* maximum number of real */
- init: dummy_init, /* init function */
-#endif
- part: part_table, /* hd struct */
- sizes: nftl_sizes, /* block sizes */
+ minor_shift: NFTL_PARTN_BITS, /* # of partition bits */
+ part: part_table, /* hd struct */
+ sizes: nftl_sizes, /* block sizes */
};
struct NFTLrecord *NFTLs[MAX_NFTLS];
diff --git a/drivers/net/de2104x.c b/drivers/net/de2104x.c
index 1d722dde4..5c43129ab 100644
--- a/drivers/net/de2104x.c
+++ b/drivers/net/de2104x.c
@@ -28,8 +28,8 @@
*/
#define DRV_NAME "de2104x"
-#define DRV_VERSION "0.5.2"
-#define DRV_RELDATE "Dec 11, 2001"
+#define DRV_VERSION "0.5.4"
+#define DRV_RELDATE "Jan 1, 2002"
#include <linux/config.h>
#include <linux/module.h>
@@ -46,6 +46,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
+#include <asm/unaligned.h>
/* These identify the driver base version and may not be removed. */
static char version[] __initdata =
@@ -100,6 +101,7 @@ MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copi
#define DE_DUMMY_SKB ((struct sk_buff *) 2)
#define DE_SETUP_FRAME_WORDS 96
#define DE_EEPROM_WORDS 256
+#define DE_EEPROM_SIZE (DE_EEPROM_WORDS * sizeof(u16))
#define DE_MAX_MEDIA 5
#define DE_MEDIA_TP_AUTO 0
@@ -110,6 +112,8 @@ MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copi
#define DE_MEDIA_INVALID DE_MAX_MEDIA
#define DE_MEDIA_FIRST 0
#define DE_MEDIA_LAST (DE_MAX_MEDIA - 1)
+#define DE_AUI_BNC (SUPPORTED_AUI | SUPPORTED_BNC)
+
#define DE_TIMER_LINK (60 * HZ)
#define DE_TIMER_NO_LINK (5 * HZ)
@@ -118,7 +122,9 @@ MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copi
#define DE_REGS_VER 1
/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (6*HZ)
+#define TX_TIMEOUT (6*HZ)
+
+#define DE_UNALIGNED_16(a) (u16)(get_unaligned((u16 *)(a)))
/* This is a mysterious value that can be written to CSR11 in the 21040 (only)
to support a pre-NWay full-duplex signaling mechanism using short frames.
@@ -255,7 +261,6 @@ struct de_srom_info_leaf {
u16 default_media;
u8 n_blocks;
u8 unused;
- struct de_srom_media_block media[0];
} __attribute__((packed));
struct de_desc {
@@ -308,6 +313,7 @@ struct de_private {
struct media_info media[DE_MAX_MEDIA];
struct timer_list media_timer;
+ u8 *ee_data;
unsigned board_idx;
unsigned de21040 : 1;
unsigned media_lock : 1;
@@ -320,6 +326,7 @@ static void de_clean_rings (struct de_private *de);
static void de_media_interrupt (struct de_private *de, u32 status);
static void de21040_media_timer (unsigned long data);
static void de21041_media_timer (unsigned long data);
+static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media);
static struct pci_device_id de_pci_tbl[] __initdata = {
@@ -919,7 +926,6 @@ static void de_stop_hw (struct de_private *de)
dw32(MacStatus, dr32(MacStatus));
- synchronize_irq();
udelay(10);
de->rx_tail = 0;
@@ -969,15 +975,29 @@ static void de_set_media (struct de_private *de)
else
de->macmode &= ~FullDuplex;
- if (netif_msg_link(de))
- printk(KERN_INFO "%s: set link %s, mode %x, sia %x,%x,%x,%x\n"
- KERN_INFO " set mode %x, set sia %x,%x,%x\n",
+ if (netif_msg_link(de)) {
+ printk(KERN_INFO "%s: set link %s\n"
+ KERN_INFO "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
+ KERN_INFO "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
de->dev->name, media_name[media],
- dr32(MacMode), dr32(SIAStatus), dr32(CSR13),
- dr32(CSR14), dr32(CSR15), de->macmode,
- de->media[media].csr13,
- de->media[media].csr14,
- de->media[media].csr15);
+ de->dev->name, dr32(MacMode), dr32(SIAStatus),
+ dr32(CSR13), dr32(CSR14), dr32(CSR15),
+ de->dev->name, de->macmode, de->media[media].csr13,
+ de->media[media].csr14, de->media[media].csr15);
+ }
+}
+
+static void de_next_media (struct de_private *de, u32 *media,
+ unsigned int n_media)
+{
+ unsigned int i;
+
+ for (i = 0; i < n_media; i++) {
+ if (de_ok_to_advertise(de, media[i])) {
+ de->media_type = media[i];
+ return;
+ }
+ }
}
static void de21040_media_timer (unsigned long data)
@@ -986,6 +1006,7 @@ static void de21040_media_timer (unsigned long data)
struct net_device *dev = de->dev;
u32 status = dr32(SIAStatus);
unsigned int carrier;
+ unsigned long flags;
carrier = (status & NetCxnErr) ? 0 : 1;
@@ -1010,12 +1031,17 @@ static void de21040_media_timer (unsigned long data)
if (de->media_lock)
return;
- if (de->media_type == DE_MEDIA_AUI)
- de->media_type = DE_MEDIA_TP;
- else
- de->media_type = DE_MEDIA_AUI;
+ if (de->media_type == DE_MEDIA_AUI) {
+ u32 next_state = DE_MEDIA_TP;
+ de_next_media(de, &next_state, 1);
+ } else {
+ u32 next_state = DE_MEDIA_AUI;
+ de_next_media(de, &next_state, 1);
+ }
+ spin_lock_irqsave(&de->lock, flags);
de_stop_rxtx(de);
+ spin_unlock_irqrestore(&de->lock, flags);
de_set_media(de);
de_start_rxtx(de);
@@ -1062,8 +1088,9 @@ static void de21041_media_timer (unsigned long data)
{
struct de_private *de = (struct de_private *) data;
struct net_device *dev = de->dev;
- u32 status = dr32(SIAStatus), new_media;
+ u32 status = dr32(SIAStatus);
unsigned int carrier;
+ unsigned long flags;
carrier = (status & NetCxnErr) ? 0 : 1;
@@ -1094,27 +1121,55 @@ static void de21041_media_timer (unsigned long data)
/* if activity detected, use that as hint for new media type */
if (status & NonselPortActive) {
- if (de->media_type == DE_MEDIA_AUI)
- de->media_type = DE_MEDIA_TP;
- else
+ unsigned int have_media = 1;
+
+ /* if AUI/BNC selected, then activity is on TP port */
+ if (de->media_type == DE_MEDIA_AUI ||
+ de->media_type == DE_MEDIA_BNC) {
+ if (de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))
+ de->media_type = DE_MEDIA_TP_AUTO;
+ else
+ have_media = 0;
+ }
+
+ /* TP selected. If there is only TP and BNC, then it's BNC */
+ else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_BNC) &&
+ de_ok_to_advertise(de, DE_MEDIA_BNC))
+ de->media_type = DE_MEDIA_BNC;
+
+ /* TP selected. If there is only TP and AUI, then it's AUI */
+ else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_AUI) &&
+ de_ok_to_advertise(de, DE_MEDIA_AUI))
de->media_type = DE_MEDIA_AUI;
- goto set_media;
- }
- /* move to next advertised media */
- new_media = de->media_type;
- do {
- if (new_media == DE_MEDIA_LAST)
- new_media = DE_MEDIA_FIRST;
+ /* otherwise, ignore the hint */
else
- new_media++;
- } while ((!de_ok_to_advertise(de, new_media)) &&
- (new_media != de->media_type));
+ have_media = 0;
- de->media_type = new_media;
+ if (have_media)
+ goto set_media;
+ }
+
+ /*
+ * Absent or ambiguous activity hint, move to next advertised
+ * media state. If de->media_type is left unchanged, this
+ * simply resets the PHY and reloads the current media settings.
+ */
+ if (de->media_type == DE_MEDIA_AUI) {
+ u32 next_states[] = { DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
+ de_next_media(de, next_states, ARRAY_SIZE(next_states));
+ } else if (de->media_type == DE_MEDIA_BNC) {
+ u32 next_states[] = { DE_MEDIA_TP_AUTO, DE_MEDIA_AUI };
+ de_next_media(de, next_states, ARRAY_SIZE(next_states));
+ } else {
+ u32 next_states[] = { DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
+ de_next_media(de, next_states, ARRAY_SIZE(next_states));
+ }
set_media:
+ spin_lock_irqsave(&de->lock, flags);
de_stop_rxtx(de);
+ spin_unlock_irqrestore(&de->lock, flags);
de_set_media(de);
de_start_rxtx(de);
@@ -1146,20 +1201,21 @@ static void de_media_interrupt (struct de_private *de, u32 status)
static int de_reset_mac (struct de_private *de)
{
- unsigned tmp;
- u32 status;
+ u32 status, tmp;
/*
* Reset MAC. Copied from de4x5.c.
*/
- dr32 (BusMode);
+ tmp = dr32 (BusMode);
+ if (tmp == 0xffffffff)
+ return -ENODEV;
mdelay (1);
- dw32 (BusMode, de_bus_mode | CmdReset);
+ dw32 (BusMode, tmp | CmdReset);
mdelay (1);
- dw32 (BusMode, de_bus_mode);
+ dw32 (BusMode, tmp);
mdelay (1);
for (tmp = 0; tmp < 5; tmp++) {
@@ -1310,12 +1366,20 @@ static void de_clean_rings (struct de_private *de)
}
for (i = 0; i < DE_TX_RING_SIZE; i++) {
- if (de->tx_skb[i].skb) {
- struct sk_buff *skb = de->tx_skb[i].skb;
- pci_unmap_single(de->pdev, de->tx_skb[i].mapping,
- skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
- de->net_stats.tx_dropped++;
+ struct sk_buff *skb = de->tx_skb[i].skb;
+ if ((skb) && (skb != DE_DUMMY_SKB)) {
+ if (skb != DE_SETUP_SKB) {
+ dev_kfree_skb(skb);
+ de->net_stats.tx_dropped++;
+ pci_unmap_single(de->pdev,
+ de->tx_skb[i].mapping,
+ skb->len, PCI_DMA_TODEVICE);
+ } else {
+ pci_unmap_single(de->pdev,
+ de->tx_skb[i].mapping,
+ sizeof(de->setup_frame),
+ PCI_DMA_TODEVICE);
+ }
}
}
@@ -1335,6 +1399,7 @@ static int de_open (struct net_device *dev)
{
struct de_private *de = dev->priv;
int rc;
+ unsigned long flags;
if (netif_msg_ifup(de))
printk(KERN_DEBUG "%s: enabling interface\n", dev->name);
@@ -1363,11 +1428,15 @@ static int de_open (struct net_device *dev)
}
netif_start_queue(dev);
+ mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
return 0;
err_out_hw:
+ spin_lock_irqsave(&de->lock, flags);
de_stop_hw(de);
+ spin_unlock_irqrestore(&de->lock, flags);
+
err_out_free:
de_free_rings(de);
return rc;
@@ -1376,15 +1445,21 @@ err_out_free:
static int de_close (struct net_device *dev)
{
struct de_private *de = dev->priv;
+ unsigned long flags;
if (netif_msg_ifdown(de))
printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
- netif_stop_queue(dev);
- netif_carrier_off(dev);
del_timer_sync(&de->media_timer);
+
+ spin_lock_irqsave(&de->lock, flags);
de_stop_hw(de);
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ spin_unlock_irqrestore(&de->lock, flags);
+
free_irq(dev->irq, dev);
+
de_free_rings(de);
de_adapter_sleep(de);
pci_disable_device(de->pdev);
@@ -1559,6 +1634,7 @@ static int de_ethtool_ioctl (struct de_private *de, void *useraddr)
strcpy (info.driver, DRV_NAME);
strcpy (info.version, DRV_VERSION);
strcpy (info.bus_info, de->pdev->slot_name);
+ info.eedump_len = DE_EEPROM_SIZE;
info.regdump_len = DE_REGS_SIZE;
if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT;
@@ -1659,6 +1735,23 @@ static int de_ethtool_ioctl (struct de_private *de, void *useraddr)
return 0;
}
+ /* get SROM dump */
+ case ETHTOOL_GEEPROM: {
+ struct ethtool_eeprom eeprom;
+
+ if (!de->ee_data)
+ break;
+ if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
+ return -EFAULT;
+ if ((eeprom.offset != 0) || (eeprom.magic != 0) ||
+ (eeprom.len != DE_EEPROM_SIZE))
+ return -EINVAL;
+
+ useraddr += offsetof(struct ethtool_regs, data);
+ if (copy_to_user(useraddr, de->ee_data, DE_EEPROM_SIZE))
+ return -EFAULT;
+ }
+
default:
break;
}
@@ -1704,7 +1797,31 @@ static void __init de21040_get_mac_address (struct de_private *de)
}
}
-/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
+static void __init de21040_get_media_info(struct de_private *de)
+{
+ unsigned int i;
+
+ de->media_type = DE_MEDIA_TP;
+ de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full |
+ SUPPORTED_10baseT_Half | SUPPORTED_AUI;
+ de->media_advertise = de->media_supported;
+
+ for (i = 0; i < DE_MAX_MEDIA; i++) {
+ switch (i) {
+ case DE_MEDIA_AUI:
+ case DE_MEDIA_TP:
+ case DE_MEDIA_TP_FD:
+ de->media[i].type = i;
+ de->media[i].csr13 = t21040_csr13[i];
+ de->media[i].csr14 = t21040_csr14[i];
+ de->media[i].csr15 = t21040_csr15[i];
+ break;
+ default:
+ de->media[i].type = DE_MEDIA_INVALID;
+ break;
+ }
+ }
+}
/* Note: this routine returns extra data bits for size detection. */
static unsigned __init tulip_read_eeprom(void *regs, int location, int addr_len)
@@ -1742,15 +1859,16 @@ static unsigned __init tulip_read_eeprom(void *regs, int location, int addr_len)
return retval;
}
-static void __init tulip_get_srom_info (struct de_private *de)
+static void __init de21041_get_srom_info (struct de_private *de)
{
unsigned i, sa_offset = 0, ofs;
- u8 ee_data[DE_EEPROM_WORDS * sizeof(u16)];
+ u8 ee_data[DE_EEPROM_SIZE + 6] = {};
unsigned ee_addr_size = tulip_read_eeprom(de->regs, 0xff, 8) & 0x40000 ? 8 : 6;
struct de_srom_info_leaf *il;
+ void *bufp;
/* download entire eeprom */
- for (i = 0; i < sizeof(ee_data)/2; i++)
+ for (i = 0; i < DE_EEPROM_WORDS; i++)
((u16 *)ee_data)[i] =
le16_to_cpu(tulip_read_eeprom(de->regs, i, ee_addr_size));
@@ -1781,13 +1899,18 @@ static void __init tulip_get_srom_info (struct de_private *de)
goto bad_srom;
/* get default media type */
- switch (il->default_media) {
+ switch (DE_UNALIGNED_16(&il->default_media)) {
case 0x0001: de->media_type = DE_MEDIA_BNC; break;
case 0x0002: de->media_type = DE_MEDIA_AUI; break;
case 0x0204: de->media_type = DE_MEDIA_TP_FD; break;
default: de->media_type = DE_MEDIA_TP_AUTO; break;
}
+ if (netif_msg_probe(de))
+ printk(KERN_INFO "de%d: SROM leaf offset %u, default media %s\n",
+ de->board_idx, ofs,
+ media_name[de->media_type]);
+
/* init SIA register values to defaults */
for (i = 0; i < DE_MAX_MEDIA; i++) {
de->media[i].type = DE_MEDIA_INVALID;
@@ -1799,8 +1922,9 @@ static void __init tulip_get_srom_info (struct de_private *de)
/* parse media blocks to see what medias are supported,
* and if any custom CSR values are provided
*/
+ bufp = ((void *)il) + sizeof(*il);
for (i = 0; i < il->n_blocks; i++) {
- struct de_srom_media_block *ib = &il[i].media[0];
+ struct de_srom_media_block *ib = bufp;
unsigned idx;
/* index based on media type in media block */
@@ -1829,16 +1953,37 @@ static void __init tulip_get_srom_info (struct de_private *de)
goto bad_srom;
}
- if (ib->opts & MediaCustomCSRs) {
- de->media[idx].csr13 = ib->csr13;
- de->media[idx].csr14 = ib->csr14;
- de->media[idx].csr15 = ib->csr15;
- }
-
de->media[idx].type = idx;
- de->media_advertise |= de->media_supported;
+
+ if (netif_msg_probe(de))
+ printk(KERN_INFO "de%d: media block #%u: %s",
+ de->board_idx, i,
+ media_name[de->media[idx].type]);
+
+ bufp += sizeof (ib->opts);
+
+ if (ib->opts & MediaCustomCSRs) {
+ de->media[idx].csr13 = DE_UNALIGNED_16(&ib->csr13);
+ de->media[idx].csr14 = DE_UNALIGNED_16(&ib->csr14);
+ de->media[idx].csr15 = DE_UNALIGNED_16(&ib->csr15);
+ bufp += sizeof(ib->csr13) + sizeof(ib->csr14) +
+ sizeof(ib->csr15);
+
+ if (netif_msg_probe(de))
+ printk(" (%x,%x,%x)\n",
+ de->media[idx].csr13,
+ de->media[idx].csr14,
+ de->media[idx].csr15);
+
+ } else if (netif_msg_probe(de))
+ printk("\n");
+
+ if (bufp > ((void *)&ee_data[DE_EEPROM_SIZE - 3]))
+ break;
}
+ de->media_advertise = de->media_supported;
+
fill_defaults:
/* fill in defaults, for cases where custom CSRs not used */
for (i = 0; i < DE_MAX_MEDIA; i++) {
@@ -1850,12 +1995,9 @@ fill_defaults:
de->media[i].csr15 = t21041_csr15[i];
}
- if (netif_msg_link(de))
- printk(KERN_INFO "de%d: SROM-listed ports: %s%s%s\n",
- de->board_idx,
- de->media_supported & SUPPORTED_TP ? "TP " : "",
- de->media_supported & SUPPORTED_BNC ? "BNC " : "",
- de->media_supported & SUPPORTED_AUI ? "AUI" : "");
+ de->ee_data = kmalloc(DE_EEPROM_SIZE, GFP_KERNEL);
+ if (de->ee_data)
+ memcpy(de->ee_data, &ee_data[0], DE_EEPROM_SIZE);
return;
@@ -1971,35 +2113,21 @@ static int __init de_init_one (struct pci_dev *pdev,
de_adapter_wake(de);
/* make sure hardware is not running */
- de_stop_hw(de);
+ rc = de_reset_mac(de);
+ if (rc) {
+ printk(KERN_ERR PFX "Cannot reset MAC, pci dev %s\n",
+ pdev->slot_name);
+ goto err_out_iomap;
+ }
- /* get MAC address, and some register values related to media types */
+ /* get MAC address, initialize default media type and
+ * get list of supported media
+ */
if (de->de21040) {
- unsigned i;
-
de21040_get_mac_address(de);
-
- de->media_type = DE_MEDIA_TP;
- de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full |
- SUPPORTED_10baseT_Half | SUPPORTED_AUI;
- de->media_advertise = de->media_supported;
- for (i = 0; i < DE_MAX_MEDIA; i++) {
- switch (i) {
- case DE_MEDIA_AUI:
- case DE_MEDIA_TP:
- case DE_MEDIA_TP_FD:
- de->media[i].type = i;
- de->media[i].csr13 = t21040_csr13[i];
- de->media[i].csr14 = t21040_csr14[i];
- de->media[i].csr15 = t21040_csr15[i];
- break;
- default:
- de->media[i].type = DE_MEDIA_INVALID;
- break;
- }
- }
+ de21040_get_media_info(de);
} else {
- tulip_get_srom_info(de);
+ de21041_get_srom_info(de);
}
/* register new network interface with kernel */
@@ -2030,6 +2158,8 @@ static int __init de_init_one (struct pci_dev *pdev,
return 0;
err_out_iomap:
+ if (de->ee_data)
+ kfree(de->ee_data);
iounmap(regs);
err_out_res:
pci_release_regions(pdev);
@@ -2048,6 +2178,8 @@ static void __exit de_remove_one (struct pci_dev *pdev)
if (!dev)
BUG();
unregister_netdev(dev);
+ if (de->ee_data)
+ kfree(de->ee_data);
iounmap(de->regs);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index d3f14dba1..63319f83c 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -502,7 +502,7 @@ static int __devinit dfx_init_one(struct pci_dev *pdev, const struct pci_device_
static int __init dfx_eisa_init(void)
{
- int rc = -NODEV;
+ int rc = -ENODEV;
int i; /* used in for loops */
u16 port; /* temporary I/O (port) address */
u32 slot_id; /* EISA hardware (slot) ID read from adapter */
diff --git a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c
index 410ca6937..c6a8663a3 100644
--- a/drivers/net/fc/iph5526.c
+++ b/drivers/net/fc/iph5526.c
@@ -4534,14 +4534,14 @@ int init_module(void)
{
int i = 0;
- driver_template.module = &__this_module;
- scsi_register_module(MODULE_SCSI_HA, &driver_template);
+ driver_template.module = THIS_MODULE;
+ scsi_register_host(&driver_template);
if (driver_template.present)
scsi_registered = TRUE;
else {
printk("iph5526: SCSI registeration failed!!!\n");
scsi_registered = FALSE;
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ scsi_unregister_host(&driver_template);
}
while(fc[i] != NULL) {
@@ -4590,7 +4590,7 @@ int i = 0;
i++;
}
if (scsi_registered == TRUE)
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ scsi_unregister_host(&driver_template);
}
#endif /* MODULE */
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 0a798790d..6c842a4d6 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -69,7 +69,6 @@
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/mm.h>
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 1a31ce27c..2fcf1ff4a 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -43,7 +43,6 @@
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <net/ax25.h>
#include "z8530.h"
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index fa32a34d3..3ff98c8ab 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -27,7 +27,6 @@
#include <linux/config.h>
#include <linux/module.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <linux/string.h>
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 60defc2ad..08e548505 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -112,9 +112,9 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self);
static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *dev);
static int irda_usb_open(struct irda_usb_cb *self);
static int irda_usb_close(struct irda_usb_cb *self);
-static void speed_bulk_callback(purb_t purb);
-static void write_bulk_callback(purb_t purb);
-static void irda_usb_receive(purb_t purb);
+static void speed_bulk_callback(struct urb *urb);
+static void write_bulk_callback(struct urb *urb);
+static void irda_usb_receive(struct urb *urb);
static int irda_usb_net_init(struct net_device *dev);
static int irda_usb_net_open(struct net_device *dev);
static int irda_usb_net_close(struct net_device *dev);
@@ -248,15 +248,15 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
{
unsigned long flags;
__u8 *frame;
- purb_t purb;
+ struct urb *urb;
int ret;
IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, xbofs=%d\n",
self->new_speed, self->new_xbofs);
/* Grab the speed URB */
- purb = &self->speed_urb;
- if (purb->status != 0) {
+ urb = &self->speed_urb;
+ if (urb->status != 0) {
WARNING(__FUNCTION__ "(), URB still in use!\n");
return;
}
@@ -270,15 +270,15 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
irda_usb_build_header(self, frame, 1);
/* Submit the 0 length IrDA frame to trigger new speed settings */
- FILL_BULK_URB(purb, self->usbdev,
+ FILL_BULK_URB(urb, self->usbdev,
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
frame, IRDA_USB_SPEED_MTU,
speed_bulk_callback, self);
- purb->transfer_buffer_length = USB_IRDA_HEADER;
- purb->transfer_flags = USB_QUEUE_BULK | USB_ASYNC_UNLINK;
- purb->timeout = MSECS_TO_JIFFIES(100);
+ urb->transfer_buffer_length = USB_IRDA_HEADER;
+ urb->transfer_flags = USB_QUEUE_BULK | USB_ASYNC_UNLINK;
+ urb->timeout = MSECS_TO_JIFFIES(100);
- if ((ret = usb_submit_urb(purb))) {
+ if ((ret = usb_submit_urb(urb))) {
WARNING(__FUNCTION__ "(), failed Speed URB\n");
}
spin_unlock_irqrestore(&self->lock, flags);
@@ -288,9 +288,9 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
/*
* Note : this function will be called with both speed_urb and empty_urb...
*/
-static void speed_bulk_callback(purb_t purb)
+static void speed_bulk_callback(struct urb *urb)
{
- struct irda_usb_cb *self = purb->context;
+ struct irda_usb_cb *self = urb->context;
IRDA_DEBUG(2, __FUNCTION__ "()\n");
@@ -301,9 +301,9 @@ static void speed_bulk_callback(purb_t purb)
}
/* Check for timeout and other USB nasties */
- if (purb->status != 0) {
+ if (urb->status != 0) {
/* I get a lot of -ECONNABORTED = -103 here - Jean II */
- IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", urb->status, urb->transfer_flags);
/* Don't do anything here, that might confuse the USB layer.
* Instead, we will wait for irda_usb_net_timeout(), the
@@ -314,10 +314,10 @@ static void speed_bulk_callback(purb_t purb)
}
/* urb is now available */
- purb->status = 0;
+ urb->status = 0;
/* If it was the speed URB, allow the stack to send more packets */
- if(purb == &self->speed_urb) {
+ if(urb == &self->speed_urb) {
netif_wake_queue(self->netdev);
}
}
@@ -329,7 +329,7 @@ static void speed_bulk_callback(purb_t purb)
static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct irda_usb_cb *self = netdev->priv;
- purb_t purb = &self->tx_urb;
+ struct urb *urb = &self->tx_urb;
unsigned long flags;
s32 speed;
s16 xbofs;
@@ -372,7 +372,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
}
}
- if (purb->status != 0) {
+ if (urb->status != 0) {
WARNING(__FUNCTION__ "(), URB still in use!\n");
dev_kfree_skb(skb);
return 0;
@@ -392,22 +392,22 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
/* FIXME: Make macro out of this one */
((struct irda_skb_cb *)skb->cb)->context = self;
- FILL_BULK_URB(purb, self->usbdev,
+ FILL_BULK_URB(urb, self->usbdev,
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
skb->data, IRDA_USB_MAX_MTU,
write_bulk_callback, skb);
- purb->transfer_buffer_length = skb->len;
+ urb->transfer_buffer_length = skb->len;
/* Note : unlink *must* be Asynchronous because of the code in
* irda_usb_net_timeout() -> call in irq - Jean II */
- purb->transfer_flags = USB_QUEUE_BULK | USB_ASYNC_UNLINK;
+ urb->transfer_flags = USB_QUEUE_BULK | USB_ASYNC_UNLINK;
/* This flag (USB_ZERO_PACKET) indicates that what we send is not
* a continuous stream of data but separate packets.
* In this case, the USB layer will insert an empty USB frame (TD)
* after each of our packets that is exact multiple of the frame size.
* This is how the dongle will detect the end of packet - Jean II */
- purb->transfer_flags |= USB_ZERO_PACKET;
+ urb->transfer_flags |= USB_ZERO_PACKET;
/* Timeout need to be shorter than NET watchdog timer */
- purb->timeout = MSECS_TO_JIFFIES(200);
+ urb->timeout = MSECS_TO_JIFFIES(200);
/* Generate min turn time. FIXME: can we do better than this? */
/* Trying to a turnaround time at this level is trying to measure
@@ -451,7 +451,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
}
/* Ask USB to send the packet */
- if ((res = usb_submit_urb(purb))) {
+ if ((res = usb_submit_urb(urb))) {
WARNING(__FUNCTION__ "(), failed Tx URB\n");
self->stats.tx_errors++;
/* Let USB recover : We will catch that in the watchdog */
@@ -472,9 +472,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
/*
* Note : this function will be called only for tx_urb...
*/
-static void write_bulk_callback(purb_t purb)
+static void write_bulk_callback(struct urb *urb)
{
- struct sk_buff *skb = purb->context;
+ struct sk_buff *skb = urb->context;
struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context;
IRDA_DEBUG(2, __FUNCTION__ "()\n");
@@ -487,12 +487,12 @@ static void write_bulk_callback(purb_t purb)
/* Free up the skb */
dev_kfree_skb_any(skb);
- purb->context = NULL;
+ urb->context = NULL;
/* Check for timeout and other USB nasties */
- if (purb->status != 0) {
+ if (urb->status != 0) {
/* I get a lot of -ECONNABORTED = -103 here - Jean II */
- IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", urb->status, urb->transfer_flags);
/* Don't do anything here, that might confuse the USB layer,
* and we could go in recursion and blow the kernel stack...
@@ -504,7 +504,7 @@ static void write_bulk_callback(purb_t purb)
}
/* urb is now available */
- purb->status = 0;
+ urb->status = 0;
/* If the network is closed, stop everything */
if ((!self->netopen) || (!self->present)) {
@@ -534,7 +534,7 @@ static void write_bulk_callback(purb_t purb)
static void irda_usb_net_timeout(struct net_device *netdev)
{
struct irda_usb_cb *self = netdev->priv;
- purb_t purb;
+ struct urb *urb;
int done = 0; /* If we have made any progress */
IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n");
@@ -546,13 +546,13 @@ static void irda_usb_net_timeout(struct net_device *netdev)
}
/* Check speed URB */
- purb = &(self->speed_urb);
- if (purb->status != 0) {
- IRDA_DEBUG(0, "%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
+ urb = &(self->speed_urb);
+ if (urb->status != 0) {
+ IRDA_DEBUG(0, "%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, urb->status, urb->transfer_flags);
- switch (purb->status) {
+ switch (urb->status) {
case -EINPROGRESS:
- usb_unlink_urb(purb);
+ usb_unlink_urb(urb);
/* Note : above will *NOT* call netif_wake_queue()
* in completion handler, we will come back here.
* Jean II */
@@ -563,7 +563,7 @@ static void irda_usb_net_timeout(struct net_device *netdev)
case -ETIMEDOUT: /* -110 */
case -ENOENT: /* -2 (urb unlinked by us) */
default: /* ??? - Play safe */
- purb->status = 0;
+ urb->status = 0;
netif_wake_queue(self->netdev);
done = 1;
break;
@@ -571,11 +571,11 @@ static void irda_usb_net_timeout(struct net_device *netdev)
}
/* Check Tx URB */
- purb = &(self->tx_urb);
- if (purb->status != 0) {
- struct sk_buff *skb = purb->context;
+ urb = &(self->tx_urb);
+ if (urb->status != 0) {
+ struct sk_buff *skb = urb->context;
- IRDA_DEBUG(0, "%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, "%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, urb->status, urb->transfer_flags);
/* Increase error count */
self->stats.tx_errors++;
@@ -589,11 +589,11 @@ static void irda_usb_net_timeout(struct net_device *netdev)
irda_usb_change_speed_xbofs(self);
#endif /* IU_BUG_KICK_TIMEOUT */
- switch (purb->status) {
+ switch (urb->status) {
case -EINPROGRESS:
- usb_unlink_urb(purb);
+ usb_unlink_urb(urb);
/* Note : above will *NOT* call netif_wake_queue()
- * in completion handler, because purb->status will
+ * in completion handler, because urb->status will
* be -ENOENT. We will fix that at the next watchdog,
* leaving more time to USB to recover...
* Also, we are in interrupt, so we need to have
@@ -608,9 +608,9 @@ static void irda_usb_net_timeout(struct net_device *netdev)
default: /* ??? - Play safe */
if(skb != NULL) {
dev_kfree_skb_any(skb);
- purb->context = NULL;
+ urb->context = NULL;
}
- purb->status = 0;
+ urb->status = 0;
netif_wake_queue(self->netdev);
done = 1;
break;
@@ -685,7 +685,7 @@ static void irda_usb_net_timeout(struct net_device *netdev)
*
* Jean II
*/
-static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, purb_t purb)
+static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struct urb *urb)
{
struct irda_skb_cb *cb;
int ret;
@@ -693,8 +693,8 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, purb_
IRDA_DEBUG(2, __FUNCTION__ "()\n");
/* Check that we have an urb */
- if (!purb) {
- WARNING(__FUNCTION__ "(), Bug : purb == NULL\n");
+ if (!urb) {
+ WARNING(__FUNCTION__ "(), Bug : urb == NULL\n");
return;
}
@@ -720,17 +720,17 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, purb_
cb->context = self;
/* Reinitialize URB */
- FILL_BULK_URB(purb, self->usbdev,
+ FILL_BULK_URB(urb, self->usbdev,
usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep),
skb->data, skb->truesize,
irda_usb_receive, skb);
- purb->transfer_flags = USB_QUEUE_BULK;
+ urb->transfer_flags = USB_QUEUE_BULK;
/* Note : unlink *must* be synchronous because of the code in
* irda_usb_net_close() -> free the skb - Jean II */
- purb->status = 0;
- purb->next = NULL; /* Don't auto resubmit URBs */
+ urb->status = 0;
+ urb->next = NULL; /* Don't auto resubmit URBs */
- ret = usb_submit_urb(purb);
+ ret = usb_submit_urb(urb);
if (ret) {
/* If this ever happen, we are in deep s***.
* Basically, the Rx path will stop... */
@@ -740,19 +740,19 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, purb_
/*------------------------------------------------------------------*/
/*
- * Function irda_usb_receive(purb)
+ * Function irda_usb_receive(urb)
*
* Called by the USB subsystem when a frame has been received
*
*/
-static void irda_usb_receive(purb_t purb)
+static void irda_usb_receive(struct urb *urb)
{
- struct sk_buff *skb = (struct sk_buff *) purb->context;
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
struct irda_usb_cb *self;
struct irda_skb_cb *cb;
struct sk_buff *new;
- IRDA_DEBUG(2, __FUNCTION__ "(), len=%d\n", purb->actual_length);
+ IRDA_DEBUG(2, __FUNCTION__ "(), len=%d\n", urb->actual_length);
/* Find ourselves */
cb = (struct irda_skb_cb *) skb->cb;
@@ -768,27 +768,27 @@ static void irda_usb_receive(purb_t purb)
}
/* Check the status */
- if (purb->status != 0) {
- switch (purb->status) {
+ if (urb->status != 0) {
+ switch (urb->status) {
case -EILSEQ:
self->stats.rx_errors++;
self->stats.rx_crc_errors++;
break;
case -ECONNRESET: /* -104 */
- IRDA_DEBUG(0, __FUNCTION__ "(), Connection Reset (-104), transfer_flags 0x%04X \n", purb->transfer_flags);
+ IRDA_DEBUG(0, __FUNCTION__ "(), Connection Reset (-104), transfer_flags 0x%04X \n", urb->transfer_flags);
/* uhci_cleanup_unlink() is going to kill the Rx
* URB just after we return. No problem, at this
* point the URB will be idle ;-) - Jean II */
break;
default:
- IRDA_DEBUG(0, __FUNCTION__ "(), RX status %d,transfer_flags 0x%04X \n", purb->status, purb->transfer_flags);
+ IRDA_DEBUG(0, __FUNCTION__ "(), RX status %d,transfer_flags 0x%04X \n", urb->status, urb->transfer_flags);
break;
}
goto done;
}
/* Check for empty frames */
- if (purb->actual_length <= USB_IRDA_HEADER) {
+ if (urb->actual_length <= USB_IRDA_HEADER) {
WARNING(__FUNCTION__ "(), empty frame!\n");
goto done;
}
@@ -801,7 +801,7 @@ static void irda_usb_receive(purb_t purb)
get_fast_time(&self->stamp);
/* Fix skb, and remove USB-IrDA header */
- skb_put(skb, purb->actual_length);
+ skb_put(skb, urb->actual_length);
skb_pull(skb, USB_IRDA_HEADER);
/* Don't waste a lot of memory on small IrDA frames */
@@ -834,7 +834,7 @@ static void irda_usb_receive(purb_t purb)
netif_rx(new);
done:
- /* Note : at this point, the URB we've just received (purb)
+ /* Note : at this point, the URB we've just received (urb)
* is still referenced by the USB layer. For example, if we
* have received a -ECONNRESET, uhci_cleanup_unlink() will
* continue to process it (in fact, cleaning it up).
@@ -848,8 +848,8 @@ done:
/* Submit the idle URB to replace the URB we've just received */
irda_usb_submit(self, skb, self->idle_rx_urb);
/* Recycle Rx URB : Now, the idle URB is the present one */
- self->idle_rx_urb = purb;
- purb->context = NULL;
+ self->idle_rx_urb = urb;
+ urb->context = NULL;
}
/*------------------------------------------------------------------*/
@@ -992,14 +992,14 @@ static int irda_usb_net_close(struct net_device *netdev)
/* Deallocate all the Rx path buffers (URBs and skb) */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
- purb_t purb = &(self->rx_urb[i]);
- struct sk_buff *skb = (struct sk_buff *) purb->context;
+ struct urb *urb = &(self->rx_urb[i]);
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
/* Cancel the receive command */
- usb_unlink_urb(purb);
+ usb_unlink_urb(urb);
/* The skb is ours, free it */
if(skb) {
dev_kfree_skb(skb);
- purb->context = NULL;
+ urb->context = NULL;
}
}
/* Cancel Tx and speed URB */
diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
index 7452310e8..cb9110e11 100644
--- a/drivers/net/irda/irtty.c
+++ b/drivers/net/irda/irtty.c
@@ -32,7 +32,6 @@
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <net/irda/irda.h>
@@ -173,7 +172,7 @@ static int irtty_open(struct tty_struct *tty)
/* Give self a name */
sprintf(name, "%s%d", tty->driver.name,
- MINOR(tty->device) - tty->driver.minor_start +
+ minor(tty->device) - tty->driver.minor_start +
tty->driver.name_base);
hashbin_insert(irtty, (irda_queue_t *) self, (int) self, NULL);
@@ -911,7 +910,7 @@ static int irtty_net_open(struct net_device *dev)
/* Give self a hardware name */
sprintf(hwname, "%s%d", tty->driver.name,
- MINOR(tty->device) - tty->driver.minor_start +
+ minor(tty->device) - tty->driver.minor_start +
tty->driver.name_base);
/*
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index 3489ffcc8..6ffb4a363 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -29,7 +29,6 @@
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/jazz.h>
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index 3cd974185..b9bce4f29 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -40,7 +40,6 @@
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/hwtest.h>
#include <asm/dma.h>
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index dc6ca00df..381693494 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -1247,3 +1247,4 @@ static void set_rx_mode(struct net_device *dev)
}
restore_flags(flags);
}
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index d634ddfec..39e7d6b6a 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -16,7 +16,6 @@
#include <linux/delay.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/page.h>
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index ebac2929f..d59f79cb8 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -739,7 +739,7 @@ sl_alloc(kdev_t line)
break;
if (slp->ctrl.leased) {
- if (slp->ctrl.line != line)
+ if (!kdev_same(slp->ctrl.line, line))
continue;
if (slp->ctrl.tty)
return NULL;
@@ -753,7 +753,7 @@ sl_alloc(kdev_t line)
continue;
if (current->pid == slp->ctrl.pid) {
- if (slp->ctrl.line == line && score < 3) {
+ if (kdev_same(slp->ctrl.line, line) && score < 3) {
sel = i;
score = 3;
continue;
@@ -764,7 +764,7 @@ sl_alloc(kdev_t line)
}
continue;
}
- if (slp->ctrl.line == line && score < 1) {
+ if (kdev_same(slp->ctrl.line, line) && score < 1) {
sel = i;
score = 1;
continue;
@@ -944,7 +944,7 @@ slip_close(struct tty_struct *tty)
tty->disc_data = 0;
sl->tty = NULL;
if (!sl->leased)
- sl->line = 0;
+ sl->line = NODEV;
/* VSV = very important to remove timers */
#ifdef CONFIG_SLIP_SMART
@@ -1394,7 +1394,7 @@ cleanup_module(void)
*/
do {
if (busy) {
- current->counter = 0;
+ current->time_slice = 0;
schedule();
}
diff --git a/drivers/net/strip.c b/drivers/net/strip.c
index 305553654..1ae2fb3fb 100644
--- a/drivers/net/strip.c
+++ b/drivers/net/strip.c
@@ -87,7 +87,6 @@ static const char StripVersion[] = "1.3-STUART.CHESHIRE";
#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
/*
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 2b1a79a91..883d064de 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -940,12 +940,12 @@ static int cosa_open(struct inode *inode, struct file *file)
unsigned long flags;
int n;
- if ((n=MINOR(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)
+ if ((n=minor(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)
>= nr_cards)
return -ENODEV;
cosa = cosa_cards+n;
- if ((n=MINOR(file->f_dentry->d_inode->i_rdev)
+ if ((n=minor(file->f_dentry->d_inode->i_rdev)
& ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)
return -ENODEV;
chan = cosa->chan + n;
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 4052912f1..0a6e81e9c 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -32,7 +32,6 @@
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/mm.h>
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 05e0ed6af..405d218ea 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -50,7 +50,6 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <asm/segment.h>
#include <linux/init.h>
#if LINUX_VERSION_CODE < 0x20155
diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c
index 1a02f6a27..3d0a02a56 100644
--- a/drivers/net/wan/lmc/lmc_media.c
+++ b/drivers/net/wan/lmc/lmc_media.c
@@ -12,7 +12,6 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <asm/segment.h>
//#include <asm/smp.h>
#if LINUX_VERSION_CODE < 0x20155
diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c
index a9d2f42f7..2bd5d9555 100644
--- a/drivers/net/wan/lmc/lmc_proto.c
+++ b/drivers/net/wan/lmc/lmc_proto.c
@@ -30,7 +30,6 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <asm/segment.h>
#include <asm/smp.h>
#include <linux/in.h>
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
index f3a574fe3..2810ab8e5 100644
--- a/drivers/net/wan/sdla_chdlc.c
+++ b/drivers/net/wan/sdla_chdlc.c
@@ -3933,7 +3933,7 @@ static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp)
if (!tty->driver_data){
int port;
- port = MINOR(tty->device) - tty->driver.minor_start;
+ port = minor(tty->device) - tty->driver.minor_start;
if ((port < 0) || (port >= NR_PORTS))
return -ENODEV;
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 2c4e856e7..5bb75f000 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -19,7 +19,6 @@
#include <linux/config.h>
#include <linux/version.h>
-#include <asm/segment.h>
#include <linux/init.h>
#include <linux/kernel.h>
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 03c48321a..d27aa6f63 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -558,7 +558,7 @@ static int unbind_request(int i, bind_info_t *bind_info)
static int ds_open(struct inode *inode, struct file *file)
{
- socket_t i = MINOR(inode->i_rdev);
+ socket_t i = minor(inode->i_rdev);
socket_info_t *s;
user_info_t *user;
@@ -590,7 +590,7 @@ static int ds_open(struct inode *inode, struct file *file)
static int ds_release(struct inode *inode, struct file *file)
{
- socket_t i = MINOR(inode->i_rdev);
+ socket_t i = minor(inode->i_rdev);
socket_info_t *s;
user_info_t *user, **link;
@@ -622,7 +622,7 @@ out:
static ssize_t ds_read(struct file *file, char *buf,
size_t count, loff_t *ppos)
{
- socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
+ socket_t i = minor(file->f_dentry->d_inode->i_rdev);
socket_info_t *s;
user_info_t *user;
@@ -651,7 +651,7 @@ static ssize_t ds_read(struct file *file, char *buf,
static ssize_t ds_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
- socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
+ socket_t i = minor(file->f_dentry->d_inode->i_rdev);
socket_info_t *s;
user_info_t *user;
@@ -684,7 +684,7 @@ static ssize_t ds_write(struct file *file, const char *buf,
/* No kernel lock - fine */
static u_int ds_poll(struct file *file, poll_table *wait)
{
- socket_t i = MINOR(file->f_dentry->d_inode->i_rdev);
+ socket_t i = minor(file->f_dentry->d_inode->i_rdev);
socket_info_t *s;
user_info_t *user;
@@ -707,7 +707,7 @@ static u_int ds_poll(struct file *file, poll_table *wait)
static int ds_ioctl(struct inode * inode, struct file * file,
u_int cmd, u_long arg)
{
- socket_t i = MINOR(inode->i_rdev);
+ socket_t i = minor(inode->i_rdev);
socket_info_t *s;
u_int size;
int ret, err;
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 912286581..884e9368d 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -49,7 +49,6 @@
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/bitops.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <pcmcia/version.h>
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 7c5aba638..b90d9fff7 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -39,7 +39,6 @@
#include <asm/io.h>
#include <asm/bitops.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/kernel.h>
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 6224a2389..f1deb2a35 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -88,7 +88,6 @@ do { \
major:D_MAJOR, \
major_name:D_NAME, \
minor_shift:D_PARTN_BITS, \
- max_p:1 << D_PARTN_BITS, \
max_nr:D_PER_MAJOR, \
nr_real:D_PER_MAJOR,
static inline struct request *
@@ -111,7 +110,6 @@ do { \
major:D_MAJOR, \
major_name:D_NAME, \
minor_shift:D_PARTN_BITS, \
- max_p:1 << D_PARTN_BITS, \
nr_real:D_PER_MAJOR, \
fops:&dasd_device_operations,
static inline struct request *
diff --git a/drivers/s390/char/tuball.c b/drivers/s390/char/tuball.c
index 04de5c4a9..92ca8049a 100644
--- a/drivers/s390/char/tuball.c
+++ b/drivers/s390/char/tuball.c
@@ -84,7 +84,6 @@ static struct console tub3270_con = {
tub3270_con_write, /* write */
NULL, /* read */
tub3270_con_device, /* device */
- NULL, /* wait_key */
tub3270_con_unblank, /* unblank */
NULL, /* setup */
CON_PRINTBUFFER, /* flags */
diff --git a/drivers/s390/s390io.c b/drivers/s390/s390io.c
index f06ffdfd2..c22080d11 100644
--- a/drivers/s390/s390io.c
+++ b/drivers/s390/s390io.c
@@ -6,6 +6,7 @@
* Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
+ * Cornelia Huck (cohuck@de.ibm.com)
* ChangeLog: 01/07/2001 Blacklist cleanup (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
* 01/04/2001 Holger Smolinski (smolinsk@de.ibm.com)
* Fixed lost interrupts and do_adapter_IO
@@ -108,7 +109,9 @@ static void init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs);
static void s390_process_subchannels( void);
static void s390_device_recognition_all( void);
static void s390_device_recognition_irq( int irq);
+#ifdef CONFIG_PROC_FS
static void s390_redo_validation(void);
+#endif
static int s390_validate_subchannel( int irq, int enable);
static int s390_SenseID( int irq, senseid_t *sid, __u8 lpm);
static int s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid);
@@ -117,7 +120,9 @@ static int s390_process_IRQ( unsigned int irq );
static int enable_subchannel( unsigned int irq);
static int disable_subchannel( unsigned int irq);
+#ifdef CONFIG_PROC_FS
static int chan_proc_init( void );
+#endif
static inline void do_adapter_IO( __u32 intparm );
@@ -666,6 +671,7 @@ static int __init cio_notoper_setup(char *parm)
__setup("cio_notoper_msg=", cio_notoper_setup);
+#ifdef CONFIG_PROC_FS
static int __init cio_proc_devinfo_setup(char *parm)
{
if (!strcmp(parm, "yes")) {
@@ -673,13 +679,14 @@ static int __init cio_proc_devinfo_setup(char *parm)
} else if (!strcmp(parm, "no")) {
cio_proc_devinfo = 0;
} else {
- printk("cio_proc_devinfo_setup: invalid parameter '%s'\n",parm);
+ printk( KERN_ERR "cio_proc_devinfo_setup: invalid parameter '%s'\n",parm);
}
return 1;
}
__setup("cio_proc_devinfo=", cio_proc_devinfo_setup);
+#endif
/*
* register for adapter interrupts
@@ -4779,10 +4786,12 @@ void s390_redo_validation(void)
}
}
+#ifdef CONFIG_PROC_FS
if (cio_proc_devinfo)
if (irq < MAX_CIO_PROCFS_ENTRIES) {
cio_procfs_device_create(ioinfo[irq]->devno);
}
+#endif
}
}
irq++;
@@ -6523,10 +6532,11 @@ void s390_do_crw_pending( crwe_t *pcrwe )
if ( ioinfo[irq]->ui.flags.oper == 0 )
{
not_oper_handler_func_t nopfunc=ioinfo[irq]->nopfunc;
-
+#ifdef CONFIG_PROC_FS
/* remove procfs entry */
if (cio_proc_devinfo)
cio_procfs_device_remove(dev_no);
+#endif
/*
* If the device has gone
* call not oper handler
@@ -6573,12 +6583,13 @@ void s390_do_crw_pending( crwe_t *pcrwe )
pdevreg->oper_func( irq, pdevreg );
} /* endif */
-
+#ifdef CONFIG_PROC_FS
/* add new procfs entry */
if (cio_proc_devinfo)
if (highest_subchannel < MAX_CIO_PROCFS_ENTRIES) {
cio_procfs_device_create(ioinfo[irq]->devno);
}
+#endif
}
/*
* ... it is and was operational, but
@@ -6586,23 +6597,26 @@ void s390_do_crw_pending( crwe_t *pcrwe )
*/
else if ((ioinfo[irq]->devno != dev_no) && ( ioinfo[irq]->nopfunc != NULL ))
{
+#ifdef CONFIG_PROC_FS
int devno_old = ioinfo[irq]->devno;
+#endif
ioinfo[irq]->nopfunc( irq,
DEVSTAT_REVALIDATE );
-
+#ifdef CONFIG_PROC_FS
/* remove old entry, add new */
if (cio_proc_devinfo) {
cio_procfs_device_remove(devno_old);
cio_procfs_device_create(ioinfo[irq]->devno);
}
+#endif
} /* endif */
} /* endif */
-
+#ifdef CONFIG_PROC_FS
/* get rid of dead procfs entries */
if (cio_proc_devinfo)
cio_procfs_device_purge();
-
+#endif
} /* endif */
break;
@@ -6756,6 +6770,7 @@ int cio_debug_init( void )
__initcall(cio_debug_init);
+#ifdef CONFIG_PROC_FS
/*
* Display info on subchannels in /proc/subchannels.
* Adapted from procfs stuff in dasd.c by Cornelia Huck, 02/28/01.
@@ -7163,19 +7178,19 @@ int cio_procfs_device_create(int devno)
entry->cio_chpid_entry = create_proc_entry( "chpids", S_IFREG|S_IRUGO, entry->cio_device_entry);
entry->cio_chpid_entry->proc_fops = &cio_chpid_entry_file_ops;
} else {
- printk("Error, could not allocate procfs structure!\n");
+ printk( KERN_WARNING "Error, could not allocate procfs structure!\n");
remove_proc_entry(buf, cio_procfs_deviceinfo_root);
kfree(entry);
rc = -ENOMEM;
}
} else {
- printk("Error, could not allocate procfs structure!\n");
+ printk( KERN_WARNING "Error, could not allocate procfs structure!\n");
kfree(entry);
rc = -ENOMEM;
}
} else {
- printk("Error, could not allocate procfs structure!\n");
+ printk( KERN_WARNING "Error, could not allocate procfs structure!\n");
rc = -ENOMEM;
}
return rc;
@@ -7370,7 +7385,7 @@ static ssize_t cio_ignore_proc_write (struct file *file, const char *user_buf,
}
buffer[user_len]='\0';
#ifdef CIO_DEBUG_IO
- printk ("/proc/cio_ignore: '%s'\n", buffer);
+ printk ( KERN_DEBUG "/proc/cio_ignore: '%s'\n", buffer);
#endif /* CIO_DEBUG_IO */
if (cio_debug_initialized)
debug_sprintf_event(cio_debug_msg_id, 2, "/proc/cio_ignore: '%s'\n",buffer);
@@ -7491,6 +7506,7 @@ static int cio_irq_proc_init(void)
__initcall(cio_irq_proc_init);
/* end of procfs stuff */
+#endif
schib_t *s390_get_schib( int irq )
{
diff --git a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c
index 378de27cd..c1d07aa02 100644
--- a/drivers/sbus/audio/audio.c
+++ b/drivers/sbus/audio/audio.c
@@ -1,4 +1,4 @@
-/* $Id: audio.c,v 1.62 2001-10-08 22:19:50 davem Exp $
+/* $Id: audio.c,v 1.63 2002-01-08 16:00:21 davem Exp $
* drivers/sbus/audio/audio.c
*
* Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
@@ -202,7 +202,7 @@ static unsigned int sparcaudio_poll(struct file *file, poll_table * wait)
{
unsigned int mask = 0;
struct inode *inode = file->f_dentry->d_inode;
- struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+ struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >>
SPARCAUDIO_DEVICE_SHIFT)];
poll_wait(file, &drv->input_read_wait, wait);
@@ -221,7 +221,7 @@ static ssize_t sparcaudio_read(struct file * file, char *buf,
size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+ struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >>
SPARCAUDIO_DEVICE_SHIFT)];
int bytes_to_copy, bytes_read = 0, err;
@@ -296,7 +296,7 @@ static ssize_t sparcaudio_write(struct file * file, const char *buf,
size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+ struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >>
SPARCAUDIO_DEVICE_SHIFT)];
int bytes_written = 0, bytes_to_copy, err;
@@ -396,7 +396,7 @@ static ssize_t sparcaudio_write(struct file * file, const char *buf,
static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned int *arg)
{
- struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+ struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >>
SPARCAUDIO_DEVICE_SHIFT)];
unsigned long i = 0, j = 0, l = 0, m = 0;
unsigned int k = 0;
@@ -647,7 +647,7 @@ static int sparcaudio_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
int retval = 0, i, j, k;
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct audio_info ainfo;
audio_buf_info binfo;
count_info cinfo;
@@ -1701,7 +1701,7 @@ static struct file_operations sparcaudioctl_fops = {
static int sparcaudio_open(struct inode * inode, struct file * file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct sparcaudio_driver *drv =
drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)];
int err;
@@ -1835,7 +1835,7 @@ static int sparcaudio_open(struct inode * inode, struct file * file)
static int sparcaudio_release(struct inode * inode, struct file * file)
{
- struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+ struct sparcaudio_driver *drv = drivers[(minor(inode->i_rdev) >>
SPARCAUDIO_DEVICE_SHIFT)];
lock_kernel();
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index 22a825264..af0e608c0 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -1,4 +1,4 @@
-/* $Id: aurora.c,v 1.18 2001-10-26 17:59:31 davem Exp $
+/* $Id: aurora.c,v 1.19 2002-01-08 16:00:16 davem Exp $
* linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
*
* Copyright (c) 1999 by Oliver Aldulea (oli at bv dot ro)
@@ -66,7 +66,6 @@
#include <asm/irq.h>
#include <asm/oplib.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/kdebug.h>
#include <asm/sbus.h>
@@ -1428,7 +1427,7 @@ static int aurora_open(struct tty_struct * tty, struct file * filp)
printk("aurora_open: start\n");
#endif
- board = AURORA_BOARD(MINOR(tty->device));
+ board = AURORA_BOARD(minor(tty->device));
if (board > AURORA_NBOARD ||
!(aurora_board[board].flags & AURORA_BOARD_PRESENT)) {
#ifdef AURORA_DEBUG
@@ -1439,7 +1438,7 @@ static int aurora_open(struct tty_struct * tty, struct file * filp)
}
bp = &aurora_board[board];
- port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(MINOR(tty->device));
+ port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(minor(tty->device));
if (aurora_paranoia_check(port, tty->device, "aurora_open")) {
#ifdef AURORA_DEBUG
printk("aurora_open: error paranoia check\n");
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index 2be051503..5ed0a0c90 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -28,7 +28,6 @@
#if defined(__i386__)
# include <asm/system.h>
-# include <asm/segment.h>
#endif
#if defined(__sparc__)
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index f5ed491fb..fdc993631 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -297,7 +297,7 @@ static inline int wd_opt_timeout(void)
static int wd_open(struct inode *inode, struct file *f)
{
- switch(MINOR(inode->i_rdev))
+ switch(minor(inode->i_rdev))
{
case WD0_MINOR:
f->private_data = &wd_dev.watchdog[WD0_ID];
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 977e2df3c..fa6ad1776 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -1,4 +1,4 @@
-/* $Id: display7seg.c,v 1.5 2001-10-08 22:19:51 davem Exp $
+/* $Id: display7seg.c,v 1.6 2002-01-08 16:00:16 davem Exp $
*
* display7seg - Driver implementation for the 7-segment display
* present on Sun Microsystems CP1400 and CP1500
@@ -89,7 +89,7 @@ static inline int d7s_obpflipped(void)
static int d7s_open(struct inode *inode, struct file *f)
{
- if (D7S_MINOR != MINOR(inode->i_rdev))
+ if (D7S_MINOR != minor(inode->i_rdev))
return -ENODEV;
MOD_INC_USE_COUNT;
@@ -98,7 +98,7 @@ static int d7s_open(struct inode *inode, struct file *f)
static int d7s_release(struct inode *inode, struct file *f)
{
- if (D7S_MINOR != MINOR(inode->i_rdev))
+ if (D7S_MINOR != minor(inode->i_rdev))
return -ENODEV;
MOD_DEC_USE_COUNT;
@@ -125,7 +125,7 @@ static int d7s_ioctl(struct inode *inode, struct file *f,
__u8 regs = readb(d7s_regs);
__u8 ireg = 0;
- if (D7S_MINOR != MINOR(inode->i_rdev))
+ if (D7S_MINOR != minor(inode->i_rdev))
return -ENODEV;
switch (cmd) {
diff --git a/drivers/sbus/char/sab82532.c b/drivers/sbus/char/sab82532.c
index 192224c60..09c0fd09a 100644
--- a/drivers/sbus/char/sab82532.c
+++ b/drivers/sbus/char/sab82532.c
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.65 2001-10-13 08:27:50 davem Exp $
+/* $Id: sab82532.c,v 1.66 2002-01-08 16:00:16 davem Exp $
* sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -361,10 +361,6 @@ static void receive_chars(struct sab82532 *info,
writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr);
}
-#ifdef CONFIG_SERIAL_CONSOLE
- if (info->is_console)
- wake_up(&keypress_wait);
-#endif
if (!tty)
return;
@@ -1917,7 +1913,7 @@ static int sab82532_open(struct tty_struct *tty, struct file * filp)
printk("sab82532_open: count = %d\n", info->count);
#endif
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS))
return -ENODEV;
@@ -2204,7 +2200,7 @@ static void __init sab82532_kgdb_hook(int line)
static inline void __init show_serial_version(void)
{
- char *revision = "$Revision: 1.65 $";
+ char *revision = "$Revision: 1.66 $";
char *version, *p;
version = strchr(revision, ' ');
@@ -2541,17 +2537,10 @@ sab82532_console_write(struct console *con, const char *s, unsigned n)
sab82532_tec_wait(info);
}
-static int
-sab82532_console_wait_key(struct console *con)
-{
- sleep_on(&keypress_wait);
- return 0;
-}
-
static kdev_t
sab82532_console_device(struct console *con)
{
- return MKDEV(TTY_MAJOR, 64 + con->index);
+ return mk_kdev(TTY_MAJOR, 64 + con->index);
}
static int
@@ -2622,7 +2611,6 @@ static struct console sab82532_console = {
name: "ttyS",
write: sab82532_console_write,
device: sab82532_console_device,
- wait_key: sab82532_console_wait_key,
setup: sab82532_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/sbus/char/su.c b/drivers/sbus/char/su.c
index 936c79181..f432973a9 100644
--- a/drivers/sbus/char/su.c
+++ b/drivers/sbus/char/su.c
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.54 2001-11-07 14:52:30 davem Exp $
+/* $Id: su.c,v 1.55 2002-01-08 16:00:16 davem Exp $
* su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -2061,7 +2061,7 @@ su_open(struct tty_struct *tty, struct file * filp)
int retval, line;
unsigned long page;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS))
return -ENODEV;
info = su_table + line;
@@ -2252,7 +2252,7 @@ done:
*/
static __inline__ void __init show_su_version(void)
{
- char *revision = "$Revision: 1.54 $";
+ char *revision = "$Revision: 1.55 $";
char *version, *p;
version = strchr(revision, ' ');
@@ -2854,44 +2854,10 @@ serial_console_write(struct console *co, const char *s,
su_outb(info, UART_IER, ier);
}
-/*
- * Receive character from the serial port
- */
-static int
-serial_console_wait_key(struct console *co)
-{
- struct su_struct *info;
- int ier;
- int lsr;
- int c;
-
- info = su_table + co->index;
-
- /*
- * First save the IER then disable the interrupts so
- * that the real driver for the port does not get the
- * character.
- */
- ier = su_inb(info, UART_IER);
- su_outb(info, UART_IER, 0x00);
-
- do {
- lsr = su_inb(info, UART_LSR);
- } while (!(lsr & UART_LSR_DR));
- c = su_inb(info, UART_RX);
-
- /*
- * Restore the interrupts
- */
- su_outb(info, UART_IER, ier);
-
- return c;
-}
-
static kdev_t
serial_console_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, 64 + c->index);
+ return mk_kdev(TTY_MAJOR, 64 + c->index);
}
/*
@@ -3013,7 +2979,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c
index 3a3bb4b1f..82ed6335b 100644
--- a/drivers/sbus/char/sunkbd.c
+++ b/drivers/sbus/char/sunkbd.c
@@ -82,16 +82,6 @@ extern void scrollfront(int);
struct l1a_kbd_state l1a_state;
-#ifndef CONFIG_PCI
-DECLARE_WAIT_QUEUE_HEAD(keypress_wait);
-#endif
-
-int keyboard_wait_for_keypress(struct console *co)
-{
- sleep_on(&keypress_wait);
- return 0;
-}
-
static spinlock_t sunkbd_lock = SPIN_LOCK_UNLOCKED;
/*
@@ -629,7 +619,6 @@ void sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
static void put_queue(int ch)
{
- wake_up(&keypress_wait);
if (tty) {
tty_insert_flip_char(tty, ch, 0);
con_schedule_flip(tty);
@@ -638,7 +627,6 @@ static void put_queue(int ch)
static void puts_queue(char *cp)
{
- wake_up(&keypress_wait);
if (!tty)
return;
diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c
index 8d714e1a6..aceb9c9ee 100644
--- a/drivers/sbus/char/zs.c
+++ b/drivers/sbus/char/zs.c
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.69 2002-01-04 21:12:44 davem Exp $
+/* $Id: zs.c,v 1.70 2002-01-08 16:00:16 davem Exp $
* zs.c: Zilog serial port driver for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -224,7 +224,7 @@ static unsigned char *tmp_buf = 0;
static DECLARE_MUTEX(tmp_buf_sem);
static inline int serial_paranoia_check(struct sun_serial *info,
- dev_t device, const char *routine)
+ kdev_t device, const char *routine)
{
#ifdef SERIAL_PARANOIA_CHECK
static const char *badmagic =
@@ -233,11 +233,11 @@ static inline int serial_paranoia_check(struct sun_serial *info,
"Warning: null sun_serial for (%d, %d) in %s\n";
if (!info) {
- printk(badinfo, MAJOR(device), MINOR(device), routine);
+ printk(badinfo, major(device), minor(device), routine);
return 1;
}
if (info->magic != SERIAL_MAGIC) {
- printk(badmagic, MAJOR(device), MINOR(device), routine);
+ printk(badmagic, major(device), minor(device), routine);
return 1;
}
#endif
@@ -539,8 +539,6 @@ static void receive_chars(struct sun_serial *info, struct pt_regs *regs)
/* Continue execution... */
return;
}
- /* It is a 'keyboard interrupt' ;-) */
- wake_up(&keypress_wait);
}
#ifndef __sparc_v9__
/* Look for kgdb 'stop' character, consult the gdb
@@ -1805,7 +1803,7 @@ int zs_open(struct tty_struct *tty, struct file * filp)
struct sun_serial *info;
int retval, line;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
/* The zilog lines for the mouse/keyboard must be
* opened using their respective drivers.
@@ -1889,7 +1887,7 @@ int zs_open(struct tty_struct *tty, struct file * filp)
static void show_serial_version(void)
{
- char *revision = "$Revision: 1.69 $";
+ char *revision = "$Revision: 1.70 $";
char *version, *p;
version = strchr(revision, ' ');
@@ -2716,16 +2714,9 @@ zs_console_write(struct console *con, const char *s, unsigned count)
#endif
}
-static int
-zs_console_wait_key(struct console *con)
-{
- sleep_on(&keypress_wait);
- return 0;
-}
-
static kdev_t zs_console_device(struct console *con)
{
- return MKDEV(TTY_MAJOR, 64 + con->index);
+ return mk_kdev(TTY_MAJOR, 64 + con->index);
}
static int __init zs_console_setup(struct console *con, char *options)
@@ -2800,7 +2791,6 @@ static struct console zs_console = {
name: "ttyS",
write: zs_console_write,
device: zs_console_device,
- wait_key: zs_console_wait_key,
setup: zs_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 6f5032c5f..1069f6a69 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -4108,7 +4108,7 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
BusLogic_HostAdapter_T *HostAdapter =
(BusLogic_HostAdapter_T *) Disk->device->host->hostdata;
BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters;
- struct buffer_head *BufferHead;
+ unsigned char *buf;
if (HostAdapter->ExtendedTranslationEnabled &&
Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */)
{
@@ -4130,20 +4130,16 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
}
DiskParameters->Cylinders =
Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
- /*
- Attempt to read the first 1024 bytes from the disk device.
- */
- BufferHead = bread(MKDEV(MAJOR(Device), MINOR(Device) & ~0x0F), 0, block_size(Device));
- if (BufferHead == NULL) return 0;
+ buf = scsi_bios_ptable(Device);
+ if (buf == NULL) return 0;
/*
If the boot sector partition table flag is valid, search for a partition
table entry whose end_head matches one of the standard BusLogic geometry
translations (64/32, 128/32, or 255/63).
*/
- if (*(unsigned short *) (BufferHead->b_data + 0x1FE) == 0xAA55)
+ if (*(unsigned short *) (buf+64) == 0xAA55)
{
- PartitionTable_T *FirstPartitionEntry =
- (PartitionTable_T *) (BufferHead->b_data + 0x1BE);
+ PartitionTable_T *FirstPartitionEntry = (PartitionTable_T *) buf;
PartitionTable_T *PartitionEntry = FirstPartitionEntry;
int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
unsigned char PartitionEntryEndHead, PartitionEntryEndSector;
@@ -4197,7 +4193,7 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
DiskParameters->Heads, DiskParameters->Sectors);
}
}
- brelse(BufferHead);
+ kfree(buf);
return 0;
}
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index 8ec1d1391..b0c7bd184 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -1531,7 +1531,7 @@ static inline
void BusLogic_AcquireHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter,
ProcessorFlags_T *ProcessorFlags)
{
- spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+ spin_lock_irqsave(&HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
}
@@ -1544,7 +1544,7 @@ static inline
void BusLogic_ReleaseHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter,
ProcessorFlags_T *ProcessorFlags)
{
- spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+ spin_unlock_irqrestore(&HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
}
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 12b800af7..b5882e5ba 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -3611,36 +3611,6 @@ typedef struct {
#define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif /* CONFIG_PROC_FS */
-/*
- * XXX - Release and acquire the io_request_lock. These macros are needed
- * because the 2.4 kernel SCSI mid-level driver holds the 'io_request_lock'
- * on entry to SCSI low-level drivers.
- *
- * These definitions and all code that uses code should be removed when the
- * SCSI mid-level driver no longer holds the 'io_request_lock' on entry to
- * SCSI low-level driver detect, queuecommand, and reset entrypoints.
- *
- * The interrupt flags values doesn't matter in the macros because the
- * SCSI mid-level will save and restore the flags values before and after
- * calling advansys_detect, advansys_queuecommand, and advansys_reset where
- * these macros are used. We do want interrupts enabled after the lock is
- * released so an explicit sti() is done. The driver only needs interrupts
- * disabled when it acquires the per board lock.
- */
-#define ASC_UNLOCK_IO_REQUEST_LOCK \
- { \
- ulong flags; /* flags value not needed, cf. comment above. */ \
- save_flags(flags); \
- spin_unlock_irqrestore(&io_request_lock, flags); \
- sti(); /* enable interrupts */ \
- }
-
-#define ASC_LOCK_IO_REQUEST_LOCK \
- { \
- ulong flags; /* flags value not needed, cf. comment above. */ \
- spin_lock_irqsave(&io_request_lock, flags); \
- }
-
/* Asc Library return codes */
#define ASC_TRUE 1
#define ASC_FALSE 0
@@ -4085,7 +4055,6 @@ typedef struct asc_board {
ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
} eep_config;
ulong last_reset; /* Saved last reset time */
- spinlock_t lock; /* Board spinlock */
#ifdef CONFIG_PROC_FS
/* /proc/scsi/advansys/[0...] */
char *prtbuf; /* /proc print buffer */
@@ -4605,13 +4574,6 @@ advansys_detect(Scsi_Host_Template *tpnt)
ASC_DBG(1, "advansys_detect: begin\n");
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level detect entrypoint.
- */
- ASC_UNLOCK_IO_REQUEST_LOCK
-
#if ASC_LINUX_KERNEL24
tpnt->proc_name = "advansys";
#elif ASC_LINUX_KERNEL22
@@ -4838,9 +4800,6 @@ advansys_detect(Scsi_Host_Template *tpnt)
memset(boardp, 0, sizeof(asc_board_t));
boardp->id = asc_board_count - 1;
- /* Initialize spinlock. */
- boardp->lock = SPIN_LOCK_UNLOCKED;
-
/*
* Handle both narrow and wide boards.
*
@@ -5724,13 +5683,6 @@ advansys_detect(Scsi_Host_Template *tpnt)
}
}
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level detect entrypoint.
- */
- ASC_LOCK_IO_REQUEST_LOCK
-
ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
return asc_board_count;
}
@@ -5894,14 +5846,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
boardp = ASC_BOARDP(shp);
ASC_STATS(shp, queuecommand);
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level queuecommand entrypoint.
- */
- ASC_UNLOCK_IO_REQUEST_LOCK
-
- spin_lock_irqsave(&boardp->lock, flags);
+ spin_lock_irqsave(&shp->host_lock, flags);
/*
* Block new commands while handling a reset or abort request.
@@ -5918,7 +5863,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
* handling.
*/
asc_enqueue(&boardp->done, scp, ASC_BACK);
- spin_unlock_irqrestore(&boardp->lock, flags);
+ spin_unlock_irqrestore(&shp->host_lock, flags);
return 0;
}
@@ -5962,15 +5907,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
break;
}
- spin_unlock_irqrestore(&boardp->lock, flags);
-
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level queuecommand entrypoint.
- */
- ASC_LOCK_IO_REQUEST_LOCK
-
+ spin_unlock_irqrestore(&shp->host_lock, flags);
return 0;
}
@@ -6016,20 +5953,13 @@ advansys_reset(Scsi_Cmnd *scp)
/*
* Check for re-entrancy.
*/
- spin_lock_irqsave(&boardp->lock, flags);
+ spin_lock_irqsave(&shp->host_lock, flags);
if (boardp->flags & ASC_HOST_IN_RESET) {
- spin_unlock_irqrestore(&boardp->lock, flags);
+ spin_unlock_irqrestore(&shp->host_lock, flags);
return FAILED;
}
boardp->flags |= ASC_HOST_IN_RESET;
- spin_unlock_irqrestore(&boardp->lock, flags);
-
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level reset entrypoint.
- */
- ASC_UNLOCK_IO_REQUEST_LOCK
+ spin_unlock_irqrestore(&shp->host_lock, flags);
if (ASC_NARROW_BOARD(boardp)) {
/*
@@ -6064,7 +5994,7 @@ advansys_reset(Scsi_Cmnd *scp)
/*
* Acquire the board lock.
*/
- spin_lock_irqsave(&boardp->lock, flags);
+ spin_lock_irqsave(&shp->host_lock, flags);
} else {
/*
@@ -6095,7 +6025,7 @@ advansys_reset(Scsi_Cmnd *scp)
* Acquire the board lock and ensure all requests completed by the
* microcode have been processed by calling AdvISR().
*/
- spin_lock_irqsave(&boardp->lock, flags);
+ spin_lock_irqsave(&shp->host_lock, flags);
(void) AdvISR(adv_dvc_varp);
}
@@ -6161,7 +6091,7 @@ advansys_reset(Scsi_Cmnd *scp)
boardp->flags &= ~ASC_HOST_IN_RESET;
/* Release the board. */
- spin_unlock_irqrestore(&boardp->lock, flags);
+ spin_unlock_irqrestore(&shp->host_lock, flags);
/*
* Complete all the 'done_scp' requests.
@@ -6170,13 +6100,6 @@ advansys_reset(Scsi_Cmnd *scp)
asc_scsi_done_list(done_scp);
}
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level reset entrypoint.
- */
- ASC_LOCK_IO_REQUEST_LOCK
-
ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
return ret;
@@ -6345,10 +6268,11 @@ advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* AscISR() will call asc_isr_callback().
*/
for (i = 0; i < asc_board_count; i++) {
- boardp = ASC_BOARDP(asc_host[i]);
+ struct Scsi_Host *shp = asc_host[i];
+ boardp = ASC_BOARDP(shp);
ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n",
i, (ulong) boardp);
- spin_lock_irqsave(&boardp->lock, flags);
+ spin_lock_irqsave(&shp->host_lock, flags);
if (ASC_NARROW_BOARD(boardp)) {
/*
* Narrow Board
@@ -6404,7 +6328,7 @@ advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
}
}
- spin_unlock_irqrestore(&boardp->lock, flags);
+ spin_unlock_irqrestore(&shp->host_lock, flags);
}
/*
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 36f38350f..938019b66 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1349,9 +1349,9 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
printk(KERN_INFO "aha152x%d: trying software interrupt, ", HOSTNO);
SETPORT(DMACNTRL0, SWINT|INTEN);
- spin_unlock_irq(&io_request_lock);
+ spin_unlock_irq(&shpnt->host_lock);
mdelay(1000);
- spin_lock_irq(&io_request_lock);
+ spin_lock_irq(&shpnt->host_lock);
free_irq(shpnt->irq, shpnt);
if (!HOSTDATA(shpnt)->swint) {
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 154777d99..d7f76a712 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -68,7 +68,7 @@ static void BAD_SG_DMA(Scsi_Cmnd * SCpnt,
int nseg,
int badseg)
{
- printk(KERN_CRIT "sgpnt[%d:%d] addr %p/0x%lx length %d\n",
+ printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%lx length %d\n",
badseg, nseg,
page_address(sgpnt[badseg].page) + sgpnt[badseg].offset,
SCSI_SG_PA(&sgpnt[badseg]),
@@ -177,7 +177,7 @@ static struct Scsi_Host *aha_host[7]; /* One for each IRQ level (9-15) */
static void setup_mailboxes(int base_io, struct Scsi_Host *shpnt);
static int aha1542_restart(struct Scsi_Host *shost);
-static void aha1542_intr_handle(int irq, void *dev_id, struct pt_regs *regs);
+static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id, struct pt_regs *regs);
static void do_aha1542_intr_handle(int irq, void *dev_id, struct pt_regs *regs);
#define aha1542_intr_reset(base) outb(IRST, CONTROL(base))
@@ -420,30 +420,30 @@ fail:
static void do_aha1542_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
+ struct Scsi_Host *shost;
+
+ shost = aha_host[irq - 9];
+ if (!shost)
+ panic("Splunge!");
- spin_lock_irqsave(&io_request_lock, flags);
- aha1542_intr_handle(irq, dev_id, regs);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_lock_irqsave(&shost->host_lock, flags);
+ aha1542_intr_handle(shost, dev_id, regs);
+ spin_unlock_irqrestore(&shost->host_lock, flags);
}
/* A "high" level interrupt handler */
-static void aha1542_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id, struct pt_regs *regs)
{
void (*my_done) (Scsi_Cmnd *) = NULL;
int errstatus, mbi, mbo, mbistatus;
int number_serviced;
unsigned long flags;
- struct Scsi_Host *shost;
Scsi_Cmnd *SCtmp;
int flag;
int needs_restart;
struct mailbox *mb;
struct ccb *ccb;
- shost = aha_host[irq - 9];
- if (!shost)
- panic("Splunge!");
-
mb = HOSTDATA(shost)->mb;
ccb = HOSTDATA(shost)->ccb;
@@ -543,7 +543,7 @@ static void aha1542_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
}
my_done = SCtmp->scsi_done;
if (SCtmp->host_scribble) {
- scsi_free(SCtmp->host_scribble, 512);
+ kfree(SCtmp->host_scribble);
SCtmp->host_scribble = 0;
}
/* Fetch the sense data, and tuck it away, in the required slot. The
@@ -704,7 +704,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
#endif
int i;
ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
- SCpnt->host_scribble = (unsigned char *) scsi_malloc(512);
+ SCpnt->host_scribble = (unsigned char *) kmalloc(512, GFP_DMA);
sgpnt = (struct scatterlist *) SCpnt->request_buffer;
cptr = (struct chain *) SCpnt->host_scribble;
if (cptr == NULL)
@@ -1445,7 +1445,7 @@ static int aha1542_dev_reset(Scsi_Cmnd * SCpnt)
Scsi_Cmnd *SCtmp;
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
if (SCtmp->host_scribble) {
- scsi_free(SCtmp->host_scribble, 512);
+ kfree(SCtmp->host_scribble);
SCtmp->host_scribble = NULL;
}
HOSTDATA(SCpnt->host)->SCint[i] = NULL;
@@ -1477,9 +1477,9 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
* check for timeout, and if we are doing something like this
* we are pretty desperate anyways.
*/
- spin_unlock_irq(&io_request_lock);
+ spin_unlock_irq(&SCpnt->host->host_lock);
scsi_sleep(4 * HZ);
- spin_lock_irq(&io_request_lock);
+ spin_lock_irq(&SCpnt->host->host_lock);
WAIT(STATUS(SCpnt->host->io_port),
STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
@@ -1508,7 +1508,7 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
continue;
}
if (SCtmp->host_scribble) {
- scsi_free(SCtmp->host_scribble, 512);
+ kfree(SCtmp->host_scribble);
SCtmp->host_scribble = NULL;
}
HOSTDATA(SCpnt->host)->SCint[i] = NULL;
@@ -1541,9 +1541,9 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt)
* check for timeout, and if we are doing something like this
* we are pretty desperate anyways.
*/
- spin_unlock_irq(&io_request_lock);
+ spin_unlock_irq(&SCpnt->host->host_lock);
scsi_sleep(4 * HZ);
- spin_lock_irq(&io_request_lock);
+ spin_lock_irq(&SCpnt->host->host_lock);
WAIT(STATUS(SCpnt->host->io_port),
STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
@@ -1577,7 +1577,7 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt)
continue;
}
if (SCtmp->host_scribble) {
- scsi_free(SCtmp->host_scribble, 512);
+ kfree(SCtmp->host_scribble);
SCtmp->host_scribble = NULL;
}
HOSTDATA(SCpnt->host)->SCint[i] = NULL;
@@ -1626,7 +1626,7 @@ static int aha1542_old_abort(Scsi_Cmnd * SCpnt)
if (mb[mbi].status) {
printk(KERN_ERR "Lost interrupt discovered on irq %d - attempting to recover\n",
SCpnt->host->irq);
- aha1542_intr_handle(SCpnt->host->irq, NULL);
+ aha1542_intr_handle(SCpnt->host, NULL);
return 0;
}
/* OK, no lost interrupt. Try looking to see how many pending commands
@@ -1715,7 +1715,7 @@ static int aha1542_old_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
SCtmp->result = DID_RESET << 16;
if (SCtmp->host_scribble) {
- scsi_free(SCtmp->host_scribble, 512);
+ kfree(SCtmp->host_scribble);
SCtmp->host_scribble = NULL;
}
printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target);
@@ -1761,7 +1761,7 @@ fail:
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
SCtmp->result = DID_RESET << 16;
if (SCtmp->host_scribble) {
- scsi_free(SCtmp->host_scribble, 512);
+ kfree(SCtmp->host_scribble);
SCtmp->host_scribble = NULL;
}
printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target);
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index 5258b8d77..650b05d7d 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -213,6 +213,7 @@ int aha1740_test_port(unsigned int base)
/* A "high" level interrupt handler */
void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
{
+ struct Scsi_Host *host = aha_host[irq - 9];
void (*my_done)(Scsi_Cmnd *);
int errstatus, adapstat;
int number_serviced;
@@ -221,11 +222,10 @@ void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
unsigned int base;
unsigned long flags;
- spin_lock_irqsave(&io_request_lock, flags);
-
- if (!aha_host[irq - 9])
+ if (!host)
panic("aha1740.c: Irq from unknown host!\n");
- base = aha_host[irq - 9]->io_port;
+ spin_lock_irqsave(&host->host_lock, flags);
+ base = host->io_port;
number_serviced = 0;
while(inb(G2STAT(base)) & G2STAT_INTPEND)
@@ -299,7 +299,7 @@ void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
number_serviced++;
}
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irqrestore(&host->host_lock, flags);
}
int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
diff --git a/drivers/scsi/aic7xxx/aic7xxx_linux.c b/drivers/scsi/aic7xxx/aic7xxx_linux.c
index 0fa747f22..5e0029fee 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_linux.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux.c
@@ -130,6 +130,7 @@
#include <linux/mm.h> /* For fetching system memory size */
#include <linux/blk.h>
+#include <scsi/scsicam.h>
/*
* To generate the correct addresses for the controller to issue
@@ -2728,15 +2729,15 @@ ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
int ret;
int extended;
struct ahc_softc *ahc;
- struct buffer_head *bh;
+ unsigned char *buf;
ahc = *((struct ahc_softc **)disk->device->host->hostdata);
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));
+ buf = scsi_bios_ptable(dev);
- if (bh) {
- ret = scsi_partsize(bh, disk->capacity,
+ if (buf) {
+ ret = scsi_partsize(buf, disk->capacity,
&geom[2], &geom[0], &geom[1]);
- brelse(bh);
+ kfree(buf);
if (ret != -1)
return (ret);
}
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index b6cef7a3b..865c110aa 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -11723,15 +11723,15 @@ aic7xxx_biosparam(Disk *disk, kdev_t dev, int geom[])
{
int heads, sectors, cylinders, ret;
struct aic7xxx_host *p;
- struct buffer_head *bh;
+ unsigned char *buf;
p = (struct aic7xxx_host *) disk->device->host->hostdata;
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev));
+ buf = scsi_bios_ptable(dev);
- if ( bh )
+ if ( buf )
{
- ret = scsi_partsize(bh, disk->capacity, &geom[2], &geom[0], &geom[1]);
- brelse(bh);
+ ret = scsi_partsize(buf, disk->capacity, &geom[2], &geom[0], &geom[1]);
+ kfree(buf);
if ( ret != -1 )
return(ret);
}
diff --git a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c
index f698dc3be..705f435b3 100644
--- a/drivers/scsi/cpqfcTSworker.c
+++ b/drivers/scsi/cpqfcTSworker.c
@@ -159,7 +159,6 @@ void cpqfcTSWorkerThread( void *host)
#ifdef PCI_KERNEL_TRACE
PTACHYON fcChip = &cpqfcHBAdata->fcChip;
#endif
- struct fs_struct *fs;
DECLARE_MUTEX_LOCKED(fcQueReady);
DECLARE_MUTEX_LOCKED(fcTYOBcomplete);
DECLARE_MUTEX_LOCKED(TachFrozen);
@@ -168,33 +167,7 @@ void cpqfcTSWorkerThread( void *host)
ENTER("WorkerThread");
lock_kernel();
- /*
- * If we were started as result of loading a module, close all of the
- * user space pages. We don't need them, and if we didn't close them
- * they would be locked into memory.
- */
- exit_mm(current);
-
- current->session = 1;
- current->pgrp = 1;
-
- /* Become as one with the init task */
-
- exit_fs(current); /* current->fs->count--; */
- fs = init_task.fs;
- // Some kernels compiled for SMP, while actually running
- // on a uniproc machine, will return NULL for this call
- if( !fs)
- {
- printk(" cpqfcTS FATAL: fs is NULL! Is this an SMP kernel on uniproc machine?\n ");
- }
-
- else
- {
- current->fs = fs;
- atomic_inc(&fs->count);
- }
-
+ daemonize();
siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 4eeb7505c..d6210ef17 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -1159,17 +1159,13 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
msg[2] |= 0x80000000 | ((u32)wait_data->id);
timeout *= HZ;
if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){
- if(!timeout){
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&io_request_lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irq(&pHba->host->host_lock);
+ if (!timeout)
schedule();
- spin_lock_irq(&io_request_lock);
- } else {
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&io_request_lock);
+ else
schedule_timeout(timeout*HZ);
- spin_lock_irq(&io_request_lock);
- }
+ spin_lock_irq(&pHba->host->host_lock);
}
wq_write_lock_irq(&adpt_wq_i2o_post.lock);
__remove_wait_queue(&adpt_wq_i2o_post, &wait);
@@ -1562,7 +1558,7 @@ static int adpt_open(struct inode *inode, struct file *file)
//TODO check for root access
//
- minor = MINOR(inode->i_rdev);
+ minor = minor(inode->i_rdev);
if (minor >= hba_count) {
return -ENXIO;
}
@@ -1593,7 +1589,7 @@ static int adpt_close(struct inode *inode, struct file *file)
int minor;
adpt_hba* pHba;
- minor = MINOR(inode->i_rdev);
+ minor = minor(inode->i_rdev);
if (minor >= hba_count) {
return -ENXIO;
}
@@ -1707,7 +1703,7 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32* arg)
}
do {
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irqsave(&pHba->host->host_lock, flags);
// This state stops any new commands from enterring the
// controller while processing the ioctl
// pHba->state |= DPTI_STATE_IOCTL;
@@ -1715,7 +1711,7 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32* arg)
// the queue empties and stops. We need a way to restart the queue
rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
// pHba->state &= ~DPTI_STATE_IOCTL;
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irqrestore(&pHba->host->host_lock, flags);
} while(rcode == -ETIMEDOUT);
if(rcode){
@@ -1889,7 +1885,7 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
adpt_hba* pHba;
ulong flags;
- minor = MINOR(inode->i_rdev);
+ minor = minor(inode->i_rdev);
if (minor >= DPTI_MAX_HBA){
return -ENXIO;
}
@@ -1953,9 +1949,9 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
break;
}
case I2ORESETCMD:
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irqsave(&pHba->host->host_lock, flags);
adpt_hba_reset(pHba);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irqrestore(&pHba->host->host_lock, flags);
break;
case I2ORESCANCMD:
adpt_rescan(pHba);
@@ -1991,19 +1987,18 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
{
Scsi_Cmnd* cmd;
- adpt_hba* pHba=NULL;
+ adpt_hba* pHba = dev_id;
u32 m;
ulong reply;
u32 status=0;
u32 context;
ulong flags = 0;
- pHba = dev_id;
if (pHba == NULL ){
printk(KERN_WARNING"adpt_isr: NULL dev_id\n");
return;
}
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irqsave(&pHba->host->host_lock, flags);
while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) {
m = readl(pHba->reply_port);
if(m == EMPTY_QUEUE){
@@ -2013,8 +2008,7 @@ static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
if(m == EMPTY_QUEUE){
// This really should not happen
printk(KERN_ERR"dpti: Could not get reply frame\n");
- spin_unlock_irqrestore(&io_request_lock,flags);
- return;
+ goto out;
}
}
reply = (ulong)bus_to_virt(m);
@@ -2069,9 +2063,7 @@ static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
wmb();
rmb();
}
- spin_unlock_irqrestore(&io_request_lock, flags);
- return;
-
+out: spin_unlock_irqrestore(&pHba->host->host_lock, flags);
}
static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d)
@@ -2344,18 +2336,14 @@ static s32 adpt_rescan(adpt_hba* pHba)
s32 rcode;
ulong flags;
- spin_lock_irqsave(&io_request_lock, flags);
- if ((rcode=adpt_i2o_lct_get(pHba)) < 0){
- spin_unlock_irqrestore(&io_request_lock, flags);
- return rcode;
- }
-
- if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){
- spin_unlock_irqrestore(&io_request_lock, flags);
- return rcode;
- }
- spin_unlock_irqrestore(&io_request_lock, flags);
- return 0;
+ spin_lock_irqsave(&pHba->host->host_lock, flags);
+ if ((rcode=adpt_i2o_lct_get(pHba)) < 0)
+ goto out;
+ if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0)
+ goto out;
+ rcode = 0;
+out: spin_unlock_irqrestore(&pHba->host->host_lock, flags);
+ return rcode;
}
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index 58fe35ab2..cc6114bcd 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1,6 +1,13 @@
/*
* eata.c - Low-level driver for EATA/DMA SCSI host adapters.
*
+ * 01 Jan 2002 Rev. 7.20 for linux 2.5.1
+ * + Use the dynamic DMA mapping API.
+ *
+ * 19 Dec 2001 Rev. 7.02 for linux 2.5.1
+ * + Use SCpnt->sc_data_direction if set.
+ * + Use sglist.page instead of sglist.address.
+ *
* 11 Dec 2001 Rev. 7.00 for linux 2.5.1
* + Use host->host_lock instead of io_request_lock.
*
@@ -223,7 +230,7 @@
* This driver is based on the CAM (Common Access Method Committee)
* EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
*
- * Copyright (C) 1994-2001 Dario Ballabio (ballabio_dario@emc.com)
+ * Copyright (C) 1994-2002 Dario Ballabio (ballabio_dario@emc.com)
*
* Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
*
@@ -636,7 +643,7 @@ struct mscp {
u_int32_t data_len; /* If sg=0 Data Length, if sg=1 sglist length */
u_int32_t cpp_index; /* Index of address to be returned in sp */
u_int32_t data_address; /* If sg=0 Data Address, if sg=1 sglist address */
- u_int32_t sp_addr; /* Address where sp is DMA'ed when cp completes */
+ u_int32_t sp_dma_addr; /* Address where sp is DMA'ed when cp completes */
u_int32_t sense_addr; /* Address where Sense Data is DMA'ed on error */
/* Additional fields begin here. */
Scsi_Cmnd *SCpnt;
@@ -658,7 +665,11 @@ struct hostdata {
unsigned long last_retried_pid; /* Pid of last retried command */
unsigned char subversion; /* Bus type, either ISA or EISA/PCI */
unsigned char protocol_rev; /* EATA 2.0 rev., 'A' or 'B' or 'C' */
- struct mssp sp[2]; /* Returned status for this board */
+ unsigned char is_pci; /* TRUE is bus type is PCI */
+ struct pci_dev *pdev; /* pdev for PCI bus, NULL otherwise */
+ struct mssp *sp_cpu_addr; /* cpu addr for DMA buffer sp */
+ dma_addr_t sp_dma_addr; /* dma handle for DMA buffer sp */
+ struct mssp sp; /* Local copy of sp buffer */
};
static struct Scsi_Host *sh[MAX_BOARDS + 1];
@@ -695,10 +706,11 @@ static unsigned long io_port[] = {
#define HD(board) ((struct hostdata *) &sh[board]->hostdata)
#define BN(board) (HD(board)->board_name)
-#define H2DEV(x) htonl(x)
-#define DEV2H(x) H2DEV(x)
+/* Device is Big Endian */
+#define H2DEV(x) cpu_to_be32(x)
+#define DEV2H(x) be32_to_cpu(x)
+
#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
-#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
static void do_interrupt_handler(int, void *, struct pt_regs *);
static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
@@ -857,7 +869,7 @@ static inline struct pci_dev *get_pci_dev(unsigned long port_base) {
static inline int port_detect \
(unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) {
- unsigned char irq, dma_channel, subversion, i;
+ unsigned char irq, dma_channel, subversion, i, is_pci = FALSE;
unsigned char protocol_rev;
struct eata_info info;
char *bus_type, dma_name[16], tag_type;
@@ -909,10 +921,12 @@ static inline int port_detect \
if (!setup_done && j > 0 && j <= MAX_PCI) {
bus_type = "PCI";
+ is_pci = TRUE;
subversion = ESA;
}
else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) {
bus_type = "PCI";
+ is_pci = TRUE;
subversion = ESA;
}
else if (port_base >= MIN_EISA_ADDR || (protocol_rev == 'C' && info.eisa)) {
@@ -925,6 +939,7 @@ static inline int port_detect \
}
else if (port_base > MAX_ISA_ADDR) {
bus_type = "PCI";
+ is_pci = TRUE;
subversion = ESA;
}
else {
@@ -965,7 +980,13 @@ static inline int port_detect \
printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
name, irq);
- pdev = get_pci_dev(port_base);
+ if (is_pci) {
+ pdev = get_pci_dev(port_base);
+ if (!pdev)
+ printk("%s: warning, failed to get pci_dev structure.\n", name);
+ }
+ else
+ pdev = NULL;
if (pdev && (irq != pdev->irq)) {
printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, pdev->irq);
@@ -995,7 +1016,7 @@ static inline int port_detect \
/* Set board configuration */
memset((char *)&config, 0, sizeof(struct eata_config));
- config.len = (ushort) htons((ushort)510);
+ config.len = (ushort) cpu_to_be16((ushort)510);
config.ocena = TRUE;
if (do_dma(port_base, (unsigned long)&config, SET_CONFIG_DMA)) {
@@ -1024,14 +1045,16 @@ static inline int port_detect \
sh[j]->n_io_port = REGION_SIZE;
sh[j]->dma_channel = dma_channel;
sh[j]->irq = irq;
- sh[j]->sg_tablesize = (ushort) ntohs(info.scatt_size);
+ sh[j]->sg_tablesize = (ushort) be16_to_cpu(info.scatt_size);
sh[j]->this_id = (ushort) info.host_addr[3];
- sh[j]->can_queue = (ushort) ntohs(info.queue_size);
+ sh[j]->can_queue = (ushort) be16_to_cpu(info.queue_size);
sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;
sh[j]->select_queue_depths = select_queue_depths;
memset(HD(j), 0, sizeof(struct hostdata));
HD(j)->subversion = subversion;
HD(j)->protocol_rev = protocol_rev;
+ HD(j)->is_pci = is_pci;
+ HD(j)->pdev = pdev;
HD(j)->board_number = j;
if (HD(j)->subversion == ESA)
@@ -1040,14 +1063,14 @@ static inline int port_detect \
unsigned long flags;
scsi_register_blocked_host(sh[j]);
sh[j]->unchecked_isa_dma = TRUE;
-
+
flags=claim_dma_lock();
disable_dma(dma_channel);
clear_dma_ff(dma_channel);
set_dma_mode(dma_channel, DMA_MODE_CASCADE);
enable_dma(dma_channel);
release_dma_lock(flags);
-
+
}
strcpy(BN(j), name);
@@ -1096,6 +1119,13 @@ static inline int port_detect \
return FALSE;
}
+ if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev,
+ sizeof(struct mssp), &HD(j)->sp_dma_addr))) {
+ printk("%s: pci_alloc_consistent failed, detaching.\n", BN(j));
+ eata2x_release(sh[j]);
+ return FALSE;
+ }
+
if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
@@ -1110,7 +1140,7 @@ static inline int port_detect \
else tag_type = 'n';
if (j == 0) {
- printk("EATA/DMA 2.0x: Copyright (C) 1994-2001 Dario Ballabio.\n");
+ printk("EATA/DMA 2.0x: Copyright (C) 1994-2002 Dario Ballabio.\n");
printk("%s config options -> tc:%c, lc:%c, mq:%d, rs:%c, et:%c.\n",
driver_name, tag_type, YESNO(linked_comm), max_queue_depth,
YESNO(rev_scan), YESNO(ext_tran));
@@ -1146,7 +1176,11 @@ static inline int port_detect \
info.pci, info.eisa, info.raidnum);
#endif
- if (pdev) pci_set_master(pdev);
+ if (HD(j)->pdev) {
+ pci_set_master(HD(j)->pdev);
+ if (pci_set_dma_mask(HD(j)->pdev, 0xffffffff))
+ printk("%s: warning, pci_set_dma_mask failed.\n", BN(j));
+ }
return TRUE;
}
@@ -1273,25 +1307,92 @@ int eata2x_detect(Scsi_Host_Template *tpnt) {
return j;
}
-static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
- unsigned int k;
+static inline void map_dma(unsigned int i, unsigned int j) {
+ unsigned int k, count, pci_dir;
struct scatterlist *sgpnt;
+ struct mscp *cpp;
+ Scsi_Cmnd *SCpnt;
+
+ cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+ pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+ if (SCpnt->sense_buffer)
+ cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer,
+ sizeof SCpnt->sense_buffer, PCI_DMA_FROMDEVICE));
+
+ cpp->sense_len = sizeof SCpnt->sense_buffer;
+
+ if (!SCpnt->use_sg) {
+
+ if (!SCpnt->request_bufflen)
+ cpp->data_address = V2DEV(SCpnt->request_buffer);
+
+ else if (SCpnt->request_buffer)
+ cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
+ SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
+
+ cpp->data_len = H2DEV(SCpnt->request_bufflen);
+ return;
+ }
sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+ count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);
- for (k = 0; k < SCpnt->use_sg; k++) {
- cpp->sglist[k].address = V2DEV(sgpnt[k].address);
- cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length);
+ for (k = 0; k < count; k++) {
+ cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));
+ cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));
}
+ cpp->sg = TRUE;
cpp->data_address = V2DEV(cpp->sglist);
cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
}
-static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
- unsigned int i, j, k;
+static void unmap_dma(unsigned int i, unsigned int j) {
+ unsigned int pci_dir;
struct mscp *cpp;
- struct mssp *spp;
+ Scsi_Cmnd *SCpnt;
+
+ cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+ pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+ if (DEV2H(cpp->sense_addr))
+ pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+ DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+ if (SCpnt->use_sg)
+ pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
+
+ else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+ pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address),
+ DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static void sync_dma(unsigned int i, unsigned int j) {
+ unsigned int pci_dir;
+ struct mscp *cpp;
+ Scsi_Cmnd *SCpnt;
+
+ cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+ pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);
+
+ if (DEV2H(cpp->sense_addr))
+ pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
+ DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
+
+ if (SCpnt->use_sg)
+ pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer,
+ SCpnt->use_sg, pci_dir);
+
+ else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
+ pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address),
+ DEV2H(cpp->data_len), pci_dir);
+
+}
+
+static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) {
+ unsigned int k;
static const unsigned char data_out_cmds[] = {
0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
@@ -1302,9 +1403,53 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
static const unsigned char data_none_cmds[] = {
0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e,
0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47,
- 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5
+ 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00
};
+ struct mscp *cpp;
+ Scsi_Cmnd *SCpnt;
+
+ cpp = &HD(j)->cp[i];
+ SCpnt = cpp->SCpnt;
+
+ if (SCpnt->sc_data_direction == SCSI_DATA_READ) {
+ cpp->din = TRUE;
+ cpp->dout = FALSE;
+ return;
+ }
+ else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) {
+ cpp->din = FALSE;
+ cpp->dout = TRUE;
+ return;
+ }
+ else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) {
+ cpp->din = FALSE;
+ cpp->dout = FALSE;
+ return;
+ }
+
+ if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN)
+ panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
+
+ for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
+ if (SCpnt->cmnd[0] == data_out_cmds[k]) {
+ cpp->dout = TRUE;
+ break;
+ }
+
+ if ((cpp->din = !cpp->dout))
+ for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
+ if (SCpnt->cmnd[0] == data_none_cmds[k]) {
+ cpp->din = FALSE;
+ break;
+ }
+
+}
+
+static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
+ unsigned int i, j, k;
+ struct mscp *cpp;
+
/* j is the board number */
j = ((struct hostdata *) SCpnt->host->hostdata)->board_number;
@@ -1336,11 +1481,8 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
- /* Set pointer to status packet structure */
- spp = &HD(j)->sp[0];
-
- /* The EATA protocol uses Big Endian format */
- cpp->sp_addr = V2DEV(spp);
+ /* Set pointer to status packet structure, Big Endian format */
+ cpp->sp_dma_addr = H2DEV(HD(j)->sp_dma_addr);
SCpnt->scsi_done = done;
cpp->cpp_index = i;
@@ -1350,19 +1492,6 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
BN(j), i, SCpnt->channel, SCpnt->target,
SCpnt->lun, SCpnt->pid);
- for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
- if (SCpnt->cmnd[0] == data_out_cmds[k]) {
- cpp->dout = TRUE;
- break;
- }
-
- if ((cpp->din = !cpp->dout))
- for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
- if (SCpnt->cmnd[0] == data_none_cmds[k]) {
- cpp->din = FALSE;
- break;
- }
-
cpp->reqsen = TRUE;
cpp->dispri = TRUE;
#if 0
@@ -1373,8 +1502,13 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
cpp->target = SCpnt->target;
cpp->lun = SCpnt->lun;
cpp->SCpnt = SCpnt;
- cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
- cpp->sense_len = sizeof SCpnt->sense_buffer;
+ memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+
+ /* Use data transfer direction SCpnt->sc_data_direction */
+ scsi_to_dev_dir(i, j);
+
+ /* Map DMA buffers and SG list */
+ map_dma(i, j);
if (SCpnt->device->tagged_queue) {
@@ -1394,17 +1528,6 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
cpp->mess[1] = SCpnt->device->current_tag++;
}
- if (SCpnt->use_sg) {
- cpp->sg = TRUE;
- build_sg_list(cpp, SCpnt);
- }
- else {
- cpp->data_address = V2DEV(SCpnt->request_buffer);
- cpp->data_len = H2DEV(SCpnt->request_bufflen);
- }
-
- memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
-
if (linked_comm && SCpnt->device->queue_depth > 2
&& TLDEV(SCpnt->device->type)) {
HD(j)->cp_stat[i] = READY;
@@ -1414,6 +1537,7 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
/* Send control packet to the board */
if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) {
+ unmap_dma(i, j);
SCpnt->host_scribble = NULL;
printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
@@ -1470,6 +1594,7 @@ static inline int do_abort(Scsi_Cmnd *SCarg) {
printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
if (SCarg->eh_state == SCSI_STATE_TIMEOUT) {
+ unmap_dma(i, j);
SCarg->host_scribble = NULL;
HD(j)->cp_stat[i] = FREE;
printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n",
@@ -1491,6 +1616,7 @@ static inline int do_abort(Scsi_Cmnd *SCarg) {
}
if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+ unmap_dma(i, j);
SCarg->result = DID_ABORT << 16;
SCarg->host_scribble = NULL;
HD(j)->cp_stat[i] = FREE;
@@ -1599,6 +1725,7 @@ static inline int do_reset(Scsi_Cmnd *SCarg) {
if (HD(j)->cp_stat[i] == IN_RESET) {
SCpnt = HD(j)->cp[i].SCpnt;
+ unmap_dma(i, j);
SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL;
@@ -1611,6 +1738,7 @@ static inline int do_reset(Scsi_Cmnd *SCarg) {
else if (HD(j)->cp_stat[i] == ABORTING) {
SCpnt = HD(j)->cp[i].SCpnt;
+ unmap_dma(i, j);
SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL;
@@ -1823,7 +1951,7 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
static inline void ihdlr(int irq, unsigned int j) {
Scsi_Cmnd *SCpnt;
unsigned int i, k, c, status, tstatus, reg;
- struct mssp *dspp, *spp;
+ struct mssp *spp;
struct mscp *cpp;
if (sh[j]->irq != irq)
@@ -1845,14 +1973,13 @@ static inline void ihdlr(int irq, unsigned int j) {
return;
}
- dspp = &HD(j)->sp[0];
- spp = &HD(j)->sp[1];
+ spp = &HD(j)->sp;
/* Make a local copy just before clearing the interrupt indication */
- memcpy(spp, dspp, sizeof(struct mssp));
+ memcpy(spp, HD(j)->sp_cpu_addr, sizeof(struct mssp));
/* Clear the completion flag and cp pointer on the dynamic copy of sp */
- memset(dspp, 0, sizeof(struct mssp));
+ memset(HD(j)->sp_cpu_addr, 0, sizeof(struct mssp));
/* Read the status register to clear the interrupt indication */
reg = inb(sh[j]->io_port + REG_STATUS);
@@ -1910,6 +2037,8 @@ static inline void ihdlr(int irq, unsigned int j) {
panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
+ sync_dma(i, j);
+
if (linked_comm && SCpnt->device->queue_depth > 2
&& TLDEV(SCpnt->device->type))
flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
@@ -1987,6 +2116,7 @@ static inline void ihdlr(int irq, unsigned int j) {
#else
status = DID_BUS_BUSY << 16;
#endif
+
HD(j)->retries++;
HD(j)->last_retried_pid = SCpnt->pid;
}
@@ -2023,6 +2153,8 @@ static inline void ihdlr(int irq, unsigned int j) {
SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
reg, HD(j)->iocount);
+ unmap_dma(i, j);
+
/* Set the command state to inactive */
SCpnt->host_scribble = NULL;
@@ -2054,13 +2186,15 @@ int eata2x_release(struct Scsi_Host *shpnt) {
if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
driver_name);
- if( sh[j]->unchecked_isa_dma ) {
- scsi_deregister_blocked_host(sh[j]);
- }
+ if(sh[j]->unchecked_isa_dma) scsi_deregister_blocked_host(sh[j]);
for (i = 0; i < sh[j]->can_queue; i++)
if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
+ if (HD(j)->sp_cpu_addr)
+ pci_free_consistent(HD(j)->pdev, sizeof(struct mssp),
+ HD(j)->sp_cpu_addr, HD(j)->sp_dma_addr);
+
free_irq(sh[j]->irq, &sha[j]);
if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
diff --git a/drivers/scsi/eata.h b/drivers/scsi/eata.h
index de0bad6ef..45d5cdaba 100644
--- a/drivers/scsi/eata.h
+++ b/drivers/scsi/eata.h
@@ -13,7 +13,7 @@ int eata2x_abort(Scsi_Cmnd *);
int eata2x_reset(Scsi_Cmnd *);
int eata2x_biosparam(Disk *, kdev_t, int *);
-#define EATA_VERSION "7.00.00"
+#define EATA_VERSION "7.20.00"
#define EATA { \
name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 229bad39f..61e3a19a6 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -382,22 +382,23 @@ enum out_port_type {
Write_FIFO = 12
};
-static int port_base = 0;
-static unsigned long bios_base = 0;
-static int bios_major = 0;
-static int bios_minor = 0;
-static int PCI_bus = 0;
-static int Quantum = 0; /* Quantum board variant */
-static int interrupt_level = 0;
-static volatile int in_command = 0;
-static Scsi_Cmnd *current_SC = NULL;
+/* .bss will zero all the static variables below */
+static int port_base;
+static unsigned long bios_base;
+static int bios_major;
+static int bios_minor;
+static int PCI_bus;
+static int Quantum; /* Quantum board variant */
+static int interrupt_level;
+static volatile int in_command;
+static Scsi_Cmnd *current_SC;
static enum chip_type chip = unknown;
-static int adapter_mask = 0;
-static int this_id = 0;
-static int setup_called = 0;
+static int adapter_mask;
+static int this_id;
+static int setup_called;
#if DEBUG_RACE
-static volatile int in_interrupt_flag = 0;
+static volatile int in_interrupt_flag;
#endif
static int SCSI_Mode_Cntl_port;
@@ -983,7 +984,7 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* Register the IRQ with the kernel */
retcode = request_irq( interrupt_level,
- do_fdomain_16x0_intr, pdev?SA_SHIRQ:0, "fdomain", NULL);
+ do_fdomain_16x0_intr, pdev?SA_SHIRQ:0, "fdomain", shpnt);
if (retcode < 0) {
if (retcode == -EINVAL) {
@@ -1265,9 +1266,9 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
#if EVERY_ACCESS
printk( " AFAIL " );
#endif
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irqsave(&current_SC->host->host_lock, flags);
my_done( DID_BUS_BUSY << 16 );
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
return;
}
current_SC->SCp.phase = in_selection;
@@ -1291,9 +1292,9 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
#if EVERY_ACCESS
printk( " SFAIL " );
#endif
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irqsave(&current_SC->host->host_lock, flags);
my_done( DID_NO_CONNECT << 16 );
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
return;
} else {
#if EVERY_ACCESS
@@ -1638,10 +1639,10 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
#if EVERY_ACCESS
printk( "BEFORE MY_DONE. . ." );
#endif
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irqsave(&current_SC->host->host_lock, flags);
my_done( (current_SC->SCp.Status & 0xff)
| ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irqrestore(&current_SC->host->host_lock, flags);
#if EVERY_ACCESS
printk( "RETURNING.\n" );
#endif
@@ -1932,11 +1933,11 @@ int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array )
0x0a bytes long. Heads are one less than we need to report.
*/
- if (MAJOR(dev) != SCSI_DISK0_MAJOR) {
+ if (major(dev) != SCSI_DISK0_MAJOR) {
printk("scsi: <fdomain> fdomain_16x0_biosparam: too many disks");
return 0;
}
- drive = MINOR(dev) >> 4;
+ drive = minor(dev) >> 4;
if (bios_major == 2) {
switch (Quantum) {
@@ -2035,6 +2036,15 @@ int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array )
return 0;
}
+int fdomain_16x0_release(struct Scsi_Host *shpnt)
+{
+ if (shpnt->irq)
+ free_irq(shpnt->irq, shpnt);
+ if (shpnt->io_port && shpnt->n_io_port)
+ release_region(shpnt->io_port, shpnt->n_io_port);
+
+}
+
MODULE_LICENSE("GPL");
/* Eventually this will go into an include file, but this will be later */
diff --git a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h
index 1769d24c7..a85539af1 100644
--- a/drivers/scsi/fdomain.h
+++ b/drivers/scsi/fdomain.h
@@ -34,6 +34,7 @@ int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
int fdomain_16x0_biosparam( Disk *, kdev_t, int * );
int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset,
int length, int hostno, int inout );
+int fdomain_16x0_release( struct Scsi_Host *shpnt );
#define FDOMAIN_16X0 { proc_info: fdomain_16x0_proc_info, \
detect: fdomain_16x0_detect, \
@@ -43,6 +44,7 @@ int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset,
abort: fdomain_16x0_abort, \
reset: fdomain_16x0_reset, \
bios_param: fdomain_16x0_biosparam, \
+ release: fdomain_16x0_release, \
can_queue: 1, \
this_id: 6, \
sg_tablesize: 64, \
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index cf32a8a3a..aa0fd64cb 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -270,15 +270,6 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j)
return retval;
}
-int
-scsi_register_device(struct Scsi_Device_Template * sdpnt)
-{
- if(sdpnt->next) panic("Device already registered");
- sdpnt->next = scsi_devicelist;
- scsi_devicelist = sdpnt;
- return 0;
-}
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
index 9045cc4cb..3246ba64f 100644
--- a/drivers/scsi/hosts.h
+++ b/drivers/scsi/hosts.h
@@ -521,17 +521,14 @@ struct Scsi_Device_Template
void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt);
-int scsi_register_device(struct Scsi_Device_Template * sdpnt);
-/* These are used by loadable modules */
-extern int scsi_register_module(int, void *);
-extern int scsi_unregister_module(int, void *);
-
-/* The different types of modules that we can load and unload */
-#define MODULE_SCSI_HA 1
-#define MODULE_SCSI_CONST 2
-#define MODULE_SCSI_IOCTL 3
-#define MODULE_SCSI_DEV 4
+/*
+ * Driver registration/unregistration.
+ */
+extern int scsi_register_device(struct Scsi_Device_Template *);
+extern int scsi_unregister_device(struct Scsi_Device_Template *);
+extern int scsi_register_host(Scsi_Host_Template *);
+extern int scsi_unregister_host(Scsi_Host_Template *);
/*
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 0cab54547..3bb3bef50 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -50,7 +50,6 @@
#include "scsi.h"
#include "hosts.h"
#include "sd.h"
-#include "ide-scsi.h"
#include <scsi/sg.h>
#define IDESCSI_DEBUG_LOG 0
@@ -748,7 +747,7 @@ static inline int should_transform(ide_drive_t *drive, Scsi_Cmnd *cmd)
{
idescsi_scsi_t *scsi = drive->driver_data;
- if (MAJOR(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR)
+ if (major(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR)
return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
return test_bit(IDESCSI_TRANSFORM, &scsi->transform);
}
@@ -840,13 +839,29 @@ int idescsi_bios (Disk *disk, kdev_t dev, int *parm)
return 0;
}
-static Scsi_Host_Template idescsi_template = IDESCSI;
+static Scsi_Host_Template idescsi_template = {
+ module: THIS_MODULE,
+ name: "idescsi",
+ detect: idescsi_detect,
+ release: idescsi_release,
+ info: idescsi_info,
+ ioctl: idescsi_ioctl,
+ queuecommand: idescsi_queue,
+ abort: idescsi_abort,
+ reset: idescsi_reset,
+ bios_param: idescsi_bios,
+ can_queue: 10,
+ this_id: -1,
+ sg_tablesize: 256,
+ cmd_per_lun: 5,
+ use_clustering: DISABLE_CLUSTERING,
+ emulated: 1,
+};
static int __init init_idescsi_module(void)
{
idescsi_init();
- idescsi_template.module = THIS_MODULE;
- scsi_register_module (MODULE_SCSI_HA, &idescsi_template);
+ scsi_register_host(&idescsi_template);
return 0;
}
@@ -856,7 +871,7 @@ static void __exit exit_idescsi_module(void)
byte media[] = {TYPE_DISK, TYPE_TAPE, TYPE_PROCESSOR, TYPE_WORM, TYPE_ROM, TYPE_SCANNER, TYPE_MOD, 255};
int i, failed;
- scsi_unregister_module (MODULE_SCSI_HA, &idescsi_template);
+ scsi_unregister_host(&idescsi_template);
for (i = 0; media[i] != 255; i++) {
failed = 0;
while ((drive = ide_scan_devices (media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL)
diff --git a/drivers/scsi/ide-scsi.h b/drivers/scsi/ide-scsi.h
deleted file mode 100644
index 84fab9263..000000000
--- a/drivers/scsi/ide-scsi.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * linux/drivers/scsi/ide-scsi.h
- *
- * Copyright (C) 1996, 1997 Gadi Oxman <gadio@netvision.net.il>
- */
-
-#ifndef IDESCSI_H
-#define IDESCSI_H
-
-extern int idescsi_detect (Scsi_Host_Template *host_template);
-extern int idescsi_release (struct Scsi_Host *host);
-extern const char *idescsi_info (struct Scsi_Host *host);
-extern int idescsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
-extern int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
-extern int idescsi_abort (Scsi_Cmnd *cmd);
-extern int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags);
-extern int idescsi_bios (Disk *disk, kdev_t dev, int *parm);
-
-#define IDESCSI { \
- name: "idescsi", /* name */ \
- detect: idescsi_detect, /* detect */ \
- release: idescsi_release, /* release */ \
- info: idescsi_info, /* info */ \
- ioctl: idescsi_ioctl, /* ioctl */ \
- queuecommand: idescsi_queue, /* queuecommand */ \
- abort: idescsi_abort, /* abort */ \
- reset: idescsi_reset, /* reset */ \
- bios_param: idescsi_bios, /* bios_param */ \
- can_queue: 10, /* can_queue */ \
- this_id: -1, /* this_id */ \
- sg_tablesize: 256, /* sg_tablesize */ \
- cmd_per_lun: 5, /* cmd_per_lun */ \
- use_clustering: DISABLE_CLUSTERING, /* clustering */ \
- emulated: 1 /* emulated */ \
-}
-
-#endif /* IDESCSI_H */
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index 5b7a67825..5659858c1 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -855,7 +855,7 @@ unsigned long flags;
/* Get the spin_lock and disable further ints, for SMP */
- CLISPIN_LOCK(flags);
+ CLISPIN_LOCK(instance, flags);
#ifdef PROC_STATISTICS
hostdata->int_cnt++;
@@ -993,7 +993,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
write1_io(0, IO_LED_OFF);
/* release the SMP spin_lock and restore irq state */
- CLISPIN_UNLOCK(flags);
+ CLISPIN_UNLOCK(instance, flags);
return;
}
@@ -1011,7 +1011,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
write1_io(0, IO_LED_OFF);
/* release the SMP spin_lock and restore irq state */
- CLISPIN_UNLOCK(flags);
+ CLISPIN_UNLOCK(instance, flags);
return;
}
@@ -1433,7 +1433,7 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
hostdata->state = S_UNCONNECTED;
/* release the SMP spin_lock and restore irq state */
- CLISPIN_UNLOCK(flags);
+ CLISPIN_UNLOCK(instance, flags);
return;
}
DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
@@ -1609,7 +1609,7 @@ DB(DB_INTR,printk("-%ld",cmd->pid))
DB(DB_INTR,printk("} "))
/* release the SMP spin_lock and restore irq state */
- CLISPIN_UNLOCK(flags);
+ CLISPIN_UNLOCK(instance, flags);
}
diff --git a/drivers/scsi/in2000.h b/drivers/scsi/in2000.h
index 7fe39c451..ac72f6a29 100644
--- a/drivers/scsi/in2000.h
+++ b/drivers/scsi/in2000.h
@@ -393,8 +393,9 @@ struct IN2000_hostdata {
# define in2000__INITFUNC(function) __initfunc(function)
# define in2000__INIT __init
# define in2000__INITDATA __initdata
-# define CLISPIN_LOCK(flags) spin_lock_irqsave(&io_request_lock, flags)
-# define CLISPIN_UNLOCK(flags) spin_unlock_irqrestore(&io_request_lock, flags)
+# define CLISPIN_LOCK(host,flags) spin_lock_irqsave(&host->host_lock, flags)
+# define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(&host->host_lock, \
+ flags)
int in2000_detect(Scsi_Host_Template *) in2000__INIT;
int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 429beabcb..797dec25f 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1771,14 +1771,13 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
char *kern_area;
u_int32_t datasize;
- /* free io_request_lock */
- spin_unlock_irq(&io_request_lock);
+ spin_unlock_irq(&SC->host->host_lock);
/* wait for the command to finish */
down(&ha->ioctl_sem);
/* reobtain the lock */
- spin_lock_irq(&io_request_lock);
+ spin_lock_irq(&SC->host->host_lock);
/* command finished -- copy back */
user_area = *((char **) &SC->cmnd[4]);
@@ -1913,31 +1912,30 @@ ips_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) {
/****************************************************************************/
void
do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
- ips_ha_t *ha;
+ ips_ha_t *ha = (ips_ha_t *) dev_id;
unsigned long cpu_flags;
+ struct Scsi_Host *host = ips_sh[ha->host_num];
METHOD_TRACE("do_ipsintr", 2);
- ha = (ips_ha_t *) dev_id;
-
- spin_lock_irqsave(&io_request_lock, cpu_flags);
+ spin_lock_irqsave(&host->host_lock, cpu_flags);
if (test_and_set_bit(IPS_IN_INTR, &ha->flags)) {
- spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+ spin_unlock_irqrestore(&host->host_lock, cpu_flags);
return ;
}
if (!ha) {
clear_bit(IPS_IN_INTR, &ha->flags);
- spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+ spin_unlock_irqrestore(&host->host_lock, cpu_flags);
return;
}
if (!ha->active) {
clear_bit(IPS_IN_INTR, &ha->flags);
- spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+ spin_unlock_irqrestore(&host->host_lock, cpu_flags);
return;
}
@@ -1946,10 +1944,11 @@ do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
clear_bit(IPS_IN_INTR, &ha->flags);
- spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+ spin_unlock_irqrestore(&host->host_lock, cpu_flags);
/* start the next command */
ips_next(ha, IPS_INTR_ON);
+ return;
}
/****************************************************************************/
@@ -2489,8 +2488,8 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
task.routine = ips_scheduled_flash_bios;
task.data = (void *) &flash_data;
- /* Unlock the master lock */
- spin_unlock_irq(&io_request_lock);
+ /* Unlock the per-board lock */
+ spin_unlock_irq(&SC->host->host_lock);
queue_task(&task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
@@ -2498,8 +2497,8 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
/* Wait for the flash to complete */
down(&ha->flash_ioctl_sem);
- /* Obtain the master lock */
- spin_lock_irq(&io_request_lock);
+ /* Obtain the per-board lock */
+ spin_lock_irq(&SC->host->host_lock);
return (flash_data.retcode);
}
@@ -2606,8 +2605,8 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
task.routine = ips_flash_bios_section;
task.data = (void *) &flash_data;
- /* Unlock the master lock */
- spin_unlock_irq(&io_request_lock);
+ /* Unlock the per-board lock */
+ spin_unlock_irq(&SC->host->host_lock);
queue_task(&task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
@@ -2615,8 +2614,8 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
/* Wait for the flash to complete */
down(&ha->flash_ioctl_sem);
- /* Obtain the master lock */
- spin_lock_irq(&io_request_lock);
+ /* Obtain the per-board lock */
+ spin_lock_irq(&SC->host->host_lock);
return (flash_data.retcode);
}
@@ -3574,18 +3573,21 @@ ips_next(ips_ha_t *ha, int intr) {
int intr_status;
unsigned long cpu_flags;
unsigned long cpu_flags2;
+ struct Scsi_Host *host;
METHOD_TRACE("ips_next", 1);
if (!ha)
return ;
+ host = ips_sh[ha->host_num];
+
/*
* Block access to the queue function so
* this command won't time out
*/
if (intr == IPS_INTR_ON) {
- spin_lock_irqsave(&io_request_lock, cpu_flags2);
+ spin_lock_irqsave(&host->host_lock, cpu_flags2);
intr_status = IPS_INTR_IORL;
} else {
intr_status = intr;
@@ -3610,7 +3612,7 @@ ips_next(ips_ha_t *ha, int intr) {
}
if (intr == IPS_INTR_ON)
- spin_unlock_irqrestore(&io_request_lock, cpu_flags2);
+ spin_unlock_irqrestore(&host->host_lock, cpu_flags2);
#ifndef NO_IPS_CMDLINE
/*
@@ -6606,6 +6608,8 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
clear_bit(IPS_IN_INTR, &ha->flags);
} else if (intr == IPS_INTR_HAL) {
+ struct Scsi_Host *host = ips_sh[ha->host_num];
+
if (ha->waitflag == FALSE) {
/*
* controller generated an interrupt to
@@ -6623,7 +6627,7 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
* We were called under the HA lock so we can assume that interrupts
* are masked.
*/
- spin_lock(&io_request_lock);
+ spin_lock(&host->host_lock);
while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
udelay(1000);
@@ -6632,7 +6636,7 @@ ips_wait(ips_ha_t *ha, int time, int intr) {
clear_bit(IPS_IN_INTR, &ha->flags);
- spin_unlock(&io_request_lock);
+ spin_unlock(&host->host_lock);
}
udelay(1000); /* 1 milisecond */
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index cbc805e4d..0cd62a196 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -353,7 +353,7 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
NCR5380_read( RESET_PARITY_INTERRUPT_REG );
- for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
+ for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
barrier();
/* switch on SCSI IRQ again */
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index e8acc9e46..ddd0bcd0a 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -4290,18 +4290,18 @@ int megaraid_biosparam (Disk * disk, kdev_t dev, int *geom)
static int
mega_partsize(Disk * disk, kdev_t dev, int *geom)
{
- struct buffer_head *bh;
struct partition *p, *largest = NULL;
int i, largest_cyl;
int heads, cyls, sectors;
int capacity = disk->capacity;
+ unsigned char *buf;
- if(!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev))))
+ if (!(buf = scsi_bios_ptable(dev)))
return -1;
- if( *(unsigned short *)(bh->b_data + 510) == 0xAA55 ) {
+ if( *(unsigned short *)(buf + 64) == 0xAA55 ) {
- for( largest_cyl = -1, p = (struct partition *)(0x1BE + bh->b_data),
+ for( largest_cyl = -1, p = (struct partition *)buf,
i = 0; i < 4; ++i, ++p) {
if (!p->sys_ind) continue;
@@ -4320,7 +4320,7 @@ mega_partsize(Disk * disk, kdev_t dev, int *geom)
sectors = largest->end_sector & 0x3f;
if (heads == 0 || sectors == 0) {
- brelse(bh);
+ kfree(buf);
return -1;
}
@@ -4330,11 +4330,11 @@ mega_partsize(Disk * disk, kdev_t dev, int *geom)
geom[1] = sectors;
geom[2] = cyls;
- brelse(bh);
+ kfree(buf);
return 0;
}
- brelse(bh);
+ kfree(buf);
return -1;
}
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index ce2e2e090..df2b302cc 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -8626,9 +8626,9 @@ static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
if (DEBUG_FLAGS & DEBUG_TINY) printk ("]\n");
if (done_list) {
- NCR_LOCK_SCSI_DONE(np, flags);
+ NCR_LOCK_SCSI_DONE(done_list->host, flags);
ncr_flush_done_cmds(done_list);
- NCR_UNLOCK_SCSI_DONE(np, flags);
+ NCR_UNLOCK_SCSI_DONE(done_list->host, flags);
}
}
@@ -8649,9 +8649,9 @@ static void ncr53c8xx_timeout(unsigned long npref)
NCR_UNLOCK_NCB(np, flags);
if (done_list) {
- NCR_LOCK_SCSI_DONE(np, flags);
+ NCR_LOCK_SCSI_DONE(done_list->host, flags);
ncr_flush_done_cmds(done_list);
- NCR_UNLOCK_SCSI_DONE(np, flags);
+ NCR_UNLOCK_SCSI_DONE(done_list->host, flags);
}
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 289096b16..36b57bfbd 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -125,8 +125,8 @@ static int debugging = 1;
#define OSST_TIMEOUT (200 * HZ)
#define OSST_LONG_TIMEOUT (1800 * HZ)
-#define TAPE_NR(x) (MINOR(x) & ~(128 | ST_MODE_MASK))
-#define TAPE_MODE(x) ((MINOR(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
+#define TAPE_NR(x) (minor(x) & ~(128 | ST_MODE_MASK))
+#define TAPE_MODE(x) ((minor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
24 bits) */
@@ -159,6 +159,7 @@ static void osst_detach(Scsi_Device *);
struct Scsi_Device_Template osst_template =
{
+ module: THIS_MODULE,
name: "OnStream tape",
tag: "osst",
scsi_type: TYPE_TAPE,
@@ -4092,7 +4093,7 @@ os_bypass:
if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
STp->rew_at_close = 0;
else if (cmd_in == MTLOAD) {
-/* STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0; FIXME */
+/* STp->rew_at_close = (minor(inode->i_rdev) & 0x80) == 0; FIXME */
for (i=0; i < ST_NBR_PARTITIONS; i++) {
STp->ps[i].rw = ST_IDLE;
STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */
@@ -4176,7 +4177,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
return (-EBUSY);
}
STp->in_use = 1;
- STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+ STp->rew_at_close = (minor(inode->i_rdev) & 0x80) == 0;
if (STp->device->host->hostt->module)
__MOD_INC_USE_COUNT(STp->device->host->hostt->module);
@@ -4198,7 +4199,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
flags = filp->f_flags;
STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
- STp->raw = (MINOR(inode->i_rdev) & 0x40) != 0;
+ STp->raw = (minor(inode->i_rdev) & 0x40) != 0;
if (STp->raw)
STp->header_ok = 0;
@@ -5495,7 +5496,7 @@ static int osst_attach(Scsi_Device * SDp)
#endif
tpnt->device = SDp;
- tpnt->devt = MKDEV(MAJOR_NR, i);
+ tpnt->devt = mk_kdev(MAJOR_NR, i);
tpnt->dirty = 0;
tpnt->in_use = 0;
tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
@@ -5675,8 +5676,7 @@ static void osst_detach(Scsi_Device * SDp)
static int __init init_osst(void)
{
validate_options();
- osst_template.module = THIS_MODULE;
- return scsi_register_module(MODULE_SCSI_DEV, &osst_template);
+ return scsi_register_device(&osst_template);
}
static void __exit exit_osst (void)
@@ -5684,7 +5684,7 @@ static void __exit exit_osst (void)
int i;
OS_Scsi_Tape * STp;
- scsi_unregister_module(MODULE_SCSI_DEV, &osst_template);
+ scsi_unregister_device(&osst_template);
#ifdef CONFIG_DEVFS_FS
devfs_unregister_chrdev(MAJOR_NR, "osst");
#else
diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c
index 88c4b4ee6..2c9b1d44d 100644
--- a/drivers/scsi/pci2000.c
+++ b/drivers/scsi/pci2000.c
@@ -275,11 +275,6 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
int z;
unsigned long flags;
- /*
- * Disable interrupts, if they aren't already disabled and acquire
- * the I/O spinlock.
- */
- spin_lock_irqsave (&io_request_lock, flags);
DEB(printk ("\npci2000 received interrupt "));
for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
@@ -298,9 +293,10 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
if ( !shost )
{
DEB (printk ("\npci2000: not my interrupt"));
- goto irq_return;
+ goto out;
}
+ spin_lock_irqsave(&shost->host_lock, flags);
padapter = HOSTDATA(shost);
tag0 = tag & 0x7F; // mask off the error bit
@@ -392,14 +388,10 @@ irqProceed:;
outb_p (CMD_DONE, padapter->cmd); // complete the op
OpDone (SCpnt, DID_OK << 16);
-irq_return:;
- /*
- * Release the I/O spinlock and restore the original flags
- * which will enable interrupts if and only if they were
- * enabled on entry.
- */
- spin_unlock_irqrestore (&io_request_lock, flags);
- }
+irq_return:
+ spin_unlock_irqrestore(&shost->host_lock, flags);
+out:;
+}
/****************************************************************
* Name: Pci2000_QueueCommand
*
diff --git a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c
index 8f5a892c6..e47effc9f 100644
--- a/drivers/scsi/pci2220i.c
+++ b/drivers/scsi/pci2220i.c
@@ -1154,6 +1154,7 @@ static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
static void TimerExpiry (unsigned long data)
{
PADAPTER2220I padapter = (PADAPTER2220I)data;
+ struct Scsi_Host *host = padapter->SCpnt->host;
POUR_DEVICE pdev = padapter->pdev;
UCHAR status = IDE_STATUS_BUSY;
UCHAR temp, temp1;
@@ -1163,7 +1164,7 @@ static void TimerExpiry (unsigned long data)
* Disable interrupts, if they aren't already disabled and acquire
* the I/O spinlock.
*/
- spin_lock_irqsave (&io_request_lock, flags);
+ spin_lock_irqsave (&host->host_lock, flags);
DEB (printk ("\nPCI2220I: Timeout expired "));
if ( padapter->failinprog )
@@ -1297,7 +1298,7 @@ timerExpiryDone:;
* which will enable interrupts if and only if they were
* enabled on entry.
*/
- spin_unlock_irqrestore (&io_request_lock, flags);
+ spin_unlock_irqrestore (&host->host_lock, flags);
}
/****************************************************************
* Name: SetReconstruct :LOCAL
@@ -1330,7 +1331,8 @@ static LONG SetReconstruct (POUR_DEVICE pdev, int index)
****************************************************************/
static void ReconTimerExpiry (unsigned long data)
{
- PADAPTER2220I padapter;
+ PADAPTER2220I padapter = (PADAPTER2220I)data;
+ struct Scsi_Host *host = padapter->SCpnt->host;
POUR_DEVICE pdev;
ULONG testsize = 0;
PIDENTIFY_DATA pid;
@@ -1344,9 +1346,8 @@ static void ReconTimerExpiry (unsigned long data)
* Disable interrupts, if they aren't already disabled and acquire
* the I/O spinlock.
*/
- spin_lock_irqsave (&io_request_lock, flags);
+ spin_lock_irqsave(&host->host_lock, flags);
- padapter = (PADAPTER2220I)data;
if ( padapter->SCpnt )
goto reconTimerExpiry;
@@ -1569,7 +1570,7 @@ reconTimerExpiry:;
* which will enable interrupts if and only if they were
* enabled on entry.
*/
- spin_unlock_irqrestore (&io_request_lock, flags);
+ spin_unlock_irqrestore(&host->host_lock, flags);
}
/****************************************************************
* Name: Irq_Handler :LOCAL
@@ -1598,12 +1599,6 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
ULONG zl;
unsigned long flags;
- /*
- * Disable interrupts, if they aren't already disabled and acquire
- * the I/O spinlock.
- */
- spin_lock_irqsave (&io_request_lock, flags);
-
// DEB (printk ("\npci2220i received interrupt\n"));
for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
@@ -1621,9 +1616,10 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
if ( !shost )
{
DEB (printk ("\npci2220i: not my interrupt"));
- goto irq_return;
+ goto out;
}
+ spin_lock_irqsave(&shost->host_lock, flags);
padapter = HOSTDATA(shost);
pdev = padapter->pdev;
SCpnt = padapter->SCpnt;
@@ -2025,13 +2021,9 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
zl = DID_OK << 16;
OpDone (padapter, zl);
-irq_return:;
- /*
- * Release the I/O spinlock and restore the original flags
- * which will enable interrupts if and only if they were
- * enabled on entry.
- */
- spin_unlock_irqrestore (&io_request_lock, flags);
+irq_return:
+ spin_unlock_irqrestore(&shost->host_lock, flags);
+out:;
}
/****************************************************************
* Name: Pci2220i_QueueCommand
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 86260644c..65b0d3c73 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -290,7 +290,7 @@ static void aha152x_config_cs(dev_link_t *link)
#endif
aha152x_setup("PCMCIA setup", ints);
- scsi_register_module(MODULE_SCSI_HA, &driver_template);
+ scsi_register_host(&driver_template);
tail = &link->dev;
info->ndev = 0;
@@ -356,7 +356,7 @@ static void aha152x_release_cs(u_long arg)
return;
}
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ scsi_unregister_host(&driver_template);
link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle);
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 8dae5f4b1..a14a17bea 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -259,7 +259,7 @@ static void fdomain_config(dev_link_t *link)
sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
fdomain_setup(str, ints);
- scsi_register_module(MODULE_SCSI_HA, &driver_template);
+ scsi_register_host(&driver_template);
tail = &link->dev;
info->ndev = 0;
@@ -324,7 +324,7 @@ static void fdomain_release(u_long arg)
return;
}
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ scsi_unregister_host(&driver_template);
link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index becd0ac8c..fc521c26e 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1515,7 +1515,7 @@ static void nsp_cs_config(dev_link_t *link)
goto cs_failed;
}
- scsi_register_module(MODULE_SCSI_HA, &driver_template);
+ scsi_register_host(&driver_template);
DEBUG(0, "GET_SCSI_INFO\n");
tail = &link->dev;
@@ -1611,7 +1611,7 @@ static void nsp_cs_release(u_long arg)
}
/* Unlink the device chain */
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ scsi_unregister_host(&driver_template);
link->dev = NULL;
if (link->win) {
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index be524f9da..9ff5d4685 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -281,7 +281,7 @@ static void qlogic_config(dev_link_t *link)
else
qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ);
- scsi_register_module(MODULE_SCSI_HA, &driver_template);
+ scsi_register_host(&driver_template);
tail = &link->dev;
info->ndev = 0;
@@ -345,7 +345,7 @@ static void qlogic_release(u_long arg)
return;
}
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ scsi_unregister_host(&driver_template);
link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle);
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 9a04761cb..3d60e8ea6 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -193,7 +193,6 @@ END OF TERMS AND CONDITIONS
#include <stdarg.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/segment.h>
#include <asm/byteorder.h>
#include <linux/version.h>
#include <linux/types.h>
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 98a478083..b3257fc46 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -200,14 +200,11 @@ void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt)
/* Hardware imposed limit. */
blk_queue_max_hw_segments(q, SHpnt->sg_tablesize);
-
- /*
- * When we remove scsi_malloc soonish, this can die too
- */
- blk_queue_max_phys_segments(q, PAGE_SIZE / sizeof(struct scatterlist));
-
blk_queue_max_sectors(q, SHpnt->max_sectors);
+ /* scsi_alloc_sgtable max */
+ blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
+
if (!SHpnt->use_clustering)
clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
}
@@ -1405,9 +1402,6 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
SCpnt->done(SCpnt);
}
-static int scsi_register_host(Scsi_Host_Template *);
-static int scsi_unregister_host(Scsi_Host_Template *);
-
/*
* Function: scsi_release_commandblocks()
*
@@ -1842,7 +1836,7 @@ out:
* This entry point should be called by a driver if it is trying
* to add a low level scsi driver to the system.
*/
-static int scsi_register_host(Scsi_Host_Template * tpnt)
+int scsi_register_host(Scsi_Host_Template * tpnt)
{
int pcount;
struct Scsi_Host *shpnt;
@@ -1992,7 +1986,7 @@ static int scsi_register_host(Scsi_Host_Template * tpnt)
* Similarly, this entry point should be called by a loadable module if it
* is trying to remove a low level scsi driver from the system.
*/
-static int scsi_unregister_host(Scsi_Host_Template * tpnt)
+int scsi_unregister_host(Scsi_Host_Template * tpnt)
{
int online_status;
int pcount0, pcount;
@@ -2203,22 +2197,27 @@ err_out:
return -1;
}
-static int scsi_unregister_device(struct Scsi_Device_Template *tpnt);
-
/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
*/
-static int scsi_register_device_module(struct Scsi_Device_Template *tpnt)
+int scsi_register_device(struct Scsi_Device_Template *tpnt)
{
Scsi_Device *SDpnt;
struct Scsi_Host *shpnt;
int out_of_space = 0;
+#ifdef CONFIG_KMOD
+ if (scsi_hosts == NULL)
+ request_module("scsi_hostadapter");
+#endif
+
if (tpnt->next)
return 1;
- scsi_register_device(tpnt);
+ tpnt->next = scsi_devicelist;
+ scsi_devicelist = tpnt;
+
/*
* First scan the devices that we know about, and see if we notice them.
*/
@@ -2274,7 +2273,7 @@ static int scsi_register_device_module(struct Scsi_Device_Template *tpnt)
return 0;
}
-static int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
+int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
{
Scsi_Device *SDpnt;
struct Scsi_Host *shpnt;
@@ -2334,60 +2333,6 @@ error_out:
return -1;
}
-
-/* This function should be called by drivers which needs to register
- * with the midlevel scsi system. As of 2.4.0-test9pre3 this is our
- * main device/hosts register function /mathiasen
- */
-int scsi_register_module(int module_type, void *ptr)
-{
- switch (module_type) {
- case MODULE_SCSI_HA:
- return scsi_register_host((Scsi_Host_Template *) ptr);
-
- /* Load upper level device handler of some kind */
- case MODULE_SCSI_DEV:
-#ifdef CONFIG_KMOD
- if (scsi_hosts == NULL)
- request_module("scsi_hostadapter");
-#endif
- return scsi_register_device_module((struct Scsi_Device_Template *) ptr);
- /* The rest of these are not yet implemented */
-
- /* Load constants.o */
- case MODULE_SCSI_CONST:
-
- /* Load specialized ioctl handler for some device. Intended for
- * cdroms that have non-SCSI2 audio command sets. */
- case MODULE_SCSI_IOCTL:
-
- default:
- return 1;
- }
-}
-
-/* Reverse the actions taken above
- */
-int scsi_unregister_module(int module_type, void *ptr)
-{
- int retval = 0;
-
- switch (module_type) {
- case MODULE_SCSI_HA:
- retval = scsi_unregister_host((Scsi_Host_Template *) ptr);
- break;
- case MODULE_SCSI_DEV:
- retval = scsi_unregister_device((struct Scsi_Device_Template *)ptr);
- break;
- /* The rest of these are not yet implemented. */
- case MODULE_SCSI_CONST:
- case MODULE_SCSI_IOCTL:
- break;
- default:;
- }
- return retval;
-}
-
#ifdef CONFIG_PROC_FS
/*
* Function: scsi_dump_status
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
index 5c2a7e182..e45098075 100644
--- a/drivers/scsi/scsi.h
+++ b/drivers/scsi/scsi.h
@@ -434,7 +434,7 @@ extern void scsi_sleep(int);
/*
* Prototypes for functions in scsicam.c
*/
-extern int scsi_partsize(struct buffer_head *bh, unsigned long capacity,
+extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds,
unsigned int *secs);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 4d4a6abc4..0188aaa2f 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -83,7 +83,6 @@ static void __scsi_insert_special(request_queue_t *q, struct request *rq,
rq->q = NULL;
rq->bio = rq->biotail = NULL;
rq->nr_phys_segments = 0;
- rq->elevator_sequence = 0;
/*
* We have the option of inserting the head or the tail of the queue.
@@ -92,7 +91,7 @@ static void __scsi_insert_special(request_queue_t *q, struct request *rq,
* device, or a host that is unable to accept a particular command.
*/
spin_lock_irqsave(q->queue_lock, flags);
- __elv_add_request(q, rq, !at_head, 0);
+ _elv_add_request(q, rq, !at_head, 0);
q->request_fn(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
@@ -262,7 +261,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
* the bad sector.
*/
SCpnt->request.special = (void *) SCpnt;
- __elv_add_request(q, &SCpnt->request, 0, 0);
+ _elv_add_request(q, &SCpnt->request, 0, 0);
}
/*
@@ -385,7 +384,7 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
if (req->waiting)
complete(req->waiting);
- add_blkdev_randomness(MAJOR(req->rq_dev));
+ add_blkdev_randomness(major(req->rq_dev));
/*
* This will goose the queue request function at the end, so we don't
@@ -718,7 +717,7 @@ struct Scsi_Device_Template *scsi_get_request_dev(struct request *req)
{
struct Scsi_Device_Template *spnt;
kdev_t dev = req->rq_dev;
- int major = MAJOR(dev);
+ int major = major(dev);
for (spnt = scsi_devicelist; spnt; spnt = spnt->next) {
/*
diff --git a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c
index c14a8eef7..efb2ca75d 100644
--- a/drivers/scsi/scsi_module.c
+++ b/drivers/scsi/scsi_module.c
@@ -35,17 +35,17 @@
static int __init init_this_scsi_driver(void)
{
driver_template.module = THIS_MODULE;
- scsi_register_module(MODULE_SCSI_HA, &driver_template);
+ scsi_register_host(&driver_template);
if (driver_template.present)
return 0;
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ scsi_unregister_host(&driver_template);
return -ENODEV;
}
static void __exit exit_this_scsi_driver(void)
{
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ scsi_unregister_host(&driver_template);
}
module_init(init_this_scsi_driver);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 9cd871b0c..aede1a6a9 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -155,11 +155,14 @@ static struct dev_info device_list[] =
{"EMC", "SYMMETRIX", "*", BLIST_SPARSELUN},
{"CMD", "CRA-7280", "*", BLIST_SPARSELUN}, // CMD RAID Controller
{"CNSI", "G7324", "*", BLIST_SPARSELUN}, // Chaparral G7324 RAID
+ {"CNSi", "G8324", "*", BLIST_SPARSELUN}, // Chaparral G8324 RAID
{"Zzyzx", "RocketStor 500S", "*", BLIST_SPARSELUN},
{"Zzyzx", "RocketStor 2000", "*", BLIST_SPARSELUN},
{"SONY", "TSL", "*", BLIST_FORCELUN}, // DDS3 & DDS4 autoloaders
{"DELL", "PERCRAID", "*", BLIST_FORCELUN},
{"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
+ {"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN},
+ {"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN},
/*
* Must be at end of list...
diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
index dbe14bacb..8f511d1a5 100644
--- a/drivers/scsi/scsi_syms.c
+++ b/drivers/scsi/scsi_syms.c
@@ -31,12 +31,15 @@
* This source file contains the symbol table used by scsi loadable
* modules.
*/
-EXPORT_SYMBOL(scsi_register_module);
-EXPORT_SYMBOL(scsi_unregister_module);
+EXPORT_SYMBOL(scsi_register_device);
+EXPORT_SYMBOL(scsi_unregister_device);
+EXPORT_SYMBOL(scsi_register_host);
+EXPORT_SYMBOL(scsi_unregister_host);
EXPORT_SYMBOL(scsi_register);
EXPORT_SYMBOL(scsi_unregister);
EXPORT_SYMBOL(scsicam_bios_param);
EXPORT_SYMBOL(scsi_partsize);
+EXPORT_SYMBOL(scsi_bios_ptable);
EXPORT_SYMBOL(scsi_allocate_device);
EXPORT_SYMBOL(scsi_do_cmd);
EXPORT_SYMBOL(scsi_command_size);
diff --git a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c
index 77c784687..367d9716a 100644
--- a/drivers/scsi/scsicam.c
+++ b/drivers/scsi/scsicam.c
@@ -26,6 +26,22 @@
static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds,
unsigned int *secs);
+unsigned char *scsi_bios_ptable(kdev_t dev)
+{
+ unsigned char *res = kmalloc(66, GFP_KERNEL);
+ kdev_t rdev = mk_kdev(major(dev), minor(dev) & ~0x0f);
+
+ if (res) {
+ struct buffer_head *bh = bread(rdev, 0, block_size(rdev));
+ if (bh) {
+ memcpy(res, bh->b_data + 0x1be, 66);
+ } else {
+ kfree(res);
+ res = NULL;
+ }
+ }
+ return res;
+}
/*
* Function : int scsicam_bios_param (Disk *disk, int dev, int *ip)
@@ -42,18 +58,18 @@ int scsicam_bios_param(Disk * disk, /* SCSI disk */
kdev_t dev, /* Device major, minor */
int *ip /* Heads, sectors, cylinders in that order */ )
{
- struct buffer_head *bh;
int ret_code;
int size = disk->capacity;
unsigned long temp_cyl;
+ unsigned char *p = scsi_bios_ptable(dev);
- if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev))))
+ if (!p)
return -1;
/* try to infer mapping from partition table */
- ret_code = scsi_partsize(bh, (unsigned long) size, (unsigned int *) ip + 2,
+ ret_code = scsi_partsize(p, (unsigned long) size, (unsigned int *) ip + 2,
(unsigned int *) ip + 0, (unsigned int *) ip + 1);
- brelse(bh);
+ kfree(p);
if (ret_code == -1) {
/* pick some standard mapping with at most 1024 cylinders,
@@ -78,7 +94,7 @@ int scsicam_bios_param(Disk * disk, /* SCSI disk */
}
/*
- * Function : static int scsi_partsize(struct buffer_head *bh, unsigned long
+ * Function : static int scsi_partsize(unsigned char *buf, unsigned long
* capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
*
* Purpose : to determine the BIOS mapping used to create the partition
@@ -88,18 +104,17 @@ int scsicam_bios_param(Disk * disk, /* SCSI disk */
*
*/
-int scsi_partsize(struct buffer_head *bh, unsigned long capacity,
+int scsi_partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds, unsigned int *secs)
{
- struct partition *p, *largest = NULL;
+ struct partition *p = (struct partition *)buf, *largest = NULL;
int i, largest_cyl;
int cyl, ext_cyl, end_head, end_cyl, end_sector;
unsigned int logical_end, physical_end, ext_physical_end;
- if (*(unsigned short *) (bh->b_data + 510) == 0xAA55) {
- for (largest_cyl = -1, p = (struct partition *)
- (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) {
+ if (*(unsigned short *) (buf + 66) == 0xAA55) {
+ for (largest_cyl = -1, i = 0; i < 4; ++i, ++p) {
if (!p->sys_ind)
continue;
#ifdef DEBUG
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 7bada9dd8..087b25b0d 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -66,7 +66,7 @@
#define SCSI_DISKS_PER_MAJOR 16
#define SD_MAJOR_NUMBER(i) SD_MAJOR((i) >> 8)
#define SD_MINOR_NUMBER(i) ((i) & 255)
-#define MKDEV_SD_PARTITION(i) MKDEV(SD_MAJOR_NUMBER(i), (i) & 255)
+#define MKDEV_SD_PARTITION(i) mk_kdev(SD_MAJOR_NUMBER(i), (i) & 255)
#define MKDEV_SD(index) MKDEV_SD_PARTITION((index) << 4)
#define N_USED_SD_MAJORS (1 + ((sd_template.dev_max - 1) >> 4))
@@ -99,6 +99,7 @@ static void sd_detach(Scsi_Device *);
static int sd_init_command(Scsi_Cmnd *);
static struct Scsi_Device_Template sd_template = {
+ module:THIS_MODULE,
name:"disk",
tag:"sd",
scsi_type:TYPE_DISK,
@@ -568,7 +569,6 @@ static struct gendisk sd_gendisk =
major: SCSI_DISK0_MAJOR,
major_name: "sd",
minor_shift: 4,
- max_p: 1 << 4,
fops: &sd_fops,
};
@@ -968,9 +968,9 @@ static int sd_init_onedisk(int i)
*/
int hard_sector = sector_size;
int sz = rscsi_disks[i].capacity * (hard_sector/256);
+ request_queue_t *queue = &rscsi_disks[i].device->request_queue;
- /* There are 16 minors allocated for each major device */
- blk_queue_hardsect_size(blk_get_queue(SD_MAJOR(i)), hard_sector);
+ blk_queue_hardsect_size(queue, hard_sector);
printk("SCSI device %s: "
"%d %d-byte hdwr sectors (%d MB)\n",
nbuff, rscsi_disks[i].capacity,
@@ -1115,7 +1115,7 @@ static int sd_init()
}
for (i = 0; i < N_USED_SD_MAJORS; i++) {
- request_queue_t *q = blk_get_queue(SD_MAJOR(i));
+ request_queue_t *q = blk_get_queue(mk_kdev(SD_MAJOR(i), 0));
int parts_per_major = (SCSI_DISKS_PER_MAJOR << 4);
blksize_size[SD_MAJOR(i)] =
@@ -1140,12 +1140,9 @@ static int sd_init()
sd_gendisks[i].major = SD_MAJOR(i);
sd_gendisks[i].major_name = "sd";
sd_gendisks[i].minor_shift = 4;
- sd_gendisks[i].max_p = 1 << 4;
sd_gendisks[i].part = sd + i * (N << 4);
sd_gendisks[i].sizes = sd_sizes + i * (N << 4);
sd_gendisks[i].nr_real = 0;
- sd_gendisks[i].real_devices =
- (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
}
return 0;
@@ -1308,7 +1305,7 @@ static void sd_detach(Scsi_Device * SDp)
for (dpnt = rscsi_disks, i = 0; i < sd_template.dev_max; i++, dpnt++)
if (dpnt->device == SDp) {
- max_p = sd_gendisk.max_p;
+ max_p = 1 << sd_gendisk.minor_shift;
start = i << sd_gendisk.minor_shift;
dev = MKDEV_SD_PARTITION(start);
wipe_partitions(dev);
@@ -1332,14 +1329,14 @@ static void sd_detach(Scsi_Device * SDp)
static int __init init_sd(void)
{
sd_template.module = THIS_MODULE;
- return scsi_register_module(MODULE_SCSI_DEV, &sd_template);
+ return scsi_register_device(&sd_template);
}
static void __exit exit_sd(void)
{
int i;
- scsi_unregister_module(MODULE_SCSI_DEV, &sd_template);
+ scsi_unregister_device(&sd_template);
for (i = 0; i < N_USED_SD_MAJORS; i++)
devfs_unregister_blkdev(SD_MAJOR(i), "sd");
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index ce9c94440..7e12f2696 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -45,7 +45,7 @@ extern kdev_t sd_find_target(void *host, int tgt);
#define N_SD_MAJORS 8
#define SD_MAJOR_MASK (N_SD_MAJORS - 1)
-#define SD_PARTITION(i) (((MAJOR(i) & SD_MAJOR_MASK) << 8) | (MINOR(i) & 255))
+#define SD_PARTITION(i) (((major(i) & SD_MAJOR_MASK) << 8) | (minor(i) & 255))
#endif
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ef1207d0a..05b5dae41 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -123,6 +123,7 @@ static rwlock_t sg_dev_arr_lock = RW_LOCK_UNLOCKED; /* Also used to lock
static struct Scsi_Device_Template sg_template =
{
+ module:THIS_MODULE,
tag:"sg",
scsi_type:0xff,
major:SCSI_GENERIC_MAJOR,
@@ -258,7 +259,7 @@ static Sg_device ** sg_dev_arr = NULL;
static int sg_open(struct inode * inode, struct file * filp)
{
- int dev = MINOR(inode->i_rdev);
+ int dev = minor(inode->i_rdev);
int flags = filp->f_flags;
Sg_device * sdp;
Sg_fd * sfp;
@@ -344,7 +345,7 @@ static int sg_release(struct inode * inode, struct file * filp)
if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) {
return -ENXIO;
}
- SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev)));
+ SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", minor(sdp->i_rdev)));
sg_fasync(-1, filp, 0); /* remove filp from async notification list */
if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */
if (! sdp->detached) {
@@ -373,7 +374,7 @@ static ssize_t sg_read(struct file * filp, char * buf,
if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n",
- MINOR(sdp->i_rdev), (int)count));
+ minor(sdp->i_rdev), (int)count));
if (ppos != &filp->f_pos)
; /* FIXME: Hmm. Seek to the right place, or fail? */
if ((k = verify_area(VERIFY_WRITE, buf, count)))
@@ -518,7 +519,7 @@ static ssize_t sg_write(struct file * filp, const char * buf,
if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n",
- MINOR(sdp->i_rdev), (int)count));
+ minor(sdp->i_rdev), (int)count));
if (sdp->detached)
return -ENODEV;
if (! ((filp->f_flags & O_NONBLOCK) ||
@@ -751,7 +752,7 @@ static int sg_ioctl(struct inode * inode, struct file * filp,
if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n",
- MINOR(sdp->i_rdev), (int)cmd_in));
+ minor(sdp->i_rdev), (int)cmd_in));
read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
switch(cmd_in)
@@ -1031,7 +1032,7 @@ static unsigned int sg_poll(struct file * filp, poll_table * wait)
else if (count < SG_MAX_QUEUE)
res |= POLLOUT | POLLWRNORM;
SCSI_LOG_TIMEOUT(3, printk("sg_poll: dev=%d, res=0x%x\n",
- MINOR(sdp->i_rdev), (int)res));
+ minor(sdp->i_rdev), (int)res));
return res;
}
@@ -1044,7 +1045,7 @@ static int sg_fasync(int fd, struct file * filp, int mode)
if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_fasync: dev=%d, mode=%d\n",
- MINOR(sdp->i_rdev), mode));
+ minor(sdp->i_rdev), mode));
retval = fasync_helper(fd, filp, mode, &sfp->async_qp);
return (retval < 0) ? retval : 0;
@@ -1185,7 +1186,7 @@ static int sg_mmap(struct file * filp, struct vm_area_struct *vma)
static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
{
Scsi_Request * SRpnt = SCpnt->sc_request;
- int dev = MINOR(SRpnt->sr_request.rq_dev);
+ int dev = minor(SRpnt->sr_request.rq_dev);
Sg_device * sdp = NULL;
Sg_fd * sfp;
Sg_request * srp = NULL;
@@ -1232,7 +1233,7 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
SRpnt->sr_bufflen = 0;
SRpnt->sr_buffer = NULL;
SRpnt->sr_underflow = 0;
- SRpnt->sr_request.rq_dev = MKDEV(0, 0); /* "sg" _disowns_ request blk */
+ SRpnt->sr_request.rq_dev = mk_kdev(0, 0); /* "sg" _disowns_ command blk */
srp->my_cmdp = NULL;
srp->done = 1;
@@ -1436,7 +1437,7 @@ static int sg_attach(Scsi_Device * scsidp)
sdp->sgdebug = 0;
sdp->detached = 0;
sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
- sdp->i_rdev = MKDEV(SCSI_GENERIC_MAJOR, k);
+ sdp->i_rdev = mk_kdev(SCSI_GENERIC_MAJOR, k);
sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT,
SCSI_GENERIC_MAJOR, k,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
@@ -1540,8 +1541,7 @@ MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
static int __init init_sg(void) {
if (def_reserved_size >= 0)
sg_big_buff = def_reserved_size;
- sg_template.module = THIS_MODULE;
- return scsi_register_module(MODULE_SCSI_DEV, &sg_template);
+ return scsi_register_device(&sg_template);
}
static void __exit exit_sg( void)
@@ -1549,7 +1549,7 @@ static void __exit exit_sg( void)
#ifdef CONFIG_PROC_FS
sg_proc_cleanup();
#endif /* CONFIG_PROC_FS */
- scsi_unregister_module(MODULE_SCSI_DEV, &sg_template);
+ scsi_unregister_device(&sg_template);
devfs_unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
if(sg_dev_arr != NULL) {
kfree((char *)sg_dev_arr);
@@ -2874,7 +2874,7 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin,
PRINT_PROC("device %d detached ??\n", j);
continue;
}
- dev = MINOR(sdp->i_rdev);
+ dev = minor(sdp->i_rdev);
if (sg_get_nth_sfp(sdp, 0)) {
PRINT_PROC(" >>> device=sg%d ", dev);
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index 142b03a84..c208ecf4b 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -904,11 +904,12 @@ handle_script_int(struct Scsi_Host * host, Scsi_Cmnd * cmd)
static void
do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
{
+ struct Scsi_Host *host = dev_id;
unsigned long flags;
- spin_lock_irqsave(&io_request_lock, flags);
- sim710_intr_handle(irq, dev_id, regs);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_lock_irqsave(&host->host_lock, flags);
+ sim710_intr_handle(irq, host, regs);
+ spin_unlock_irqrestore(&host->host_lock, flags);
}
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 9624acc7f..660cf3bc6 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -71,6 +71,7 @@ static int sr_init_command(Scsi_Cmnd *);
static struct Scsi_Device_Template sr_template =
{
+ module:THIS_MODULE,
name:"cdrom",
tag:"sr",
scsi_type:TYPE_ROM,
@@ -98,11 +99,11 @@ static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *)
static void sr_release(struct cdrom_device_info *cdi)
{
- if (scsi_CDs[MINOR(cdi->dev)].device->sector_size > 2048)
- sr_set_blocklength(MINOR(cdi->dev), 2048);
- scsi_CDs[MINOR(cdi->dev)].device->access_count--;
- if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module)
- __MOD_DEC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module);
+ if (scsi_CDs[minor(cdi->dev)].device->sector_size > 2048)
+ sr_set_blocklength(minor(cdi->dev), 2048);
+ scsi_CDs[minor(cdi->dev)].device->access_count--;
+ if (scsi_CDs[minor(cdi->dev)].device->host->hostt->module)
+ __MOD_DEC_USE_COUNT(scsi_CDs[minor(cdi->dev)].device->host->hostt->module);
if (sr_template.module)
__MOD_DEC_USE_COUNT(sr_template.module);
}
@@ -149,7 +150,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
/* no changer support */
return -EINVAL;
}
- retval = scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
+ retval = scsi_ioctl(scsi_CDs[minor(cdi->dev)].device,
SCSI_IOCTL_TEST_UNIT_READY, 0);
if (retval) {
@@ -158,13 +159,13 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
* and we will figure it out later once the drive is
* available again. */
- scsi_CDs[MINOR(cdi->dev)].device->changed = 1;
+ scsi_CDs[minor(cdi->dev)].device->changed = 1;
return 1; /* This will force a flush, if called from
* check_disk_change */
};
- retval = scsi_CDs[MINOR(cdi->dev)].device->changed;
- scsi_CDs[MINOR(cdi->dev)].device->changed = 0;
+ retval = scsi_CDs[minor(cdi->dev)].device->changed;
+ scsi_CDs[minor(cdi->dev)].device->changed = 0;
/* If the disk changed, the capacity will now be different,
* so we force a re-read of this information */
if (retval) {
@@ -178,9 +179,9 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
* be trying to use something that is too small if the disc
* has changed.
*/
- scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
+ scsi_CDs[minor(cdi->dev)].needs_sector_size = 1;
- scsi_CDs[MINOR(cdi->dev)].device->sector_size = 2048;
+ scsi_CDs[minor(cdi->dev)].device->sector_size = 2048;
}
return retval;
}
@@ -252,17 +253,17 @@ static request_queue_t *sr_find_queue(kdev_t dev)
/*
* No such device
*/
- if (MINOR(dev) >= sr_template.dev_max || !scsi_CDs[MINOR(dev)].device)
+ if (minor(dev) >= sr_template.dev_max || !scsi_CDs[minor(dev)].device)
return NULL;
- return &scsi_CDs[MINOR(dev)].device->request_queue;
+ return &scsi_CDs[minor(dev)].device->request_queue;
}
static int sr_init_command(Scsi_Cmnd * SCpnt)
{
int dev, devm, block=0, this_count, s_size;
- devm = MINOR(SCpnt->request.rq_dev);
+ devm = minor(SCpnt->request.rq_dev);
dev = DEVICE_NR(SCpnt->request.rq_dev);
SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
@@ -398,20 +399,20 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose)
{
check_disk_change(cdi->dev);
- if (MINOR(cdi->dev) >= sr_template.dev_max
- || !scsi_CDs[MINOR(cdi->dev)].device) {
+ if (minor(cdi->dev) >= sr_template.dev_max
+ || !scsi_CDs[minor(cdi->dev)].device) {
return -ENXIO; /* No such device */
}
/*
* If the device is in error recovery, wait until it is done.
* If the device is offline, then disallow any access to it.
*/
- if (!scsi_block_when_processing_errors(scsi_CDs[MINOR(cdi->dev)].device)) {
+ if (!scsi_block_when_processing_errors(scsi_CDs[minor(cdi->dev)].device)) {
return -ENXIO;
}
- scsi_CDs[MINOR(cdi->dev)].device->access_count++;
- if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module)
- __MOD_INC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module);
+ scsi_CDs[minor(cdi->dev)].device->access_count++;
+ if (scsi_CDs[minor(cdi->dev)].device->host->hostt->module)
+ __MOD_INC_USE_COUNT(scsi_CDs[minor(cdi->dev)].device->host->hostt->module);
if (sr_template.module)
__MOD_INC_USE_COUNT(sr_template.module);
@@ -420,8 +421,8 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose)
* this is the case, and try again.
*/
- if (scsi_CDs[MINOR(cdi->dev)].needs_sector_size)
- get_sectorsize(MINOR(cdi->dev));
+ if (scsi_CDs[minor(cdi->dev)].needs_sector_size)
+ get_sectorsize(minor(cdi->dev));
return 0;
}
@@ -474,6 +475,7 @@ void get_sectorsize(int i)
int the_result, retries;
int sector_size;
Scsi_Request *SRpnt;
+ request_queue_t *queue;
buffer = (unsigned char *) kmalloc(512, GFP_DMA);
SRpnt = scsi_allocate_request(scsi_CDs[i].device);
@@ -563,8 +565,9 @@ void get_sectorsize(int i)
*/
scsi_CDs[i].needs_sector_size = 0;
sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
- };
- blk_queue_hardsect_size(blk_get_queue(MAJOR_NR), sector_size);
+ }
+ queue = &scsi_CDs[i].device->request_queue;
+ blk_queue_hardsect_size(queue, sector_size);
kfree(buffer);
}
@@ -668,13 +671,13 @@ void get_capabilities(int i)
*/
static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc)
{
- Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;
+ Scsi_Device *device = scsi_CDs[minor(cdi->dev)].device;
/* set the LUN */
if (device->scsi_level <= SCSI_2)
cgc->cmd[1] |= device->lun << 5;
- cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
+ cgc->stat = sr_do_ioctl(minor(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
return cgc->stat;
}
@@ -763,7 +766,7 @@ void sr_finish()
scsi_CDs[i].cdi.ops = &sr_dops;
scsi_CDs[i].cdi.handle = &scsi_CDs[i];
- scsi_CDs[i].cdi.dev = MKDEV(MAJOR_NR, i);
+ scsi_CDs[i].cdi.dev = mk_kdev(MAJOR_NR, i);
scsi_CDs[i].cdi.mask = 0;
scsi_CDs[i].cdi.capacity = 1;
/*
@@ -806,7 +809,7 @@ static void sr_detach(Scsi_Device * SDp)
* the device.
* We should be kind to our buffer cache, however.
*/
- invalidate_device(MKDEV(MAJOR_NR, i), 0);
+ invalidate_device(mk_kdev(MAJOR_NR, i), 0);
/*
* Reset things back to a sane state so that one can
@@ -826,13 +829,12 @@ static void sr_detach(Scsi_Device * SDp)
static int __init init_sr(void)
{
- sr_template.module = THIS_MODULE;
- return scsi_register_module(MODULE_SCSI_DEV, &sr_template);
+ return scsi_register_device(&sr_template);
}
static void __exit exit_sr(void)
{
- scsi_unregister_module(MODULE_SCSI_DEV, &sr_template);
+ scsi_unregister_device(&sr_template);
devfs_unregister_blkdev(MAJOR_NR, "sr");
sr_registered--;
if (scsi_CDs != NULL) {
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index da3ec60fe..6d76a4f22 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -68,7 +68,7 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
sr_cmd[6] = trk1_te.cdte_addr.msf.minute;
sr_cmd[7] = trk1_te.cdte_addr.msf.second;
sr_cmd[8] = trk1_te.cdte_addr.msf.frame;
- return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+ return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
}
/* We do our own retries because we want to know what the specific
@@ -206,17 +206,17 @@ int sr_tray_move(struct cdrom_device_info *cdi, int pos)
u_char sr_cmd[10];
sr_cmd[0] = GPCMD_START_STOP_UNIT;
- sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
- ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+ sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+ ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
- return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+ return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
}
int sr_lock_door(struct cdrom_device_info *cdi, int lock)
{
- return scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
+ return scsi_ioctl(scsi_CDs[minor(cdi->dev)].device,
lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
0);
}
@@ -227,7 +227,7 @@ int sr_drive_status(struct cdrom_device_info *cdi, int slot)
/* we have no changer support */
return -EINVAL;
}
- if (0 == test_unit_ready(MINOR(cdi->dev)))
+ if (0 == test_unit_ready(minor(cdi->dev)))
return CDS_DISC_OK;
return CDS_TRAY_OPEN;
@@ -256,7 +256,7 @@ int sr_disk_status(struct cdrom_device_info *cdi)
if (!have_datatracks)
return CDS_AUDIO;
- if (scsi_CDs[MINOR(cdi->dev)].xa_flag)
+ if (scsi_CDs[minor(cdi->dev)].xa_flag)
return CDS_XA_2_1;
else
return CDS_DATA_1;
@@ -265,9 +265,9 @@ int sr_disk_status(struct cdrom_device_info *cdi)
int sr_get_last_session(struct cdrom_device_info *cdi,
struct cdrom_multisession *ms_info)
{
- ms_info->addr.lba = scsi_CDs[MINOR(cdi->dev)].ms_offset;
- ms_info->xa_flag = scsi_CDs[MINOR(cdi->dev)].xa_flag ||
- (scsi_CDs[MINOR(cdi->dev)].ms_offset > 0);
+ ms_info->addr.lba = scsi_CDs[minor(cdi->dev)].ms_offset;
+ ms_info->xa_flag = scsi_CDs[minor(cdi->dev)].xa_flag ||
+ (scsi_CDs[minor(cdi->dev)].ms_offset > 0);
return 0;
}
@@ -279,8 +279,8 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
int result;
sr_cmd[0] = GPCMD_READ_SUBCHANNEL;
- sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
- ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+ sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+ ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
sr_cmd[2] = 0x40; /* I do want the subchannel info */
sr_cmd[3] = 0x02; /* Give me medium catalog number info */
sr_cmd[4] = sr_cmd[5] = 0;
@@ -289,7 +289,7 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
sr_cmd[8] = 24;
sr_cmd[9] = 0;
- result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
+ result = sr_do_ioctl(minor(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
memcpy(mcn->medium_catalog_number, buffer + 9, 13);
mcn->medium_catalog_number[13] = 0;
@@ -314,12 +314,12 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
memset(sr_cmd, 0, MAX_COMMAND_SIZE);
sr_cmd[0] = GPCMD_SET_SPEED; /* SET CD SPEED */
- sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->scsi_level <= SCSI_2) ?
- ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5) : 0;
+ sr_cmd[1] = (scsi_CDs[minor(cdi->dev)].device->scsi_level <= SCSI_2) ?
+ ((scsi_CDs[minor(cdi->dev)].device->lun) << 5) : 0;
sr_cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */
sr_cmd[3] = speed & 0xff; /* LSB */
- if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
+ if (sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
return -EIO;
return 0;
}
@@ -333,7 +333,7 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
{
u_char sr_cmd[10];
- int result, target = MINOR(cdi->dev);
+ int result, target = minor(cdi->dev);
unsigned char buffer[32];
memset(sr_cmd, 0, sizeof(sr_cmd));
@@ -541,7 +541,7 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
{
int target;
- target = MINOR(cdi->dev);
+ target = minor(cdi->dev);
switch (cmd) {
case BLKGETSIZE:
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index a1d4a7db4..1a030a49b 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -158,7 +158,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
unsigned char cmd[MAX_COMMAND_SIZE]; /* the scsi-command */
int rc, no_multi, minor;
- minor = MINOR(cdi->dev);
+ minor = minor(cdi->dev);
if (scsi_CDs[minor].cdi.mask & CDC_MULTI_SESSION)
return 0;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index ce4330c8e..a8292a04e 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -133,8 +133,8 @@ DEB( static int debugging = DEBUG; )
#define ST_TIMEOUT (900 * HZ)
#define ST_LONG_TIMEOUT (14000 * HZ)
-#define TAPE_NR(x) (MINOR(x) & ~(128 | ST_MODE_MASK))
-#define TAPE_MODE(x) ((MINOR(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
+#define TAPE_NR(x) (minor(x) & ~(-1 << ST_MODE_SHIFT))
+#define TAPE_MODE(x) ((minor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
24 bits) */
@@ -878,7 +878,7 @@ static int st_open(struct inode *inode, struct file *filp)
}
STp->in_use = 1;
write_unlock_irqrestore(&st_dev_arr_lock, flags);
- STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0;
+ STp->rew_at_close = STp->autorew_dev = (minor(inode->i_rdev) & 0x80) == 0;
if (STp->device->host->hostt->module)
__MOD_INC_USE_COUNT(STp->device->host->hostt->module);
@@ -3713,7 +3713,7 @@ static int st_attach(Scsi_Device * SDp)
tpnt->tape_type = MT_ISSCSI2;
tpnt->inited = 0;
- tpnt->devt = MKDEV(SCSI_TAPE_MAJOR, i);
+ tpnt->devt = mk_kdev(SCSI_TAPE_MAJOR, i);
tpnt->dirty = 0;
tpnt->in_use = 0;
tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
@@ -3863,14 +3863,14 @@ static int __init init_st(void)
validate_options();
st_template.module = THIS_MODULE;
- return scsi_register_module(MODULE_SCSI_DEV, &st_template);
+ return scsi_register_device(&st_template);
}
static void __exit exit_st(void)
{
int i;
- scsi_unregister_module(MODULE_SCSI_DEV, &st_template);
+ scsi_unregister_device(&st_template);
devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
st_registered--;
if (scsi_tapes != NULL) {
diff --git a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h
index ec4f1cc41..9fde4ab6b 100644
--- a/drivers/scsi/sym53c8xx_comm.h
+++ b/drivers/scsi/sym53c8xx_comm.h
@@ -438,10 +438,10 @@ spinlock_t DRIVER_SMP_LOCK = SPIN_LOCK_UNLOCKED;
#define NCR_LOCK_NCB(np, flags) spin_lock_irqsave(&np->smp_lock, flags)
#define NCR_UNLOCK_NCB(np, flags) spin_unlock_irqrestore(&np->smp_lock, flags)
-#define NCR_LOCK_SCSI_DONE(np, flags) \
- spin_lock_irqsave(&io_request_lock, flags)
-#define NCR_UNLOCK_SCSI_DONE(np, flags) \
- spin_unlock_irqrestore(&io_request_lock, flags)
+#define NCR_LOCK_SCSI_DONE(host, flags) \
+ spin_lock_irqsave(&(host)->host_lock, flags)
+#define NCR_UNLOCK_SCSI_DONE(host, flags) \
+ spin_unlock_irqrestore(&((host)->host_lock), flags)
#else
@@ -452,8 +452,8 @@ spinlock_t DRIVER_SMP_LOCK = SPIN_LOCK_UNLOCKED;
#define NCR_LOCK_NCB(np, flags) do { save_flags(flags); cli(); } while (0)
#define NCR_UNLOCK_NCB(np, flags) do { restore_flags(flags); } while (0)
-#define NCR_LOCK_SCSI_DONE(np, flags) do {;} while (0)
-#define NCR_UNLOCK_SCSI_DONE(np, flags) do {;} while (0)
+#define NCR_LOCK_SCSI_DONE(host, flags) do {;} while (0)
+#define NCR_UNLOCK_SCSI_DONE(host, flags) do {;} while (0)
#endif
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 1847ca48a..eef872ae6 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -1371,7 +1371,7 @@ int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
#include <asm/unaligned.h>
/*
- * Function : static int partsize(struct buffer_head *bh, unsigned long
+ * Function : static int partsize(unsigned char *buf, unsigned long
* capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
*
* Purpose : to determine the BIOS mapping used to create the partition
@@ -1381,7 +1381,7 @@ int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
*
*/
-static int partsize(struct buffer_head *bh, unsigned long capacity,
+static int partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds, unsigned int *secs) {
struct partition *p, *largest = NULL;
int i, largest_cyl;
@@ -1389,9 +1389,9 @@ static int partsize(struct buffer_head *bh, unsigned long capacity,
unsigned int logical_end, physical_end, ext_physical_end;
- if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
- for (largest_cyl = -1, p = (struct partition *)
- (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) {
+ if (*(unsigned short *) (buf+64) == 0xAA55) {
+ for (largest_cyl = -1, p = (struct partition *) buf,
+ i = 0; i < 4; ++i, ++p) {
if (!p->sys_ind)
continue;
cyl = p->cyl + ((p->sector & 0xc0) << 2);
@@ -1446,16 +1446,16 @@ int DC390_bios_param (Disk *disk, kdev_t devno, int geom[])
{
int heads, sectors, cylinders;
PACB pACB = (PACB) disk->device->host->hostdata;
- struct buffer_head *bh;
int ret_code = -1;
int size = disk->capacity;
+ unsigned char *buf;
- if ((bh = bread(MKDEV(MAJOR(devno), MINOR(devno)&~0xf), 0, block_size(devno))))
+ if ((buf = scsi_bios_ptable(devno)))
{
/* try to infer mapping from partition table */
- ret_code = partsize (bh, (unsigned long) size, (unsigned int *) geom + 2,
+ ret_code = partsize (buf, (unsigned long) size, (unsigned int *) geom + 2,
(unsigned int *) geom + 0, (unsigned int *) geom + 1);
- brelse (bh);
+ kfree (buf);
}
if (ret_code == -1)
{
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index bc30c95b5..328598332 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1,6 +1,13 @@
/*
* u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
*
+ * 01 Jan 2002 Rev. 7.20 for linux 2.5.1
+ * + Use the dynamic DMA mapping API.
+ *
+ * 19 Dec 2001 Rev. 7.02 for linux 2.5.1
+ * + Use SCpnt->sc_data_direction if set.
+ * + Use sglist.page instead of sglist.address.
+ *
* 11 Dec 2001 Rev. 7.00 for linux 2.5.1
* + Use host->host_lock instead of io_request_lock.
*
@@ -186,7 +193,7 @@
*
* Multiple U14F and/or U34F host adapters are supported.
*
- * Copyright (C) 1994-2001 Dario Ballabio (ballabio_dario@emc.com)
+ * Copyright (C) 1994-2002 Dario Ballabio (ballabio_dario@emc.com)
*
* Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
*
@@ -377,6 +384,7 @@ MODULE_AUTHOR("Dario Ballabio");
#include "u14-34f.h"
#include <linux/stat.h>
#include <linux/config.h>
+#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/spinlock.h>
@@ -483,13 +491,13 @@ struct mscp {
unsigned char clink_id; /* identifies command in chain */
unsigned char use_sg; /* (if sg is set) 8 bytes per list */
unsigned char sense_len;
- unsigned char scsi_cdbs_len; /* 6, 10, or 12 */
- unsigned char scsi_cdbs[12]; /* SCSI commands */
+ unsigned char cdb_len; /* 6, 10, or 12 */
+ unsigned char cdb[12]; /* SCSI Command Descriptor Block */
unsigned char adapter_status; /* non-zero indicates HA error */
unsigned char target_status; /* non-zero indicates target error */
unsigned int sense_addr PACKED;
Scsi_Cmnd *SCpnt;
- unsigned int index; /* cp index */
+ unsigned int cpp_index; /* cp index */
struct sg_list *sglist;
};
@@ -507,6 +515,7 @@ struct hostdata {
unsigned int retries; /* Number of internal retries */
unsigned long last_retried_pid; /* Pid of last retried command */
unsigned char subversion; /* Bus type, either ISA or ESA */
+ struct pci_dev *pdev; /* Always NULL */
unsigned char heads;
unsigned char sectors;
@@ -537,19 +546,10 @@ static unsigned long io_port[] = {
#define HD(board) ((struct hostdata *) &sh[board]->hostdata)
#define BN(board) (HD(board)->board_name)
-#define SWAP_BYTE(x) ((unsigned long)( \
- (((unsigned long)(x) & 0x000000ffU) << 24) | \
- (((unsigned long)(x) & 0x0000ff00U) << 8) | \
- (((unsigned long)(x) & 0x00ff0000U) >> 8) | \
- (((unsigned long)(x) & 0xff000000U) >> 24)))
-
-#if defined(__BIG_ENDIAN)
-#define H2DEV(x) SWAP_BYTE(x)
-#else
-#define H2DEV(x) (x)
-#endif
+/* Device is Little Endian */
+#define H2DEV(x) cpu_to_le32(x)
+#define DEV2H(x) le32_to_cpu(x)
-#define DEV2H(x) H2DEV(x)
#define V2DEV(addr) ((addr) ? H2DEV(isa_virt_to_bus((void *)addr)) : 0)
#define DEV2V(addr) ((addr) ? DEV2H(isa_bus_to_virt((unsigned long)addr)) : 0)
@@ -653,8 +653,8 @@ static int board_inquiry(unsigned int j) {
cpp->xdir = DTD_IN;
cpp->data_address = V2DEV(HD(j)->board_id);
cpp->data_len = H2DEV(sizeof(HD(j)->board_id));
- cpp->scsi_cdbs_len = 6;
- cpp->scsi_cdbs[0] = HA_CMD_INQUIRY;
+ cpp->cdb_len = 6;
+ cpp->cdb[0] = HA_CMD_INQUIRY;
if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
printk("%s: board_inquiry, adapter busy.\n", BN(j));
@@ -832,14 +832,14 @@ static inline int port_detect \
unsigned long flags;
scsi_register_blocked_host(sh[j]);
sh[j]->unchecked_isa_dma = TRUE;
-
+
flags=claim_dma_lock();
disable_dma(dma_channel);
clear_dma_ff(dma_channel);
set_dma_mode(dma_channel, DMA_MODE_CASCADE);
enable_dma(dma_channel);
release_dma_lock(flags);
-
+
sh[j]->dma_channel = dma_channel;
sprintf(BN(j), "U14F%d", j);
bus_type = "ISA";
@@ -879,7 +879,7 @@ static inline int port_detect \
if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
if (j == 0) {
- printk("UltraStor 14F/34F: Copyright (C) 1994-2001 Dario Ballabio.\n");
+ printk("UltraStor 14F/34F: Copyright (C) 1994-2002 Dario Ballabio.\n");
printk("%s config options -> of:%c, lc:%c, mq:%d, et:%c.\n",
driver_name, YESNO(have_old_firmware), YESNO(linked_comm),
max_queue_depth, YESNO(ext_tran));
@@ -949,8 +949,7 @@ static int option_setup(char *str) {
return 1;
}
-int u14_34f_detect(Scsi_Host_Template *tpnt)
-{
+int u14_34f_detect(Scsi_Host_Template *tpnt) {
unsigned int j = 0, k;
tpnt->proc_name = "u14-34f";
@@ -1008,9 +1007,51 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
static const unsigned char data_none_cmds[] = {
0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e,
0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47,
- 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5
+ 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00
};
+ struct mscp *cpp;
+ Scsi_Cmnd *SCpnt;
+
+ cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
+
+ if (SCpnt->sc_data_direction == SCSI_DATA_READ) {
+ cpp->xdir = DTD_IN;
+ return;
+ }
+ else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) {
+ cpp->xdir = DTD_OUT;
+ return;
+ }
+ else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) {
+ cpp->xdir = DTD_NONE;
+ return;
+ }
+
+ if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN)
+ panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
+
+ cpp->xdir = DTD_IN;
+
+ for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
+ if (SCpnt->cmnd[0] == data_out_cmds[k]) {
+ cpp->xdir = DTD_OUT;
+ break;
+ }
+
+ if (cpp->xdir == DTD_IN)
+ for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
+ if (SCpnt->cmnd[0] == data_none_cmds[k]) {
+ cpp->xdir = DTD_NONE;
+ break;
+ }
+
+}
+
+static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
+ unsigned int i, j, k;
+ struct mscp *cpp;
+
/* j is the board number */
j = ((struct hostdata *) SCpnt->host->hostdata)->board_number;
@@ -1042,47 +1083,26 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
SCpnt->scsi_done = done;
- cpp->index = i;
- SCpnt->host_scribble = (unsigned char *) &cpp->index;
+ cpp->cpp_index = i;
+ SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index;
if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
BN(j), i, SCpnt->channel, SCpnt->target,
SCpnt->lun, SCpnt->pid);
- cpp->xdir = DTD_IN;
-
- for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
- if (SCpnt->cmnd[0] == data_out_cmds[k]) {
- cpp->xdir = DTD_OUT;
- break;
- }
-
- if (cpp->xdir == DTD_IN)
- for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
- if (SCpnt->cmnd[0] == data_none_cmds[k]) {
- cpp->xdir = DTD_NONE;
- break;
- }
-
cpp->opcode = OP_SCSI;
cpp->channel = SCpnt->channel;
cpp->target = SCpnt->target;
cpp->lun = SCpnt->lun;
cpp->SCpnt = SCpnt;
- cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
- cpp->sense_len = sizeof SCpnt->sense_buffer;
+ cpp->cdb_len = SCpnt->cmd_len;
+ memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
- if (SCpnt->use_sg) {
- cpp->sg = TRUE;
- build_sg_list(cpp, SCpnt);
- }
- else {
- cpp->data_address = V2DEV(SCpnt->request_buffer);
- cpp->data_len = H2DEV(SCpnt->request_bufflen);
- }
+ /* Use data transfer direction SCpnt->sc_data_direction */
+ scsi_to_dev_dir(i, j);
- cpp->scsi_cdbs_len = SCpnt->cmd_len;
- memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len);
+ /* Map DMA buffers and SG list */
+ map_dma(i, j);
if (linked_comm && SCpnt->device->queue_depth > 2
&& TLDEV(SCpnt->device->type)) {
@@ -1092,6 +1112,7 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
}
if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+ unmap_dma(i, j);
SCpnt->host_scribble = NULL;
printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
@@ -1154,6 +1175,7 @@ static inline int do_abort(Scsi_Cmnd *SCarg) {
printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
if (SCarg->eh_state == SCSI_STATE_TIMEOUT) {
+ unmap_dma(i, j);
SCarg->host_scribble = NULL;
HD(j)->cp_stat[i] = FREE;
printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n",
@@ -1175,6 +1197,7 @@ static inline int do_abort(Scsi_Cmnd *SCarg) {
}
if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
+ unmap_dma(i, j);
SCarg->result = DID_ABORT << 16;
SCarg->host_scribble = NULL;
HD(j)->cp_stat[i] = FREE;
@@ -1272,18 +1295,19 @@ static inline int do_reset(Scsi_Cmnd *SCarg) {
#endif
HD(j)->in_reset = TRUE;
-
+
spin_unlock_irq(&sh[j]->host_lock);
time = jiffies;
while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
spin_lock_irq(&sh[j]->host_lock);
-
+
printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
for (i = 0; i < sh[j]->can_queue; i++) {
if (HD(j)->cp_stat[i] == IN_RESET) {
SCpnt = HD(j)->cp[i].SCpnt;
+ unmap_dma(i, j);
SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL;
@@ -1296,6 +1320,7 @@ static inline int do_reset(Scsi_Cmnd *SCarg) {
else if (HD(j)->cp_stat[i] == ABORTING) {
SCpnt = HD(j)->cp[i].SCpnt;
+ unmap_dma(i, j);
SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL;
@@ -1536,23 +1561,25 @@ static inline void ihdlr(int irq, unsigned int j) {
return;
}
- spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
- cpp = spp;
+ ret = inl(sh[j]->io_port + REG_ICM);
/* Clear interrupt pending flag */
outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
-#if defined(DEBUG_GENERATE_ABORTS)
- if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return;
-#endif
-
/* Find the mailbox to be serviced on this board */
- i = cpp - HD(j)->cp;
+ for (i = 0; i < sh[j]->can_queue; i++)
+ if (V2DEV(&(HD(j)->cp[i])) == ret) break;
- if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
- || i >= sh[j]->can_queue)
+ if (i >= sh[j]->can_queue)
panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
- (void *)ret, HD(j)->cp);
+ (void *)ret, (void *)V2DEV(HD(j)->cp));
+
+ cpp = &(HD(j)->cp[i]);
+ spp = cpp;
+
+#if defined(DEBUG_GENERATE_ABORTS)
+ if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return;
+#endif
if (HD(j)->cp_stat[i] == IGNORE) {
HD(j)->cp_stat[i] = FREE;
@@ -1588,6 +1615,8 @@ static inline void ihdlr(int irq, unsigned int j) {
panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
+ sync_dma(i, j);
+
if (linked_comm && SCpnt->device->queue_depth > 2
&& TLDEV(SCpnt->device->type))
flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
@@ -1705,6 +1734,8 @@ static inline void ihdlr(int irq, unsigned int j) {
SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
reg, HD(j)->iocount);
+ unmap_dma(i, j);
+
/* Set the command state to inactive */
SCpnt->host_scribble = NULL;
@@ -1736,9 +1767,7 @@ int u14_34f_release(struct Scsi_Host *shpnt) {
if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
driver_name);
- if( sh[j]->unchecked_isa_dma ) {
- scsi_deregister_blocked_host(sh[j]);
- }
+ if(sh[j]->unchecked_isa_dma) scsi_deregister_blocked_host(sh[j]);
for (i = 0; i < sh[j]->can_queue; i++)
if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
diff --git a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h
index d8d1d400f..a044c2b45 100644
--- a/drivers/scsi/u14-34f.h
+++ b/drivers/scsi/u14-34f.h
@@ -13,7 +13,7 @@ int u14_34f_abort(Scsi_Cmnd *);
int u14_34f_reset(Scsi_Cmnd *);
int u14_34f_biosparam(Disk *, kdev_t, int *);
-#define U14_34F_VERSION "7.00.00"
+#define U14_34F_VERSION "7.20.00"
#define ULTRASTOR_14_34F { \
name: "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index 7ecb62ce1..bdfd886b6 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -140,6 +140,11 @@
* 03/01/1998
*
* WD7000 driver now work on kernels >= 2.1.x
+ *
+ *
+ * 12/31/2001 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * use host->host_lock, not io_request_lock, cleanups
*/
#include <linux/module.h>
@@ -166,6 +171,11 @@
#define ANY2SCSI_INLINE /* undef this to use old macros */
#undef WD7000_DEBUG /* general debug */
+#ifdef WD7000_DEBUG
+#define dprintk printk
+#else
+#define dprintk(format,args...)
+#endif
#include "wd7000.h"
#include <linux/stat.h>
@@ -557,7 +567,7 @@ typedef union icb {
} Icb;
#ifdef MODULE
-static char * wd7000 = NULL;
+static char *wd7000;
MODULE_PARM(wd7000, "s");
#endif
@@ -568,23 +578,23 @@ MODULE_PARM(wd7000, "s");
* structure is not part of the Adapter structure.
*/
static Scb scbs[MAX_SCBS];
-static Scb *scbfree = NULL; /* free list */
+static Scb *scbfree; /* free list */
static int freescbs = MAX_SCBS; /* free list counter */
/*
* END of data/declarations - code follows.
*/
-static void setup_error (char *mesg, int *ints)
+static void __init setup_error(char *mesg, int *ints)
{
if (ints[0] == 3)
- printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n",
- ints[1], ints[2], ints[3], mesg);
+ printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n",
+ ints[1], ints[2], ints[3], mesg);
else if (ints[0] == 4)
- printk ("wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n",
- ints[1], ints[2], ints[3], ints[4], mesg);
+ printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n",
+ ints[1], ints[2], ints[3], ints[4], mesg);
else
- printk ("wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n",
- ints[1], ints[2], ints[3], ints[4], ints[5], mesg);
+ printk(KERN_ERR "wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n",
+ ints[1], ints[2], ints[3], ints[4], ints[5], mesg);
}
@@ -604,21 +614,23 @@ static void setup_error (char *mesg, int *ints)
*/
static int __init wd7000_setup(char *str)
{
- static short wd7000_card_num = 0;
- short i, j;
+ static short wd7000_card_num; /* .bss will zero this */
+ short i;
int ints[6];
(void)get_options(str, ARRAY_SIZE(ints), ints);
if (wd7000_card_num >= NUM_CONFIGS) {
- printk("wd7000_setup: Too many \"wd7000=\" configurations in "
- "command line!\n");
+ printk(KERN_ERR __FUNCTION__
+ ": Too many \"wd7000=\" configurations in "
+ "command line!\n");
return 0;
}
if ((ints[0] < 3) || (ints[0] > 5)) {
- printk("wd7000_setup: Error in command line! "
- "Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>[,<BUS_OFF>]]\n");
+ printk(KERN_ERR __FUNCTION__ ": Error in command line! "
+ "Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>"
+ "[,<BUS_OFF>]]\n");
} else {
for (i = 0; i < NUM_IRQS; i++)
if (ints[1] == wd7000_irq[i])
@@ -652,7 +664,8 @@ static int __init wd7000_setup(char *str)
if (ints[0] > 3) {
if ((ints[4] < 500) || (ints[4] > 31875)) {
- setup_error("BUS_ON value is out of range (500 to 31875 nanoseconds)!", ints);
+ setup_error("BUS_ON value is out of range (500"
+ " to 31875 nanoseconds)!", ints);
configs[wd7000_card_num].bus_on = BUS_ON;
} else
configs[wd7000_card_num].bus_on = ints[4] / 125;
@@ -661,36 +674,47 @@ static int __init wd7000_setup(char *str)
if (ints[0] > 4) {
if ((ints[5] < 500) || (ints[5] > 31875)) {
- setup_error("BUS_OFF value is out of range (500 to 31875 nanoseconds)!", ints);
+ setup_error("BUS_OFF value is out of range (500"
+ " to 31875 nanoseconds)!", ints);
configs[wd7000_card_num].bus_off = BUS_OFF;
} else
- configs[wd7000_card_num].bus_off = ints[5] / 125;
+ configs[wd7000_card_num].bus_off = ints[5] /
+ 125;
} else
configs[wd7000_card_num].bus_off = BUS_OFF;
if (wd7000_card_num) {
- for (i = 0; i < (wd7000_card_num - 1); i++)
- for (j = i + 1; j < wd7000_card_num; j++)
+ for (i = 0; i < (wd7000_card_num - 1); i++) {
+ int j = i + 1;
+
+ for (; j < wd7000_card_num; j++)
if (configs[i].irq == configs[j].irq) {
- setup_error("duplicated IRQ!", ints);
+ setup_error("duplicated IRQ!",
+ ints);
return 0;
- } else if (configs[i].dma == configs[j].dma) {
- setup_error("duplicated DMA channel!", ints);
+ }
+ if (configs[i].dma == configs[j].dma) {
+ setup_error("duplicated DMA "
+ "channel!", ints);
return 0;
- } else if (configs[i].iobase == configs[j].iobase) {
- setup_error ("duplicated I/O base address!", ints);
+ }
+ if (configs[i].iobase ==
+ configs[j].iobase) {
+ setup_error("duplicated I/O "
+ "base address!",
+ ints);
return 0;
}
+ }
}
-#ifdef WD7000_DEBUG
- printk ("wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, BUS_ON=%dns, BUS_OFF=%dns\n",
+ dprintk(KERN_DEBUG "wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, "
+ "BUS_ON=%dns, BUS_OFF=%dns\n",
configs[wd7000_card_num].irq,
configs[wd7000_card_num].dma,
configs[wd7000_card_num].iobase,
configs[wd7000_card_num].bus_on * 125,
configs[wd7000_card_num].bus_off * 125);
-#endif
wd7000_card_num++;
}
@@ -811,7 +835,7 @@ static inline int command_out (Adapter * host, unchar * cmd, int len)
return (1);
}
- printk ("wd7000 command_out: WAIT failed(%d)\n", len + 1);
+ printk(KERN_WARNING "wd7000 command_out: WAIT failed(%d)\n", len + 1);
return (0);
}
@@ -827,7 +851,7 @@ static inline int command_out (Adapter * host, unchar * cmd, int len)
* the satisfiability of a request is not dependent on the size of the
* request.
*/
-static inline Scb *alloc_scbs (int needed)
+static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed)
{
register Scb *scb, *p;
register unsigned long flags;
@@ -842,18 +866,18 @@ static inline Scb *alloc_scbs (int needed)
save_flags (flags);
cli ();
while (busy) { /* someone else is allocating */
- spin_unlock_irq(&io_request_lock);
+ spin_unlock_irq(&host->host_lock);
for (now = jiffies; now == jiffies; ); /* wait a jiffy */
- spin_lock_irq(&io_request_lock);
+ spin_lock_irq(&host->host_lock);
}
busy = 1; /* not busy now; it's our turn */
while (freescbs < needed) {
timeout = jiffies + WAITnexttimeout;
do {
- spin_unlock_irq(&io_request_lock);
+ spin_unlock_irq(&host->host_lock);
for (now = jiffies; now == jiffies; ); /* wait a jiffy */
- spin_lock_irq(&io_request_lock);
+ spin_lock_irq(&host->host_lock);
} while (freescbs < needed && time_before_eq(jiffies, timeout));
/*
* If we get here with enough free Scbs, we can take them.
@@ -929,9 +953,7 @@ static int mail_out (Adapter *host, Scb *scbptr)
Mailbox *ogmbs = host->mb.ogmb;
int *next_ogmb = &(host->next_ogmb);
-#ifdef WD7000_DEBUG
- printk ("wd7000_mail_out: 0x%06lx", (long) scbptr);
-#endif
+ dprintk("wd7000_mail_out: 0x%06lx", (long) scbptr);
/* We first look for a free outgoing mailbox */
save_flags (flags);
@@ -939,9 +961,7 @@ static int mail_out (Adapter *host, Scb *scbptr)
ogmb = *next_ogmb;
for (i = 0; i < OGMB_CNT; i++) {
if (ogmbs[ogmb].status == 0) {
-#ifdef WD7000_DEBUG
- printk (" using OGMB 0x%x", ogmb);
-#endif
+ dprintk(" using OGMB 0x%x", ogmb);
ogmbs[ogmb].status = 1;
any2scsi ((unchar *) ogmbs[ogmb].scbptr, (int) scbptr);
@@ -953,9 +973,7 @@ static int mail_out (Adapter *host, Scb *scbptr)
}
restore_flags (flags);
-#ifdef WD7000_DEBUG
- printk (", scb is 0x%06lx", (long) scbptr);
-#endif
+ dprintk(", scb is 0x%06lx", (long) scbptr);
if (i >= OGMB_CNT) {
/*
@@ -966,9 +984,7 @@ static int mail_out (Adapter *host, Scb *scbptr)
* that marks OGMB's free, waiting even with interrupts off
* should work, since they are freed very quickly in most cases.
*/
-#ifdef WD7000_DEBUG
- printk (", no free OGMBs.\n");
-#endif
+ dprintk(", no free OGMBs.\n");
return (0);
}
@@ -977,9 +993,7 @@ static int mail_out (Adapter *host, Scb *scbptr)
start_ogmb = START_OGMB | ogmb;
command_out (host, &start_ogmb, 1);
-#ifdef WD7000_DEBUG
- printk (", awaiting interrupt.\n");
-#endif
+ dprintk(", awaiting interrupt.\n");
return (1);
}
@@ -1026,7 +1040,7 @@ int make_code (unsigned hosterr, unsigned scsierr)
}
#ifdef WD7000_DEBUG
if (scsierr || hosterr)
- printk ("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n",
+ dprintk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n",
scsierr, in_error, hosterr);
#endif
return (scsierr | (hosterr << 16));
@@ -1035,10 +1049,7 @@ int make_code (unsigned hosterr, unsigned scsierr)
static void wd7000_scsi_done (Scsi_Cmnd *SCpnt)
{
-#ifdef WD7000_DEBUG
- printk ("wd7000_scsi_done: 0x%06lx\n", (long) SCpnt);
-#endif
-
+ dprintk("wd7000_scsi_done: 0x%06lx\n", (long)SCpnt);
SCpnt->SCp.phase = 0;
}
@@ -1057,15 +1068,11 @@ void wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs)
host->int_counter++;
-#ifdef WD7000_DEBUG
- printk ("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host);
-#endif
+ dprintk("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host);
flag = inb (host->iobase + ASC_INTR_STAT);
-#ifdef WD7000_DEBUG
- printk ("wd7000_intr_handle: intr stat = 0x%02x\n", flag);
-#endif
+ dprintk("wd7000_intr_handle: intr stat = 0x%02x\n", flag);
if (!(inb (host->iobase + ASC_STAT) & INT_IM)) {
/* NB: these are _very_ possible if IRQ 15 is being used, since
@@ -1076,9 +1083,7 @@ void wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs)
* can sort these out. Otherwise, electrical noise and other such
* problems would be indistinguishable from valid interrupts...
*/
-#ifdef WD7000_DEBUG
- printk ("wd7000_intr_handle: phantom interrupt...\n");
-#endif
+ dprintk("wd7000_intr_handle: phantom interrupt...\n");
wd7000_intr_ack (host);
return;
}
@@ -1086,9 +1091,7 @@ void wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs)
if (flag & MB_INTR) {
/* The interrupt is for a mailbox */
if (!(flag & IMB_INTR)) {
-#ifdef WD7000_DEBUG
- printk ("wd7000_intr_handle: free outgoing mailbox\n");
-#endif
+ dprintk("wd7000_intr_handle: free outgoing mailbox\n");
/*
* If sleep_on() and the "interrupt on free OGMB" command are
* used in mail_out(), wake_up() should correspondingly be called
@@ -1102,10 +1105,8 @@ void wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs)
icmb = flag & MB_MASK;
icmb_status = icmbs[icmb].status;
if (icmb_status & 0x80) { /* unsolicited - result in ICMB */
-#ifdef WD7000_DEBUG
- printk ("wd7000_intr_handle: unsolicited interrupt 0x%02x\n",
+ dprintk("wd7000_intr_handle: unsolicited interrupt 0x%02x\n",
icmb_status);
-#endif
wd7000_intr_ack (host);
return;
}
@@ -1135,18 +1136,17 @@ void wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs)
wd7000_intr_ack (host);
-#ifdef WD7000_DEBUG
- printk ("wd7000_intr_handle: return from interrupt handler\n");
-#endif
+ dprintk("wd7000_intr_handle: return from interrupt handler\n");
}
void do_wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
+ struct Scsi_Host *host = dev_id;
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irqsave(&host->host_lock, flags);
wd7000_intr_handle(irq, dev_id, regs);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irqrestore(&host->host_lock, flags);
}
@@ -1163,7 +1163,7 @@ int wd7000_queuecommand (Scsi_Cmnd *SCpnt, void (*done) (Scsi_Cmnd *))
idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7);
SCpnt->scsi_done = done;
SCpnt->SCp.phase = 1;
- scb = alloc_scbs (1);
+ scb = alloc_scbs(SCpnt->host, 1);
scb->idlun = idlun;
memcpy (scb->cdb, cdb, cdblen);
scb->direc = 0x40; /* Disable direction check */
@@ -1179,9 +1179,7 @@ int wd7000_queuecommand (Scsi_Cmnd *SCpnt, void (*done) (Scsi_Cmnd *))
if (SCpnt->host->sg_tablesize == SG_NONE) {
panic ("wd7000_queuecommand: scatter/gather not supported.\n");
}
-#ifdef WD7000_DEBUG
- printk ("Using scatter/gather with %d elements.\n", SCpnt->use_sg);
-#endif
+ dprintk ("Using scatter/gather with %d elements.\n", SCpnt->use_sg);
sgb = scb->sgb;
scb->op = 1;
@@ -1368,14 +1366,12 @@ int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host)
save_flags (flags);
cli ();
-#ifdef WD7000_DEBUG
- printk ("Buffer = <%.*s>, length = %d\n", length, buffer, length);
-#endif
+ dprintk("Buffer = <%.*s>, length = %d\n", length, buffer, length);
/*
* Currently this is a no-op
*/
- printk ("Sorry, this function is currently out of order...\n");
+ dprintk("Sorry, this function is currently out of order...\n");
restore_flags (flags);
@@ -1522,9 +1518,7 @@ int wd7000_detect (Scsi_Host_Template *tpnt)
Adapter *host = NULL;
struct Scsi_Host *sh;
-#ifdef WD7000_DEBUG
- printk ("wd7000_detect: started\n");
-#endif
+ dprintk("wd7000_detect: started\n");
#ifdef MODULE
if (wd7000)
@@ -1574,12 +1568,12 @@ int wd7000_detect (Scsi_Host_Template *tpnt)
* BIOS SIGNATURE has been found.
*/
#ifdef WD7000_DEBUG
- printk ("wd7000_detect: pass %d\n", pass + 1);
+ dprintk("wd7000_detect: pass %d\n", pass + 1);
if (biosaddr_ptr == NUM_ADDRS)
- printk ("WD-7000 SST BIOS not detected...\n");
+ dprintk("WD-7000 SST BIOS not detected...\n");
else
- printk ("WD-7000 SST BIOS detected at 0x%lx: checking...\n",
+ dprintk("WD-7000 SST BIOS detected at 0x%lx: checking...\n",
wd7000_biosaddr[biosaddr_ptr]);
#endif
@@ -1588,15 +1582,11 @@ int wd7000_detect (Scsi_Host_Template *tpnt)
iobase = configs[pass].iobase;
-#ifdef WD7000_DEBUG
- printk ("wd7000_detect: check IO 0x%x region...\n", iobase);
-#endif
+ dprintk("wd7000_detect: check IO 0x%x region...\n", iobase);
if (request_region (iobase, 4, "wd7000")) {
-#ifdef WD7000_DEBUG
- printk ("wd7000_detect: ASC reset (IO 0x%x) ...", iobase);
-#endif
+ dprintk("wd7000_detect: ASC reset (IO 0x%x) ...", iobase);
/*
* ASC reset...
*/
@@ -1604,17 +1594,11 @@ int wd7000_detect (Scsi_Host_Template *tpnt)
delay (1);
outb (0, iobase + ASC_CONTROL);
- if (WAIT (iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0))
-#ifdef WD7000_DEBUG
- {
- printk ("failed!\n");
+ if (WAIT (iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) {
+ dprintk("failed!\n");
goto err_release;
- }
- else
- printk ("ok!\n");
-#else
- goto err_release;
-#endif
+ } else
+ dprintk("ok!\n");
if (inb (iobase + ASC_INTR_STAT) == 1) {
/*
@@ -1630,10 +1614,8 @@ int wd7000_detect (Scsi_Host_Template *tpnt)
host = (Adapter *) sh->hostdata;
-#ifdef WD7000_DEBUG
- printk ("wd7000_detect: adapter allocated at 0x%x\n", (int) host);
-#endif
-
+ dprintk("wd7000_detect: adapter allocated at 0x%x\n",
+ (int)host);
memset (host, 0, sizeof (Adapter));
host->irq = configs[pass].irq;
@@ -1644,11 +1626,9 @@ int wd7000_detect (Scsi_Host_Template *tpnt)
host->bus_off = configs[pass].bus_off;
host->sh = wd7000_host[host->irq - IRQ_MIN] = sh;
-#ifdef WD7000_DEBUG
- printk ("wd7000_detect: Trying init WD-7000 card at IO "
+ dprintk("wd7000_detect: Trying init WD-7000 card at IO "
"0x%x, IRQ %d, DMA %d...\n",
host->iobase, host->irq, host->dma);
-#endif
if (!wd7000_init (host)) /* Initialization failed */
goto err_unregister;
@@ -1676,12 +1656,9 @@ int wd7000_detect (Scsi_Host_Template *tpnt)
printk (" BUS_ON time: %dns, BUS_OFF time: %dns\n",
host->bus_on * 125, host->bus_off * 125);
}
- }
-
-#ifdef WD7000_DEBUG
- else
- printk ("wd7000_detect: IO 0x%x region already allocated!\n", iobase);
-#endif
+ } else
+ dprintk("wd7000_detect: IO 0x%x region already allocated!\n",
+ iobase);
continue;
@@ -1731,9 +1708,8 @@ int wd7000_reset (Scsi_Cmnd *SCpnt, unsigned int unused)
*/
int wd7000_biosparam (Disk *disk, kdev_t dev, int *ip)
{
-#ifdef WD7000_DEBUG
- printk ("wd7000_biosparam: dev=%s, size=%d, ", kdevname (dev), disk->capacity);
-#endif
+ dprintk("wd7000_biosparam: dev=%s, size=%d, ", kdevname(dev),
+ disk->capacity);
/*
* try default translation
@@ -1767,14 +1743,13 @@ int wd7000_biosparam (Disk *disk, kdev_t dev, int *ip)
ip[2] = info[2];
if (info[0] == 255)
- printk ("wd7000_biosparam: current partition table is using extended translation.\n");
+ printk(KERN_INFO __FUNCTION__ ": current partition table is "
+ "using extended translation.\n");
}
}
-#ifdef WD7000_DEBUG
- printk ("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]);
- printk ("WARNING: check, if the bios geometry is correct.\n");
-#endif
+ dprintk("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]);
+ dprintk("WARNING: check, if the bios geometry is correct.\n");
return (0);
}
diff --git a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c
index 93ee3de03..a478ddb74 100644
--- a/drivers/sgi/char/sgiserial.c
+++ b/drivers/sgi/char/sgiserial.c
@@ -49,8 +49,6 @@
#define NUM_SERIAL 1 /* One chip on board. */
#define NUM_CHANNELS (NUM_SERIAL * 2)
-extern wait_queue_head_t keypress_wait;
-
struct sgi_zslayout *zs_chips[NUM_SERIAL] = { 0, };
struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, };
struct sgi_zschannel *zs_conschan;
@@ -428,8 +426,6 @@ static _INLINE_ void receive_chars(struct sgi_serial *info, struct pt_regs *regs
show_buffers();
return;
}
- /* It is a 'keyboard interrupt' ;-) */
- wake_up(&keypress_wait);
}
/* Look for kgdb 'stop' character, consult the gdb documentation
* for remote target debugging and arch/sparc/kernel/sparc-stub.c
@@ -2117,12 +2113,6 @@ static void zs_console_write(struct console *co, const char *str,
rs_fair_output();
}
-static int zs_console_wait_key(struct console *con)
-{
- sleep_on(&keypress_wait);
- return 0;
-}
-
static kdev_t zs_console_device(struct console *con)
{
return MKDEV(TTY_MAJOR, 64 + con->index);
@@ -2274,7 +2264,6 @@ static struct console sgi_console_driver = {
name: "ttyS",
write: zs_console_write,
device: zs_console_device,
- wait_key: zs_console_wait_key,
setup: zs_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c
index e54f47b35..c77867795 100644
--- a/drivers/sound/ad1848.c
+++ b/drivers/sound/ad1848.c
@@ -148,7 +148,7 @@ static int ad_format_mask[13 /*devc->model */ ] =
AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW /* Ensoniq Soundscape*/,
AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
- AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM
+ AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM
};
static ad1848_info adev_info[MAX_AUDIO_DEV];
@@ -174,7 +174,7 @@ static struct {
,{CAP_F_TIMER} /* MD_1845_SSCAPE */
};
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
static int isapnp = 1;
static int isapnpjump = 0;
static int reverse = 0;
@@ -2934,7 +2934,7 @@ MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen */
MODULE_PARM(deskpro_m, "i"); /* Special magic for Deskpro M box */
MODULE_PARM(soundpro, "i"); /* More special magic for SoundPro chips */
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
MODULE_PARM(isapnp, "i");
MODULE_PARM(isapnpjump, "i");
MODULE_PARM(reverse, "i");
@@ -2968,6 +2968,10 @@ static struct {
ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021),
1, 0, 0, 1, 1},
+ {"Advanced Gravis InterWave Audio",
+ ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001),
+ ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000),
+ 0, 0, 0, 1, 0},
{0}
};
@@ -2980,6 +2984,8 @@ static struct isapnp_device_id id_table[] __devinitdata = {
ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), 0 },
+ { ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001),
+ ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000), 0 },
{0}
};
@@ -3104,7 +3110,7 @@ static int __init init_ad1848(void)
{
printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
if(isapnp && (ad1848_isapnp_probe(&cfg) < 0) ) {
printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n");
isapnp = 0;
@@ -3139,7 +3145,7 @@ static void __exit cleanup_ad1848(void)
if(loaded)
unload_ms_sound(&cfg);
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
if(audio_activated)
if(ad1848_dev)
ad1848_dev->deactivate(ad1848_dev);
diff --git a/drivers/sound/btaudio.c b/drivers/sound/btaudio.c
index 22daae685..40a6966ea 100644
--- a/drivers/sound/btaudio.c
+++ b/drivers/sound/btaudio.c
@@ -300,7 +300,7 @@ static void stop_recording(struct btaudio *bta)
static int btaudio_mixer_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct btaudio *bta;
for (bta = btaudios; bta != NULL; bta = bta->next)
@@ -459,7 +459,7 @@ static int btaudio_dsp_open(struct inode *inode, struct file *file,
static int btaudio_dsp_open_digital(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct btaudio *bta;
for (bta = btaudios; bta != NULL; bta = bta->next)
@@ -475,7 +475,7 @@ static int btaudio_dsp_open_digital(struct inode *inode, struct file *file)
static int btaudio_dsp_open_analog(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct btaudio *bta;
for (bta = btaudios; bta != NULL; bta = bta->next)
diff --git a/drivers/sound/cs4281/cs4281m.c b/drivers/sound/cs4281/cs4281m.c
index f1ee130a0..6854d7041 100644
--- a/drivers/sound/cs4281/cs4281m.c
+++ b/drivers/sound/cs4281/cs4281m.c
@@ -2569,7 +2569,7 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd,
static int cs4281_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct cs4281_state *s=NULL;
struct list_head *entry;
@@ -3625,7 +3625,7 @@ static int cs4281_release(struct inode *inode, struct file *file)
static int cs4281_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct cs4281_state *s=NULL;
struct list_head *entry;
@@ -3966,7 +3966,7 @@ static unsigned int cs4281_midi_poll(struct file *file,
static int cs4281_midi_open(struct inode *inode, struct file *file)
{
unsigned long flags, temp1;
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct cs4281_state *s=NULL;
struct list_head *entry;
list_for_each(entry, &cs4281_devs)
diff --git a/drivers/sound/cs46xx.c b/drivers/sound/cs46xx.c
index 362ede371..1de32dadb 100644
--- a/drivers/sound/cs46xx.c
+++ b/drivers/sound/cs46xx.c
@@ -1835,7 +1835,7 @@ static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wa
static int cs_midi_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct cs_card *card=NULL;
unsigned long flags;
struct list_head *entry;
@@ -3198,7 +3198,7 @@ static int cs_open(struct inode *inode, struct file *file)
struct cs_state *state = NULL;
struct dmabuf *dmabuf = NULL;
struct list_head *entry;
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
int ret=0;
unsigned int tmp;
@@ -4047,7 +4047,7 @@ static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val)
static int cs_open_mixdev(struct inode *inode, struct file *file)
{
int i=0;
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct cs_card *card=NULL;
struct list_head *entry;
unsigned int tmp;
@@ -4094,7 +4094,7 @@ static int cs_open_mixdev(struct inode *inode, struct file *file)
static int cs_release_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct cs_card *card=NULL;
struct list_head *entry;
int i;
diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c
index 93afb7a4d..598891164 100644
--- a/drivers/sound/es1370.c
+++ b/drivers/sound/es1370.c
@@ -1029,7 +1029,7 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
static int es1370_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct list_head *list;
struct es1370_state *s;
@@ -1729,7 +1729,7 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
static int es1370_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
struct list_head *list;
@@ -2165,7 +2165,7 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
static int es1370_open_dac(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
struct list_head *list;
@@ -2408,7 +2408,7 @@ static unsigned int es1370_midi_poll(struct file *file, struct poll_table_struct
static int es1370_midi_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
struct list_head *list;
diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c
index f822ea90a..d70d5dfa5 100644
--- a/drivers/sound/es1371.c
+++ b/drivers/sound/es1371.c
@@ -1213,7 +1213,7 @@ static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned lon
static int es1371_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct list_head *list;
struct es1371_state *s;
@@ -1913,7 +1913,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
static int es1371_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
struct list_head *list;
@@ -2342,7 +2342,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
static int es1371_open_dac(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
struct list_head *list;
@@ -2584,7 +2584,7 @@ static unsigned int es1371_midi_poll(struct file *file, struct poll_table_struct
static int es1371_midi_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
struct list_head *list;
diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c
index fad9e6a5f..e196264f1 100644
--- a/drivers/sound/esssolo1.c
+++ b/drivers/sound/esssolo1.c
@@ -913,7 +913,7 @@ static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long ar
static int solo1_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct solo1_state *s = NULL;
struct pci_dev *pci_dev;
@@ -1590,7 +1590,7 @@ static int solo1_release(struct inode *inode, struct file *file)
static int solo1_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
struct solo1_state *s = NULL;
struct pci_dev *pci_dev;
@@ -1879,7 +1879,7 @@ static unsigned int solo1_midi_poll(struct file *file, struct poll_table_struct
static int solo1_midi_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
struct solo1_state *s = NULL;
@@ -2105,7 +2105,7 @@ static int solo1_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int
static int solo1_dmfm_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
struct solo1_state *s = NULL;
struct pci_dev *pci_dev;
diff --git a/drivers/sound/i810_audio.c b/drivers/sound/i810_audio.c
index 81397ece5..2915a5a70 100644
--- a/drivers/sound/i810_audio.c
+++ b/drivers/sound/i810_audio.c
@@ -2341,7 +2341,7 @@ static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data)
static int i810_open_mixdev(struct inode *inode, struct file *file)
{
int i;
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct i810_card *card = devs;
for (card = devs; card != NULL; card = card->next)
diff --git a/drivers/sound/maestro.c b/drivers/sound/maestro.c
index 4df9e3b5b..03f3cb52f 100644
--- a/drivers/sound/maestro.c
+++ b/drivers/sound/maestro.c
@@ -2126,7 +2126,7 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long ar
/* --------------------------------------------------------------------- */
static int ess_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct ess_card *card = NULL;
struct pci_dev *pdev;
struct pci_driver *drvr;
@@ -2967,7 +2967,7 @@ free_buffers(struct ess_state *s)
static int
ess_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct ess_state *s = NULL;
unsigned char fmtm = ~0, fmts = 0;
struct pci_dev *pdev;
diff --git a/drivers/sound/maestro3.c b/drivers/sound/maestro3.c
index 64dcea37d..05e2032f2 100644
--- a/drivers/sound/maestro3.c
+++ b/drivers/sound/maestro3.c
@@ -1969,7 +1969,7 @@ free_dmabuf(struct pci_dev *pci_dev, struct dmabuf *db)
static int m3_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct m3_card *c;
struct m3_state *s = NULL;
int i;
@@ -2137,7 +2137,7 @@ out:
/* OSS /dev/mixer file operation methods */
static int m3_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct m3_card *card = devs;
for (card = devs; card != NULL; card = card->next) {
diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c
index de05ee691..9fd55621a 100644
--- a/drivers/sound/sound_core.c
+++ b/drivers/sound/sound_core.c
@@ -478,7 +478,7 @@ static struct sound_unit *__look_for_unit(int chain, int unit)
int soundcore_open(struct inode *inode, struct file *file)
{
int chain;
- int unit=MINOR(inode->i_rdev);
+ int unit = minor(inode->i_rdev);
struct sound_unit *s;
struct file_operations *new_fops = NULL;
diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c
index 4f9d27b58..31bcc48e9 100644
--- a/drivers/sound/soundcard.c
+++ b/drivers/sound/soundcard.c
@@ -35,7 +35,6 @@
#include <linux/kmod.h>
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/ioport.h>
@@ -145,7 +144,7 @@ static int get_mixer_levels(caddr_t arg)
static ssize_t sound_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+ int dev = minor(file->f_dentry->d_inode->i_rdev);
int ret = -EINVAL;
/*
@@ -178,7 +177,7 @@ static ssize_t sound_read(struct file *file, char *buf, size_t count, loff_t *pp
static ssize_t sound_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+ int dev = minor(file->f_dentry->d_inode->i_rdev);
int ret = -EINVAL;
lock_kernel();
@@ -205,7 +204,7 @@ static ssize_t sound_write(struct file *file, const char *buf, size_t count, lof
static int sound_open(struct inode *inode, struct file *file)
{
- int dev = MINOR(inode->i_rdev);
+ int dev = minor(inode->i_rdev);
int retval;
DEB(printk("sound_open(dev=%d)\n", dev));
@@ -256,7 +255,7 @@ static int sound_open(struct inode *inode, struct file *file)
static int sound_release(struct inode *inode, struct file *file)
{
- int dev = MINOR(inode->i_rdev);
+ int dev = minor(inode->i_rdev);
lock_kernel();
DEB(printk("sound_release(dev=%d)\n", dev));
@@ -342,7 +341,7 @@ static int sound_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int err, len = 0, dtype;
- int dev = MINOR(inode->i_rdev);
+ int dev = minor(inode->i_rdev);
if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) {
/*
@@ -405,7 +404,7 @@ static int sound_ioctl(struct inode *inode, struct file *file,
static unsigned int sound_poll(struct file *file, poll_table * wait)
{
struct inode *inode = file->f_dentry->d_inode;
- int dev = MINOR(inode->i_rdev);
+ int dev = minor(inode->i_rdev);
DEB(printk("sound_poll(dev=%d)\n", dev));
switch (dev & 0x0f) {
@@ -429,7 +428,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
int dev_class;
unsigned long size;
struct dma_buffparms *dmap = NULL;
- int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+ int dev = minor(file->f_dentry->d_inode->i_rdev);
dev_class = dev & 0x0f;
dev >>= 4;
diff --git a/drivers/sound/sscape.c b/drivers/sound/sscape.c
index 55c77c7df..425f41ae9 100644
--- a/drivers/sound/sscape.c
+++ b/drivers/sound/sscape.c
@@ -34,7 +34,6 @@
#include <linux/kmod.h>
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/ioport.h>
diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c
index c402dfb12..a400ac7e5 100644
--- a/drivers/sound/trident.c
+++ b/drivers/sound/trident.c
@@ -2556,7 +2556,7 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
static int trident_open(struct inode *inode, struct file *file)
{
int i = 0;
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct trident_card *card = devs;
struct trident_state *state = NULL;
struct dmabuf *dmabuf = NULL;
@@ -3751,7 +3751,7 @@ static int ali_write_proc(struct file *file, const char *buffer, unsigned long c
static int trident_open_mixdev(struct inode *inode, struct file *file)
{
int i = 0;
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct trident_card *card = devs;
for (card = devs; card != NULL; card = card->next)
diff --git a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c
index adb7d9dad..db3b9eed7 100644
--- a/drivers/sound/ymfpci.c
+++ b/drivers/sound/ymfpci.c
@@ -1858,7 +1858,7 @@ static int ymf_open(struct inode *inode, struct file *file)
struct ymf_state *state;
int err;
- minor = MINOR(inode->i_rdev);
+ minor = minor(inode->i_rdev);
if ((minor & 0x0F) == 3) { /* /dev/dspN */
;
} else {
@@ -1970,7 +1970,7 @@ static int ymf_release(struct inode *inode, struct file *file)
*/
static int ymf_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct list_head *list;
ymfpci_t *unit;
int i;
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 927932c16..6239675f8 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -64,7 +64,6 @@
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/wbflush.h>
@@ -2125,18 +2124,6 @@ static void serial_console_write(struct console *co, const char *s,
}
}
-/*
- * Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
- struct dec_serial *info;
-
- info = zs_soft + co->index;
-
- return zs_poll_rx_char(info);
-}
-
static kdev_t serial_console_device(struct console *c)
{
return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -2271,7 +2258,6 @@ static struct console sercons = {
name: "ttyS",
write: serial_console_write,
device: serial_console_device,
- wait_key: serial_console_wait_key,
setup: serial_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 0c774e769..037872804 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -268,7 +268,6 @@ static char ixj_c_revision[] = "$Revision: 4.7 $";
#include <linux/pci.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/isapnp.h>
diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in
index c1792a622..1be04d52c 100644
--- a/drivers/usb/Config.in
+++ b/drivers/usb/Config.in
@@ -18,7 +18,8 @@ comment 'Miscellaneous USB options'
bool ' Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
fi
-comment 'USB Controllers'
+comment 'USB Host Controller Drivers'
+source drivers/usb/hcd/Config.in
if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
fi
@@ -72,6 +73,8 @@ else
dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
dep_tristate ' USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
dep_tristate ' USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
+ dep_tristate ' USB STV680 (Pencam) Camera support' CONFIG_USB_STV680 $CONFIG_USB $CONFIG_VIDEO_DEV
+ dep_tristate ' USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
fi
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 3c1cbb475..b09211ea1 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -10,19 +10,13 @@ O_TARGET := usbdrv.o
# Objects that export symbols.
-export-objs := usb.o
+export-objs := usb.o hcd.o ov511.o pwc-uncompress.o
# Multipart objects.
-list-multi := usbcore.o hid.o
-usbcore-objs := usb.o usb-debug.o hub.o
+list-multi := usbcore.o hid.o pwc.o
+usbcore-objs := usb.o usb-debug.o hub.o hcd.o
hid-objs := hid-core.o hid-input.o
-
-ifneq ($(CONFIG_USB_PWC),n)
- export-objs += pwc-uncompress.o
- list-multi += pwc.o
-endif
-
pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
@@ -65,8 +59,10 @@ obj-$(CONFIG_USB_DC2XX) += dc2xx.o
obj-$(CONFIG_USB_MDC800) += mdc800.o
obj-$(CONFIG_USB_USS720) += uss720.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
+obj-$(CONFIG_USB_VICAM) += vicam.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
+obj-$(CONFIG_USB_STV680) += stv680.o
obj-$(CONFIG_USB_PEGASUS) += pegasus.o
obj-$(CONFIG_USB_CATC) += catc.o
obj-$(CONFIG_USB_KAWETH) += kaweth.o
@@ -79,11 +75,16 @@ obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
# Object files in subdirectories
-mod-subdirs := serial
+mod-subdirs := serial hcd
+subdir-$(CONFIG_USB_EHCI_HCD) += hcd
subdir-$(CONFIG_USB_SERIAL) += serial
subdir-$(CONFIG_USB_STORAGE) += storage
+ifeq ($(CONFIG_USB_EHCI_HCD),y)
+ obj-y += hcd/ehci-hcd.o
+endif
+
ifeq ($(CONFIG_USB_SERIAL),y)
obj-y += serial/usb-serial.o
endif
diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c
index 882c53a7d..9eee6a5f9 100644
--- a/drivers/usb/acm.c
+++ b/drivers/usb/acm.c
@@ -297,7 +297,7 @@ static void acm_softint(void *private)
static int acm_tty_open(struct tty_struct *tty, struct file *filp)
{
- struct acm *acm = acm_table[MINOR(tty->device)];
+ struct acm *acm = acm_table[minor(tty->device)];
if (!acm || !acm->dev) return -EINVAL;
diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c
index d2b88390f..8fec33785 100644
--- a/drivers/usb/audio.c
+++ b/drivers/usb/audio.c
@@ -833,7 +833,7 @@ static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int s
}
}
-static int usbin_prepare_desc(struct usbin *u, purb_t urb)
+static int usbin_prepare_desc(struct usbin *u, struct urb *urb)
{
unsigned int i, maxsize, offs;
@@ -850,7 +850,7 @@ static int usbin_prepare_desc(struct usbin *u, purb_t urb)
* return value: 0 if descriptor should be restarted, -1 otherwise
* convert sample format on the fly if necessary
*/
-static int usbin_retire_desc(struct usbin *u, purb_t urb)
+static int usbin_retire_desc(struct usbin *u, struct urb *urb)
{
unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree;
unsigned char *cp;
@@ -930,7 +930,7 @@ static void usbin_completed(struct urb *urb)
/*
* we output sync data
*/
-static int usbin_sync_prepare_desc(struct usbin *u, purb_t urb)
+static int usbin_sync_prepare_desc(struct usbin *u, struct urb *urb)
{
unsigned char *cp = urb->transfer_buffer;
unsigned int i, offs;
@@ -948,7 +948,7 @@ static int usbin_sync_prepare_desc(struct usbin *u, purb_t urb)
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
-static int usbin_sync_retire_desc(struct usbin *u, purb_t urb)
+static int usbin_sync_retire_desc(struct usbin *u, struct urb *urb)
{
unsigned int i;
@@ -996,7 +996,7 @@ static int usbin_start(struct usb_audiodev *as)
{
struct usb_device *dev = as->state->usbdev;
struct usbin *u = &as->usbin;
- purb_t urb;
+ struct urb *urb;
unsigned long flags;
unsigned int maxsze, bufsz;
@@ -1186,7 +1186,7 @@ static void usbout_convert(struct usbout *u, unsigned char *buffer, unsigned int
}
}
-static int usbout_prepare_desc(struct usbout *u, purb_t urb)
+static int usbout_prepare_desc(struct usbout *u, struct urb *urb)
{
unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs;
unsigned char *cp = urb->transfer_buffer;
@@ -1238,7 +1238,7 @@ static int usbout_prepare_desc(struct usbout *u, purb_t urb)
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
-static int usbout_retire_desc(struct usbout *u, purb_t urb)
+static int usbout_retire_desc(struct usbout *u, struct urb *urb)
{
unsigned int i;
@@ -1285,7 +1285,7 @@ static void usbout_completed(struct urb *urb)
spin_unlock_irqrestore(&as->lock, flags);
}
-static int usbout_sync_prepare_desc(struct usbout *u, purb_t urb)
+static int usbout_sync_prepare_desc(struct usbout *u, struct urb *urb)
{
unsigned int i, offs;
@@ -1299,7 +1299,7 @@ static int usbout_sync_prepare_desc(struct usbout *u, purb_t urb)
/*
* return value: 0 if descriptor should be restarted, -1 otherwise
*/
-static int usbout_sync_retire_desc(struct usbout *u, purb_t urb)
+static int usbout_sync_retire_desc(struct usbout *u, struct urb *urb)
{
unsigned char *cp = urb->transfer_buffer;
unsigned int f, i;
@@ -1361,7 +1361,7 @@ static int usbout_start(struct usb_audiodev *as)
{
struct usb_device *dev = as->state->usbdev;
struct usbout *u = &as->usbout;
- purb_t urb;
+ struct urb *urb;
unsigned long flags;
unsigned int maxsze, bufsz;
@@ -1947,7 +1947,7 @@ extern inline int prog_dmabuf_out(struct usb_audiodev *as)
static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct list_head *devs, *mdevs;
struct usb_mixerdev *ms;
struct usb_audio_state *s;
@@ -2621,7 +2621,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
static int usb_audio_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
DECLARE_WAITQUEUE(wait, current);
struct list_head *devs, *adevs;
struct usb_audiodev *as;
diff --git a/drivers/usb/bluetooth.c b/drivers/usb/bluetooth.c
index c4786295e..ba1db6f54 100644
--- a/drivers/usb/bluetooth.c
+++ b/drivers/usb/bluetooth.c
@@ -360,7 +360,7 @@ static int bluetooth_open (struct tty_struct *tty, struct file * filp)
tty->driver_data = NULL;
/* get the bluetooth object associated with this tty pointer */
- bluetooth = get_bluetooth_by_minor (MINOR(tty->device));
+ bluetooth = get_bluetooth_by_minor (minor(tty->device));
if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) {
return -ENODEV;
diff --git a/drivers/usb/catc.c b/drivers/usb/catc.c
index 9cd3f2166..0c704dc07 100644
--- a/drivers/usb/catc.c
+++ b/drivers/usb/catc.c
@@ -38,7 +38,9 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
+#include <linux/ethtool.h>
#include <asm/bitops.h>
+#include <asm/uaccess.h>
#undef DEBUG
@@ -48,9 +50,10 @@
* Version information.
*/
-#define DRIVER_VERSION "v2.7"
+#define DRIVER_VERSION "v2.8"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
#define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver"
+#define SHORT_DRIVER_DESC "EL1210A NetMate USB Ethernet"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -259,11 +262,15 @@ static void catc_irq_done(struct urb *urb)
}
}
- if (data[1] & 0x40)
+ if (data[1] & 0x40) {
+ netif_carrier_on(catc->netdev);
dbg("link ok");
+ }
- if (data[1] & 0x20)
+ if (data[1] & 0x20) {
+ netif_carrier_off(catc->netdev);
dbg("link bad");
+ }
}
/*
@@ -564,6 +571,54 @@ static void catc_set_multicast_list(struct net_device *netdev)
}
/*
+ * ioctl's
+ */
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+ struct catc *catc = dev->priv;
+ u32 cmd;
+ char tmp[40];
+
+ if (get_user(cmd, (u32 *)useraddr))
+ return -EFAULT;
+
+ switch (cmd) {
+ /* get driver info */
+ case ETHTOOL_GDRVINFO: {
+ struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+ strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
+ strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+ sprintf(tmp, "usb%d:%d", catc->usbdev->bus->busnum, catc->usbdev->devnum);
+ strncpy(info.bus_info, tmp,ETHTOOL_BUSINFO_LEN);
+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ /* get link status */
+ case ETHTOOL_GLINK: {
+ struct ethtool_value edata = {ETHTOOL_GLINK};
+ edata.data = netif_carrier_ok(dev);
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+ }
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ switch(cmd) {
+ case SIOCETHTOOL:
+ return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+
+/*
* Open, close.
*/
@@ -629,6 +684,7 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
netdev->tx_timeout = catc_tx_timeout;
netdev->watchdog_timeo = TX_TIMEOUT;
netdev->set_multicast_list = catc_set_multicast_list;
+ netdev->do_ioctl = catc_ioctl;
netdev->priv = catc;
catc->usbdev = usbdev;
diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c
index 123bbc322..40ba92fed 100644
--- a/drivers/usb/dabusb.c
+++ b/drivers/usb/dabusb.c
@@ -83,24 +83,24 @@ static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_
}
/*-------------------------------------------------------------------*/
#ifdef DEBUG
-static void dump_urb (purb_t purb)
+static void dump_urb (struct urb *urb)
{
- dbg("urb :%p", purb);
- dbg("next :%p", purb->next);
- dbg("dev :%p", purb->dev);
- dbg("pipe :%08X", purb->pipe);
- dbg("status :%d", purb->status);
- dbg("transfer_flags :%08X", purb->transfer_flags);
- dbg("transfer_buffer :%p", purb->transfer_buffer);
- dbg("transfer_buffer_length:%d", purb->transfer_buffer_length);
- dbg("actual_length :%d", purb->actual_length);
- dbg("setup_packet :%p", purb->setup_packet);
- dbg("start_frame :%d", purb->start_frame);
- dbg("number_of_packets :%d", purb->number_of_packets);
- dbg("interval :%d", purb->interval);
- dbg("error_count :%d", purb->error_count);
- dbg("context :%p", purb->context);
- dbg("complete :%p", purb->complete);
+ dbg("urb :%p", urb);
+ dbg("next :%p", urb->next);
+ dbg("dev :%p", urb->dev);
+ dbg("pipe :%08X", urb->pipe);
+ dbg("status :%d", urb->status);
+ dbg("transfer_flags :%08X", urb->transfer_flags);
+ dbg("transfer_buffer :%p", urb->transfer_buffer);
+ dbg("transfer_buffer_length:%d", urb->transfer_buffer_length);
+ dbg("actual_length :%d", urb->actual_length);
+ dbg("setup_packet :%p", urb->setup_packet);
+ dbg("start_frame :%d", urb->start_frame);
+ dbg("number_of_packets :%d", urb->number_of_packets);
+ dbg("interval :%d", urb->interval);
+ dbg("error_count :%d", urb->error_count);
+ dbg("context :%p", urb->context);
+ dbg("complete :%p", urb->complete);
}
#endif
/*-------------------------------------------------------------------*/
@@ -167,7 +167,7 @@ static int dabusb_free_buffers (pdabusb_t s)
return 0;
}
/*-------------------------------------------------------------------*/
-static void dabusb_iso_complete (purb_t purb)
+static void dabusb_iso_complete (struct urb *purb)
{
pbuff_t b = purb->context;
pdabusb_t s = b->s;
@@ -482,7 +482,7 @@ static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t *
int rem;
int cnt;
pbuff_t b;
- purb_t purb = NULL;
+ struct urb *purb = NULL;
dbg("dabusb_read");
@@ -579,7 +579,7 @@ static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t *
static int dabusb_open (struct inode *inode, struct file *file)
{
- int devnum = MINOR (inode->i_rdev);
+ int devnum = minor (inode->i_rdev);
pdabusb_t s;
if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
diff --git a/drivers/usb/dabusb.h b/drivers/usb/dabusb.h
index ddb4d8971..9fc09c8a2 100644
--- a/drivers/usb/dabusb.h
+++ b/drivers/usb/dabusb.h
@@ -38,7 +38,7 @@ typedef struct
typedef struct
{
pdabusb_t s;
- purb_t purb;
+ struct urb *purb;
struct list_head buff_list;
} buff_t,*pbuff_t;
diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c
index 931a274dc..08c7485b5 100644
--- a/drivers/usb/dc2xx.c
+++ b/drivers/usb/dc2xx.c
@@ -298,7 +298,7 @@ static int camera_open (struct inode *inode, struct file *file)
int value = 0;
down (&state_table_mutex);
- subminor = MINOR (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
+ subminor = minor (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
if (subminor < 0 || subminor >= MAX_CAMERAS
|| !(camera = minor_data [subminor])) {
up (&state_table_mutex);
diff --git a/drivers/usb/devio.c b/drivers/usb/devio.c
index f88e46910..424fee8de 100644
--- a/drivers/usb/devio.c
+++ b/drivers/usb/devio.c
@@ -40,6 +40,7 @@
#include <linux/smp_lock.h>
#include <linux/signal.h>
#include <linux/poll.h>
+#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <asm/uaccess.h>
@@ -245,7 +246,7 @@ extern __inline__ struct async *async_getpending(struct dev_state *ps, void *use
return NULL;
}
-static void async_completed(purb_t urb)
+static void async_completed(struct urb *urb)
{
struct async *as = (struct async *)urb->context;
struct dev_state *ps = as->ps;
@@ -471,9 +472,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
*/
lock_kernel();
ret = -ENOENT;
- if (ITYPE(inode->i_ino) != IDEVICE)
- goto out;
- dev = inode->u.usbdev_i.p.dev;
+ dev = inode->u.generic_ip;
if (!dev)
goto out;
ret = -ENOMEM;
@@ -1088,10 +1087,15 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
else if (ifp->driver == 0 || ifp->driver->ioctl == 0)
retval = -ENOSYS;
}
- if (retval == 0)
+ if (retval == 0) {
+ if (ifp->driver->owner)
+ __MOD_INC_USE_COUNT(ifp->driver->owner);
/* ifno might usefully be passed ... */
retval = ifp->driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
/* size = min_t(int, size, retval)? */
+ if (ifp->driver->owner)
+ __MOD_DEC_USE_COUNT(ifp->driver->owner);
+ }
}
/* cleanup and return */
diff --git a/drivers/usb/hcd.c b/drivers/usb/hcd.c
new file mode 100644
index 000000000..d01a1bcf4
--- /dev/null
+++ b/drivers/usb/hcd.c
@@ -0,0 +1,1305 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/uts.h> /* for UTS_SYSNAME */
+
+#ifndef CONFIG_USB_DEBUG
+ #define CONFIG_USB_DEBUG /* this is experimental! */
+#endif
+
+#ifdef CONFIG_USB_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+
+#include <linux/usb.h>
+#include "hcd.h"
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * USB Host Controller Driver framework
+ *
+ * Plugs into usbcore (usb_bus) and lets HCDs share code, minimizing
+ * HCD-specific behaviors/bugs.
+ *
+ * This does error checks, tracks devices and urbs, and delegates to a
+ * "hc_driver" only for code (and data) that really needs to know about
+ * hardware differences. That includes root hub registers, i/o queues,
+ * and so on ... but as little else as possible.
+ *
+ * Shared code includes most of the "root hub" code (these are emulated,
+ * though each HC's hardware works differently) and PCI glue, plus request
+ * tracking overhead. The HCD code should only block on spinlocks or on
+ * hardware handshaking; blocking on software events (such as other kernel
+ * threads releasing resources, or completing actions) is all generic.
+ *
+ * Happens the USB 2.0 spec says this would be invisible inside the "USBD",
+ * and includes mostly a "HCDI" (HCD Interface) along with some APIs used
+ * only by the hub driver ... and that neither should be seen or used by
+ * usb client device drivers.
+ *
+ * Contributors of ideas or unattributed patches include: David Brownell,
+ * Roman Weissgaerber, Rory Bolt, ...
+ *
+ * HISTORY:
+ * 2001-12-12 Initial patch version for Linux 2.5.1 kernel.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* host controllers we manage */
+static LIST_HEAD (hcd_list);
+
+/* used when updating list of hcds */
+static DECLARE_MUTEX (hcd_list_lock);
+
+/* used when updating hcd data */
+static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
+
+static struct usb_operations hcd_operations;
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Sharable chunks of root hub code.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* usb 2.0 root hub device descriptor */
+static const u8 usb2_rh_dev_descriptor [18] = {
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x00, 0x02, /* __u16 bcdUSB; v2.0 */
+
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ]*/
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+
+ 0x00, 0x00, /* __u16 idVendor; */
+ 0x00, 0x00, /* __u16 idProduct; */
+ 0x40, 0x02, /* __u16 bcdDevice; (v2.4) */
+
+ 0x03, /* __u8 iManufacturer; */
+ 0x02, /* __u8 iProduct; */
+ 0x01, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+/* no usb 2.0 root hub "device qualifier" descriptor: one speed only */
+
+/* usb 1.1 root hub device descriptor */
+static const u8 usb11_rh_dev_descriptor [18] = {
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, 0x01, /* __u16 bcdUSB; v1.1 */
+
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+
+ 0x00, 0x00, /* __u16 idVendor; */
+ 0x00, 0x00, /* __u16 idProduct; */
+ 0x40, 0x02, /* __u16 bcdDevice; (v2.4) */
+
+ 0x03, /* __u8 iManufacturer; */
+ 0x02, /* __u8 iProduct; */
+ 0x01, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+
+/*-------------------------------------------------------------------------*/
+
+/* Configuration descriptor for all our root hubs */
+
+static const u8 rh_config_descriptor [] = {
+
+ /* one configuration */
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, 0x00, /* __u16 wTotalLength; */
+ 0x01, /* __u8 bNumInterfaces; (1) */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ Bit 7: Bus-powered,
+ 6: Self-powered,
+ 5 Remote-wakwup,
+ 4..0: resvd */
+ 0x00, /* __u8 MaxPower; */
+
+ /* USB 1.1:
+ * USB 2.0, single TT organization (mandatory):
+ * one interface, protocol 0
+ *
+ * USB 2.0, multiple TT organization (optional):
+ * two interfaces, protocols 1 (like single TT)
+ * and 2 (multiple TT mode) ... config is
+ * sometimes settable
+ * NOT IMPLEMENTED
+ */
+
+ /* one interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* one endpoint (status change endpoint) */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+ 0x0c /* __u8 ep_bInterval; (12ms -- usb 2.0 spec) */
+};
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * helper routine for returning string descriptors in UTF-16LE
+ * input can actually be ISO-8859-1; ASCII is its 7-bit subset
+ */
+static int ascii2utf (char *ascii, u8 *utf, int utfmax)
+{
+ int retval;
+
+ for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
+ *utf++ = *ascii++ & 0x7f;
+ *utf++ = 0;
+ }
+ return retval;
+}
+
+/*
+ * rh_string - provides manufacturer, product and serial strings for root hub
+ * @id: the string ID number (1: serial number, 2: product, 3: vendor)
+ * @pci_desc: PCI device descriptor for the relevant HC
+ * @type: string describing our driver
+ * @data: return packet in UTF-16 LE
+ * @len: length of the return packet
+ *
+ * Produces either a manufacturer, product or serial number string for the
+ * virtual root hub device.
+ */
+static int rh_string (
+ int id,
+ struct pci_dev *pci_desc,
+ char *type,
+ u8 *data,
+ int len
+) {
+ char buf [100];
+
+ // language ids
+ if (id == 0) {
+ *data++ = 4; *data++ = 3; /* 4 bytes string data */
+ *data++ = 0; *data++ = 0; /* some language id */
+ return 4;
+
+ // serial number
+ } else if (id == 1) {
+ strcpy (buf, pci_desc->slot_name);
+
+ // product description
+ } else if (id == 2) {
+ strcpy (buf, pci_desc->name);
+
+ // id 3 == vendor description
+ } else if (id == 3) {
+ sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE, type);
+
+ // unsupported IDs --> "protocol stall"
+ } else
+ return 0;
+
+ data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
+ data [1] = 3; /* type == string */
+ return data [0];
+}
+
+
+/* Root hub control transfers execute synchronously */
+static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+{
+ devrequest *cmd = (devrequest *) urb->setup_packet;
+ u16 typeReq, wValue, wIndex, wLength;
+ const u8 *bufp = 0;
+ u8 *ubuf = urb->transfer_buffer;
+ int len = 0;
+
+ typeReq = (cmd->requesttype << 8) | cmd->request;
+ wValue = le16_to_cpu (cmd->value);
+ wIndex = le16_to_cpu (cmd->index);
+ wLength = le16_to_cpu (cmd->length);
+
+ if (wLength > urb->transfer_buffer_length)
+ goto error;
+
+ /* set up for success */
+ urb->status = 0;
+ urb->actual_length = wLength;
+ switch (typeReq) {
+
+ /* DEVICE REQUESTS */
+
+ case DeviceRequest | USB_REQ_GET_STATUS:
+ // DEVICE_REMOTE_WAKEUP
+ ubuf [0] = 1; // selfpowered
+ ubuf [1] = 0;
+ /* FALLTHROUGH */
+ case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+ case DeviceOutRequest | USB_REQ_SET_FEATURE:
+ dbg ("no device features yet yet");
+ break;
+ case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+ ubuf [0] = 1;
+ /* FALLTHROUGH */
+ case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+ break;
+ case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+ switch (wValue & 0xff00) {
+ case USB_DT_DEVICE << 8:
+ if (hcd->driver->flags & HCD_USB2)
+ bufp = usb2_rh_dev_descriptor;
+ else if (hcd->driver->flags & HCD_USB11)
+ bufp = usb11_rh_dev_descriptor;
+ else
+ goto error;
+ len = 18;
+ break;
+ case USB_DT_CONFIG << 8:
+ bufp = rh_config_descriptor;
+ len = sizeof rh_config_descriptor;
+ break;
+ case USB_DT_STRING << 8:
+ urb->actual_length = rh_string (
+ wValue & 0xff,
+ hcd->pdev,
+ (char *) hcd->description,
+ ubuf, wLength);
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case DeviceRequest | USB_REQ_GET_INTERFACE:
+ ubuf [0] = 0;
+ /* FALLTHROUGH */
+ case DeviceOutRequest | USB_REQ_SET_INTERFACE:
+ break;
+ case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+ // wValue == urb->dev->devaddr
+ dbg ("%s root hub device address %d",
+ hcd->bus_name, wValue);
+ break;
+
+ /* INTERFACE REQUESTS (no defined feature/status flags) */
+
+ /* ENDPOINT REQUESTS */
+
+ case EndpointRequest | USB_REQ_GET_STATUS:
+ // ENDPOINT_HALT flag
+ ubuf [0] = 0;
+ ubuf [1] = 0;
+ /* FALLTHROUGH */
+ case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
+ case EndpointOutRequest | USB_REQ_SET_FEATURE:
+ dbg ("no endpoint features yet");
+ break;
+
+ /* CLASS REQUESTS (and errors) */
+
+ default:
+ /* non-generic request */
+ urb->status = hcd->driver->hub_control (hcd,
+ typeReq, wValue, wIndex,
+ ubuf, wLength);
+ break;
+error:
+ /* "protocol stall" on error */
+ urb->status = -EPIPE;
+ dbg ("unsupported hub control message (maxchild %d)",
+ urb->dev->maxchild);
+ }
+ if (urb->status) {
+ urb->actual_length = 0;
+ dbg ("CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d",
+ typeReq, wValue, wIndex, wLength, urb->status);
+ }
+ if (bufp) {
+ if (urb->transfer_buffer_length < len)
+ len = urb->transfer_buffer_length;
+ urb->actual_length = len;
+ // always USB_DIR_IN, toward host
+ memcpy (ubuf, bufp, len);
+ }
+
+ /* any errors get returned through the urb completion */
+ usb_hcd_giveback_urb (hcd, urb);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Root Hub interrupt transfers are synthesized with a timer.
+ * Completions are called in_interrupt() but not in_irq().
+ */
+
+static void rh_report_status (unsigned long ptr);
+
+static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb)
+{
+ int len = 1 + (urb->dev->maxchild / 8);
+
+ /* rh_timer protected by hcd_data_lock */
+ if (timer_pending (&hcd->rh_timer)
+ || urb->status != -EINPROGRESS
+ || !HCD_IS_RUNNING (hcd->state)
+ || urb->transfer_buffer_length < len) {
+ dbg ("not queuing status urb, stat %d", urb->status);
+ return -EINVAL;
+ }
+
+ urb->hcpriv = hcd; /* nonzero to indicate it's queued */
+ init_timer (&hcd->rh_timer);
+ hcd->rh_timer.function = rh_report_status;
+ hcd->rh_timer.data = (unsigned long) urb;
+ hcd->rh_timer.expires = jiffies
+ + (HZ * (urb->interval < 30
+ ? 30
+ : urb->interval)) / 1000;
+ add_timer (&hcd->rh_timer);
+ return 0;
+}
+
+/* timer callback */
+
+static void rh_report_status (unsigned long ptr)
+{
+ struct urb *urb;
+ struct usb_hcd *hcd;
+ int length;
+ unsigned long flags;
+
+ urb = (struct urb *) ptr;
+ spin_lock_irqsave (&urb->lock, flags);
+ if (!urb->dev) {
+ spin_unlock_irqrestore (&urb->lock, flags);
+ return;
+ }
+
+ hcd = urb->dev->bus->hcpriv;
+ if (urb->status == -EINPROGRESS) {
+ if (HCD_IS_RUNNING (hcd->state)) {
+ length = hcd->driver->hub_status_data (hcd,
+ urb->transfer_buffer);
+ spin_unlock_irqrestore (&urb->lock, flags);
+ if (length > 0) {
+ urb->actual_length = length;
+ urb->status = 0;
+ urb->complete (urb);
+ }
+ spin_lock_irqsave (&hcd_data_lock, flags);
+ urb->status = -EINPROGRESS;
+ if (HCD_IS_RUNNING (hcd->state)
+ && rh_status_urb (hcd, urb) != 0) {
+ /* another driver snuck in? */
+ dbg ("%s, can't resubmit roothub status urb?",
+ hcd->bus_name);
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+ BUG ();
+ }
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+ } else
+ spin_unlock_irqrestore (&urb->lock, flags);
+ } else {
+ /* this urb's been unlinked */
+ urb->hcpriv = 0;
+ spin_unlock_irqrestore (&urb->lock, flags);
+
+ usb_hcd_giveback_urb (hcd, urb);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
+{
+ if (usb_pipeint (urb->pipe)) {
+ int retval;
+ unsigned long flags;
+
+ spin_lock_irqsave (&hcd_data_lock, flags);
+ retval = rh_status_urb (hcd, urb);
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+ return retval;
+ }
+ if (usb_pipecontrol (urb->pipe))
+ return rh_call_control (hcd, urb);
+ else
+ return -EINVAL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave (&hcd_data_lock, flags);
+ del_timer_sync (&hcd->rh_timer);
+ hcd->rh_timer.data = 0;
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+ /* we rely on RH callback code not unlinking its URB! */
+ usb_hcd_giveback_urb (hcd, urb);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PCI
+
+/* PCI-based HCs are normal, but custom bus glue should be ok */
+
+static void hcd_irq (int irq, void *__hcd, struct pt_regs *r);
+static void hc_died (struct usb_hcd *hcd);
+
+/*-------------------------------------------------------------------------*/
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+/**
+ * usb_hcd_pci_probe - initialize PCI-based HCDs
+ * @dev: USB Host Controller being probed
+ * @id: pci hotplug id connecting controller to HCD framework
+ *
+ * Allocates basic PCI resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ * Store this function in the HCD's struct pci_driver as probe().
+ */
+int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+{
+ struct hc_driver *driver;
+ unsigned long resource, len;
+ void *base;
+ u8 latency, limit;
+ struct usb_bus *bus;
+ struct usb_hcd *hcd;
+ int retval, region;
+ char buf [8], *bufp = buf;
+
+ if (!id || !(driver = (struct hc_driver *) id->driver_data))
+ return -EINVAL;
+
+ if (pci_enable_device (dev) < 0)
+ return -ENODEV;
+
+ if (!dev->irq) {
+ err ("Found HC with no IRQ. Check BIOS/PCI %s setup!",
+ dev->slot_name);
+ return -ENODEV;
+ }
+
+ if (driver->flags & HCD_MEMORY) { // EHCI, OHCI
+ region = 0;
+ resource = pci_resource_start (dev, 0);
+ len = pci_resource_len (dev, 0);
+ if (!request_mem_region (resource, len, driver->description)) {
+ dbg ("controller already in use");
+ return -EBUSY;
+ }
+ base = ioremap_nocache (resource, len);
+ if (base == NULL) {
+ dbg ("error mapping memory");
+ retval = -EFAULT;
+clean_1:
+ release_mem_region (resource, len);
+ err ("init %s fail, %d", dev->slot_name, retval);
+ return retval;
+ }
+
+ } else { // UHCI
+ resource = len = 0;
+ for (region = 0; region < PCI_ROM_RESOURCE; region++) {
+ if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
+ continue;
+
+ resource = pci_resource_start (dev, region);
+ len = pci_resource_len (dev, region);
+ if (request_region (resource, len,
+ driver->description))
+ break;
+ }
+ if (region == PCI_ROM_RESOURCE) {
+ dbg ("no i/o regions available");
+ return -EBUSY;
+ }
+ base = (void *) resource;
+ }
+
+ // driver->start(), later on, will transfer device from
+ // control by SMM/BIOS to control by Linux (if needed)
+
+ pci_set_master (dev);
+ hcd = driver->hcd_alloc ();
+ if (hcd == NULL){
+ dbg ("hcd alloc fail");
+ retval = -ENOMEM;
+clean_2:
+ if (driver->flags & HCD_MEMORY) {
+ iounmap (base);
+ goto clean_1;
+ } else {
+ release_region (resource, len);
+ err ("init %s fail, %d", dev->slot_name, retval);
+ return retval;
+ }
+ }
+ dev->driver_data = hcd;
+ hcd->driver = driver;
+ hcd->description = driver->description;
+ hcd->pdev = dev;
+ info ("%s @ %s, %s", hcd->description, dev->slot_name, dev->name);
+
+ pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+ if (latency) {
+ pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
+ if (limit && limit < latency) {
+ dbg ("PCI latency reduced to max %d", limit);
+ pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
+ }
+ }
+
+#ifndef __sparc__
+ sprintf (buf, "%d", dev->irq);
+#else
+ bufp = __irq_itoa(dev->irq);
+#endif
+ if (request_irq (dev->irq, hcd_irq, SA_SHIRQ, hcd->description, hcd)
+ != 0) {
+ err ("request interrupt %s failed", bufp);
+ retval = -EBUSY;
+clean_3:
+ driver->hcd_free (hcd);
+ goto clean_2;
+ }
+ hcd->irq = dev->irq;
+
+ hcd->regs = base;
+ hcd->region = region;
+ info ("irq %s, %s %p", bufp,
+ (driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
+ base);
+
+// FIXME simpler: make "bus" be that data, not pointer to it.
+ bus = usb_alloc_bus (&hcd_operations);
+ if (bus == NULL) {
+ dbg ("usb_alloc_bus fail");
+ retval = -ENOMEM;
+ free_irq (dev->irq, hcd);
+ goto clean_3;
+ }
+ hcd->bus = bus;
+ hcd->bus_name = dev->slot_name;
+ bus->hcpriv = (void *) hcd;
+
+ INIT_LIST_HEAD (&hcd->dev_list);
+ INIT_LIST_HEAD (&hcd->hcd_list);
+
+ down (&hcd_list_lock);
+ list_add (&hcd->hcd_list, &hcd_list);
+ up (&hcd_list_lock);
+
+ usb_register_bus (bus);
+
+ if ((retval = driver->start (hcd)) < 0)
+ usb_hcd_pci_remove (dev);
+
+ return retval;
+}
+EXPORT_SYMBOL (usb_hcd_pci_probe);
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
+ * @dev: USB Host Controller being removed
+ *
+ * Reverses the effect of usb_hcd_pci_probe(), first invoking
+ * the HCD's stop() method. It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ * Store this function in the HCD's struct pci_driver as remove().
+ */
+void usb_hcd_pci_remove (struct pci_dev *dev)
+{
+ struct usb_hcd *hcd;
+ struct usb_device *hub;
+
+ hcd = (struct usb_hcd *) dev->driver_data;
+ if (!hcd)
+ return;
+ info ("remove: %s, state %x", hcd->bus_name, hcd->state);
+
+ if (in_interrupt ()) BUG ();
+
+ hub = hcd->bus->root_hub;
+ hcd->state = USB_STATE_QUIESCING;
+
+ dbg ("%s: roothub graceful disconnect", hcd->bus_name);
+ usb_disconnect (&hub);
+ // usb_disconnect (&hcd->bus->root_hub);
+
+ hcd->driver->stop (hcd);
+ hcd->state = USB_STATE_HALT;
+
+ free_irq (hcd->irq, hcd);
+ if (hcd->driver->flags & HCD_MEMORY) {
+ iounmap (hcd->regs);
+ release_mem_region (pci_resource_start (dev, 0),
+ pci_resource_len (dev, 0));
+ } else {
+ release_region (pci_resource_start (dev, hcd->region),
+ pci_resource_len (dev, hcd->region));
+ }
+
+ down (&hcd_list_lock);
+ list_del (&hcd->hcd_list);
+ up (&hcd_list_lock);
+
+ usb_deregister_bus (hcd->bus);
+ usb_free_bus (hcd->bus);
+ hcd->bus = NULL;
+
+ hcd->driver->hcd_free (hcd);
+}
+EXPORT_SYMBOL (usb_hcd_pci_remove);
+
+
+#ifdef CONFIG_PM
+
+/*
+ * Some "sleep" power levels imply updating struct usb_driver
+ * to include a callback asking hcds to do their bit by checking
+ * if all the drivers can suspend. Gets involved with remote wakeup.
+ *
+ * If there are pending urbs, then HCs will need to access memory,
+ * causing extra power drain. New sleep()/wakeup() PM calls might
+ * be needed, beyond PCI suspend()/resume(). The root hub timer
+ * still be accessing memory though ...
+ *
+ * FIXME: USB should have some power budgeting support working with
+ * all kinds of hubs.
+ *
+ * FIXME: This assumes only D0->D3 suspend and D3->D0 resume.
+ * D1 and D2 states should do something, yes?
+ *
+ * FIXME: Should provide generic enable_wake(), calling pci_enable_wake()
+ * for all supported states, so that USB remote wakeup can work for any
+ * devices that support it (and are connected via powered hubs).
+ *
+ * FIXME: resume doesn't seem to work right any more...
+ */
+
+
+// 2.4 kernels have issued concurrent resumes (w/APM)
+// we defend against that error; PCI doesn't yet.
+
+/**
+ * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
+ * @dev: USB Host Controller being suspended
+ *
+ * Store this function in the HCD's struct pci_driver as suspend().
+ */
+int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
+{
+ struct usb_hcd *hcd;
+ int retval;
+
+ hcd = (struct usb_hcd *) dev->driver_data;
+ info ("suspend %s to state %d", hcd->bus_name, state);
+
+ pci_save_state (dev, hcd->pci_state);
+
+ // FIXME for all connected devices, leaf-to-root:
+ // driver->suspend()
+ // proposed "new 2.5 driver model" will automate that
+
+ /* driver may want to disable DMA etc */
+ retval = hcd->driver->suspend (hcd, state);
+ hcd->state = USB_STATE_SUSPENDED;
+
+ pci_set_power_state (dev, state);
+ return retval;
+}
+EXPORT_SYMBOL (usb_hcd_pci_suspend);
+
+/**
+ * usb_hcd_pci_resume - power management resume of a PCI-based HCD
+ * @dev: USB Host Controller being resumed
+ *
+ * Store this function in the HCD's struct pci_driver as resume().
+ */
+int usb_hcd_pci_resume (struct pci_dev *dev)
+{
+ struct usb_hcd *hcd;
+ int retval;
+
+ hcd = (struct usb_hcd *) dev->driver_data;
+ info ("resume %s", hcd->bus_name);
+
+ /* guard against multiple resumes (APM bug?) */
+ atomic_inc (&hcd->resume_count);
+ if (atomic_read (&hcd->resume_count) != 1) {
+ err ("concurrent PCI resumes for %s", hcd->bus_name);
+ retval = 0;
+ goto done;
+ }
+
+ retval = -EBUSY;
+ if (hcd->state != USB_STATE_SUSPENDED) {
+ dbg ("can't resume, not suspended!");
+ goto done;
+ }
+ hcd->state = USB_STATE_RESUMING;
+
+ pci_set_power_state (dev, 0);
+ pci_restore_state (dev, hcd->pci_state);
+
+ retval = hcd->driver->resume (hcd);
+ if (!HCD_IS_RUNNING (hcd->state)) {
+ dbg ("resume %s failure, retval %d", hcd->bus_name, retval);
+ hc_died (hcd);
+// FIXME: recover, reset etc.
+ } else {
+ // FIXME for all connected devices, root-to-leaf:
+ // driver->resume ();
+ // proposed "new 2.5 driver model" will automate that
+ }
+
+done:
+ atomic_dec (&hcd->resume_count);
+ return retval;
+}
+EXPORT_SYMBOL (usb_hcd_pci_resume);
+
+#endif /* CONFIG_PM */
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Generic HC operations.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* called from khubd, or root hub init threads for hcd-private init */
+static int hcd_alloc_dev (struct usb_device *udev)
+{
+ struct hcd_dev *dev;
+ struct usb_hcd *hcd;
+ unsigned long flags;
+
+ if (!udev || udev->hcpriv)
+ return -EINVAL;
+ if (!udev->bus || !udev->bus->hcpriv)
+ return -ENODEV;
+ hcd = udev->bus->hcpriv;
+ if (hcd->state == USB_STATE_QUIESCING)
+ return -ENOLINK;
+
+ dev = (struct hcd_dev *) kmalloc (sizeof *dev, GFP_KERNEL);
+ if (dev == NULL)
+ return -ENOMEM;
+ memset (dev, 0, sizeof *dev);
+
+ INIT_LIST_HEAD (&dev->dev_list);
+ INIT_LIST_HEAD (&dev->urb_list);
+
+ spin_lock_irqsave (&hcd_data_lock, flags);
+ list_add (&dev->dev_list, &hcd->dev_list);
+ // refcount is implicit
+ udev->hcpriv = dev;
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void hc_died (struct usb_hcd *hcd)
+{
+ struct list_head *devlist, *urblist;
+ struct hcd_dev *dev;
+ struct urb *urb;
+ unsigned long flags;
+
+ /* flag every pending urb as done */
+ spin_lock_irqsave (&hcd_data_lock, flags);
+ list_for_each (devlist, &hcd->dev_list) {
+ dev = list_entry (devlist, struct hcd_dev, dev_list);
+ list_for_each (urblist, &dev->urb_list) {
+ urb = list_entry (urblist, struct urb, urb_list);
+ dbg ("shutdown %s urb %p pipe %x, current status %d",
+ hcd->bus_name, urb, urb->pipe, urb->status);
+ if (urb->status == -EINPROGRESS)
+ urb->status = -ESHUTDOWN;
+ }
+ }
+ urb = (struct urb *) hcd->rh_timer.data;
+ if (urb)
+ urb->status = -ESHUTDOWN;
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+ if (urb)
+ rh_status_dequeue (hcd, urb);
+ hcd->driver->stop (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* may be called in any context with a valid urb->dev usecount */
+/* caller surrenders "ownership" of urb (and chain at urb->next). */
+
+static int hcd_submit_urb (struct urb *urb)
+{
+ int status;
+ struct usb_hcd *hcd;
+ struct hcd_dev *dev;
+ unsigned long flags;
+ int pipe;
+ int mem_flags;
+
+ if (!urb || urb->hcpriv || !urb->complete)
+ return -EINVAL;
+
+ urb->status = -EINPROGRESS;
+ urb->actual_length = 0;
+ INIT_LIST_HEAD (&urb->urb_list);
+
+ if (!urb->dev || !urb->dev->bus || urb->dev->devnum <= 0)
+ return -ENODEV;
+ hcd = urb->dev->bus->hcpriv;
+ dev = urb->dev->hcpriv;
+ if (!hcd || !dev)
+ return -ENODEV;
+
+ /* can't submit new urbs when quiescing, halted, ... */
+ if (hcd->state == USB_STATE_QUIESCING || !HCD_IS_RUNNING (hcd->state))
+ return -ESHUTDOWN;
+ pipe = urb->pipe;
+ if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe),
+ usb_pipeout (pipe)))
+ return -EPIPE;
+
+ // FIXME paging/swapping requests over USB should not use GFP_KERNEL
+ // and might even need to use GFP_NOIO ... that flag actually needs
+ // to be passed from the higher level.
+ mem_flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
+
+#ifdef DEBUG
+ {
+ unsigned int orig_flags = urb->transfer_flags;
+ unsigned int allowed;
+
+ /* enforce simple/standard policy */
+ allowed = USB_ASYNC_UNLINK; // affects later unlinks
+ allowed |= USB_NO_FSBR; // only affects UHCI
+ switch (usb_pipetype (pipe)) {
+ case PIPE_CONTROL:
+ allowed |= USB_DISABLE_SPD;
+ break;
+ case PIPE_BULK:
+ allowed |= USB_DISABLE_SPD | USB_QUEUE_BULK
+ | USB_ZERO_PACKET | URB_NO_INTERRUPT;
+ break;
+ case PIPE_INTERRUPT:
+ allowed |= USB_DISABLE_SPD;
+ break;
+ case PIPE_ISOCHRONOUS:
+ allowed |= USB_ISO_ASAP;
+ break;
+ }
+ urb->transfer_flags &= allowed;
+
+ /* warn if submitter gave bogus flags */
+ if (urb->transfer_flags != orig_flags)
+ warn ("BOGUS urb flags, %x --> %x",
+ orig_flags, urb->transfer_flags);
+ }
+#endif
+ /*
+ * FIXME: alloc periodic bandwidth here, for interrupt and iso?
+ * Need to look at the ring submit mechanism for iso tds ... they
+ * aren't actually "periodic" in 2.4 kernels.
+ *
+ * FIXME: make urb timeouts be generic, keeping the HCD cores
+ * as simple as possible.
+ */
+
+ // NOTE: a generic device/urb monitoring hook would go here.
+ // hcd_monitor_hook(MONITOR_URB_SUBMIT, urb)
+ // It would catch submission paths for all urbs.
+
+ /*
+ * Atomically queue the urb, first to our records, then to the HCD.
+ * Access to urb->status is controlled by urb->lock ... changes on
+ * i/o completion (normal or fault) or unlinking.
+ */
+
+ // FIXME: verify that quiescing hc works right (RH cleans up)
+
+ spin_lock_irqsave (&hcd_data_lock, flags);
+ if (HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_QUIESCING) {
+ usb_inc_dev_use (urb->dev);
+ list_add (&urb->urb_list, &dev->urb_list);
+ status = 0;
+ } else {
+ INIT_LIST_HEAD (&urb->urb_list);
+ status = -ESHUTDOWN;
+ }
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+ if (!status) {
+ if (urb->dev == hcd->bus->root_hub)
+ status = rh_urb_enqueue (hcd, urb);
+ else
+ status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+ }
+ if (status) {
+ if (urb->dev) {
+ urb->status = status;
+ usb_hcd_giveback_urb (hcd, urb);
+ }
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* called in any context */
+static int hcd_get_frame_number (struct usb_device *udev)
+{
+ struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv;
+ return hcd->driver->get_frame_number (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+struct completion_splice { // modified urb context:
+ /* did we complete? */
+ int done;
+
+ /* original urb data */
+ void (*complete)(struct urb *);
+ void *context;
+};
+
+static void unlink_complete (struct urb *urb)
+{
+ struct completion_splice *splice;
+
+ splice = (struct completion_splice *) urb->context;
+
+ /* issue original completion call */
+ urb->complete = splice->complete;
+ urb->context = splice->context;
+ urb->complete (urb);
+
+ splice->done = 1;
+}
+
+/*
+ * called in any context; note ASYNC_UNLINK restrictions
+ *
+ * caller guarantees urb won't be recycled till both unlink()
+ * and the urb's completion function return
+ */
+static int hcd_unlink_urb (struct urb *urb)
+{
+ struct hcd_dev *dev;
+ struct usb_hcd *hcd = 0;
+ unsigned long flags;
+ struct completion_splice splice;
+ int retval;
+
+ if (!urb)
+ return -EINVAL;
+
+ // FIXME: add some explicit records to flag the
+ // state where the URB is "in periodic completion".
+ // Workaround is for driver to set the urb status
+ // to "-EINPROGRESS", so it can get through here
+ // and unlink from the completion handler.
+
+ /*
+ * we contend for urb->status with the hcd core,
+ * which changes it while returning the urb.
+ */
+ spin_lock_irqsave (&urb->lock, flags);
+ if (!urb->hcpriv
+ || urb->status != -EINPROGRESS
+ || urb->transfer_flags & USB_TIMEOUT_KILLED) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ if (!urb->dev || !urb->dev->bus) {
+ retval = -ENODEV;
+ goto done;
+ }
+ dev = urb->dev->hcpriv;
+ hcd = urb->dev->bus->hcpriv;
+ if (!dev || !hcd) {
+ retval = -ENODEV;
+ goto done;
+ }
+
+ /* maybe set up to block on completion notification */
+ if ((urb->transfer_flags & USB_TIMEOUT_KILLED))
+ urb->status = -ETIMEDOUT;
+ else if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
+ if (in_interrupt ()) {
+ dbg ("non-async unlink in_interrupt");
+ retval = -EWOULDBLOCK;
+ goto done;
+ }
+ /* synchronous unlink: block till we see the completion */
+ splice.done = 0;
+ splice.complete = urb->complete;
+ splice.context = urb->context;
+ urb->complete = unlink_complete;
+ urb->context = &splice;
+ urb->status = -ENOENT;
+ } else {
+ /* asynchronous unlink */
+ urb->status = -ECONNRESET;
+ }
+ spin_unlock_irqrestore (&urb->lock, flags);
+
+ if (urb == (struct urb *) hcd->rh_timer.data) {
+ rh_status_dequeue (hcd, urb);
+ retval = 0;
+ } else {
+ retval = hcd->driver->urb_dequeue (hcd, urb);
+// FIXME: if retval and we tried to splice, whoa!!
+if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
+ }
+
+ /* block till giveback, if needed */
+ if (!(urb->transfer_flags & (USB_ASYNC_UNLINK|USB_TIMEOUT_KILLED))
+ && HCD_IS_RUNNING (hcd->state)
+ && !retval) {
+ while (!splice.done) {
+ set_current_state (TASK_UNINTERRUPTIBLE);
+ schedule_timeout ((2/*msec*/ * HZ) / 1000);
+ dbg ("%s: wait for giveback urb %p",
+ hcd->bus_name, urb);
+ }
+ }
+ goto bye;
+done:
+ spin_unlock_irqrestore (&urb->lock, flags);
+bye:
+ if (retval)
+ dbg ("%s: hcd_unlink_urb fail %d",
+ hcd ? hcd->bus_name : "(no bus?)",
+ retval);
+ return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup */
+
+// FIXME: likely best to have explicit per-setting (config+alt)
+// setup primitives in the usbcore-to-hcd driver API, so nothing
+// is implicit. kernel 2.5 needs a bunch of config cleanup...
+
+static int hcd_free_dev (struct usb_device *udev)
+{
+ struct hcd_dev *dev;
+ struct usb_hcd *hcd;
+ unsigned long flags;
+
+ if (!udev || !udev->hcpriv)
+ return -EINVAL;
+
+ if (!udev->bus || !udev->bus->hcpriv)
+ return -ENODEV;
+
+ // should udev->devnum == -1 ??
+
+ dev = udev->hcpriv;
+ hcd = udev->bus->hcpriv;
+
+ /* device driver problem with refcounts? */
+ if (!list_empty (&dev->urb_list)) {
+ dbg ("free busy dev, %s devnum %d (bug!)",
+ hcd->bus_name, udev->devnum);
+ return -EINVAL;
+ }
+
+ hcd->driver->free_config (hcd, udev);
+
+ spin_lock_irqsave (&hcd_data_lock, flags);
+ list_del (&dev->dev_list);
+ udev->hcpriv = NULL;
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+ kfree (dev);
+ return 0;
+}
+
+static struct usb_operations hcd_operations = {
+ allocate: hcd_alloc_dev,
+ get_frame_number: hcd_get_frame_number,
+ submit_urb: hcd_submit_urb,
+ unlink_urb: hcd_unlink_urb,
+ deallocate: hcd_free_dev,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
+{
+ struct usb_hcd *hcd = __hcd;
+ int start = hcd->state;
+
+ hcd->driver->irq (hcd);
+ if (hcd->state != start && hcd->state == USB_STATE_HALT)
+ hc_died (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_hcd_giveback_urb - return URB from HCD to device driver
+ * @hcd: host controller returning the URB
+ * @urb: urb being returned to the USB device driver.
+ *
+ * This hands the URB from HCD to its USB device driver, using its
+ * completion function. The HCD has freed all per-urb resources
+ * (and is done using urb->hcpriv). It also released all HCD locks;
+ * the device driver won't cause deadlocks if it resubmits this URB,
+ * and won't confuse things by modifying and resubmitting this one.
+ * Bandwidth and other resources will be deallocated.
+ *
+ * HCDs must not use this for periodic URBs that are still scheduled
+ * and will be reissued. They should just call their completion handlers
+ * until the urb is returned to the device driver by unlinking.
+ *
+ * In common cases, urb->next will be submitted before the completion
+ * function gets called. That's not done if the URB includes error
+ * status (including unlinking).
+ */
+void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+{
+ unsigned long flags;
+ struct usb_device *dev;
+
+ /* Release periodic transfer bandwidth */
+ if (urb->bandwidth) {
+ switch (usb_pipetype (urb->pipe)) {
+ case PIPE_INTERRUPT:
+ usb_release_bandwidth (urb->dev, urb, 0);
+ break;
+ case PIPE_ISOCHRONOUS:
+ usb_release_bandwidth (urb->dev, urb, 1);
+ break;
+ }
+ }
+
+ /* clear all state linking urb to this dev (and hcd) */
+
+ spin_lock_irqsave (&hcd_data_lock, flags);
+ list_del_init (&urb->urb_list);
+ dev = urb->dev;
+ urb->dev = NULL;
+ spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+ // NOTE: a generic device/urb monitoring hook would go here.
+ // hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev)
+ // It would catch exit/unlink paths for all urbs, but non-exit
+ // completions for periodic urbs need hooks inside the HCD.
+ // hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
+
+ if (urb->status)
+ dbg ("giveback urb %p status %d", urb, urb->status);
+
+ /* if no error, make sure urb->next progresses */
+ else if (urb->next) {
+ int status;
+
+ status = usb_submit_urb (urb->next);
+ if (status) {
+ dbg ("urb %p chain fail, %d", urb->next, status);
+ urb->next->status = -ENOTCONN;
+ }
+
+ /* HCDs never modify the urb->next chain, and only use it here,
+ * so that if urb->complete sees an URB there with -ENOTCONN,
+ * it knows the driver chained it but it couldn't be submitted.
+ */
+ }
+
+ /* pass ownership to the completion handler */
+ usb_dec_dev_use (dev);
+ urb->complete (urb);
+}
+EXPORT_SYMBOL (usb_hcd_giveback_urb);
diff --git a/drivers/usb/hcd.h b/drivers/usb/hcd.h
new file mode 100644
index 000000000..37ef85bd9
--- /dev/null
+++ b/drivers/usb/hcd.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * USB Host Controller Driver (usb_hcd) framework
+ *
+ * Since "struct usb_bus" is so thin, you can't share much code in it.
+ * This framework is a layer over that, and should be more sharable.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+struct usb_hcd { /* usb_bus.hcpriv points to this */
+
+ /*
+ * housekeeping
+ */
+ struct usb_bus *bus; /* hcd is-a bus */
+ struct list_head hcd_list;
+
+ const char *bus_name;
+
+ const char *description; /* "ehci-hcd" etc */
+
+ struct timer_list rh_timer; /* drives root hub */
+ struct list_head dev_list; /* devices on this bus */
+
+ /*
+ * hardware info/state
+ */
+ struct hc_driver *driver; /* hw-specific hooks */
+ int irq; /* irq allocated */
+ void *regs; /* device memory/io */
+
+#ifdef CONFIG_PCI
+ /* a few non-PCI controllers exist, mostly for OHCI */
+ struct pci_dev *pdev; /* pci is typical */
+ int region; /* pci region for regs */
+ u32 pci_state [16]; /* for PM state save */
+ atomic_t resume_count; /* multiple resumes issue */
+#endif
+
+ int state;
+# define __ACTIVE 0x01
+# define __SLEEPY 0x02
+# define __SUSPEND 0x04
+# define __TRANSIENT 0x80
+
+# define USB_STATE_HALT 0
+# define USB_STATE_RUNNING (__ACTIVE)
+# define USB_STATE_READY (__ACTIVE|__SLEEPY)
+# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
+# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
+# define USB_STATE_SUSPENDED (__SUSPEND)
+
+#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
+#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
+
+ /* more shared queuing code would be good; it should support
+ * smarter scheduling, handle transaction translators, etc;
+ * input size of periodic table to an interrupt scheduler.
+ * (ohci 32, uhci 1024, ehci 256/512/1024).
+ */
+};
+
+struct hcd_dev { /* usb_device.hcpriv points to this */
+ struct list_head dev_list; /* on this hcd */
+ struct list_head urb_list; /* pending on this dev */
+
+ /* per-configuration HC/HCD state, such as QH or ED */
+ void *ep[32];
+};
+
+// urb.hcpriv is really hardware-specific
+
+struct hcd_timeout { /* timeouts we allocate */
+ struct list_head timeout_list;
+ struct timer_list timer;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* each driver provides one of these, and hardware init support */
+
+struct hc_driver {
+ const char *description; /* "ehci-hcd" etc */
+
+ /* irq handler */
+ void (*irq) (struct usb_hcd *hcd);
+
+ int flags;
+#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
+#define HCD_USB11 0x0010 /* USB 1.1 */
+#define HCD_USB2 0x0020 /* USB 2.0 */
+
+ /* called to init HCD and root hub */
+ int (*start) (struct usb_hcd *hcd);
+
+ /* called after all devices were suspended */
+ int (*suspend) (struct usb_hcd *hcd, u32 state);
+
+ /* called before any devices get resumed */
+ int (*resume) (struct usb_hcd *hcd);
+
+ /* cleanly make HCD stop writing memory and doing I/O */
+ void (*stop) (struct usb_hcd *hcd);
+
+ /* return current frame number */
+ int (*get_frame_number) (struct usb_hcd *hcd);
+
+// FIXME: rework generic-to-specific HCD linkage (specific contains generic)
+
+ /* memory lifecycle */
+ struct usb_hcd *(*hcd_alloc) (void);
+ void (*hcd_free) (struct usb_hcd *hcd);
+
+ /* manage i/o requests, device state */
+ int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
+ int mem_flags);
+ int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
+
+ // frees configuration resources -- allocated as needed during
+ // urb_enqueue, and not freed by urb_dequeue
+ void (*free_config) (struct usb_hcd *hcd,
+ struct usb_device *dev);
+
+ /* root hub support */
+ int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
+ int (*hub_control) (struct usb_hcd *hcd,
+ u16 typeReq, u16 wValue, u16 wIndex,
+ char *buf, u16 wLength);
+};
+
+extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb);
+
+#ifdef CONFIG_PCI
+
+extern int usb_hcd_pci_probe (struct pci_dev *dev,
+ const struct pci_device_id *id);
+extern void usb_hcd_pci_remove (struct pci_dev *dev);
+
+#ifdef CONFIG_PM
+// FIXME: see Documentation/power/pci.txt (2.4.6 and later?)
+// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
+extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
+extern int usb_hcd_pci_resume (struct pci_dev *dev);
+// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
+#endif /* CONFIG_PM */
+
+#endif /* CONFIG_PCI */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * HCD Root Hub support
+ */
+
+#include "hub.h"
+
+/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
+#define DeviceRequest \
+ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
+#define DeviceOutRequest \
+ ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
+
+#define InterfaceRequest \
+ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+
+#define EndpointRequest \
+ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+#define EndpointOutRequest \
+ ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+
+/* table 9.6 standard features */
+#define DEVICE_REMOTE_WAKEUP 1
+#define ENDPOINT_HALT 0
+
+/* class requests from the USB 2.0 hub spec, table 11-15 */
+/* GetBusState and SetHubDescriptor are optional, omitted */
+#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
+#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
+#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
+#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
+#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
+#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
+#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
+
+
+/*-------------------------------------------------------------------------*/
+
+/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
+// bleech -- resurfaced in 2.4.11 or 2.4.12
+#define bitmap DeviceRemovable
+
+
+/*-------------------------------------------------------------------------*/
+
+/* random stuff */
+
+#define RUN_CONTEXT (in_irq () ? "in_irq" \
+ : (in_interrupt () ? "in_interrupt" : "can sleep"))
diff --git a/drivers/usb/hcd/Config.in b/drivers/usb/hcd/Config.in
new file mode 100644
index 000000000..6f64bd8b3
--- /dev/null
+++ b/drivers/usb/hcd/Config.in
@@ -0,0 +1,7 @@
+#
+# USB Host Controller Drivers
+#
+dep_tristate ' EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+# dep_tristate ' OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+# dep_tristate ' UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+
diff --git a/drivers/usb/hcd/Makefile b/drivers/usb/hcd/Makefile
new file mode 100644
index 000000000..432740891
--- /dev/null
+++ b/drivers/usb/hcd/Makefile
@@ -0,0 +1,27 @@
+#
+# Makefile for USB Host Controller Driver
+# framework and drivers
+#
+
+O_TARGET :=
+
+obj-$(CONFIG_EHCI_HCD) += ehci-hcd.o
+# obj-$(CONFIG_OHCI_HCD) += ohci-hcd.o
+# obj-$(CONFIG_UHCI_HCD) += uhci-hcd.o
+
+# Extract lists of the multi-part drivers.
+# The 'int-*' lists are the intermediate files used to build the multi's.
+multi-y := $(filter $(list-multi), $(obj-y))
+multi-m := $(filter $(list-multi), $(obj-m))
+int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
+int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
+
+# Take multi-part drivers out of obj-y and put components in.
+obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
+
+# Translate to Rules.make lists.
+OX_OBJS := $(obj-y)
+MX_OBJS := $(obj-m)
+MIX_OBJS := $(int-m)
+
+include $(TOPDIR)/Rules.make
diff --git a/drivers/usb/hcd/ehci-dbg.c b/drivers/usb/hcd/ehci-dbg.c
new file mode 100644
index 000000000..442bbe39a
--- /dev/null
+++ b/drivers/usb/hcd/ehci-dbg.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+#ifdef EHCI_VERBOSE_DEBUG
+# define vdbg dbg
+#else
+ static inline void vdbg (char *fmt, ...) { }
+#endif
+
+#ifdef DEBUG
+
+/* check the values in the HCSPARAMS register - host controller structural parameters */
+/* see EHCI 0.95 Spec, Table 2-4 for each value */
+static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
+{
+ u32 params = readl (&ehci->caps->hcs_params);
+
+ dbg ("%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d",
+ label, params,
+ HCS_DEBUG_PORT (params),
+ HCS_INDICATOR (params) ? " ind" : "",
+ HCS_N_CC (params),
+ HCS_N_PCC (params),
+ HCS_PORTROUTED (params) ? "" : " ordered",
+ HCS_PPC (params) ? "" : " !ppc",
+ HCS_N_PORTS (params)
+ );
+ /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */
+ if (HCS_PORTROUTED (params)) {
+ int i;
+ char buf [46], tmp [7], byte;
+
+ buf[0] = 0;
+ for (i = 0; i < HCS_N_PORTS (params); i++) {
+ byte = readb (&ehci->caps->portroute[(i>>1)]);
+ sprintf(tmp, "%d ",
+ ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf)));
+ strcat(buf, tmp);
+ }
+ dbg ("%s: %s portroute %s",
+ ehci->hcd.bus_name, label,
+ buf);
+ }
+}
+#else
+
+static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {}
+
+#endif
+
+#ifdef DEBUG
+
+/* check the values in the HCCPARAMS register - host controller capability parameters */
+/* see EHCI 0.95 Spec, Table 2-5 for each value */
+static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
+{
+ u32 params = readl (&ehci->caps->hcc_params);
+
+ if (HCC_EXT_CAPS (params)) {
+ // EHCI 0.96 ... could interpret these (legacy?)
+ dbg ("%s extended capabilities at pci %d",
+ label, HCC_EXT_CAPS (params));
+ }
+ if (HCC_ISOC_CACHE (params)) {
+ dbg ("%s hcc_params 0x%04x caching frame %s%s%s",
+ label, params,
+ HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
+ HCC_CANPARK (params) ? " park" : "",
+ HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+ } else {
+ dbg ("%s hcc_params 0x%04x caching %d uframes %s%s%s",
+ label,
+ params,
+ HCC_ISOC_THRES (params),
+ HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
+ HCC_CANPARK (params) ? " park" : "",
+ HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+ }
+}
+#else
+
+static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {}
+
+#endif
+
+#ifdef DEBUG
+
+#if 0
+static void dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ dbg ("%s %p info1 %x info2 %x hw_curr %x qtd_next %x", label,
+ qh, qh->hw_info1, qh->hw_info2,
+ qh->hw_current, qh->hw_qtd_next);
+ dbg (" alt+errs= %x, token= %x, page0= %x, page1= %x",
+ qh->hw_alt_next, qh->hw_token,
+ qh->hw_buf [0], qh->hw_buf [1]);
+ if (qh->hw_buf [2]) {
+ dbg (" page2= %x, page3= %x, page4= %x",
+ qh->hw_buf [2], qh->hw_buf [3],
+ qh->hw_buf [4]);
+ }
+}
+#endif
+
+static const char *const fls_strings [] =
+ { "1024", "512", "256", "??" };
+
+#else
+#if 0
+static inline void dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) {}
+#endif
+#endif /* DEBUG */
+
+/* functions have the "wrong" filename when they're output... */
+
+#define dbg_status(ehci, label, status) \
+ dbg ("%s status 0x%x%s%s%s%s%s%s%s%s%s%s", \
+ label, status, \
+ (status & STS_ASS) ? " Async" : "", \
+ (status & STS_PSS) ? " Periodic" : "", \
+ (status & STS_RECL) ? " Recl" : "", \
+ (status & STS_HALT) ? " Halt" : "", \
+ (status & STS_IAA) ? " IAA" : "", \
+ (status & STS_FATAL) ? " FATAL" : "", \
+ (status & STS_FLR) ? " FLR" : "", \
+ (status & STS_PCD) ? " PCD" : "", \
+ (status & STS_ERR) ? " ERR" : "", \
+ (status & STS_INT) ? " INT" : "" \
+ )
+
+#define dbg_cmd(ehci, label, command) \
+ dbg ("%s %x cmd %s=%d ithresh=%d%s%s%s%s period=%s%s %s", \
+ label, command, \
+ (command & CMD_PARK) ? "park" : "(park)", \
+ CMD_PARK_CNT (command), \
+ (command >> 16) & 0x3f, \
+ (command & CMD_LRESET) ? " LReset" : "", \
+ (command & CMD_IAAD) ? " IAAD" : "", \
+ (command & CMD_ASE) ? " Async" : "", \
+ (command & CMD_PSE) ? " Periodic" : "", \
+ fls_strings [(command >> 2) & 0x3], \
+ (command & CMD_RESET) ? " Reset" : "", \
+ (command & CMD_RUN) ? "RUN" : "HALT" \
+ )
+
+#define dbg_port(hcd, label, port, status) \
+ dbg ("%s port %d status 0x%x%s%s speed=%d%s%s%s%s%s%s%s%s%s", \
+ label, port, status, \
+ (status & PORT_OWNER) ? " OWNER" : "", \
+ (status & PORT_POWER) ? " POWER" : "", \
+ (status >> 10) & 3, \
+ (status & PORT_RESET) ? " RESET" : "", \
+ (status & PORT_SUSPEND) ? " SUSPEND" : "", \
+ (status & PORT_RESUME) ? " RESUME" : "", \
+ (status & PORT_OCC) ? " OCC" : "", \
+ (status & PORT_OC) ? " OC" : "", \
+ (status & PORT_PEC) ? " PEC" : "", \
+ (status & PORT_PE) ? " PE" : "", \
+ (status & PORT_CSC) ? " CSC" : "", \
+ (status & PORT_CONNECT) ? " CONNECT" : "" \
+ )
+
diff --git a/drivers/usb/hcd/ehci-hcd.c b/drivers/usb/hcd/ehci-hcd.c
new file mode 100644
index 000000000..83a33212f
--- /dev/null
+++ b/drivers/usb/hcd/ehci-hcd.c
@@ -0,0 +1,758 @@
+/*
+ * Copyright (c) 2000-2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+
+#ifndef CONFIG_USB_DEBUG
+ #define CONFIG_USB_DEBUG /* this is still experimental! */
+#endif
+
+#ifdef CONFIG_USB_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+
+#include <linux/usb.h>
+#include "../hcd.h"
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+//#undef KERN_DEBUG
+//#define KERN_DEBUG ""
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI hc_driver implementation ... experimental, incomplete.
+ * Based on the 0.96 register interface specification.
+ *
+ * There are lots of things to help out with here ... notably
+ * everything "periodic", and of course testing with all sorts
+ * of usb 2.0 devices and configurations.
+ *
+ * USB 2.0 shows up in upcoming www.pcmcia.org technology.
+ * First was PCMCIA, like ISA; then CardBus, which is PCI.
+ * Next comes "CardBay", using USB 2.0 signals.
+ *
+ * Contains additional contributions by:
+ * Brad Hards
+ * Rory Bolt
+ * ...
+ */
+
+#define DRIVER_VERSION "$Revision: 0.25 $"
+#define DRIVER_AUTHOR "David Brownell"
+#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
+
+
+// #define EHCI_VERBOSE_DEBUG
+// #define have_iso
+
+#ifdef DEBUG
+# define EHCI_SLAB_FLAGS (SLAB_POISON)
+#else
+# define EHCI_SLAB_FLAGS 0
+#endif
+
+/* magic numbers that can affect system performance */
+#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
+#define EHCI_TUNE_RL_HS 0 /* nak throttle; see 4.9 */
+#define EHCI_TUNE_RL_TT 0
+#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
+#define EHCI_TUNE_MULT_TT 1
+
+/* Initial IRQ latency: lower than default */
+static int log2_irq_thresh = 0; // 0 to 6
+MODULE_PARM (log2_irq_thresh, "i");
+MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
+
+/* Some A steppings of the NEC controller need soft retries */
+//#define EHCI_SOFT_RETRIES 5 /* after CERR-induced fault */
+
+#define INTR_MASK (STS_IAA | STS_FATAL | STS_ERR | STS_INT)
+
+/*-------------------------------------------------------------------------*/
+
+#include "ehci.h"
+#include "ehci-dbg.c"
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * hc states include: unknown, halted, ready, running
+ * transitional states are messy just now
+ * trying to avoid "running" unless urbs are active
+ * a "ready" hc can be finishing prefetched work
+ */
+
+/* halt a non-running controller */
+static void ehci_reset (struct ehci_hcd *ehci)
+{
+ u32 command = readl (&ehci->regs->command);
+
+ command |= CMD_RESET;
+ dbg_cmd (ehci, "reset", command);
+ writel (command, &ehci->regs->command);
+ while (readl (&ehci->regs->command) & CMD_RESET)
+ continue;
+ ehci->hcd.state = USB_STATE_HALT;
+}
+
+/* idle the controller (from running) */
+static void ehci_ready (struct ehci_hcd *ehci)
+{
+ u32 command;
+
+#ifdef DEBUG
+ if (!HCD_IS_RUNNING (ehci->hcd.state))
+ BUG ();
+#endif
+
+ while (!(readl (&ehci->regs->status) & (STS_ASS | STS_PSS)))
+ udelay (100);
+ command = readl (&ehci->regs->command);
+ command &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
+ writel (command, &ehci->regs->command);
+
+ // hardware can take 16 microframes to turn off ...
+ ehci->hcd.state = USB_STATE_READY;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#include "ehci-hub.c"
+#include "ehci-mem.c"
+#include "ehci-q.c"
+#include "ehci-sched.c"
+
+/*-------------------------------------------------------------------------*/
+
+static void ehci_tasklet (unsigned long param);
+
+/* called by khubd or root hub init threads */
+
+static int ehci_start (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ u32 temp;
+ struct usb_device *udev;
+ int retval;
+ u32 hcc_params;
+ u8 tempbyte;
+
+ // FIXME: given EHCI 0.96 or later, and a controller with
+ // the USBLEGSUP/USBLEGCTLSTS extended capability, make sure
+ // the BIOS doesn't still own this controller.
+
+ spin_lock_init (&ehci->lock);
+
+ ehci->caps = (struct ehci_caps *) hcd->regs;
+ ehci->regs = (struct ehci_regs *) (hcd->regs + ehci->caps->length);
+ dbg_hcs_params (ehci, "ehci_start");
+ dbg_hcc_params (ehci, "ehci_start");
+
+ /*
+ * hw default: 1K periodic list heads, one per frame.
+ * periodic_size can shrink by USBCMD update if hcc_params allows.
+ */
+ ehci->periodic_size = DEFAULT_I_TDPS;
+ if ((retval = ehci_mem_init (ehci, EHCI_SLAB_FLAGS | SLAB_KERNEL)) < 0)
+ return retval;
+ hcc_params = readl (&ehci->caps->hcc_params);
+
+ /* controllers may cache some of the periodic schedule ... */
+ if (HCC_ISOC_CACHE (hcc_params)) // full frame cache
+ ehci->i_thresh = 8;
+ else // N microframes cached
+ ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params);
+
+ ehci->async = 0;
+ ehci->reclaim = 0;
+ ehci->next_frame = -1;
+
+ /* controller state: unknown --> reset */
+
+ /* EHCI spec section 4.1 */
+ ehci_reset (ehci);
+ writel (INTR_MASK, &ehci->regs->intr_enable);
+ writel (ehci->periodic_dma, &ehci->regs->frame_list);
+
+ /*
+ * hcc_params controls whether ehci->regs->segment must (!!!)
+ * be used; it constrains QH/ITD/SITD and QTD locations.
+ * By default, pci_alloc_consistent() won't hand out addresses
+ * above 4GB (via pdev->dma_mask) so we know this value.
+ *
+ * NOTE: that pdev->dma_mask setting means that all DMA mappings
+ * for I/O buffers will have the same restriction, though it's
+ * neither necessary nor desirable in that case.
+ */
+ if (HCC_64BIT_ADDR (hcc_params)) {
+ writel (0, &ehci->regs->segment);
+ info ("using segment 0 for 64bit DMA addresses ...");
+ }
+
+ /* clear interrupt enables, set irq latency */
+ temp = readl (&ehci->regs->command) & 0xff;
+ if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
+ log2_irq_thresh = 0;
+ temp |= 1 << (16 + log2_irq_thresh);
+ // keeping default periodic framelist size
+ temp &= ~(CMD_IAAD | CMD_ASE | CMD_PSE),
+ writel (temp, &ehci->regs->command);
+ dbg_cmd (ehci, "init", temp);
+
+ /* set async sleep time = 10 us ... ? */
+
+ ehci->tasklet.func = ehci_tasklet;
+ ehci->tasklet.data = (unsigned long) ehci;
+
+ /* wire up the root hub */
+ hcd->bus->root_hub = udev = usb_alloc_dev (NULL, hcd->bus);
+ if (!udev) {
+done2:
+ ehci_mem_cleanup (ehci);
+ return -ENOMEM;
+ }
+
+ /*
+ * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
+ * are explicitly handed to companion controller(s), so no TT is
+ * involved with the root hub.
+ */
+ ehci->hcd.state = USB_STATE_READY;
+ writel (FLAG_CF, &ehci->regs->configured_flag);
+ readl (&ehci->regs->command); /* unblock posted write */
+
+ /* PCI Serial Bus Release Number is at 0x60 offset */
+ pci_read_config_byte(hcd->pdev, 0x60, &tempbyte);
+ temp = readw (&ehci->caps->hci_version);
+ info ("USB %x.%x support enabled, EHCI rev %x.%2x",
+ ((tempbyte & 0xf0)>>4),
+ (tempbyte & 0x0f),
+ temp >> 8,
+ temp & 0xff);
+
+ /*
+ * From here on, khubd concurrently accesses the root
+ * hub; drivers will be talking to enumerated devices.
+ *
+ * Before this point the HC was idle/ready. After, khubd
+ * and device drivers may start it running.
+ */
+ usb_connect (udev);
+ udev->speed = USB_SPEED_HIGH;
+ if (usb_new_device (udev) != 0) {
+ if (hcd->state == USB_STATE_RUNNING)
+ ehci_ready (ehci);
+ while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
+ udelay (100);
+ ehci_reset (ehci);
+ // usb_disconnect (udev);
+ hcd->bus->root_hub = 0;
+ usb_free_dev (udev);
+ retval = -ENODEV;
+ goto done2;
+ }
+
+ return 0;
+}
+
+/* always called by thread; normally rmmod */
+
+static void ehci_stop (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+
+ dbg ("%s: stop", hcd->bus_name);
+
+ if (hcd->state == USB_STATE_RUNNING)
+ ehci_ready (ehci);
+ while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
+ udelay (100);
+ ehci_reset (ehci);
+
+ // root hub is shut down separately (first, when possible)
+ scan_async (ehci);
+ if (ehci->next_frame != -1)
+ scan_periodic (ehci);
+ ehci_mem_cleanup (ehci);
+
+ dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
+}
+
+static int ehci_get_frame (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+/* suspend/resume, section 4.3 */
+
+static int ehci_suspend (struct usb_hcd *hcd, u32 state)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ u32 params;
+ int ports;
+ int i;
+
+ dbg ("%s: suspend to %d", hcd->bus_name, state);
+
+ params = readl (&ehci->caps->hcs_params);
+ ports = HCS_N_PORTS (params);
+
+ // FIXME: This assumes what's probably a D3 level suspend...
+
+ // FIXME: usb wakeup events on this bus should resume the machine.
+ // pci config register PORTWAKECAP controls which ports can do it;
+ // bios may have initted the register...
+
+ /* suspend each port, then stop the hc */
+ for (i = 0; i < ports; i++) {
+ int temp = readl (&ehci->regs->port_status [i]);
+
+ if ((temp & PORT_PE) == 0
+ || (temp & PORT_OWNER) != 0)
+ continue;
+dbg ("%s: suspend port %d", hcd->bus_name, i);
+ temp |= PORT_SUSPEND;
+ writel (temp, &ehci->regs->port_status [i]);
+ }
+
+ if (hcd->state == USB_STATE_RUNNING)
+ ehci_ready (ehci);
+ while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
+ udelay (100);
+ writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command);
+
+// save pci FLADJ value
+
+ /* who tells PCI to reduce power consumption? */
+
+ return 0;
+}
+
+static int ehci_resume (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ u32 params;
+ int ports;
+ int i;
+
+ dbg ("%s: resume", hcd->bus_name);
+
+ params = readl (&ehci->caps->hcs_params);
+ ports = HCS_N_PORTS (params);
+
+ // FIXME: if controller didn't retain state,
+ // return and let generic code clean it up
+ // test configured_flag ?
+
+ /* resume HC and each port */
+// restore pci FLADJ value
+ // khubd and drivers will set HC running, if needed;
+ hcd->state = USB_STATE_READY;
+ for (i = 0; i < ports; i++) {
+ int temp = readl (&ehci->regs->port_status [i]);
+
+ if ((temp & PORT_PE) == 0
+ || (temp & PORT_SUSPEND) != 0)
+ continue;
+dbg ("%s: resume port %d", hcd->bus_name, i);
+ temp |= PORT_RESUME;
+ writel (temp, &ehci->regs->port_status [i]);
+ readl (&ehci->regs->command); /* unblock posted writes */
+
+ wait_ms (20);
+ temp &= ~PORT_RESUME;
+ writel (temp, &ehci->regs->port_status [i]);
+ }
+ readl (&ehci->regs->command); /* unblock posted writes */
+ return 0;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * tasklet scheduled by some interrupts and other events
+ * calls driver completion functions ... but not in_irq()
+ */
+static void ehci_tasklet (unsigned long param)
+{
+ struct ehci_hcd *ehci = (struct ehci_hcd *) param;
+
+ if (ehci->reclaim_ready)
+ end_unlink_async (ehci);
+ scan_async (ehci);
+ if (ehci->next_frame != -1)
+ scan_periodic (ehci);
+
+ // FIXME: when nothing is connected to the root hub,
+ // turn off the RUN bit so the host can enter C3 "sleep" power
+ // saving mode; make root hub code scan memory less often.
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void ehci_irq (struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ u32 status = readl (&ehci->regs->status);
+ int bh = 0;
+
+ /* clear (just) interrupts */
+ status &= INTR_MASK;
+ writel (status, &ehci->regs->status);
+ readl (&ehci->regs->command); /* unblock posted write */
+
+ if (unlikely (hcd->state == USB_STATE_HALT)) /* irq sharing? */
+ return;
+
+#ifdef EHCI_VERBOSE_DEBUG
+ /* unrequested/ignored: Port Change Detect, Frame List Rollover */
+ if (status & INTR_MASK)
+ dbg_status (ehci, "irq", status);
+#endif
+
+ /* INT, ERR, and IAA interrupt rates can be throttled */
+
+ /* normal [4.15.1.2] or error [4.15.1.1] completion */
+ if (likely ((status & (STS_INT|STS_ERR)) != 0))
+ bh = 1;
+
+ /* complete the unlinking of some qh [4.15.2.3] */
+ if (status & STS_IAA) {
+ ehci->reclaim_ready = 1;
+ bh = 1;
+ }
+
+ /* PCI errors [4.15.2.4] */
+ if (unlikely ((status & STS_FATAL) != 0)) {
+ err ("%s: fatal error, state %x", hcd->bus_name, hcd->state);
+ ehci_reset (ehci);
+ // generic layer kills/unlinks all urbs
+ // then tasklet cleans up the rest
+ bh = 1;
+ }
+
+ /* most work doesn't need to be in_irq() */
+ if (likely (bh == 1))
+ tasklet_schedule (&ehci->tasklet);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * non-error returns are a promise to giveback() the urb later
+ * we drop ownership so next owner (or urb unlink) can get it
+ *
+ * urb + dev is in hcd_dev.urb_list
+ * we're queueing TDs onto software and hardware lists
+ *
+ * hcd-specific init for hcpriv hasn't been done yet
+ *
+ * NOTE: EHCI queues control and bulk requests transparently, like OHCI.
+ */
+static int ehci_urb_enqueue (
+ struct usb_hcd *hcd,
+ struct urb *urb,
+ int mem_flags
+) {
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ struct list_head qtd_list;
+
+ urb->transfer_flags &= ~EHCI_STATE_UNLINK;
+ INIT_LIST_HEAD (&qtd_list);
+ switch (usb_pipetype (urb->pipe)) {
+
+ case PIPE_CONTROL:
+ case PIPE_BULK:
+ if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
+ return -ENOMEM;
+ submit_async (ehci, urb, &qtd_list, mem_flags);
+ break;
+
+ case PIPE_INTERRUPT:
+ if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
+ return -ENOMEM;
+ return intr_submit (ehci, urb, &qtd_list, mem_flags);
+
+ case PIPE_ISOCHRONOUS:
+#ifdef have_iso
+ if (urb->dev->speed == USB_SPEED_HIGH)
+ return itd_submit (ehci, urb);
+ else
+ return sitd_submit (ehci, urb);
+#else
+ // FIXME highspeed iso stuff is written but never run/tested.
+ // and the split iso support isn't even written yet.
+ dbg ("no iso support yet");
+ return -ENOSYS;
+#endif /* have_iso */
+
+ }
+ return 0;
+}
+
+/* remove from hardware lists
+ * completions normally happen asynchronously
+ */
+
+static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
+ unsigned long flags;
+
+ dbg ("%s urb_dequeue %p qh state %d",
+ hcd->bus_name, urb, qh->qh_state);
+
+ switch (usb_pipetype (urb->pipe)) {
+ case PIPE_CONTROL:
+ case PIPE_BULK:
+ spin_lock_irqsave (&ehci->lock, flags);
+ if (ehci->reclaim) {
+dbg ("dq: reclaim busy, %s", RUN_CONTEXT);
+ if (in_interrupt ()) {
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ return -EAGAIN;
+ }
+ while (qh->qh_state == QH_STATE_LINKED
+ && ehci->reclaim
+ && ehci->hcd.state != USB_STATE_HALT
+ ) {
+ spin_unlock_irqrestore (&ehci->lock, flags);
+// yeech ... this could spin for up to two frames!
+dbg ("wait for dequeue: state %d, reclaim %p, hcd state %d",
+ qh->qh_state, ehci->reclaim, ehci->hcd.state
+);
+ udelay (100);
+ spin_lock_irqsave (&ehci->lock, flags);
+ }
+ }
+ if (qh->qh_state == QH_STATE_LINKED)
+ start_unlink_async (ehci, qh);
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ return 0;
+
+ case PIPE_INTERRUPT:
+ intr_deschedule (ehci, urb->start_frame, qh, urb->interval);
+ if (ehci->hcd.state == USB_STATE_HALT)
+ urb->status = -ESHUTDOWN;
+ qh_completions (ehci, &qh->qtd_list, 1);
+ return 0;
+
+ case PIPE_ISOCHRONOUS:
+ // itd or sitd ...
+
+ // wait till next completion, do it then.
+ // completion irqs can wait up to 128 msec,
+ urb->transfer_flags |= EHCI_STATE_UNLINK;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+// bulk qh holds the data toggle
+
+static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
+{
+ struct hcd_dev *dev = (struct hcd_dev *)udev->hcpriv;
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ int i;
+ unsigned long flags;
+
+ /* ASSERT: nobody can be submitting urbs for this any more */
+
+ dbg ("%s: free_config devnum %d", hcd->bus_name, udev->devnum);
+
+ spin_lock_irqsave (&ehci->lock, flags);
+ for (i = 0; i < 32; i++) {
+ if (dev->ep [i]) {
+ struct ehci_qh *qh;
+
+ // FIXME: this might be an itd/sitd too ...
+ // or an interrupt urb (not on async list)
+ // can use "union ehci_shadow"
+
+ qh = (struct ehci_qh *) dev->ep [i];
+ vdbg ("free_config, ep 0x%02x qh %p", i, qh);
+ if (!list_empty (&qh->qtd_list)) {
+ dbg ("ep 0x%02x qh %p not empty!", i, qh);
+ BUG ();
+ }
+ dev->ep [i] = 0;
+
+ /* wait_ms() won't spin here -- we're a thread */
+ while (qh->qh_state == QH_STATE_LINKED
+ && ehci->reclaim
+ && ehci->hcd.state != USB_STATE_HALT
+ ) {
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ wait_ms (1);
+ spin_lock_irqsave (&ehci->lock, flags);
+ }
+ if (qh->qh_state == QH_STATE_LINKED) {
+ start_unlink_async (ehci, qh);
+ while (qh->qh_state != QH_STATE_IDLE) {
+ spin_unlock_irqrestore (&ehci->lock,
+ flags);
+ wait_ms (1);
+ spin_lock_irqsave (&ehci->lock, flags);
+ }
+ }
+ qh_unput (ehci, qh);
+ }
+ }
+
+ spin_unlock_irqrestore (&ehci->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const char hcd_name [] = "ehci-hcd";
+
+static const struct hc_driver ehci_driver = {
+ description: hcd_name,
+
+ /*
+ * generic hardware linkage
+ */
+ irq: ehci_irq,
+ flags: HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ */
+ start: ehci_start,
+#ifdef CONFIG_PM
+ suspend: ehci_suspend,
+ resume: ehci_resume,
+#endif
+ stop: ehci_stop,
+
+ /*
+ * memory lifecycle (except per-request)
+ */
+ hcd_alloc: ehci_hcd_alloc,
+ hcd_free: ehci_hcd_free,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ urb_enqueue: ehci_urb_enqueue,
+ urb_dequeue: ehci_urb_dequeue,
+ free_config: ehci_free_config,
+
+ /*
+ * scheduling support
+ */
+ get_frame_number: ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ hub_status_data: ehci_hub_status_data,
+ hub_control: ehci_hub_control,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* EHCI spec says PCI is required. */
+
+/* PCI driver selection metadata; PCI hotplugging uses this */
+static const struct pci_device_id __devinitdata pci_ids [] = { {
+
+ /* handle any USB 2.0 EHCI controller */
+
+ class: ((PCI_CLASS_SERIAL_USB << 8) | 0x20),
+ class_mask: ~0,
+ driver_data: (unsigned long) &ehci_driver,
+
+ /* no matter who makes it */
+ vendor: PCI_ANY_ID,
+ device: PCI_ANY_ID,
+ subvendor: PCI_ANY_ID,
+ subdevice: PCI_ANY_ID,
+
+}, { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE (pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver ehci_pci_driver = {
+ name: (char *) hcd_name,
+ id_table: pci_ids,
+
+ probe: usb_hcd_pci_probe,
+ remove: usb_hcd_pci_remove,
+
+#ifdef CONFIG_PM
+ suspend: usb_hcd_pci_suspend,
+ resume: usb_hcd_pci_resume,
+#endif
+};
+
+#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
+
+EXPORT_NO_SYMBOLS;
+MODULE_DESCRIPTION (DRIVER_INFO);
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_LICENSE ("GPL");
+
+static int __init init (void)
+{
+ dbg (DRIVER_INFO);
+ dbg ("block sizes: qh %d qtd %d itd %d sitd %d",
+ sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
+ sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
+
+ return pci_module_init (&ehci_pci_driver);
+}
+module_init (init);
+
+static void __exit cleanup (void)
+{
+ pci_unregister_driver (&ehci_pci_driver);
+}
+module_exit (cleanup);
diff --git a/drivers/usb/hcd/ehci-hub.c b/drivers/usb/hcd/ehci-hub.c
new file mode 100644
index 000000000..4234fd8f2
--- /dev/null
+++ b/drivers/usb/hcd/ehci-hub.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Root Hub ... the nonsharable stuff
+ *
+ * Registers don't need cpu_to_le32, that happens transparently
+ */
+
+/*-------------------------------------------------------------------------*/
+
+static int check_reset_complete (
+ struct ehci_hcd *ehci,
+ int index,
+ int port_status
+) {
+ if (!(port_status & PORT_CONNECT)) {
+ ehci->reset_done [index] = 0;
+ return port_status;
+ }
+
+ /* if reset finished and it's still not enabled -- handoff */
+ if (!(port_status & PORT_PE)) {
+ dbg ("%s port %d full speed, give to companion, 0x%x",
+ ehci->hcd.bus_name, index + 1, port_status);
+
+ // what happens if HCS_N_CC(params) == 0 ?
+ port_status |= PORT_OWNER;
+ writel (port_status, &ehci->regs->port_status [index]);
+
+ } else
+ dbg ("%s port %d high speed", ehci->hcd.bus_name, index + 1);
+
+ return port_status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+/* build "status change" packet (one or two bytes) from HC registers */
+
+static int
+ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ u32 temp, status = 0;
+ int ports, i, retval = 1;
+ unsigned long flags;
+
+ /* init status to no-changes */
+ buf [0] = 0;
+ temp = readl (&ehci->caps->hcs_params);
+ ports = HCS_N_PORTS (temp);
+ if (ports > 7) {
+ buf [1] = 0;
+ retval++;
+ }
+
+ /* no hub change reports (bit 0) for now (power, ...) */
+
+ /* port N changes (bit N)? */
+ spin_lock_irqsave (&ehci->lock, flags);
+ for (i = 0; i < ports; i++) {
+ temp = readl (&ehci->regs->port_status [i]);
+ if (temp & PORT_OWNER) {
+ // get disconnected ports back if no companion driver
+ if (temp & PORT_CONNECT)
+ continue;
+ temp &= ~(PORT_OWNER|PORT_CSC);
+ writel (temp, &ehci->regs->port_status [i]);
+ }
+ if (!(temp & PORT_CONNECT))
+ ehci->reset_done [i] = 0;
+ if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0) {
+ set_bit (i, buf);
+ status = STS_PCD;
+ }
+ }
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ return status ? retval : 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+ehci_hub_descriptor (
+ struct ehci_hcd *ehci,
+ struct usb_hub_descriptor *desc
+) {
+ u32 params = readl (&ehci->caps->hcs_params);
+ int ports = HCS_N_PORTS (params);
+ u16 temp;
+
+ desc->bDescriptorType = 0x29;
+ desc->bPwrOn2PwrGood = 0; /* FIXME: f(system power) */
+ desc->bHubContrCurrent = 0;
+
+ desc->bNbrPorts = ports;
+ temp = 1 + (ports / 8);
+ desc->bDescLength = 7 + 2 * temp;
+
+ /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+ memset (&desc->bitmap [0], 0, temp);
+ memset (&desc->bitmap [temp], 0xff, temp);
+
+ temp = 0x0008; /* per-port overcurrent reporting */
+ if (HCS_PPC (params)) /* per-port power control */
+ temp |= 0x0001;
+ if (HCS_INDICATOR (params)) /* per-port indicators (LEDs) */
+ temp |= 0x0080;
+ desc->wHubCharacteristics = cpu_to_le16 (temp);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int ehci_hub_control (
+ struct usb_hcd *hcd,
+ u16 typeReq,
+ u16 wValue,
+ u16 wIndex,
+ char *buf,
+ u16 wLength
+) {
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+ u32 params = readl (&ehci->caps->hcs_params);
+ int ports = HCS_N_PORTS (params);
+ u32 temp;
+ unsigned long flags;
+ int retval = 0;
+
+ /*
+ * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
+ * HCS_INDICATOR may say we can change LEDs to off/amber/green.
+ * (track current state ourselves) ... blink for diagnostics,
+ * power, "this is the one", etc. EHCI spec supports this.
+ */
+
+ spin_lock_irqsave (&ehci->lock, flags);
+ switch (typeReq) {
+ case ClearHubFeature:
+ switch (wValue) {
+ case C_HUB_LOCAL_POWER:
+ case C_HUB_OVER_CURRENT:
+ /* no hub-wide feature/status flags */
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case ClearPortFeature:
+ if (!wIndex || wIndex > ports)
+ goto error;
+ wIndex--;
+ temp = readl (&ehci->regs->port_status [wIndex]);
+ if (temp & PORT_OWNER)
+ break;
+
+ switch (wValue) {
+ case USB_PORT_FEAT_ENABLE:
+ writel (temp & ~PORT_PE,
+ &ehci->regs->port_status [wIndex]);
+ break;
+ case USB_PORT_FEAT_C_ENABLE:
+ writel (temp | PORT_PEC,
+ &ehci->regs->port_status [wIndex]);
+ break;
+ case USB_PORT_FEAT_SUSPEND:
+ case USB_PORT_FEAT_C_SUSPEND:
+ /* ? */
+ break;
+ case USB_PORT_FEAT_POWER:
+ if (HCS_PPC (params))
+ writel (temp & ~PORT_POWER,
+ &ehci->regs->port_status [wIndex]);
+ break;
+ case USB_PORT_FEAT_C_CONNECTION:
+ writel (temp | PORT_CSC,
+ &ehci->regs->port_status [wIndex]);
+ break;
+ case USB_PORT_FEAT_C_OVER_CURRENT:
+ writel (temp | PORT_OCC,
+ &ehci->regs->port_status [wIndex]);
+ break;
+ case USB_PORT_FEAT_C_RESET:
+ /* GetPortStatus clears reset */
+ break;
+ default:
+ goto error;
+ }
+ readl (&ehci->regs->command); /* unblock posted write */
+ break;
+ case GetHubDescriptor:
+ ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
+ buf);
+ break;
+ case GetHubStatus:
+ /* no hub-wide feature/status flags */
+ memset (buf, 0, 4);
+ //cpu_to_le32s ((u32 *) buf);
+ break;
+ case GetPortStatus:
+ if (!wIndex || wIndex > ports)
+ goto error;
+ wIndex--;
+ memset (buf, 0, 4);
+ temp = readl (&ehci->regs->port_status [wIndex]);
+
+ // wPortChange bits
+ if (temp & PORT_CSC)
+ set_bit (USB_PORT_FEAT_C_CONNECTION, buf);
+ if (temp & PORT_PEC)
+ set_bit (USB_PORT_FEAT_C_ENABLE, buf);
+ // USB_PORT_FEAT_C_SUSPEND
+ if (temp & PORT_OCC)
+ set_bit (USB_PORT_FEAT_C_OVER_CURRENT, buf);
+
+ /* whoever resets must GetPortStatus to complete it!! */
+ if ((temp & PORT_RESET)
+ && jiffies > ehci->reset_done [wIndex]) {
+ set_bit (USB_PORT_FEAT_C_RESET, buf);
+
+ /* force reset to complete */
+ writel (temp & ~PORT_RESET,
+ &ehci->regs->port_status [wIndex]);
+ do {
+ temp = readl (
+ &ehci->regs->port_status [wIndex]);
+ udelay (10);
+ } while (temp & PORT_RESET);
+
+ /* see what we found out */
+ temp = check_reset_complete (ehci, wIndex, temp);
+ }
+
+ // don't show wPortStatus if it's owned by a companion hc
+ if (!(temp & PORT_OWNER)) {
+ if (temp & PORT_CONNECT) {
+ set_bit (USB_PORT_FEAT_CONNECTION, buf);
+ set_bit (USB_PORT_FEAT_HIGHSPEED, buf);
+ }
+ if (temp & PORT_PE)
+ set_bit (USB_PORT_FEAT_ENABLE, buf);
+ if (temp & PORT_SUSPEND)
+ set_bit (USB_PORT_FEAT_SUSPEND, buf);
+ if (temp & PORT_OC)
+ set_bit (USB_PORT_FEAT_OVER_CURRENT, buf);
+ if (temp & PORT_RESET)
+ set_bit (USB_PORT_FEAT_RESET, buf);
+ if (temp & PORT_POWER)
+ set_bit (USB_PORT_FEAT_POWER, buf);
+ }
+
+#ifndef EHCI_VERBOSE_DEBUG
+ if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
+#endif
+ dbg_port (hcd, "GetStatus", wIndex + 1, temp);
+ cpu_to_le32s ((u32 *) buf);
+ break;
+ case SetHubFeature:
+ switch (wValue) {
+ case C_HUB_LOCAL_POWER:
+ case C_HUB_OVER_CURRENT:
+ /* no hub-wide feature/status flags */
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case SetPortFeature:
+ if (!wIndex || wIndex > ports)
+ goto error;
+ wIndex--;
+ temp = readl (&ehci->regs->port_status [wIndex]);
+ if (temp & PORT_OWNER)
+ break;
+
+ switch (wValue) {
+ case USB_PORT_FEAT_SUSPEND:
+ writel (temp | PORT_SUSPEND,
+ &ehci->regs->port_status [wIndex]);
+ break;
+ case USB_PORT_FEAT_POWER:
+ if (HCS_PPC (params))
+ writel (temp | PORT_POWER,
+ &ehci->regs->port_status [wIndex]);
+ break;
+ case USB_PORT_FEAT_RESET:
+ /* line status bits may report this as low speed */
+ if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
+ && PORT_USB11 (temp)) {
+ dbg ("%s port %d low speed, give to companion",
+ hcd->bus_name, wIndex + 1);
+ temp |= PORT_OWNER;
+ } else {
+ vdbg ("%s port %d reset",
+ hcd->bus_name, wIndex + 1);
+ temp |= PORT_RESET;
+ temp &= ~PORT_PE;
+
+ /*
+ * caller must wait, then call GetPortStatus
+ * usb 2.0 spec says 50 ms resets on root
+ */
+ ehci->reset_done [wIndex] = jiffies
+ + ((50 /* msec */ * HZ) / 1000);
+ }
+ writel (temp, &ehci->regs->port_status [wIndex]);
+ break;
+ default:
+ goto error;
+ }
+ readl (&ehci->regs->command); /* unblock posted writes */
+ break;
+
+ default:
+error:
+ /* "stall" on error */
+ retval = -EPIPE;
+ }
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ return retval;
+}
diff --git a/drivers/usb/hcd/ehci-mem.c b/drivers/usb/hcd/ehci-mem.c
new file mode 100644
index 000000000..b2ee617c6
--- /dev/null
+++ b/drivers/usb/hcd/ehci-mem.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * There's basically three types of memory:
+ * - data used only by the HCD ... kmalloc is fine
+ * - async and periodic schedules, shared by HC and HCD ... these
+ * need to use pci_pool or pci_alloc_consistent
+ * - driver buffers, read/written by HC ... single shot DMA mapped
+ *
+ * There's also PCI "register" data, which is memory mapped.
+ * No memory seen by this driver is pagable.
+ */
+
+/*-------------------------------------------------------------------------*/
+/*
+ * Allocator / cleanup for the per device structure
+ * Called by hcd init / removal code
+ */
+static struct usb_hcd *ehci_hcd_alloc (void)
+{
+ struct ehci_hcd *ehci;
+
+ ehci = (struct ehci_hcd *)
+ kmalloc (sizeof (struct ehci_hcd), GFP_KERNEL);
+ if (ehci != 0) {
+ memset (ehci, 0, sizeof (struct ehci_hcd));
+ return &ehci->hcd;
+ }
+ return 0;
+}
+
+static void ehci_hcd_free (struct usb_hcd *hcd)
+{
+ kfree (hcd_to_ehci (hcd));
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Allocate the key transfer structures from the previously allocated pool */
+
+static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
+{
+ struct ehci_qtd *qtd;
+ dma_addr_t dma;
+
+ qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma);
+ if (qtd != 0) {
+ memset (qtd, 0, sizeof *qtd);
+ qtd->qtd_dma = dma;
+ qtd->hw_next = EHCI_LIST_END;
+ qtd->hw_alt_next = EHCI_LIST_END;
+ INIT_LIST_HEAD (&qtd->qtd_list);
+ }
+ return qtd;
+}
+
+static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
+{
+ pci_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
+}
+
+
+static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
+{
+ struct ehci_qh *qh;
+ dma_addr_t dma;
+
+ qh = (struct ehci_qh *)
+ pci_pool_alloc (ehci->qh_pool, flags, &dma);
+ if (qh) {
+ memset (qh, 0, sizeof *qh);
+ atomic_set (&qh->refcount, 1);
+ qh->qh_dma = dma;
+ // INIT_LIST_HEAD (&qh->qh_list);
+ INIT_LIST_HEAD (&qh->qtd_list);
+ }
+ return qh;
+}
+
+/* to share a qh (cpu threads, or hc) */
+static inline struct ehci_qh *qh_put (/* ehci, */ struct ehci_qh *qh)
+{
+ // dbg ("put %p (%d++)", qh, qh->refcount.counter);
+ atomic_inc (&qh->refcount);
+ return qh;
+}
+
+static void qh_unput (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ // dbg ("unput %p (--%d)", qh, qh->refcount.counter);
+ if (!atomic_dec_and_test (&qh->refcount))
+ return;
+ /* clean qtds first, and know this is not linked */
+ if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
+ dbg ("unused qh not empty!");
+ BUG ();
+ }
+ pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* The queue heads and transfer descriptors are managed from pools tied
+ * to each of the "per device" structures.
+ * This is the initialisation and cleanup code.
+ */
+
+static void ehci_mem_cleanup (struct ehci_hcd *ehci)
+{
+ /* PCI consistent memory and pools */
+ if (ehci->qtd_pool)
+ pci_pool_destroy (ehci->qtd_pool);
+ ehci->qtd_pool = 0;
+
+ if (ehci->qh_pool) {
+ pci_pool_destroy (ehci->qh_pool);
+ ehci->qh_pool = 0;
+ }
+
+ if (ehci->itd_pool)
+ pci_pool_destroy (ehci->itd_pool);
+ ehci->itd_pool = 0;
+
+ if (ehci->sitd_pool)
+ pci_pool_destroy (ehci->sitd_pool);
+ ehci->sitd_pool = 0;
+
+ if (ehci->periodic)
+ pci_free_consistent (ehci->hcd.pdev,
+ ehci->periodic_size * sizeof (u32),
+ ehci->periodic, ehci->periodic_dma);
+ ehci->periodic = 0;
+
+ /* shadow periodic table */
+ if (ehci->pshadow)
+ kfree (ehci->pshadow);
+ ehci->pshadow = 0;
+}
+
+/* remember to add cleanup code (above) if you add anything here */
+static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
+{
+ int i;
+
+ /* QTDs for control/bulk/intr transfers */
+ ehci->qtd_pool = pci_pool_create ("ehci_qtd", ehci->hcd.pdev,
+ sizeof (struct ehci_qtd),
+ 32 /* byte alignment (for hw parts) */,
+ 4096 /* can't cross 4K */,
+ flags);
+ if (!ehci->qtd_pool) {
+ dbg ("no qtd pool");
+ ehci_mem_cleanup (ehci);
+ return -ENOMEM;
+ }
+
+ /* QH for control/bulk/intr transfers */
+ ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev,
+ sizeof (struct ehci_qh),
+ 32 /* byte alignment (for hw parts) */,
+ 4096 /* can't cross 4K */,
+ flags);
+ if (!ehci->qh_pool) {
+ dbg ("no qh pool");
+ ehci_mem_cleanup (ehci);
+ return -ENOMEM;
+ }
+
+ /* ITD for high speed ISO transfers */
+ ehci->itd_pool = pci_pool_create ("ehci_itd", ehci->hcd.pdev,
+ sizeof (struct ehci_itd),
+ 32 /* byte alignment (for hw parts) */,
+ 4096 /* can't cross 4K */,
+ flags);
+ if (!ehci->itd_pool) {
+ dbg ("no itd pool");
+ ehci_mem_cleanup (ehci);
+ return -ENOMEM;
+ }
+
+ /* SITD for full/low speed split ISO transfers */
+ ehci->sitd_pool = pci_pool_create ("ehci_sitd", ehci->hcd.pdev,
+ sizeof (struct ehci_sitd),
+ 32 /* byte alignment (for hw parts) */,
+ 4096 /* can't cross 4K */,
+ flags);
+ if (!ehci->sitd_pool) {
+ dbg ("no sitd pool");
+ ehci_mem_cleanup (ehci);
+ return -ENOMEM;
+ }
+
+ /* Hardware periodic table */
+ ehci->periodic = (u32 *)
+ pci_alloc_consistent (ehci->hcd.pdev,
+ ehci->periodic_size * sizeof (u32),
+ &ehci->periodic_dma);
+ if (ehci->periodic == 0) {
+ dbg ("no hw periodic table");
+ ehci_mem_cleanup (ehci);
+ return -ENOMEM;
+ }
+ for (i = 0; i < ehci->periodic_size; i++)
+ ehci->periodic [i] = EHCI_LIST_END;
+
+ /* software shadow of hardware table */
+ ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *),
+ flags & ~EHCI_SLAB_FLAGS);
+ if (ehci->pshadow == 0) {
+ dbg ("no shadow periodic table");
+ ehci_mem_cleanup (ehci);
+ return -ENOMEM;
+ }
+ memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *));
+
+ return 0;
+}
diff --git a/drivers/usb/hcd/ehci-q.c b/drivers/usb/hcd/ehci-q.c
new file mode 100644
index 000000000..25a305dc1
--- /dev/null
+++ b/drivers/usb/hcd/ehci-q.c
@@ -0,0 +1,949 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI hardware queue manipulation
+ *
+ * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd"
+ * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
+ * buffers needed for the larger number). We use one QH per endpoint, queue
+ * multiple (bulk or control) urbs per endpoint. URBs may need several qtds.
+ * A scheduled interrupt qh always has one qtd, one urb.
+ *
+ * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with
+ * interrupts) needs careful scheduling. Performance improvements can be
+ * an ongoing challenge.
+ *
+ * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
+ * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
+ * (b) special fields in qh entries or (c) split iso entries. TTs will
+ * buffer low/full speed data so the host collects it at high speed.
+ */
+
+#ifdef EHCI_SOFT_RETRIES
+static int soft_retries = EHCI_SOFT_RETRIES;
+MODULE_PARM (soft_retries, "i");
+MODULE_PARM_DESC (soft_retries, "Number of software retries for endpoint i/o");
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* fill a qtd, returning how much of the buffer we were able to queue up */
+
+static int
+qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token)
+{
+ int i, count;
+
+ /* one buffer entry per 4K ... first might be short or unaligned */
+ qtd->hw_buf [0] = cpu_to_le32 (buf);
+ count = 0x1000 - (buf & 0x0fff); /* rest of that page */
+ if (likely (len < count)) /* ... iff needed */
+ count = len;
+ else {
+ buf += 0x1000;
+ buf &= ~0x0fff;
+
+ /* per-qtd limit: from 16K to 20K (best alignment) */
+ for (i = 1; count < len && i < 5; i++) {
+ u64 addr = buf;
+ qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
+ qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
+ buf += 0x1000;
+ if ((count + 0x1000) < len)
+ count += 0x1000;
+ else
+ count = len;
+ }
+ }
+ qtd->hw_token = cpu_to_le32 ((count << 16) | token);
+ qtd->length = count;
+
+#if 0
+ vdbg (" qtd_fill %p, token %8x bytes %d dma %x",
+ qtd, le32_to_cpu (qtd->hw_token), count, qtd->hw_buf [0]);
+#endif
+
+ return count;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* update halted (but potentially linked) qh */
+
+static inline void qh_update (struct ehci_qh *qh, struct ehci_qtd *qtd)
+{
+ qh->hw_current = 0;
+ qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
+ qh->hw_alt_next = EHCI_LIST_END;
+
+ /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
+ qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token)
+{
+ /* count IN/OUT bytes, not SETUP (even short packets) */
+ if (likely (QTD_PID (token) != 2))
+ urb->actual_length += length - QTD_LENGTH (token);
+
+ /* don't modify error codes */
+ if (unlikely (urb->status == -EINPROGRESS && (token & QTD_STS_HALT))) {
+ if (token & QTD_STS_BABBLE) {
+ urb->status = -EOVERFLOW;
+ } else if (!QTD_CERR (token)) {
+ if (token & QTD_STS_DBE)
+ urb->status = (QTD_PID (token) == 1) /* IN ? */
+ ? -ENOSR /* hc couldn't read data */
+ : -ECOMM; /* hc couldn't write data */
+ else if (token & QTD_STS_MMF) /* missed tt uframe */
+ urb->status = -EPROTO;
+ else if (token & QTD_STS_XACT) {
+ if (QTD_LENGTH (token))
+ urb->status = -EPIPE;
+ else {
+ dbg ("3strikes");
+ urb->status = -EPROTO;
+ }
+ } else /* presumably a stall */
+ urb->status = -EPIPE;
+
+ /* CERR nonzero + data left + halt --> stall */
+ } else if (QTD_LENGTH (token))
+ urb->status = -EPIPE;
+ else /* unknown */
+ urb->status = -EPROTO;
+ dbg ("devpath %s ep %d-%s qtd token %x --> status %d",
+ urb->dev->devpath, usb_pipeendpoint (urb->pipe),
+ usb_pipein (urb->pipe) ? "in" : "out",
+ token, urb->status);
+
+ /* stall indicates some recovery action is needed */
+ if (urb->status == -EPIPE) {
+ int pipe = urb->pipe;
+
+ if (!usb_pipecontrol (pipe))
+ usb_endpoint_halt (urb->dev,
+ usb_pipeendpoint (pipe),
+ usb_pipeout (pipe));
+ if (urb->dev->tt && !usb_pipeint (pipe)) {
+err ("must CLEAR_TT_BUFFER, hub %s port %d%s addr %d ep %d",
+ urb->dev->tt->hub->devpath, urb->dev->ttport,
+ urb->dev->tt->multi ? "" : " (all-ports TT)",
+ urb->dev->devnum, usb_pipeendpoint (urb->pipe));
+ // FIXME something (khubd?) should make the hub
+ // CLEAR_TT_BUFFER ASAP, it's blocking other
+ // fs/ls requests... hub_tt_clear_buffer() ?
+ }
+ }
+ }
+}
+
+static void ehci_urb_complete (
+ struct ehci_hcd *ehci,
+ dma_addr_t addr,
+ struct urb *urb
+) {
+ if (urb->transfer_buffer_length && usb_pipein (urb->pipe))
+ pci_dma_sync_single (ehci->hcd.pdev, addr,
+ urb->transfer_buffer_length,
+ PCI_DMA_FROMDEVICE);
+
+ /* cleanse status if we saw no error */
+ if (likely (urb->status == -EINPROGRESS)) {
+ if (urb->actual_length != urb->transfer_buffer_length
+ && (urb->transfer_flags & USB_DISABLE_SPD))
+ urb->status = -EREMOTEIO;
+ else
+ urb->status = 0;
+ }
+
+ /* only report unlinks once */
+ if (likely (urb->status != -ENOENT && urb->status != -ENOTCONN))
+ urb->complete (urb);
+}
+
+/* urb->lock ignored from here on (hcd is done with urb) */
+
+static void ehci_urb_done (
+ struct ehci_hcd *ehci,
+ dma_addr_t addr,
+ struct urb *urb
+) {
+ if (urb->transfer_buffer_length)
+ pci_unmap_single (ehci->hcd.pdev,
+ addr,
+ urb->transfer_buffer_length,
+ usb_pipein (urb->pipe)
+ ? PCI_DMA_FROMDEVICE
+ : PCI_DMA_TODEVICE);
+ if (likely (urb->hcpriv != 0)) {
+ qh_unput (ehci, (struct ehci_qh *) urb->hcpriv);
+ urb->hcpriv = 0;
+ }
+
+ if (likely (urb->status == -EINPROGRESS)) {
+ if (urb->actual_length != urb->transfer_buffer_length
+ && (urb->transfer_flags & USB_DISABLE_SPD))
+ urb->status = -EREMOTEIO;
+ else
+ urb->status = 0;
+ }
+
+ /* hand off urb ownership */
+ usb_hcd_giveback_urb (&ehci->hcd, urb);
+}
+
+
+/*
+ * Process completed qtds for a qh, issuing completions if needed.
+ * When freeing: frees qtds, unmaps buf, returns URB to driver.
+ * When not freeing (queued periodic qh): retain qtds, mapping, and urb.
+ * Races up to qh->hw_current; returns number of urb completions.
+ */
+static int
+qh_completions (
+ struct ehci_hcd *ehci,
+ struct list_head *qtd_list,
+ int freeing
+) {
+ struct ehci_qtd *qtd = 0;
+ struct list_head *next = 0;
+ u32 token;
+ struct ehci_qh *qh = 0;
+ struct urb *urb = 0;
+ int halted = 0;
+ unsigned long flags;
+ int retval = 0;
+
+ spin_lock_irqsave (&ehci->lock, flags);
+ if (unlikely (list_empty (qtd_list))) {
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ return retval;
+ }
+
+ for (qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
+ next != qtd_list;
+ qtd = list_entry (next, struct ehci_qtd, qtd_list)) {
+ token = le32_to_cpu (qtd->hw_token);
+ if (!qh) {
+ urb = qtd->urb;
+ qh = (struct ehci_qh *) urb->hcpriv;
+ }
+ if (likely (qh != 0)) {
+ halted = halted
+ || (ehci->hcd.state == USB_STATE_HALT)
+ || (qh->qh_state == QH_STATE_IDLE);
+
+ if (unlikely ((token & QTD_STS_HALT) != 0)) {
+#ifdef EHCI_SOFT_RETRIES
+ /* extra soft retries for protocol errors */
+ if (!halted
+ && qh->retries < soft_retries
+ && (QTD_STS_HALT|QTD_STS_XACT)
+ == (token & 0xff)
+ && QTD_CERR (token) == 0) {
+ if (qh->retries == 0)
+ dbg ("soft retry, qh %p qtd %p",
+ qh, qtd);
+ qh->retries++;
+ token &= ~0x0ff;
+ token |= QTD_STS_ACTIVE;
+ token |= (EHCI_TUNE_CERR << 10);
+ /* qtd update not needed */
+ qh->hw_token = cpu_to_le32 (token);
+ spin_unlock_irqrestore (&ehci->lock,
+ flags);
+ return;
+
+ } else if (qh->retries >= soft_retries
+ && soft_retries) {
+ dbg ("retried %d times, qh %p qtd %p",
+ qh->retries, qh, qtd);
+ }
+#endif /* EHCI_SOFT_RETRIES */
+ halted = 1;
+ }
+
+ if (unlikely ((token & QTD_STS_ACTIVE) != 0)) {
+ /* stop scan if qtd is visible to the HC */
+ if (!halted) {
+ urb = 0;
+ break;
+ }
+
+ /* continue cleanup if HC is halted */
+ if (ehci->hcd.state == USB_STATE_HALT) {
+ urb->status = -ESHUTDOWN;
+ goto scrub;
+ }
+
+ /* stall? some other urb was unlinked? */
+ if (urb->status == -EINPROGRESS) {
+dbg ("?why? qh %p, qtd %p halted, urb %p, token %8x, len %d",
+ qh, qtd, urb, token, urb->actual_length);
+spin_unlock_irqrestore (&ehci->lock, flags);
+return retval;
+ /*
+ * FIXME: write this code. When one queued urb is unlinked,
+ * unlink every succeeding urb.
+ */
+ continue;
+ }
+
+ /* else stopped for some other reason */
+ }
+scrub:
+ spin_lock (&urb->lock);
+ qtd_copy_status (urb, qtd->length, token);
+ spin_unlock (&urb->lock);
+ }
+ next = qtd->qtd_list.next;
+
+ /*
+ * NOTE: this won't work right with interrupt urbs that
+ * need multiple qtds ... only the first scan of qh->qtd_list
+ * starts at the right qtd, yet multiple scans could happen
+ * for transfers that are scheduled across multiple uframes.
+ */
+ if (likely (freeing != 0))
+ list_del (&qtd->qtd_list);
+ else {
+ /* restore everything the HC could change
+ * from an interrupt QTD
+ */
+ qtd->hw_token = (qtd->hw_token
+ & ~__constant_cpu_to_le32 (0x8300))
+ | cpu_to_le32 (qtd->length << 16)
+ | __constant_cpu_to_le32 (QTD_IOC
+ | (EHCI_TUNE_CERR << 10)
+ | QTD_STS_ACTIVE);
+ qtd->hw_buf [0] &= ~__constant_cpu_to_le32 (0x0fff);
+
+ /* this offset, and the length above,
+ * are likely wrong on QTDs #2..N
+ */
+ qtd->hw_buf [0] |= cpu_to_le32 (0x0fff & qtd->buf_dma);
+ }
+
+ spin_unlock_irqrestore (&ehci->lock, flags);
+
+#if 0
+ if (urb->status == -EINPROGRESS)
+ vdbg (" qtd %p ok, urb %p, token %8x, len %d",
+ qtd, urb, token, urb->actual_length);
+ else
+ vdbg ("urb %p status %d, qtd %p, token %8x, len %d",
+ urb, urb->status, qtd, token,
+ urb->actual_length);
+#endif
+
+ /* SETUP for control urb? */
+ if (unlikely (QTD_PID (token) == 2))
+ pci_unmap_single (ehci->hcd.pdev,
+ qtd->buf_dma, sizeof (devrequest),
+ PCI_DMA_TODEVICE);
+
+ /* another queued urb? */
+ if (unlikely (qtd->urb != urb)) {
+ if (likely (freeing != 0))
+ ehci_urb_done (ehci, qtd->buf_dma, urb);
+ else
+ ehci_urb_complete (ehci, qtd->buf_dma, urb);
+ retval++;
+ urb = qtd->urb;
+ }
+
+ if (likely (freeing != 0))
+ ehci_qtd_free (ehci, qtd);
+ spin_lock_irqsave (&ehci->lock, flags);
+ qtd = list_entry (next, struct ehci_qtd, qtd_list);
+ }
+
+ /* patch up list head? */
+ if (unlikely (halted && qh && !list_empty (qtd_list))) {
+ qh_update (qh, list_entry (qtd_list->next,
+ struct ehci_qtd, qtd_list));
+ }
+ spin_unlock_irqrestore (&ehci->lock, flags);
+
+ /* last urb's completion might still need calling */
+ if (likely (qtd && urb)) {
+ if (likely (freeing != 0))
+ ehci_urb_done (ehci, qtd->buf_dma, urb);
+ else
+ ehci_urb_complete (ehci, qtd->buf_dma, urb);
+ retval++;
+ }
+ return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * create a list of filled qtds for this URB; won't link into qh.
+ */
+static struct list_head *
+qh_urb_transaction (
+ struct ehci_hcd *ehci,
+ struct urb *urb,
+ struct list_head *head,
+ int flags
+) {
+ struct ehci_qtd *qtd, *qtd_prev;
+ dma_addr_t buf, map_buf;
+ int len, maxpacket;
+ u32 token;
+
+ /*
+ * URBs map to sequences of QTDs: one logical transaction
+ */
+ qtd = ehci_qtd_alloc (ehci, flags);
+ if (unlikely (!qtd))
+ return 0;
+ qtd_prev = 0;
+ list_add_tail (&qtd->qtd_list, head);
+ qtd->urb = urb;
+
+ token = QTD_STS_ACTIVE;
+ token |= (EHCI_TUNE_CERR << 10);
+ /* for split transactions, SplitXState initialized to zero */
+
+ if (usb_pipecontrol (urb->pipe)) {
+ /* control request data is passed in the "setup" pid */
+
+ /* NOTE: this isn't smart about 64bit DMA, since it uses the
+ * default (32bit) mask rather than using the whole address
+ * space. we could set pdev->dma_mask to all-ones while
+ * getting this mapping, locking it and restoring before
+ * allocating qtd/qh/... or maybe only do that for the main
+ * data phase (below).
+ */
+ qtd->buf_dma = pci_map_single (
+ ehci->hcd.pdev,
+ urb->setup_packet,
+ sizeof (devrequest),
+ PCI_DMA_TODEVICE);
+ if (unlikely (!qtd->buf_dma))
+ goto cleanup;
+
+ /* SETUP pid */
+ qtd_fill (qtd, qtd->buf_dma, sizeof (devrequest),
+ token | (2 /* "setup" */ << 8));
+
+ /* ... and always at least one more pid */
+ token ^= QTD_TOGGLE;
+ qtd_prev = qtd;
+ qtd = ehci_qtd_alloc (ehci, flags);
+ if (unlikely (!qtd))
+ goto cleanup;
+ qtd->urb = urb;
+ qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+ list_add_tail (&qtd->qtd_list, head);
+ }
+
+ /*
+ * data transfer stage: buffer setup
+ */
+ len = urb->transfer_buffer_length;
+ if (likely (len > 0)) {
+ /* NOTE: sub-optimal mapping with 64bit DMA (see above) */
+ buf = map_buf = pci_map_single (ehci->hcd.pdev,
+ urb->transfer_buffer, len,
+ usb_pipein (urb->pipe)
+ ? PCI_DMA_FROMDEVICE
+ : PCI_DMA_TODEVICE);
+ if (unlikely (!buf))
+ goto cleanup;
+ } else
+ buf = map_buf = 0;
+
+ if (!buf || usb_pipein (urb->pipe))
+ token |= (1 /* "in" */ << 8);
+ /* else it's already initted to "out" pid (0 << 8) */
+
+ maxpacket = usb_maxpacket (urb->dev, urb->pipe,
+ usb_pipeout (urb->pipe));
+
+ /*
+ * buffer gets wrapped in one or more qtds;
+ * last one may be "short" (including zero len)
+ * and may serve as a control status ack
+ */
+ for (;;) {
+ int this_qtd_len;
+
+ qtd->urb = urb;
+ qtd->buf_dma = map_buf;
+ this_qtd_len = qtd_fill (qtd, buf, len, token);
+ len -= this_qtd_len;
+ buf += this_qtd_len;
+
+ /* qh makes control packets use qtd toggle; maybe switch it */
+ if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
+ token ^= QTD_TOGGLE;
+
+ if (likely (len <= 0))
+ break;
+
+ qtd_prev = qtd;
+ qtd = ehci_qtd_alloc (ehci, flags);
+ if (unlikely (!qtd))
+ goto cleanup;
+ qtd->urb = urb;
+ qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+ list_add_tail (&qtd->qtd_list, head);
+ }
+
+ /*
+ * control requests may need a terminating data "status" ack;
+ * bulk ones may need a terminating short packet (zero length).
+ */
+ if (likely (buf != 0)) {
+ int one_more = 0;
+
+ if (usb_pipecontrol (urb->pipe)) {
+ one_more = 1;
+ token ^= 0x0100; /* "in" <--> "out" */
+ token |= QTD_TOGGLE; /* force DATA1 */
+ } else if (usb_pipebulk (urb->pipe)
+ && (urb->transfer_flags & USB_ZERO_PACKET)
+ && !(urb->transfer_buffer_length % maxpacket)) {
+ one_more = 1;
+ }
+ if (one_more) {
+ qtd_prev = qtd;
+ qtd = ehci_qtd_alloc (ehci, flags);
+ if (unlikely (!qtd))
+ goto cleanup;
+ qtd->urb = urb;
+ qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+ list_add_tail (&qtd->qtd_list, head);
+
+ /* never any data in such packets */
+ qtd_fill (qtd, 0, 0, token);
+ }
+ }
+
+ /* by default, enable interrupt on urb completion */
+ if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
+ qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
+ return head;
+
+cleanup:
+ urb->status = -ENOMEM;
+ qh_completions (ehci, head, 1);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Hardware maintains data toggle (like OHCI) ... here we (re)initialize
+ * the hardware data toggle in the QH, and set the pseudo-toggle in udev
+ * so we can see if usb_clear_halt() was called. NOP for control, since
+ * we set up qh->hw_info1 to always use the QTD toggle bits.
+ */
+static inline void
+clear_toggle (struct usb_device *udev, int ep, int is_out, struct ehci_qh *qh)
+{
+ vdbg ("clear toggle, dev %d ep 0x%x-%s",
+ udev->devnum, ep, is_out ? "out" : "in");
+ qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
+ usb_settoggle (udev, ep, is_out, 1);
+}
+
+// Would be best to create all qh's from config descriptors,
+// when each interface/altsetting is established. Unlink
+// any previous qh and cancel its urbs first; endpoints are
+// implicitly reset then (data toggle too).
+// That'd mean updating how usbcore talks to HCDs. (2.5?)
+
+
+/*
+ * Each QH holds a qtd list; a QH is used for everything except iso.
+ *
+ * For interrupt urbs, the scheduler must set the microframe scheduling
+ * mask(s) each time the QH gets scheduled. For highspeed, that's
+ * just one microframe in the s-mask. For split interrupt transactions
+ * there are additional complications: c-mask, maybe FSTNs.
+ */
+static struct ehci_qh *
+ehci_qh_make (
+ struct ehci_hcd *ehci,
+ struct urb *urb,
+ struct list_head *qtd_list,
+ int flags
+) {
+ struct ehci_qh *qh = ehci_qh_alloc (ehci, flags);
+ u32 info1 = 0, info2 = 0;
+
+ if (!qh)
+ return qh;
+
+ /*
+ * init endpoint/device data for this QH
+ */
+ info1 |= usb_pipeendpoint (urb->pipe) << 8;
+ info1 |= usb_pipedevice (urb->pipe) << 0;
+
+ /* using TT? */
+ switch (urb->dev->speed) {
+ case USB_SPEED_LOW:
+ info1 |= (1 << 12); /* EPS "low" */
+ /* FALL THROUGH */
+
+ case USB_SPEED_FULL:
+ /* EPS 0 means "full" */
+ info1 |= (EHCI_TUNE_RL_TT << 28);
+ if (usb_pipecontrol (urb->pipe)) {
+ info1 |= (1 << 27); /* for TT */
+ info1 |= 1 << 14; /* toggle from qtd */
+ }
+ info1 |= usb_maxpacket (urb->dev, urb->pipe,
+ usb_pipeout (urb->pipe)) << 16;
+
+ info2 |= (EHCI_TUNE_MULT_TT << 30);
+ info2 |= urb->dev->ttport << 23;
+ info2 |= urb->dev->tt->hub->devnum << 16;
+
+ /* NOTE: if (usb_pipeint (urb->pipe)) { scheduler sets c-mask }
+ * ... and a 0.96 scheduler might use FSTN nodes too
+ */
+ break;
+
+ case USB_SPEED_HIGH: /* no TT involved */
+ info1 |= (2 << 12); /* EPS "high" */
+ info1 |= (EHCI_TUNE_RL_HS << 28);
+ if (usb_pipecontrol (urb->pipe)) {
+ info1 |= 64 << 16; /* usb2 fixed maxpacket */
+ info1 |= 1 << 14; /* toggle from qtd */
+ } else if (usb_pipebulk (urb->pipe)) {
+ info1 |= 512 << 16; /* usb2 fixed maxpacket */
+ info2 |= (EHCI_TUNE_MULT_HS << 30);
+ } else
+ info1 |= usb_maxpacket (urb->dev, urb->pipe,
+ usb_pipeout (urb->pipe)) << 16;
+ break;
+ default:
+#ifdef DEBUG
+ BUG ();
+#endif
+ }
+
+ /* NOTE: if (usb_pipeint (urb->pipe)) { scheduler sets s-mask } */
+
+ qh->qh_state = QH_STATE_IDLE;
+ qh->hw_info1 = cpu_to_le32 (info1);
+ qh->hw_info2 = cpu_to_le32 (info2);
+
+ /* initialize sw and hw queues with these qtds */
+ list_splice (qtd_list, &qh->qtd_list);
+ qh_update (qh, list_entry (qtd_list->next, struct ehci_qtd, qtd_list));
+
+ /* initialize data toggle state */
+ if (!usb_pipecontrol (urb->pipe))
+ clear_toggle (urb->dev,
+ usb_pipeendpoint (urb->pipe),
+ usb_pipeout (urb->pipe),
+ qh);
+
+ return qh;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* move qh (and its qtds) onto async queue; maybe enable queue. */
+
+static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ u32 dma = QH_NEXT (qh->qh_dma);
+ struct ehci_qh *q;
+
+ if (unlikely (!(q = ehci->async))) {
+ u32 cmd = readl (&ehci->regs->command);
+
+ /* in case a clear of CMD_ASE didn't take yet */
+ while (readl (&ehci->regs->status) & STS_ASS)
+ udelay (100);
+
+ qh->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
+ qh->qh_next.qh = qh;
+ qh->hw_next = dma;
+ ehci->async = qh;
+ writel ((u32)qh->qh_dma, &ehci->regs->async_next);
+ cmd |= CMD_ASE | CMD_RUN;
+ writel (cmd, &ehci->regs->command);
+ ehci->hcd.state = USB_STATE_RUNNING;
+ /* posted write need not be known to HC yet ... */
+ } else {
+ /* splice right after "start" of ring */
+ qh->hw_info1 &= ~__constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
+ qh->qh_next = q->qh_next;
+ qh->hw_next = q->hw_next;
+ q->qh_next.qh = qh;
+ q->hw_next = dma;
+ }
+ qh->qh_state = QH_STATE_LINKED;
+ /* qtd completions reported later by interrupt */
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+submit_async (
+ struct ehci_hcd *ehci,
+ struct urb *urb,
+ struct list_head *qtd_list,
+ int mem_flags
+) {
+ struct ehci_qtd *qtd;
+ struct hcd_dev *dev;
+ int epnum;
+ unsigned long flags;
+ struct ehci_qh *qh = 0;
+
+ qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
+ dev = (struct hcd_dev *)urb->dev->hcpriv;
+ epnum = usb_pipeendpoint (urb->pipe);
+ if (usb_pipein (urb->pipe))
+ epnum |= 0x10;
+
+ vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]",
+ ehci->hcd.bus_name, urb, urb->transfer_buffer_length,
+ epnum & 0x0f, (epnum & 0x10) ? "in" : "out",
+ qtd, dev ? dev->ep [epnum] : (void *)~0);
+
+ spin_lock_irqsave (&ehci->lock, flags);
+
+ qh = (struct ehci_qh *) dev->ep [epnum];
+ if (likely (qh != 0)) {
+ u32 hw_next = QTD_NEXT (qtd->qtd_dma);
+
+ /* maybe patch the qh used for set_address */
+ if (unlikely (epnum == 0
+ && le32_to_cpu (qh->hw_info1 & 0x7f) == 0))
+ qh->hw_info1 |= cpu_to_le32 (usb_pipedevice(urb->pipe));
+
+ /* is an URB is queued to this qh already? */
+ if (unlikely (!list_empty (&qh->qtd_list))) {
+ struct ehci_qtd *last_qtd;
+
+ // dbg_qh ("non-empty qh", ehci, qh);
+ last_qtd = list_entry (qh->qtd_list.prev,
+ struct ehci_qtd, qtd_list);
+ last_qtd->hw_next = hw_next;
+
+ /* previous urb allows short rx? maybe optimize. */
+ if (!(last_qtd->urb->transfer_flags & USB_DISABLE_SPD)
+ && (epnum & 0x10)) {
+ // only the last QTD for now
+ last_qtd->hw_alt_next = hw_next;
+ }
+
+ /* no URB queued */
+ } else {
+ // dbg_qh ("empty qh", ehci, qh);
+
+// FIXME: how handle usb_clear_halt() for an EP with queued URBs?
+// usbcore may not let us handle that cleanly...
+// likely must cancel them all first!
+
+ /* usb_clear_halt() means qh data toggle gets reset */
+ if (usb_pipebulk (urb->pipe)
+ && unlikely (!usb_gettoggle (urb->dev,
+ (epnum & 0x0f),
+ !(epnum & 0x10)))) {
+ clear_toggle (urb->dev,
+ epnum & 0x0f, !(epnum & 0x10), qh);
+ }
+ qh_update (qh, qtd);
+ }
+ list_splice (qtd_list, qh->qtd_list.prev);
+
+ } else {
+ /* can't sleep here, we have ehci->lock... */
+ qh = ehci_qh_make (ehci, urb, qtd_list, SLAB_ATOMIC);
+ if (likely (qh != 0)) {
+ // dbg_qh ("new qh", ehci, qh);
+ dev->ep [epnum] = qh;
+ } else
+ urb->status = -ENOMEM;
+ }
+
+ /* Control/bulk operations through TTs don't need scheduling,
+ * the HC and TT handle it when the TT has a buffer ready.
+ */
+ if (likely (qh != 0)) {
+ urb->hcpriv = qh_put (qh);
+ if (likely (qh->qh_state == QH_STATE_IDLE))
+ qh_link_async (ehci, qh_put (qh));
+ }
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ if (unlikely (!qh))
+ qh_completions (ehci, qtd_list, 1);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* the async qh for the qtds being reclaimed are now unlinked from the HC */
+/* caller must not own ehci->lock */
+
+static void end_unlink_async (struct ehci_hcd *ehci)
+{
+ struct ehci_qh *qh = ehci->reclaim;
+
+ qh->qh_state = QH_STATE_IDLE;
+ qh->qh_next.qh = 0;
+ qh_unput (ehci, qh); // refcount from reclaim
+ ehci->reclaim = 0;
+ ehci->reclaim_ready = 0;
+
+ qh_completions (ehci, &qh->qtd_list, 1);
+
+ // FIXME unlink any urb should unlink all following urbs,
+ // so that this will never happen
+ if (!list_empty (&qh->qtd_list)
+ && HCD_IS_RUNNING (ehci->hcd.state))
+ qh_link_async (ehci, qh);
+ else
+ qh_unput (ehci, qh); // refcount from async list
+}
+
+
+/* makes sure the async qh will become idle */
+/* caller must own ehci->lock */
+
+static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ int cmd = readl (&ehci->regs->command);
+ struct ehci_qh *prev;
+
+#ifdef DEBUG
+ if (ehci->reclaim
+ || !ehci->async
+ || qh->qh_state != QH_STATE_LINKED
+#ifdef CONFIG_SMP
+// this macro lies except on SMP compiles
+ || !spin_is_locked (&ehci->lock)
+#endif
+ )
+ BUG ();
+#endif
+
+ qh->qh_state = QH_STATE_UNLINK;
+ ehci->reclaim = qh = qh_put (qh);
+
+ // dbg_qh ("start unlink", ehci, qh);
+
+ /* Remove the last QH (qhead)? Stop async schedule first. */
+ if (unlikely (qh == ehci->async && qh->qh_next.qh == qh)) {
+ /* can't get here without STS_ASS set */
+ if (ehci->hcd.state != USB_STATE_HALT) {
+ if (cmd & CMD_PSE)
+ writel (cmd & __constant_cpu_to_le32 (~CMD_ASE),
+ &ehci->regs->command);
+ else {
+ ehci_ready (ehci);
+ while (!(readl (&ehci->regs->status) & STS_ASS))
+ udelay (100);
+ }
+ }
+ qh->qh_next.qh = ehci->async = 0;
+
+ ehci->reclaim_ready = 1;
+ tasklet_schedule (&ehci->tasklet);
+ return;
+ }
+
+ if (unlikely (ehci->hcd.state == USB_STATE_HALT)) {
+ ehci->reclaim_ready = 1;
+ tasklet_schedule (&ehci->tasklet);
+ return;
+ }
+
+ prev = ehci->async;
+ while (prev->qh_next.qh != qh && prev->qh_next.qh != ehci->async)
+ prev = prev->qh_next.qh;
+#ifdef DEBUG
+ if (prev->qh_next.qh != qh)
+ BUG ();
+#endif
+
+ if (qh->hw_info1 & __constant_cpu_to_le32 (QH_HEAD)) {
+ ehci->async = prev;
+ prev->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD);
+ }
+ prev->hw_next = qh->hw_next;
+ prev->qh_next = qh->qh_next;
+
+ ehci->reclaim_ready = 0;
+ cmd |= CMD_IAAD;
+ writel (cmd, &ehci->regs->command);
+ /* posted write need not be known to HC yet ... */
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void scan_async (struct ehci_hcd *ehci)
+{
+ struct ehci_qh *qh;
+ unsigned long flags;
+
+ spin_lock_irqsave (&ehci->lock, flags);
+rescan:
+ qh = ehci->async;
+ if (likely (qh != 0)) {
+ do {
+ /* clean any finished work for this qh */
+ if (!list_empty (&qh->qtd_list)) {
+ // dbg_qh ("scan_async", ehci, qh);
+ qh = qh_put (qh);
+ spin_unlock_irqrestore (&ehci->lock, flags);
+
+ /* concurrent unlink could happen here */
+ qh_completions (ehci, &qh->qtd_list, 1);
+
+ spin_lock_irqsave (&ehci->lock, flags);
+ qh_unput (ehci, qh);
+ }
+
+ /* unlink idle entries (reduces PCI usage) */
+ if (list_empty (&qh->qtd_list) && !ehci->reclaim) {
+ if (qh->qh_next.qh != qh) {
+ // dbg ("irq/empty");
+ start_unlink_async (ehci, qh);
+ } else {
+ // FIXME: arrange to stop
+ // after it's been idle a while.
+ }
+ }
+ qh = qh->qh_next.qh;
+ if (!qh) /* unlinked? */
+ goto rescan;
+ } while (qh != ehci->async);
+ }
+
+ spin_unlock_irqrestore (&ehci->lock, flags);
+}
diff --git a/drivers/usb/hcd/ehci-sched.c b/drivers/usb/hcd/ehci-sched.c
new file mode 100644
index 000000000..905e506f3
--- /dev/null
+++ b/drivers/usb/hcd/ehci-sched.c
@@ -0,0 +1,1053 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI scheduled transaction support: interrupt, iso, split iso
+ * These are called "periodic" transactions in the EHCI spec.
+ */
+
+/*
+ * Ceiling microseconds (typical) for that many bytes at high speed
+ * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
+ * to preallocate bandwidth)
+ */
+#define EHCI_HOST_DELAY 5 /* nsec, guess */
+#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \
+ + ((2083UL * (3167 + BitTime (bytes)))/1000) \
+ + EHCI_HOST_DELAY)
+#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \
+ + ((2083UL * (3167 + BitTime (bytes)))/1000) \
+ + EHCI_HOST_DELAY)
+
+static int ehci_get_frame (struct usb_hcd *hcd);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * periodic_next_shadow - return "next" pointer on shadow list
+ * @periodic: host pointer to qh/itd/sitd
+ * @tag: hardware tag for type of this record
+ */
+static union ehci_shadow *
+periodic_next_shadow (union ehci_shadow *periodic, int tag)
+{
+ switch (tag) {
+ case Q_TYPE_QH:
+ return &periodic->qh->qh_next;
+ case Q_TYPE_FSTN:
+ return &periodic->fstn->fstn_next;
+#ifdef have_iso
+ case Q_TYPE_ITD:
+ return &periodic->itd->itd_next;
+ case Q_TYPE_SITD:
+ return &periodic->sitd->sitd_next;
+#endif /* have_iso */
+ }
+ dbg ("BAD shadow %p tag %d", periodic->ptr, tag);
+ // BUG ();
+ return 0;
+}
+
+/* returns true after successful unlink */
+/* caller must hold ehci->lock */
+static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
+{
+ union ehci_shadow *prev_p = &ehci->pshadow [frame];
+ u32 *hw_p = &ehci->periodic [frame];
+ union ehci_shadow here = *prev_p;
+ union ehci_shadow *next_p;
+
+ /* find predecessor of "ptr"; hw and shadow lists are in sync */
+ while (here.ptr && here.ptr != ptr) {
+ prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
+ hw_p = &here.qh->hw_next;
+ here = *prev_p;
+ }
+ /* an interrupt entry (at list end) could have been shared */
+ if (!here.ptr) {
+ dbg ("entry %p no longer on frame [%d]", ptr, frame);
+ return 0;
+ }
+ // vdbg ("periodic unlink %p from frame %d", ptr, frame);
+
+ /* update hardware list ... HC may still know the old structure, so
+ * don't change hw_next until it'll have purged its cache
+ */
+ next_p = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
+ *hw_p = here.qh->hw_next;
+
+ /* unlink from shadow list; HCD won't see old structure again */
+ *prev_p = *next_p;
+ next_p->ptr = 0;
+
+ return 1;
+}
+
+/* how many of the uframe's 125 usecs are allocated? */
+static unsigned short
+periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
+{
+ u32 *hw_p = &ehci->periodic [frame];
+ union ehci_shadow *q = &ehci->pshadow [frame];
+ unsigned usecs = 0;
+#ifdef have_iso
+ u32 temp = 0;
+#endif
+
+ while (q->ptr) {
+ switch (Q_NEXT_TYPE (*hw_p)) {
+ case Q_TYPE_QH:
+ /* is it in the S-mask? */
+ if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
+ usecs += q->qh->usecs;
+ q = &q->qh->qh_next;
+ break;
+ case Q_TYPE_FSTN:
+ /* for "save place" FSTNs, count the relevant INTR
+ * bandwidth from the previous frame
+ */
+ if (q->fstn->hw_prev != EHCI_LIST_END) {
+ dbg ("not counting FSTN bandwidth yet ...");
+ }
+ q = &q->fstn->fstn_next;
+ break;
+#ifdef have_iso
+ case Q_TYPE_ITD:
+ temp = le32_to_cpu (q->itd->transaction [uframe]);
+ temp >>= 16;
+ temp &= 0x0fff;
+ if (temp)
+ usecs += HS_USECS_ISO (temp);
+ q = &q->itd->itd_next;
+ break;
+ case Q_TYPE_SITD:
+ temp = q->sitd->hw_fullspeed_ep &
+ __constant_cpu_to_le32 (1 << 31);
+
+ // FIXME: this doesn't count data bytes right...
+
+ /* is it in the S-mask? (count SPLIT, DATA) */
+ if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
+ if (temp)
+ usecs += HS_USECS (188);
+ else
+ usecs += HS_USECS (1);
+ }
+
+ /* ... C-mask? (count CSPLIT, DATA) */
+ if (q->sitd->hw_uframe &
+ cpu_to_le32 (1 << (8 + uframe))) {
+ if (temp)
+ usecs += HS_USECS (0);
+ else
+ usecs += HS_USECS (188);
+ }
+ q = &q->sitd->sitd_next;
+ break;
+#endif /* have_iso */
+ default:
+ BUG ();
+ }
+ }
+#ifdef DEBUG
+ if (usecs > 100)
+ err ("overallocated uframe %d, periodic is %d usecs",
+ frame * 8 + uframe, usecs);
+#endif
+ return usecs;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void intr_deschedule (
+ struct ehci_hcd *ehci,
+ unsigned frame,
+ struct ehci_qh *qh,
+ unsigned period
+) {
+ unsigned long flags;
+
+ spin_lock_irqsave (&ehci->lock, flags);
+
+ do {
+ periodic_unlink (ehci, frame, qh);
+ qh_unput (ehci, qh);
+ frame += period;
+ } while (frame < ehci->periodic_size);
+
+ qh->qh_state = QH_STATE_UNLINK;
+ qh->qh_next.ptr = 0;
+ ehci->periodic_urbs--;
+
+ /* maybe turn off periodic schedule */
+ if (!ehci->periodic_urbs) {
+ u32 cmd = readl (&ehci->regs->command);
+
+ /* did setting PSE not take effect yet?
+ * takes effect only at frame boundaries...
+ */
+ while (!(readl (&ehci->regs->status) & STS_PSS))
+ udelay (20);
+
+ cmd &= ~CMD_PSE;
+ writel (cmd, &ehci->regs->command);
+ /* posted write ... */
+
+ ehci->next_frame = -1;
+ } else
+ vdbg ("periodic schedule still enabled");
+
+ spin_unlock_irqrestore (&ehci->lock, flags);
+
+ /*
+ * If the hc may be looking at this qh, then delay a uframe
+ * (yeech!) to be sure it's done.
+ * No other threads may be mucking with this qh.
+ */
+ if (((ehci_get_frame (&ehci->hcd) - frame) % period) == 0)
+ udelay (125);
+
+ qh->qh_state = QH_STATE_IDLE;
+ qh->hw_next = EHCI_LIST_END;
+
+ vdbg ("descheduled qh %p, per = %d frame = %d count = %d, urbs = %d",
+ qh, period, frame,
+ atomic_read (&qh->refcount), ehci->periodic_urbs);
+}
+
+static int intr_submit (
+ struct ehci_hcd *ehci,
+ struct urb *urb,
+ struct list_head *qtd_list,
+ int mem_flags
+) {
+ unsigned epnum, period;
+ unsigned temp;
+ unsigned short mult, usecs;
+ unsigned long flags;
+ struct ehci_qh *qh;
+ struct hcd_dev *dev;
+ int status = 0;
+
+ /* get endpoint and transfer data */
+ epnum = usb_pipeendpoint (urb->pipe);
+ if (usb_pipein (urb->pipe)) {
+ temp = urb->dev->epmaxpacketin [epnum];
+ epnum |= 0x10;
+ } else
+ temp = urb->dev->epmaxpacketout [epnum];
+ mult = 1;
+ if (urb->dev->speed == USB_SPEED_HIGH) {
+ /* high speed "high bandwidth" is coded in ep maxpacket */
+ mult += (temp >> 11) & 0x03;
+ temp &= 0x03ff;
+ } else {
+ dbg ("no intr/tt scheduling yet");
+ status = -ENOSYS;
+ goto done;
+ }
+
+ /*
+ * NOTE: current completion/restart logic doesn't handle more than
+ * one qtd in a periodic qh ... 16-20 KB/urb is pretty big for this.
+ * such big requests need many periods to transfer.
+ */
+ if (unlikely (qtd_list->next != qtd_list->prev)) {
+ dbg ("only one intr qtd per urb allowed");
+ status = -EINVAL;
+ goto done;
+ }
+
+ usecs = HS_USECS (urb->transfer_buffer_length);
+
+ /*
+ * force a power-of-two (frames) sized polling interval
+ *
+ * NOTE: endpoint->bInterval for highspeed is measured in uframes,
+ * while for full/low speeds it's in frames. Here we "know" that
+ * urb->interval doesn't give acccess to high interrupt rates.
+ */
+ period = ehci->periodic_size;
+ temp = period;
+ if (unlikely (urb->interval < 1))
+ urb->interval = 1;
+ while (temp > urb->interval)
+ temp >>= 1;
+ period = urb->interval = temp;
+
+ spin_lock_irqsave (&ehci->lock, flags);
+
+ /* get the qh (must be empty and idle) */
+ dev = (struct hcd_dev *)urb->dev->hcpriv;
+ qh = (struct ehci_qh *) dev->ep [epnum];
+ if (qh) {
+ /* only allow one queued interrupt urb per EP */
+ if (unlikely (qh->qh_state != QH_STATE_IDLE
+ || !list_empty (&qh->qtd_list))) {
+ dbg ("interrupt urb already queued");
+ status = -EBUSY;
+ } else {
+ /* maybe reset hardware's data toggle in the qh */
+ if (unlikely (!usb_gettoggle (urb->dev, epnum & 0x0f,
+ !(epnum & 0x10)))) {
+ qh->hw_token |=
+ __constant_cpu_to_le32 (QTD_TOGGLE);
+ usb_settoggle (urb->dev, epnum & 0x0f,
+ !(epnum & 0x10), 1);
+ }
+ /* trust the QH was set up as interrupt ... */
+ list_splice (qtd_list, &qh->qtd_list);
+ qh_update (qh, list_entry (qtd_list->next,
+ struct ehci_qtd, qtd_list));
+ }
+ } else {
+ /* can't sleep here, we have ehci->lock... */
+ qh = ehci_qh_make (ehci, urb, qtd_list, SLAB_ATOMIC);
+ qtd_list = &qh->qtd_list;
+ if (likely (qh != 0)) {
+ // dbg ("new INTR qh %p", qh);
+ dev->ep [epnum] = qh;
+ } else
+ status = -ENOMEM;
+ }
+
+ /* Schedule this periodic QH. */
+ if (likely (status == 0)) {
+ unsigned frame = urb->interval;
+
+ qh->hw_next = EHCI_LIST_END;
+ qh->hw_info2 |= cpu_to_le32 (mult << 30);
+ qh->usecs = usecs;
+
+ urb->hcpriv = qh_put (qh);
+ status = -ENOSPC;
+
+ /* pick a set of schedule slots, link the QH into them */
+ do {
+ int uframe;
+
+ /* Select some frame 0..(urb->interval - 1) with a
+ * microframe that can hold this transaction.
+ *
+ * FIXME for TT splits, need uframes for start and end.
+ * FSTNs can put end into next frame (uframes 0 or 1).
+ */
+ frame--;
+ for (uframe = 0; uframe < 8; uframe++) {
+ int claimed;
+ claimed = periodic_usecs (ehci, frame, uframe);
+ /* 80% periodic == 100 usec max committed */
+ if ((claimed + usecs) <= 100) {
+ vdbg ("frame %d.%d: %d usecs, plus %d",
+ frame, uframe, claimed, usecs);
+ break;
+ }
+ }
+ if (uframe == 8)
+ continue;
+// FIXME delete when code below handles non-empty queues
+ if (ehci->pshadow [frame].ptr)
+ continue;
+
+ /* QH will run once each period, starting there */
+ urb->start_frame = frame;
+ status = 0;
+
+ /* set S-frame mask */
+ qh->hw_info2 |= cpu_to_le32 (1 << uframe);
+ // dbg_qh ("Schedule INTR qh", ehci, qh);
+
+ /* stuff into the periodic schedule */
+ qh->qh_state = QH_STATE_LINKED;
+ vdbg ("qh %p usecs %d period %d starting frame %d.%d",
+ qh, qh->usecs, period, frame, uframe);
+ do {
+ if (unlikely ((int)ehci->pshadow [frame].ptr)) {
+// FIXME -- just link to the end, before any qh with a shorter period,
+// AND handle it already being (implicitly) linked into this frame
+ BUG ();
+ } else {
+ ehci->pshadow [frame].qh = qh_put (qh);
+ ehci->periodic [frame] =
+ QH_NEXT (qh->qh_dma);
+ }
+ frame += period;
+ } while (frame < ehci->periodic_size);
+
+ /* maybe enable periodic schedule processing */
+ if (!ehci->periodic_urbs++) {
+ u32 cmd;
+
+ /* did clearing PSE did take effect yet?
+ * takes effect only at frame boundaries...
+ */
+ while (readl (&ehci->regs->status) & STS_PSS)
+ udelay (20);
+
+ cmd = readl (&ehci->regs->command) | CMD_PSE;
+ writel (cmd, &ehci->regs->command);
+ /* posted write ... PSS happens later */
+ ehci->hcd.state = USB_STATE_RUNNING;
+
+ /* make sure tasklet scans these */
+ ehci->next_frame = ehci_get_frame (&ehci->hcd);
+ }
+ break;
+
+ } while (frame);
+ }
+ spin_unlock_irqrestore (&ehci->lock, flags);
+done:
+ if (status) {
+ usb_complete_t complete = urb->complete;
+
+ urb->complete = 0;
+ urb->status = status;
+ qh_completions (ehci, qtd_list, 1);
+ urb->complete = complete;
+ }
+ return status;
+}
+
+static unsigned long
+intr_complete (
+ struct ehci_hcd *ehci,
+ unsigned frame,
+ struct ehci_qh *qh,
+ unsigned long flags /* caller owns ehci->lock ... */
+) {
+ struct ehci_qtd *qtd;
+ struct urb *urb;
+ int unlinking;
+
+ /* nothing to report? */
+ if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE))
+ != 0))
+ return flags;
+
+ qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list);
+ urb = qtd->urb;
+ unlinking = (urb->status == -ENOENT) || (urb->status == -ECONNRESET);
+
+ /* call any completions, after patching for reactivation */
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ /* NOTE: currently restricted to one qtd per qh! */
+ if (qh_completions (ehci, &qh->qtd_list, 0) == 0)
+ urb = 0;
+ spin_lock_irqsave (&ehci->lock, flags);
+
+ /* never reactivate requests that were unlinked ... */
+ if (likely (urb != 0)) {
+ if (unlinking
+ || urb->status == -ECONNRESET
+ || urb->status == -ENOENT
+ // || (urb->dev == null)
+ || ehci->hcd.state == USB_STATE_HALT)
+ urb = 0;
+ // FIXME look at all those unlink cases ... we always
+ // need exactly one completion that reports unlink.
+ // the one above might not have been it!
+ }
+
+ /* normally reactivate */
+ if (likely (urb != 0)) {
+ if (usb_pipeout (urb->pipe))
+ pci_dma_sync_single (ehci->hcd.pdev,
+ qtd->buf_dma,
+ urb->transfer_buffer_length,
+ PCI_DMA_TODEVICE);
+ urb->status = -EINPROGRESS;
+ urb->actual_length = 0;
+
+ /* patch qh and restart */
+ qh_update (qh, qtd);
+ }
+ return flags;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef have_iso
+
+static inline void itd_free (struct ehci_hcd *ehci, struct ehci_itd *itd)
+{
+ pci_pool_free (ehci->itd_pool, itd, itd->itd_dma);
+}
+
+/*
+ * Create itd and allocate into uframes within specified frame.
+ * Caller must update the resulting uframe links.
+ */
+static struct ehci_itd *
+itd_make (
+ struct ehci_hcd *ehci,
+ struct urb *urb,
+ unsigned index, // urb->iso_frame_desc [index]
+ unsigned frame, // scheduled start
+ dma_addr_t dma, // mapped transfer buffer
+ int mem_flags
+) {
+ struct ehci_itd *itd;
+ u64 temp;
+ u32 buf1;
+ unsigned epnum, maxp, multi, usecs;
+ unsigned length;
+ unsigned i, bufnum;
+
+ /* allocate itd, start to fill it */
+ itd = pci_pool_alloc (ehci->itd_pool, mem_flags, &dma);
+ if (!itd)
+ return itd;
+
+ itd->hw_next = EHCI_LIST_END;
+ itd->urb = urb;
+ itd->index = index;
+ INIT_LIST_HEAD (&itd->itd_list);
+ itd->uframe = (frame * 8) % ehci->periodic_size;
+
+ /* tell itd about the buffer its transfers will consume */
+ length = urb->iso_frame_desc [index].length;
+ dma += urb->iso_frame_desc [index].offset;
+ temp = dma & ~0x0fff;
+ for (i = 0; i < 7; i++) {
+ itd->hw_bufp [i] = cpu_to_le32 ((u32) temp);
+ itd->hw_bufp_hi [i] = cpu_to_le32 ((u32)(temp >> 32));
+ temp += 0x0fff;
+ }
+
+ /*
+ * this might be a "high bandwidth" highspeed endpoint,
+ * as encoded in the ep descriptor's maxpacket field
+ */
+ epnum = usb_pipeendpoint (urb->pipe);
+ if (usb_pipein (urb->pipe)) {
+ maxp = urb->dev->epmaxpacketin [epnum];
+ buf1 = (1 << 11) | maxp;
+ } else {
+ maxp = urb->dev->epmaxpacketout [epnum];
+ buf1 = maxp;
+ }
+ multi = 1;
+ multi += (temp >> 11) & 0x03;
+ maxp &= 0x03ff;
+
+ /* "plus" info in low order bits of buffer pointers */
+ itd->hw_bufp [0] |= cpu_to_le32 ((epnum << 8) | urb->dev->devnum);
+ itd->hw_bufp [1] |= cpu_to_le32 (buf1);
+ itd->hw_bufp [2] |= cpu_to_le32 (multi);
+
+ /* schedule as many uframes as needed */
+ maxp *= multi;
+ usecs = HS_USECS_ISO (maxp);
+ bufnum = 0;
+ for (i = 0; i < 8; i++) {
+ unsigned t, offset, scratch;
+
+ if (length <= 0) {
+ itd->hw_transaction [i] = 0;
+ continue;
+ }
+
+ /* don't commit more than 80% periodic == 100 usec */
+ if ((periodic_usecs (ehci, itd->uframe, i) + usecs) > 100)
+ continue;
+
+ /* we'll use this uframe; figure hw_transaction */
+ t = EHCI_ISOC_ACTIVE;
+ t |= bufnum << 12; // which buffer?
+ offset = temp & 0x0fff; // offset therein
+ t |= offset;
+ if ((offset + maxp) >= 4096) // hc auto-wraps end-of-"page"
+ bufnum++;
+ if (length <= maxp) {
+ // interrupt only needed at end-of-urb
+ if ((index + 1) == urb->number_of_packets)
+ t |= EHCI_ITD_IOC;
+ scratch = length;
+ } else
+ scratch = maxp;
+ t |= scratch << 16;
+ t = cpu_to_le32 (t);
+
+ itd->hw_transaction [i] = itd->transaction [i] = t;
+ length -= scratch;
+ }
+ if (length > 0) {
+ dbg ("iso frame too big, urb %p [%d], %d extra (of %d)",
+ urb, index, length, urb->iso_frame_desc [index].length);
+ itd_free (ehci, itd);
+ itd = 0;
+ }
+ return itd;
+}
+
+static inline void
+itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
+{
+ u32 ptr;
+
+ ptr = cpu_to_le32 (itd->itd_dma); // type 0 == itd
+ if (ehci->pshadow [frame].ptr) {
+ if (!itd->itd_next.ptr) {
+ itd->itd_next = ehci->pshadow [frame];
+ itd->hw_next = ehci->periodic [frame];
+ } else if (itd->itd_next.ptr != ehci->pshadow [frame].ptr) {
+ dbg ("frame %d itd link goof", frame);
+ BUG ();
+ }
+ }
+ ehci->pshadow [frame].itd = itd;
+ ehci->periodic [frame] = ptr;
+}
+
+#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
+
+static unsigned long
+itd_complete (struct ehci_hcd *ehci, struct ehci_itd *itd, unsigned long flags)
+{
+ struct urb *urb = itd->urb;
+
+ /* if not unlinking: */
+ if (!(urb->transfer_flags & EHCI_STATE_UNLINK)
+ && ehci->hcd.state != USB_STATE_HALT) {
+ int i;
+ iso_packet_descriptor_t *desc;
+ struct ehci_itd *first_itd = urb->hcpriv;
+
+ /* update status for this frame's transfers */
+ desc = &urb->iso_frame_desc [itd->index];
+ desc->status = 0;
+ desc->actual_length = 0;
+ for (i = 0; i < 8; i++) {
+ u32 t = itd->hw_transaction [i];
+ if (t & (ISO_ERRS | EHCI_ISOC_ACTIVE)) {
+ if (t & EHCI_ISOC_ACTIVE)
+ desc->status = -EXDEV;
+ else if (t & EHCI_ISOC_BUF_ERR)
+ desc->status = usb_pipein (urb->pipe)
+ ? -ENOSR /* couldn't read */
+ : -ECOMM; /* couldn't write */
+ else if (t & EHCI_ISOC_BABBLE)
+ desc->status = -EOVERFLOW;
+ else /* (t & EHCI_ISOC_XACTERR) */
+ desc->status = -EPROTO;
+ break;
+ }
+ desc->actual_length += EHCI_ITD_LENGTH (t);
+ }
+
+ /* handle completion now? */
+ if ((itd->index + 1) != urb->number_of_packets)
+ return flags;
+
+ i = usb_pipein (urb->pipe);
+ if (i)
+ pci_dma_sync_single (ehci->hcd.pdev,
+ first_itd->buf_dma,
+ urb->transfer_buffer_length,
+ PCI_DMA_FROMDEVICE);
+
+ /* call completion with no locks; it can unlink ... */
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ urb->complete (urb);
+ spin_lock_irqsave (&ehci->lock, flags);
+
+ /* re-activate this URB? or unlink? */
+ if (!(urb->transfer_flags & EHCI_STATE_UNLINK)
+ && ehci->hcd.state != USB_STATE_HALT) {
+ if (!i)
+ pci_dma_sync_single (ehci->hcd.pdev,
+ first_itd->buf_dma,
+ urb->transfer_buffer_length,
+ PCI_DMA_TODEVICE);
+
+ itd = urb->hcpriv;
+ do {
+ for (i = 0; i < 8; i++)
+ itd->hw_transaction [i]
+ = itd->transaction [i];
+ itd = list_entry (itd->itd_list.next,
+ struct ehci_itd, itd_list);
+ } while (itd != urb->hcpriv);
+ return flags;
+ }
+
+ /* unlink done only on the last itd */
+ } else if ((itd->index + 1) != urb->number_of_packets)
+ return flags;
+
+ /* we're unlinking ... */
+
+ /* decouple urb from the hcd */
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ if (ehci->hcd.state == USB_STATE_HALT)
+ urb->status = -ESHUTDOWN;
+ itd = urb->hcpriv;
+ urb->hcpriv = 0;
+ ehci_urb_done (ehci, itd->buf_dma, urb);
+ spin_lock_irqsave (&ehci->lock, flags);
+
+ /* take itds out of the hc's periodic schedule */
+ list_entry (itd->itd_list.prev, struct ehci_itd, itd_list)
+ ->itd_list.next = 0;
+ do {
+ struct ehci_itd *next;
+
+ if (itd->itd_list.next)
+ next = list_entry (itd->itd_list.next,
+ struct ehci_itd, itd_list);
+ else
+ next = 0;
+
+ // FIXME: hc WILL (!) lap us here, if we get behind
+ // by 128 msec (or less, with smaller periodic_size).
+ // Reading/caching these itds will cause trouble...
+
+ periodic_unlink (ehci, itd->uframe, itd);
+ itd_free (ehci, itd);
+ itd = next;
+ } while (itd);
+ return flags;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int itd_submit (struct ehci_hcd *ehci, struct urb *urb)
+{
+ struct ehci_itd *first_itd = 0, *itd;
+ unsigned frame_index;
+ dma_addr_t dma;
+ unsigned long flags;
+
+ dbg ("itd_submit");
+
+ /* set up one dma mapping for this urb */
+ dma = pci_map_single (ehci->hcd.pdev,
+ urb->transfer_buffer, urb->transfer_buffer_length,
+ usb_pipein (urb->pipe)
+ ? PCI_DMA_FROMDEVICE
+ : PCI_DMA_TODEVICE);
+ if (dma == 0)
+ return -ENOMEM;
+
+ /*
+ * Schedule as needed. This is VERY optimistic about free
+ * bandwidth! But the API assumes drivers can pick frames
+ * intelligently (how?), so there's no other good option.
+ *
+ * FIXME this doesn't handle urb->next rings, or try to
+ * use the iso periodicity.
+ */
+ if (urb->transfer_flags & USB_ISO_ASAP) {
+ urb->start_frame = ehci_get_frame (&ehci->hcd);
+ urb->start_frame++;
+ }
+ urb->start_frame %= ehci->periodic_size;
+
+ /* create and populate itds (doing uframe scheduling) */
+ spin_lock_irqsave (&ehci->lock, flags);
+ for (frame_index = 0;
+ frame_index < urb->number_of_packets;
+ frame_index++) {
+ itd = itd_make (ehci, urb, frame_index,
+ urb->start_frame + frame_index,
+ dma, SLAB_ATOMIC);
+ if (itd) {
+ if (first_itd)
+ list_add_tail (&itd->itd_list,
+ &first_itd->itd_list);
+ else
+ first_itd = itd;
+ } else {
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ if (first_itd) {
+ while (!list_empty (&first_itd->itd_list)) {
+ itd = list_entry (
+ first_itd->itd_list.next,
+ struct ehci_itd, itd_list);
+ list_del (&itd->itd_list);
+ itd_free (ehci, itd);
+ }
+ itd_free (ehci, first_itd);
+ }
+ pci_unmap_single (ehci->hcd.pdev,
+ dma, urb->transfer_buffer_length,
+ usb_pipein (urb->pipe)
+ ? PCI_DMA_FROMDEVICE
+ : PCI_DMA_TODEVICE);
+ return -ENOMEM;
+ }
+ }
+
+ /* stuff into the schedule */
+ itd = first_itd;
+ do {
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ if (!itd->hw_transaction [i])
+ continue;
+ itd_link (ehci, itd->uframe + i, itd);
+ }
+ itd = list_entry (itd->itd_list.next,
+ struct ehci_itd, itd_list);
+ } while (itd != first_itd);
+ urb->hcpriv = first_itd;
+
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * "Split ISO TDs" ... used for USB 1.1 devices going through
+ * the TTs in USB 2.0 hubs.
+ */
+
+static inline void
+sitd_free (struct ehci_hcd *ehci, struct ehci_sitd *sitd)
+{
+ pci_pool_free (ehci->sitd_pool, sitd, sitd->sitd_dma);
+}
+
+static struct ehci_sitd *
+sitd_make (
+ struct ehci_hcd *ehci,
+ struct urb *urb,
+ unsigned index, // urb->iso_frame_desc [index]
+ unsigned uframe, // scheduled start
+ dma_addr_t dma, // mapped transfer buffer
+ int mem_flags
+) {
+ struct ehci_sitd *sitd;
+ unsigned length;
+
+ sitd = pci_pool_alloc (ehci->sitd_pool, mem_flags, &dma);
+ if (!sitd)
+ return sitd;
+ sitd->urb = urb;
+ length = urb->iso_frame_desc [index].length;
+ dma += urb->iso_frame_desc [index].offset;
+
+#if 0
+ // FIXME: do the rest!
+#else
+ sitd_free (ehci, sitd);
+ return 0;
+#endif
+
+}
+
+static inline void
+sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
+{
+ u32 ptr;
+
+ ptr = cpu_to_le32 (sitd->sitd_dma | 2); // type 2 == sitd
+ if (ehci->pshadow [frame].ptr) {
+ if (!sitd->sitd_next.ptr) {
+ sitd->sitd_next = ehci->pshadow [frame];
+ sitd->hw_next = ehci->periodic [frame];
+ } else if (sitd->sitd_next.ptr != ehci->pshadow [frame].ptr) {
+ dbg ("frame %d sitd link goof", frame);
+ BUG ();
+ }
+ }
+ ehci->pshadow [frame].sitd = sitd;
+ ehci->periodic [frame] = ptr;
+}
+
+static unsigned long
+sitd_complete (
+ struct ehci_hcd *ehci,
+ struct ehci_sitd *sitd,
+ unsigned long flags
+) {
+ // FIXME -- implement!
+
+ dbg ("NYI -- sitd_complete");
+ return flags;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb)
+{
+ // struct ehci_sitd *first_sitd = 0;
+ unsigned frame_index;
+ dma_addr_t dma;
+ int mem_flags;
+
+ dbg ("NYI -- sitd_submit");
+
+ // FIXME -- implement!
+
+ // FIXME: setup one big dma mapping
+ dma = 0;
+
+ mem_flags = SLAB_ATOMIC;
+
+ for (frame_index = 0;
+ frame_index < urb->number_of_packets;
+ frame_index++) {
+ struct ehci_sitd *sitd;
+ unsigned uframe;
+
+ // FIXME: use real arguments, schedule this!
+ uframe = -1;
+
+ sitd = sitd_make (ehci, urb, frame_index,
+ uframe, dma, mem_flags);
+
+ if (sitd) {
+ /*
+ if (first_sitd)
+ list_add_tail (&sitd->sitd_list,
+ &first_sitd->sitd_list);
+ else
+ first_sitd = sitd;
+ */
+ } else {
+ // FIXME: clean everything up
+ }
+ }
+
+ // if we have a first sitd, then
+ // store them all into the periodic schedule!
+ // urb->hcpriv = first sitd in sitd_list
+
+ return -ENOSYS;
+}
+
+#endif /* have_iso */
+
+/*-------------------------------------------------------------------------*/
+
+static void scan_periodic (struct ehci_hcd *ehci)
+{
+ unsigned frame;
+ unsigned clock;
+ unsigned long flags;
+
+ spin_lock_irqsave (&ehci->lock, flags);
+
+ /*
+ * When running, scan from last scan point up to "now"
+ * Touches as few pages as possible: cache-friendly.
+ * It's safe to scan entries more than once, though.
+ */
+ if (HCD_IS_RUNNING (ehci->hcd.state)) {
+ frame = ehci->next_frame;
+ clock = ehci_get_frame (&ehci->hcd);
+
+ /* when shutting down, scan everything for thoroughness */
+ } else {
+ frame = 0;
+ clock = ehci->periodic_size - 1;
+ }
+ for (;;) {
+ union ehci_shadow q;
+ u32 type;
+
+restart:
+ q.ptr = ehci->pshadow [frame].ptr;
+ type = Q_NEXT_TYPE (ehci->periodic [frame]);
+
+ /* scan each element in frame's queue for completions */
+ while (q.ptr != 0) {
+ int last;
+ union ehci_shadow temp;
+
+ switch (type) {
+ case Q_TYPE_QH:
+ last = (q.qh->hw_next == EHCI_LIST_END);
+ flags = intr_complete (ehci, frame,
+ qh_put (q.qh), flags);
+ type = Q_NEXT_TYPE (q.qh->hw_next);
+ temp = q.qh->qh_next;
+ qh_unput (ehci, q.qh);
+ q = temp;
+ break;
+ case Q_TYPE_FSTN:
+ last = (q.fstn->hw_next == EHCI_LIST_END);
+ /* for "save place" FSTNs, look at QH entries
+ * in the previous frame for completions.
+ */
+ if (q.fstn->hw_prev != EHCI_LIST_END) {
+ dbg ("ignoring completions from FSTNs");
+ }
+ type = Q_NEXT_TYPE (q.fstn->hw_next);
+ temp = q.fstn->fstn_next;
+ break;
+#ifdef have_iso
+ case Q_TYPE_ITD:
+ last = (q.itd->hw_next == EHCI_LIST_END);
+ flags = itd_complete (ehci, q.itd, flags);
+ type = Q_NEXT_TYPE (q.itd->hw_next);
+ q = q.itd->itd_next;
+ break;
+ case Q_TYPE_SITD:
+ last = (q.sitd->hw_next == EHCI_LIST_END);
+ flags = sitd_complete (ehci, q.sitd, flags);
+ type = Q_NEXT_TYPE (q.sitd->hw_next);
+ q = q.sitd->sitd_next;
+ break;
+#endif /* have_iso */
+ default:
+ dbg ("corrupt type %d frame %d shadow %p",
+ type, frame, q.ptr);
+ // BUG ();
+ last = 1;
+ q.ptr = 0;
+ }
+
+ /* did completion remove an interior q entry? */
+ if (unlikely (q.ptr == 0 && !last))
+ goto restart;
+ }
+
+ /* stop when we catch up to the HC */
+
+ // FIXME: this assumes we won't get lapped when
+ // latencies climb; that should be rare, but...
+ // detect it, and just go all the way around.
+ // FLR might help detect this case, so long as latencies
+ // don't exceed periodic_size msec (default 1.024 sec).
+
+ // FIXME: likewise assumes HC doesn't halt mid-scan
+
+ if (frame == clock) {
+ unsigned now;
+
+ if (!HCD_IS_RUNNING (ehci->hcd.state))
+ break;
+ ehci->next_frame = clock;
+ now = ehci_get_frame (&ehci->hcd);
+ if (clock == now)
+ break;
+ clock = now;
+ } else if (++frame >= ehci->periodic_size)
+ frame = 0;
+ }
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ }
diff --git a/drivers/usb/hcd/ehci.h b/drivers/usb/hcd/ehci.h
new file mode 100644
index 000000000..eda91299c
--- /dev/null
+++ b/drivers/usb/hcd/ehci.h
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LINUX_EHCI_HCD_H
+#define __LINUX_EHCI_HCD_H
+
+/* definitions used for the EHCI driver */
+
+/* ehci_hcd->lock guards shared data against other CPUs:
+ * ehci_hcd: async, reclaim, periodic (and shadow), ...
+ * hcd_dev: ep[]
+ * ehci_qh: qh_next, qtd_list
+ * ehci_qtd: qtd_list
+ *
+ * Also, hold this lock when talking to HC registers or
+ * when updating hw_* fields in shared qh/qtd/... structures.
+ */
+
+#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */
+
+struct ehci_hcd { /* one per controller */
+ spinlock_t lock;
+
+ /* async schedule support */
+ struct ehci_qh *async;
+ struct ehci_qh *reclaim;
+ int reclaim_ready;
+
+ /* periodic schedule support */
+#define DEFAULT_I_TDPS 1024 /* some HCs can do less */
+ unsigned periodic_size;
+ u32 *periodic; /* hw periodic table */
+ dma_addr_t periodic_dma;
+ unsigned i_thresh; /* uframes HC might cache */
+
+ union ehci_shadow *pshadow; /* mirror hw periodic table */
+ int next_frame; /* scan periodic, start here */
+ unsigned periodic_urbs; /* how many urbs scheduled? */
+
+ /* deferred work from IRQ, etc */
+ struct tasklet_struct tasklet;
+
+ /* per root hub port */
+ unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
+
+ /* glue to PCI and HCD framework */
+ struct usb_hcd hcd;
+ struct ehci_caps *caps;
+ struct ehci_regs *regs;
+
+ /* per-HC memory pools (could be per-PCI-bus, but ...) */
+ struct pci_pool *qh_pool; /* qh per active urb */
+ struct pci_pool *qtd_pool; /* one or more per qh */
+ struct pci_pool *itd_pool; /* itd per iso urb */
+ struct pci_pool *sitd_pool; /* sitd per split iso urb */
+};
+
+/* unwrap an HCD pointer to get an EHCI_HCD pointer */
+#define hcd_to_ehci(hcd_ptr) list_entry(hcd_ptr, struct ehci_hcd, hcd)
+
+/* NOTE: urb->transfer_flags expected to not use this bit !!! */
+#define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */
+
+/*-------------------------------------------------------------------------*/
+
+/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
+
+/* Section 2.2 Host Controller Capability Registers */
+struct ehci_caps {
+ u8 length; /* CAPLENGTH - size of this struct */
+ u8 reserved; /* offset 0x1 */
+ u16 hci_version; /* HCIVERSION - offset 0x2 */
+ u32 hcs_params; /* HCSPARAMS - offset 0x4 */
+#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */
+#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */
+#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */
+#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */
+#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */
+#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */
+#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */
+
+ u32 hcc_params; /* HCCPARAMS - offset 0x8 */
+#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */
+#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */
+#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */
+#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */
+#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/
+#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */
+ u8 portroute [8]; /* nibbles for routing - offset 0xC */
+} __attribute__ ((packed));
+
+
+/* Section 2.3 Host Controller Operational Registers */
+struct ehci_regs {
+
+ /* USBCMD: offset 0x00 */
+ u32 command;
+/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
+#define CMD_PARK (1<<11) /* enable "park" on async qh */
+#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */
+#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */
+#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */
+#define CMD_ASE (1<<5) /* async schedule enable */
+#define CMD_PSE (1<<4) /* periodic schedule enable */
+/* 3:2 is periodic frame list size */
+#define CMD_RESET (1<<1) /* reset HC not bus */
+#define CMD_RUN (1<<0) /* start/stop HC */
+
+ /* USBSTS: offset 0x04 */
+ u32 status;
+#define STS_ASS (1<<15) /* Async Schedule Status */
+#define STS_PSS (1<<14) /* Periodic Schedule Status */
+#define STS_RECL (1<<13) /* Reclamation */
+#define STS_HALT (1<<12) /* Not running (any reason) */
+/* some bits reserved */
+ /* these STS_* flags are also intr_enable bits (USBINTR) */
+#define STS_IAA (1<<5) /* Interrupted on async advance */
+#define STS_FATAL (1<<4) /* such as some PCI access errors */
+#define STS_FLR (1<<3) /* frame list rolled over */
+#define STS_PCD (1<<2) /* port change detect */
+#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */
+#define STS_INT (1<<0) /* "normal" completion (short, ...) */
+
+ /* USBINTR: offset 0x08 */
+ u32 intr_enable;
+
+ /* FRINDEX: offset 0x0C */
+ u32 frame_index; /* current microframe number */
+ /* CTRLDSSEGMENT: offset 0x10 */
+ u32 segment; /* address bits 63:32 if needed */
+ /* PERIODICLISTBASE: offset 0x14 */
+ u32 frame_list; /* points to periodic list */
+ /* ASYNCICLISTADDR: offset 0x18 */
+ u32 async_next; /* address of next async queue head */
+
+ u32 reserved [9];
+
+ /* CONFIGFLAG: offset 0x40 */
+ u32 configured_flag;
+#define FLAG_CF (1<<0) /* true: we'll support "high speed" */
+
+ /* PORTSC: offset 0x44 */
+ u32 port_status [0]; /* up to N_PORTS */
+/* 31:23 reserved */
+#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */
+#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */
+#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */
+/* 19:16 for port testing */
+/* 15:14 for using port indicator leds (if HCS_INDICATOR allows) */
+#define PORT_OWNER (1<<13) /* true: companion hc owns this port */
+#define PORT_POWER (1<<12) /* true: has power (see PPC) */
+#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */
+/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
+/* 9 reserved */
+#define PORT_RESET (1<<8) /* reset port */
+#define PORT_SUSPEND (1<<7) /* suspend port */
+#define PORT_RESUME (1<<6) /* resume it */
+#define PORT_OCC (1<<5) /* over current change */
+#define PORT_OC (1<<4) /* over current active */
+#define PORT_PEC (1<<3) /* port enable change */
+#define PORT_PE (1<<2) /* port enable */
+#define PORT_CSC (1<<1) /* connect status change */
+#define PORT_CONNECT (1<<0) /* device connected */
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+#define QTD_NEXT(dma) cpu_to_le32((u32)dma)
+
+/*
+ * EHCI Specification 0.95 Section 3.5
+ * QTD: describe data transfer components (buffer, direction, ...)
+ * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
+ *
+ * These are associated only with "QH" (Queue Head) structures,
+ * used with control, bulk, and interrupt transfers.
+ */
+struct ehci_qtd {
+ /* first part defined by EHCI spec */
+ u32 hw_next; /* see EHCI 3.5.1 */
+ u32 hw_alt_next; /* see EHCI 3.5.2 */
+ u32 hw_token; /* see EHCI 3.5.3 */
+#define QTD_TOGGLE (1 << 31) /* data toggle */
+#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
+#define QTD_IOC (1 << 15) /* interrupt on complete */
+#define QTD_CERR(tok) (((tok)>>10) & 0x3)
+#define QTD_PID(tok) (((tok)>>8) & 0x3)
+#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */
+#define QTD_STS_HALT (1 << 6) /* halted on error */
+#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */
+#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */
+#define QTD_STS_XACT (1 << 3) /* device gave illegal response */
+#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */
+#define QTD_STS_STS (1 << 1) /* split transaction state */
+#define QTD_STS_PING (1 << 0) /* issue PING? */
+ u32 hw_buf [5]; /* see EHCI 3.5.4 */
+ u32 hw_buf_hi [5]; /* Appendix B */
+
+ /* the rest is HCD-private */
+ dma_addr_t qtd_dma; /* qtd address */
+ struct list_head qtd_list; /* sw qtd list */
+
+ /* dma same in urb's qtds, except 1st control qtd (setup buffer) */
+ struct urb *urb; /* qtd's urb */
+ dma_addr_t buf_dma; /* buffer address */
+ size_t length; /* length of buffer */
+} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+/* type tag from {qh,itd,sitd,fstn}->hw_next */
+#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
+
+/* values for that type tag */
+#define Q_TYPE_ITD __constant_cpu_to_le32 (0 << 1)
+#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1)
+#define Q_TYPE_SITD __constant_cpu_to_le32 (2 << 1)
+#define Q_TYPE_FSTN __constant_cpu_to_le32 (3 << 1)
+
+/* next async queue entry, or pointer to interrupt/periodic QH */
+#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
+
+/* for periodic/async schedules and qtd lists, mark end of list */
+#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */
+
+/*
+ * Entries in periodic shadow table are pointers to one of four kinds
+ * of data structure. That's dictated by the hardware; a type tag is
+ * encoded in the low bits of the hardware's periodic schedule. Use
+ * Q_NEXT_TYPE to get the tag.
+ *
+ * For entries in the async schedule, the type tag always says "qh".
+ */
+union ehci_shadow {
+ struct ehci_qh *qh; /* Q_TYPE_QH */
+ struct ehci_itd *itd; /* Q_TYPE_ITD */
+ struct ehci_sitd *sitd; /* Q_TYPE_SITD */
+ struct ehci_fstn *fstn; /* Q_TYPE_FSTN */
+ void *ptr;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.95 Section 3.6
+ * QH: describes control/bulk/interrupt endpoints
+ * See Fig 3-7 "Queue Head Structure Layout".
+ *
+ * These appear in both the async and (for interrupt) periodic schedules.
+ */
+
+struct ehci_qh {
+ /* first part defined by EHCI spec */
+ u32 hw_next; /* see EHCI 3.6.1 */
+ u32 hw_info1; /* see EHCI 3.6.2 */
+#define QH_HEAD 0x00008000
+ u32 hw_info2; /* see EHCI 3.6.2 */
+ u32 hw_current; /* qtd list - see EHCI 3.6.4 */
+
+ /* qtd overlay (hardware parts of a struct ehci_qtd) */
+ u32 hw_qtd_next;
+ u32 hw_alt_next;
+ u32 hw_token;
+ u32 hw_buf [5];
+ u32 hw_buf_hi [5];
+
+ /* the rest is HCD-private */
+ dma_addr_t qh_dma; /* address of qh */
+ union ehci_shadow qh_next; /* ptr to qh; or periodic */
+ struct list_head qtd_list; /* sw qtd list */
+
+ atomic_t refcount;
+ unsigned short usecs; /* intr bandwidth */
+ short qh_state;
+#define QH_STATE_LINKED 1 /* HC sees this */
+#define QH_STATE_UNLINK 2 /* HC may still see this */
+#define QH_STATE_IDLE 3 /* HC doesn't see this */
+
+#ifdef EHCI_SOFT_RETRIES
+ int retries;
+#endif
+} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.95 Section 3.3
+ * Fig 3-4 "Isochronous Transaction Descriptor (iTD)"
+ *
+ * Schedule records for high speed iso xfers
+ */
+struct ehci_itd {
+ /* first part defined by EHCI spec */
+ u32 hw_next; /* see EHCI 3.3.1 */
+ u32 hw_transaction [8]; /* see EHCI 3.3.2 */
+#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */
+#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */
+#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */
+#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */
+#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x7fff)
+#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */
+
+ u32 hw_bufp [7]; /* see EHCI 3.3.3 */
+ u32 hw_bufp_hi [7]; /* Appendix B */
+
+ /* the rest is HCD-private */
+ dma_addr_t itd_dma; /* for this itd */
+ union ehci_shadow itd_next; /* ptr to periodic q entry */
+
+ struct urb *urb;
+ unsigned index; /* in urb->iso_frame_desc */
+ struct list_head itd_list; /* list of urb frames' itds */
+ dma_addr_t buf_dma; /* frame's buffer address */
+
+ unsigned uframe; /* in periodic schedule */
+ u32 transaction [8]; /* copy of hw_transaction */
+
+} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.95 Section 3.4
+ * siTD, aka split-transaction isochronous Transfer Descriptor
+ * ... describe low/full speed iso xfers through TT in hubs
+ * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
+ */
+struct ehci_sitd {
+ /* first part defined by EHCI spec */
+ u32 hw_next;
+/* uses bit field macros above - see EHCI 0.95 Table 3-8 */
+ u32 hw_fullspeed_ep; /* see EHCI table 3-9 */
+ u32 hw_uframe; /* see EHCI table 3-10 */
+ u32 hw_tx_results1; /* see EHCI table 3-11 */
+ u32 hw_tx_results2; /* see EHCI table 3-12 */
+ u32 hw_tx_results3; /* see EHCI table 3-12 */
+ u32 hw_backpointer; /* see EHCI table 3-13 */
+ u32 hw_buf_hi [2]; /* Appendix B */
+
+ /* the rest is HCD-private */
+ dma_addr_t sitd_dma;
+ union ehci_shadow sitd_next; /* ptr to periodic q entry */
+ struct urb *urb;
+ dma_addr_t buf_dma; /* buffer address */
+} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.96 Section 3.7
+ * Periodic Frame Span Traversal Node (FSTN)
+ *
+ * Manages split interrupt transactions (using TT) that span frame boundaries
+ * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN
+ * makes the HC jump (back) to a QH to scan for fs/ls QH completions until
+ * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
+ */
+struct ehci_fstn {
+ u32 hw_next; /* any periodic q entry */
+ u32 hw_prev; /* qh or EHCI_LIST_END */
+
+ /* the rest is HCD-private */
+ dma_addr_t fstn_dma;
+ union ehci_shadow fstn_next; /* ptr to periodic q entry */
+} __attribute__ ((aligned (32)));
+
+#endif /* __LINUX_EHCI_HCD_H */
diff --git a/drivers/usb/hiddev.c b/drivers/usb/hiddev.c
index b9b3f1daa..f194a2573 100644
--- a/drivers/usb/hiddev.c
+++ b/drivers/usb/hiddev.c
@@ -218,7 +218,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
static int hiddev_open(struct inode * inode, struct file * file) {
struct hiddev_list *list;
- int i = MINOR(inode->i_rdev) - HIDDEV_MINOR_BASE;
+ int i = minor(inode->i_rdev) - HIDDEV_MINOR_BASE;
if (i >= HIDDEV_MINORS || !hiddev_table[i])
return -ENODEV;
diff --git a/drivers/usb/hpusbscsi.c b/drivers/usb/hpusbscsi.c
index 97fe6cdb9..b96e10329 100644
--- a/drivers/usb/hpusbscsi.c
+++ b/drivers/usb/hpusbscsi.c
@@ -117,7 +117,7 @@ hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface,
(struct hpusbscsi *) new->ctempl.proc_dir = new;
new->ctempl.module = THIS_MODULE;
- if (scsi_register_module (MODULE_SCSI_HA, &(new->ctempl)))
+ if (scsi_register_host(&new->ctempl))
goto err_out;
/* adding to list for module unload */
@@ -185,7 +185,7 @@ hpusbscsi_exit (void)
tmp = tmp->next;
o = (struct hpusbscsi *)old;
usb_unlink_urb(&o->controlurb);
- scsi_unregister_module(MODULE_SCSI_HA,&o->ctempl);
+ scsi_unregister_host(&o->ctempl);
kfree(old);
}
diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c
index 0e52bf2ea..78b9f1926 100644
--- a/drivers/usb/hub.c
+++ b/drivers/usb/hub.c
@@ -35,7 +35,7 @@ static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
static DECLARE_MUTEX(usb_address0_sem);
static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */
-static LIST_HEAD(hub_list); /* List containing all of the hubs (for cleanup) */
+static LIST_HEAD(hub_list); /* List of all hubs (for cleanup) */
static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
static int khubd_pid = 0; /* PID of khubd */
@@ -110,22 +110,30 @@ static int usb_get_port_status(struct usb_device *dev, int port, void *data)
data, sizeof(struct usb_hub_status), HZ);
}
+/* completion function, fires on port status changes and various faults */
static void hub_irq(struct urb *urb)
{
struct usb_hub *hub = (struct usb_hub *)urb->context;
unsigned long flags;
- /* Cause a hub reset after 10 consecutive errors */
- if (urb->status) {
- if (urb->status == -ENOENT)
- return;
-
- dbg("nonzero status in irq %d", urb->status);
+ switch (urb->status) {
+ case -ENOENT: /* synchronous unlink */
+ case -ECONNRESET: /* async unlink */
+ case -ESHUTDOWN: /* hardware going away */
+ return;
+ default: /* presumably an error */
+ /* Cause a hub reset after 10 consecutive errors */
+ dbg("hub '%s' status %d for interrupt transfer",
+ urb->dev->devpath, urb->status);
if ((++hub->nerrors < 10) || hub->error)
return;
-
hub->error = urb->status;
+ /* FALL THROUGH */
+
+ /* let khubd handle things */
+ case 0: /* we got data: port status changed */
+ break;
}
hub->nerrors = 0;
@@ -152,7 +160,8 @@ static void usb_hub_power_on(struct usb_hub *hub)
wait_ms(hub->descriptor->bPwrOn2PwrGood * 2);
}
-static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint)
+static int usb_hub_configure(struct usb_hub *hub,
+ struct usb_endpoint_descriptor *endpoint)
{
struct usb_device *dev = hub->dev;
struct usb_hub_status hubstatus;
@@ -162,22 +171,30 @@ static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor
hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
if (!hub->descriptor) {
- err("Unable to kmalloc %Zd bytes for hub descriptor", sizeof(*hub->descriptor));
+ err("Unable to kmalloc %Zd bytes for hub descriptor",
+ sizeof(*hub->descriptor));
return -1;
}
- /* Request the entire hub descriptor. */
- ret = usb_get_hub_descriptor(dev, hub->descriptor, sizeof(*hub->descriptor));
- /* <hub->descriptor> is large enough for a hub with 127 ports;
- * the hub can/will return fewer bytes here. */
+ /* Request the entire hub descriptor.
+ * hub->descriptor can handle USB_MAXCHILDREN ports,
+ * but the hub can/will return fewer bytes here.
+ */
+ ret = usb_get_hub_descriptor(dev, hub->descriptor,
+ sizeof(*hub->descriptor));
if (ret < 0) {
err("Unable to get hub descriptor (err = %d)", ret);
kfree(hub->descriptor);
return -1;
+ } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
+ err("Hub is too big! %d children", hub->descriptor->bNbrPorts);
+ kfree(hub->descriptor);
+ return -1;
}
dev->maxchild = hub->descriptor->bNbrPorts;
- info("%d port%s detected", hub->descriptor->bNbrPorts, (hub->descriptor->bNbrPorts == 1) ? "" : "s");
+ info("%d port%s detected", dev->maxchild,
+ (dev->maxchild == 1) ? "" : "s");
le16_to_cpus(&hub->descriptor->wHubCharacteristics);
@@ -217,9 +234,12 @@ static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor
break;
case 1:
dbg("Single TT");
+ hub->tt.hub = dev;
break;
case 2:
- dbg("Multiple TT");
+ dbg("TT per port");
+ hub->tt.hub = dev;
+ hub->tt.multi = 1;
break;
default:
dbg("Unrecognized hub protocol %d",
@@ -244,13 +264,18 @@ static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor
}
dbg("Port indicators are %s supported",
- (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) ? "" : "not");
+ (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND)
+ ? "" : "not");
- dbg("power on to power good time: %dms", hub->descriptor->bPwrOn2PwrGood * 2);
- dbg("hub controller current requirement: %dmA", hub->descriptor->bHubContrCurrent);
+ dbg("power on to power good time: %dms",
+ hub->descriptor->bPwrOn2PwrGood * 2);
+ dbg("hub controller current requirement: %dmA",
+ hub->descriptor->bHubContrCurrent);
for (i = 0; i < dev->maxchild; i++)
- portstr[i] = hub->descriptor->DeviceRemovable[((i + 1) / 8)] & (1 << ((i + 1) % 8)) ? 'F' : 'R';
+ portstr[i] = hub->descriptor->DeviceRemovable
+ [((i + 1) / 8)] & (1 << ((i + 1) % 8))
+ ? 'F' : 'R';
portstr[dev->maxchild] = 0;
dbg("port removable status: %s", portstr);
@@ -265,7 +290,8 @@ static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor
le16_to_cpus(&hubstatus.wHubStatus);
dbg("local power source is %s",
- (hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
+ (hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER)
+ ? "lost (inactive)" : "good");
dbg("%sover-current condition exists",
(hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
@@ -337,14 +363,15 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
}
/* If it's not an interrupt endpoint, we'd better punt! */
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
- err("Device #%d is hub class, but has endpoint other than interrupt?",
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ != USB_ENDPOINT_XFER_INT) {
+ err("Device #%d is hub class, but endpoint is not interrupt?",
dev->devnum);
return NULL;
}
/* We found a hub */
- info("USB hub found");
+ info("USB hub found at %s", dev->devpath);
hub = kmalloc(sizeof(*hub), GFP_KERNEL);
if (!hub) {
@@ -367,7 +394,7 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
if (usb_hub_configure(hub, endpoint) >= 0)
return hub;
- err("hub configuration failed for device #%d", dev->devnum);
+ err("hub configuration failed for device at %s", dev->devpath);
/* free hub, but first clean up its list. */
spin_lock_irqsave(&hub_event_lock, flags);
@@ -436,7 +463,8 @@ static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
if (hub->children[i] == NULL)
info->port[i] = 0;
else
- info->port[i] = hub->children[i]->devnum;
+ info->port[i] =
+ hub->children[i]->devnum;
}
}
spin_unlock_irqrestore(&hub_event_lock, flags);
@@ -493,7 +521,7 @@ static void usb_hub_disconnect(struct usb_device *dev)
}
}
- err("cannot disconnect hub %d", dev->devnum);
+ err("cannot disconnect hub %s", dev->devpath);
}
#define HUB_RESET_TRIES 5
@@ -510,14 +538,17 @@ static int usb_hub_port_wait_reset(struct usb_device *hub, int port,
struct usb_port_status portsts;
unsigned short portchange, portstatus;
- for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay) {
+ for (delay_time = 0;
+ delay_time < HUB_RESET_TIMEOUT;
+ delay_time += delay) {
/* wait to give the device a chance to reset */
wait_ms(delay);
/* read and decode port status */
ret = usb_get_port_status(hub, port + 1, &portsts);
if (ret < 0) {
- err("get_port_status(%d) failed (err = %d)", port + 1, ret);
+ err("get_port_status(%d) failed (err = %d)",
+ port + 1, ret);
return -1;
}
@@ -546,8 +577,8 @@ static int usb_hub_port_wait_reset(struct usb_device *hub, int port,
if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
delay = HUB_LONG_RESET_TIME;
- dbg("port %d of hub %d not reset yet, waiting %dms", port + 1,
- hub->devnum, delay);
+ dbg("port %d of hub %s not reset yet, waiting %dms", port + 1,
+ hub->devpath, delay);
}
return -1;
@@ -566,17 +597,18 @@ static int usb_hub_port_reset(struct usb_device *hub, int port,
/* return on disconnect or reset */
status = usb_hub_port_wait_reset(hub, port, dev, delay);
if (status != -1) {
- usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_RESET);
+ usb_clear_port_feature(hub,
+ port + 1, USB_PORT_FEAT_C_RESET);
return status;
}
- dbg("port %d of hub %d not enabled, trying reset again...",
- port + 1, hub->devnum);
+ dbg("port %d of hub %s not enabled, trying reset again...",
+ port + 1, hub->devpath);
delay = HUB_LONG_RESET_TIME;
}
- err("Cannot enable port %i of hub %d, disabling port.",
- port + 1, hub->devnum);
+ err("Cannot enable port %i of hub %s, disabling port.",
+ port + 1, hub->devpath);
err("Maybe the USB cable is bad?");
return -1;
@@ -588,23 +620,24 @@ void usb_hub_port_disable(struct usb_device *hub, int port)
ret = usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
if (ret)
- err("cannot disable port %d of hub %d (err = %d)",
- port + 1, hub->devnum, ret);
+ err("cannot disable port %d of hub %s (err = %d)",
+ port + 1, hub->devpath, ret);
}
-static void usb_hub_port_connect_change(struct usb_device *hub, int port,
+static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
struct usb_port_status *portsts)
{
+ struct usb_device *hub = hubstate->dev;
struct usb_device *dev;
unsigned short portstatus, portchange;
unsigned int delay = HUB_SHORT_RESET_TIME;
int i;
- char *portstr, *tempstr;
portstatus = le16_to_cpu(portsts->wPortStatus);
portchange = le16_to_cpu(portsts->wPortChange);
- dbg("port %d, portstatus %x, change %x, %s",
- port + 1, portstatus, portchange, portspeed (portstatus));
+ dbg("hub %s port %d, portstatus %x, change %x, %s",
+ hub->devpath, port + 1,
+ portstatus, portchange, portspeed (portstatus));
/* Clear the connection change status */
usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
@@ -630,11 +663,9 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port,
down(&usb_address0_sem);
- tempstr = kmalloc(1024, GFP_KERNEL);
- portstr = kmalloc(1024, GFP_KERNEL);
-
for (i = 0; i < HUB_PROBE_TRIES; i++) {
- struct usb_device *pdev, *cdev;
+ struct usb_device *pdev;
+ int len;
/* Allocate a new device struct */
dev = usb_alloc_dev(hub, hub->bus);
@@ -645,41 +676,46 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port,
hub->children[port] = dev;
- /* Reset the device */
+ /* Reset the device, and detect its speed */
if (usb_hub_port_reset(hub, port, dev, delay)) {
usb_free_dev(dev);
break;
}
- /* Find a new device ID for it */
+ /* Find a new address for it */
usb_connect(dev);
- /* Create a readable topology string */
- cdev = dev;
- pdev = dev->parent;
- if (portstr && tempstr) {
- portstr[0] = 0;
- while (pdev) {
- int port;
-
- for (port = 0; port < pdev->maxchild; port++)
- if (pdev->children[port] == cdev)
- break;
-
- strcpy(tempstr, portstr);
- if (!strlen(tempstr))
- sprintf(portstr, "%d", port + 1);
- else
- sprintf(portstr, "%d/%s", port + 1, tempstr);
+ /* Set up TT records, if needed */
+ if (hub->tt) {
+ dev->tt = hub->tt;
+ dev->ttport = hub->ttport;
+ } else if (dev->speed != USB_SPEED_HIGH
+ && hub->speed == USB_SPEED_HIGH) {
+ dev->tt = &hubstate->tt;
+ dev->ttport = port + 1;
+ }
- cdev = pdev;
- pdev = pdev->parent;
- }
- info("USB new device connect on bus%d/%s, assigned device number %d",
- dev->bus->busnum, portstr, dev->devnum);
- } else
- info("USB new device connect on bus%d, assigned device number %d",
- dev->bus->busnum, dev->devnum);
+ /* Save readable and stable topology id, distinguishing
+ * devices by location for diagnostics, tools, etc. The
+ * string is a path along hub ports, from the root. Each
+ * device's id will be stable until USB is re-cabled, and
+ * hubs are often labled with these port numbers.
+ *
+ * Initial size: "/NN" times five hubs + NUL = 16 bytes max
+ * (quite rare, since most hubs have 4-6 ports).
+ */
+ pdev = dev->parent;
+ if (pdev->devpath [1] != '\0') /* parent not root */
+ len = snprintf (dev->devpath, sizeof dev->devpath,
+ "%s/%d", pdev->devpath, port + 1);
+ else /* root == "/", root port 2 == "/2" */
+ len = snprintf (dev->devpath, sizeof dev->devpath,
+ "/%d", port + 1);
+ if (len == sizeof dev->devpath)
+ warn ("devpath size! usb/%03d/%03d path %s",
+ dev->bus->busnum, dev->devnum, dev->devpath);
+ info("new USB device on bus %d path %s, assigned address %d",
+ dev->bus->busnum, dev->devpath, dev->devnum);
/* Run it through the hoops (find a driver, etc) */
if (!usb_new_device(dev))
@@ -696,10 +732,6 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port,
usb_hub_port_disable(hub, port);
done:
up(&usb_address0_sem);
- if (portstr)
- kfree(portstr);
- if (tempstr)
- kfree(tempstr);
}
static void usb_hub_events(void)
@@ -737,10 +769,12 @@ static void usb_hub_events(void)
spin_unlock_irqrestore(&hub_event_lock, flags);
if (hub->error) {
- dbg("resetting hub %d for error %d", dev->devnum, hub->error);
+ dbg("resetting hub %s for error %d",
+ dev->devpath, hub->error);
if (usb_hub_reset(hub)) {
- err("error resetting hub %d - disconnecting", dev->devnum);
+ err("error resetting hub %s - disconnecting",
+ dev->devpath);
up(&hub->khubd_sem);
usb_hub_disconnect(dev);
continue;
@@ -756,7 +790,8 @@ static void usb_hub_events(void)
ret = usb_get_port_status(dev, i + 1, &portsts);
if (ret < 0) {
- err("get_port_status failed (err = %d)", ret);
+ err("hub %s get_port_status failed (err = %d)",
+ dev->devpath, ret);
continue;
}
@@ -764,55 +799,68 @@ static void usb_hub_events(void)
portchange = le16_to_cpu(portsts.wPortChange);
if (portchange & USB_PORT_STAT_C_CONNECTION) {
- dbg("port %d connection change", i + 1);
-
- usb_hub_port_connect_change(dev, i, &portsts);
+ dbg("hub %s port %d connection change",
+ dev->devpath, i + 1);
+ usb_hub_port_connect_change(hub, i, &portsts);
} else if (portchange & USB_PORT_STAT_C_ENABLE) {
- dbg("port %d enable change, status %x", i + 1, portstatus);
- usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
+ dbg("hub %s port %d enable change, status %x",
+ dev->devpath, i + 1, portstatus);
+ usb_clear_port_feature(dev,
+ i + 1, USB_PORT_FEAT_C_ENABLE);
/*
- * EM interference sometimes causes bad shielded USB devices to
- * be shutdown by the hub, this hack enables them again.
+ * EM interference sometimes causes badly
+ * shielded USB devices to be shutdown by
+ * the hub, this hack enables them again.
* Works at least with mouse driver.
*/
- if (!(portstatus & USB_PORT_STAT_ENABLE) &&
- (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) {
- err("already running port %i disabled by hub (EMI?), re-enabling...",
- i + 1);
- usb_hub_port_connect_change(dev, i, &portsts);
+ if (!(portstatus & USB_PORT_STAT_ENABLE)
+ && (portstatus & USB_PORT_STAT_CONNECTION)
+ && (dev->children[i])) {
+ err("already running hub %s port %i "
+ "disabled by hub (EMI?), "
+ "re-enabling...",
+ dev->devpath, i + 1);
+ usb_hub_port_connect_change(hub,
+ i, &portsts);
}
}
if (portchange & USB_PORT_STAT_C_SUSPEND) {
- dbg("port %d suspend change", i + 1);
- usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_SUSPEND);
+ dbg("hub %s port %d suspend change",
+ dev->devpath, i + 1);
+ usb_clear_port_feature(dev,
+ i + 1, USB_PORT_FEAT_C_SUSPEND);
}
if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
- err("port %d over-current change", i + 1);
- usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
+ err("hub %s port %d over-current change",
+ dev->devpath, i + 1);
+ usb_clear_port_feature(dev,
+ i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
usb_hub_power_on(hub);
}
if (portchange & USB_PORT_STAT_C_RESET) {
- dbg("port %d reset change", i + 1);
- usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
+ dbg("hub %s port %d reset change",
+ dev->devpath, i + 1);
+ usb_clear_port_feature(dev,
+ i + 1, USB_PORT_FEAT_C_RESET);
}
} /* end for i */
/* deal with hub status changes */
if (usb_get_hub_status(dev, &hubsts) < 0)
- err("get_hub_status failed");
+ err("get_hub_status %s failed", dev->devpath);
else {
hubstatus = le16_to_cpup(&hubsts.wHubStatus);
hubchange = le16_to_cpup(&hubsts.wHubChange);
if (hubchange & HUB_CHANGE_LOCAL_POWER) {
- dbg("hub power change");
+ dbg("hub %s power change", dev->devpath);
usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
}
if (hubchange & HUB_CHANGE_OVERCURRENT) {
- dbg("hub overcurrent change");
+ dbg("hub %s overcurrent change", dev->devpath);
wait_ms(500); /* Cool down */
usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
usb_hub_power_on(hub);
@@ -851,6 +899,8 @@ static int usb_hub_thread(void *__hub)
}
static struct usb_device_id hub_id_table [] = {
+ { match_flags: USB_DEVICE_ID_MATCH_DEV_CLASS,
+ bDeviceClass: USB_CLASS_HUB},
{ match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
bInterfaceClass: USB_CLASS_HUB},
{ } /* Terminating entry */
@@ -989,9 +1039,13 @@ int usb_reset_device(struct usb_device *dev)
ret = usb_get_device_descriptor(dev);
if (ret < sizeof(dev->descriptor)) {
if (ret < 0)
- err("unable to get device descriptor (error=%d)", ret);
+ err("unable to get device %s descriptor "
+ "(error=%d)", dev->devpath, ret);
else
- err("USB device descriptor short read (expected %Zi, got %i)", sizeof(dev->descriptor), ret);
+ err("USB device %s descriptor short read "
+ "(expected %Zi, got %i)",
+ dev->devpath,
+ sizeof(dev->descriptor), ret);
clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
dev->devnum = -1;
@@ -1015,17 +1069,22 @@ int usb_reset_device(struct usb_device *dev)
ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
if (ret < 0) {
- err("failed to set active configuration (error=%d)", ret);
+ err("failed to set dev %s active configuration (error=%d)",
+ dev->devpath, ret);
return ret;
}
for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
struct usb_interface *intf = &dev->actconfig->interface[i];
- struct usb_interface_descriptor *as = &intf->altsetting[intf->act_altsetting];
+ struct usb_interface_descriptor *as;
- ret = usb_set_interface(dev, as->bInterfaceNumber, as->bAlternateSetting);
+ as = &intf->altsetting[intf->act_altsetting];
+ ret = usb_set_interface(dev, as->bInterfaceNumber,
+ as->bAlternateSetting);
if (ret < 0) {
- err("failed to set active alternate setting for interface %d (error=%d)", i, ret);
+ err("failed to set active alternate setting "
+ "for dev %s interface %d (error=%d)",
+ dev->devpath, i, ret);
return ret;
}
}
diff --git a/drivers/usb/hub.h b/drivers/usb/hub.h
index 50ae148c5..566da376d 100644
--- a/drivers/usb/hub.h
+++ b/drivers/usb/hub.h
@@ -1,6 +1,13 @@
#ifndef __LINUX_HUB_H
#define __LINUX_HUB_H
+/*
+ * Hub protocol and driver data structures.
+ *
+ * Some of these are known to the "virtual root hub" code
+ * in host controller drivers.
+ */
+
#include <linux/list.h>
/*
@@ -11,6 +18,15 @@
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
/*
+ * Hub class requests
+ * See USB 2.0 spec Table 11-16
+ */
+#define HUB_CLEAR_TT_BUFFER 8
+#define HUB_RESET_TT 9
+#define HUB_GET_TT_STATE 10
+#define HUB_STOP_TT 11
+
+/*
* Hub Class feature numbers
* See USB 2.0 spec Table 11-17
*/
@@ -55,7 +71,7 @@ struct usb_port_status {
#define USB_PORT_STAT_SUSPEND 0x0004
#define USB_PORT_STAT_OVERCURRENT 0x0008
#define USB_PORT_STAT_RESET 0x0010
-/* bits 5 for 7 are reserved */
+/* bits 5 to 7 are reserved */
#define USB_PORT_STAT_POWER 0x0100
#define USB_PORT_STAT_LOW_SPEED 0x0200
#define USB_PORT_STAT_HIGH_SPEED 0x0400
@@ -120,22 +136,21 @@ struct usb_hub_descriptor {
struct usb_device;
struct usb_hub {
- struct usb_device *dev;
-
- struct urb *urb; /* Interrupt polling pipe */
-
- char buffer[(USB_MAXCHILDREN + 1 + 7) / 8]; /* add 1 bit for hub status change */
- /* and add 7 bits to round up to byte boundary */
- int error;
- int nerrors;
+ struct usb_device *dev; /* the "real" device */
+ struct urb *urb; /* for interrupt polling pipe */
- struct list_head hub_list;
+ /* buffer for urb ... 1 bit each for hub and children, rounded up */
+ char buffer[(USB_MAXCHILDREN + 1 + 7) / 8];
- struct list_head event_list;
+ int error; /* last reported error */
+ int nerrors; /* track consecutive errors */
- struct usb_hub_descriptor *descriptor;
+ struct list_head hub_list; /* all hubs */
+ struct list_head event_list; /* hubs w/data or errs ready */
- struct semaphore khubd_sem;
+ struct usb_hub_descriptor *descriptor; /* class descriptor */
+ struct semaphore khubd_sem;
+ struct usb_tt tt; /* Transaction Translator */
};
#endif /* __LINUX_HUB_H */
diff --git a/drivers/usb/inode.c b/drivers/usb/inode.c
index cd38ce06a..a73a209dc 100644
--- a/drivers/usb/inode.c
+++ b/drivers/usb/inode.c
@@ -3,8 +3,8 @@
/*
* inode.c -- Inode/Dentry functions for the USB device file system.
*
- * Copyright (C) 2000
- * Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,10 +20,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: inode.c,v 1.3 2000/01/11 13:58:25 tom Exp $
- *
* History:
* 0.1 04.01.2000 Created
+ * 0.2 10.12.2001 converted to use the vfs layer better
*/
/*****************************************************************************/
@@ -32,146 +31,40 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/locks.h>
+#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
-#include <asm/uaccess.h>
-
-/* --------------------------------------------------------------------- */
-
-/*
- * This list of superblocks is still used,
- * but since usbdevfs became FS_SINGLE
- * there is only one super_block.
- */
-static LIST_HEAD(superlist);
-
-struct special {
- const char *name;
- struct file_operations *fops;
- struct inode *inode;
- struct list_head inodes;
-};
-
-static struct special special[] = {
- { "devices", &usbdevfs_devices_fops, },
- { "drivers", &usbdevfs_drivers_fops, }
-};
-
-#define NRSPECIAL (sizeof(special)/sizeof(special[0]))
-
-/* --------------------------------------------------------------------- */
-
-static int dnumber(struct dentry *dentry)
-{
- const char *name;
- unsigned int s;
-
- if (dentry->d_name.len != 3)
- return -1;
- name = dentry->d_name.name;
- if (name[0] < '0' || name[0] > '9' ||
- name[1] < '0' || name[1] > '9' ||
- name[2] < '0' || name[2] > '9')
- return -1;
- s = name[0] - '0';
- s = s * 10 + name[1] - '0';
- s = s * 10 + name[2] - '0';
- return s;
-}
-
-/*
- * utility functions; should be called with the kernel lock held
- * to protect against busses/devices appearing/disappearing
- */
-
-static void new_dev_inode(struct usb_device *dev, struct super_block *sb)
-{
- struct inode *inode;
- unsigned int devnum = dev->devnum;
- unsigned int busnum = dev->bus->busnum;
-
- if (devnum < 1 || devnum > 127 || busnum > 255)
- return;
- inode = iget(sb, IDEVICE | (busnum << 8) | devnum);
- if (!inode) {
- printk(KERN_ERR "usbdevfs: cannot create inode for bus %u device %u\n", busnum, devnum);
- return;
- }
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_uid = sb->u.usbdevfs_sb.devuid;
- inode->i_gid = sb->u.usbdevfs_sb.devgid;
- inode->i_mode = sb->u.usbdevfs_sb.devmode | S_IFREG;
- inode->i_fop = &usbdevfs_device_file_operations;
- inode->i_size = sizeof(struct usb_device_descriptor);
- inode->u.usbdev_i.p.dev = dev;
- list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
- list_add_tail(&inode->u.usbdev_i.dlist, &dev->inodes);
-}
-static void recurse_new_dev_inode(struct usb_device *dev, struct super_block *sb)
-{
- unsigned int i;
- if (!dev)
- return;
- new_dev_inode(dev, sb);
- for (i = 0; i < dev->maxchild; i++) {
- if (!dev->children[i])
- continue;
- recurse_new_dev_inode(dev->children[i], sb);
- }
-}
-
-static void new_bus_inode(struct usb_bus *bus, struct super_block *sb)
-{
- struct inode *inode;
- unsigned int busnum = bus->busnum;
-
- if (busnum > 255)
- return;
- inode = iget(sb, IBUS | (busnum << 8));
- if (!inode) {
- printk(KERN_ERR "usbdevfs: cannot create inode for bus %u\n", busnum);
- return;
- }
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_uid = sb->u.usbdevfs_sb.busuid;
- inode->i_gid = sb->u.usbdevfs_sb.busgid;
- inode->i_mode = sb->u.usbdevfs_sb.busmode | S_IFDIR;
- inode->i_op = &usbdevfs_bus_inode_operations;
- inode->i_fop = &usbdevfs_bus_file_operations;
- inode->u.usbdev_i.p.bus = bus;
- list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
- list_add_tail(&inode->u.usbdev_i.dlist, &bus->inodes);
-}
-
-static void free_inode(struct inode *inode)
-{
- inode->u.usbdev_i.p.bus = NULL;
- inode->u.usbdev_i.p.dev = NULL;
- inode->i_mode &= ~S_IRWXUGO;
- inode->i_uid = inode->i_gid = 0;
- inode->i_size = 0;
- list_del(&inode->u.usbdev_i.slist);
- INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
- list_del(&inode->u.usbdev_i.dlist);
- INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
- iput(inode);
-}
+static struct super_operations usbfs_ops;
+static struct address_space_operations usbfs_aops;
+static struct file_operations usbfs_dir_operations;
+static struct file_operations default_file_operations;
+static struct inode_operations usbfs_dir_inode_operations;
+static struct vfsmount *usbfs_mount;
+static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
+static int mount_count; /* = 0 */
+
+static struct dentry *devices_dentry;
+static struct dentry *drivers_dentry;
+static int num_buses; /* = 0 */
+
+static uid_t devuid; /* = 0 */
+static uid_t busuid; /* = 0 */
+static uid_t listuid; /* = 0 */
+static gid_t devgid; /* = 0 */
+static gid_t busgid; /* = 0 */
+static gid_t listgid; /* = 0 */
+static umode_t devmode = S_IWUSR | S_IRUGO;
+static umode_t busmode = S_IXUGO | S_IRUGO;
+static umode_t listmode = S_IRUGO;
static int parse_options(struct super_block *s, char *data)
{
- uid_t devuid = 0, busuid = 0, listuid = 0;
- gid_t devgid = 0, busgid = 0, listgid = 0;
- umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;
char *curopt = NULL, *value;
- /* parse options */
if (data)
curopt = strtok(data, ",");
for (; curopt; curopt = strtok(NULL, ",")) {
@@ -242,481 +135,572 @@ static int parse_options(struct super_block *s, char *data)
}
}
- s->u.usbdevfs_sb.devuid = devuid;
- s->u.usbdevfs_sb.devgid = devgid;
- s->u.usbdevfs_sb.devmode = devmode;
- s->u.usbdevfs_sb.busuid = busuid;
- s->u.usbdevfs_sb.busgid = busgid;
- s->u.usbdevfs_sb.busmode = busmode;
- s->u.usbdevfs_sb.listuid = listuid;
- s->u.usbdevfs_sb.listgid = listgid;
- s->u.usbdevfs_sb.listmode = listmode;
-
return 0;
}
-static struct usb_bus *usbdevfs_findbus(int busnr)
+
+/* --------------------------------------------------------------------- */
+
+static struct dentry *usbfs_lookup (struct inode *dir, struct dentry *dentry)
{
- struct list_head *list;
- struct usb_bus *bus;
+ d_add(dentry, NULL);
+ return NULL;
+}
- down (&usb_bus_list_lock);
- for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {
- bus = list_entry(list, struct usb_bus, bus_list);
- if (bus->busnum == busnr) {
- up (&usb_bus_list_lock);
- return bus;
+static int usbfs_statfs(struct super_block *sb, struct statfs *buf)
+{
+ buf->f_type = USBDEVICE_SUPER_MAGIC;
+ buf->f_bsize = PAGE_CACHE_SIZE;
+ buf->f_namelen = NAME_MAX;
+ return 0;
+}
+
+static struct inode *usbfs_get_inode (struct super_block *sb, int mode, int dev)
+{
+ struct inode *inode = new_inode(sb);
+
+ if (inode) {
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_rdev = NODEV;
+ inode->i_mapping->a_ops = &usbfs_aops;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ switch (mode & S_IFMT) {
+ default:
+ init_special_inode(inode, mode, dev);
+ break;
+ case S_IFREG:
+ inode->i_fop = &default_file_operations;
+ break;
+ case S_IFDIR:
+ inode->i_op = &usbfs_dir_inode_operations;
+ inode->i_fop = &usbfs_dir_operations;
+ break;
}
- }
- up (&usb_bus_list_lock);
- return NULL;
+ }
+ return inode;
}
-#if 0
-static struct usb_device *finddev(struct usb_device *dev, int devnr)
+static int usbfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
+ int dev)
{
- unsigned int i;
- struct usb_device *d2;
+ struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev);
+ int error = -ENOSPC;
- if (!dev)
- return NULL;
- if (dev->devnum == devnr)
- return dev;
- for (i = 0; i < dev->maxchild; i++) {
- if (!dev->children[i])
- continue;
- if ((d2 = finddev(dev->children[i], devnr)))
- return d2;
- }
- return NULL;
+ if (inode) {
+ d_instantiate(dentry, inode);
+ dget(dentry);
+ error = 0;
+ }
+ return error;
}
-static struct usb_device *usbdevfs_finddevice(struct usb_bus *bus, int devnr)
+static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
{
- return finddev(bus->root_hub, devnr);
+ return usbfs_mknod (dir, dentry, mode | S_IFDIR, 0);
}
-#endif
-/* --------------------------------------------------------------------- */
+static int usbfs_create (struct inode *dir, struct dentry *dentry, int mode)
+{
+ return usbfs_mknod (dir, dentry, mode | S_IFREG, 0);
+}
-static int usbdevfs_revalidate(struct dentry *dentry, int flags)
+static int usbfs_link (struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = old_dentry->d_inode;
- if (!inode)
- return 0;
- if (ITYPE(inode->i_ino) == IBUS && !inode->u.usbdev_i.p.bus)
- return 0;
- if (ITYPE(inode->i_ino) == IDEVICE && !inode->u.usbdev_i.p.dev)
- return 0;
- return 1;
+ if(S_ISDIR(inode->i_mode))
+ return -EPERM;
+
+ inode->i_nlink++;
+ atomic_inc(&inode->i_count);
+ dget(dentry);
+ d_instantiate(dentry, inode);
+ return 0;
}
-static struct dentry_operations usbdevfs_dentry_operations = {
- d_revalidate: usbdevfs_revalidate,
-};
+static inline int usbfs_positive (struct dentry *dentry)
+{
+ return dentry->d_inode && !d_unhashed(dentry);
+}
-static struct dentry *usbdevfs_root_lookup(struct inode *dir, struct dentry *dentry)
+static int usbfs_empty (struct dentry *dentry)
{
- int busnr;
- unsigned long ino = 0;
- unsigned int i;
- struct inode *inode;
+ struct list_head *list;
- /* sanity check */
- if (dir->i_ino != IROOT)
- return ERR_PTR(-EINVAL);
- dentry->d_op = &usbdevfs_dentry_operations;
- busnr = dnumber(dentry);
- if (busnr >= 0 && busnr <= 255)
- ino = IBUS | (busnr << 8);
- if (!ino) {
- for (i = 0; i < NRSPECIAL; i++) {
- if (strlen(special[i].name) == dentry->d_name.len &&
- !strncmp(special[i].name, dentry->d_name.name, dentry->d_name.len)) {
- ino = ISPECIAL | (i + IROOT + 1);
- break;
- }
+ spin_lock(&dcache_lock);
+
+ list_for_each(list, &dentry->d_subdirs) {
+ struct dentry *de = list_entry(list, struct dentry, d_child);
+ if (usbfs_positive(de)) {
+ spin_unlock(&dcache_lock);
+ return 0;
}
}
- if (!ino)
- return ERR_PTR(-ENOENT);
- inode = iget(dir->i_sb, ino);
- if (!inode)
- return ERR_PTR(-EINVAL);
- if (inode && ITYPE(ino) == IBUS && inode->u.usbdev_i.p.bus == NULL) {
- iput(inode);
- inode = NULL;
- }
- d_add(dentry, inode);
- return NULL;
+
+ spin_unlock(&dcache_lock);
+ return 1;
}
-static struct dentry *usbdevfs_bus_lookup(struct inode *dir, struct dentry *dentry)
+static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
{
- struct inode *inode;
- int devnr;
-
- /* sanity check */
- if (ITYPE(dir->i_ino) != IBUS)
- return ERR_PTR(-EINVAL);
- dentry->d_op = &usbdevfs_dentry_operations;
- devnr = dnumber(dentry);
- if (devnr < 1 || devnr > 127)
- return ERR_PTR(-ENOENT);
- inode = iget(dir->i_sb, IDEVICE | (dir->i_ino & (0xff << 8)) | devnr);
- if (!inode)
- return ERR_PTR(-EINVAL);
- if (inode && inode->u.usbdev_i.p.dev == NULL) {
- iput(inode);
- inode = NULL;
+ int error = -ENOTEMPTY;
+
+ if (usbfs_empty(dentry)) {
+ struct inode *inode = dentry->d_inode;
+
+ inode->i_nlink--;
+ dput(dentry);
+ error = 0;
}
- d_add(dentry, inode);
- return NULL;
+ return error;
}
-static int usbdevfs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
+static int usbfs_rename (struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
- struct inode *inode = filp->f_dentry->d_inode;
- unsigned long ino = inode->i_ino;
- struct special *spec;
- struct list_head *list;
- struct usb_bus *bus;
- char numbuf[8];
- unsigned int i;
-
- /* sanity check */
- if (ino != IROOT)
- return -EINVAL;
- i = filp->f_pos;
- switch (i) {
- case 0:
- if (filldir(dirent, ".", 1, i, IROOT, DT_DIR) < 0)
- return 0;
- filp->f_pos++;
- i++;
- /* fall through */
+ int error = -ENOTEMPTY;
- case 1:
- if (filldir(dirent, "..", 2, i, IROOT, DT_DIR) < 0)
- return 0;
- filp->f_pos++;
- i++;
- /* fall through */
-
- default:
-
- while (i >= 2 && i < 2+NRSPECIAL) {
- spec = &special[filp->f_pos-2];
- if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT), DT_UNKNOWN) < 0)
- return 0;
- filp->f_pos++;
- i++;
- }
- if (i < 2+NRSPECIAL)
- return 0;
- i -= 2+NRSPECIAL;
- down (&usb_bus_list_lock);
- for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {
- if (i > 0) {
- i--;
- continue;
- }
- bus = list_entry(list, struct usb_bus, bus_list);
- sprintf(numbuf, "%03d", bus->busnum);
- if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8), DT_UNKNOWN) < 0)
- break;
- filp->f_pos++;
+ if (usbfs_empty(new_dentry)) {
+ struct inode *inode = new_dentry->d_inode;
+ if (inode) {
+ inode->i_nlink--;
+ dput(new_dentry);
}
- up (&usb_bus_list_lock);
- return 0;
+ error = 0;
}
+ return error;
}
-static int bus_readdir(struct usb_device *dev, unsigned long ino, int pos, struct file *filp, void *dirent, filldir_t filldir)
+#define usbfs_rmdir usbfs_unlink
+
+/* default file operations */
+static ssize_t default_read_file (struct file *file, char *buf,
+ size_t count, loff_t *ppos)
{
- char numbuf[8];
- unsigned int i;
+ return 0;
+}
- if (!dev)
- return pos;
- sprintf(numbuf, "%03d", dev->devnum);
- if (pos > 0)
- pos--;
- else {
- if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff), DT_UNKNOWN) < 0)
- return -1;
- filp->f_pos++;
- }
- for (i = 0; i < dev->maxchild; i++) {
- if (!dev->children[i])
- continue;
- pos = bus_readdir(dev->children[i], ino, pos, filp, dirent, filldir);
- if (pos < 0)
- return -1;
- }
- return pos;
+static ssize_t default_write_file (struct file *file, const char *buf,
+ size_t count, loff_t *ppos)
+{
+ return count;
}
-static int usbdevfs_bus_readdir(struct file *filp, void *dirent, filldir_t filldir)
+static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
{
- struct inode *inode = filp->f_dentry->d_inode;
- unsigned long ino = inode->i_ino;
- struct usb_bus *bus;
+ loff_t retval = -EINVAL;
- /* sanity check */
- if (ITYPE(ino) != IBUS)
- return -EINVAL;
- switch ((unsigned int)filp->f_pos) {
+ switch(orig) {
case 0:
- if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0)
- return 0;
- filp->f_pos++;
- /* fall through */
-
+ if (offset > 0) {
+ file->f_pos = offset;
+ retval = file->f_pos;
+ }
+ break;
case 1:
- if (filldir(dirent, "..", 2, filp->f_pos, IROOT, DT_DIR) < 0)
- return 0;
- filp->f_pos++;
- /* fall through */
-
+ if ((offset + file->f_pos) > 0) {
+ file->f_pos += offset;
+ retval = file->f_pos;
+ }
+ break;
default:
- lock_kernel();
- bus = usbdevfs_findbus(IBUSNR(ino));
- bus_readdir(bus->root_hub, IDEVICE | ((bus->busnum & 0xff) << 8), filp->f_pos-2, filp, dirent, filldir);
- unlock_kernel();
- return 0;
+ break;
}
+ return retval;
+}
+
+static int default_open (struct inode *inode, struct file *filp)
+{
+ if (inode->u.generic_ip)
+ filp->private_data = inode->u.generic_ip;
+
+ return 0;
+}
+
+static int default_sync_file (struct file *file, struct dentry *dentry,
+ int datasync)
+{
+ return 0;
}
-static struct file_operations usbdevfs_root_file_operations = {
- readdir: usbdevfs_root_readdir,
+static struct address_space_operations usbfs_aops = {
};
-static struct inode_operations usbdevfs_root_inode_operations = {
- lookup: usbdevfs_root_lookup,
+static struct file_operations usbfs_dir_operations = {
+ read: generic_read_dir,
+ readdir: dcache_readdir,
+ fsync: default_sync_file,
};
-static struct file_operations usbdevfs_bus_file_operations = {
- readdir: usbdevfs_bus_readdir,
+static struct file_operations default_file_operations = {
+ read: default_read_file,
+ write: default_write_file,
+ open: default_open,
+ llseek: default_file_lseek,
+ fsync: default_sync_file,
+ mmap: generic_file_mmap,
};
-static struct inode_operations usbdevfs_bus_inode_operations = {
- lookup: usbdevfs_bus_lookup,
+static struct inode_operations usbfs_dir_inode_operations = {
+ create: usbfs_create,
+ lookup: usbfs_lookup,
+ link: usbfs_link,
+ unlink: usbfs_unlink,
+ mkdir: usbfs_mkdir,
+ rmdir: usbfs_rmdir,
+ mknod: usbfs_mknod,
+ rename: usbfs_rename,
};
-static void usbdevfs_read_inode(struct inode *inode)
-{
- struct special *spec;
-
- inode->i_ctime = inode->i_mtime = inode->i_atime = CURRENT_TIME;
- inode->i_mode = S_IFREG;
- inode->i_gid = inode->i_uid = 0;
- INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
- INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
- inode->u.usbdev_i.p.dev = NULL;
- inode->u.usbdev_i.p.bus = NULL;
- switch (ITYPE(inode->i_ino)) {
- case ISPECIAL:
- if (inode->i_ino == IROOT) {
- inode->i_op = &usbdevfs_root_inode_operations;
- inode->i_fop = &usbdevfs_root_file_operations;
- inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
- return;
- }
- if (inode->i_ino <= IROOT || inode->i_ino > IROOT+NRSPECIAL)
- return;
- spec = &special[inode->i_ino-(IROOT+1)];
- inode->i_fop = spec->fops;
- return;
+static struct super_operations usbfs_ops = {
+ statfs: usbfs_statfs,
+ put_inode: force_delete,
+};
- case IDEVICE:
- return;
+static struct super_block *usbfs_read_super (struct super_block *sb, void *data,
+ int silent)
+{
+ struct inode *inode;
+ struct dentry *root;
- case IBUS:
- return;
+ if (parse_options(sb, data)) {
+ warn("usbfs: mount parameter error:");
+ return NULL;
+ }
- default:
- return;
- }
-}
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = USBDEVICE_SUPER_MAGIC;
+ sb->s_op = &usbfs_ops;
+ inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
-static void usbdevfs_put_super(struct super_block *sb)
-{
- list_del(&sb->u.usbdevfs_sb.slist);
- INIT_LIST_HEAD(&sb->u.usbdevfs_sb.slist);
- while (!list_empty(&sb->u.usbdevfs_sb.ilist))
- free_inode(list_entry(sb->u.usbdevfs_sb.ilist.next, struct inode, u.usbdev_i.slist));
-}
+ if (!inode) {
+ dbg("%s: could not get inode!\n",__FUNCTION__);
+ return NULL;
+ }
-static int usbdevfs_statfs(struct super_block *sb, struct statfs *buf)
-{
- buf->f_type = USBDEVICE_SUPER_MAGIC;
- buf->f_bsize = PAGE_SIZE/sizeof(long); /* ??? */
- buf->f_bfree = 0;
- buf->f_bavail = 0;
- buf->f_ffree = 0;
- buf->f_namelen = NAME_MAX;
- return 0;
+ root = d_alloc_root(inode);
+ if (!root) {
+ dbg("%s: could not get root dentry!\n",__FUNCTION__);
+ iput(inode);
+ return NULL;
+ }
+ sb->s_root = root;
+ return sb;
}
-static int usbdevfs_remount(struct super_block *s, int *flags, char *data)
+/**
+ * fs_create_by_name - create a file, given a name
+ * @name: name of file
+ * @mode: type of file
+ * @parent: dentry of directory to create it in
+ * @dentry: resulting dentry of file
+ *
+ * There is a bit of overhead in creating a file - basically, we
+ * have to hash the name of the file, then look it up. This will
+ * prevent files of the same name.
+ * We then call the proper vfs_ function to take care of all the
+ * file creation details.
+ * This function handles both regular files and directories.
+ */
+static int fs_create_by_name (const char *name, mode_t mode,
+ struct dentry *parent, struct dentry **dentry)
{
- struct list_head *ilist = s->u.usbdevfs_sb.ilist.next;
- struct inode *inode;
- int ret;
+ struct dentry *d = NULL;
+ struct qstr qstr;
+ int error;
+
+ /* If the parent is not specified, we create it in the root.
+ * We need the root dentry to do this, which is in the super
+ * block. A pointer to that is in the struct vfsmount that we
+ * have around.
+ */
+ if (!parent ) {
+ if (usbfs_mount && usbfs_mount->mnt_sb) {
+ parent = usbfs_mount->mnt_sb->s_root;
+ }
+ }
- if ((ret = parse_options(s, data))) {
- printk(KERN_WARNING "usbdevfs: remount parameter error\n");
- return ret;
+ if (!parent) {
+ dbg("Ah! can not find a parent!\n");
+ return -EFAULT;
}
- for (; ilist != &s->u.usbdevfs_sb.ilist; ilist = ilist->next) {
- inode = list_entry(ilist, struct inode, u.usbdev_i.slist);
+ *dentry = NULL;
+ qstr.name = name;
+ qstr.len = strlen(name);
+ qstr.hash = full_name_hash(name,qstr.len);
- switch (ITYPE(inode->i_ino)) {
- case ISPECIAL :
- inode->i_uid = s->u.usbdevfs_sb.listuid;
- inode->i_gid = s->u.usbdevfs_sb.listgid;
- inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG;
- break;
- case IBUS :
- inode->i_uid = s->u.usbdevfs_sb.busuid;
- inode->i_gid = s->u.usbdevfs_sb.busgid;
- inode->i_mode = s->u.usbdevfs_sb.busmode | S_IFDIR;
+ parent = dget(parent);
+
+ down(&parent->d_inode->i_sem);
+
+ d = lookup_hash(&qstr,parent);
+
+ error = PTR_ERR(d);
+ if (!IS_ERR(d)) {
+ switch(mode & S_IFMT) {
+ case 0:
+ case S_IFREG:
+ error = vfs_create(parent->d_inode,d,mode);
break;
- case IDEVICE :
- inode->i_uid = s->u.usbdevfs_sb.devuid;
- inode->i_gid = s->u.usbdevfs_sb.devgid;
- inode->i_mode = s->u.usbdevfs_sb.devmode | S_IFREG;
+ case S_IFDIR:
+ error = vfs_mkdir(parent->d_inode,d,mode);
break;
+ default:
+ err("cannot create special files\n");
}
+ *dentry = d;
}
+ up(&parent->d_inode->i_sem);
- return 0;
+ dput(parent);
+ return error;
}
-static struct super_operations usbdevfs_sops = {
- read_inode: usbdevfs_read_inode,
- put_super: usbdevfs_put_super,
- statfs: usbdevfs_statfs,
- remount_fs: usbdevfs_remount,
-};
+static struct dentry *fs_create_file (const char *name, mode_t mode,
+ struct dentry *parent, void *data,
+ struct file_operations *fops,
+ uid_t uid, gid_t gid)
+{
+ struct dentry *dentry;
+ int error;
+
+ dbg("creating file '%s'\n",name);
+
+ error = fs_create_by_name(name,mode,parent,&dentry);
+ if (error) {
+ dentry = NULL;
+ } else {
+ if (dentry->d_inode) {
+ if (data)
+ dentry->d_inode->u.generic_ip = data;
+ if (fops)
+ dentry->d_inode->i_fop = fops;
+ dentry->d_inode->i_uid = uid;
+ dentry->d_inode->i_gid = gid;
+ }
+ }
+
+ return dentry;
+}
-struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int silent)
+static void fs_remove_file (struct dentry *dentry)
{
- struct inode *root_inode, *inode;
- struct list_head *blist;
- struct usb_bus *bus;
- unsigned int i;
+ struct dentry *parent = dentry->d_parent;
+
+ if (!parent || !parent->d_inode)
+ return;
- if (parse_options(s, data)) {
- printk(KERN_WARNING "usbdevfs: mount parameter error\n");
- return NULL;
- }
+ down(&parent->d_inode->i_sem);
+ if (usbfs_positive(dentry)) {
+ if (dentry->d_inode) {
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ vfs_rmdir(parent->d_inode,dentry);
+ else
+ vfs_unlink(parent->d_inode,dentry);
+ }
- /* fill superblock */
- s->s_blocksize = 1024;
- s->s_blocksize_bits = 10;
- s->s_magic = USBDEVICE_SUPER_MAGIC;
- s->s_op = &usbdevfs_sops;
- INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist);
- INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist);
- root_inode = iget(s, IROOT);
- if (!root_inode)
- goto out_no_root;
- s->s_root = d_alloc_root(root_inode);
- if (!s->s_root)
- goto out_no_root;
- list_add_tail(&s->u.usbdevfs_sb.slist, &superlist);
- for (i = 0; i < NRSPECIAL; i++) {
- if (!(inode = iget(s, IROOT+1+i)))
- continue;
- inode->i_uid = s->u.usbdevfs_sb.listuid;
- inode->i_gid = s->u.usbdevfs_sb.listgid;
- inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG;
- special[i].inode = inode;
- list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist);
- list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes);
- }
- down (&usb_bus_list_lock);
- for (blist = usb_bus_list.next; blist != &usb_bus_list; blist = blist->next) {
- bus = list_entry(blist, struct usb_bus, bus_list);
- new_bus_inode(bus, s);
- recurse_new_dev_inode(bus->root_hub, s);
+ dput(dentry);
}
- up (&usb_bus_list_lock);
- return s;
-
- out_no_root:
- printk("usbdevfs_read_super: get root inode failed\n");
- iput(root_inode);
- return NULL;
+ up(&parent->d_inode->i_sem);
}
+/* --------------------------------------------------------------------- */
+
+
+
/*
- * The usbdevfs name is now depreciated (as of 2.5.1).
+ * The usbdevfs name is now deprecated (as of 2.5.1).
* It will be removed when the 2.7.x development cycle is started.
* You have been warned :)
*/
-static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, FS_SINGLE);
-static DECLARE_FSTYPE(usb_fs_type, "usbfs", usbdevfs_read_super, FS_SINGLE);
+static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbfs_read_super, FS_SINGLE);
+static DECLARE_FSTYPE(usb_fs_type, "usbfs", usbfs_read_super, FS_SINGLE);
/* --------------------------------------------------------------------- */
+static int get_mount (void)
+{
+ struct vfsmount *mnt;
+
+ spin_lock (&mount_lock);
+ if (usbfs_mount) {
+ mntget(usbfs_mount);
+ ++mount_count;
+ spin_unlock (&mount_lock);
+ goto go_ahead;
+ }
+
+ spin_unlock (&mount_lock);
+ mnt = kern_mount (&usbdevice_fs_type);
+ if (IS_ERR(mnt)) {
+ err ("could not mount the fs...erroring out!\n");
+ return -ENODEV;
+ }
+ spin_lock (&mount_lock);
+ if (!usbfs_mount) {
+ usbfs_mount = mnt;
+ ++mount_count;
+ spin_unlock (&mount_lock);
+ goto go_ahead;
+ }
+ mntget(usbfs_mount);
+ ++mount_count;
+ spin_unlock (&mount_lock);
+ mntput(mnt);
+
+go_ahead:
+ dbg("mount_count = %d\n", mount_count);
+ return 0;
+}
+
+static void remove_mount (void)
+{
+ struct vfsmount *mnt;
+
+ spin_lock (&mount_lock);
+ mnt = usbfs_mount;
+ --mount_count;
+ if (!mount_count)
+ usbfs_mount = NULL;
+
+ spin_unlock (&mount_lock);
+ mntput(mnt);
+ dbg("mount_count = %d\n", mount_count);
+}
-static void update_special_inodes (void)
+static int create_special_files (void)
{
- int i;
- for (i = 0; i < NRSPECIAL; i++) {
- struct inode *inode = special[i].inode;
+ int retval;
+
+ /* create the devices and drivers special files */
+ retval = get_mount ();
+ if (retval)
+ return retval;
+ devices_dentry = fs_create_file ("devices",
+ listmode | S_IFREG,
+ NULL, NULL,
+ &usbdevfs_devices_fops,
+ listuid, listgid);
+ if (devices_dentry == NULL) {
+ err ("Unable to create devices usbfs file");
+ return -ENODEV;
+ }
+
+ drivers_dentry = fs_create_file ("drivers",
+ listmode | S_IFREG,
+ NULL, NULL,
+ &usbdevfs_drivers_fops,
+ listuid, listgid);
+ if (drivers_dentry == NULL) {
+ err ("Unable to create drivers usbfs file");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void remove_special_files (void)
+{
+ if (devices_dentry)
+ fs_remove_file (devices_dentry);
+ if (drivers_dentry)
+ fs_remove_file (drivers_dentry);
+ devices_dentry = NULL;
+ drivers_dentry = NULL;
+ remove_mount();
+}
+
+void usbfs_update_special (void)
+{
+ struct inode *inode;
+
+ if (devices_dentry) {
+ inode = devices_dentry->d_inode;
+ if (inode)
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ }
+ if (drivers_dentry) {
+ inode = devices_dentry->d_inode;
if (inode)
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}
}
-
-void usbdevfs_add_bus(struct usb_bus *bus)
+void usbfs_add_bus(struct usb_bus *bus)
{
- struct list_head *slist;
+ char name[8];
+ int retval;
+
+ /* create the special files if this is the first bus added */
+ if (num_buses == 0) {
+ retval = create_special_files();
+ if (retval)
+ return;
+ }
+ ++num_buses;
+
+ sprintf (name, "%03d", bus->busnum);
+ bus->dentry = fs_create_file (name,
+ busmode | S_IFDIR,
+ NULL, bus, NULL,
+ busuid, busgid);
+ if (bus->dentry == NULL)
+ return;
- lock_kernel();
- for (slist = superlist.next; slist != &superlist; slist = slist->next)
- new_bus_inode(bus, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
- update_special_inodes();
- unlock_kernel();
+ usbfs_update_special();
usbdevfs_conn_disc_event();
}
-void usbdevfs_remove_bus(struct usb_bus *bus)
+
+void usbfs_remove_bus(struct usb_bus *bus)
{
- lock_kernel();
- while (!list_empty(&bus->inodes))
- free_inode(list_entry(bus->inodes.next, struct inode, u.usbdev_i.dlist));
- update_special_inodes();
- unlock_kernel();
+ if (bus->dentry) {
+ fs_remove_file (bus->dentry);
+ bus->dentry = NULL;
+ }
+
+ --num_buses;
+ if (num_buses <= 0) {
+ remove_special_files();
+ num_buses = 0;
+ }
+
+ usbfs_update_special();
usbdevfs_conn_disc_event();
}
-void usbdevfs_add_device(struct usb_device *dev)
+void usbfs_add_device(struct usb_device *dev)
{
- struct list_head *slist;
+ char name[8];
+
+ sprintf (name, "%03d", dev->devnum);
+ dev->dentry = fs_create_file (name,
+ devmode | S_IFREG,
+ dev->bus->dentry, dev,
+ &usbdevfs_device_file_operations,
+ devuid, devgid);
+ if (dev->dentry == NULL)
+ return;
- lock_kernel();
- for (slist = superlist.next; slist != &superlist; slist = slist->next)
- new_dev_inode(dev, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
- update_special_inodes();
- unlock_kernel();
+ usbfs_update_special();
usbdevfs_conn_disc_event();
}
-void usbdevfs_remove_device(struct usb_device *dev)
+void usbfs_remove_device(struct usb_device *dev)
{
struct dev_state *ds;
struct siginfo sinfo;
- lock_kernel();
- while (!list_empty(&dev->inodes))
- free_inode(list_entry(dev->inodes.next, struct inode, u.usbdev_i.dlist));
+ if (dev->dentry) {
+ fs_remove_file (dev->dentry);
+ dev->dentry = NULL;
+ }
while (!list_empty(&dev->filelist)) {
ds = list_entry(dev->filelist.next, struct dev_state, list);
list_del(&ds->list);
@@ -732,9 +716,7 @@ void usbdevfs_remove_device(struct usb_device *dev)
send_sig_info(ds->discsignr, &sinfo, ds->disctask);
}
}
-
- update_special_inodes();
- unlock_kernel();
+ usbfs_update_special();
usbdevfs_conn_disc_event();
}
@@ -744,39 +726,42 @@ void usbdevfs_remove_device(struct usb_device *dev)
static struct proc_dir_entry *usbdir = NULL;
#endif
-int __init usbdevfs_init(void)
+int __init usbfs_init(void)
{
- int ret;
+ int retval;
- for (ret = 0; ret < NRSPECIAL; ret++) {
- INIT_LIST_HEAD(&special[ret].inodes);
- }
- if ((ret = usb_register(&usbdevfs_driver)))
- return ret;
- if ((ret = register_filesystem(&usb_fs_type))) {
+ retval = usb_register(&usbdevfs_driver);
+ if (retval)
+ return retval;
+
+ retval = register_filesystem(&usb_fs_type);
+ if (retval) {
usb_deregister(&usbdevfs_driver);
- return ret;
+ return retval;
}
- if ((ret = register_filesystem(&usbdevice_fs_type))) {
+ retval = register_filesystem(&usbdevice_fs_type);
+ if (retval) {
unregister_filesystem(&usb_fs_type);
usb_deregister(&usbdevfs_driver);
- return ret;
+ return retval;
}
+
#ifdef CONFIG_PROC_FS
/* create mount point for usbdevfs */
usbdir = proc_mkdir("usb", proc_bus);
#endif
- return ret;
+
+ return 0;
}
-void __exit usbdevfs_cleanup(void)
+void __exit usbfs_cleanup(void)
{
usb_deregister(&usbdevfs_driver);
unregister_filesystem(&usb_fs_type);
unregister_filesystem(&usbdevice_fs_type);
#ifdef CONFIG_PROC_FS
- if (usbdir)
- remove_proc_entry("usb", proc_bus);
+ if (usbdir)
+ remove_proc_entry("usb", proc_bus);
#endif
}
diff --git a/drivers/usb/mdc800.c b/drivers/usb/mdc800.c
index d2a1ebe71..a6b2e0c54 100644
--- a/drivers/usb/mdc800.c
+++ b/drivers/usb/mdc800.c
@@ -140,7 +140,7 @@ struct mdc800_data
unsigned int endpoint [4];
- purb_t irq_urb;
+ struct urb * irq_urb;
wait_queue_head_t irq_wait;
int irq_woken;
char* irq_urb_buffer;
@@ -149,13 +149,13 @@ struct mdc800_data
int camera_request_ready; // Status to synchronize with irq
char camera_response [8]; // last Bytes send after busy
- purb_t write_urb;
+ struct urb * write_urb;
char* write_urb_buffer;
wait_queue_head_t write_wait;
int written;
- purb_t download_urb;
+ struct urb * download_urb;
char* download_urb_buffer;
wait_queue_head_t download_wait;
int downloaded;
diff --git a/drivers/usb/microtek.c b/drivers/usb/microtek.c
index 00d086603..fb16a6484 100644
--- a/drivers/usb/microtek.c
+++ b/drivers/usb/microtek.c
@@ -367,7 +367,7 @@ void mts_remove_nolock( struct mts_desc* to_remove )
}
MTS_DEBUG_GOT_HERE();
- scsi_unregister_module(MODULE_SCSI_HA, &(to_remove->ctempl));
+ scsi_unregister_host(&to_remove->ctempl);
unlock_kernel();
kfree( to_remove );
@@ -983,11 +983,11 @@ static void * mts_usb_probe (struct usb_device *dev, unsigned int interface,
MTS_DEBUG("registering SCSI module\n");
new_desc->ctempl.module = THIS_MODULE;
- result = scsi_register_module(MODULE_SCSI_HA, &(new_desc->ctempl));
+ result = scsi_register_host(&new_desc->ctempl);
/* Will get hit back in microtek_detect by this func */
if ( result )
{
- MTS_ERROR( "error %d from scsi_register_module! Help!\n",
+ MTS_ERROR( "error %d from scsi_register_host! Help!\n",
(int)result );
/* FIXME: need more cleanup? */
diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c
index f6cebd2e7..7a44e9310 100644
--- a/drivers/usb/ov511.c
+++ b/drivers/usb/ov511.c
@@ -1,13 +1,16 @@
/*
* OmniVision OV511 Camera-to-USB Bridge Driver
*
- * Copyright (c) 1999-2000 Mark W. McClelland
+ * Copyright (c) 1999-2001 Mark W. McClelland
+ * Original decompression code Copyright 1998-2000 OmniVision Technologies
* Many improvements by Bret Wallach <bwallac1@san.rr.com>
* Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
* Snapshot code by Kevin Moore
* OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
* Changes by Claudio Matsuoka <claudio@conectiva.com>
- *
+ * Original SAA7111A code by Dave Perks <dperks@ibm.net>
+ * Kernel I2C interface adapted from nt1003 driver
+ *
* Based on the Linux CPiA driver written by Peter Pregler,
* Scott J. Bertin and Johannes Erdfelt.
*
@@ -30,11 +33,9 @@
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define __NO_VERSION__
-
#include <linux/config.h>
-#include <linux/module.h>
#include <linux/version.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
@@ -42,32 +43,51 @@
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
-#include <linux/usb.h>
#include <asm/io.h>
#include <asm/semaphore.h>
+#include <asm/processor.h>
#include <linux/wrapper.h>
+#if defined (__i386__)
+ #include <asm/cpufeature.h>
+#endif
+
#include "ov511.h"
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.28"
-#define DRIVER_AUTHOR "Mark McClelland <mwm@i.am> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"
+#define DRIVER_VERSION "v1.48 for Linux 2.4"
+#define EMAIL "mmcclell@bigfoot.com"
+#define DRIVER_AUTHOR "Mark McClelland <mmcclell@bigfoot.com> & Bret Wallach \
+ & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \
+ <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"
#define DRIVER_DESC "OV511 USB Camera Driver"
#define OV511_I2C_RETRIES 3
+#define ENABLE_Y_QUANTABLE 1
+#define ENABLE_UV_QUANTABLE 1
+
+/* Pixel count * 3 bytes for RGB */
+#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3)
+#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval))
-/* Video Size 640 x 480 x 3 bytes for RGB */
-#define MAX_FRAME_SIZE (640 * 480 * 3)
-#define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval))
+/* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */
+#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024)
-#define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_GREY ? 256 : 384)
+#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)
/* PARAMETER VARIABLES: */
-static int autoadjust = 1; /* CCD dynamically changes exposure, etc... */
+/* (See ov511.txt for detailed descriptions of these.) */
-static int video_nr = -1;
+/* Sensor automatically changes brightness */
+static int autobright = 1;
+
+/* Sensor automatically changes gain */
+static int autogain = 1;
+
+/* Sensor automatically changes exposure */
+static int autoexp = 1;
/* 0=no debug messages
* 1=init/detection/unload and other significant messages,
@@ -77,27 +97,17 @@ static int video_nr = -1;
* 5=highly repetitive mesgs
* NOTE: This should be changed to 0, 1, or 2 for production kernels
*/
-static int debug = 0;
+static int debug; /* = 0 */
/* Fix vertical misalignment of red and blue at 640x480 */
-static int fix_rgb_offset = 0;
+static int fix_rgb_offset; /* = 0 */
/* Snapshot mode enabled flag */
-static int snapshot = 0;
-
-/* Sensor detection override (global for all attached cameras) */
-static int sensor = 0;
-
-/* Increase this if you are getting "Failed to read sensor ID..." */
-static int i2c_detect_tries = 5;
-
-/* For legal values, see the OV7610/7620 specs under register Common F,
- * upper nybble (set to 0-F) */
-static int aperture = -1;
+static int snapshot; /* = 0 */
/* Force image to be read in RGB instead of BGR. This option allow
* programs that expect RGB data (e.g. gqcam) to work with this driver. */
-static int force_rgb = 0;
+static int force_rgb; /* = 0 */
/* Number of seconds before inactive buffers are deallocated */
static int buf_timeout = 5;
@@ -105,76 +115,219 @@ static int buf_timeout = 5;
/* Number of cameras to stream from simultaneously */
static int cams = 1;
-/* Prevent apps from timing out if frame is not done in time */
-static int retry_sync = 0;
-
-/* Enable compression. This is for experimentation only; compressed images
- * still cannot be decoded yet. */
-static int compress = 0;
+/* Enable compression. Needs a fast (>300 MHz) CPU. */
+static int compress; /* = 0 */
/* Display test pattern - doesn't work yet either */
-static int testpat = 0;
+static int testpat; /* = 0 */
-/* Setting this to 1 will make the sensor output GBR422 instead on YUV420. Only
+/* Setting this to 1 will make the sensor output GBR422 instead of YUV420. Only
* affects RGB24 mode. */
-static int sensor_gbr = 0;
-
-/* Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details. */
-static int dumppix = 0;
-
-MODULE_PARM(autoadjust, "i");
-MODULE_PARM_DESC(autoadjust, "CCD dynamically changes exposure");
+static int sensor_gbr; /* = 0 */
+
+/* Dump raw pixel data. */
+static int dumppix; /* = 0 */
+
+/* LED policy. Only works on some OV511+ cameras. 0=off, 1=on (default), 2=auto
+ * (on when open) */
+static int led = 1;
+
+/* Set this to 1 to dump the bridge register contents after initialization */
+static int dump_bridge; /* = 0 */
+
+/* Set this to 1 to dump the sensor register contents after initialization */
+static int dump_sensor; /* = 0 */
+
+/* Temporary option for debugging "works, but no image" problem. Prints the
+ * first 12 bytes of data (potentially a packet header) in each isochronous
+ * data frame. */
+static int printph; /* = 0 */
+
+/* Compression parameters - I'm not exactly sure what these do yet */
+static int phy = 0x1f;
+static int phuv = 0x05;
+static int pvy = 0x06;
+static int pvuv = 0x06;
+static int qhy = 0x14;
+static int qhuv = 0x03;
+static int qvy = 0x04;
+static int qvuv = 0x04;
+
+/* Light frequency. Set to 50 or 60 (Hz), or zero for default settings */
+static int lightfreq; /* = 0 */
+
+/* Set this to 1 to enable banding filter by default. Compensates for
+ * alternating horizontal light/dark bands caused by (usually fluorescent)
+ * lights */
+static int bandingfilter; /* = 0 */
+
+/* Pixel clock divisor */
+static int clockdiv = -1;
+
+/* Isoc packet size */
+static int packetsize = -1;
+
+/* Frame drop register (16h) */
+static int framedrop = -1;
+
+/* Allows picture settings (brightness, hue, etc...) to take effect immediately,
+ * even in the middle of a frame. This reduces the time to change settings, but
+ * can ruin frames during the change. Only affects OmniVision sensors. */
+static int fastset; /* = 0 */
+
+/* Forces the palette to a specific value. If an application requests a
+ * different palette, it will be rejected. */
+static int force_palette; /* = 0 */
+
+/* Set tuner type, if not autodetected */
+static int tuner = -1;
+
+/* Allows proper exposure of objects that are illuminated from behind. Only
+ * affects OmniVision sensors. */
+static int backlight; /* = 0 */
+
+/* If you change this, you must also change the MODULE_PARM definition */
+#define OV511_MAX_UNIT_VIDEO 16
+
+/* Allows specified minor numbers to be forced. They will be assigned in the
+ * order that devices are detected. Note that you cannot specify 0 as a minor
+ * number. If you do not specify any, the next available one will be used. This
+ * requires kernel 2.4.5 or later. */
+static int unit_video[OV511_MAX_UNIT_VIDEO];
+
+/* Remove zero-padding from uncompressed incoming data. This will compensate for
+ * the blocks of corruption that appear when the camera cannot keep up with the
+ * speed of the USB bus (eg. at low frame resolutions) */
+static int remove_zeros; /* = 0 */
+
+MODULE_PARM(autobright, "i");
+MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
+MODULE_PARM(autogain, "i");
+MODULE_PARM_DESC(autogain, "Sensor automatically changes gain");
+MODULE_PARM(autoexp, "i");
+MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");
MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=init/detection, 2=warning, 3=config/control, 4=function call, 5=max");
+MODULE_PARM_DESC(debug,
+ "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");
MODULE_PARM(fix_rgb_offset, "i");
-MODULE_PARM_DESC(fix_rgb_offset, "Fix vertical misalignment of red and blue at 640x480");
+MODULE_PARM_DESC(fix_rgb_offset,
+ "Fix vertical misalignment of red and blue at 640x480");
MODULE_PARM(snapshot, "i");
MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
-MODULE_PARM(sensor, "i");
-MODULE_PARM_DESC(sensor, "Override sensor detection");
-MODULE_PARM(i2c_detect_tries, "i");
-MODULE_PARM_DESC(i2c_detect_tries, "Number of tries to detect sensor");
-MODULE_PARM(aperture, "i");
-MODULE_PARM_DESC(aperture, "Read the OV7610/7620 specs");
MODULE_PARM(force_rgb, "i");
MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");
MODULE_PARM(buf_timeout, "i");
MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation");
MODULE_PARM(cams, "i");
MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
-MODULE_PARM(retry_sync, "i");
-MODULE_PARM_DESC(retry_sync, "Prevent apps from timing out");
MODULE_PARM(compress, "i");
-MODULE_PARM_DESC(compress, "Turn on compression (not functional yet)");
+MODULE_PARM_DESC(compress, "Turn on compression (not reliable yet)");
MODULE_PARM(testpat, "i");
-MODULE_PARM_DESC(testpat, "Replace image with vertical bar testpattern (only partially working)");
-MODULE_PARM(sensor_gbr, "i");
-MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420");
-MODULE_PARM(dumppix, "i");
-MODULE_PARM_DESC(dumppix, "Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details");
-MODULE_PARM(video_nr,"i");
+MODULE_PARM_DESC(testpat,
+ "Replace image with vertical bar testpattern (only partially working)");
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+// Temporarily removed (needs to be rewritten for new format conversion code)
+// MODULE_PARM(sensor_gbr, "i");
+// MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420");
+
+MODULE_PARM(dumppix, "i");
+MODULE_PARM_DESC(dumppix, "Dump raw pixel data");
+MODULE_PARM(led, "i");
+MODULE_PARM_DESC(led,
+ "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");
+MODULE_PARM(dump_bridge, "i");
+MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");
+MODULE_PARM(dump_sensor, "i");
+MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers");
+MODULE_PARM(printph, "i");
+MODULE_PARM_DESC(printph, "Print frame start/end headers");
+MODULE_PARM(phy, "i");
+MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");
+MODULE_PARM(phuv, "i");
+MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");
+MODULE_PARM(pvy, "i");
+MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");
+MODULE_PARM(pvuv, "i");
+MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");
+MODULE_PARM(qhy, "i");
+MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");
+MODULE_PARM(qhuv, "i");
+MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");
+MODULE_PARM(qvy, "i");
+MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");
+MODULE_PARM(qvuv, "i");
+MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");
+MODULE_PARM(lightfreq, "i");
+MODULE_PARM_DESC(lightfreq,
+ "Light frequency. Set to 50 or 60 Hz, or zero for default settings");
+MODULE_PARM(bandingfilter, "i");
+MODULE_PARM_DESC(bandingfilter,
+ "Enable banding filter (to reduce effects of fluorescent lighting)");
+MODULE_PARM(clockdiv, "i");
+MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");
+MODULE_PARM(packetsize, "i");
+MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");
+MODULE_PARM(framedrop, "i");
+MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");
+MODULE_PARM(fastset, "i");
+MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");
+MODULE_PARM(force_palette, "i");
+MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");
+MODULE_PARM(tuner, "i");
+MODULE_PARM_DESC(tuner, "Set tuner type, if not autodetected");
+MODULE_PARM(backlight, "i");
+MODULE_PARM_DESC(backlight, "For objects that are lit from behind");
+MODULE_PARM(unit_video, "0-16i");
+MODULE_PARM_DESC(unit_video,
+ "Force use of specific minor number(s). 0 is not allowed.");
+MODULE_PARM(remove_zeros, "i");
+MODULE_PARM_DESC(remove_zeros,
+ "Remove zero-padding from uncompressed incoming data");
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
static struct usb_driver ov511_driver;
-/* I know, I know, global variables suck. This is only a temporary hack */
-int output_offset;
+static struct ov51x_decomp_ops *ov511_decomp_ops;
+static struct ov51x_decomp_ops *ov511_mmx_decomp_ops;
+static struct ov51x_decomp_ops *ov518_decomp_ops;
+static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;
+
+/* Number of times to retry a failed I2C transaction. Increase this if you
+ * are getting "Failed to read sensor ID..." */
+static int i2c_detect_tries = 5;
+
+/* MMX support is present in kernel and CPU. Checked upon decomp module load. */
+static int ov51x_mmx_available;
+
+/* Function prototypes */
+static void ov51x_clear_snapshot(struct usb_ov511 *);
+static int ov51x_check_snapshot(struct usb_ov511 *);
+static inline int sensor_get_picture(struct usb_ov511 *,
+ struct video_picture *);
+static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
+static int ov511_control_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
/**********************************************************************
* List of known OV511-based cameras
**********************************************************************/
static struct cam_list clist[] = {
- { 0, "generic model (no ID)" },
+ { 0, "Generic Camera (no ID)" },
+ { 1, "Mustek WCam 3X" },
{ 3, "D-Link DSB-C300" },
- { 4, "generic OV511/OV7610" },
+ { 4, "Generic OV511/OV7610" },
{ 5, "Puretek PT-6007" },
+ { 6, "Lifeview USB Life TV (NTSC)" },
{ 21, "Creative Labs WebCam 3" },
{ 36, "Koala-Cam" },
- { 38, "Lifeview USB Life TV" }, /* No support yet! */
+ { 38, "Lifeview USB Life TV" },
+ { 41, "Samsung Anycam MPC-M10" },
+ { 43, "Mtekvision Zeca MV402" },
+ { 46, "Suma eON" },
{ 100, "Lifeview RoboCam" },
{ 102, "AverMedia InterCam Elite" },
{ 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */
@@ -182,9 +335,11 @@ static struct cam_list clist[] = {
};
static __devinitdata struct usb_device_id device_table [] = {
- { USB_DEVICE(0x05a9, 0x0511) }, /* OV511 */
- { USB_DEVICE(0x05a9, 0xA511) }, /* OV511+ */
- { USB_DEVICE(0x0813, 0x0002) }, /* Intel Play Me2Cam OV511+ */
+ { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
+ { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
+ { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },
+ { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },
+ { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },
{ } /* Terminating entry */
};
@@ -212,6 +367,11 @@ static struct palette_list plist[] = {
};
#endif
+static unsigned char yQuanTable511[] = OV511_YQUANTABLE;
+static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE;
+static unsigned char yQuanTable518[] = OV518_YQUANTABLE;
+static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;
+
/**********************************************************************
*
* Memory management
@@ -231,7 +391,8 @@ static struct palette_list plist[] = {
/* Given PGD from the address space's page table, return the kernel
* virtual mapping of the physical memory mapped at ADR.
*/
-static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+static inline unsigned long
+uvirt_to_kva(pgd_t *pgd, unsigned long adr)
{
unsigned long ret = 0UL;
pmd_t *pmd;
@@ -243,7 +404,8 @@ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
ptep = pte_offset(pmd, adr);
pte = *ptep;
if (pte_present(pte)) {
- ret = (unsigned long) page_address(pte_page(pte));
+ ret = (unsigned long)
+ page_address(pte_page(pte));
ret |= (adr & (PAGE_SIZE - 1));
}
}
@@ -256,7 +418,8 @@ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
* This is used when initializing the contents of the
* area and marking the pages as reserved.
*/
-static inline unsigned long kvirt_to_pa(unsigned long adr)
+static inline unsigned long
+kvirt_to_pa(unsigned long adr)
{
unsigned long va, kva, ret;
@@ -266,7 +429,8 @@ static inline unsigned long kvirt_to_pa(unsigned long adr)
return ret;
}
-static void *rvmalloc(unsigned long size)
+static void *
+rvmalloc(unsigned long size)
{
void *mem;
unsigned long adr, page;
@@ -294,7 +458,8 @@ static void *rvmalloc(unsigned long size)
return mem;
}
-static void rvfree(void *mem, unsigned long size)
+static void
+rvfree(void *mem, unsigned long size)
{
unsigned long adr, page;
@@ -329,70 +494,90 @@ extern struct proc_dir_entry *video_proc_entry;
#define YES_NO(x) ((x) ? "yes" : "no")
-static int ov511_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+/* /proc/video/ov511/<minor#>/info */
+static int
+ov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,
+ void *data)
{
char *out = page;
int i, j, len;
struct usb_ov511 *ov511 = data;
+ struct video_picture p;
+ unsigned char exp;
+
+ if (!ov511 || !ov511->dev)
+ return -ENODEV;
+
+ sensor_get_picture(ov511, &p);
+ sensor_get_exposure(ov511, &exp);
/* IMPORTANT: This output MUST be kept under PAGE_SIZE
* or we need to get more sophisticated. */
- out += sprintf (out, "driver_version : %s\n", DRIVER_VERSION);
- out += sprintf (out, "custom_id : %d\n", ov511->customid);
- out += sprintf (out, "model : %s\n", ov511->desc ?
- clist[ov511->desc].description : "unknown");
- out += sprintf (out, "streaming : %s\n", YES_NO (ov511->streaming));
- out += sprintf (out, "grabbing : %s\n", YES_NO (ov511->grabbing));
- out += sprintf (out, "compress : %s\n", YES_NO (ov511->compress));
- out += sprintf (out, "subcapture : %s\n", YES_NO (ov511->sub_flag));
- out += sprintf (out, "sub_size : %d %d %d %d\n",
- ov511->subx, ov511->suby, ov511->subw, ov511->subh);
- out += sprintf (out, "data_format : %s\n", force_rgb ? "RGB" : "BGR");
- out += sprintf (out, "brightness : %d\n", ov511->brightness >> 8);
- out += sprintf (out, "colour : %d\n", ov511->colour >> 8);
- out += sprintf (out, "contrast : %d\n", ov511->contrast >> 8);
- out += sprintf (out, "num_frames : %d\n", OV511_NUMFRAMES);
+ out += sprintf(out, "driver_version : %s\n", DRIVER_VERSION);
+ out += sprintf(out, "custom_id : %d\n", ov511->customid);
+ out += sprintf(out, "model : %s\n", ov511->desc ?
+ clist[ov511->desc].description : "unknown");
+ out += sprintf(out, "streaming : %s\n", YES_NO(ov511->streaming));
+ out += sprintf(out, "grabbing : %s\n", YES_NO(ov511->grabbing));
+ out += sprintf(out, "compress : %s\n", YES_NO(ov511->compress));
+ out += sprintf(out, "subcapture : %s\n", YES_NO(ov511->sub_flag));
+ out += sprintf(out, "sub_size : %d %d %d %d\n",
+ ov511->subx, ov511->suby, ov511->subw, ov511->subh);
+ out += sprintf(out, "data_format : %s\n",
+ force_rgb ? "RGB" : "BGR");
+ out += sprintf(out, "brightness : %d\n", p.brightness >> 8);
+ out += sprintf(out, "colour : %d\n", p.colour >> 8);
+ out += sprintf(out, "contrast : %d\n", p.contrast >> 8);
+ out += sprintf(out, "hue : %d\n", p.hue >> 8);
+ out += sprintf(out, "exposure : %d\n", exp);
+ out += sprintf(out, "num_frames : %d\n", OV511_NUMFRAMES);
for (i = 0; i < OV511_NUMFRAMES; i++) {
- out += sprintf (out, "frame : %d\n", i);
- out += sprintf (out, " depth : %d\n",
- ov511->frame[i].depth);
- out += sprintf (out, " size : %d %d\n",
- ov511->frame[i].width, ov511->frame[i].height);
- out += sprintf (out, " format : ");
+ out += sprintf(out, "frame : %d\n", i);
+ out += sprintf(out, " depth : %d\n",
+ ov511->frame[i].depth);
+ out += sprintf(out, " size : %d %d\n",
+ ov511->frame[i].width, ov511->frame[i].height);
+ out += sprintf(out, " format : ");
for (j = 0; plist[j].num >= 0; j++) {
if (plist[j].num == ov511->frame[i].format) {
- out += sprintf (out, "%s\n", plist[j].name);
+ out += sprintf(out, "%s\n", plist[j].name);
break;
}
}
if (plist[j].num < 0)
- out += sprintf (out, "unknown\n");
- out += sprintf (out, " segsize : %d\n",
- ov511->frame[i].segsize);
- out += sprintf (out, " data_buffer : 0x%p\n",
- ov511->frame[i].data);
- }
- out += sprintf (out, "snap_enabled : %s\n", YES_NO (ov511->snap_enabled));
- out += sprintf (out, "bridge : %s\n",
- ov511->bridge == BRG_OV511 ? "OV511" :
- ov511->bridge == BRG_OV511PLUS ? "OV511+" :
- "unknown");
- out += sprintf (out, "sensor : %s\n",
- ov511->sensor == SEN_OV6620 ? "OV6620" :
- ov511->sensor == SEN_OV7610 ? "OV7610" :
- ov511->sensor == SEN_OV7620 ? "OV7620" :
- ov511->sensor == SEN_OV7620AE ? "OV7620AE" :
- "unknown");
- out += sprintf (out, "packet_size : %d\n", ov511->packet_size);
- out += sprintf (out, "framebuffer : 0x%p\n", ov511->fbuf);
-
+ out += sprintf(out, "unknown\n");
+ out += sprintf(out, " data_buffer : 0x%p\n",
+ ov511->frame[i].data);
+ }
+ out += sprintf(out, "snap_enabled : %s\n",
+ YES_NO(ov511->snap_enabled));
+ out += sprintf(out, "bridge : %s\n",
+ ov511->bridge == BRG_OV511 ? "OV511" :
+ ov511->bridge == BRG_OV511PLUS ? "OV511+" :
+ ov511->bridge == BRG_OV518 ? "OV518" :
+ ov511->bridge == BRG_OV518PLUS ? "OV518+" :
+ "unknown");
+ out += sprintf(out, "sensor : %s\n",
+ ov511->sensor == SEN_OV6620 ? "OV6620" :
+ ov511->sensor == SEN_OV6630 ? "OV6630" :
+ ov511->sensor == SEN_OV7610 ? "OV7610" :
+ ov511->sensor == SEN_OV7620 ? "OV7620" :
+ ov511->sensor == SEN_OV7620AE ? "OV7620AE" :
+ ov511->sensor == SEN_OV8600 ? "OV8600" :
+ ov511->sensor == SEN_KS0127 ? "KS0127" :
+ ov511->sensor == SEN_KS0127B ? "KS0127B" :
+ ov511->sensor == SEN_SAA7111A ? "SAA7111A" :
+ "unknown");
+ out += sprintf(out, "packet_size : %d\n", ov511->packet_size);
+ out += sprintf(out, "framebuffer : 0x%p\n", ov511->fbuf);
+
len = out - page;
len -= off;
if (len < count) {
*eof = 1;
- if (len <= 0) return 0;
+ if (len <= 0)
+ return 0;
} else
len = count;
@@ -401,69 +586,160 @@ static int ov511_read_proc(char *page, char **start, off_t off,
return len;
}
-static int ov511_write_proc(struct file *file, const char *buffer,
- unsigned long count, void *data)
+/* /proc/video/ov511/<minor#>/button
+ *
+ * When the camera's button is pressed, the output of this will change from a
+ * 0 to a 1 (ASCII). It will retain this value until it is read, after which
+ * it will reset to zero.
+ *
+ * SECURITY NOTE: Since reading this file can change the state of the snapshot
+ * status, it is important for applications that open it to keep it locked
+ * against access by other processes, using flock() or a similar mechanism. No
+ * locking is provided by this driver.
+ */
+static int
+ov511_read_proc_button(char *page, char **start, off_t off, int count, int *eof,
+ void *data)
{
- return -EINVAL;
+ char *out = page;
+ int len, status;
+ struct usb_ov511 *ov511 = data;
+
+ if (!ov511 || !ov511->dev)
+ return -ENODEV;
+
+ status = ov51x_check_snapshot(ov511);
+ out += sprintf(out, "%d", status);
+
+ if (status)
+ ov51x_clear_snapshot(ov511);
+
+ len = out - page;
+ len -= off;
+ if (len < count) {
+ *eof = 1;
+ if (len <= 0)
+ return 0;
+ } else {
+ len = count;
+ }
+
+ *start = page + off;
+
+ return len;
}
-static void create_proc_ov511_cam (struct usb_ov511 *ov511)
+static void
+create_proc_ov511_cam(struct usb_ov511 *ov511)
{
- char name[7];
- struct proc_dir_entry *ent;
-
+ char dirname[4];
+
if (!ov511_proc_entry || !ov511)
return;
- sprintf(name, "video%d", ov511->vdev.minor);
- PDEBUG (4, "creating /proc/video/ov511/%s", name);
-
- ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry);
+ /* Create per-device directory */
+ sprintf(dirname, "%d", ov511->vdev.minor);
+ PDEBUG(4, "creating /proc/video/ov511/%s/", dirname);
+ ov511->proc_devdir = create_proc_entry(dirname, S_IFDIR,
+ ov511_proc_entry);
+ if (!ov511->proc_devdir)
+ return;
- if (!ent)
+ /* Create "info" entry (human readable device information) */
+ PDEBUG(4, "creating /proc/video/ov511/%s/info", dirname);
+ ov511->proc_info = create_proc_read_entry("info",
+ S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir,
+ ov511_read_proc_info, ov511);
+ if (!ov511->proc_info)
return;
- ent->data = ov511;
- ent->read_proc = ov511_read_proc;
- ent->write_proc = ov511_write_proc;
- ov511->proc_entry = ent;
+ /* Don't create it if old snapshot mode on (would cause race cond.) */
+ if (!snapshot) {
+ /* Create "button" entry (snapshot button status) */
+ PDEBUG(4, "creating /proc/video/ov511/%s/button", dirname);
+ ov511->proc_button = create_proc_read_entry("button",
+ S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir,
+ ov511_read_proc_button, ov511);
+ if (!ov511->proc_button)
+ return;
+ }
+
+ /* Create "control" entry (ioctl() interface) */
+ PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname);
+ lock_kernel();
+ ov511->proc_control = create_proc_entry("control",
+ S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir);
+ if (!ov511->proc_control) {
+ unlock_kernel();
+ return;
+ }
+ ov511->proc_control->proc_fops->ioctl = ov511_control_ioctl;
+ ov511->proc_control->data = ov511;
+ unlock_kernel();
}
-static void destroy_proc_ov511_cam (struct usb_ov511 *ov511)
+static void
+destroy_proc_ov511_cam(struct usb_ov511 *ov511)
{
- char name[7];
+ char dirname[4];
- if (!ov511 || !ov511->proc_entry)
+ if (!ov511 || !ov511->proc_devdir)
return;
-
- sprintf(name, "video%d", ov511->vdev.minor);
- PDEBUG (4, "destroying %s", name);
- remove_proc_entry(name, ov511_proc_entry);
- ov511->proc_entry = NULL;
+
+ sprintf(dirname, "%d", ov511->vdev.minor);
+
+ /* Destroy "control" entry */
+ if (ov511->proc_control) {
+ PDEBUG(4, "destroying /proc/video/ov511/%s/control", dirname);
+ remove_proc_entry("control", ov511->proc_devdir);
+ ov511->proc_control = NULL;
+ }
+
+ /* Destroy "button" entry */
+ if (ov511->proc_button) {
+ PDEBUG(4, "destroying /proc/video/ov511/%s/button", dirname);
+ remove_proc_entry("button", ov511->proc_devdir);
+ ov511->proc_button = NULL;
+ }
+
+ /* Destroy "info" entry */
+ if (ov511->proc_info) {
+ PDEBUG(4, "destroying /proc/video/ov511/%s/info", dirname);
+ remove_proc_entry("info", ov511->proc_devdir);
+ ov511->proc_info = NULL;
+ }
+
+ /* Destroy per-device directory */
+ PDEBUG(4, "destroying /proc/video/ov511/%s/", dirname);
+ remove_proc_entry(dirname, ov511_proc_entry);
+ ov511->proc_devdir = NULL;
}
-static void proc_ov511_create(void)
+static void
+proc_ov511_create(void)
{
/* No current standard here. Alan prefers /proc/video/ as it keeps
* /proc "less cluttered than /proc/randomcardifoundintheshed/"
* -claudio
*/
if (video_proc_entry == NULL) {
- err("Unable to initialise /proc/video/ov511");
+ err("Error: /proc/video/ does not exist");
return;
}
- ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry);
+ ov511_proc_entry = create_proc_entry("ov511", S_IFDIR,
+ video_proc_entry);
if (ov511_proc_entry)
ov511_proc_entry->owner = THIS_MODULE;
else
- err("Unable to initialise /proc/ov511");
+ err("Unable to create /proc/video/ov511");
}
-static void proc_ov511_destroy(void)
+static void
+proc_ov511_destroy(void)
{
- PDEBUG (3, "removing /proc/video/ov511");
+ PDEBUG(3, "removing /proc/video/ov511");
if (ov511_proc_entry == NULL)
return;
@@ -474,23 +750,22 @@ static void proc_ov511_destroy(void)
/**********************************************************************
*
- * Camera interface
+ * Register I/O
*
**********************************************************************/
-static int ov511_reg_write(struct usb_device *dev,
- unsigned char reg,
- unsigned char value)
+static int
+ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value)
{
int rc;
- rc = usb_control_msg(dev,
- usb_sndctrlpipe(dev, 0),
- 2 /* REG_IO */,
- USB_TYPE_CLASS | USB_RECIP_DEVICE,
- 0, (__u16)reg, &value, 1, HZ);
+ PDEBUG(5, "0x%02X:0x%02X", reg, value);
- PDEBUG(5, "reg write: 0x%02X:0x%02X, 0x%x", reg, value, rc);
+ rc = usb_control_msg(dev,
+ usb_sndctrlpipe(dev, 0),
+ 2 /* REG_IO */,
+ USB_TYPE_CLASS | USB_RECIP_DEVICE,
+ 0, (__u16)reg, &value, 1, HZ);
if (rc < 0)
err("reg write: error %d", rc);
@@ -499,18 +774,19 @@ static int ov511_reg_write(struct usb_device *dev,
}
/* returns: negative is error, pos or zero is data */
-static int ov511_reg_read(struct usb_device *dev, unsigned char reg)
+static int
+ov511_reg_read(struct usb_device *dev, unsigned char reg)
{
int rc;
unsigned char buffer[1];
rc = usb_control_msg(dev,
- usb_rcvctrlpipe(dev, 0),
- 2 /* REG_IO */,
- USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
- 0, (__u16)reg, buffer, 1, HZ);
+ usb_rcvctrlpipe(dev, 0),
+ 2 /* REG_IO */,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
+ 0, (__u16)reg, buffer, 1, HZ);
- PDEBUG(5, "reg read: 0x%02X:0x%02X", reg, buffer[0]);
+ PDEBUG(5, "0x%02X:0x%02X", reg, buffer[0]);
if (rc < 0) {
err("reg read: error %d", rc);
@@ -520,18 +796,197 @@ static int ov511_reg_read(struct usb_device *dev, unsigned char reg)
}
}
-static int ov511_i2c_write(struct usb_device *dev,
- unsigned char reg,
- unsigned char value)
+/*
+ * Writes bits at positions specified by mask to a reg. Bits that are in
+ * the same position as 1's in "mask" are cleared and set to "value". Bits
+ * that are in the same position as 0's in "mask" are preserved, regardless
+ * of their respective state in "value".
+ */
+static int
+ov511_reg_write_mask(struct usb_device *dev,
+ unsigned char reg,
+ unsigned char value,
+ unsigned char mask)
+{
+ int ret;
+ unsigned char oldval, newval;
+
+ ret = ov511_reg_read(dev, reg);
+ if (ret < 0)
+ return ret;
+
+ oldval = (unsigned char) ret;
+ oldval &= (~mask); /* Clear the masked bits */
+ value &= mask; /* Enforce mask on value */
+ newval = oldval | value; /* Set the desired bits */
+
+ return (ov511_reg_write(dev, reg, newval));
+}
+
+/* Writes multiple (n) values to a single register. Only valid with certain
+ * registers (0x30 and 0xc4 - 0xce). Used for writing 16 and 24-bit values. */
+static int
+ov518_reg_write_multi(struct usb_device *dev,
+ unsigned char reg,
+ unsigned char *values,
+ int n)
+{
+ int rc;
+
+ PDEBUG(5, "0x%02X:[multiple], n=%d", reg, n); // FIXME
+
+ if (values == NULL) {
+ err("reg write multiple: NULL buffer");
+ return -EINVAL;
+ }
+
+ rc = usb_control_msg(dev,
+ usb_sndctrlpipe(dev, 0),
+ 2 /* REG_IO */,
+ USB_TYPE_CLASS | USB_RECIP_DEVICE,
+ 0, (__u16)reg, values, n, HZ);
+
+ if (rc < 0)
+ err("reg write multiple: error %d", rc);
+
+ return rc;
+}
+
+static int
+ov511_upload_quan_tables(struct usb_device *dev)
+{
+ unsigned char *pYTable = yQuanTable511;
+ unsigned char *pUVTable = uvQuanTable511;
+ unsigned char val0, val1;
+ int i, rc, reg = OV511_OMNICE_Y_LUT_BEGIN;
+
+ PDEBUG(4, "Uploading quantization tables");
+
+ for (i = 0; i < OV511_QUANTABLESIZE / 2; i++)
+ {
+ if (ENABLE_Y_QUANTABLE)
+ {
+ val0 = *pYTable++;
+ val1 = *pYTable++;
+ val0 &= 0x0f;
+ val1 &= 0x0f;
+ val0 |= val1 << 4;
+ rc = ov511_reg_write(dev, reg, val0);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (ENABLE_UV_QUANTABLE)
+ {
+ val0 = *pUVTable++;
+ val1 = *pUVTable++;
+ val0 &= 0x0f;
+ val1 &= 0x0f;
+ val0 |= val1 << 4;
+ rc = ov511_reg_write(dev, reg + OV511_QUANTABLESIZE / 2,
+ val0);
+ if (rc < 0)
+ return rc;
+ }
+
+ reg++;
+ }
+
+ return 0;
+}
+
+/* OV518 quantization tables are 8x4 (instead of 8x8) */
+static int
+ov518_upload_quan_tables(struct usb_device *dev)
+{
+ unsigned char *pYTable = yQuanTable518;
+ unsigned char *pUVTable = uvQuanTable518;
+ unsigned char val0, val1;
+ int i, rc, reg = OV511_OMNICE_Y_LUT_BEGIN;
+
+ PDEBUG(4, "Uploading quantization tables");
+
+ for (i = 0; i < OV518_QUANTABLESIZE / 2; i++)
+ {
+ if (ENABLE_Y_QUANTABLE)
+ {
+ val0 = *pYTable++;
+ val1 = *pYTable++;
+ val0 &= 0x0f;
+ val1 &= 0x0f;
+ val0 |= val1 << 4;
+ rc = ov511_reg_write(dev, reg, val0);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (ENABLE_UV_QUANTABLE)
+ {
+ val0 = *pUVTable++;
+ val1 = *pUVTable++;
+ val0 &= 0x0f;
+ val1 &= 0x0f;
+ val0 |= val1 << 4;
+ rc = ov511_reg_write(dev, reg + OV518_QUANTABLESIZE / 2,
+ val0);
+ if (rc < 0)
+ return rc;
+ }
+
+ reg++;
+ }
+
+ return 0;
+}
+
+/* NOTE: Do not call this function directly!
+ * The OV518 I2C I/O procedure is different, hence, this function.
+ * This is normally only called from ov51x_i2c_write(). Note that this function
+ * always succeeds regardless of whether the sensor is present and working.
+ */
+static int
+ov518_i2c_write_internal(struct usb_device *dev,
+ unsigned char reg,
+ unsigned char value)
+{
+ int rc;
+
+ PDEBUG(5, "0x%02X:0x%02X", reg, value);
+
+ /* Select camera register */
+ rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
+ if (rc < 0) goto error;
+
+ /* Write "value" to I2C data port of OV511 */
+ rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);
+ if (rc < 0) goto error;
+
+ /* Initiate 3-byte write cycle */
+ rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x01);
+ if (rc < 0) goto error;
+
+ return 0;
+
+error:
+ err("ov518 i2c write: error %d", rc);
+ return rc;
+}
+
+/* NOTE: Do not call this function directly! */
+static int
+ov511_i2c_write_internal(struct usb_device *dev,
+ unsigned char reg,
+ unsigned char value)
{
int rc, retries;
- PDEBUG(5, "i2c write: 0x%02X:0x%02X", reg, value);
+ PDEBUG(5, "0x%02X:0x%02X", reg, value);
/* Three byte write cycle */
for (retries = OV511_I2C_RETRIES; ; ) {
/* Select camera register */
- rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
+ rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE,
+ reg);
if (rc < 0) goto error;
/* Write "value" to I2C data port of OV511 */
@@ -566,15 +1021,51 @@ error:
return rc;
}
-/* returns: negative is error, pos or zero is data */
-static int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
+/* NOTE: Do not call this function directly!
+ * The OV518 I2C I/O procedure is different, hence, this function.
+ * This is normally only called from ov51x_i2c_read(). Note that this function
+ * always succeeds regardless of whether the sensor is present and working.
+ */
+static int
+ov518_i2c_read_internal(struct usb_device *dev, unsigned char reg)
+{
+ int rc, value;
+
+ /* Select camera register */
+ rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
+ if (rc < 0) goto error;
+
+ /* Initiate 2-byte write cycle */
+ rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x03);
+ if (rc < 0) goto error;
+
+ /* Initiate 2-byte read cycle */
+ rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x05);
+ if (rc < 0) goto error;
+
+ value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
+
+ PDEBUG(5, "0x%02X:0x%02X", reg, value);
+
+ return value;
+
+error:
+ err("ov518 i2c read: error %d", rc);
+ return rc;
+}
+
+/* NOTE: Do not call this function directly!
+ * returns: negative is error, pos or zero is data */
+static int
+ov511_i2c_read_internal(struct usb_device *dev, unsigned char reg)
{
int rc, value, retries;
/* Two byte write cycle */
for (retries = OV511_I2C_RETRIES; ; ) {
/* Select camera register */
- rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
+ rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE,
+ reg);
if (rc < 0) goto error;
/* Initiate 2-byte write cycle */
@@ -624,9 +1115,9 @@ static int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
- PDEBUG(5, "i2c read: 0x%02X:0x%02X", reg, value);
+ PDEBUG(5, "0x%02X:0x%02X", reg, value);
- /* This is needed to make ov511_i2c_write() work */
+ /* This is needed to make ov51x_i2c_write() work */
rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
if (rc < 0)
goto error;
@@ -638,19 +1129,207 @@ error:
return rc;
}
-static int ov511_write_regvals(struct usb_device *dev,
- struct ov511_regvals * pRegvals)
+/* returns: negative is error, pos or zero is data */
+static int
+ov51x_i2c_read(struct usb_ov511 *ov511, unsigned char reg)
+{
+ int rc;
+ struct usb_device *dev = ov511->dev;
+
+ down(&ov511->i2c_lock);
+
+ if (dev->descriptor.idProduct == PROD_OV518 ||
+ dev->descriptor.idProduct == PROD_OV518PLUS)
+ rc = ov518_i2c_read_internal(dev, reg);
+ else
+ rc = ov511_i2c_read_internal(dev, reg);
+
+ up(&ov511->i2c_lock);
+
+ return rc;
+}
+
+static int
+ov51x_i2c_write(struct usb_ov511 *ov511,
+ unsigned char reg,
+ unsigned char value)
+{
+ int rc;
+ struct usb_device *dev = ov511->dev;
+
+ down(&ov511->i2c_lock);
+
+ if (dev->descriptor.idProduct == PROD_OV518 ||
+ dev->descriptor.idProduct == PROD_OV518PLUS)
+ rc = ov518_i2c_write_internal(dev, reg, value);
+ else
+ rc = ov511_i2c_write_internal(dev, reg, value);
+
+ up(&ov511->i2c_lock);
+
+ return rc;
+}
+
+/* Do not call this function directly! */
+static int
+ov51x_i2c_write_mask_internal(struct usb_device *dev,
+ unsigned char reg,
+ unsigned char value,
+ unsigned char mask)
+{
+ int rc;
+ unsigned char oldval, newval;
+
+ if (mask == 0xff) {
+ newval = value;
+ } else {
+ if (dev->descriptor.idProduct == PROD_OV518 ||
+ dev->descriptor.idProduct == PROD_OV518PLUS)
+ rc = ov518_i2c_read_internal(dev, reg);
+ else
+ rc = ov511_i2c_read_internal(dev, reg);
+ if (rc < 0)
+ return rc;
+
+ oldval = (unsigned char) rc;
+ oldval &= (~mask); /* Clear the masked bits */
+ value &= mask; /* Enforce mask on value */
+ newval = oldval | value; /* Set the desired bits */
+ }
+
+ if (dev->descriptor.idProduct == PROD_OV518 ||
+ dev->descriptor.idProduct == PROD_OV518PLUS)
+ return (ov518_i2c_write_internal(dev, reg, newval));
+ else
+ return (ov511_i2c_write_internal(dev, reg, newval));
+}
+
+/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
+ * the same position as 1's in "mask" are cleared and set to "value". Bits
+ * that are in the same position as 0's in "mask" are preserved, regardless
+ * of their respective state in "value".
+ */
+static int
+ov51x_i2c_write_mask(struct usb_ov511 *ov511,
+ unsigned char reg,
+ unsigned char value,
+ unsigned char mask)
+{
+ int rc;
+ struct usb_device *dev = ov511->dev;
+
+ down(&ov511->i2c_lock);
+ rc = ov51x_i2c_write_mask_internal(dev, reg, value, mask);
+ up(&ov511->i2c_lock);
+
+ return rc;
+}
+
+/* Write to a specific I2C slave ID and register, using the specified mask */
+static int
+ov51x_i2c_write_slave(struct usb_ov511 *ov511,
+ unsigned char slave,
+ unsigned char reg,
+ unsigned char value,
+ unsigned char mask)
+{
+ int rc = 0;
+ struct usb_device *dev = ov511->dev;
+
+ down(&ov511->i2c_lock);
+
+ /* Set new slave IDs */
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+ rc = ov51x_i2c_write_mask_internal(dev, reg, value, mask);
+ /* Don't bail out yet if error; IDs must be restored */
+
+ /* Restore primary IDs */
+ slave = ov511->primary_i2c_slave;
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+out:
+ up(&ov511->i2c_lock);
+ return rc;
+}
+
+/* Read from a specific I2C slave ID and register */
+static int
+ov51x_i2c_read_slave(struct usb_ov511 *ov511,
+ unsigned char slave,
+ unsigned char reg)
{
int rc;
+ struct usb_device *dev = ov511->dev;
+
+ down(&ov511->i2c_lock);
+
+ /* Set new slave IDs */
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+ if (dev->descriptor.idProduct == PROD_OV518 ||
+ dev->descriptor.idProduct == PROD_OV518PLUS)
+ rc = ov518_i2c_read_internal(dev, reg);
+ else
+ rc = ov511_i2c_read_internal(dev, reg);
+ /* Don't bail out yet if error; IDs must be restored */
+
+ /* Restore primary IDs */
+ slave = ov511->primary_i2c_slave;
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {
+ rc = -EIO;
+ goto out;
+ }
+
+out:
+ up(&ov511->i2c_lock);
+ return rc;
+}
+
+static int
+ov511_write_regvals(struct usb_ov511 *ov511,
+ struct ov511_regvals * pRegvals)
+{
+ int rc;
+ struct usb_device *dev = ov511->dev;
while (pRegvals->bus != OV511_DONE_BUS) {
if (pRegvals->bus == OV511_REG_BUS) {
if ((rc = ov511_reg_write(dev, pRegvals->reg,
- pRegvals->val)) < 0)
+ pRegvals->val)) < 0)
goto error;
} else if (pRegvals->bus == OV511_I2C_BUS) {
- if ((rc = ov511_i2c_write(dev, pRegvals->reg,
- pRegvals->val)) < 0)
+ if ((rc = ov51x_i2c_write(ov511, pRegvals->reg,
+ pRegvals->val)) < 0)
goto error;
} else {
err("Bad regval array");
@@ -667,65 +1346,92 @@ error:
}
#ifdef OV511_DEBUG
-static void ov511_dump_i2c_range(struct usb_device *dev, int reg1, int regn)
+static void
+ov511_dump_i2c_range(struct usb_ov511 *ov511, int reg1, int regn)
{
int i;
int rc;
- for(i = reg1; i <= regn; i++) {
- rc = ov511_i2c_read(dev, i);
- PDEBUG(1, "OV7610[0x%X] = 0x%X", i, rc);
+ for (i = reg1; i <= regn; i++) {
+ rc = ov51x_i2c_read(ov511, i);
+ info("OV7610[0x%X] = 0x%X", i, rc);
}
}
-static void ov511_dump_i2c_regs(struct usb_device *dev)
+static void
+ov51x_dump_i2c_regs(struct usb_ov511 *ov511)
{
- PDEBUG(3, "I2C REGS");
- ov511_dump_i2c_range(dev, 0x00, 0x7C);
+ info("I2C REGS");
+ ov511_dump_i2c_range(ov511, 0x00, 0x7C);
}
-#if 0
-static void ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn)
+static void
+ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn)
{
int i;
int rc;
- for(i = reg1; i <= regn; i++) {
+ for (i = reg1; i <= regn; i++) {
rc = ov511_reg_read(dev, i);
- PDEBUG(1, "OV511[0x%X] = 0x%X", i, rc);
+ info("OV511[0x%X] = 0x%X", i, rc);
}
}
-static void ov511_dump_regs(struct usb_device *dev)
+static void
+ov511_dump_regs(struct usb_device *dev)
{
- PDEBUG(1, "CAMERA INTERFACE REGS");
+ info("CAMERA INTERFACE REGS");
ov511_dump_reg_range(dev, 0x10, 0x1f);
- PDEBUG(1, "DRAM INTERFACE REGS");
+ info("DRAM INTERFACE REGS");
ov511_dump_reg_range(dev, 0x20, 0x23);
- PDEBUG(1, "ISO FIFO REGS");
+ info("ISO FIFO REGS");
ov511_dump_reg_range(dev, 0x30, 0x31);
- PDEBUG(1, "PIO REGS");
+ info("PIO REGS");
ov511_dump_reg_range(dev, 0x38, 0x39);
ov511_dump_reg_range(dev, 0x3e, 0x3e);
- PDEBUG(1, "I2C REGS");
+ info("I2C REGS");
ov511_dump_reg_range(dev, 0x40, 0x49);
- PDEBUG(1, "SYSTEM CONTROL REGS");
+ info("SYSTEM CONTROL REGS");
ov511_dump_reg_range(dev, 0x50, 0x55);
ov511_dump_reg_range(dev, 0x5e, 0x5f);
- PDEBUG(1, "OmniCE REGS");
+ info("OmniCE REGS");
ov511_dump_reg_range(dev, 0x70, 0x79);
+ /* NOTE: Quantization tables are not readable. You will get the value
+ * in reg. 0x79 for every table register */
ov511_dump_reg_range(dev, 0x80, 0x9f);
ov511_dump_reg_range(dev, 0xa0, 0xbf);
}
#endif
-#endif
-static int ov511_reset(struct usb_device *dev, unsigned char reset_type)
+/**********************************************************************
+ *
+ * Kernel I2C Interface
+ *
+ **********************************************************************/
+
+/* For as-yet unimplemented I2C interface */
+static void
+call_i2c_clients(struct usb_ov511 *ov511, unsigned int cmd,
+ void *arg)
+{
+ /* Do nothing */
+}
+
+/*****************************************************************************/
+
+static int
+ov511_reset(struct usb_ov511 *ov511, unsigned char reset_type)
{
int rc;
-
+
+ /* Setting bit 0 not allowed on 518/518Plus */
+ if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS)
+ reset_type &= 0xfe;
+
PDEBUG(4, "Reset: type=0x%X", reset_type);
- rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
- rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
+
+ rc = ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, reset_type);
+ rc = ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0);
if (rc < 0)
err("reset: command failed");
@@ -735,24 +1441,145 @@ static int ov511_reset(struct usb_device *dev, unsigned char reset_type)
/* Temporarily stops OV511 from functioning. Must do this before changing
* registers while the camera is streaming */
-static inline int ov511_stop(struct usb_device *dev)
+static inline int
+ov511_stop(struct usb_ov511 *ov511)
{
PDEBUG(4, "stopping");
- return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d));
+ ov511->stopped = 1;
+ if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS)
+ return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,
+ 0x3a));
+ else
+ return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,
+ 0x3d));
}
-/* Restarts OV511 after ov511_stop() is called */
-static inline int ov511_restart(struct usb_device *dev)
+/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
+ * actually stopped (for performance). */
+static inline int
+ov511_restart(struct usb_ov511 *ov511)
{
- PDEBUG(4, "restarting");
- return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00));
+ if (ov511->stopped) {
+ PDEBUG(4, "restarting");
+ ov511->stopped = 0;
+
+ /* Reinitialize the stream */
+ if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS)
+ ov511_reg_write(ov511->dev, 0x2f, 0x80);
+
+ return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,
+ 0x00));
+ }
+
+ return 0;
+}
+
+/* Resets the hardware snapshot button */
+static void
+ov51x_clear_snapshot(struct usb_ov511 *ov511)
+{
+ if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS) {
+ ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
+ ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
+ ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
+ } else if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS) {
+ warn("snapshot reset not supported yet on OV518(+)");
+ } else {
+ err("clear snap: invalid bridge type");
+ }
+
+}
+
+/* Checks the status of the snapshot button. Returns 1 if it was pressed since
+ * it was last cleared, and zero in all other cases (including errors) */
+static int
+ov51x_check_snapshot(struct usb_ov511 *ov511)
+{
+ int ret, status = 0;
+
+ if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS) {
+ ret = ov511_reg_read(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT);
+ if (ret < 0) {
+ err("Error checking snspshot status (%d)", ret);
+ } else if (ret & 0x08) {
+ status = 1;
+ }
+ } else if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS) {
+ warn("snapshot check not supported yet on OV518(+)");
+ } else {
+ err("check snap: invalid bridge type");
+ }
+
+ return status;
}
-static int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
+/* Sets I2C read and write slave IDs. Returns <0 for error */
+static int
+ov51x_set_slave_ids(struct usb_ov511 *ov511,
+ unsigned char write_id,
+ unsigned char read_id)
+{
+ struct usb_device *dev = ov511->dev;
+
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, write_id) < 0)
+ return -EIO;
+
+ if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, read_id) < 0)
+ return -EIO;
+
+ if (ov511_reset(ov511, OV511_RESET_NOREGS) < 0)
+ return -EIO;
+
+ return 0;
+}
+
+/* This does an initial reset of an OmniVision sensor and ensures that I2C
+ * is synchronized. Returns <0 for failure.
+ */
+static int
+ov51x_init_ov_sensor(struct usb_ov511 *ov511)
+{
+ int i, success;
+
+ /* Reset the sensor */
+ if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) return -EIO;
+
+ /* Wait for it to initialize */
+ schedule_timeout (1 + 150 * HZ / 1000);
+
+ for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
+ if ((ov51x_i2c_read(ov511, OV7610_REG_ID_HIGH) == 0x7F) &&
+ (ov51x_i2c_read(ov511, OV7610_REG_ID_LOW) == 0xA2)) {
+ success = 1;
+ continue;
+ }
+
+ /* Reset the sensor */
+ if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) return -EIO;
+ /* Wait for it to initialize */
+ schedule_timeout(1 + 150 * HZ / 1000);
+ /* Dummy read to sync I2C */
+ if (ov51x_i2c_read(ov511, 0x00) < 0) return -EIO;
+ }
+
+ if (!success)
+ return -EIO;
+
+ PDEBUG(1, "I2C synced in %d attempt(s)", i);
+
+ return 0;
+}
+
+static int
+ov511_set_packet_size(struct usb_ov511 *ov511, int size)
{
int alt, mult;
- if (ov511_stop(ov511->dev) < 0)
+ if (ov511_stop(ov511) < 0)
return -EIO;
mult = size >> 5;
@@ -780,6 +1607,20 @@ static int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
err("Set packet size: invalid size (%d)", size);
return -EINVAL;
}
+ } else if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS) {
+ if (size == 0) alt = OV518_ALT_SIZE_0;
+ else if (size == 128) alt = OV518_ALT_SIZE_128;
+ else if (size == 256) alt = OV518_ALT_SIZE_256;
+ else if (size == 384) alt = OV518_ALT_SIZE_384;
+ else if (size == 512) alt = OV518_ALT_SIZE_512;
+ else if (size == 640) alt = OV518_ALT_SIZE_640;
+ else if (size == 768) alt = OV518_ALT_SIZE_768;
+ else if (size == 896) alt = OV518_ALT_SIZE_896;
+ else {
+ err("Set packet size: invalid size (%d)", size);
+ return -EINVAL;
+ }
} else {
err("Set packet size: Invalid bridge type");
return -EINVAL;
@@ -787,118 +1628,522 @@ static int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);
- if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE, mult) < 0)
- return -ENOMEM;
+ // FIXME: Don't know how to do this on OV518 yet
+ if (ov511->bridge != BRG_OV518 &&
+ ov511->bridge != BRG_OV518PLUS) {
+ if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
+ mult) < 0) {
+ return -EIO;
+ }
+ }
if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {
err("Set packet size: set interface error");
return -EBUSY;
}
+ /* Initialize the stream */
+ if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS)
+ if (ov511_reg_write(ov511->dev, 0x2f, 0x80) < 0)
+ return -EIO;
+
// FIXME - Should we only reset the FIFO?
- if (ov511_reset(ov511->dev, OV511_RESET_NOREGS) < 0)
- return -ENOMEM;
+ if (ov511_reset(ov511, OV511_RESET_NOREGS) < 0)
+ return -EIO;
ov511->packet_size = size;
- if (ov511_restart(ov511->dev) < 0)
+ if (ov511_restart(ov511) < 0)
return -EIO;
return 0;
}
+/* Upload compression params and quantization tables. Returns 0 for success. */
+static int
+ov511_init_compression(struct usb_ov511 *ov511)
+{
+ struct usb_device *dev = ov511->dev;
+ int rc = 0;
+
+ if (!ov511->compress_inited) {
+
+ ov511_reg_write(dev, 0x70, phy);
+ ov511_reg_write(dev, 0x71, phuv);
+ ov511_reg_write(dev, 0x72, pvy);
+ ov511_reg_write(dev, 0x73, pvuv);
+ ov511_reg_write(dev, 0x74, qhy);
+ ov511_reg_write(dev, 0x75, qhuv);
+ ov511_reg_write(dev, 0x76, qvy);
+ ov511_reg_write(dev, 0x77, qvuv);
+
+ if (ov511_upload_quan_tables(dev) < 0) {
+ err("Error uploading quantization tables");
+ rc = -EIO;
+ goto out;
+ }
+ }
+
+ ov511->compress_inited = 1;
+out:
+ return rc;
+}
-static inline int
-ov7610_set_picture(struct usb_ov511 *ov511, struct video_picture *p)
+/* Upload compression params and quantization tables. Returns 0 for success. */
+static int
+ov518_init_compression(struct usb_ov511 *ov511)
{
- int ret;
struct usb_device *dev = ov511->dev;
+ int rc = 0;
- PDEBUG(4, "ov511_set_picture");
+ if (!ov511->compress_inited) {
- if (ov511_stop(dev) < 0)
- return -EIO;
+ if (ov518_upload_quan_tables(dev) < 0) {
+ err("Error uploading quantization tables");
+ rc = -EIO;
+ goto out;
+ }
+ }
- ov511->contrast = p->contrast;
- ov511->brightness = p->brightness;
- ov511->colour = p->colour;
- ov511->hue = p->hue;
- ov511->whiteness = p->whiteness;
+ ov511->compress_inited = 1;
+out:
+ return rc;
+}
- if ((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)
- return -EIO;
-#if 0
- /* disable auto adjust mode */
- if (ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
- return -EIO;
-#endif
- if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV7620AE
- || ov511->sensor == SEN_OV6620)
- if (ov511_i2c_write(dev, OV7610_REG_SAT, p->colour >> 8) < 0)
- return -EIO;
+/* -------------------------------------------------------------------------- */
- if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV6620) {
- if (ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
- return -EIO;
+/* Sets sensor's contrast setting to "val" */
+static int
+sensor_set_contrast(struct usb_ov511 *ov511, unsigned short val)
+{
+ int rc;
- if (ov511_i2c_write(dev, OV7610_REG_RED, 0xFF - (p->hue >> 8)) < 0)
- return -EIO;
+ PDEBUG(3, "%d", val);
- if (ov511_i2c_write(dev, OV7610_REG_BLUE, p->hue >> 8) < 0)
+ if (ov511->stop_during_set)
+ if (ov511_stop(ov511) < 0)
return -EIO;
- if (ov511_i2c_write(dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ {
+ rc = ov51x_i2c_write(ov511, OV7610_REG_CNT, val >> 8);
+ if (rc < 0)
+ goto out;
+ break;
+ }
+ case SEN_OV7620:
+ {
+ unsigned char ctab[] = {
+ 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
+ 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
+ };
+
+ /* Use Y gamma control instead. Bit 0 enables it. */
+ rc = ov51x_i2c_write(ov511, 0x64, ctab[val>>12]);
+ if (rc < 0)
+ goto out;
+ break;
+ }
+ case SEN_SAA7111A:
+ {
+ rc = ov51x_i2c_write(ov511, 0x0b, val >> 9);
+ if (rc < 0)
+ goto out;
+ break;
+ }
+ default:
+ {
+ PDEBUG(3, "Unsupported with this sensor");
+ rc = -EPERM;
+ goto out;
+ }
+ }
+
+ rc = 0; /* Success */
+ ov511->contrast = val;
+out:
+ if (ov511_restart(ov511) < 0)
+ return -EIO;
+
+ return rc;
+}
+
+/* Gets sensor's contrast setting */
+static int
+sensor_get_contrast(struct usb_ov511 *ov511, unsigned short *val)
+{
+ int rc;
+
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ rc = ov51x_i2c_read(ov511, OV7610_REG_CNT);
+ if (rc < 0)
+ return rc;
+ else
+ *val = rc << 8;
+ break;
+ case SEN_OV7620:
+ /* Use Y gamma reg instead. Bit 0 is the enable bit. */
+ rc = ov51x_i2c_read(ov511, 0x64);
+ if (rc < 0)
+ return rc;
+ else
+ *val = (rc & 0xfe) << 8;
+ break;
+ case SEN_SAA7111A:
+ *val = ov511->contrast;
+ break;
+ default:
+ PDEBUG(3, "Unsupported with this sensor");
+ return -EPERM;
+ }
+
+ PDEBUG(3, "%d", *val);
+ ov511->contrast = *val;
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Sets sensor's brightness setting to "val" */
+static int
+sensor_set_brightness(struct usb_ov511 *ov511, unsigned short val)
+{
+ int rc;
+
+ PDEBUG(4, "%d", val);
+
+ if (ov511->stop_during_set)
+ if (ov511_stop(ov511) < 0)
return -EIO;
- } else if ((ov511->sensor == SEN_OV7620)
- || (ov511->sensor == SEN_OV7620AE)) {
-#if 0
- int cur_sat, new_sat, tmp;
- cur_sat = ov511_i2c_read(dev, OV7610_REG_BLUE);
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV7620AE:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ rc = ov51x_i2c_write(ov511, OV7610_REG_BRT, val >> 8);
+ if (rc < 0)
+ goto out;
+ break;
+ case SEN_OV7620:
+ /* 7620 doesn't like manual changes when in auto mode */
+ if (!ov511->auto_brt) {
+ rc = ov51x_i2c_write(ov511, OV7610_REG_BRT, val >> 8);
+ if (rc < 0)
+ goto out;
+ }
+ break;
+ case SEN_SAA7111A:
+ rc = ov51x_i2c_write(ov511, 0x0a, val >> 8);
+ if (rc < 0)
+ goto out;
+ break;
+ default:
+ PDEBUG(3, "Unsupported with this sensor");
+ rc = -EPERM;
+ goto out;
+ }
- tmp = (p->hue >> 8) - cur_sat;
- new_sat = (tmp < 0) ? (-tmp) | 0x80 : tmp;
+ rc = 0; /* Success */
+ ov511->brightness = val;
+out:
+ if (ov511_restart(ov511) < 0)
+ return -EIO;
+
+ return rc;
+}
- PDEBUG(1, "cur=%d target=%d diff=%d", cur_sat, p->hue >> 8, tmp);
+/* Gets sensor's brightness setting */
+static int
+sensor_get_brightness(struct usb_ov511 *ov511, unsigned short *val)
+{
+ int rc;
- if (ov511_i2c_write(dev, OV7610_REG_BLUE, new_sat) < 0)
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV7620AE:
+ case SEN_OV7620:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ rc = ov51x_i2c_read(ov511, OV7610_REG_BRT);
+ if (rc < 0)
+ return rc;
+ else
+ *val = rc << 8;
+ break;
+ case SEN_SAA7111A:
+ *val = ov511->brightness;
+ break;
+ default:
+ PDEBUG(3, "Unsupported with this sensor");
+ return -EPERM;
+ }
+
+ PDEBUG(3, "%d", *val);
+ ov511->brightness = *val;
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Sets sensor's saturation (color intensity) setting to "val" */
+static int
+sensor_set_saturation(struct usb_ov511 *ov511, unsigned short val)
+{
+ int rc;
+
+ PDEBUG(3, "%d", val);
+
+ if (ov511->stop_during_set)
+ if (ov511_stop(ov511) < 0)
return -EIO;
- // DEBUG_CODE
- PDEBUG(1, "hue=%d", ov511_i2c_read(dev, OV7610_REG_BLUE));
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV7620AE:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ rc = ov51x_i2c_write(ov511, OV7610_REG_SAT, val >> 8);
+ if (rc < 0)
+ goto out;
+ break;
+ case SEN_OV7620:
+// /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
+// rc = ov511_i2c_write(ov511->dev, 0x62, (val >> 9) & 0x7e);
+// if (rc < 0)
+// goto out;
+ rc = ov51x_i2c_write(ov511, OV7610_REG_SAT, val >> 8);
+ if (rc < 0)
+ goto out;
+ break;
+ case SEN_SAA7111A:
+ rc = ov51x_i2c_write(ov511, 0x0c, val >> 9);
+ if (rc < 0)
+ goto out;
+ break;
+ default:
+ PDEBUG(3, "Unsupported with this sensor");
+ rc = -EPERM;
+ goto out;
+ }
+
+ rc = 0; /* Success */
+ ov511->colour = val;
+out:
+ if (ov511_restart(ov511) < 0)
+ return -EIO;
+
+ return rc;
+}
+
+/* Gets sensor's saturation (color intensity) setting */
+static int
+sensor_get_saturation(struct usb_ov511 *ov511, unsigned short *val)
+{
+ int rc;
+
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV7620AE:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ rc = ov51x_i2c_read(ov511, OV7610_REG_SAT);
+ if (rc < 0)
+ return rc;
+ else
+ *val = rc << 8;
+ break;
+ case SEN_OV7620:
+// /* Use UV gamma reg instead. Bits 0 & 7 are reserved. */
+// rc = ov51x_i2c_read(ov511, 0x62);
+// if (rc < 0)
+// return rc;
+// else
+// *val = (rc & 0x7e) << 9;
+ rc = ov51x_i2c_read(ov511, OV7610_REG_SAT);
+ if (rc < 0)
+ return rc;
+ else
+ *val = rc << 8;
+ break;
+ case SEN_SAA7111A:
+ *val = ov511->colour;
+ break;
+ default:
+ PDEBUG(3, "Unsupported with this sensor");
+ return -EPERM;
+ }
+
+ PDEBUG(3, "%d", *val);
+ ov511->colour = *val;
+ return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Sets sensor's hue (red/blue balance) setting to "val" */
+static int
+sensor_set_hue(struct usb_ov511 *ov511, unsigned short val)
+{
+ int rc;
+
+ PDEBUG(3, "%d", val);
+
+ if (ov511->stop_during_set)
+ if (ov511_stop(ov511) < 0)
+ return -EIO;
+
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ rc = ov51x_i2c_write(ov511, OV7610_REG_RED, 0xFF - (val >> 8));
+ if (rc < 0)
+ goto out;
+
+ rc = ov51x_i2c_write(ov511, OV7610_REG_BLUE, val >> 8);
+ if (rc < 0)
+ goto out;
+ break;
+ case SEN_OV7620:
+// Hue control is causing problems. I will enable it once it's fixed.
+#if 0
+ rc = ov51x_i2c_write(ov511, 0x7a,
+ (unsigned char)(val >> 8) + 0xb);
+ if (rc < 0)
+ goto out;
+
+ rc = ov51x_i2c_write(ov511, 0x79,
+ (unsigned char)(val >> 8) + 0xb);
+ if (rc < 0)
+ goto out;
#endif
+ break;
+ case SEN_SAA7111A:
+ rc = ov51x_i2c_write(ov511, 0x0d, (val + 32768) >> 8);
+ if (rc < 0)
+ goto out;
+ break;
+ default:
+ PDEBUG(3, "Unsupported with this sensor");
+ rc = -EPERM;
+ goto out;
}
- if (ov511_restart(dev) < 0)
+ rc = 0; /* Success */
+ ov511->hue = val;
+out:
+ if (ov511_restart(ov511) < 0)
return -EIO;
+ return rc;
+}
+
+/* Gets sensor's hue (red/blue balance) setting */
+static int
+sensor_get_hue(struct usb_ov511 *ov511, unsigned short *val)
+{
+ int rc;
+
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ rc = ov51x_i2c_read(ov511, OV7610_REG_BLUE);
+ if (rc < 0)
+ return rc;
+ else
+ *val = rc << 8;
+ break;
+ case SEN_OV7620:
+ rc = ov51x_i2c_read(ov511, 0x7a);
+ if (rc < 0)
+ return rc;
+ else
+ *val = rc << 8;
+ break;
+ case SEN_SAA7111A:
+ *val = ov511->hue;
+ break;
+ default:
+ PDEBUG(3, "Unsupported with this sensor");
+ return -EPERM;
+ }
+
+ PDEBUG(3, "%d", *val);
+ ov511->hue = *val;
+
return 0;
}
+/* -------------------------------------------------------------------------- */
+
static inline int
-ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
+sensor_set_picture(struct usb_ov511 *ov511, struct video_picture *p)
{
- int ret;
- struct usb_device *dev = ov511->dev;
+ int rc;
- PDEBUG(4, "ov511_get_picture");
+ PDEBUG(4, "sensor_set_picture");
- if (ov511_stop(dev) < 0)
- return -EIO;
+ ov511->whiteness = p->whiteness;
+
+ /* Don't return error if a setting is unsupported, or rest of settings
+ * will not be performed */
+
+ rc = sensor_set_contrast(ov511, p->contrast);
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ rc = sensor_set_brightness(ov511, p->brightness);
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ rc = sensor_set_saturation(ov511, p->colour);
+ if (FATAL_ERROR(rc))
+ return rc;
- if ((ret = ov511_i2c_read(dev, OV7610_REG_SAT)) < 0) return -EIO;
- p->colour = ret << 8;
+ rc = sensor_set_hue(ov511, p->hue);
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ return 0;
+}
- if ((ret = ov511_i2c_read(dev, OV7610_REG_CNT)) < 0) return -EIO;
- p->contrast = ret << 8;
+static inline int
+sensor_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
+{
+ int rc;
- if ((ret = ov511_i2c_read(dev, OV7610_REG_BRT)) < 0) return -EIO;
- p->brightness = ret << 8;
+ PDEBUG(4, "sensor_get_picture");
- /* This may not be the best way to do it */
- if ((ret = ov511_i2c_read(dev, OV7610_REG_BLUE)) < 0) return -EIO;
- p->hue = ret << 8;
+ /* Don't return error if a setting is unsupported, or rest of settings
+ * will not be performed */
+
+ rc = sensor_get_contrast(ov511, &(p->contrast));
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ rc = sensor_get_brightness(ov511, &(p->brightness));
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ rc = sensor_get_saturation(ov511, &(p->colour));
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ rc = sensor_get_hue(ov511, &(p->hue));
+ if (FATAL_ERROR(rc))
+ return rc;
p->whiteness = 105 << 8;
@@ -906,16 +2151,316 @@ ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
p->depth = ov511->frame[0].depth;
p->palette = ov511->frame[0].format;
- if (ov511_restart(dev) < 0)
+ return 0;
+}
+
+// FIXME: Exposure range is only 0x00-0x7f in interlace mode
+/* Sets current exposure for sensor. This only has an effect if auto-exposure
+ * is off */
+static inline int
+sensor_set_exposure(struct usb_ov511 *ov511, unsigned char val)
+{
+ int rc;
+
+ PDEBUG(3, "%d", val);
+
+ if (ov511->stop_during_set)
+ if (ov511_stop(ov511) < 0)
+ return -EIO;
+
+ switch (ov511->sensor) {
+ case SEN_OV6620:
+ case SEN_OV6630:
+ case SEN_OV7610:
+ case SEN_OV7620:
+ case SEN_OV7620AE:
+ case SEN_OV8600:
+ rc = ov51x_i2c_write(ov511, 0x10, val);
+ if (rc < 0)
+ goto out;
+
+ break;
+ case SEN_KS0127:
+ case SEN_KS0127B:
+ case SEN_SAA7111A:
+ PDEBUG(3, "Unsupported with this sensor");
+ return -EPERM;
+ default:
+ err("Sensor not supported for set_exposure");
+ return -EINVAL;
+ }
+
+ rc = 0; /* Success */
+ ov511->exposure = val;
+out:
+ if (ov511_restart(ov511) < 0)
return -EIO;
+ return rc;
+}
+
+/* Gets current exposure level from sensor, regardless of whether it is under
+ * manual control. */
+static int
+sensor_get_exposure(struct usb_ov511 *ov511, unsigned char *val)
+{
+ int rc;
+
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ case SEN_OV7620:
+ case SEN_OV7620AE:
+ case SEN_OV8600:
+ rc = ov51x_i2c_read(ov511, 0x10);
+ if (rc < 0)
+ return rc;
+ else
+ *val = rc;
+ break;
+ case SEN_KS0127:
+ case SEN_KS0127B:
+ case SEN_SAA7111A:
+ val = 0;
+ PDEBUG(3, "Unsupported with this sensor");
+ return -EPERM;
+ default:
+ err("Sensor not supported for get_exposure");
+ return -EINVAL;
+ }
+
+ PDEBUG(3, "%d", *val);
+ ov511->exposure = *val;
+
+ return 0;
+}
+
+/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */
+static inline void
+ov51x_led_control(struct usb_ov511 *ov511, int enable)
+{
+ PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+ if (ov511->bridge == BRG_OV511PLUS)
+ ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_LED_CTL,
+ enable ? 1 : 0);
+ else if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS)
+ ov511_reg_write_mask(ov511->dev, OV518_REG_GPIO_OUT,
+ enable ? 0x02 : 0x00, 0x02);
+ return;
+}
+
+/* Matches the sensor's internal frame rate to the lighting frequency.
+ * Valid frequencies are:
+ * 50 - 50Hz, for European and Asian lighting
+ * 60 - 60Hz, for American lighting
+ *
+ * Tested with: OV7610, OV7620, OV7620AE, OV6620
+ * Unsupported: KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static int
+sensor_set_light_freq(struct usb_ov511 *ov511, int freq)
+{
+ int sixty;
+
+ PDEBUG(4, "%d Hz", freq);
+
+ if (freq == 60)
+ sixty = 1;
+ else if (freq == 50)
+ sixty = 0;
+ else {
+ err("Invalid light freq (%d Hz)", freq);
+ return -EINVAL;
+ }
+
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ ov51x_i2c_write_mask(ov511, 0x2a, sixty?0x00:0x80, 0x80);
+ ov51x_i2c_write(ov511, 0x2b, sixty?0x00:0xac);
+ ov51x_i2c_write_mask(ov511, 0x13, 0x10, 0x10);
+ ov51x_i2c_write_mask(ov511, 0x13, 0x00, 0x10);
+ break;
+ case SEN_OV7620:
+ case SEN_OV7620AE:
+ case SEN_OV8600:
+ ov51x_i2c_write_mask(ov511, 0x2a, sixty?0x00:0x80, 0x80);
+ ov51x_i2c_write(ov511, 0x2b, sixty?0x00:0xac);
+ ov51x_i2c_write_mask(ov511, 0x76, 0x01, 0x01);
+ break;
+ case SEN_OV6620:
+ case SEN_OV6630:
+ ov51x_i2c_write(ov511, 0x2b, sixty?0xa8:0x28);
+ ov51x_i2c_write(ov511, 0x2a, sixty?0x84:0xa4);
+ break;
+ case SEN_KS0127:
+ case SEN_KS0127B:
+ case SEN_SAA7111A:
+ PDEBUG(5, "Unsupported with this sensor");
+ return -EPERM;
+ default:
+ err("Sensor not supported for set_light_freq");
+ return -EINVAL;
+ }
+
+ ov511->lightfreq = freq;
+
+ return 0;
+}
+
+/* If enable is true, turn on the sensor's banding filter, otherwise turn it
+ * off. This filter tries to reduce the pattern of horizontal light/dark bands
+ * caused by some (usually fluorescent) lighting. The light frequency must be
+ * set either before or after enabling it with ov51x_set_light_freq().
+ *
+ * Tested with: OV7610, OV7620, OV7620AE, OV6620.
+ * Unsupported: KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static inline int
+sensor_set_banding_filter(struct usb_ov511 *ov511, int enable)
+{
+ int rc;
+
+ PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+ if (ov511->sensor == SEN_KS0127 || ov511->sensor == SEN_KS0127B
+ || ov511->sensor == SEN_SAA7111A) {
+ PDEBUG(5, "Unsupported with this sensor");
+ return -EPERM;
+ }
+
+ rc = ov51x_i2c_write_mask(ov511, 0x2d, enable?0x04:0x00, 0x04);
+ if (rc < 0)
+ return rc;
+
+ ov511->bandfilt = enable;
+
+ return 0;
+}
+
+/* If enable is true, turn on the sensor's auto brightness control, otherwise
+ * turn it off.
+ *
+ * Unsupported: KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static inline int
+sensor_set_auto_brightness(struct usb_ov511 *ov511, int enable)
+{
+ int rc;
+
+ PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+ if (ov511->sensor == SEN_KS0127 || ov511->sensor == SEN_KS0127B
+ || ov511->sensor == SEN_SAA7111A) {
+ PDEBUG(5, "Unsupported with this sensor");
+ return -EPERM;
+ }
+
+ rc = ov51x_i2c_write_mask(ov511, 0x2d, enable?0x10:0x00, 0x10);
+ if (rc < 0)
+ return rc;
+
+ ov511->auto_brt = enable;
+
return 0;
}
-/* Returns number of bits per pixel (regardless of where they are located; planar or
- * not), or zero for unsupported format.
+/* If enable is true, turn on the sensor's auto exposure control, otherwise
+ * turn it off.
+ *
+ * Unsupported: KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
*/
-static int ov511_get_depth(int palette)
+static inline int
+sensor_set_auto_exposure(struct usb_ov511 *ov511, int enable)
+{
+ PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ ov51x_i2c_write_mask(ov511, 0x29, enable?0x00:0x80, 0x80);
+ break;
+ case SEN_OV6620:
+ case SEN_OV7620:
+ case SEN_OV7620AE:
+ case SEN_OV8600:
+ ov51x_i2c_write_mask(ov511, 0x13, enable?0x01:0x00, 0x01);
+ break;
+ case SEN_OV6630:
+ ov51x_i2c_write_mask(ov511, 0x28, enable?0x00:0x10, 0x10);
+ break;
+ case SEN_KS0127:
+ case SEN_KS0127B:
+ case SEN_SAA7111A:
+ PDEBUG(5, "Unsupported with this sensor");
+ return -EPERM;
+ default:
+ err("Sensor not supported for set_auto_exposure");
+ return -EINVAL;
+ }
+
+ ov511->auto_exp = enable;
+
+ return 0;
+}
+
+/* Modifies the sensor's exposure algorithm to allow proper exposure of objects
+ * that are illuminated from behind.
+ *
+ * Tested with: OV6620, OV7620
+ * Unsupported: OV7610, OV7620AE, KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static int
+sensor_set_backlight(struct usb_ov511 *ov511, int enable)
+{
+
+ PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+ switch (ov511->sensor) {
+ case SEN_OV7620:
+ case SEN_OV8600:
+ ov51x_i2c_write_mask(ov511, 0x68, enable?0xe0:0xc0, 0xe0);
+ ov51x_i2c_write_mask(ov511, 0x29, enable?0x08:0x00, 0x08);
+ ov51x_i2c_write_mask(ov511, 0x28, enable?0x02:0x00, 0x02);
+ break;
+ case SEN_OV6620:
+ ov51x_i2c_write_mask(ov511, 0x4e, enable?0xe0:0xc0, 0xe0);
+ ov51x_i2c_write_mask(ov511, 0x29, enable?0x08:0x00, 0x08);
+ ov51x_i2c_write_mask(ov511, 0x0e, enable?0x80:0x00, 0x80);
+ break;
+ case SEN_OV6630:
+ ov51x_i2c_write_mask(ov511, 0x4e, enable?0x80:0x60, 0xe0);
+ ov51x_i2c_write_mask(ov511, 0x29, enable?0x08:0x00, 0x08);
+ ov51x_i2c_write_mask(ov511, 0x28, enable?0x02:0x00, 0x02);
+ break;
+ case SEN_OV7610:
+ case SEN_OV7620AE:
+ case SEN_KS0127:
+ case SEN_KS0127B:
+ case SEN_SAA7111A:
+ PDEBUG(5, "Unsupported with this sensor");
+ return -EPERM;
+ default:
+ err("Sensor not supported for set_backlight");
+ return -EINVAL;
+ }
+
+ ov511->backlight = enable;
+
+ return 0;
+}
+
+/* Returns number of bits per pixel (regardless of where they are located;
+ * planar or not), or zero for unsupported format.
+ */
+static inline int
+ov511_get_depth(int palette)
{
switch (palette) {
case VIDEO_PALETTE_GREY: return 8;
@@ -923,80 +2468,189 @@ static int ov511_get_depth(int palette)
case VIDEO_PALETTE_RGB24: return 24;
case VIDEO_PALETTE_YUV422: return 16;
case VIDEO_PALETTE_YUYV: return 16;
- case VIDEO_PALETTE_YUV420: return 24;
- case VIDEO_PALETTE_YUV422P: return 24; /* Planar */
+ case VIDEO_PALETTE_YUV420: return 12;
+ case VIDEO_PALETTE_YUV422P: return 16; /* Planar */
+ case VIDEO_PALETTE_YUV420P: return 12; /* Planar */
default: return 0; /* Invalid format */
}
}
-/* LNCNT values fixed by Lawrence Glaister <lg@jfm.bc.ca> */
-static struct mode_list mlist[] = {
- /* W H C PXCNT LNCNT PXDIV LNDIV M420 COMA COML */
- { 640, 480, 0, 0x4f, 0x3b, 0x00, 0x00, 0x03, 0x24, 0x9e },
- { 640, 480, 1, 0x4f, 0x3b, 0x00, 0x00, 0x03, 0x24, 0x9e },
- { 320, 240, 0, 0x27, 0x1d, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 320, 240, 1, 0x27, 0x1d, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 352, 288, 0, 0x2b, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 352, 288, 1, 0x2b, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 384, 288, 0, 0x2f, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 384, 288, 1, 0x2f, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 448, 336, 0, 0x37, 0x29, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 448, 336, 1, 0x37, 0x29, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 176, 144, 0, 0x15, 0x12, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 176, 144, 1, 0x15, 0x12, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 160, 120, 0, 0x13, 0x0e, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 160, 120, 1, 0x13, 0x0e, 0x00, 0x00, 0x03, 0x04, 0x1e },
- { 0, 0 }
-};
+/* Bytes per frame. Used by read(). Return of 0 indicates error */
+static inline long int
+get_frame_length(struct ov511_frame *frame)
+{
+ if (!frame)
+ return 0;
+ else
+ return ((frame->width * frame->height
+ * ov511_get_depth(frame->format)) >> 3);
+}
static int
-ov511_mode_init_regs(struct usb_ov511 *ov511,
- int width, int height, int mode, int sub_flag)
+mode_init_ov_sensor_regs(struct usb_ov511 *ov511, int width, int height,
+ int mode, int sub_flag, int qvga)
{
- int i;
- struct usb_device *dev = ov511->dev;
- int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize;
- int hwscale = 0, vwscale = 0;
-
- PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
- width, height, mode, sub_flag);
+ int clock;
- if (ov511_stop(ov511->dev) < 0)
- return -EIO;
+ /******** Mode (VGA/QVGA) and sensor specific regs ********/
- /* Dumppix only works with RGB24 */
- if (dumppix && (mode != VIDEO_PALETTE_RGB24)) {
- err("dumppix only supported with RGB 24");
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ ov51x_i2c_write(ov511, 0x14, qvga?0x24:0x04);
+// FIXME: Does this improve the image quality or frame rate?
+#if 0
+ ov51x_i2c_write_mask(ov511, 0x28, qvga?0x00:0x20, 0x20);
+ ov51x_i2c_write(ov511, 0x24, 0x10);
+ ov51x_i2c_write(ov511, 0x25, qvga?0x40:0x8a);
+ ov51x_i2c_write(ov511, 0x2f, qvga?0x30:0xb0);
+ ov51x_i2c_write(ov511, 0x35, qvga?0x1c:0x9c);
+#endif
+ break;
+ case SEN_OV7620:
+// ov51x_i2c_write(ov511, 0x2b, 0x00);
+ ov51x_i2c_write(ov511, 0x14, qvga?0xa4:0x84);
+ ov51x_i2c_write_mask(ov511, 0x28, qvga?0x00:0x20, 0x20);
+ ov51x_i2c_write(ov511, 0x24, qvga?0x20:0x3a);
+ ov51x_i2c_write(ov511, 0x25, qvga?0x30:0x60);
+ ov51x_i2c_write_mask(ov511, 0x2d, qvga?0x40:0x00, 0x40);
+ ov51x_i2c_write_mask(ov511, 0x67, qvga?0xf0:0x90, 0xf0);
+ ov51x_i2c_write_mask(ov511, 0x74, qvga?0x20:0x00, 0x20);
+ break;
+ case SEN_OV7620AE:
+// ov51x_i2c_write(ov511, 0x2b, 0x00);
+ ov51x_i2c_write(ov511, 0x14, qvga?0xa4:0x84);
+// FIXME: Enable this once 7620AE uses 7620 initial settings
+#if 0
+ ov51x_i2c_write_mask(ov511, 0x28, qvga?0x00:0x20, 0x20);
+ ov51x_i2c_write(ov511, 0x24, qvga?0x20:0x3a);
+ ov51x_i2c_write(ov511, 0x25, qvga?0x30:0x60);
+ ov51x_i2c_write_mask(ov511, 0x2d, qvga?0x40:0x00, 0x40);
+ ov51x_i2c_write_mask(ov511, 0x67, qvga?0xb0:0x90, 0xf0);
+ ov51x_i2c_write_mask(ov511, 0x74, qvga?0x20:0x00, 0x20);
+#endif
+ break;
+ case SEN_OV6620:
+ case SEN_OV6630:
+ ov51x_i2c_write(ov511, 0x14, qvga?0x24:0x04);
+ /* No special settings yet */
+ break;
+ default:
+ err("Invalid sensor");
return -EINVAL;
}
+ /******** Palette-specific regs ********/
+
if (mode == VIDEO_PALETTE_GREY) {
- ov511_reg_write(dev, 0x16, 0x00);
if (ov511->sensor == SEN_OV7610
|| ov511->sensor == SEN_OV7620AE) {
- /* these aren't valid on the OV6620/OV7620 */
- ov511_i2c_write(dev, 0x0e, 0x44);
+ /* these aren't valid on the OV6620/OV7620/6630? */
+ ov51x_i2c_write_mask(ov511, 0x0e, 0x40, 0x40);
}
- ov511_i2c_write(dev, 0x13, autoadjust ? 0x21 : 0x20);
-
- /* For snapshot */
- ov511_reg_write(dev, 0x1e, 0x00);
- ov511_reg_write(dev, 0x1f, 0x01);
+ ov51x_i2c_write_mask(ov511, 0x13, 0x20, 0x20);
} else {
- ov511_reg_write(dev, 0x16, 0x01);
if (ov511->sensor == SEN_OV7610
|| ov511->sensor == SEN_OV7620AE) {
- /* not valid on the OV6620/OV7620 */
- ov511_i2c_write(dev, 0x0e, 0x04);
+ /* not valid on the OV6620/OV7620/6630? */
+ ov51x_i2c_write_mask(ov511, 0x0e, 0x00, 0x40);
}
- ov511_i2c_write(dev, 0x13, autoadjust ? 0x01 : 0x00);
+ ov51x_i2c_write_mask(ov511, 0x13, 0x00, 0x20);
+ }
- /* For snapshot */
- ov511_reg_write(dev, 0x1e, 0x01);
- ov511_reg_write(dev, 0x1f, 0x03);
+ /******** Clock programming ********/
+
+ // FIXME: Test this with OV6630
+
+ /* The OV6620 needs special handling. This prevents the
+ * severe banding that normally occurs */
+ if (ov511->sensor == SEN_OV6620 || ov511->sensor == SEN_OV6630)
+ {
+ /* Clock down */
+
+ ov51x_i2c_write(ov511, 0x2a, 0x04);
+
+ if (ov511->compress) {
+// clock = 0; /* This ensures the highest frame rate */
+ clock = 3;
+ } else if (clockdiv == -1) { /* If user didn't override it */
+ clock = 3; /* Gives better exposure time */
+ } else {
+ clock = clockdiv;
+ }
+
+ PDEBUG(4, "Setting clock divisor to %d", clock);
+
+ ov51x_i2c_write(ov511, 0x11, clock);
+
+ ov51x_i2c_write(ov511, 0x2a, 0x84);
+ /* This next setting is critical. It seems to improve
+ * the gain or the contrast. The "reserved" bits seem
+ * to have some effect in this case. */
+ ov51x_i2c_write(ov511, 0x2d, 0x85);
}
+ else
+ {
+ if (ov511->compress) {
+ clock = 1; /* This ensures the highest frame rate */
+ } else if (clockdiv == -1) { /* If user didn't override it */
+ /* Calculate and set the clock divisor */
+ clock = ((sub_flag ? ov511->subw * ov511->subh
+ : width * height)
+ * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2)
+ / 66000;
+ } else {
+ clock = clockdiv;
+ }
+
+ PDEBUG(4, "Setting clock divisor to %d", clock);
+
+ ov51x_i2c_write(ov511, 0x11, clock);
+ }
+
+ /******** Special Features ********/
+
+ if (framedrop >= 0)
+ ov51x_i2c_write(ov511, 0x16, framedrop);
+
+ /* We only have code to convert GBR -> RGB24 */
+ if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)
+ ov51x_i2c_write_mask(ov511, 0x12, 0x08, 0x08);
+ else
+ ov51x_i2c_write_mask(ov511, 0x12, 0x00, 0x08);
+
+ /* Test Pattern */
+ ov51x_i2c_write_mask(ov511, 0x12, (testpat?0x02:0x00), 0x02);
+
+ /* Auto white balance */
+// if (awb)
+ ov51x_i2c_write_mask(ov511, 0x12, 0x04, 0x04);
+// else
+// ov51x_i2c_write_mask(ov511, 0x12, 0x00, 0x04);
+
+ // This will go away as soon as ov511_mode_init_sensor_regs()
+ // is fully tested.
+ /* 7620/6620/6630? don't have register 0x35, so play it safe */
+ if (ov511->sensor == SEN_OV7610 ||
+ ov511->sensor == SEN_OV7620AE) {
+ if (width == 640 && height == 480)
+ ov51x_i2c_write(ov511, 0x35, 0x9e);
+ else
+ ov51x_i2c_write(ov511, 0x35, 0x1e);
+ }
+
+ return 0;
+}
+
+static int
+set_ov_sensor_window(struct usb_ov511 *ov511, int width, int height, int mode,
+ int sub_flag)
+{
+ int ret;
+ int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize;
+ int hoffset, voffset, hwscale = 0, vwscale = 0;
- /* The different sensor ICs handle setting up of window differently */
+ /* The different sensor ICs handle setting up of window differently.
+ * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */
switch (ov511->sensor) {
case SEN_OV7610:
case SEN_OV7620AE:
@@ -1005,14 +2659,15 @@ ov511_mode_init_regs(struct usb_ov511 *ov511,
vwsbase = vwebase = 0x05;
break;
case SEN_OV6620:
+ case SEN_OV6630: // FIXME: Is this right?
hwsbase = 0x38;
hwebase = 0x3a;
vwsbase = 0x05;
vwebase = 0x06;
break;
case SEN_OV7620:
- hwsbase = 0x2c;
- hwebase = 0x2d;
+ hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
+ hwebase = 0x2f;
vwsbase = vwebase = 0x05;
break;
default:
@@ -1020,118 +2675,531 @@ ov511_mode_init_regs(struct usb_ov511 *ov511,
return -EINVAL;
}
- /* Bit 5 of COM C register varies with sensor */
- if (ov511->sensor == SEN_OV6620) {
+ if (ov511->sensor == SEN_OV6620 || ov511->sensor == SEN_OV6630) {
if (width > 176 && height > 144) { /* CIF */
- ov511_i2c_write(dev, 0x14, 0x04);
+ ret = mode_init_ov_sensor_regs(ov511, width, height,
+ mode, sub_flag, 0);
+ if (ret < 0)
+ return ret;
hwscale = 1;
vwscale = 1; /* The datasheet says 0; it's wrong */
hwsize = 352;
vwsize = 288;
+ } else if (width > 176 || height > 144) {
+ err("Illegal dimensions");
+ return -EINVAL;
} else { /* QCIF */
- ov511_i2c_write(dev, 0x14, 0x24);
+ ret = mode_init_ov_sensor_regs(ov511, width, height,
+ mode, sub_flag, 1);
+ if (ret < 0)
+ return ret;
hwsize = 176;
vwsize = 144;
}
- }
- else {
+ } else {
if (width > 320 && height > 240) { /* VGA */
- ov511_i2c_write(dev, 0x14, 0x04);
+ ret = mode_init_ov_sensor_regs(ov511, width, height,
+ mode, sub_flag, 0);
+ if (ret < 0)
+ return ret;
hwscale = 2;
vwscale = 1;
hwsize = 640;
vwsize = 480;
+ } else if (width > 320 || height > 240) {
+ err("Illegal dimensions");
+ return -EINVAL;
} else { /* QVGA */
- ov511_i2c_write(dev, 0x14, 0x24);
+ ret = mode_init_ov_sensor_regs(ov511, width, height,
+ mode, sub_flag, 1);
+ if (ret < 0)
+ return ret;
hwscale = 1;
hwsize = 320;
vwsize = 240;
- }
+ }
}
+ /* Center the window */
+ hoffset = ((hwsize - width) / 2) >> hwscale;
+ voffset = ((vwsize - height) / 2) >> vwscale;
+
/* FIXME! - This needs to be changed to support 160x120 and 6620!!! */
if (sub_flag) {
- ov511_i2c_write(dev, 0x17, hwsbase+(ov511->subx>>hwscale));
- ov511_i2c_write(dev, 0x18, hwebase+((ov511->subx+ov511->subw)>>hwscale));
- ov511_i2c_write(dev, 0x19, vwsbase+(ov511->suby>>vwscale));
- ov511_i2c_write(dev, 0x1a, vwebase+((ov511->suby+ov511->subh)>>vwscale));
+ ov51x_i2c_write(ov511, 0x17, hwsbase+(ov511->subx>>hwscale));
+ ov51x_i2c_write(ov511, 0x18,
+ hwebase+((ov511->subx+ov511->subw)>>hwscale));
+ ov51x_i2c_write(ov511, 0x19, vwsbase+(ov511->suby>>vwscale));
+ ov51x_i2c_write(ov511, 0x1a,
+ vwebase+((ov511->suby+ov511->subh)>>vwscale));
} else {
- ov511_i2c_write(dev, 0x17, hwsbase);
- ov511_i2c_write(dev, 0x18, hwebase + (hwsize>>hwscale));
- ov511_i2c_write(dev, 0x19, vwsbase);
- ov511_i2c_write(dev, 0x1a, vwebase + (vwsize>>vwscale));
+ ov51x_i2c_write(ov511, 0x17, hwsbase + hoffset);
+ ov51x_i2c_write(ov511, 0x18,
+ hwebase + hoffset + (hwsize>>hwscale));
+ ov51x_i2c_write(ov511, 0x19, vwsbase + voffset);
+ ov51x_i2c_write(ov511, 0x1a,
+ vwebase + voffset + (vwsize>>vwscale));
}
- for (i = 0; mlist[i].width; i++) {
- int lncnt, pxcnt, clock;
+#ifdef OV511_DEBUG
+ if (dump_sensor)
+ ov51x_dump_i2c_regs(ov511);
+#endif
- if (width != mlist[i].width || height != mlist[i].height)
- continue;
+ return 0;
+}
- if (!mlist[i].color && mode != VIDEO_PALETTE_GREY)
- continue;
+/* Set up the OV511/OV511+ with the given image parameters.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static int
+ov511_mode_init_regs(struct usb_ov511 *ov511,
+ int width, int height, int mode, int sub_flag)
+{
+ int lncnt, pxcnt, rc = 0;
+ struct usb_device *dev = ov511->dev;
- /* Here I'm assuming that snapshot size == image size.
- * I hope that's always true. --claudio
- */
- pxcnt = sub_flag ? (ov511->subw >> 3) - 1 : mlist[i].pxcnt;
- lncnt = sub_flag ? (ov511->subh >> 3) - 1 : mlist[i].lncnt;
-
- ov511_reg_write(dev, 0x12, pxcnt);
- ov511_reg_write(dev, 0x13, lncnt);
- ov511_reg_write(dev, 0x14, mlist[i].pxdv);
- ov511_reg_write(dev, 0x15, mlist[i].lndv);
- ov511_reg_write(dev, 0x18, mlist[i].m420);
-
- /* Snapshot additions */
- ov511_reg_write(dev, 0x1a, pxcnt);
- ov511_reg_write(dev, 0x1b, lncnt);
- ov511_reg_write(dev, 0x1c, mlist[i].pxdv);
- ov511_reg_write(dev, 0x1d, mlist[i].lndv);
-
- /* Calculate and set the clock divisor */
- clock = ((sub_flag ? ov511->subw * ov511->subh : width * height)
- * (mlist[i].color ? 3 : 2) / 2) / 66000;
-#if 0
- clock *= cams;
-#endif
- ov511_i2c_write(dev, 0x11, clock);
+ if (!ov511 || !dev)
+ return -EFAULT;
- /* We only have code to convert GBR -> RGB24 */
- if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)
- ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x0a:0x08));
- else
- ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x02:0x00));
+ if (sub_flag) {
+ width = ov511->subw;
+ height = ov511->subh;
+ }
- /* 7620/6620 don't have register 0x35, so play it safe */
- if (ov511->sensor == SEN_OV7610 ||
- ov511->sensor == SEN_OV7620AE)
- ov511_i2c_write(dev, 0x35, mlist[i].common_L);
+ PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
+ width, height, mode, sub_flag);
- break;
+ // FIXME: This should be moved to a 7111a-specific function once
+ // subcapture is dealt with properly
+ if (ov511->sensor == SEN_SAA7111A) {
+ if (width == 320 && height == 240) {
+ /* No need to do anything special */
+ } else if (width == 640 && height == 480) {
+ /* Set the OV511 up as 320x480, but keep the V4L
+ * resolution as 640x480 */
+ width = 320;
+ } else {
+ err("SAA7111A only supports 320x240 or 640x480");
+ return -EINVAL;
+ }
+ }
+
+ /* Make sure width and height are a multiple of 8 */
+ if (width % 8 || height % 8) {
+ err("Invalid size (%d, %d) (mode = %d)", width, height, mode);
+ return -EINVAL;
+ }
+
+ if (width < ov511->minwidth || height < ov511->minheight) {
+ err("Requested dimensions are too small");
+ return -EINVAL;
+ }
+
+ if (ov511_stop(ov511) < 0)
+ return -EIO;
+
+ if (mode == VIDEO_PALETTE_GREY) {
+ ov511_reg_write(dev, 0x16, 0x00);
+
+ /* For snapshot */
+ ov511_reg_write(dev, 0x1e, 0x00);
+ ov511_reg_write(dev, 0x1f, 0x01);
+ } else {
+ ov511_reg_write(dev, 0x16, 0x01);
+
+ /* For snapshot */
+ ov511_reg_write(dev, 0x1e, 0x01);
+ ov511_reg_write(dev, 0x1f, 0x03);
}
- if (compress) {
- ov511_reg_write(dev, 0x78, 0x03); // Turn on Y compression
- ov511_reg_write(dev, 0x79, 0x00); // Disable LUTs
+ /* Here I'm assuming that snapshot size == image size.
+ * I hope that's always true. --claudio
+ */
+ pxcnt = (width >> 3) - 1;
+ lncnt = (height >> 3) - 1;
+
+ ov511_reg_write(dev, 0x12, pxcnt);
+ ov511_reg_write(dev, 0x13, lncnt);
+ ov511_reg_write(dev, 0x14, 0x00);
+ ov511_reg_write(dev, 0x15, 0x00);
+ ov511_reg_write(dev, 0x18, 0x03); /* YUV420, low pass filer on */
+
+ /* Snapshot additions */
+ ov511_reg_write(dev, 0x1a, pxcnt);
+ ov511_reg_write(dev, 0x1b, lncnt);
+ ov511_reg_write(dev, 0x1c, 0x00);
+ ov511_reg_write(dev, 0x1d, 0x00);
+
+ if (ov511->compress) {
+ ov511_reg_write(dev, 0x78, 0x07); // Turn on Y & UV compression
+ ov511_reg_write(dev, 0x79, 0x03); // Enable LUTs
+ ov511_reset(ov511, OV511_RESET_OMNICE);
}
+//out:
+ if (ov511_restart(ov511) < 0)
+ return -EIO;
+
+ return rc;
+}
+
+static struct mode_list_518 mlist518[] = {
+ /* W H reg28 reg29 reg2a reg2c reg2e reg24 reg25 */
+ { 352, 288, 0x00, 0x16, 0x48, 0x00, 0x00, 0x9f, 0x90 },
+ { 320, 240, 0x00, 0x14, 0x3c, 0x10, 0x18, 0x9f, 0x90 },
+ { 176, 144, 0x05, 0x0b, 0x24, 0x00, 0x00, 0xff, 0xf0 },
+ { 160, 120, 0x05, 0x0a, 0x1e, 0x08, 0x0c, 0xff, 0xf0 },
+ { 0, 0 }
+};
+
+/* Sets up the OV518/OV518+ with the given image parameters
+ *
+ * OV518 needs a completely different approach, until we can figure out what
+ * the individual registers do. Many register ops are commented out until we
+ * can find out if they are still valid. Also, only 15 FPS is supported now.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static int
+ov518_mode_init_regs(struct usb_ov511 *ov511,
+ int width, int height, int mode, int sub_flag)
+{
+ int i;
+ struct usb_device *dev = ov511->dev;
+ unsigned char b[3]; /* Multiple-value reg buffer */
+
+ PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
+ width, height, mode, sub_flag);
- if (ov511_restart(ov511->dev) < 0)
+ if (ov511_stop(ov511) < 0)
return -EIO;
- if (mlist[i].width == 0) {
+ for (i = 0; mlist518[i].width; i++) {
+// int lncnt, pxcnt;
+
+ if (width != mlist518[i].width || height != mlist518[i].height)
+ continue;
+
+// FIXME: Subcapture won't be possible until we know what the registers do
+// FIXME: We can't handle anything but YUV420 so far
+
+// /* Here I'm assuming that snapshot size == image size.
+// * I hope that's always true. --claudio
+// */
+// pxcnt = sub_flag ? (ov511->subw >> 3) - 1 : mlist[i].pxcnt;
+// lncnt = sub_flag ? (ov511->subh >> 3) - 1 : mlist[i].lncnt;
+//
+// ov511_reg_write(dev, 0x12, pxcnt);
+// ov511_reg_write(dev, 0x13, lncnt);
+
+ /******** Set the mode ********/
+
+ /* Mode independent regs */
+ ov511_reg_write(dev, 0x2b, 0x00);
+ ov511_reg_write(dev, 0x2d, 0x00);
+ ov511_reg_write(dev, 0x3b, 0x00);
+ ov511_reg_write(dev, 0x3d, 0x00);
+
+ /* Mode dependent regs. Regs 38 - 3e are always the same as
+ * regs 28 - 2e */
+ ov511_reg_write_mask(dev, 0x28, mlist518[i].reg28
+ | (mode == VIDEO_PALETTE_GREY) ? 0x80:0x00, 0x8f);
+ ov511_reg_write(dev, 0x29, mlist518[i].reg29);
+ ov511_reg_write(dev, 0x2a, mlist518[i].reg2a);
+ ov511_reg_write(dev, 0x2c, mlist518[i].reg2c);
+ ov511_reg_write(dev, 0x2e, mlist518[i].reg2e);
+ ov511_reg_write_mask(dev, 0x38, mlist518[i].reg28
+ | (mode == VIDEO_PALETTE_GREY) ? 0x80:0x00, 0x8f);
+ ov511_reg_write(dev, 0x39, mlist518[i].reg29);
+ ov511_reg_write(dev, 0x3a, mlist518[i].reg2a);
+ ov511_reg_write(dev, 0x3c, mlist518[i].reg2c);
+ ov511_reg_write(dev, 0x3e, mlist518[i].reg2e);
+ ov511_reg_write(dev, 0x24, mlist518[i].reg24);
+ ov511_reg_write(dev, 0x25, mlist518[i].reg25);
+
+ /* Windows driver does this here; who knows why */
+ ov511_reg_write(dev, 0x2f, 0x80);
+
+ /******** Set the framerate (to 15 FPS) ********/
+
+ /* Mode independent, but framerate dependent, regs */
+ /* These are for 15 FPS only */
+ ov511_reg_write(dev, 0x51, 0x08);
+ ov511_reg_write(dev, 0x22, 0x18);
+ ov511_reg_write(dev, 0x23, 0xff);
+ ov511_reg_write(dev, 0x71, 0x19); /* Compression-related? */
+
+ // FIXME: Sensor-specific
+ /* Bit 5 is what matters here. Of course, it is "reserved" */
+ ov51x_i2c_write(ov511, 0x54, 0x23);
+
+ ov511_reg_write(dev, 0x2f, 0x80);
+
+ /* Mode dependent regs */
+ if ((width == 352 && height == 288) ||
+ (width == 320 && height == 240)) {
+ b[0]=0x80; b[1]=0x02;
+ ov518_reg_write_multi(dev, 0x30, b, 2);
+ b[0]=0x90; b[1]=0x01;
+ ov518_reg_write_multi(dev, 0xc4, b, 2);
+ b[0]=0xf4; b[1]=0x01;
+ ov518_reg_write_multi(dev, 0xc6, b, 2);
+ b[0]=0xf4; b[1]=0x01;
+ ov518_reg_write_multi(dev, 0xc7, b, 2);
+ b[0]=0x8e; b[1]=0x00;
+ ov518_reg_write_multi(dev, 0xc8, b, 2);
+ b[0]=0x1a; b[1]=0x00; b[2]=0x02;
+ ov518_reg_write_multi(dev, 0xca, b, 3);
+ b[0]=0x14; b[1]=0x02;
+ ov518_reg_write_multi(dev, 0xcb, b, 2);
+ b[0]=0xd0; b[1]=0x07;
+ ov518_reg_write_multi(dev, 0xcc, b, 2);
+ b[0]=0x20; b[1]=0x00;
+ ov518_reg_write_multi(dev, 0xcd, b, 2);
+ b[0]=0x60; b[1]=0x02;
+ ov518_reg_write_multi(dev, 0xce, b, 2);
+
+ } else if ((width == 176 && height == 144) ||
+ (width == 160 && height == 120)) {
+ b[0]=0x80; b[1]=0x01;
+ ov518_reg_write_multi(dev, 0x30, b, 2);
+ b[0]=0xc8; b[1]=0x00;
+ ov518_reg_write_multi(dev, 0xc4, b, 2);
+ b[0]=0x40; b[1]=0x01;
+ ov518_reg_write_multi(dev, 0xc6, b, 2);
+ b[0]=0x40; b[1]=0x01;
+ ov518_reg_write_multi(dev, 0xc7, b, 2);
+ b[0]=0x60; b[1]=0x00;
+ ov518_reg_write_multi(dev, 0xc8, b, 2);
+ b[0]=0x0f; b[1]=0x33; b[2]=0x01;
+ ov518_reg_write_multi(dev, 0xca, b, 3);
+ b[0]=0x40; b[1]=0x01;
+ ov518_reg_write_multi(dev, 0xcb, b, 2);
+ b[0]=0xec; b[1]=0x04;
+ ov518_reg_write_multi(dev, 0xcc, b, 2);
+ b[0]=0x13; b[1]=0x00;
+ ov518_reg_write_multi(dev, 0xcd, b, 2);
+ b[0]=0x6d; b[1]=0x01;
+ ov518_reg_write_multi(dev, 0xce, b, 2);
+ } else {
+ /* Can't happen, since we already handled this case */
+ err("ov518_mode_init_regs(): **** logic error ****");
+ }
+
+ ov511_reg_write(dev, 0x2f, 0x80);
+
+ break;
+ }
+
+ if (ov511_restart(ov511) < 0)
+ return -EIO;
+
+ /* Reset it just for good measure */
+ if (ov511_reset(ov511, OV511_RESET_NOREGS) < 0)
+ return -EIO;
+
+ if (mlist518[i].width == 0) {
err("Unknown mode (%d, %d): %d", width, height, mode);
return -EINVAL;
}
-#ifdef OV511_DEBUG
- if (debug >= 5)
- ov511_dump_i2c_regs(dev);
-#endif
+ return 0;
+}
+
+/* This is a wrapper around the OV511, OV518, and sensor specific functions */
+static int
+mode_init_regs(struct usb_ov511 *ov511,
+ int width, int height, int mode, int sub_flag)
+{
+ int rc = 0;
+
+ if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS) {
+ rc = ov518_mode_init_regs(ov511, width, height, mode, sub_flag);
+ } else {
+ rc = ov511_mode_init_regs(ov511, width, height, mode, sub_flag);
+ }
+
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ switch (ov511->sensor) {
+ case SEN_OV7610:
+ case SEN_OV7620:
+ case SEN_OV7620AE:
+ case SEN_OV8600:
+ case SEN_OV6620:
+ case SEN_OV6630:
+ rc = set_ov_sensor_window(ov511, width, height, mode, sub_flag);
+ break;
+ case SEN_KS0127:
+ case SEN_KS0127B:
+ err("KS0127-series decoders not supported yet");
+ rc = -EINVAL;
+ break;
+ case SEN_SAA7111A:
+// rc = mode_init_saa_sensor_regs(ov511, width, height, mode,
+// sub_flag);
+
+ PDEBUG(1, "SAA status = 0X%x", ov51x_i2c_read(ov511, 0x1f));
+ break;
+ default:
+ err("Unknown sensor");
+ rc = -EINVAL;
+ }
+
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ /* Sensor-independent settings */
+ rc = sensor_set_auto_brightness(ov511, ov511->auto_brt);
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ rc = sensor_set_auto_exposure(ov511, ov511->auto_exp);
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ rc = sensor_set_banding_filter(ov511, bandingfilter);
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ if (ov511->lightfreq) {
+ rc = sensor_set_light_freq(ov511, lightfreq);
+ if (FATAL_ERROR(rc))
+ return rc;
+ }
+
+ rc = sensor_set_backlight(ov511, ov511->backlight);
+ if (FATAL_ERROR(rc))
+ return rc;
+
+ return 0;
+}
+
+/* This sets the default image parameters (Size = max, RGB24). This is
+ * useful for apps that use read() and do not set these.
+ */
+static int
+ov51x_set_default_params(struct usb_ov511 *ov511)
+{
+ int i;
+
+ PDEBUG(3, "%dx%d, RGB24", ov511->maxwidth, ov511->maxheight);
+
+ /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
+ * (using read() instead). */
+ for (i = 0; i < OV511_NUMFRAMES; i++) {
+ ov511->frame[i].width = ov511->maxwidth;
+ ov511->frame[i].height = ov511->maxheight;
+ ov511->frame[i].bytes_read = 0;
+ if (force_palette)
+ ov511->frame[i].format = force_palette;
+ else
+ ov511->frame[i].format = VIDEO_PALETTE_RGB24;
+ ov511->frame[i].depth = ov511_get_depth(ov511->frame[i].format);
+ }
+
+ /* Initialize to max width/height, RGB24 */
+ if (mode_init_regs(ov511, ov511->maxwidth, ov511->maxheight,
+ ov511->frame[0].format, 0) < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**********************************************************************
+ *
+ * Video decoder stuff
+ *
+ **********************************************************************/
+
+/* Set analog input port of decoder */
+static int
+decoder_set_input(struct usb_ov511 *ov511, int input)
+{
+ PDEBUG(4, "port %d", input);
+
+ switch (ov511->sensor) {
+ case SEN_SAA7111A:
+ {
+ /* Select mode */
+ ov51x_i2c_write_mask(ov511, 0x02, input, 0x07);
+ /* Bypass chrominance trap for modes 4..7 */
+ ov51x_i2c_write_mask(ov511, 0x09,
+ (input > 3) ? 0x80:0x00, 0x80);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Get ASCII name of video input */
+static int
+decoder_get_input_name(struct usb_ov511 *ov511, int input, char *name)
+{
+ switch (ov511->sensor) {
+ case SEN_SAA7111A:
+ {
+ if (input < 0 || input > 7)
+ return -EINVAL;
+ else if (input < 4)
+ sprintf(name, "CVBS-%d", input);
+ else // if (input < 8)
+ sprintf(name, "S-Video-%d", input - 4);
+
+ break;
+ }
+ default:
+ sprintf(name, "%s", "Camera");
+ }
+
+ return 0;
+}
+
+/* Set norm (NTSC, PAL, SECAM, AUTO) */
+static int
+decoder_set_norm(struct usb_ov511 *ov511, int norm)
+{
+ PDEBUG(4, "%d", norm);
+
+ switch (ov511->sensor) {
+ case SEN_SAA7111A:
+ {
+ int reg_8, reg_e;
+
+ if (norm == VIDEO_MODE_NTSC) {
+ reg_8 = 0x40; /* 60 Hz */
+ reg_e = 0x00; /* NTSC M / PAL BGHI */
+ } else if (norm == VIDEO_MODE_PAL) {
+ reg_8 = 0x00; /* 50 Hz */
+ reg_e = 0x00; /* NTSC M / PAL BGHI */
+ } else if (norm == VIDEO_MODE_AUTO) {
+ reg_8 = 0x80; /* Auto field detect */
+ reg_e = 0x00; /* NTSC M / PAL BGHI */
+ } else if (norm == VIDEO_MODE_SECAM) {
+ reg_8 = 0x00; /* 50 Hz */
+ reg_e = 0x50; /* SECAM / PAL 4.43 */
+ } else {
+ return -EINVAL;
+ }
+
+ ov51x_i2c_write_mask(ov511, 0x08, reg_8, 0xc0);
+ ov51x_i2c_write_mask(ov511, 0x0e, reg_e, 0x70);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
return 0;
}
+
/**********************************************************************
*
* Color correction functions
@@ -1169,7 +3237,7 @@ ov511_mode_init_regs(struct usb_ov511 *ov511,
static inline void
ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
- int rowPixels, unsigned char * rgb, int bits)
+ int rowPixels, unsigned char * rgb, int bits)
{
const int rvScale = 91881;
const int guScale = -22553;
@@ -1192,34 +3260,104 @@ ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
if (bits == 24) {
/* Write out top two pixels */
- rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL);
- rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR);
+ rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
+ rgb[2] = LIMIT(r+yTL);
+
+ rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
+ rgb[5] = LIMIT(r+yTR);
/* Skip down to next line to write out bottom two pixels */
rgb += 3 * rowPixels;
- rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL);
- rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR);
+ rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
+ rgb[2] = LIMIT(r+yBL);
+
+ rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
+ rgb[5] = LIMIT(r+yBR);
} else if (bits == 16) {
/* Write out top two pixels */
- rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F) | ((LIMIT(g+yTL) << 3) & 0xE0);
- rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07) | (LIMIT(r+yTL) & 0xF8);
+ rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F)
+ | ((LIMIT(g+yTL) << 3) & 0xE0);
+ rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07)
+ | (LIMIT(r+yTL) & 0xF8);
- rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F) | ((LIMIT(g+yTR) << 3) & 0xE0);
- rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07) | (LIMIT(r+yTR) & 0xF8);
+ rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F)
+ | ((LIMIT(g+yTR) << 3) & 0xE0);
+ rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07)
+ | (LIMIT(r+yTR) & 0xF8);
/* Skip down to next line to write out bottom two pixels */
rgb += 2 * rowPixels;
- rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F) | ((LIMIT(g+yBL) << 3) & 0xE0);
- rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07) | (LIMIT(r+yBL) & 0xF8);
+ rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F)
+ | ((LIMIT(g+yBL) << 3) & 0xE0);
+ rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07)
+ | (LIMIT(r+yBL) & 0xF8);
- rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F) | ((LIMIT(g+yBR) << 3) & 0xE0);
- rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07) | (LIMIT(r+yBR) & 0xF8);
+ rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F)
+ | ((LIMIT(g+yBR) << 3) & 0xE0);
+ rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07)
+ | (LIMIT(r+yBR) & 0xF8);
}
}
+/**********************************************************************
+ *
+ * Raw data parsing
+ *
+ **********************************************************************/
+
+/* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the
+ * array at pOut is specified by w.
+ */
+static inline void
+ov511_make_8x8(unsigned char *pIn, unsigned char *pOut, int w)
+{
+ unsigned char *pOut1 = pOut;
+ int x, y;
+
+ for (y = 0; y < 8; y++) {
+ pOut1 = pOut;
+ for (x = 0; x < 8; x++) {
+ *pOut1++ = *pIn++;
+ }
+ pOut += w;
+ }
+
+}
+
/*
- * For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.
+ * For RAW BW (YUV400) images, data shows up in 256 byte segments.
+ * The segments represent 4 squares of 8x8 pixels as follows:
+ *
+ * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199
+ * 8 9 ... 15 72 73 ... 79 200 201 ... 207
+ * ... ... ...
+ * 56 57 ... 63 120 121 ... 127 248 249 ... 255
+ *
+ */
+static void
+yuv400raw_to_yuv400p(struct ov511_frame *frame,
+ unsigned char *pIn0, unsigned char *pOut0)
+{
+ int x, y;
+ unsigned char *pIn, *pOut, *pOutLine;
+
+ /* Copy Y */
+ pIn = pIn0;
+ pOutLine = pOut0;
+ for (y = 0; y < frame->rawheight - 1; y += 8) {
+ pOut = pOutLine;
+ for (x = 0; x < frame->rawwidth - 1; x += 8) {
+ ov511_make_8x8(pIn, pOut, frame->rawwidth);
+ pIn += 64;
+ pOut += 8;
+ }
+ pOutLine += 8 * frame->rawwidth;
+ }
+}
+
+/*
+ * For YUV4:2:0 images, the data shows up in 384 byte segments.
* The first 64 bytes of each segment are U, the next 64 are V. The U and
* V are arranged as follows:
*
@@ -1239,7 +3377,9 @@ ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
* 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255
*
* Note that the U and V data in one segment represents a 16 x 16 pixel
- * area, but the Y data represents a 32 x 8 pixel area.
+ * area, but the Y data represents a 32 x 8 pixel area. If the width is not an
+ * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the
+ * next horizontal stripe.
*
* If dumppix module param is set, _parse_data just dumps the incoming segments,
* verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
@@ -1248,391 +3388,504 @@ ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
* this data is scrambled.
*/
-#define HDIV 8
-#define WDIV (256/HDIV)
-
+/* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0.
+ *
+ * FIXME: Currently only handles width and height that are multiples of 16
+ */
static void
-ov511_parse_gbr422_to_rgb24(unsigned char *pIn0, unsigned char *pOut0,
- int iOutY, int iOutUV, int iHalf, int iWidth)
+yuv420raw_to_yuv420p(struct ov511_frame *frame,
+ unsigned char *pIn0, unsigned char *pOut0)
{
- int k, l, m;
- unsigned char *pIn;
- unsigned char *pOut, *pOut1;
+ int k, x, y;
+ unsigned char *pIn, *pOut, *pOutLine;
+ const unsigned int a = frame->rawwidth * frame->rawheight;
+ const unsigned int w = frame->rawwidth / 2;
+ /* Copy U and V */
pIn = pIn0;
- pOut = pOut0 + iOutUV + (force_rgb ? 2 : 0);
-
- for (k = 0; k < 8; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- *pOut1 = *(pOut1 + 3) = *(pOut1 + iWidth*3) =
- *(pOut1 + iWidth*3 + 3) = *pIn++;
- pOut1 += 6;
+ pOutLine = pOut0 + a;
+ for (y = 0; y < frame->rawheight - 1; y += 16) {
+ pOut = pOutLine;
+ for (x = 0; x < frame->rawwidth - 1; x += 16) {
+ ov511_make_8x8(pIn, pOut, w);
+ ov511_make_8x8(pIn + 64, pOut + a/4, w);
+ pIn += 384;
+ pOut += 8;
}
- pOut += iWidth*3*2;
- }
-
- pIn = pIn0 + 64;
- pOut = pOut0 + iOutUV + (force_rgb ? 0 : 2);
- for (k = 0; k < 8; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- *pOut1 = *(pOut1 + 3) = *(pOut1 + iWidth*3) =
- *(pOut1 + iWidth*3 + 3) = *pIn++;
- pOut1 += 6;
- }
- pOut += iWidth*3*2;
+ pOutLine += 8 * w;
}
+ /* Copy Y */
pIn = pIn0 + 128;
- pOut = pOut0 + iOutY + 1;
- for (k = 0; k < 4; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- for (m = 0; m < 8; m++) {
- *pOut1 = *pIn++;
- pOut1 += 3;
+ pOutLine = pOut0;
+ k = 0;
+ for (y = 0; y < frame->rawheight - 1; y += 8) {
+ pOut = pOutLine;
+ for (x = 0; x < frame->rawwidth - 1; x += 8) {
+ ov511_make_8x8(pIn, pOut, frame->rawwidth);
+ pIn += 64;
+ pOut += 8;
+ if ((++k) > 3) {
+ k = 0;
+ pIn += 128;
}
- pOut1 += (iWidth - 8) * 3;
}
- pOut += 8 * 3;
+ pOutLine += 8 * frame->rawwidth;
}
}
-static void
-ov511_parse_yuv420_to_rgb(unsigned char *pIn0, unsigned char *pOut0,
- int iOutY, int iOutUV, int iHalf, int iWidth, int bits)
-{
- int k, l, m;
- int bytes = bits >> 3;
- unsigned char *pIn;
- unsigned char *pOut, *pOut1;
-
- /* Just copy the Y's if in the first stripe */
- if (!iHalf) {
- pIn = pIn0 + 128;
- pOut = pOut0 + iOutY;
- for (k = 0; k < 4; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- for (m = 0; m < 8; m++) {
- *pOut1 = *pIn++;
- pOut1 += bytes;
- }
- pOut1 += (iWidth - 8) * bytes;
- }
- pOut += 8 * bytes;
- }
+/*
+ * fixFrameRGBoffset--
+ * My camera seems to return the red channel about 1 pixel
+ * low, and the blue channel about 1 pixel high. After YUV->RGB
+ * conversion, we can correct this easily. OSL 2/24/2000.
+ */
+static void
+fixFrameRGBoffset(struct ov511_frame *frame)
+{
+ int x, y;
+ int rowBytes = frame->width*3, w = frame->width;
+ unsigned char *rgb = frame->data;
+ const int shift = 1; /* Distance to shift pixels by, vertically */
+
+ /* Don't bother with little images */
+ if (frame->width < 400)
+ return;
+
+ /* This only works with RGB24 */
+ if (frame->format != VIDEO_PALETTE_RGB24)
+ return;
+
+ /* Shift red channel up */
+ for (y = shift; y < frame->height; y++) {
+ int lp = (y-shift)*rowBytes; /* Previous line offset */
+ int lc = y*rowBytes; /* Current line offset */
+ for (x = 0; x < w; x++)
+ rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
}
- /* Use the first half of VUs to calculate value */
- pIn = pIn0;
- pOut = pOut0 + iOutUV;
- for (l = 0; l < 4; l++) {
- for (m=0; m<8; m++) {
- int y00 = *(pOut);
- int y01 = *(pOut+bytes);
- int y10 = *(pOut+iWidth*bytes);
- int y11 = *(pOut+iWidth*bytes+bytes);
- int v = *(pIn+64) - 128;
- int u = *pIn++ - 128;
- ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth,
- pOut, bits);
- pOut += 2 * bytes;
- }
- pOut += (iWidth*2 - 16) * bytes;
- }
-
- /* Just copy the other UV rows */
- for (l = 0; l < 4; l++) {
- for (m = 0; m < 8; m++) {
- *pOut++ = *(pIn + 64);
- *pOut = *pIn++;
- pOut += 2 * bytes - 1;
- }
- pOut += (iWidth*2 - 16) * bytes;
- }
-
- /* Calculate values if it's the second half */
- if (iHalf) {
- pIn = pIn0 + 128;
- pOut = pOut0 + iOutY;
- for (k = 0; k < 4; k++) {
- pOut1 = pOut;
- for (l=0; l<4; l++) {
- for (m=0; m<4; m++) {
- int y10 = *(pIn+8);
- int y00 = *pIn++;
- int y11 = *(pIn+8);
- int y01 = *pIn++;
- int v = *pOut1 - 128;
- int u = *(pOut1+1) - 128;
- ov511_move_420_block(y00, y01, y10,
- y11, u, v, iWidth, pOut1, bits);
- pOut1 += 2 * bytes;
- }
- pOut1 += (iWidth*2 - 8) * bytes;
- pIn += 8;
- }
- pOut += 8 * bytes;
- }
+ /* Shift blue channel down */
+ for (y = frame->height-shift-1; y >= 0; y--) {
+ int ln = (y + shift) * rowBytes; /* Next line offset */
+ int lc = y * rowBytes; /* Current line offset */
+ for (x = 0; x < w; x++)
+ rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
}
}
-static void
-ov511_dumppix(unsigned char *pIn0, unsigned char *pOut0,
- int iOutY, int iOutUV, int iHalf, int iWidth)
-{
- int i, j, k;
- unsigned char *pIn, *pOut, *pOut1;
-
- switch (dumppix) {
- case 1: /* Just dump YUV data straight out for debug */
- pOut0 += iOutY;
- for (i = 0; i < HDIV; i++) {
- for (j = 0; j < WDIV; j++) {
- *pOut0++ = *pIn0++;
- *pOut0++ = *pIn0++;
- *pOut0++ = *pIn0++;
- }
- pOut0 += (iWidth - WDIV) * 3;
+/**********************************************************************
+ *
+ * Decompression
+ *
+ **********************************************************************/
+
+/* Chooses a decompression module, locks it, and sets ov511->decomp_ops
+ * accordingly. Returns -ENXIO if decompressor is not available, otherwise
+ * returns 0 if no other error.
+ */
+static int
+ov51x_request_decompressor(struct usb_ov511 *ov511)
+{
+ if (!ov511)
+ return -ENODEV;
+
+ if (ov511->decomp_ops) {
+ err("ERROR: Decompressor already requested!");
+ return -EINVAL;
+ }
+
+ lock_kernel();
+
+ /* Try to get MMX, and fall back on no-MMX if necessary */
+ if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS) {
+ if (ov511_mmx_decomp_ops) {
+ PDEBUG(3, "Using OV511 MMX decompressor");
+ ov511->decomp_ops = ov511_mmx_decomp_ops;
+ } else if (ov511_decomp_ops) {
+ PDEBUG(3, "Using OV511 decompressor");
+ ov511->decomp_ops = ov511_decomp_ops;
+ } else {
+ err("No decompressor available");
}
- break;
- case 2: /* This converts the Y data to "black-and-white" RGB data */
- /* Useful for experimenting with compression */
- pIn = pIn0 + 128;
- pOut = pOut0 + iOutY;
- for (i = 0; i < 4; i++) {
- pOut1 = pOut;
- for (j = 0; j < 8; j++) {
- for (k = 0; k < 8; k++) {
- *pOut1++ = *pIn;
- *pOut1++ = *pIn;
- *pOut1++ = *pIn++;
- }
- pOut1 += (iWidth - 8) * 3;
- }
- pOut += 8 * 3;
+ } else if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS) {
+ if (ov518_mmx_decomp_ops) {
+ PDEBUG(3, "Using OV518 MMX decompressor");
+ ov511->decomp_ops = ov518_mmx_decomp_ops;
+ } else if (ov518_decomp_ops) {
+ PDEBUG(3, "Using OV518 decompressor");
+ ov511->decomp_ops = ov518_decomp_ops;
+ } else {
+ err("No decompressor available");
}
- break;
- case 3: /* This will dump only the Y channel data stream as-is */
- pIn = pIn0 + 128;
- pOut = pOut0 + output_offset;
- for (i = 0; i < 256; i++) {
- *pOut++ = *pIn;
- *pOut++ = *pIn;
- *pOut++ = *pIn++;
- output_offset += 3;
+ } else {
+ err("Unknown bridge");
+ }
+
+ if (ov511->decomp_ops) {
+ if (!ov511->decomp_ops->decomp_lock) {
+ ov511->decomp_ops = NULL;
+ unlock_kernel();
+ return -ENOSYS;
}
- break;
- } /* End switch (dumppix) */
+ ov511->decomp_ops->decomp_lock();
+ unlock_kernel();
+ return 0;
+ } else {
+ unlock_kernel();
+ return -ENXIO;
+ }
}
-/* This converts YUV420 segments to YUYV */
-static void
-ov511_parse_data_yuv422(unsigned char *pIn0, unsigned char *pOut0,
- int iOutY, int iOutUV, int iWidth)
+/* Unlocks decompression module and nulls ov511->decomp_ops. Safe to call even
+ * if ov511->decomp_ops is NULL.
+ */
+static void
+ov51x_release_decompressor(struct usb_ov511 *ov511)
{
- int k, l, m;
- unsigned char *pIn, *pOut, *pOut1;
+ int released = 0; /* Did we actually do anything? */
+
+ if (!ov511)
+ return;
+
+ lock_kernel();
+
+ if (ov511->decomp_ops && ov511->decomp_ops->decomp_unlock) {
+ ov511->decomp_ops->decomp_unlock();
+ released = 1;
+ }
+
+ ov511->decomp_ops = NULL;
+
+ unlock_kernel();
+
+ if (released)
+ PDEBUG(3, "Decompressor released");
+}
+
+static void
+ov51x_decompress(struct usb_ov511 *ov511, struct ov511_frame *frame,
+ unsigned char *pIn0, unsigned char *pOut0)
+{
+ if (!ov511->decomp_ops)
+ if (ov51x_request_decompressor(ov511))
+ return;
+
+ PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd);
+
+ if (frame->format == VIDEO_PALETTE_GREY
+ && ov511->decomp_ops->decomp_400) {
+ int ret = ov511->decomp_ops->decomp_400(
+ pIn0,
+ pOut0,
+ frame->rawwidth,
+ frame->rawheight,
+ frame->bytes_recvd);
+ PDEBUG(4, "DEBUG: decomp_400 returned %d", ret);
+ } else if (ov511->decomp_ops->decomp_420) {
+ int ret = ov511->decomp_ops->decomp_420(
+ pIn0,
+ pOut0,
+ frame->rawwidth,
+ frame->rawheight,
+ frame->bytes_recvd);
+ PDEBUG(4, "DEBUG: decomp_420 returned %d", ret);
+ } else {
+ err("Decompressor does not support this format");
+ }
+}
+
+/**********************************************************************
+ *
+ * Format conversion
+ *
+ **********************************************************************/
+
+/* Converts from planar YUV420 to RGB24. */
+static void
+yuv420p_to_rgb(struct ov511_frame *frame,
+ unsigned char *pIn0, unsigned char *pOut0, int bits)
+{
+ const int numpix = frame->width * frame->height;
+ const int bytes = bits >> 3;
+ int i, j, y00, y01, y10, y11, u, v;
+ unsigned char *pY = pIn0;
+ unsigned char *pU = pY + numpix;
+ unsigned char *pV = pU + numpix / 4;
+ unsigned char *pOut = pOut0;
+
+ for (j = 0; j <= frame->height - 2; j += 2) {
+ for (i = 0; i <= frame->width - 2; i += 2) {
+ y00 = *pY;
+ y01 = *(pY + 1);
+ y10 = *(pY + frame->width);
+ y11 = *(pY + frame->width + 1);
+ u = (*pU++) - 128;
+ v = (*pV++) - 128;
+
+ ov511_move_420_block(y00, y01, y10, y11, u, v,
+ frame->width, pOut, bits);
+
+ pY += 2;
+ pOut += 2 * bytes;
- pIn = pIn0 + 128;
- pOut = pOut0 + iOutY;
- for (k = 0; k < 4; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- for (m = 0; m < 8; m++) {
- *pOut1 = (*pIn++);
- pOut1 += 2;
- }
- pOut1 += (iWidth - 8) * 2;
}
- pOut += 8 * 2;
+ pY += frame->width;
+ pOut += frame->width * bytes;
}
+}
- pIn = pIn0;
- pOut = pOut0 + iOutUV + 1;
- for (l = 0; l < 8; l++) {
- for (m=0; m<8; m++) {
- int v = *(pIn+64);
- int u = *pIn++;
+/* Converts from planar YUV420 to YUV422 (YUYV). */
+static void
+yuv420p_to_yuv422(struct ov511_frame *frame,
+ unsigned char *pIn0, unsigned char *pOut0)
+{
+ const int numpix = frame->width * frame->height;
+ int i, j;
+ unsigned char *pY = pIn0;
+ unsigned char *pU = pY + numpix;
+ unsigned char *pV = pU + numpix / 4;
+ unsigned char *pOut = pOut0;
+
+ for (i = 0; i < numpix; i++) {
+ *pOut = *(pY + i);
+ pOut += 2;
+ }
+
+ pOut = pOut0 + 1;
+ for (j = 0; j <= frame->height - 2 ; j += 2) {
+ for (i = 0; i <= frame->width - 2; i += 2) {
+ int u = *pU++;
+ int v = *pV++;
*pOut = u;
*(pOut+2) = v;
- *(pOut+iWidth) = u;
- *(pOut+iWidth+2) = v;
+ *(pOut+frame->width*2) = u;
+ *(pOut+frame->width*2+2) = v;
pOut += 4;
}
- pOut += (iWidth*4 - 32);
+ pOut += (frame->width * 2);
}
}
+/* Converts pData from planar YUV420 to planar YUV422 **in place**. */
static void
-ov511_parse_data_yuv420(unsigned char *pIn0, unsigned char *pOut0,
- int iOutY, int iOutUV, int iWidth, int iHeight)
+yuv420p_to_yuv422p(struct ov511_frame *frame, unsigned char *pData)
{
- int k, l, m;
- unsigned char *pIn;
- unsigned char *pOut, *pOut1;
- unsigned a = iWidth * iHeight;
- unsigned w = iWidth / 2;
-
- pIn = pIn0;
- pOut = pOut0 + iOutUV + a;
- for (k = 0; k < 8; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) *pOut1++ = *pIn++;
- pOut += w;
- }
-
- pIn = pIn0 + 64;
- pOut = pOut0 + iOutUV + a + a/4;
- for (k = 0; k < 8; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) *pOut1++ = *pIn++;
+ const int numpix = frame->width * frame->height;
+ const int w = frame->width;
+ int j;
+ unsigned char *pIn, *pOut;
+
+ /* Clear U and V */
+ memset(pData + numpix + numpix / 2, 127, numpix / 2);
+
+ /* Convert V starting from beginning and working forward */
+ pIn = pData + numpix + numpix / 4;
+ pOut = pData + numpix +numpix / 2;
+ for (j = 0; j <= frame->height - 2; j += 2) {
+ memmove(pOut, pIn, w/2);
+ memmove(pOut + w/2, pIn, w/2);
+ pIn += w/2;
pOut += w;
}
- pIn = pIn0 + 128;
- pOut = pOut0 + iOutY;
- for (k = 0; k < 4; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- for (m = 0; m < 8; m++)
- *pOut1++ =*pIn++;
- pOut1 += iWidth - 8;
- }
- pOut += 8;
+ /* Convert U, starting from end and working backward */
+ pIn = pData + numpix + numpix / 4;
+ pOut = pData + numpix + numpix / 2;
+ for (j = 0; j <= frame->height - 2; j += 2) {
+ pIn -= w/2;
+ pOut -= w;
+ memmove(pOut, pIn, w/2);
+ memmove(pOut + w/2, pIn, w/2);
}
}
+/* Fuses even and odd fields together, and doubles width.
+ * INPUT: an odd field followed by an even field at pIn0, in YUV planar format
+ * OUTPUT: a normal YUV planar image, with correct aspect ratio
+ */
static void
-ov511_parse_data_yuv422p(unsigned char *pIn0, unsigned char *pOut0,
- int iOutY, int iOutUV, int iWidth, int iHeight)
+deinterlace(struct ov511_frame *frame, int rawformat,
+ unsigned char *pIn0, unsigned char *pOut0)
{
- int k, l, m;
- unsigned char *pIn;
- unsigned char *pOut, *pOut1;
- unsigned a = iWidth * iHeight;
- unsigned w = iWidth / 2;
+ const int fieldheight = frame->rawheight / 2;
+ const int fieldpix = fieldheight * frame->rawwidth;
+ const int w = frame->width;
+ int x, y;
+ unsigned char *pInEven, *pInOdd, *pOut;
- pIn = pIn0;
- pOut = pOut0 + iOutUV + a;
- for (k = 0; k < 8; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- *pOut1 = *(pOut1 + w) = *pIn++;
- pOut1++;
- }
- pOut += iWidth;
+ PDEBUG(5, "fieldheight=%d", fieldheight);
+
+ if (frame->rawheight != frame->height) {
+ err("invalid height");
+ return;
}
- pIn = pIn0 + 64;
- pOut = pOut0 + iOutUV + a + a/2;
- for (k = 0; k < 8; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- *pOut1 = *(pOut1 + w) = *pIn++;
- pOut1++;
- }
- pOut += iWidth;
+ if ((frame->rawwidth * 2) != frame->width) {
+ err("invalid width");
+ return;
}
- pIn = pIn0 + 128;
- pOut = pOut0 + iOutY;
- for (k = 0; k < 4; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- for (m = 0; m < 8; m++)
- *pOut1++ =*pIn++;
- pOut1 += iWidth - 8;
+ /* Y */
+ pInOdd = pIn0;
+ pInEven = pInOdd + fieldpix;
+ pOut = pOut0;
+ for (y = 0; y < fieldheight; y++) {
+ for (x = 0; x < frame->rawwidth; x++) {
+ *pOut = *pInEven;
+ *(pOut+1) = *pInEven++;
+ *(pOut+w) = *pInOdd;
+ *(pOut+w+1) = *pInOdd++;
+ pOut += 2;
}
- pOut += 8;
+ pOut += w;
}
-}
-/*
- * For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
- * The segments represent 4 squares of 8x8 pixels as follows:
- *
- * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199
- * 8 9 ... 15 72 73 ... 79 200 201 ... 207
- * ... ... ...
- * 56 57 ... 63 120 121 ... 127 248 249 ... 255
- *
- */
-static void
-ov511_parse_data_grey(unsigned char *pIn0, unsigned char *pOut0,
- int iOutY, int iWidth)
-{
- int k, l, m;
- unsigned char *pIn;
- unsigned char *pOut, *pOut1;
-
- pIn = pIn0;
- pOut = pOut0 + iOutY;
- for (k = 0; k < 4; k++) {
- pOut1 = pOut;
- for (l = 0; l < 8; l++) {
- for (m = 0; m < 8; m++) {
- *pOut1++ = *pIn++;
+ if (rawformat == RAWFMT_YUV420) {
+ /* U */
+ pInOdd = pIn0 + fieldpix * 2;
+ pInEven = pInOdd + fieldpix / 4;
+ for (y = 0; y < fieldheight / 2; y++) {
+ for (x = 0; x < frame->rawwidth / 2; x++) {
+ *pOut = *pInEven;
+ *(pOut+1) = *pInEven++;
+ *(pOut+w/2) = *pInOdd;
+ *(pOut+w/2+1) = *pInOdd++;
+ pOut += 2;
+ }
+ pOut += w/2;
+ }
+ /* V */
+ pInOdd = pIn0 + fieldpix * 2 + fieldpix / 2;
+ pInEven = pInOdd + fieldpix / 4;
+ for (y = 0; y < fieldheight / 2; y++) {
+ for (x = 0; x < frame->rawwidth / 2; x++) {
+ *pOut = *pInEven;
+ *(pOut+1) = *pInEven++;
+ *(pOut+w/2) = *pInOdd;
+ *(pOut+w/2+1) = *pInOdd++;
+ pOut += 2;
}
- pOut1 += iWidth - 8;
+ pOut += w/2;
}
- pOut += 8;
}
}
-/*
- * fixFrameRGBoffset--
- * My camera seems to return the red channel about 1 pixel
- * low, and the blue channel about 1 pixel high. After YUV->RGB
- * conversion, we can correct this easily. OSL 2/24/2000.
+/* Post-processes the specified frame. This consists of:
+ * 1. Decompress frame, if necessary
+ * 2. Deinterlace frame and scale to proper size, if necessary
+ * 3. Convert from YUV planar to destination format, if necessary
+ * 4. Fix the RGB offset, if necessary
*/
-static void fixFrameRGBoffset(struct ov511_frame *frame)
+static void
+ov511_postprocess(struct usb_ov511 *ov511, struct ov511_frame *frame)
{
- int x, y;
- int rowBytes = frame->width*3, w = frame->width;
- unsigned char *rgb = frame->data;
- const int shift = 1; /* Distance to shift pixels by, vertically */
+ if (dumppix) {
+ memset(frame->data, 0,
+ MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight));
+ PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd);
+ memmove(frame->data, frame->rawdata, frame->bytes_recvd);
+ return;
+ }
+
+ /* YUV400 must be handled separately */
+ if (frame->format == VIDEO_PALETTE_GREY) {
+ /* Deinterlace frame, if necessary */
+ if (ov511->sensor == SEN_SAA7111A && frame->rawheight == 480) {
+ if (frame->compressed)
+ ov51x_decompress(ov511, frame, frame->rawdata,
+ frame->tempdata);
+ else
+ yuv400raw_to_yuv400p(frame, frame->rawdata,
+ frame->tempdata);
+
+ deinterlace(frame, RAWFMT_YUV400, frame->tempdata,
+ frame->data);
+ } else {
+ if (frame->compressed)
+ ov51x_decompress(ov511, frame, frame->rawdata,
+ frame->data);
+ else
+ yuv400raw_to_yuv400p(frame, frame->rawdata,
+ frame->data);
+ }
- /* Don't bother with little images */
- if (frame->width < 400)
return;
+ }
- /* Shift red channel up */
- for (y = shift; y < frame->height; y++) {
- int lp = (y-shift)*rowBytes; /* Previous line offset */
- int lc = y*rowBytes; /* Current line offset */
- for (x = 0; x < w; x++)
- rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
+ /* Process frame->data to frame->rawdata */
+ if (frame->compressed)
+ ov51x_decompress(ov511, frame, frame->rawdata, frame->tempdata);
+ else
+ yuv420raw_to_yuv420p(frame, frame->rawdata, frame->tempdata);
+
+ /* Deinterlace frame, if necessary */
+ if (ov511->sensor == SEN_SAA7111A && frame->rawheight == 480) {
+ memmove(frame->rawdata, frame->tempdata,
+ MAX_RAW_DATA_SIZE(frame->width, frame->height));
+ deinterlace(frame, RAWFMT_YUV420, frame->rawdata,
+ frame->tempdata);
}
- /* Shift blue channel down */
- for (y = frame->height-shift-1; y >= 0; y--) {
- int ln = (y + shift) * rowBytes; /* Next line offset */
- int lc = y * rowBytes; /* Current line offset */
- for (x = 0; x < w; x++)
- rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
+ /* Frame should be (width x height) and not (rawwidth x rawheight) at
+ * this point. */
+
+#if 0
+ /* Clear output buffer for testing purposes */
+ memset(frame->data, 0, MAX_DATA_SIZE(frame->width, frame->height));
+#endif
+
+ /* Process frame->tempdata to frame->data */
+ switch (frame->format) {
+ case VIDEO_PALETTE_RGB565:
+ yuv420p_to_rgb(frame, frame->tempdata, frame->data, 16);
+ break;
+ case VIDEO_PALETTE_RGB24:
+ yuv420p_to_rgb(frame, frame->tempdata, frame->data, 24);
+ break;
+ case VIDEO_PALETTE_YUV422:
+ case VIDEO_PALETTE_YUYV:
+ yuv420p_to_yuv422(frame, frame->tempdata, frame->data);
+ break;
+ case VIDEO_PALETTE_YUV420:
+ case VIDEO_PALETTE_YUV420P:
+ memmove(frame->data, frame->tempdata,
+ MAX_RAW_DATA_SIZE(frame->width, frame->height));
+ break;
+ case VIDEO_PALETTE_YUV422P:
+ /* Data is converted in place, so copy it in advance */
+ memmove(frame->data, frame->tempdata,
+ MAX_RAW_DATA_SIZE(frame->width, frame->height));
+
+ yuv420p_to_yuv422p(frame, frame->data);
+ break;
+ default:
+ err("Cannot convert data to this format");
}
+
+ if (fix_rgb_offset)
+ fixFrameRGBoffset(frame);
}
/**********************************************************************
*
- * OV511 data transfer, IRQ handler
+ * OV51x data transfer, IRQ handler
*
**********************************************************************/
-static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
+static int
+ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
{
unsigned char *cdata;
- int i, totlen = 0;
- int aPackNum[10];
+ int data_size, num, offset, i, totlen = 0;
+ int aPackNum[FRAMES_PER_DESC];
struct ov511_frame *frame;
- unsigned char *pData;
- int iPix;
+ struct timeval *ts;
+
+ PDEBUG(5, "Moving %d packets", urb->number_of_packets);
- PDEBUG (4, "Moving %d packets", urb->number_of_packets);
+ data_size = ov511->packet_size - 1;
for (i = 0; i < urb->number_of_packets; i++) {
int n = urb->iso_frame_desc[i].actual_length;
@@ -1652,44 +3905,65 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
frame = &ov511->frame[ov511->curframe];
-
+
/* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
* byte non-zero. The EOF packet has image width/height in the
- * 10th and 11th packets. The 9th bit is given as follows:
+ * 10th and 11th bytes. The 9th byte is given as follows:
*
* bit 7: EOF
* 6: compression enabled
* 5: 422/420/400 modes
* 4: 422/420/400 modes
* 3: 1
- * 2: snapshot bottom on
+ * 2: snapshot button on
* 1: snapshot frame
* 0: even/odd field
*/
+ if (printph) {
+ info("packet header (%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
+ cdata[ov511->packet_size - 1],
+ cdata[0], cdata[1], cdata[2], cdata[3], cdata[4], cdata[5],
+ cdata[6], cdata[7], cdata[8], cdata[9], cdata[10], cdata[11]);
+ }
+
/* Check for SOF/EOF packet */
- if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] |
+ if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] |
cdata[4] | cdata[5] | cdata[6] | cdata[7]) ||
(~cdata[8] & 0x08))
goto check_middle;
/* Frame end */
if (cdata[8] & 0x80) {
- struct timeval *ts;
-
- ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE);
- do_gettimeofday (ts);
-
- PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d",
- ov511->curframe, (int)(cdata[ov511->packet_size - 1]),
- (int)(cdata[9]), (int)(cdata[10]));
+ ts = (struct timeval *)(frame->data
+ + MAX_FRAME_SIZE(ov511->maxwidth, ov511->maxheight));
+ do_gettimeofday(ts);
+
+ /* Get the actual frame size from the EOF header */
+ frame->rawwidth = ((int)(cdata[9]) + 1) * 8;
+ frame->rawheight = ((int)(cdata[10]) + 1) * 8;
+
+ PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d, recvd=%d",
+ ov511->curframe,
+ (int)(cdata[ov511->packet_size - 1]),
+ frame->rawwidth,
+ frame->rawheight,
+ frame->bytes_recvd);
+
+ /* Validate the header data */
+ RESTRICT_TO_RANGE(frame->rawwidth, ov511->minwidth, ov511->maxwidth);
+ RESTRICT_TO_RANGE(frame->rawheight, ov511->minheight, ov511->maxheight);
+
+ /* Don't allow byte count to exceed buffer size */
+ RESTRICT_TO_RANGE(frame->bytes_recvd,
+ 8,
+ MAX_RAW_DATA_SIZE(ov511->maxwidth,
+ ov511->maxheight));
if (frame->scanstate == STATE_LINES) {
int iFrameNext;
- if (fix_rgb_offset)
- fixFrameRGBoffset(frame);
- frame->grabstate = FRAME_DONE;
+ frame->grabstate = FRAME_DONE; // FIXME: Is this right?
if (waitqueue_active(&frame->wq)) {
frame->grabstate = FRAME_DONE;
@@ -1713,6 +3987,8 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
ov511->curframe = -1;
}
+ } else {
+ PDEBUG(5, "Frame done, but not scanning");
}
/* Image corruption caused by misplaced frame->segment = 0
* fixed by carlosf@conectiva.com.br
@@ -1721,13 +3997,6 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
/* Frame start */
PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
-#if 0
- /* Make sure no previous data carries over; necessary
- * for compression experimentation */
- memset(frame->data, 0, MAX_DATA_SIZE);
-#endif
- output_offset = 0;
-
/* Check to see if it's a snapshot frame */
/* FIXME?? Should the snapshot reset go here? Performance? */
if (cdata[8] & 0x02) {
@@ -1736,129 +4005,324 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
}
frame->scanstate = STATE_LINES;
- frame->segment = 0;
+ frame->bytes_recvd = 0;
+ frame->compressed = cdata[8] & 0x40;
}
check_middle:
/* Are we in a frame? */
- if (frame->scanstate != STATE_LINES)
+ if (frame->scanstate != STATE_LINES) {
+ PDEBUG(5, "Not in a frame; packet skipped");
continue;
+ }
- /* Deal with leftover from last segment, if any */
- if (frame->segment) {
- pData = ov511->scratch;
- iPix = -ov511->scratchlen;
- memmove(pData + ov511->scratchlen, cdata,
- iPix+frame->segsize);
- } else {
- pData = &cdata[iPix = 9];
- }
-
- /* Parse the segments */
- while (iPix <= (ov511->packet_size - 1) - frame->segsize &&
- frame->segment < frame->width * frame->height / 256) {
- int iSegY, iSegUV;
- int iY, jY, iUV, jUV;
- int iOutY, iOutYP, iOutUV, iOutUVP;
- unsigned char *pOut;
-
- iSegY = iSegUV = frame->segment;
- pOut = frame->data;
- frame->segment++;
- iPix += frame->segsize;
-
- /* Handle subwindow */
- if (frame->sub_flag) {
- int iSeg1;
-
- iSeg1 = iSegY / (ov511->subw / 32);
- iSeg1 *= frame->width / 32;
- iSegY = iSeg1 + (iSegY % (ov511->subw / 32));
- if (iSegY >= frame->width * ov511->subh / 256)
- break;
-
- iSeg1 = iSegUV / (ov511->subw / 16);
- iSeg1 *= frame->width / 16;
- iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16));
-
- pOut += (ov511->subx + ov511->suby * frame->width) *
- (frame->depth >> 3);
+#if 0
+ /* Skip packet if first 9 bytes are zero. These are common, so
+ * we use a less expensive test here instead of later */
+ if (frame->compressed) {
+ int b, skip = 1;
+
+ for (b = 0; b < 9; b++) {
+ if (cdata[b])
+ skip=0;
}
- /*
- * i counts segment lines
- * j counts segment columns
- * iOut is the offset (in bytes) of the upper left corner
- */
- iY = iSegY / (frame->width / WDIV);
- jY = iSegY - iY * (frame->width / WDIV);
- iOutYP = iY*HDIV*frame->width + jY*WDIV;
- iOutY = iOutYP * (frame->depth >> 3);
- iUV = iSegUV / (frame->width / WDIV * 2);
- jUV = iSegUV - iUV * (frame->width / WDIV * 2);
- iOutUVP = iUV*HDIV*2*frame->width + jUV*WDIV/2;
- iOutUV = iOutUVP * (frame->depth >> 3);
-
- switch (frame->format) {
- case VIDEO_PALETTE_GREY:
- ov511_parse_data_grey (pData, pOut, iOutY, frame->width);
- break;
- case VIDEO_PALETTE_RGB24:
- if (dumppix)
- ov511_dumppix(pData, pOut, iOutY, iOutUV,
- iY & 1, frame->width);
- else if (sensor_gbr)
- ov511_parse_gbr422_to_rgb24(pData, pOut, iOutY, iOutUV,
- iY & 1, frame->width);
- else
- ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,
- iY & 1, frame->width, 24);
- break;
- case VIDEO_PALETTE_RGB565:
- ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,
- iY & 1, frame->width, 16);
- break;
- case VIDEO_PALETTE_YUV422:
- case VIDEO_PALETTE_YUYV:
- ov511_parse_data_yuv422(pData, pOut, iOutY, iOutUV, frame->width);
- break;
- case VIDEO_PALETTE_YUV420:
- ov511_parse_data_yuv420 (pData, pOut, iOutYP, iUV*HDIV*frame->width/2 + jUV*WDIV/4,
- frame->width, frame->height);
- break;
- case VIDEO_PALETTE_YUV422P:
- ov511_parse_data_yuv422p (pData, pOut, iOutYP, iOutUVP/2,
- frame->width, frame->height);
- break;
- default:
- err("Unsupported format: %d", frame->format);
+ if (skip) {
+ PDEBUG(5, "Skipping packet (all zero)");
+ continue;
}
-
- pData = &cdata[iPix];
}
+#endif
+ /* If frame start, skip header */
+ if (frame->bytes_recvd == 0)
+ offset = 9;
+ else
+ offset = 0;
+
+ num = n - offset - 1;
- /* Save extra data for next time */
- if (frame->segment < frame->width * frame->height / 256) {
- ov511->scratchlen = (ov511->packet_size - 1) - iPix;
- if (ov511->scratchlen < frame->segsize)
- memmove(ov511->scratch, pData, ov511->scratchlen);
+ /* Dump all data exactly as received */
+ if (dumppix == 2) {
+ frame->bytes_recvd += n - 1;
+ if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight))
+ memmove(frame->rawdata + frame->bytes_recvd - (n - 1),
+ &cdata[0], n - 1);
else
- ov511->scratchlen = 0;
+ PDEBUG(3, "Raw data buffer overrun!! (%d)",
+ frame->bytes_recvd
+ - MAX_RAW_DATA_SIZE(ov511->maxwidth,
+ ov511->maxheight));
+ } else if (!frame->compressed && !remove_zeros) {
+ frame->bytes_recvd += num;
+ if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight))
+ memmove(frame->rawdata + frame->bytes_recvd - num,
+ &cdata[offset], num);
+ else
+ PDEBUG(3, "Raw data buffer overrun!! (%d)",
+ frame->bytes_recvd
+ - MAX_RAW_DATA_SIZE(ov511->maxwidth,
+ ov511->maxheight));
+ } else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */
+ int b, in = 0, allzero, copied=0;
+ if (offset) {
+ frame->bytes_recvd += 32 - offset; // Bytes out
+ memmove(frame->rawdata,
+ &cdata[offset], 32 - offset);
+ in += 32;
+ }
+
+ while (in < n - 1) {
+ allzero = 1;
+ for (b = 0; b < 32; b++) {
+ if (cdata[in + b]) {
+ allzero = 0;
+ break;
+ }
+ }
+
+ if (allzero) {
+ /* Don't copy it */
+ } else {
+ if (frame->bytes_recvd + copied + 32
+ <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight)) {
+ memmove(frame->rawdata + frame->bytes_recvd + copied,
+ &cdata[in], 32);
+ copied += 32;
+ } else {
+ PDEBUG(3, "Raw data buffer overrun!!");
+ }
+ }
+ in += 32;
+ }
+
+ frame->bytes_recvd += copied;
}
+
}
PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d",
- aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
- aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
+ aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
+ aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
return totlen;
}
-static void ov511_isoc_irq(struct urb *urb)
+static int
+ov518_move_data(struct usb_ov511 *ov511, urb_t *urb)
+{
+ unsigned char *cdata;
+ int i, data_size, totlen = 0;
+ struct ov511_frame *frame;
+ struct timeval *ts;
+
+ PDEBUG(5, "Moving %d packets", urb->number_of_packets);
+
+ /* OV518(+) has no packet numbering */
+ data_size = ov511->packet_size;
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ int n = urb->iso_frame_desc[i].actual_length;
+ int st = urb->iso_frame_desc[i].status;
+
+ urb->iso_frame_desc[i].actual_length = 0;
+ urb->iso_frame_desc[i].status = 0;
+
+ cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+ if (!n) {
+ PDEBUG(4, "Zero-length packet");
+ continue;
+ }
+
+ if (ov511->curframe == -1) {
+ PDEBUG(4, "No frame currently active");
+ continue;
+ }
+
+ if (st)
+ PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
+
+ frame = &ov511->frame[ov511->curframe];
+
+#if 0
+ {
+ int d;
+ /* Print all data */
+ for (d = 0; d <= data_size - 16; d += 16) {
+ info("%4x: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", d,
+ cdata[d], cdata[d+1], cdata[d+2], cdata[d+3],
+ cdata[d+4], cdata[d+5], cdata[d+6], cdata[d+7],
+ cdata[d+8], cdata[d+9], cdata[d+10], cdata[d+11],
+ cdata[d+12], cdata[d+13], cdata[d+14], cdata[d+15]);
+ }
+ }
+#endif
+
+ if (printph) {
+ info("packet header: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
+ cdata[0], cdata[1], cdata[2], cdata[3], cdata[4], cdata[5],
+ cdata[6], cdata[7], cdata[8], cdata[9], cdata[10], cdata[11]);
+ }
+
+ /* A false positive here is likely, until OVT gives me
+ * the definitive SOF/EOF format */
+ if ((!(cdata[0] | cdata[1] | cdata[2] | cdata[3] |
+ cdata[5])) && cdata[6]) {
+
+ if (frame->scanstate == STATE_LINES) {
+ PDEBUG(4, "Detected frame end/start");
+ goto eof;
+ } else { //scanstate == STATE_SCANNING
+ /* Frame start */
+ PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
+ goto sof;
+ }
+ } else {
+ goto check_middle;
+ }
+
+eof:
+ ts = (struct timeval *)(frame->data
+ + MAX_FRAME_SIZE(ov511->maxwidth, ov511->maxheight));
+ do_gettimeofday(ts);
+
+ PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d",
+ ov511->curframe,
+ (int)(cdata[9]), (int)(cdata[10]), frame->bytes_recvd);
+
+ // FIXME: Since we don't know the header formats yet,
+ // there is no way to know what the actual image size is
+ frame->rawwidth = frame->width;
+ frame->rawheight = frame->height;
+
+ /* Validate the header data */
+ RESTRICT_TO_RANGE(frame->rawwidth, ov511->minwidth, ov511->maxwidth);
+ RESTRICT_TO_RANGE(frame->rawheight, ov511->minheight, ov511->maxheight);
+
+ /* Don't allow byte count to exceed buffer size */
+ RESTRICT_TO_RANGE(frame->bytes_recvd,
+ 8,
+ MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight));
+
+ if (frame->scanstate == STATE_LINES) {
+ int iFrameNext;
+
+ frame->grabstate = FRAME_DONE; // FIXME: Is this right?
+
+ if (waitqueue_active(&frame->wq)) {
+ frame->grabstate = FRAME_DONE;
+ wake_up_interruptible(&frame->wq);
+ }
+
+ /* If next frame is ready or grabbing,
+ * point to it */
+ iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;
+ if (ov511->frame[iFrameNext].grabstate == FRAME_READY
+ || ov511->frame[iFrameNext].grabstate == FRAME_GRABBING) {
+ ov511->curframe = iFrameNext;
+ ov511->frame[iFrameNext].scanstate = STATE_SCANNING;
+ frame = &ov511->frame[iFrameNext];
+ } else {
+ if (frame->grabstate == FRAME_DONE) {
+ PDEBUG(4, "Frame done! congratulations");
+ } else {
+ PDEBUG(4, "Frame not ready? state = %d",
+ ov511->frame[iFrameNext].grabstate);
+ }
+
+ ov511->curframe = -1;
+ PDEBUG(4, "SOF dropped (no active frame)");
+ continue; /* Nowhere to store this frame */
+ }
+ }
+ /* Image corruption caused by misplaced frame->segment = 0
+ * fixed by carlosf@conectiva.com.br
+ */
+sof:
+ PDEBUG(4, "Starting capture on frame %d", frame->framenum);
+// Snapshot not reverse-engineered yet.
+#if 0
+ /* Check to see if it's a snapshot frame */
+ /* FIXME?? Should the snapshot reset go here? Performance? */
+ if (cdata[8] & 0x02) {
+ frame->snapshot = 1;
+ PDEBUG(3, "snapshot detected");
+ }
+#endif
+ frame->scanstate = STATE_LINES;
+ frame->bytes_recvd = 0;
+// frame->compressed = 1;
+
+check_middle:
+ /* Are we in a frame? */
+ if (frame->scanstate != STATE_LINES) {
+ PDEBUG(4, "scanstate: no SOF yet");
+ continue;
+ }
+
+ /* Dump all data exactly as received */
+ if (dumppix == 2) {
+ frame->bytes_recvd += n;
+ if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight))
+ memmove(frame->rawdata + frame->bytes_recvd - n,
+ &cdata[0], n);
+ else
+ PDEBUG(3, "Raw data buffer overrun!! (%d)",
+ frame->bytes_recvd
+ - MAX_RAW_DATA_SIZE(ov511->maxwidth,
+ ov511->maxheight));
+ } else {
+ /* All incoming data are divided into 8-byte segments. If the
+ * segment contains all zero bytes, it must be skipped. These
+ * zero-segments allow the OV518 to mainain a constant data rate
+ * regardless of the effectiveness of the compression. Segments
+ * are aligned relative to the beginning of each isochronous
+ * packet. The first segment is a header.
+ */
+
+ int b, in = 0, allzero, copied=0;
+
+// Decompressor expects the header
+#if 0
+ if (frame->bytes_recvd == 0)
+ in += 8; /* Skip header */
+#endif
+
+ while (in < n) {
+ allzero = 1;
+ for (b = 0; b < 8; b++) {
+ if (cdata[in + b]) {
+ allzero = 0;
+ break;
+ }
+ }
+
+ if (allzero) {
+ /* Don't copy it */
+ } else {
+ if (frame->bytes_recvd + copied + 8
+ <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight)) {
+ memmove(frame->rawdata + frame->bytes_recvd + copied,
+ &cdata[in], 8);
+ copied += 8;
+ } else {
+ PDEBUG(3, "Raw data buffer overrun!!");
+ }
+ }
+ in += 8;
+ }
+ frame->bytes_recvd += copied;
+ }
+ }
+
+ return totlen;
+}
+
+static void
+ov511_isoc_irq(struct urb *urb)
{
int len;
struct usb_ov511 *ov511;
- struct ov511_sbuf *sbuf;
if (!urb->context) {
PDEBUG(4, "no context");
@@ -1876,60 +4340,86 @@ static void ov511_isoc_irq(struct urb *urb)
PDEBUG(4, "hmmm... not streaming, but got interrupt");
return;
}
-
- sbuf = &ov511->sbuf[ov511->cursbuf];
- /* Copy the data received into our scratch buffer */
+ /* Copy the data received into our frame buffer */
if (ov511->curframe >= 0) {
- len = ov511_move_data(ov511, urb);
+ if (ov511->bridge == BRG_OV511 ||
+ ov511->bridge == BRG_OV511PLUS)
+ len = ov511_move_data(ov511, urb);
+ else if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS)
+ len = ov518_move_data(ov511, urb);
+ else
+ err("Unknown bridge device (%d)", ov511->bridge);
} else if (waitqueue_active(&ov511->wq)) {
wake_up_interruptible(&ov511->wq);
}
- /* Move to the next sbuf */
- ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;
-
urb->dev = ov511->dev;
return;
}
-static int ov511_init_isoc(struct usb_ov511 *ov511)
+/****************************************************************************
+ *
+ * Stream initialization and termination
+ *
+ ***************************************************************************/
+
+static int
+ov511_init_isoc(struct usb_ov511 *ov511)
{
urb_t *urb;
int fx, err, n, size;
PDEBUG(3, "*** Initializing capture ***");
- ov511->compress = 0;
ov511->curframe = -1;
- ov511->cursbuf = 0;
- ov511->scratchlen = 0;
- if (ov511->bridge == BRG_OV511)
- if (cams == 1) size = 993;
- else if (cams == 2) size = 513;
- else if (cams == 3 || cams == 4) size = 257;
+ if (ov511->bridge == BRG_OV511) {
+ if (cams == 1) size = 993;
+ else if (cams == 2) size = 513;
+ else if (cams == 3 || cams == 4) size = 257;
else {
err("\"cams\" parameter too high!");
return -1;
}
- else if (ov511->bridge == BRG_OV511PLUS)
- if (cams == 1) size = 961;
- else if (cams == 2) size = 513;
- else if (cams == 3 || cams == 4) size = 257;
- else if (cams >= 5 && cams <= 8) size = 129;
- else if (cams >= 9 && cams <= 31) size = 33;
+ } else if (ov511->bridge == BRG_OV511PLUS) {
+ if (cams == 1) size = 961;
+ else if (cams == 2) size = 513;
+ else if (cams == 3 || cams == 4) size = 257;
+ else if (cams >= 5 && cams <= 8) size = 129;
+ else if (cams >= 9 && cams <= 31) size = 33;
else {
err("\"cams\" parameter too high!");
return -1;
}
- else {
+ } else if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS) {
+ if (cams == 1) size = 896;
+ else if (cams == 2) size = 512;
+ else if (cams == 3 || cams == 4) size = 256;
+ else if (cams >= 5 && cams <= 8) size = 128;
+ else {
+ err("\"cams\" parameter too high!");
+ return -1;
+ }
+ } else {
err("invalid bridge type");
return -1;
}
- ov511_set_packet_size(ov511, size);
+ if (packetsize == -1) {
+ // FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now
+ if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS)
+ ov511_set_packet_size(ov511, 640);
+ else
+ ov511_set_packet_size(ov511, size);
+ } else {
+ info("Forcing packet size to %d", packetsize);
+ ov511_set_packet_size(ov511, packetsize);
+ }
for (n = 0; n < OV511_NUMSBUF; n++) {
urb = usb_alloc_urb(FRAMES_PER_DESC);
@@ -1946,13 +4436,17 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
urb->transfer_buffer = ov511->sbuf[n].data;
urb->complete = ov511_isoc_irq;
urb->number_of_packets = FRAMES_PER_DESC;
- urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
+ urb->transfer_buffer_length =
+ ov511->packet_size * FRAMES_PER_DESC;
for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
- urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
+ urb->iso_frame_desc[fx].offset =
+ ov511->packet_size * fx;
urb->iso_frame_desc[fx].length = ov511->packet_size;
}
}
+ ov511->streaming = 1;
+
ov511->sbuf[OV511_NUMSBUF - 1].urb->next = ov511->sbuf[0].urb;
for (n = 0; n < OV511_NUMSBUF - 1; n++)
ov511->sbuf[n].urb->next = ov511->sbuf[n+1].urb;
@@ -1964,19 +4458,18 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
err("init isoc: usb_submit_urb(%d) ret %d", n, err);
}
- ov511->streaming = 1;
-
return 0;
}
-static void ov511_stop_isoc(struct usb_ov511 *ov511)
+static void
+ov511_stop_isoc(struct usb_ov511 *ov511)
{
int n;
if (!ov511->streaming || !ov511->dev)
return;
- PDEBUG (3, "*** Stopping capture ***");
+ PDEBUG(3, "*** Stopping capture ***");
ov511_set_packet_size(ov511, 0);
@@ -1993,9 +4486,11 @@ static void ov511_stop_isoc(struct usb_ov511 *ov511)
}
}
-static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
+static int
+ov511_new_frame(struct usb_ov511 *ov511, int framenum)
{
struct ov511_frame *frame;
+ int newnum;
PDEBUG(4, "ov511->curframe = %d, framenum = %d", ov511->curframe,
framenum);
@@ -2005,19 +4500,19 @@ static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
/* If we're not grabbing a frame right now and the other frame is */
/* ready to be grabbed into, then use it instead */
if (ov511->curframe == -1) {
- if (ov511->frame[(framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES].grabstate == FRAME_READY)
- framenum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
+ newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
+ if (ov511->frame[newnum].grabstate == FRAME_READY)
+ framenum = newnum;
} else
return 0;
frame = &ov511->frame[framenum];
- PDEBUG (4, "framenum = %d, width = %d, height = %d", framenum,
- frame->width, frame->height);
+ PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum,
+ frame->width, frame->height);
frame->grabstate = FRAME_GRABBING;
frame->scanstate = STATE_SCANNING;
- frame->scanlength = 0; /* accumulated in ov511_parse_data() */
frame->snapshot = 0;
ov511->curframe = framenum;
@@ -2041,9 +4536,12 @@ static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
* Buffer management
*
***************************************************************************/
-static int ov511_alloc(struct usb_ov511 *ov511)
+static int
+ov511_alloc(struct usb_ov511 *ov511)
{
int i;
+ int w = ov511->maxwidth;
+ int h = ov511->maxheight;
PDEBUG(4, "entered");
down(&ov511->buf_lock);
@@ -2056,15 +4554,29 @@ static int ov511_alloc(struct usb_ov511 *ov511)
if (ov511->buf_state == BUF_ALLOCATED)
goto out;
- ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE);
+ ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE(w, h));
if (!ov511->fbuf)
goto error;
- for (i = 0; i < OV511_NUMFRAMES; i++) {
- ov511->frame[i].grabstate = FRAME_UNUSED;
- ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE;
- PDEBUG(4, "frame[%d] @ %p", i, ov511->frame[i].data);
+ ov511->rawfbuf = vmalloc(OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h));
+ if (!ov511->rawfbuf) {
+ rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE(w, h));
+ ov511->fbuf = NULL;
+ goto error;
+ }
+ memset(ov511->rawfbuf, 0, OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h));
+ ov511->tempfbuf = vmalloc(OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h));
+ if (!ov511->tempfbuf) {
+ vfree(ov511->rawfbuf);
+ ov511->rawfbuf = NULL;
+ rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE(w, h));
+ ov511->fbuf = NULL;
+ goto error;
+ }
+ memset(ov511->tempfbuf, 0, OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h));
+
+ for (i = 0; i < OV511_NUMSBUF; i++) {
ov511->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
if (!ov511->sbuf[i].data) {
@@ -2072,12 +4584,28 @@ static int ov511_alloc(struct usb_ov511 *ov511)
kfree(ov511->sbuf[i].data);
ov511->sbuf[i].data = NULL;
}
- rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE);
+ vfree(ov511->tempfbuf);
+ ov511->tempfbuf = NULL;
+ vfree(ov511->rawfbuf);
+ ov511->rawfbuf = NULL;
+ rvfree(ov511->fbuf,
+ OV511_NUMFRAMES * MAX_DATA_SIZE(w, h));
ov511->fbuf = NULL;
+
goto error;
}
PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data);
}
+
+ for (i = 0; i < OV511_NUMFRAMES; i++) {
+ ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE(w, h);
+ ov511->frame[i].rawdata = ov511->rawfbuf
+ + i * MAX_RAW_DATA_SIZE(w, h);
+ ov511->frame[i].tempdata = ov511->tempfbuf
+ + i * MAX_RAW_DATA_SIZE(w, h);
+ PDEBUG(4, "frame[%d] @ %p", i, ov511->frame[i].data);
+ }
+
ov511->buf_state = BUF_ALLOCATED;
out:
up(&ov511->buf_lock);
@@ -2095,29 +4623,48 @@ error:
* - Because this code will free any non-null pointer, you must be sure to null
* them if you explicitly free them somewhere else!
*/
-static void ov511_do_dealloc(struct usb_ov511 *ov511)
+static void
+ov511_do_dealloc(struct usb_ov511 *ov511)
{
int i;
PDEBUG(4, "entered");
if (ov511->fbuf) {
- rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE);
+ rvfree(ov511->fbuf, OV511_NUMFRAMES
+ * MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight));
ov511->fbuf = NULL;
}
- for (i = 0; i < OV511_NUMFRAMES; i++) {
+ if (ov511->rawfbuf) {
+ vfree(ov511->rawfbuf);
+ ov511->rawfbuf = NULL;
+ }
+
+ if (ov511->tempfbuf) {
+ vfree(ov511->tempfbuf);
+ ov511->tempfbuf = NULL;
+ }
+
+ for (i = 0; i < OV511_NUMSBUF; i++) {
if (ov511->sbuf[i].data) {
kfree(ov511->sbuf[i].data);
ov511->sbuf[i].data = NULL;
}
}
+ for (i = 0; i < OV511_NUMFRAMES; i++) {
+ ov511->frame[i].data = NULL;
+ ov511->frame[i].rawdata = NULL;
+ ov511->frame[i].tempdata = NULL;
+ }
+
PDEBUG(4, "buffer memory deallocated");
ov511->buf_state = BUF_NOT_ALLOCATED;
PDEBUG(4, "leaving");
}
-static void ov511_buf_callback(unsigned long data)
+static void
+ov511_buf_callback(unsigned long data)
{
struct usb_ov511 *ov511 = (struct usb_ov511 *)data;
PDEBUG(4, "entered");
@@ -2130,7 +4677,8 @@ static void ov511_buf_callback(unsigned long data)
PDEBUG(4, "leaving");
}
-static void ov511_dealloc(struct usb_ov511 *ov511, int now)
+static void
+ov511_dealloc(struct usb_ov511 *ov511, int now)
{
struct timer_list *bt = &(ov511->buf_timer);
PDEBUG(4, "entered");
@@ -2163,13 +4711,14 @@ static void ov511_dealloc(struct usb_ov511 *ov511, int now)
*
***************************************************************************/
-static int ov511_open(struct video_device *dev, int flags)
+static int
+ov511_open(struct video_device *vdev, int flags)
{
- struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
- int err;
+ struct usb_ov511 *ov511 = vdev->priv;
+ int err, i;
- MOD_INC_USE_COUNT;
PDEBUG(4, "opening");
+
down(&ov511->lock);
err = -EBUSY;
@@ -2182,6 +4731,24 @@ static int ov511_open(struct video_device *dev, int flags)
ov511->sub_flag = 0;
+ /* In case app doesn't set them... */
+ if (ov51x_set_default_params(ov511) < 0)
+ goto out;
+
+ /* Make sure frames are reset */
+ for (i = 0; i < OV511_NUMFRAMES; i++) {
+ ov511->frame[i].grabstate = FRAME_UNUSED;
+ ov511->frame[i].bytes_read = 0;
+ }
+
+ /* If compression is on, make sure now that a
+ * decompressor can be loaded */
+ if (ov511->compress && !ov511->decomp_ops) {
+ err = ov51x_request_decompressor(ov511);
+ if (err)
+ goto out;
+ }
+
err = ov511_init_isoc(ov511);
if (err) {
ov511_dealloc(ov511, 0);
@@ -2189,17 +4756,18 @@ static int ov511_open(struct video_device *dev, int flags)
}
ov511->user++;
+
+ if (ov511->led_policy == LED_AUTO)
+ ov51x_led_control(ov511, 1);
out:
up(&ov511->lock);
- if (err)
- MOD_DEC_USE_COUNT;
-
return err;
}
-static void ov511_close(struct video_device *dev)
+static void
+ov511_close(struct video_device *dev)
{
struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
@@ -2210,40 +4778,50 @@ static void ov511_close(struct video_device *dev)
ov511->user--;
ov511_stop_isoc(ov511);
+ ov51x_release_decompressor(ov511);
+
+ if (ov511->led_policy == LED_AUTO)
+ ov51x_led_control(ov511, 0);
+
if (ov511->dev)
ov511_dealloc(ov511, 0);
up(&ov511->lock);
+ /* Device unplugged while open. Only a minimum of unregistration is done
+ * here; the disconnect callback already did the rest. */
if (!ov511->dev) {
ov511_dealloc(ov511, 1);
video_unregister_device(&ov511->vdev);
kfree(ov511);
ov511 = NULL;
}
-
- MOD_DEC_USE_COUNT;
}
-static int ov511_init_done(struct video_device *dev)
+static int
+ov511_init_done(struct video_device *vdev)
{
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
- create_proc_ov511_cam((struct usb_ov511 *)dev);
+ create_proc_ov511_cam((struct usb_ov511 *)vdev);
#endif
return 0;
}
-static long ov511_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
+static long
+ov511_write(struct video_device *vdev, const char *buf,
+ unsigned long count, int noblock)
{
return -EINVAL;
}
-static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+/* Do not call this function directly! */
+static int
+ov511_ioctl_internal(struct video_device *vdev, unsigned int cmd, void *arg)
{
struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
- PDEBUG(4, "IOCtl: 0x%X", cmd);
+ PDEBUG(5, "IOCtl: 0x%X", cmd);
if (!ov511->dev)
return -EIO;
@@ -2253,17 +4831,24 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
struct video_capability b;
- PDEBUG (4, "VIDIOCGCAP");
+ PDEBUG(4, "VIDIOCGCAP");
memset(&b, 0, sizeof(b));
- strcpy(b.name, "OV511 USB Camera");
+ sprintf(b.name, "%s USB Camera",
+ ov511->bridge == BRG_OV511 ? "OV511" :
+ ov511->bridge == BRG_OV511PLUS ? "OV511+" :
+ ov511->bridge == BRG_OV518 ? "OV518" :
+ ov511->bridge == BRG_OV518PLUS ? "OV518+" :
+ "unknown");
b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
- b.channels = 1;
- b.audios = 0;
+ if (ov511->has_tuner)
+ b.type |= VID_TYPE_TUNER;
+ b.channels = ov511->num_inputs;
+ b.audios = ov511->has_audio_proc ? 1:0;
b.maxwidth = ov511->maxwidth;
b.maxheight = ov511->maxheight;
- b.minwidth = 160;
- b.minheight = 120;
+ b.minwidth = ov511->minwidth;
+ b.minheight = ov511->minheight;
if (copy_to_user(arg, &b, sizeof(b)))
return -EFAULT;
@@ -2274,15 +4859,23 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
struct video_channel v;
+ PDEBUG(4, "VIDIOCGCHAN");
+
if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
- if (v.channel != 0)
+
+ if ((unsigned)(v.channel) >= ov511->num_inputs) {
+ err("Invalid channel (%d)", v.channel);
return -EINVAL;
+ }
- v.flags = 0;
- v.tuners = 0;
- v.type = VIDEO_TYPE_CAMERA;
- strcpy(v.name, "Camera");
+ v.norm = ov511->norm;
+ v.type = (ov511->has_tuner) ? VIDEO_TYPE_TV : VIDEO_TYPE_CAMERA;
+ v.flags = (ov511->has_tuner) ? VIDEO_VC_TUNER : 0;
+ v.flags |= (ov511->has_audio_proc) ? VIDEO_VC_AUDIO : 0;
+// v.flags |= (ov511->has_decoder) ? VIDEO_VC_NORM : 0;
+ v.tuners = (ov511->has_tuner) ? 1:0;
+ decoder_get_input_name(ov511, v.channel, v.name);
if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT;
@@ -2291,13 +4884,42 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
}
case VIDIOCSCHAN:
{
- int v;
+ struct video_channel v;
+ int err;
+
+ PDEBUG(4, "VIDIOCSCHAN");
if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
- if (v != 0)
+ /* Make sure it's not a camera */
+ if (!ov511->has_decoder) {
+ if (v.channel == 0)
+ return 0;
+ else
+ return -EINVAL;
+ }
+
+ if (v.norm != VIDEO_MODE_PAL &&
+ v.norm != VIDEO_MODE_NTSC &&
+ v.norm != VIDEO_MODE_SECAM &&
+ v.norm != VIDEO_MODE_AUTO) {
+ err("Invalid norm (%d)", v.norm);
+ return -EINVAL;
+ }
+
+ if ((unsigned)(v.channel) >= ov511->num_inputs) {
+ err("Invalid channel (%d)", v.channel);
return -EINVAL;
+ }
+
+ err = decoder_set_input(ov511, v.channel);
+ if (err)
+ return err;
+
+ err = decoder_set_norm(ov511, v.norm);
+ if (err)
+ return err;
return 0;
}
@@ -2305,11 +4927,11 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
struct video_picture p;
- PDEBUG (4, "VIDIOCGPICT");
+ PDEBUG(4, "VIDIOCGPICT");
memset(&p, 0, sizeof(p));
- if (ov7610_get_picture(ov511, &p))
+ if (sensor_get_picture(ov511, &p))
return -EIO;
if (copy_to_user(arg, &p, sizeof(p)))
@@ -2322,22 +4944,40 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
struct video_picture p;
int i;
- PDEBUG (4, "VIDIOCSPICT");
+ PDEBUG(4, "VIDIOCSPICT");
if (copy_from_user(&p, arg, sizeof(p)))
return -EFAULT;
if (!ov511_get_depth(p.palette))
return -EINVAL;
-
- if (ov7610_set_picture(ov511, &p))
+
+ if (sensor_set_picture(ov511, &p))
return -EIO;
+ if (force_palette && p.palette != force_palette) {
+ info("Palette rejected (%d)", p.palette);
+ return -EINVAL;
+ }
+
+ // FIXME: Format should be independent of frames
+ if (p.palette != ov511->frame[0].format) {
+ PDEBUG(4, "Detected format change");
+
+ /* If we're collecting previous frame wait
+ before changing modes */
+ interruptible_sleep_on(&ov511->wq);
+ if (signal_pending(current)) return -EINTR;
+
+ mode_init_regs(ov511, ov511->frame[0].width,
+ ov511->frame[0].height, p.palette,
+ ov511->sub_flag);
+ }
+
PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette);
for (i = 0; i < OV511_NUMFRAMES; i++) {
ov511->frame[i].depth = p.depth;
ov511->frame[i].format = p.palette;
- ov511->frame[i].segsize = GET_SEGSIZE(p.palette);
}
return 0;
@@ -2346,7 +4986,7 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
int vf;
- PDEBUG (4, "VIDIOCGCAPTURE");
+ PDEBUG(4, "VIDIOCGCAPTURE");
if (copy_from_user(&vf, arg, sizeof(vf)))
return -EFAULT;
@@ -2357,6 +4997,8 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
struct video_capture vc;
+ PDEBUG(4, "VIDIOCSCAPTURE");
+
if (copy_from_user(&vc, arg, sizeof(vc)))
return -EFAULT;
if (vc.flags)
@@ -2391,7 +5033,7 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
if (copy_from_user(&vw, arg, sizeof(vw)))
return -EFAULT;
- PDEBUG (4, "VIDIOCSWIN: width=%d, height=%d",
+ PDEBUG(4, "VIDIOCSWIN: width=%d, height=%d",
vw.width, vw.height);
#if 0
@@ -2410,7 +5052,7 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
interruptible_sleep_on(&ov511->wq);
if (signal_pending(current)) return -EINTR;
- result = ov511_mode_init_regs(ov511, vw.width, vw.height,
+ result = mode_init_regs(ov511, vw.width, vw.height,
ov511->frame[0].format, ov511->sub_flag);
if (result < 0)
return result;
@@ -2433,7 +5075,7 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
vw.height = ov511->frame[0].height;
vw.flags = 30;
- PDEBUG (4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
+ PDEBUG(4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
if (copy_to_user(arg, &vw, sizeof(vw)))
return -EFAULT;
@@ -2444,14 +5086,18 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
struct video_mbuf vm;
int i;
-
+
+ PDEBUG(4, "VIDIOCGMBUF");
+
memset(&vm, 0, sizeof(vm));
- vm.size = OV511_NUMFRAMES * MAX_DATA_SIZE;
+ vm.size = OV511_NUMFRAMES
+ * MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight);
vm.frames = OV511_NUMFRAMES;
+
vm.offsets[0] = 0;
for (i = 1; i < OV511_NUMFRAMES; i++) {
- vm.offsets[i] = vm.offsets[i-1] + MAX_FRAME_SIZE
- + sizeof (struct timeval);
+ vm.offsets[i] = vm.offsets[i-1]
+ + MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight);
}
if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
@@ -2482,63 +5128,74 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
return -EINVAL;
}
- if (vm.width > ov511->maxwidth || vm.height > ov511->maxheight) {
+ if (vm.width > ov511->maxwidth
+ || vm.height > ov511->maxheight) {
err("VIDIOCMCAPTURE: requested dimensions too big");
return -EINVAL;
}
- if (ov511->frame[vm.frame].grabstate == FRAME_GRABBING)
+ if (ov511->frame[vm.frame].grabstate == FRAME_GRABBING) {
+ PDEBUG(4, "VIDIOCMCAPTURE: already grabbing");
return -EBUSY;
+ }
+
+ if (force_palette && vm.format != force_palette) {
+ info("palette rejected (%d)", vm.format);
+ return -EINVAL;
+ }
- /* Don't compress if the size changed */
if ((ov511->frame[vm.frame].width != vm.width) ||
(ov511->frame[vm.frame].height != vm.height) ||
(ov511->frame[vm.frame].format != vm.format) ||
- (ov511->frame[vm.frame].sub_flag !=
- ov511->sub_flag)) {
+ (ov511->frame[vm.frame].sub_flag != ov511->sub_flag) ||
+ (ov511->frame[vm.frame].depth != depth)) {
+ PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters");
+
/* If we're collecting previous frame wait
before changing modes */
interruptible_sleep_on(&ov511->wq);
if (signal_pending(current)) return -EINTR;
- ret = ov511_mode_init_regs(ov511, vm.width, vm.height,
+ ret = mode_init_regs(ov511, vm.width, vm.height,
vm.format, ov511->sub_flag);
#if 0
- if (ret < 0)
+ if (ret < 0) {
+ PDEBUG(1, "Got error while initializing regs ");
return ret;
+ }
#endif
+ ov511->frame[vm.frame].width = vm.width;
+ ov511->frame[vm.frame].height = vm.height;
+ ov511->frame[vm.frame].format = vm.format;
+ ov511->frame[vm.frame].sub_flag = ov511->sub_flag;
+ ov511->frame[vm.frame].depth = depth;
}
- ov511->frame[vm.frame].width = vm.width;
- ov511->frame[vm.frame].height = vm.height;
- ov511->frame[vm.frame].format = vm.format;
- ov511->frame[vm.frame].sub_flag = ov511->sub_flag;
- ov511->frame[vm.frame].segsize = GET_SEGSIZE(vm.format);
- ov511->frame[vm.frame].depth = depth;
-
/* Mark it as ready */
ov511->frame[vm.frame].grabstate = FRAME_READY;
+ PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", vm.frame);
+
return ov511_new_frame(ov511, vm.frame);
}
case VIDIOCSYNC:
{
- int frame;
+ int fnum, rc;
+ struct ov511_frame *frame;
- if (copy_from_user((void *)&frame, arg, sizeof(int)))
+ if (copy_from_user((void *)&fnum, arg, sizeof(int)))
return -EFAULT;
- if ((unsigned)frame >= OV511_NUMFRAMES) {
- err("VIDIOCSYNC: invalid frame (%d)", frame);
+ if ((unsigned)fnum >= OV511_NUMFRAMES) {
+ err("VIDIOCSYNC: invalid frame (%d)", fnum);
return -EINVAL;
}
- PDEBUG(4, "syncing to frame %d, grabstate = %d", frame,
- ov511->frame[frame].grabstate);
+ frame = &ov511->frame[fnum];
- if(frame < 0 || frame >= OV511_NUMFRAMES)
- return -EINVAL;
-
- switch (ov511->frame[frame].grabstate) {
+ PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum,
+ frame->grabstate);
+
+ switch (frame->grabstate) {
case FRAME_UNUSED:
return -EINVAL;
case FRAME_READY:
@@ -2548,56 +5205,41 @@ redo:
if (!ov511->dev)
return -EIO;
- do {
-#if 0
- init_waitqueue_head(&ov511->frame[frame].wq);
-#endif
- interruptible_sleep_on(&ov511->frame[frame].wq);
- if (signal_pending(current)) {
- if (retry_sync) {
- PDEBUG(3, "***retry sync***");
-
- /* Polling apps will destroy frames with that! */
- ov511_new_frame(ov511, frame);
- ov511->curframe = -1;
-
- /* This will request another frame. */
- if (waitqueue_active(&ov511->frame[frame].wq))
- wake_up_interruptible(&ov511->frame[frame].wq);
-
- return 0;
- } else {
- return -EINTR;
- }
- }
- } while (ov511->frame[frame].grabstate == FRAME_GRABBING);
+ rc = wait_event_interruptible(frame->wq,
+ (frame->grabstate == FRAME_DONE)
+ || (frame->grabstate == FRAME_ERROR));
- if (ov511->frame[frame].grabstate == FRAME_ERROR) {
+ if (rc)
+ return rc;
+
+ if (frame->grabstate == FRAME_ERROR) {
int ret;
- if ((ret = ov511_new_frame(ov511, frame)) < 0)
+ if ((ret = ov511_new_frame(ov511, fnum)) < 0)
return ret;
goto redo;
- }
+ }
+ /* Fall through */
case FRAME_DONE:
- if (ov511->snap_enabled && !ov511->frame[frame].snapshot) {
+ if (ov511->snap_enabled && !frame->snapshot) {
int ret;
- if ((ret = ov511_new_frame(ov511, frame)) < 0)
+ if ((ret = ov511_new_frame(ov511, fnum)) < 0)
return ret;
goto redo;
}
- ov511->frame[frame].grabstate = FRAME_UNUSED;
+ frame->grabstate = FRAME_UNUSED;
/* Reset the hardware snapshot button */
/* FIXME - Is this the best place for this? */
- if ((ov511->snap_enabled) &&
- (ov511->frame[frame].snapshot)) {
- ov511->frame[frame].snapshot = 0;
- ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
- ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
- ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
+ if ((ov511->snap_enabled) && (frame->snapshot)) {
+ frame->snapshot = 0;
+ ov51x_clear_snapshot(ov511);
}
+
+ /* Decompression, format conversion, etc... */
+ ov511_postprocess(ov511, frame);
+
break;
} /* end switch */
@@ -2607,6 +5249,8 @@ redo:
{
struct video_buffer vb;
+ PDEBUG(4, "VIDIOCSCHAN");
+
memset(&vb, 0, sizeof(vb));
vb.base = NULL; /* frame buffer not supported, not used */
@@ -2615,43 +5259,170 @@ redo:
return 0;
}
- case VIDIOCKEY:
+ case VIDIOCGUNIT:
+ {
+ struct video_unit vu;
+
+ PDEBUG(4, "VIDIOCGUNIT");
+
+ memset(&vu, 0, sizeof(vu));
+
+ vu.video = ov511->vdev.minor; /* Video minor */
+ vu.vbi = VIDEO_NO_UNIT; /* VBI minor */
+ vu.radio = VIDEO_NO_UNIT; /* Radio minor */
+ vu.audio = VIDEO_NO_UNIT; /* Audio minor */
+ vu.teletext = VIDEO_NO_UNIT; /* Teletext minor */
+
+ if (copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))
+ return -EFAULT;
+
return 0;
- case VIDIOCCAPTURE:
- return -EINVAL;
- case VIDIOCSFBUF:
- return -EINVAL;
+ }
case VIDIOCGTUNER:
+ {
+ struct video_tuner v;
+
+ PDEBUG(4, "VIDIOCGTUNER");
+
+ if (copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+
+ if (!ov511->has_tuner || v.tuner) // Only tuner 0
+ return -EINVAL;
+
+ strcpy(v.name, "Television");
+
+ // FIXME: Need a way to get the real values
+ v.rangelow = 0;
+ v.rangehigh = ~0;
+
+ v.flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC |
+ VIDEO_TUNER_SECAM;
+ v.mode = 0; /* FIXME: Not sure what this is yet */
+ v.signal = 0xFFFF; /* unknown */
+
+ call_i2c_clients(ov511, cmd, &v);
+
+ if (copy_to_user(arg, &v, sizeof(v)))
+ return -EFAULT;
+
+ return 0;
+ }
case VIDIOCSTUNER:
- return -EINVAL;
+ {
+ struct video_tuner v;
+ int err;
+
+ PDEBUG(4, "VIDIOCSTUNER");
+
+ if (copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+
+ /* Only no or one tuner for now */
+ if (!ov511->has_tuner || v.tuner)
+ return -EINVAL;
+
+ /* and it only has certain valid modes */
+ if (v.mode != VIDEO_MODE_PAL &&
+ v.mode != VIDEO_MODE_NTSC &&
+ v.mode != VIDEO_MODE_SECAM) return -EOPNOTSUPP;
+
+ /* Is this right/necessary? */
+ err = decoder_set_norm(ov511, v.mode);
+ if (err)
+ return err;
+
+ call_i2c_clients(ov511, cmd, &v);
+
+ return 0;
+ }
case VIDIOCGFREQ:
+ {
+ unsigned long v = ov511->freq;
+
+ PDEBUG(4, "VIDIOCGFREQ");
+
+ if (!ov511->has_tuner)
+ return -EINVAL;
+#if 0
+ /* FIXME: this is necessary for testing */
+ v = 46*16;
+#endif
+ if (copy_to_user(arg, &v, sizeof(v)))
+ return -EFAULT;
+
+ return 0;
+ }
case VIDIOCSFREQ:
- return -EINVAL;
+ {
+ unsigned long v;
+
+ if (!ov511->has_tuner)
+ return -EINVAL;
+
+ if (copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+
+ PDEBUG(4, "VIDIOCSFREQ: %lx", v);
+
+ ov511->freq = v;
+ call_i2c_clients(ov511, cmd, &v);
+
+ return 0;
+ }
case VIDIOCGAUDIO:
case VIDIOCSAUDIO:
- return -EINVAL;
+ {
+ /* FIXME: Implement this... */
+ return 0;
+ }
default:
+ PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd);
return -ENOIOCTLCMD;
} /* end switch */
return 0;
}
-static long ov511_read(struct video_device *dev, char *buf, unsigned long count, int noblock)
+static int
+ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
- struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
- int i;
- int frmx = -1;
- volatile struct ov511_frame *frame;
+ int rc;
+ struct usb_ov511 *ov511 = vdev->priv;
+
+ if (down_interruptible(&ov511->lock))
+ return -EINTR;
+
+ rc = ov511_ioctl_internal(vdev, cmd, arg);
+
+ up(&ov511->lock);
+ return rc;
+}
+
+static inline long
+ov511_read(struct video_device *vdev, char *buf, unsigned long count,
+ int noblock)
+{
+ struct usb_ov511 *ov511 = vdev->priv;
+ int i, rc = 0, frmx = -1;
+ struct ov511_frame *frame;
+
+ if (down_interruptible(&ov511->lock))
+ return -EINTR;
PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
- if (!dev || !buf)
- return -EFAULT;
+ if (!vdev || !buf) {
+ rc = -EFAULT;
+ goto error;
+ }
- if (!ov511->dev)
- return -EIO;
+ if (!ov511->dev) {
+ rc = -EIO;
+ goto error;
+ }
+// FIXME: Only supports two frames
/* See if a frame is completed, then use it. */
if (ov511->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */
frmx = 0;
@@ -2659,8 +5430,10 @@ static long ov511_read(struct video_device *dev, char *buf, unsigned long count,
frmx = 1;
/* If nonblocking we return immediately */
- if (noblock && (frmx == -1))
- return -EAGAIN;
+ if (noblock && (frmx == -1)) {
+ rc = -EAGAIN;
+ goto error;
+ }
/* If no FRAME_DONE, look for a FRAME_GRABBING state. */
/* See if a frame is in process (grabbing), then use it. */
@@ -2672,89 +5445,116 @@ static long ov511_read(struct video_device *dev, char *buf, unsigned long count,
}
/* If no frame is active, start one. */
- if (frmx == -1)
- ov511_new_frame(ov511, frmx = 0);
+ if (frmx == -1) {
+ if ((rc = ov511_new_frame(ov511, frmx = 0))) {
+ err("read: ov511_new_frame error");
+ goto error;
+ }
+ }
frame = &ov511->frame[frmx];
restart:
- if (!ov511->dev)
- return -EIO;
+ if (!ov511->dev) {
+ rc = -EIO;
+ goto error;
+ }
/* Wait while we're grabbing the image */
PDEBUG(4, "Waiting image grabbing");
- while (frame->grabstate == FRAME_GRABBING) {
- interruptible_sleep_on(&ov511->frame[frmx].wq);
- if (signal_pending(current))
- return -EINTR;
- }
+ rc = wait_event_interruptible(frame->wq,
+ (frame->grabstate == FRAME_DONE)
+ || (frame->grabstate == FRAME_ERROR));
+
+ if (rc)
+ goto error;
+
PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate);
+ PDEBUG(4, "bytes_recvd = %d", frame->bytes_recvd);
if (frame->grabstate == FRAME_ERROR) {
frame->bytes_read = 0;
err("** ick! ** Errored frame %d", ov511->curframe);
- if (ov511_new_frame(ov511, frmx))
+ if (ov511_new_frame(ov511, frmx)) {
err("read: ov511_new_frame error");
+ goto error;
+ }
goto restart;
}
/* Repeat until we get a snapshot frame */
if (ov511->snap_enabled)
- PDEBUG (4, "Waiting snapshot frame");
+ PDEBUG(4, "Waiting snapshot frame");
if (ov511->snap_enabled && !frame->snapshot) {
frame->bytes_read = 0;
- if (ov511_new_frame(ov511, frmx))
- err("ov511_new_frame error");
+ if ((rc = ov511_new_frame(ov511, frmx))) {
+ err("read: ov511_new_frame error");
+ goto error;
+ }
goto restart;
}
/* Clear the snapshot */
if (ov511->snap_enabled && frame->snapshot) {
frame->snapshot = 0;
- ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
- ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
- ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
+ ov51x_clear_snapshot(ov511);
}
- PDEBUG(4, "frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
- frame->bytes_read, frame->scanlength);
+ /* Decompression, format conversion, etc... */
+ ov511_postprocess(ov511, frame);
+
+ PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx,
+ frame->bytes_read,
+ get_frame_length(frame));
/* copy bytes to user space; we allow for partials reads */
-// if ((count + frame->bytes_read) > frame->scanlength)
+// if ((count + frame->bytes_read)
+// > get_frame_length((struct ov511_frame *)frame))
// count = frame->scanlength - frame->bytes_read;
/* FIXME - count hardwired to be one frame... */
- count = frame->width * frame->height * (frame->depth >> 3);
+ count = get_frame_length(frame);
PDEBUG(4, "Copy to user space: %ld bytes", count);
if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) {
PDEBUG(4, "Copy failed! %d bytes not copied", i);
- return -EFAULT;
+ rc = -EFAULT;
+ goto error;
}
frame->bytes_read += count;
PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
count, frame->bytes_read);
- if (frame->bytes_read >= frame->scanlength) { /* All data has been read */
+ /* If all data has been read... */
+ if (frame->bytes_read
+ >= get_frame_length(frame)) {
frame->bytes_read = 0;
+// FIXME: Only supports two frames
/* Mark it as available to be used again. */
ov511->frame[frmx].grabstate = FRAME_UNUSED;
- if (ov511_new_frame(ov511, !frmx))
+ if ((rc = ov511_new_frame(ov511, !frmx))) {
err("ov511_new_frame returned error");
+ goto error;
+ }
}
PDEBUG(4, "read finished, returning %ld (sweet)", count);
+ up(&ov511->lock);
return count;
+
+error:
+ up(&ov511->lock);
+ return rc;
}
-static int ov511_mmap(struct vm_area_struct *vma, struct video_device *dev, const char *adr,
- unsigned long size)
+static int
+ov511_mmap(struct vm_area_struct *vma, struct video_device *vdev, const char *adr, unsigned long size)
{
- struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
+ struct usb_ov511 *ov511 = vdev->priv;
unsigned long start = (unsigned long)adr;
unsigned long page, pos;
@@ -2763,14 +5563,21 @@ static int ov511_mmap(struct vm_area_struct *vma, struct video_device *dev, cons
PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
- if (size > (((OV511_NUMFRAMES * MAX_DATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
+ if (size > (((OV511_NUMFRAMES
+ * MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight)
+ + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
return -EINVAL;
+ if (down_interruptible(&ov511->lock))
+ return -EINTR;
+
pos = (unsigned long)ov511->fbuf;
while (size > 0) {
page = kvirt_to_pa(pos);
- if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+ if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+ up(&ov511->lock);
return -EAGAIN;
+ }
start += PAGE_SIZE;
pos += PAGE_SIZE;
if (size > PAGE_SIZE)
@@ -2779,10 +5586,12 @@ static int ov511_mmap(struct vm_area_struct *vma, struct video_device *dev, cons
size = 0;
}
+ up(&ov511->lock);
return 0;
}
static struct video_device ov511_template = {
+ owner: THIS_MODULE,
name: "OV511 USB Camera",
type: VID_TYPE_CAPTURE,
hardware: VID_HARDWARE_OV511,
@@ -2795,15 +5604,237 @@ static struct video_device ov511_template = {
initialize: ov511_init_done,
};
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+static int
+ov511_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long ularg)
+{
+ struct proc_dir_entry *pde;
+ struct usb_ov511 *ov511;
+ void *arg = (void *) ularg;
+ int rc;
+
+ pde = (struct proc_dir_entry *) inode->u.generic_ip;
+ if (!pde)
+ return -ENOENT;
+
+ ov511 = (struct usb_ov511 *) pde->data;
+ if (!ov511)
+ return -ENODEV;
+
+ if (!ov511->dev)
+ return -EIO;
+
+ /* Should we pass through standard V4L IOCTLs? */
+
+ switch (cmd) {
+ case OV511IOC_GINTVER:
+ {
+ int ver = OV511_INTERFACE_VER;
+
+ PDEBUG(4, "Get interface version: %d", ver);
+ if (copy_to_user(arg, &ver, sizeof(ver)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case OV511IOC_GUSHORT:
+ {
+ struct ov511_ushort_opt opt;
+
+ if (copy_from_user(&opt, arg, sizeof(opt)))
+ return -EFAULT;
+
+ switch (opt.optnum) {
+ case OV511_USOPT_BRIGHT:
+ rc = sensor_get_brightness(ov511, &(opt.val));
+ if (rc) return rc;
+ break;
+ case OV511_USOPT_SAT:
+ rc = sensor_get_saturation(ov511, &(opt.val));
+ if (rc) return rc;
+ break;
+ case OV511_USOPT_HUE:
+ rc = sensor_get_hue(ov511, &(opt.val));
+ if (rc) return rc;
+ break;
+ case OV511_USOPT_CONTRAST:
+ rc = sensor_get_contrast(ov511, &(opt.val));
+ if (rc) return rc;
+ break;
+ default:
+ err("Invalid get short option number");
+ return -EINVAL;
+ }
+
+ if (copy_to_user(arg, &opt, sizeof(opt)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case OV511IOC_SUSHORT:
+ {
+ struct ov511_ushort_opt opt;
+
+ if (copy_from_user(&opt, arg, sizeof(opt)))
+ return -EFAULT;
+
+ switch (opt.optnum) {
+ case OV511_USOPT_BRIGHT:
+ rc = sensor_set_brightness(ov511, opt.val);
+ if (rc) return rc;
+ break;
+ case OV511_USOPT_SAT:
+ rc = sensor_set_saturation(ov511, opt.val);
+ if (rc) return rc;
+ break;
+ case OV511_USOPT_HUE:
+ rc = sensor_set_hue(ov511, opt.val);
+ if (rc) return rc;
+ break;
+ case OV511_USOPT_CONTRAST:
+ rc = sensor_set_contrast(ov511, opt.val);
+ if (rc) return rc;
+ break;
+ default:
+ err("Invalid set short option number");
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+ case OV511IOC_GUINT:
+ {
+ struct ov511_uint_opt opt;
+
+ if (copy_from_user(&opt, arg, sizeof(opt)))
+ return -EFAULT;
+
+ switch (opt.optnum) {
+ case OV511_UIOPT_POWER_FREQ:
+ opt.val = ov511->lightfreq;
+ break;
+ case OV511_UIOPT_BFILTER:
+ opt.val = ov511->bandfilt;
+ break;
+ case OV511_UIOPT_LED:
+ opt.val = ov511->led_policy;
+ break;
+ case OV511_UIOPT_DEBUG:
+ opt.val = debug;
+ break;
+ case OV511_UIOPT_COMPRESS:
+ opt.val = ov511->compress;
+ break;
+ default:
+ err("Invalid get int option number");
+ return -EINVAL;
+ }
+
+ if (copy_to_user(arg, &opt, sizeof(opt)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case OV511IOC_SUINT:
+ {
+ struct ov511_uint_opt opt;
+
+ if (copy_from_user(&opt, arg, sizeof(opt)))
+ return -EFAULT;
+
+ switch (opt.optnum) {
+ case OV511_UIOPT_POWER_FREQ:
+ rc = sensor_set_light_freq(ov511, opt.val);
+ if (rc) return rc;
+ break;
+ case OV511_UIOPT_BFILTER:
+ rc = sensor_set_banding_filter(ov511, opt.val);
+ if (rc) return rc;
+ break;
+ case OV511_UIOPT_LED:
+ if (opt.val <= 2) {
+ ov511->led_policy = opt.val;
+ if (ov511->led_policy == LED_OFF)
+ ov51x_led_control(ov511, 0);
+ else if (ov511->led_policy == LED_ON)
+ ov51x_led_control(ov511, 1);
+ } else {
+ return -EINVAL;
+ }
+ break;
+ case OV511_UIOPT_DEBUG:
+ if (opt.val <= 5)
+ debug = opt.val;
+ else
+ return -EINVAL;
+ break;
+ case OV511_UIOPT_COMPRESS:
+ ov511->compress = opt.val;
+ if (ov511->compress) {
+ if (ov511->bridge == BRG_OV511 ||
+ ov511->bridge == BRG_OV511PLUS)
+ ov511_init_compression(ov511);
+ else if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS)
+ ov518_init_compression(ov511);
+ }
+ break;
+ default:
+ err("Invalid get int option number");
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+ case OV511IOC_WI2C:
+ {
+ struct ov511_i2c_struct w;
+
+ if (copy_from_user(&w, arg, sizeof(w)))
+ return -EFAULT;
+
+ return ov51x_i2c_write_slave(ov511, w.slave, w.reg, w.value,
+ w.mask);
+ }
+ case OV511IOC_RI2C:
+ {
+ struct ov511_i2c_struct r;
+
+ if (copy_from_user(&r, arg, sizeof(r)))
+ return -EFAULT;
+
+ rc = ov51x_i2c_read_slave(ov511, r.slave, r.reg);
+ if (rc < 0)
+ return rc;
+
+ r.value = rc;
+
+ if (copy_to_user(arg, &r, sizeof(r)))
+ return -EFAULT;
+
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ } /* end switch */
+
+ return 0;
+}
+#endif
+
/****************************************************************************
*
- * OV511/OV7610 configuration
+ * OV511 and sensor configuration
*
***************************************************************************/
-static int ov76xx_configure(struct usb_ov511 *ov511)
+/* This initializes the OV7610, OV7620, or OV7620AE sensor. The OV7620AE uses
+ * the same register settings as the OV7610, since they are very similar.
+ */
+static int
+ov7xx0_configure(struct usb_ov511 *ov511)
{
- struct usb_device *dev = ov511->dev;
int i, success;
int rc;
@@ -2832,9 +5863,11 @@ static int ov76xx_configure(struct usb_ov511 *ov511)
{ OV511_I2C_BUS, 0x23, 0x2a },
{ OV511_I2C_BUS, 0x24, 0x10 },
{ OV511_I2C_BUS, 0x25, 0x8a },
+ { OV511_I2C_BUS, 0x26, 0xa2 },
{ OV511_I2C_BUS, 0x27, 0xc2 },
{ OV511_I2C_BUS, 0x2a, 0x04 },
{ OV511_I2C_BUS, 0x2c, 0xfe },
+ { OV511_I2C_BUS, 0x2d, 0x93 },
{ OV511_I2C_BUS, 0x30, 0x71 },
{ OV511_I2C_BUS, 0x31, 0x60 },
{ OV511_I2C_BUS, 0x32, 0x26 },
@@ -2848,81 +5881,96 @@ static int ov76xx_configure(struct usb_ov511 *ov511)
};
static struct ov511_regvals aRegvalsNorm7620[] = {
- { OV511_I2C_BUS, 0x10, 0xff },
- { OV511_I2C_BUS, 0x16, 0x06 },
- { OV511_I2C_BUS, 0x28, 0x24 },
- { OV511_I2C_BUS, 0x2b, 0xac },
- { OV511_I2C_BUS, 0x12, 0x00 },
- { OV511_I2C_BUS, 0x28, 0x24 },
- { OV511_I2C_BUS, 0x0f, 0x85 }, /* lg's setting */
- { OV511_I2C_BUS, 0x15, 0x01 },
- { OV511_I2C_BUS, 0x23, 0x00 },
- { OV511_I2C_BUS, 0x24, 0x10 },
- { OV511_I2C_BUS, 0x25, 0x8a },
- { OV511_I2C_BUS, 0x27, 0xe2 },
- { OV511_I2C_BUS, 0x2a, 0x00 },
- { OV511_I2C_BUS, 0x2c, 0xfe },
- { OV511_I2C_BUS, 0x30, 0x71 },
- { OV511_I2C_BUS, 0x31, 0x60 },
- { OV511_I2C_BUS, 0x32, 0x26 },
- { OV511_I2C_BUS, 0x33, 0x20 },
- { OV511_I2C_BUS, 0x34, 0x48 },
- { OV511_I2C_BUS, 0x12, 0x24 },
- { OV511_I2C_BUS, 0x11, 0x01 },
+ { OV511_I2C_BUS, 0x00, 0x00 },
+ { OV511_I2C_BUS, 0x01, 0x80 },
+ { OV511_I2C_BUS, 0x02, 0x80 },
+ { OV511_I2C_BUS, 0x03, 0xc0 },
+ { OV511_I2C_BUS, 0x06, 0x60 },
+ { OV511_I2C_BUS, 0x07, 0x00 },
+ { OV511_I2C_BUS, 0x0c, 0x24 },
{ OV511_I2C_BUS, 0x0c, 0x24 },
{ OV511_I2C_BUS, 0x0d, 0x24 },
+ { OV511_I2C_BUS, 0x11, 0x01 },
+ { OV511_I2C_BUS, 0x12, 0x24 },
+ { OV511_I2C_BUS, 0x13, 0x01 },
+ { OV511_I2C_BUS, 0x14, 0x84 },
+ { OV511_I2C_BUS, 0x15, 0x01 },
+ { OV511_I2C_BUS, 0x16, 0x03 },
+ { OV511_I2C_BUS, 0x17, 0x2f },
+ { OV511_I2C_BUS, 0x18, 0xcf },
+ { OV511_I2C_BUS, 0x19, 0x06 },
+ { OV511_I2C_BUS, 0x1a, 0xf5 },
+ { OV511_I2C_BUS, 0x1b, 0x00 },
+ { OV511_I2C_BUS, 0x20, 0x18 },
+ { OV511_I2C_BUS, 0x21, 0x80 },
+ { OV511_I2C_BUS, 0x22, 0x80 },
+ { OV511_I2C_BUS, 0x23, 0x00 },
+ { OV511_I2C_BUS, 0x26, 0xa2 },
+ { OV511_I2C_BUS, 0x27, 0xea },
+ { OV511_I2C_BUS, 0x28, 0x20 },
+ { OV511_I2C_BUS, 0x29, 0x00 },
+ { OV511_I2C_BUS, 0x2a, 0x10 },
+ { OV511_I2C_BUS, 0x2b, 0x00 },
+ { OV511_I2C_BUS, 0x2c, 0x88 },
+ { OV511_I2C_BUS, 0x2d, 0x91 },
+ { OV511_I2C_BUS, 0x2e, 0x80 },
+ { OV511_I2C_BUS, 0x2f, 0x44 },
+ { OV511_I2C_BUS, 0x60, 0x27 },
+ { OV511_I2C_BUS, 0x61, 0x02 },
+ { OV511_I2C_BUS, 0x62, 0x5f },
+ { OV511_I2C_BUS, 0x63, 0xd5 },
+ { OV511_I2C_BUS, 0x64, 0x57 },
+ { OV511_I2C_BUS, 0x65, 0x83 },
+ { OV511_I2C_BUS, 0x66, 0x55 },
+ { OV511_I2C_BUS, 0x67, 0x92 },
+ { OV511_I2C_BUS, 0x68, 0xcf },
+ { OV511_I2C_BUS, 0x69, 0x76 },
+ { OV511_I2C_BUS, 0x6a, 0x22 },
+ { OV511_I2C_BUS, 0x6b, 0x00 },
+ { OV511_I2C_BUS, 0x6c, 0x02 },
+ { OV511_I2C_BUS, 0x6d, 0x44 },
+ { OV511_I2C_BUS, 0x6e, 0x80 },
+ { OV511_I2C_BUS, 0x6f, 0x1d },
+ { OV511_I2C_BUS, 0x70, 0x8b },
+ { OV511_I2C_BUS, 0x71, 0x00 },
+ { OV511_I2C_BUS, 0x72, 0x14 },
+ { OV511_I2C_BUS, 0x73, 0x54 },
+ { OV511_I2C_BUS, 0x74, 0x00 },
+ { OV511_I2C_BUS, 0x75, 0x8e },
+ { OV511_I2C_BUS, 0x76, 0x00 },
+ { OV511_I2C_BUS, 0x77, 0xff },
+ { OV511_I2C_BUS, 0x78, 0x80 },
+ { OV511_I2C_BUS, 0x79, 0x80 },
+ { OV511_I2C_BUS, 0x7a, 0x80 },
+ { OV511_I2C_BUS, 0x7b, 0xe2 },
+ { OV511_I2C_BUS, 0x7c, 0x00 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
- PDEBUG (4, "starting configuration");
+ PDEBUG(4, "starting configuration");
/* This looks redundant, but is necessary for WebCam 3 */
- if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
- OV7610_I2C_WRITE_ID) < 0)
- return -1;
-
- if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
- OV7610_I2C_READ_ID) < 0)
+ ov511->primary_i2c_slave = OV7xx0_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, OV7xx0_I2C_WRITE_ID,
+ OV7xx0_I2C_READ_ID) < 0)
return -1;
- if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
- return -1;
-
- /* Reset the 76xx */
- if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
-
- /* Wait for it to initialize */
- schedule_timeout (1 + 150 * HZ / 1000);
-
- for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
- if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
- (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
- success = 1;
- continue;
- }
-
- /* Reset the 76xx */
- if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
- /* Wait for it to initialize */
- schedule_timeout (1 + 150 * HZ / 1000);
- /* Dummy read to sync I2C */
- if (ov511_i2c_read(dev, 0x00) < 0) return -1;
- }
-
- if (success) {
- PDEBUG(1, "I2C synced in %d attempt(s) (method 1)", i);
+ if (ov51x_init_ov_sensor(ov511) >= 0) {
+ PDEBUG(1, "OV7xx0 sensor initalized (method 1)");
} else {
/* Reset the 76xx */
- if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
+ if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) return -1;
/* Wait for it to initialize */
- schedule_timeout (1 + 150 * HZ / 1000);
+ schedule_timeout(1 + 150 * HZ / 1000);
i = 0;
success = 0;
while (i <= i2c_detect_tries) {
- if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
- (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
+ if ((ov51x_i2c_read(ov511,
+ OV7610_REG_ID_HIGH) == 0x7F) &&
+ (ov51x_i2c_read(ov511,
+ OV7610_REG_ID_LOW) == 0xA2)) {
success = 1;
break;
} else {
@@ -2930,204 +5978,423 @@ static int ov76xx_configure(struct usb_ov511 *ov511)
}
}
- if ((i == i2c_detect_tries) && (success == 0)) {
- err("Failed to read sensor ID. You might not have an OV7610/20,");
- err("or it may be not responding. Report this to");
- err("mwm@i.am");
- return -1;
+// Was (i == i2c_detect_tries) previously. This obviously used to always report
+// success. Whether anyone actually depended on that bug is unknown
+ if ((i >= i2c_detect_tries) && (success == 0)) {
+ err("Failed to read sensor ID. You might not have an");
+ err("OV7610/20, or it may be not responding. Report");
+ err("this to " EMAIL);
+ err("This is only a warning. You can attempt to use");
+ err("your camera anyway");
+// Only issue a warning for now
+// return -1;
} else {
- PDEBUG(1, "I2C synced in %d attempt(s) (method 2)", i+1);
+ PDEBUG(1, "OV7xx0 initialized (method 2, %dx)", i+1);
}
}
- /* Detect sensor if user didn't use override param */
- if (sensor == 0) {
- rc = ov511_i2c_read(dev, OV7610_REG_COM_I);
+ /* Detect sensor (sub)type */
+ rc = ov51x_i2c_read(ov511, OV7610_REG_COM_I);
- if (rc < 0) {
- err("Error detecting sensor type");
- return -1;
- } else if((rc & 3) == 3) {
- info("Sensor is an OV7610");
- ov511->sensor = SEN_OV7610;
- } else if((rc & 3) == 1) {
+ if (rc < 0) {
+ err("Error detecting sensor type");
+ return -1;
+ } else if ((rc & 3) == 3) {
+ info("Sensor is an OV7610");
+ ov511->sensor = SEN_OV7610;
+ } else if ((rc & 3) == 1) {
+ /* I don't know what's different about the 76BE yet */
+ if (ov51x_i2c_read(ov511, 0x15) & 1)
info("Sensor is an OV7620AE");
- ov511->sensor = SEN_OV7620AE;
- } else if((rc & 3) == 0) {
- info("Sensor is an OV7620");
+ else
+ info("Sensor is an OV76BE");
+
+ /* OV511+ will return all zero isoc data unless we
+ * configure the sensor as a 7620. Someone needs to
+ * find the exact reg. setting that causes this. */
+ if (ov511->bridge == BRG_OV511PLUS) {
+ info("Enabling 511+/7620AE workaround");
ov511->sensor = SEN_OV7620;
} else {
- err("Unknown image sensor version: %d", rc & 3);
- return -1;
+ ov511->sensor = SEN_OV7620AE;
}
- } else { /* sensor != 0; user overrode detection */
- ov511->sensor = sensor;
- info("Sensor set to type %d", ov511->sensor);
+ } else if ((rc & 3) == 0) {
+ info("Sensor is an OV7620");
+ ov511->sensor = SEN_OV7620;
+ } else {
+ err("Unknown image sensor version: %d", rc & 3);
+ return -1;
}
if (ov511->sensor == SEN_OV7620) {
PDEBUG(4, "Writing 7620 registers");
- if (ov511_write_regvals(dev, aRegvalsNorm7620))
+ if (ov511_write_regvals(ov511, aRegvalsNorm7620))
return -1;
} else {
PDEBUG(4, "Writing 7610 registers");
- if (ov511_write_regvals(dev, aRegvalsNorm7610))
+ if (ov511_write_regvals(ov511, aRegvalsNorm7610))
return -1;
}
/* Set sensor-specific vars */
ov511->maxwidth = 640;
ov511->maxheight = 480;
+ ov511->minwidth = 64;
+ ov511->minheight = 48;
- if (aperture < 0) { /* go with the default */
- if (ov511_i2c_write(dev, 0x26, 0xa2) < 0) return -1;
- } else if (aperture <= 0xf) { /* user overrode default */
- if (ov511_i2c_write(dev, 0x26, (aperture << 4) + 2) < 0)
- return -1;
- } else {
- err("Invalid setting for aperture; legal value: 0 - 15");
- return -1;
- }
-
- if (autoadjust) {
- if (ov511_i2c_write(dev, 0x13, 0x01) < 0) return -1;
- if (ov511_i2c_write(dev, 0x2d,
- ov511->sensor==SEN_OV7620?0x91:0x93) < 0) return -1;
- } else {
- if (ov511_i2c_write(dev, 0x13, 0x00) < 0) return -1;
- if (ov511_i2c_write(dev, 0x2d,
- ov511->sensor==SEN_OV7620?0x81:0x83) < 0) return -1;
- ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
- }
+ // FIXME: These do not match the actual settings yet
+ ov511->brightness = 0x80 << 8;
+ ov511->contrast = 0x80 << 8;
+ ov511->colour = 0x80 << 8;
+ ov511->hue = 0x80 << 8;
return 0;
}
-static int ov6xx0_configure(struct usb_ov511 *ov511)
+/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
+static int
+ov6xx0_configure(struct usb_ov511 *ov511)
{
- struct usb_device *dev = ov511->dev;
- int i, success, rc;
+ int rc;
static struct ov511_regvals aRegvalsNorm6x20[] = {
- { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
+ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
{ OV511_I2C_BUS, 0x11, 0x01 },
- { OV511_I2C_BUS, 0x03, 0xd0 },
- { OV511_I2C_BUS, 0x05, 0x7f },
+ { OV511_I2C_BUS, 0x03, 0x60 },
+ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
{ OV511_I2C_BUS, 0x07, 0xa8 },
+ /* The ratio of 0x0c and 0x0d controls the white point */
{ OV511_I2C_BUS, 0x0c, 0x24 },
{ OV511_I2C_BUS, 0x0d, 0x24 },
- { OV511_I2C_BUS, 0x10, 0xff }, /* ? */
+ { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
{ OV511_I2C_BUS, 0x14, 0x04 },
- { OV511_I2C_BUS, 0x16, 0x06 }, /* ? */
- { OV511_I2C_BUS, 0x19, 0x04 },
- { OV511_I2C_BUS, 0x1a, 0x93 },
- { OV511_I2C_BUS, 0x20, 0x28 },
- { OV511_I2C_BUS, 0x27, 0xa2 },
- { OV511_I2C_BUS, 0x28, 0x24 },
- { OV511_I2C_BUS, 0x2a, 0x04 }, /* 84? */
- { OV511_I2C_BUS, 0x2b, 0xac }, /* a8? */
- { OV511_I2C_BUS, 0x2d, 0x95 },
- { OV511_I2C_BUS, 0x33, 0x28 },
- { OV511_I2C_BUS, 0x34, 0xc7 },
+ /* 0x16: 0x06 helps frame stability with moving objects */
+ { OV511_I2C_BUS, 0x16, 0x06 },
+// { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
+ { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */
+ /* 0x28: 0x05 Selects RGB format if RGB on */
+ { OV511_I2C_BUS, 0x28, 0x05 },
+ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
+// { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
+ { OV511_I2C_BUS, 0x2d, 0x99 },
+ { OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */
{ OV511_I2C_BUS, 0x38, 0x8b },
- { OV511_I2C_BUS, 0x3c, 0x5c },
+ { OV511_I2C_BUS, 0x39, 0x40 },
+
+ { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
+ { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
+ { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
+
{ OV511_I2C_BUS, 0x3d, 0x80 },
- { OV511_I2C_BUS, 0x3f, 0x00 },
- { OV511_I2C_BUS, 0x4a, 0x80 }, /* undocumented */
- { OV511_I2C_BUS, 0x4b, 0x80 }, /* undocumented */
- { OV511_I2C_BUS, 0x4d, 0xd2 },
+ /* These next two registers (0x4a, 0x4b) are undocumented. They
+ * control the color balance */
+ { OV511_I2C_BUS, 0x4a, 0x80 },
+ { OV511_I2C_BUS, 0x4b, 0x80 },
+ { OV511_I2C_BUS, 0x4d, 0xd2 }, /* This reduces noise a bit */
{ OV511_I2C_BUS, 0x4e, 0xc1 },
{ OV511_I2C_BUS, 0x4f, 0x04 },
+// Do 50-53 have any effect?
+// Toggle 0x12[2] off and on here?
+ { OV511_DONE_BUS, 0x0, 0x00 },
+ };
+
+ /* This chip is undocumented so many of these are guesses. OK=verified,
+ * A=Added since 6620, U=unknown function (not a 6620 reg) */
+ static struct ov511_regvals aRegvalsNorm6x30[] = {
+ /*OK*/ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
+ /*00?*/ { OV511_I2C_BUS, 0x11, 0x01 },
+ /*OK*/ { OV511_I2C_BUS, 0x03, 0x60 },
+ /*0A?*/ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
+ { OV511_I2C_BUS, 0x07, 0xa8 },
+ /* The ratio of 0x0c and 0x0d controls the white point */
+ /*OK*/ { OV511_I2C_BUS, 0x0c, 0x24 },
+ /*OK*/ { OV511_I2C_BUS, 0x0d, 0x24 },
+ /*A*/ { OV511_I2C_BUS, 0x0e, 0x20 },
+
+// /*24?*/ { OV511_I2C_BUS, 0x12, 0x28 }, /* Enable AGC */
+// { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
+
+// /*A*/ { OV511_I2C_BUS, 0x13, 0x21 },
+// /*A*/ { OV511_I2C_BUS, 0x13, 0x25 }, /* Tristate Y and UV busses */
+
+// /*04?*/ { OV511_I2C_BUS, 0x14, 0x80 },
+ /* 0x16: 0x06 helps frame stability with moving objects */
+ /*03?*/ { OV511_I2C_BUS, 0x16, 0x06 },
+// /*OK*/ { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
+ // 21 & 22? The suggested values look wrong. Go with default
+ /*A*/ { OV511_I2C_BUS, 0x23, 0xc0 },
+ /*A*/ { OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default
+// /*OK*/ { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */
+
+ /* 0x28: 0x05 Selects RGB format if RGB on */
+// /*04?*/ { OV511_I2C_BUS, 0x28, 0x05 },
+// /*04?*/ { OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus
+
+ /*OK*/ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
+// /*OK*/ { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
+// /*U*/ { OV511_I2C_BUS, 0x2c, 0xa0 },
+ { OV511_I2C_BUS, 0x2d, 0x99 },
+// /*A*/ { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620
+// /*d2?*/ { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */
+// /*U*/ { OV511_I2C_BUS, 0x36, 0x8f }, // May not be necessary
+// /*U*/ { OV511_I2C_BUS, 0x37, 0x80 }, // May not be necessary
+// /*8b?*/ { OV511_I2C_BUS, 0x38, 0x83 },
+// /*40?*/ { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7
+// { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
+// { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
+// { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
+ /*OK*/ { OV511_I2C_BUS, 0x3d, 0x80 },
+// /*A*/ { OV511_I2C_BUS, 0x3f, 0x0e },
+// /*U*/ { OV511_I2C_BUS, 0x40, 0x00 },
+// /*U*/ { OV511_I2C_BUS, 0x41, 0x00 },
+// /*U*/ { OV511_I2C_BUS, 0x42, 0x80 },
+// /*U*/ { OV511_I2C_BUS, 0x43, 0x3f },
+// /*U*/ { OV511_I2C_BUS, 0x44, 0x80 },
+// /*U*/ { OV511_I2C_BUS, 0x45, 0x20 },
+// /*U*/ { OV511_I2C_BUS, 0x46, 0x20 },
+// /*U*/ { OV511_I2C_BUS, 0x47, 0x80 },
+// /*U*/ { OV511_I2C_BUS, 0x48, 0x7f },
+// /*U*/ { OV511_I2C_BUS, 0x49, 0x00 },
+
+ /* These next two registers (0x4a, 0x4b) are undocumented. They
+ * control the color balance */
+// /*OK?*/ { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these
+// /*OK?*/ { OV511_I2C_BUS, 0x4b, 0x80 },
+// /*U*/ { OV511_I2C_BUS, 0x4c, 0xd0 },
+ /*d2?*/ { OV511_I2C_BUS, 0x4d, 0x10 }, /* This reduces noise a bit */
+ /*c1?*/ { OV511_I2C_BUS, 0x4e, 0x40 },
+ /*04?*/ { OV511_I2C_BUS, 0x4f, 0x07 },
+// /*U*/ { OV511_I2C_BUS, 0x50, 0xff },
+ /*U*/ { OV511_I2C_BUS, 0x54, 0x23 },
+// /*U*/ { OV511_I2C_BUS, 0x55, 0xff },
+// /*U*/ { OV511_I2C_BUS, 0x56, 0x12 },
+ /*U*/ { OV511_I2C_BUS, 0x57, 0x81 },
+// /*U*/ { OV511_I2C_BUS, 0x58, 0x75 },
+ /*U*/ { OV511_I2C_BUS, 0x59, 0x01 },
+ /*U*/ { OV511_I2C_BUS, 0x5a, 0x2c },
+ /*U*/ { OV511_I2C_BUS, 0x5b, 0x0f },
+// /*U*/ { OV511_I2C_BUS, 0x5c, 0x10 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
- PDEBUG (4, "starting sensor configuration");
+ PDEBUG(4, "starting sensor configuration");
- /* Reset the 6xx0 */
- if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
+ if (ov51x_init_ov_sensor(ov511) < 0) {
+ err("Failed to read sensor ID. You might not have an OV6xx0,");
+ err("or it may be not responding. Report this to " EMAIL);
+ return -1;
+ } else {
+ PDEBUG(1, "OV6xx0 sensor detected");
+ }
- /* Wait for it to initialize */
- schedule_timeout (1 + 150 * HZ / 1000);
+ /* Detect sensor (sub)type */
+ rc = ov51x_i2c_read(ov511, OV7610_REG_COM_I);
- for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
- if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
- (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
- success = 1;
- continue;
- }
+ if (rc < 0) {
+ err("Error detecting sensor type");
+ return -1;
+ } else if ((rc & 3) == 0) {
+ info("Sensor is an OV6630");
+ ov511->sensor = SEN_OV6630;
+ } else if ((rc & 3) == 1) {
+ info("Sensor is an OV6620");
+ ov511->sensor = SEN_OV6620;
+ } else if ((rc & 3) == 2) {
+ info("Sensor is an OV6630AE");
+ ov511->sensor = SEN_OV6630;
+ } else if ((rc & 3) == 3) {
+ info("Sensor is an OV6630AF");
+ ov511->sensor = SEN_OV6630;
+ }
- /* Reset the 6xx0 */
- if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
- /* Wait for it to initialize */
- schedule_timeout (1 + 150 * HZ / 1000);
- /* Dummy read to sync I2C */
- if (ov511_i2c_read(dev, 0x00) < 0) return -1;
+ /* Set sensor-specific vars */
+ if (ov511->sensor == SEN_OV6620) {
+ ov511->maxwidth = 352;
+ ov511->maxheight = 288;
+ } else {
+ /* 352x288 not working with OV518 yet */
+ ov511->maxwidth = 320;
+ ov511->maxheight = 240;
}
+ ov511->minwidth = 64;
+ ov511->minheight = 48;
+
+ // FIXME: These do not match the actual settings yet
+ ov511->brightness = 0x80 << 8;
+ ov511->contrast = 0x80 << 8;
+ ov511->colour = 0x80 << 8;
+ ov511->hue = 0x80 << 8;
- if (success) {
- PDEBUG(1, "I2C synced in %d attempt(s)", i);
+ if (ov511->sensor == SEN_OV6620) {
+ PDEBUG(4, "Writing 6x20 registers");
+ if (ov511_write_regvals(ov511, aRegvalsNorm6x20))
+ return -1;
} else {
- err("Failed to read sensor ID. You might not have an OV6xx0,");
- err("or it may be not responding. Report this to");
- err("mwm@i.am");
- return -1;
+ PDEBUG(4, "Writing 6x30 registers");
+ if (ov511_write_regvals(ov511, aRegvalsNorm6x30))
+ return -1;
}
+
+ return 0;
+}
+
+/* This initializes the KS0127 and KS0127B video decoders. */
+static int
+ks0127_configure(struct usb_ov511 *ov511)
+{
+ int rc;
- /* Detect sensor if user didn't use override param */
- if (sensor == 0) {
- rc = ov511_i2c_read(dev, OV7610_REG_COM_I);
+// FIXME: I don't know how to sync or reset it yet
+#if 0
+ if (ov51x_init_ks_sensor(ov511) < 0) {
+ err("Failed to initialize the KS0127");
+ return -1;
+ } else {
+ PDEBUG(1, "KS012x(B) sensor detected");
+ }
+#endif
+ /* Detect decoder subtype */
+ rc = ov51x_i2c_read(ov511, 0x00);
+ if (rc < 0) {
+ err("Error detecting sensor type");
+ return -1;
+ } else if (rc & 0x08) {
+ rc = ov51x_i2c_read(ov511, 0x3d);
if (rc < 0) {
err("Error detecting sensor type");
return -1;
- } else {
- info("Sensor is an OV6xx0 (version %d)", rc & 3);
- ov511->sensor = SEN_OV6620;
+ } else if ((rc & 0x0f) == 0) {
+ info("Sensor is a KS0127");
+ ov511->sensor = SEN_KS0127;
+ } else if ((rc & 0x0f) == 9) {
+ info("Sensor is a KS0127B Rev. A");
+ ov511->sensor = SEN_KS0127B;
}
- } else { /* sensor != 0; user overrode detection */
- ov511->sensor = sensor;
- info("Sensor set to type %d", ov511->sensor);
+ } else {
+ err("Error: Sensor is an unsupported KS0122");
+ return -1;
}
/* Set sensor-specific vars */
- ov511->maxwidth = 352;
- ov511->maxheight = 288;
+ ov511->maxwidth = 640;
+ ov511->maxheight = 480;
+ ov511->minwidth = 64;
+ ov511->minheight = 48;
- PDEBUG(4, "Writing 6x20 registers");
- if (ov511_write_regvals(dev, aRegvalsNorm6x20))
- return -1;
+ // FIXME: These do not match the actual settings yet
+ ov511->brightness = 0x80 << 8;
+ ov511->contrast = 0x80 << 8;
+ ov511->colour = 0x80 << 8;
+ ov511->hue = 0x80 << 8;
- if (aperture < 0) { /* go with the default */
- if (ov511_i2c_write(dev, 0x26, 0xa2) < 0) return -1;
- } else if (aperture <= 0xf) { /* user overrode default */
- if (ov511_i2c_write(dev, 0x26, (aperture << 4) + 2) < 0)
- return -1;
- } else {
- err("Invalid setting for aperture; legal value: 0 - 15");
+ /* This device is not supported yet. Bail out now... */
+ err("This sensor is not supported yet.");
+ return -1;
+
+ return 0;
+}
+
+/* This initializes the SAA7111A video decoder. */
+static int
+saa7111a_configure(struct usb_ov511 *ov511)
+{
+ struct usb_device *dev = ov511->dev;
+ int rc;
+
+ /* Since there is no register reset command, all registers must be
+ * written, otherwise gives erratic results */
+ static struct ov511_regvals aRegvalsNormSAA7111A[] = {
+ { OV511_I2C_BUS, 0x06, 0xce },
+ { OV511_I2C_BUS, 0x07, 0x00 },
+ { OV511_I2C_BUS, 0x10, 0x44 }, /* YUV422, 240/286 lines */
+ { OV511_I2C_BUS, 0x0e, 0x01 }, /* NTSC M or PAL BGHI */
+ { OV511_I2C_BUS, 0x00, 0x00 },
+ { OV511_I2C_BUS, 0x01, 0x00 },
+ { OV511_I2C_BUS, 0x03, 0x23 },
+ { OV511_I2C_BUS, 0x04, 0x00 },
+ { OV511_I2C_BUS, 0x05, 0x00 },
+ { OV511_I2C_BUS, 0x08, 0xc8 }, /* Auto field freq */
+ { OV511_I2C_BUS, 0x09, 0x01 }, /* Chrom. trap off, APER=0.25 */
+ { OV511_I2C_BUS, 0x0a, 0x80 }, /* BRIG=128 */
+ { OV511_I2C_BUS, 0x0b, 0x40 }, /* CONT=1.0 */
+ { OV511_I2C_BUS, 0x0c, 0x40 }, /* SATN=1.0 */
+ { OV511_I2C_BUS, 0x0d, 0x00 }, /* HUE=0 */
+ { OV511_I2C_BUS, 0x0f, 0x00 },
+ { OV511_I2C_BUS, 0x11, 0x0c },
+ { OV511_I2C_BUS, 0x12, 0x00 },
+ { OV511_I2C_BUS, 0x13, 0x00 },
+ { OV511_I2C_BUS, 0x14, 0x00 },
+ { OV511_I2C_BUS, 0x15, 0x00 },
+ { OV511_I2C_BUS, 0x16, 0x00 },
+ { OV511_I2C_BUS, 0x17, 0x00 },
+ { OV511_I2C_BUS, 0x02, 0xc0 }, /* Composite input 0 */
+ { OV511_DONE_BUS, 0x0, 0x00 },
+ };
+
+// FIXME: I don't know how to sync or reset it yet
+#if 0
+ if (ov51x_init_saa_sensor(ov511) < 0) {
+ err("Failed to initialize the SAA7111A");
return -1;
+ } else {
+ PDEBUG(1, "SAA7111A sensor detected");
}
+#endif
+
+ /* Set sensor-specific vars */
+ ov511->maxwidth = 640;
+ ov511->maxheight = 480; /* Even/Odd fields */
+ ov511->minwidth = 320;
+ ov511->minheight = 240; /* Even field only */
+
+ ov511->has_decoder = 1;
+ ov511->num_inputs = 8;
+ ov511->norm = VIDEO_MODE_AUTO;
+ ov511->stop_during_set = 0; /* Decoder guarantees stable image */
+
+ /* Decoder doesn't change these values, so we use these instead of
+ * acutally reading the registers (which doesn't work) */
+ ov511->brightness = 0x80 << 8;
+ ov511->contrast = 0x40 << 9;
+ ov511->colour = 0x40 << 9;
+ ov511->hue = 32768;
+
+ PDEBUG(4, "Writing SAA7111A registers");
+ if (ov511_write_regvals(ov511, aRegvalsNormSAA7111A))
+ return -1;
- if (autoadjust) {
- if (ov511_i2c_write(dev, 0x13, 0x01) < 0) return -1;
- if (ov511_i2c_write(dev, 0x2d,
- ov511->sensor==SEN_OV7620?0x91:0x93) < 0) return -1;
+ /* Detect version of decoder. This must be done after writing the
+ * initial regs or the decoder will lock up. */
+ rc = ov51x_i2c_read(ov511, 0x00);
+
+ if (rc < 0) {
+ err("Error detecting sensor version");
+ return -1;
} else {
- if (ov511_i2c_write(dev, 0x13, 0x00) < 0) return -1;
- if (ov511_i2c_write(dev, 0x2d,
- ov511->sensor==SEN_OV7620?0x81:0x83) < 0) return -1;
- ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
+ info("Sensor is an SAA7111A (version 0x%x)", rc);
+ ov511->sensor = SEN_SAA7111A;
}
+ // FIXME: Fix this for OV518(+)
+ /* Latch to negative edge of clock. Otherwise, we get incorrect
+ * colors and jitter in the digital signal. */
+ if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS)
+ ov511_reg_write(dev, 0x11, 0x00);
+ else
+ warn("SAA7111A not yet supported with OV518/OV518+");
+
return 0;
}
-
-static int ov511_configure(struct usb_ov511 *ov511)
+/* This initializes the OV511/OV511+ and the sensor */
+static int
+ov511_configure(struct usb_ov511 *ov511)
{
struct usb_device *dev = ov511->dev;
int i;
- static struct ov511_regvals aRegvalsInit[] = {
+ static struct ov511_regvals aRegvalsInit511[] = {
{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
@@ -3140,101 +6407,276 @@ static int ov511_configure(struct usb_ov511 *ov511)
static struct ov511_regvals aRegvalsNorm511[] = {
{ OV511_REG_BUS, OV511_REG_DRAM_ENABLE_FLOW_CONTROL, 0x01 },
- { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x02 },
- { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x00 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x01 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x03 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x01 },
{ OV511_REG_BUS, OV511_REG_FIFO_BITMASK, 0x1f },
- { OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_Y, 0x08 },
- { OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_UV, 0x01 },
- { OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_Y, 0x08 },
- { OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_UV, 0x01 },
- { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_Y, 0x01 },
- { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_UV, 0x01 },
- { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_Y, 0x01 },
- { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_UV, 0x01 },
- { OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x06 },
+ { OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x00 },
{ OV511_REG_BUS, OV511_OMNICE_LUT_ENABLE, 0x03 },
{ OV511_DONE_BUS, 0x0, 0x00 },
};
- memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template));
+ static struct ov511_regvals aRegvalsNorm511Plus[] = {
+ { OV511_REG_BUS, OV511_REG_DRAM_ENABLE_FLOW_CONTROL, 0xff },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x01 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x03 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x01 },
+ { OV511_REG_BUS, OV511_REG_FIFO_BITMASK, 0xff },
+ { OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x00 },
+ { OV511_REG_BUS, OV511_OMNICE_LUT_ENABLE, 0x03 },
+ { OV511_DONE_BUS, 0x0, 0x00 },
+ };
- for (i = 0; i < OV511_NUMFRAMES; i++)
- init_waitqueue_head(&ov511->frame[i].wq);
+ PDEBUG(4, "");
- init_waitqueue_head(&ov511->wq);
+ ov511->customid = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
+ if (ov511->customid < 0) {
+ err("Unable to read camera bridge registers");
+ goto error;
+ }
+
+ ov511->desc = -1;
+ PDEBUG (1, "CustomID = %d", ov511->customid);
+ for (i = 0; clist[i].id >= 0; i++) {
+ if (ov511->customid == clist[i].id) {
+ info("model: %s", clist[i].description);
+ ov511->desc = i;
+ break;
+ }
+ }
+
+ if (clist[i].id == -1) {
+ err("Camera type (%d) not recognized", ov511->customid);
+ err("Please notify " EMAIL " of the name,");
+ err("manufacturer, model, and this number of your camera.");
+ err("Also include the output of the detection process.");
+ }
+
+ if (clist[i].id == 6) { /* USB Life TV (NTSC) */
+ ov511->tuner_type = 8; /* Temic 4036FY5 3X 1981 */
+ }
+
+ if (ov511_write_regvals(ov511, aRegvalsInit511)) goto error;
+
+ if (ov511->led_policy == LED_OFF || ov511->led_policy == LED_AUTO)
+ ov51x_led_control(ov511, 0);
+
+ /* The OV511+ has undocumented bits in the flow control register.
+ * Setting it to 0xff fixes the corruption with moving objects. */
+ if (ov511->bridge == BRG_OV511) {
+ if (ov511_write_regvals(ov511, aRegvalsNorm511)) goto error;
+ } else if (ov511->bridge == BRG_OV511PLUS) {
+ if (ov511_write_regvals(ov511, aRegvalsNorm511Plus)) goto error;
+ } else {
+ err("Invalid bridge");
+ }
- if (ov511_write_regvals(dev, aRegvalsInit)) goto error;
- if (ov511_write_regvals(dev, aRegvalsNorm511)) goto error;
+ if (ov511_init_compression(ov511)) goto error;
ov511_set_packet_size(ov511, 0);
ov511->snap_enabled = snapshot;
- /* Test for 76xx */
- if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
- OV7610_I2C_WRITE_ID) < 0)
+ /* Test for 7xx0 */
+ PDEBUG(3, "Testing for 0V7xx0");
+ ov511->primary_i2c_slave = OV7xx0_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, OV7xx0_I2C_WRITE_ID,
+ OV7xx0_I2C_READ_ID) < 0)
goto error;
- if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
- OV7610_I2C_READ_ID) < 0)
- goto error;
+ if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) {
+ /* Test for 6xx0 */
+ PDEBUG(3, "Testing for 0V6xx0");
+ ov511->primary_i2c_slave = OV6xx0_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, OV6xx0_I2C_WRITE_ID,
+ OV6xx0_I2C_READ_ID) < 0)
+ goto error;
+
+ if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) {
+ /* Test for 8xx0 */
+ PDEBUG(3, "Testing for 0V8xx0");
+ ov511->primary_i2c_slave = OV8xx0_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, OV8xx0_I2C_WRITE_ID,
+ OV8xx0_I2C_READ_ID))
+ goto error;
+
+ if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) {
+ /* Test for SAA7111A */
+ PDEBUG(3, "Testing for SAA7111A");
+ ov511->primary_i2c_slave = SAA7111A_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, SAA7111A_I2C_WRITE_ID,
+ SAA7111A_I2C_READ_ID))
+ goto error;
+
+ if (ov51x_i2c_write(ov511, 0x0d, 0x00) < 0) {
+ /* Test for KS0127 */
+ PDEBUG(3, "Testing for KS0127");
+ ov511->primary_i2c_slave = KS0127_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, KS0127_I2C_WRITE_ID,
+ KS0127_I2C_READ_ID))
+ goto error;
+
+ if (ov51x_i2c_write(ov511, 0x10, 0x00) < 0) {
+ err("Can't determine sensor slave IDs");
+ goto error;
+ } else {
+ if(ks0127_configure(ov511) < 0) {
+ err("Failed to configure KS0127");
+ goto error;
+ }
+ }
+ } else {
+ if(saa7111a_configure(ov511) < 0) {
+ err("Failed to configure SAA7111A");
+ goto error;
+ }
+ }
+ } else {
+ err("Detected unsupported OV8xx0 sensor");
+ goto error;
+ }
+ } else {
+ if(ov6xx0_configure(ov511) < 0) {
+ err("Failed to configure OV6xx0");
+ goto error;
+ }
+ }
+ } else {
+ if(ov7xx0_configure(ov511) < 0) {
+ err("Failed to configure OV7xx0");
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ err("OV511 Config failed");
+
+ return -EBUSY;
+}
+
+/* This initializes the OV518/OV518+ and the sensor */
+static int
+ov518_configure(struct usb_ov511 *ov511)
+{
+ struct usb_device *dev = ov511->dev;
+
+ static struct ov511_regvals aRegvalsInit518[] = {
+ { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x40 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0xe1 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3e },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0xe1 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x00 },
+ { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0xe1 },
+ { OV511_REG_BUS, 0x46, 0x00 },
+ { OV511_REG_BUS, 0x5d, 0x03 },
+ { OV511_DONE_BUS, 0x0, 0x00},
+ };
+
+ /* New values, based on Windows driver. Since what they do is not
+ * known yet, this may be incorrect. */
+ static struct ov511_regvals aRegvalsNorm518[] = {
+ { OV511_REG_BUS, 0x52, 0x02 }, /* Reset snapshot */
+ { OV511_REG_BUS, 0x52, 0x01 }, /* Enable snapshot */
+ { OV511_REG_BUS, 0x31, 0x0f },
+ { OV511_REG_BUS, 0x5d, 0x03 },
+ { OV511_REG_BUS, 0x24, 0x9f },
+ { OV511_REG_BUS, 0x25, 0x90 },
+ { OV511_REG_BUS, 0x20, 0x00 }, /* Was 0x08 */
+ { OV511_REG_BUS, 0x51, 0x04 },
+ { OV511_REG_BUS, 0x71, 0x19 },
+ { OV511_DONE_BUS, 0x0, 0x00 },
+ };
+
+ PDEBUG(4, "");
+
+ /* First 5 bits of custom ID reg are a revision ID on OV518 */
+ info("Device revision %d",
+ 0x1F & ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID));
+
+ if (ov511_write_regvals(ov511, aRegvalsInit518)) goto error;
+
+ /* Set LED GPIO pin to output mode */
+ if (ov511_reg_write_mask(dev, 0x57,0x00, 0x02) < 0) goto error;
+
+ /* LED is off by default with OV518; have to explicitly turn it on */
+ if (ov511->led_policy == LED_OFF || ov511->led_policy == LED_AUTO)
+ ov51x_led_control(ov511, 0);
+ else
+ ov51x_led_control(ov511, 1);
+
+ /* Don't require compression if dumppix is enabled; otherwise it's
+ * required. OV518 has no uncompressed mode, to save RAM. */
+ if (!dumppix && !ov511->compress) {
+ ov511->compress = 1;
+ warn("Compression required with OV518...enabling");
+ }
+
+ if (ov511_write_regvals(ov511, aRegvalsNorm518)) goto error;
+
+ if (ov511_reg_write(dev, 0x2f,0x80) < 0) goto error;
- if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
+ if (ov518_init_compression(ov511)) goto error;
+
+ ov511_set_packet_size(ov511, 0);
+
+ ov511->snap_enabled = snapshot;
+
+ /* Test for 76xx */
+ ov511->primary_i2c_slave = OV7xx0_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, OV7xx0_I2C_WRITE_ID,
+ OV7xx0_I2C_READ_ID) < 0)
goto error;
- if (ov511_i2c_write(dev, 0x12, 0x80) < 0) {
- /* Test for 6xx0 */
- if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
- OV6xx0_I2C_WRITE_ID) < 0)
- goto error;
+ /* The OV518 must be more aggressive about sensor detection since
+ * I2C write will never fail if the sensor is not present. We have
+ * to try to initialize the sensor to detect its presence */
- if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
- OV6xx0_I2C_READ_ID) < 0)
+ if (ov51x_init_ov_sensor(ov511) < 0) {
+ /* Test for 6xx0 */
+ ov511->primary_i2c_slave = OV6xx0_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, OV6xx0_I2C_WRITE_ID,
+ OV6xx0_I2C_READ_ID) < 0)
goto error;
- if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
- goto error;
+ if (ov51x_init_ov_sensor(ov511) < 0) {
+ /* Test for 8xx0 */
+ ov511->primary_i2c_slave = OV8xx0_I2C_WRITE_ID;
+ if (ov51x_set_slave_ids(ov511, OV8xx0_I2C_WRITE_ID,
+ OV8xx0_I2C_READ_ID) < 0)
+ goto error;
- if (ov511_i2c_write(dev, 0x12, 0x80) < 0) {
- err("Can't determine sensor slave IDs");
- goto error;
- }
-
- if(ov6xx0_configure(ov511) < 0) {
- err("failed to configure OV6xx0");
- goto error;
+ if (ov51x_init_ov_sensor(ov511) < 0) {
+ err("Can't determine sensor slave IDs");
+ goto error;
+ } else {
+ err("Detected unsupported OV8xx0 sensor");
+ goto error;
+ }
+ } else {
+ if (ov6xx0_configure(ov511) < 0) {
+ err("Failed to configure OV6xx0");
+ goto error;
+ }
}
} else {
- if(ov76xx_configure(ov511) < 0) {
- err("failed to configure OV76xx");
+ if (ov7xx0_configure(ov511) < 0) {
+ err("Failed to configure OV7xx0");
goto error;
}
}
-
- /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
- * (using read() instead). */
- for (i = 0; i < OV511_NUMFRAMES; i++) {
- ov511->frame[i].width = ov511->maxwidth;
- ov511->frame[i].height = ov511->maxheight;
- ov511->frame[i].depth = 24;
- ov511->frame[i].bytes_read = 0;
- ov511->frame[i].segment = 0;
- ov511->frame[i].format = VIDEO_PALETTE_RGB24;
- ov511->frame[i].segsize = GET_SEGSIZE(ov511->frame[i].format);
- }
- /* Initialize to max width/height, RGB24 */
- if (ov511_mode_init_regs(ov511, ov511->maxwidth, ov511->maxheight,
- VIDEO_PALETTE_RGB24, 0) < 0)
- goto error;
+ // The OV518 cannot go as low as the sensor can
+ ov511->minwidth = 160;
+ ov511->minheight = 120;
return 0;
-
+
error:
- usb_driver_release_interface(&ov511_driver,
- &dev->actconfig->interface[ov511->iface]);
+ err("OV518 Config failed");
- return -EBUSY;
+ return -EBUSY;
}
@@ -3245,12 +6687,13 @@ error:
***************************************************************************/
static void *
-ov511_probe(struct usb_device *dev, unsigned int ifnum,
- const struct usb_device_id *id)
+ov51x_probe(struct usb_device *dev, unsigned int ifnum,
+ const struct usb_device_id *id)
{
struct usb_interface_descriptor *interface;
struct usb_ov511 *ov511;
int i;
+ int registered = 0;
PDEBUG(1, "probing for device...");
@@ -3271,98 +6714,147 @@ ov511_probe(struct usb_device *dev, unsigned int ifnum,
if ((ov511 = kmalloc(sizeof(*ov511), GFP_KERNEL)) == NULL) {
err("couldn't kmalloc ov511 struct");
- goto error;
+ goto error_unlock;
}
memset(ov511, 0, sizeof(*ov511));
ov511->dev = dev;
ov511->iface = interface->bInterfaceNumber;
+ ov511->led_policy = led;
+ ov511->compress = compress;
+ ov511->lightfreq = lightfreq;
+ ov511->num_inputs = 1; /* Video decoder init functs. change this */
+ ov511->stop_during_set = !fastset;
+ ov511->tuner_type = tuner;
+ ov511->backlight = backlight;
+
+ ov511->auto_brt = autobright;
+ ov511->auto_gain = autogain;
+ ov511->auto_exp = autoexp;
switch (dev->descriptor.idProduct) {
- case 0x0511:
+ case PROD_OV511:
info("USB OV511 camera found");
ov511->bridge = BRG_OV511;
+ ov511->bclass = BCL_OV511;
break;
- case 0xA511:
+ case PROD_OV511PLUS:
info("USB OV511+ camera found");
ov511->bridge = BRG_OV511PLUS;
+ ov511->bclass = BCL_OV511;
+ break;
+ case PROD_OV518:
+ info("USB OV518 camera found");
+ ov511->bridge = BRG_OV518;
+ ov511->bclass = BCL_OV518;
break;
- case 0x0002:
- if (dev->descriptor.idVendor != 0x0813)
+ case PROD_OV518PLUS:
+ info("USB OV518+ camera found");
+ ov511->bridge = BRG_OV518PLUS;
+ ov511->bclass = BCL_OV518;
+ break;
+ case PROD_ME2CAM:
+ if (dev->descriptor.idVendor != VEND_MATTEL)
goto error;
info("Intel Play Me2Cam (OV511+) found");
ov511->bridge = BRG_OV511PLUS;
+ ov511->bclass = BCL_OV511;
break;
default:
- err("Unknown product ID");
- goto error;
+ err("Unknown product ID 0x%x", dev->descriptor.idProduct);
+ goto error_dealloc;
}
- ov511->customid = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
- if (ov511->customid < 0) {
- err("Unable to read camera bridge registers");
- goto error;
+ /* Workaround for some applications that want data in RGB
+ * instead of BGR. */
+ if (force_rgb)
+ info("data format set to RGB");
+
+ init_waitqueue_head(&ov511->wq);
+
+ init_MUTEX(&ov511->lock); /* to 1 == available */
+ init_MUTEX(&ov511->buf_lock);
+ init_MUTEX(&ov511->param_lock);
+ init_MUTEX(&ov511->i2c_lock);
+ ov511->buf_state = BUF_NOT_ALLOCATED;
+
+ if (ov511->bridge == BRG_OV518 ||
+ ov511->bridge == BRG_OV518PLUS) {
+ if (ov518_configure(ov511) < 0)
+ goto error;
+ } else {
+ if (ov511_configure(ov511) < 0)
+ goto error;
}
- ov511->desc = -1;
- PDEBUG (4, "CustomID = %d", ov511->customid);
- for (i = 0; clist[i].id >= 0; i++) {
- if (ov511->customid == clist[i].id) {
- info("camera: %s", clist[i].description);
- ov511->desc = i;
- break;
- }
+ for (i = 0; i < OV511_NUMFRAMES; i++) {
+ ov511->frame[i].framenum = i;
+ init_waitqueue_head(&ov511->frame[i].wq);
}
- /* Lifeview USB Life TV not supported */
- if (clist[i].id == 38) {
- err("This device is not supported yet.");
+ /* Unnecessary? (This is done on open(). Need to make sure variables
+ * are properly initialized without this before removing it, though). */
+ if (ov51x_set_default_params(ov511) < 0)
goto error;
- }
- if (clist[i].id == -1) {
- err("Camera type (%d) not recognized", ov511->customid);
- err("Please contact mwm@i.am to request");
- err("support for your camera.");
- }
+#ifdef OV511_DEBUG
+ if (dump_bridge)
+ ov511_dump_regs(dev);
+#endif
- /* Workaround for some applications that want data in RGB
- * instead of BGR */
- if (force_rgb)
- info("data format set to RGB");
+ memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template));
+ ov511->vdev.priv = ov511;
- if (!ov511_configure(ov511)) {
- ov511->user = 0;
- init_MUTEX(&ov511->lock); /* to 1 == available */
- init_MUTEX(&ov511->buf_lock);
- ov511->buf_state = BUF_NOT_ALLOCATED;
- } else {
- err("Failed to configure camera");
- goto error;
+ for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
+ /* Minor 0 cannot be specified; assume user wants autodetect */
+ if (unit_video[i] == 0)
+ break;
+
+ if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER,
+ unit_video[i]) >= 0) {
+ registered = 1;
+ break;
+ }
}
- if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+ /* Use the next available one */
+ if (!registered &&
+ video_register_device(&ov511->vdev, VFL_TYPE_GRABBER, -1) < 0) {
err("video_register_device failed");
goto error;
}
+ info("Device registered on minor %d", ov511->vdev.minor);
+
MOD_DEC_USE_COUNT;
return ov511;
error:
+ err("Camera initialization failed");
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+ /* Safe to call even if entry doesn't exist */
+ destroy_proc_ov511_cam(ov511);
+#endif
+
+ usb_driver_release_interface(&ov511_driver,
+ &dev->actconfig->interface[ov511->iface]);
+
+error_dealloc:
if (ov511) {
kfree(ov511);
ov511 = NULL;
}
+error_unlock:
MOD_DEC_USE_COUNT;
return NULL;
}
static void
-ov511_disconnect(struct usb_device *dev, void *ptr)
+ov51x_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
int n;
@@ -3422,8 +6914,8 @@ ov511_disconnect(struct usb_device *dev, void *ptr)
static struct usb_driver ov511_driver = {
name: "ov511",
id_table: device_table,
- probe: ov511_probe,
- disconnect: ov511_disconnect
+ probe: ov51x_probe,
+ disconnect: ov51x_disconnect
};
@@ -3433,7 +6925,88 @@ static struct usb_driver ov511_driver = {
*
***************************************************************************/
-static int __init usb_ov511_init(void)
+/* Returns 0 for success */
+int
+ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, int ov518,
+ int mmx)
+{
+ if (ver != DECOMP_INTERFACE_VER) {
+ err("Decompression module has incompatible");
+ err("interface version %d", ver);
+ err("Interface version %d is required", DECOMP_INTERFACE_VER);
+ return -EINVAL;
+ }
+
+ if (!ops)
+ return -EFAULT;
+
+ if (mmx && !ov51x_mmx_available) {
+ err("MMX not available on this system or kernel");
+ return -EINVAL;
+ }
+
+ lock_kernel();
+
+ if (ov518) {
+ if (mmx) {
+ if (ov518_mmx_decomp_ops)
+ goto err_in_use;
+ else
+ ov518_mmx_decomp_ops = ops;
+ } else {
+ if (ov518_decomp_ops)
+ goto err_in_use;
+ else
+ ov518_decomp_ops = ops;
+ }
+ } else {
+ if (mmx) {
+ if (ov511_mmx_decomp_ops)
+ goto err_in_use;
+ else
+ ov511_mmx_decomp_ops = ops;
+ } else {
+ if (ov511_decomp_ops)
+ goto err_in_use;
+ else
+ ov511_decomp_ops = ops;
+ }
+ }
+
+ MOD_INC_USE_COUNT;
+
+ unlock_kernel();
+ return 0;
+
+err_in_use:
+ unlock_kernel();
+ return -EBUSY;
+}
+
+void
+ov511_deregister_decomp_module(int ov518, int mmx)
+{
+ lock_kernel();
+
+ if (ov518) {
+ if (mmx)
+ ov518_mmx_decomp_ops = NULL;
+ else
+ ov518_decomp_ops = NULL;
+ } else {
+ if (mmx)
+ ov511_mmx_decomp_ops = NULL;
+ else
+ ov511_decomp_ops = NULL;
+ }
+
+ MOD_DEC_USE_COUNT;
+
+ unlock_kernel();
+}
+
+static int __init
+usb_ov511_init(void)
{
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
proc_ov511_create();
@@ -3442,20 +7015,33 @@ static int __init usb_ov511_init(void)
if (usb_register(&ov511_driver) < 0)
return -1;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ // FIXME: Don't know how to determine this yet
+ ov51x_mmx_available = 0;
+
+#if defined (__i386__)
+ if (test_bit(X86_FEATURE_MMX, &boot_cpu_data.x86_capability))
+ ov51x_mmx_available = 1;
+#endif
+
+ info(DRIVER_VERSION " : " DRIVER_DESC);
return 0;
}
-static void __exit usb_ov511_exit(void)
+static void __exit
+usb_ov511_exit(void)
{
usb_deregister(&ov511_driver);
info("driver deregistered");
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
proc_ov511_destroy();
-#endif
+#endif
}
module_init(usb_ov511_init);
module_exit(usb_ov511_exit);
+
+/* No version, for compatibility with binary-only modules */
+EXPORT_SYMBOL_NOVERS(ov511_register_decomp_module);
+EXPORT_SYMBOL_NOVERS(ov511_deregister_decomp_module);
diff --git a/drivers/usb/ov511.h b/drivers/usb/ov511.h
index a4ef7dacd..a3f55f7e5 100644
--- a/drivers/usb/ov511.h
+++ b/drivers/usb/ov511.h
@@ -1,20 +1,41 @@
-
#ifndef __LINUX_OV511_H
#define __LINUX_OV511_H
#include <asm/uaccess.h>
#include <linux/videodev.h>
#include <linux/smp_lock.h>
+#include <linux/usb.h>
#define OV511_DEBUG /* Turn on debug messages */
#ifdef OV511_DEBUG
# define PDEBUG(level, fmt, args...) \
-if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
+if (debug >= (level)) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , \
+ ## args)
#else
# define PDEBUG(level, fmt, args...) do {} while(0)
#endif
+/* This macro restricts an int variable to an inclusive range */
+#define RESTRICT_TO_RANGE(v,mi,ma) { \
+ if ((v) < (mi)) (v) = (mi); \
+ else if ((v) > (ma)) (v) = (ma); \
+}
+
+/* --------------------------------- */
+/* DEFINES FOR OV511 AND OTHER CHIPS */
+/* --------------------------------- */
+
+/* USB IDs */
+#define VEND_OMNIVISION 0x05A9
+#define PROD_OV511 0x0511
+#define PROD_OV511PLUS 0xA511
+#define PROD_OV518 0x0518
+#define PROD_OV518PLUS 0xA518
+
+#define VEND_MATTEL 0x0813
+#define PROD_ME2CAM 0x0002
+
/* Camera interface register numbers */
#define OV511_REG_CAMERA_DELAY_MODE 0x10
#define OV511_REG_CAMERA_EDGE_MODE 0x11
@@ -52,6 +73,7 @@ if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args
/* I2C register numbers */
#define OV511_REG_I2C_CONTROL 0x40
+#define OV518_REG_I2C_CONTROL 0x47 /* OV518(+) only */
#define OV511_REG_I2C_SLAVE_ID_WRITE 0x41
#define OV511_REG_I2C_SUB_ADDRESS_3_BYTE 0x42
#define OV511_REG_I2C_SUB_ADDRESS_2_BYTE 0x43
@@ -78,8 +100,16 @@ if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args
#define OV511_REG_SYSTEM_CLOCK_DIVISOR 0x51
#define OV511_REG_SYSTEM_SNAPSHOT 0x52
#define OV511_REG_SYSTEM_INIT 0x53
-#define OV511_REG_SYSTEM_PWR_CLK 0x54 /* OV511+ only */
+#define OV511_REG_SYSTEM_PWR_CLK 0x54 /* OV511+/OV518(+) only */
#define OV511_REG_SYSTEM_LED_CTL 0x55 /* OV511+ only */
+#define OV518_REG_GPIO_IN 0x55 /* OV518(+) only */
+#define OV518_REG_GPIO_OUT 0x56 /* OV518(+) only */
+#define OV518_REG_GPIO_CTL 0x57 /* OV518(+) only */
+#define OV518_REG_GPIO_PULSE_IN 0x58 /* OV518(+) only */
+#define OV518_REG_GPIO_PULSE_CLEAR 0x59 /* OV518(+) only */
+#define OV518_REG_GPIO_PULSE_POLARITY 0x5a /* OV518(+) only */
+#define OV518_REG_GPIO_PULSE_EN 0x5b /* OV518(+) only */
+#define OV518_REG_GPIO_RESET 0x5c /* OV518(+) only */
#define OV511_REG_SYSTEM_USER_DEFINED 0x5E
#define OV511_REG_SYSTEM_CUSTOM_ID 0x5F
@@ -119,6 +149,16 @@ if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args
#define OV511PLUS_ALT_SIZE_769 6
#define OV511PLUS_ALT_SIZE_961 7
+/* Alternate numbers for various max packet sizes (OV518(+) only) */
+#define OV518_ALT_SIZE_0 0
+#define OV518_ALT_SIZE_128 1
+#define OV518_ALT_SIZE_256 2
+#define OV518_ALT_SIZE_384 3
+#define OV518_ALT_SIZE_512 4
+#define OV518_ALT_SIZE_640 5
+#define OV518_ALT_SIZE_768 6
+#define OV518_ALT_SIZE_896 7
+
/* OV7610 registers */
#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
#define OV7610_REG_BLUE 0x01 /* blue channel balance */
@@ -170,45 +210,75 @@ if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args
/* 36-37 reserved */
#define OV7610_REG_COM_K 0x38 /* misc registers */
-
-#define SCRATCH_BUF_SIZE 512
-
#define FRAMES_PER_DESC 10 /* FIXME - What should this be? */
#define FRAME_SIZE_PER_DESC 993 /* FIXME - Deprecated */
#define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */
+#define PIXELS_PER_SEG 256 /* Pixels per segment */
#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */
-// CAMERA SPECIFIC
-// FIXME - these can vary between specific models
-#define OV7610_I2C_WRITE_ID 0x42
-#define OV7610_I2C_READ_ID 0x43
-#define OV6xx0_I2C_WRITE_ID 0xC0
-#define OV6xx0_I2C_READ_ID 0xC1
+/* I2C addresses */
+#define OV7xx0_I2C_WRITE_ID 0x42
+#define OV7xx0_I2C_READ_ID 0x43
+#define OV6xx0_I2C_WRITE_ID 0xC0
+#define OV6xx0_I2C_READ_ID 0xC1
+#define OV8xx0_I2C_WRITE_ID 0xA0
+#define OV8xx0_I2C_READ_ID 0xA1
+#define KS0127_I2C_WRITE_ID 0xD8
+#define KS0127_I2C_READ_ID 0xD9
+#define SAA7111A_I2C_WRITE_ID 0x48
+#define SAA7111A_I2C_READ_ID 0x49
#define OV511_I2C_CLOCK_PRESCALER 0x03
-/* Prototypes */
-int usb_ov511_reg_read(struct usb_device *dev, unsigned char reg);
-int usb_ov511_reg_write(struct usb_device *dev,
- unsigned char reg,
- unsigned char value);
-
/* Bridge types */
enum {
+ BRG_UNKNOWN,
BRG_OV511,
BRG_OV511PLUS,
+ BRG_OV518,
+ BRG_OV518PLUS,
+};
+
+/* Bridge classes */
+enum {
+ BCL_UNKNOWN,
+ BCL_OV511,
+ BCL_OV518,
};
/* Sensor types */
enum {
SEN_UNKNOWN,
+ SEN_OV76BE,
SEN_OV7610,
SEN_OV7620,
SEN_OV7620AE,
SEN_OV6620,
+ SEN_OV6630,
+ SEN_OV6630AE,
+ SEN_OV6630AF,
+ SEN_OV8600,
+ SEN_KS0127,
+ SEN_KS0127B,
+ SEN_SAA7111A,
};
+// Not implemented yet
+#if 0
+/* Sensor classes */
+enum {
+ SCL_UNKNOWN,
+ SCL_OV7610, /* 7610, 76BE, 7620AE (for now) */
+ SCL_OV7620,
+ SCL_OV6620,
+ SCL_OV6630, /* 6630, 6630AE, 6630AF */
+ SCL_OV8600,
+ SCL_KS0127, /* SEN_KS0127, SEN_KS0127B */
+ SCL_SAA7111A,
+};
+#endif
+
enum {
STATE_SCANNING, /* Scanning for start */
STATE_HEADER, /* Parsing header */
@@ -222,7 +292,77 @@ enum {
BUF_PEND_DEALLOC, /* ov511->buf_timer is set */
};
-struct usb_device;
+/* --------- Definition of ioctl interface --------- */
+
+#define OV511_INTERFACE_VER 101
+
+/* LED options */
+enum {
+ LED_OFF,
+ LED_ON,
+ LED_AUTO,
+};
+
+/* Raw frame formats */
+enum {
+ RAWFMT_INVALID,
+ RAWFMT_YUV400,
+ RAWFMT_YUV420,
+ RAWFMT_YUV422,
+ RAWFMT_GBR422,
+};
+
+/* Unsigned short option numbers */
+enum {
+ OV511_USOPT_INVALID,
+ OV511_USOPT_BRIGHT,
+ OV511_USOPT_SAT,
+ OV511_USOPT_HUE,
+ OV511_USOPT_CONTRAST,
+};
+
+/* Unsigned int option numbers */
+enum {
+ OV511_UIOPT_INVALID,
+ OV511_UIOPT_POWER_FREQ,
+ OV511_UIOPT_BFILTER,
+ OV511_UIOPT_LED,
+ OV511_UIOPT_DEBUG,
+ OV511_UIOPT_COMPRESS,
+};
+
+struct ov511_ushort_opt {
+ int optnum; /* Specific option number */
+ unsigned short val;
+};
+
+struct ov511_uint_opt {
+ int optnum; /* Specific option number */
+ unsigned int val;
+};
+
+struct ov511_i2c_struct {
+ unsigned char slave; /* Write slave ID (read ID - 1) */
+ unsigned char reg; /* Index of register */
+ unsigned char value; /* User sets this w/ write, driver does w/ read */
+ unsigned char mask; /* Bits to be changed. Not used with read ops */
+};
+
+/* ioctls */
+#define OV511IOC_GINTVER _IOR('v', BASE_VIDIOCPRIVATE + 0, int)
+#define OV511IOC_GUSHORT _IOWR('v', BASE_VIDIOCPRIVATE + 1, \
+ struct ov511_ushort_opt)
+#define OV511IOC_SUSHORT _IOW('v', BASE_VIDIOCPRIVATE + 2, \
+ struct ov511_ushort_opt)
+#define OV511IOC_GUINT _IOWR('v', BASE_VIDIOCPRIVATE + 3, \
+ struct ov511_uint_opt)
+#define OV511IOC_SUINT _IOW('v', BASE_VIDIOCPRIVATE + 4, \
+ struct ov511_uint_opt)
+#define OV511IOC_WI2C _IOW('v', BASE_VIDIOCPRIVATE + 5, \
+ struct ov511_i2c_struct)
+#define OV511IOC_RI2C _IOWR('v', BASE_VIDIOCPRIVATE + 6, \
+ struct ov511_i2c_struct)
+/* ------------- End IOCTL interface -------------- */
struct ov511_sbuf {
char *data;
@@ -248,36 +388,51 @@ struct ov511_regvals {
};
struct ov511_frame {
+ int framenum; /* Index of this frame */
char *data; /* Frame buffer */
+ char *tempdata; /* Temp buffer for multi-stage conversions */
+ char *rawdata; /* Raw camera data buffer */
int depth; /* Bytes per pixel */
int width; /* Width application is expecting */
- int height; /* Height */
+ int height; /* Height application is expecting */
- int hdrwidth; /* Width the frame actually is */
- int hdrheight; /* Height */
+ int rawwidth; /* Actual width of frame sent from camera */
+ int rawheight; /* Actual height of frame sent from camera */
int sub_flag; /* Sub-capture mode for this frame? */
unsigned int format; /* Format for this frame */
- int segsize; /* How big is each segment from the camera? */
+ int compressed; /* Is frame compressed? */
volatile int grabstate; /* State of grabbing */
int scanstate; /* State of scanning */
- int curline; /* Line of frame we're working on */
- int curpix;
- int segment; /* Segment from the incoming data */
+ int bytes_recvd; /* Number of image bytes received from camera */
- long scanlength; /* uncompressed, raw data length of frame */
- long bytes_read; /* amount of scanlength that has been read from *data */
+ long bytes_read; /* Amount that has been read() */
wait_queue_head_t wq; /* Processes waiting */
int snapshot; /* True if frame was a snapshot */
};
+#define DECOMP_INTERFACE_VER 2
+
+/* Compression module operations */
+struct ov51x_decomp_ops {
+ int (*decomp_400)(unsigned char *, unsigned char *, int, int, int);
+ int (*decomp_420)(unsigned char *, unsigned char *, int, int, int);
+ int (*decomp_422)(unsigned char *, unsigned char *, int, int, int);
+ void (*decomp_lock)(void);
+ void (*decomp_unlock)(void);
+};
+
#define OV511_NUMFRAMES 2
-#define OV511_NUMSBUF 2
+#if OV511_NUMFRAMES > VIDEO_MAX_FRAME
+#error "OV511_NUMFRAMES is too high"
+#endif
+
+#define OV511_NUMSBUF 2
struct usb_ov511 {
struct video_device vdev;
@@ -292,22 +447,37 @@ struct usb_ov511 {
/* Determined by sensor type */
int maxwidth;
int maxheight;
+ int minwidth;
+ int minheight;
int brightness;
int colour;
int contrast;
int hue;
int whiteness;
+ int exposure;
+ int auto_brt; /* Auto brightness enabled flag */
+ int auto_gain; /* Auto gain control enabled flag */
+ int auto_exp; /* Auto exposure enabled flag */
+ int backlight; /* Backlight exposure algorithm flag */
- struct semaphore lock;
+ int led_policy; /* LED: off|on|auto; OV511+ only */
+
+ struct semaphore lock; /* Serializes user-accessible operations */
int user; /* user count for exclusive use */
int streaming; /* Are we streaming Isochronous? */
int grabbing; /* Are we grabbing? */
int compress; /* Should the next frame be compressed? */
+ int compress_inited; /* Are compression params uploaded? */
+
+ int lightfreq; /* Power (lighting) frequency */
+ int bandfilt; /* Banding filter enabled flag */
char *fbuf; /* Videodev buffer area */
+ char *tempfbuf; /* Temporary (intermediate) buffer area */
+ char *rawfbuf; /* Raw camera data buffer area */
int sub_flag; /* Pix Array subcapture on flag */
int subx; /* Pix Array subcapture x offset */
@@ -318,30 +488,53 @@ struct usb_ov511 {
int curframe; /* Current receiving sbuf */
struct ov511_frame frame[OV511_NUMFRAMES];
- int cursbuf; /* Current receiving sbuf */
struct ov511_sbuf sbuf[OV511_NUMSBUF];
- /* Scratch space from the Isochronous pipe */
- unsigned char scratch[SCRATCH_BUF_SIZE];
- int scratchlen;
-
wait_queue_head_t wq; /* Processes waiting */
int snap_enabled; /* Snapshot mode enabled */
- int bridge; /* Type of bridge (OV511 or OV511+) */
- int sensor; /* Type of image sensor chip */
+ int bridge; /* Type of bridge (BRG_*) */
+ int bclass; /* Class of bridge (BCL_*) */
+ int sensor; /* Type of image sensor chip (SEN_*) */
+ int sclass; /* Type of image sensor chip (SCL_*) */
+ int tuner; /* Type of TV tuner */
int packet_size; /* Frame size per isoc desc */
- /* proc interface */
struct semaphore param_lock; /* params lock for this camera */
- struct proc_dir_entry *proc_entry; /* /proc/ov511/videoX */
-
+
+ /* /proc entries, relative to /proc/video/ov511/ */
+ struct proc_dir_entry *proc_devdir; /* Per-device proc directory */
+ struct proc_dir_entry *proc_info; /* <minor#>/info entry */
+ struct proc_dir_entry *proc_button; /* <minor#>/button entry */
+ struct proc_dir_entry *proc_control; /* <minor#>/control entry */
+
/* Framebuffer/sbuf management */
int buf_state;
struct semaphore buf_lock;
struct timer_list buf_timer;
+
+ struct ov51x_decomp_ops *decomp_ops;
+
+ /* Stop streaming while changing picture settings */
+ int stop_during_set;
+
+ int stopped; /* Streaming is temporarily paused */
+
+ /* Video decoder stuff */
+ int input; /* Composite, S-VIDEO, etc... */
+ int num_inputs; /* Number of inputs */
+ int norm; /* NTSC / PAL / SECAM */
+ int has_decoder; /* Device has a video decoder */
+ int has_tuner; /* Device has a TV tuner */
+ int has_audio_proc; /* Device has an audio processor */
+ int freq; /* Current tuner frequency */
+ int tuner_type; /* Specific tuner model */
+
+ /* I2C interface to kernel */
+ struct semaphore i2c_lock; /* Protect I2C controller regs */
+ unsigned char primary_i2c_slave; /* I2C write id of sensor */
};
struct cam_list {
@@ -354,18 +547,57 @@ struct palette_list {
char *name;
};
-struct mode_list {
+struct mode_list_518 {
int width;
int height;
- int color; /* 0=grayscale, 1=color */
- u8 pxcnt; /* pixel counter */
- u8 lncnt; /* line counter */
- u8 pxdv; /* pixel divisor */
- u8 lndv; /* line divisor */
- u8 m420;
- u8 common_A;
- u8 common_L;
+ u8 reg28;
+ u8 reg29;
+ u8 reg2a;
+ u8 reg2c;
+ u8 reg2e;
+ u8 reg24;
+ u8 reg25;
};
-#endif
+/* Compression stuff */
+
+#define OV511_QUANTABLESIZE 64
+#define OV518_QUANTABLESIZE 32
+
+#define OV511_YQUANTABLE { \
+ 0, 1, 1, 2, 2, 3, 3, 4, \
+ 1, 1, 1, 2, 2, 3, 4, 4, \
+ 1, 1, 2, 2, 3, 4, 4, 4, \
+ 2, 2, 2, 3, 4, 4, 4, 4, \
+ 2, 2, 3, 4, 4, 5, 5, 5, \
+ 3, 3, 4, 4, 5, 5, 5, 5, \
+ 3, 4, 4, 4, 5, 5, 5, 5, \
+ 4, 4, 4, 4, 5, 5, 5, 5 \
+}
+
+#define OV511_UVQUANTABLE { \
+ 0, 2, 2, 3, 4, 4, 4, 4, \
+ 2, 2, 2, 4, 4, 4, 4, 4, \
+ 2, 2, 3, 4, 4, 4, 4, 4, \
+ 3, 4, 4, 4, 4, 4, 4, 4, \
+ 4, 4, 4, 4, 4, 4, 4, 4, \
+ 4, 4, 4, 4, 4, 4, 4, 4, \
+ 4, 4, 4, 4, 4, 4, 4, 4, \
+ 4, 4, 4, 4, 4, 4, 4, 4 \
+}
+
+#define OV518_YQUANTABLE { \
+ 5, 4, 5, 6, 6, 7, 7, 7, \
+ 5, 5, 5, 5, 6, 7, 7, 7, \
+ 6, 6, 6, 6, 7, 7, 7, 8, \
+ 7, 7, 6, 7, 7, 7, 8, 8 \
+}
+
+#define OV518_UVQUANTABLE { \
+ 6, 6, 6, 7, 7, 7, 7, 7, \
+ 6, 6, 6, 7, 7, 7, 7, 7, \
+ 6, 6, 6, 7, 7, 7, 7, 8, \
+ 7, 7, 7, 7, 7, 7, 8, 8 \
+}
+#endif
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 881119273..3b12890a4 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -201,7 +201,7 @@ static int usblp_check_status(struct usblp *usblp, int err)
static int usblp_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev) - USBLP_MINOR_BASE;
+ int minor = minor(inode->i_rdev) - USBLP_MINOR_BASE;
struct usblp *usblp;
int retval;
diff --git a/drivers/usb/pwc-ctrl.c b/drivers/usb/pwc-ctrl.c
index 3d8eb253a..a6ba654b6 100644
--- a/drivers/usb/pwc-ctrl.c
+++ b/drivers/usb/pwc-ctrl.c
@@ -1008,6 +1008,8 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
if (pdev->type < 730)
return 0;
+ on_value /= 100;
+ off_value /= 100;
if (on_value < 0)
on_value = 0;
if (on_value > 0xff)
@@ -1048,8 +1050,8 @@ int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
if (ret < 0)
return ret;
- *on_value = buf[0];
- *off_value = buf[1];
+ *on_value = buf[0] * 100;
+ *off_value = buf[1] * 100;
return 0;
}
@@ -1175,6 +1177,8 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
wb.read_red = pwc_read_red_gain(pdev);
wb.read_blue = pwc_read_blue_gain(pdev);
}
+ if (copy_to_user(arg, &wb, sizeof(wb)))
+ return -EFAULT;
break;
}
diff --git a/drivers/usb/pwc-if.c b/drivers/usb/pwc-if.c
index 9c7e10b98..bac4b10b4 100644
--- a/drivers/usb/pwc-if.c
+++ b/drivers/usb/pwc-if.c
@@ -39,7 +39,10 @@
/* Contributors:
- Alvarado: adding whitebalance code
- - Alistar Moire: QuickCam 3000 Pro testing
+ - Alistar Moire: QuickCam 3000 Pro device/product ID
+ - Tony Hoyle: Creative Labs Webcam 5 device/product ID
+ - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
+ - Jk Fang: SOTEC device/product ID
*/
#include <linux/errno.h>
@@ -76,6 +79,8 @@ static __devinitdata struct usb_device_id pwc_device_table [] = {
{ USB_DEVICE(0x046D, 0x08b0) },
{ USB_DEVICE(0x055D, 0x9000) },
{ USB_DEVICE(0x055D, 0x9001) },
+ { USB_DEVICE(0x041E, 0x400C) },
+ { USB_DEVICE(0x04CC, 0x8116) },
{ }
};
MODULE_DEVICE_TABLE(usb, pwc_device_table);
@@ -624,7 +629,7 @@ static int pwc_set_palette(struct pwc_device *pdev, int pal)
/* This gets called for the Isochronous pipe (video). This is done in
* interrupt time, so it has to be fast, not crash, and not stall. Neat.
*/
-static void pwc_isoc_handler(purb_t urb)
+static void pwc_isoc_handler(struct urb *urb)
{
struct pwc_device *pdev;
int i, fst, flen;
@@ -786,7 +791,7 @@ static void pwc_isoc_handler(purb_t urb)
static int pwc_isoc_init(struct pwc_device *pdev)
{
struct usb_device *udev;
- purb_t urb;
+ struct urb *urb;
int i, j, ret;
struct usb_interface_descriptor *idesc;
@@ -887,6 +892,7 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
/* Stop camera, but only if we are sure the camera is still there */
if (!pdev->unplugged)
usb_set_interface(pdev->udev, 0, 0);
+ /* Unlinking ISOC buffers one by one */
for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
pdev->sbuf[i].urb->next = NULL;
usb_unlink_urb(pdev->sbuf[i].urb);
@@ -1493,6 +1499,12 @@ static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *ar
*/
add_wait_queue(&pdev->frameq, &wait);
while (pdev->full_frames == NULL) {
+ if (pdev->unplugged) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -ENODEV;
+ }
+
if (signal_pending(current)) {
remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING);
@@ -1710,7 +1722,29 @@ static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const st
break;
}
}
- else return NULL; /* Not Philips, Askey, Logitech or Samsung, for sure. */
+ else if (vendor_id == 0x041e) {
+ switch(product_id) {
+ case 0x400c:
+ Info("Creative Labs Webcam 5 detected.\n");
+ type_id = 730;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ }
+ else if (vendor_id == 0x04cc) {
+ switch(product_id) {
+ case 0x8116:
+ Info("SOTEC CMS-001 USB webcam detected.\n");
+ type_id = 730;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ }
+ else return NULL; /* Not Philips, Askey, Logitech, Samsung, Creative or SOTEC, for sure. */
memset(serial_number, 0, 30);
usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
@@ -1780,16 +1814,6 @@ static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const st
if (hint < MAX_DEV_HINTS)
device_hint[hint].pdev = pdev;
-#if 0
- /* Shut down camera now (some people like the LED off) */
- if (power_save) {
- Trace(TRACE_PROBE, "Powering down camera");
- i = pwc_camera_power(pdev, 0);
- if (i < 0)
- Info("Failed to power-down the camera (%d)\n", i);
- }
-#endif
-
Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
return pdev;
}
@@ -1799,6 +1823,7 @@ static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
{
struct pwc_device *pdev;
int hint;
+ DECLARE_WAITQUEUE(wait, current);
lock_kernel();
free_mem_leak();
@@ -1833,13 +1858,19 @@ static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
*/
wake_up(&pdev->frameq);
- /* Wait until we get a 'go' from _close(). This
- had a gigantic race condition, since we kfree()
+ /* Wait until we get a 'go' from _close(). This used
+ to have a gigantic race condition, since we kfree()
stuff here, but we have to wait until close()
- is finished. */
+ is finished.
+ */
Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
- sleep_on(&pdev->remove_ok);
+ add_wait_queue(&pdev->remove_ok, &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ /* ... wait ... */
+ schedule();
+ remove_wait_queue(&pdev->remove_ok, &wait);
+ set_current_state(TASK_RUNNING);
Trace(TRACE_PROBE, "Done sleeping.\n");
set_mem_leak(pdev->vdev);
pdev->vdev = NULL;
@@ -1920,7 +1951,7 @@ static int __init usb_pwc_init(void)
char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
- Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro and the Samsung MPC-C10 and MPC-C30.\n");
+ Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30, the Creative WebCam 5 and the SOTEC CMS-001.\n");
if (fps) {
if (fps < 5 || fps > 30) {
diff --git a/drivers/usb/pwc-ioctl.h b/drivers/usb/pwc-ioctl.h
index 19b267a4c..6807cab91 100644
--- a/drivers/usb/pwc-ioctl.h
+++ b/drivers/usb/pwc-ioctl.h
@@ -79,8 +79,8 @@ struct pwc_whitebalance
/* Used with VIDIOCPWC[SG]LED */
struct pwc_leds
{
- int led_on; /* Led on-time; range = 0..255 */
- int led_off; /* */
+ int led_on; /* Led on-time; range = 0..25000 */
+ int led_off; /* Led off-time; range = 0..25000 */
};
diff --git a/drivers/usb/pwc.h b/drivers/usb/pwc.h
index 40bfb2784..28ebbb6c7 100644
--- a/drivers/usb/pwc.h
+++ b/drivers/usb/pwc.h
@@ -60,8 +60,8 @@
/* Version block */
#define PWC_MAJOR 8
-#define PWC_MINOR 4
-#define PWC_VERSION "8.4"
+#define PWC_MINOR 5
+#define PWC_VERSION "8.5"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
@@ -96,7 +96,7 @@ struct pwc_iso_buf
void *data;
int length;
int read;
- purb_t urb;
+ struct urb *urb;
};
/* intermediate buffers with raw data from the USB cam */
diff --git a/drivers/usb/scanner.c b/drivers/usb/scanner.c
index 2e17eabd2..bf1fdb968 100644
--- a/drivers/usb/scanner.c
+++ b/drivers/usb/scanner.c
@@ -365,7 +365,7 @@ open_scanner(struct inode * inode, struct file * file)
struct scn_usb_data *scn;
struct usb_device *dev;
- kdev_t scn_minor;
+ int scn_minor;
int err=0;
@@ -432,7 +432,7 @@ close_scanner(struct inode * inode, struct file * file)
{
struct scn_usb_data *scn;
- kdev_t scn_minor;
+ int scn_minor;
scn_minor = USB_SCN_MINOR (inode);
@@ -469,7 +469,7 @@ write_scanner(struct file * file, const char * buffer,
ssize_t bytes_written = 0; /* Overall count of bytes written */
ssize_t ret = 0;
- kdev_t scn_minor;
+ int scn_minor;
int this_write; /* Number of bytes to write */
int partial; /* Number of bytes successfully written */
@@ -556,8 +556,7 @@ read_scanner(struct file * file, char * buffer,
ssize_t bytes_read; /* Overall count of bytes_read */
ssize_t ret;
- kdev_t scn_minor;
-
+ int scn_minor;
int partial; /* Number of bytes successfully read */
int this_read; /* Max number of bytes to read */
int result;
@@ -671,7 +670,7 @@ ioctl_scanner(struct inode *inode, struct file *file,
{
struct usb_device *dev;
- kdev_t scn_minor;
+ int scn_minor;
scn_minor = USB_SCN_MINOR(inode);
@@ -810,8 +809,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
int ep_cnt;
int ix;
-
- kdev_t scn_minor;
+ int scn_minor;
char valid_device = 0;
char have_bulk_in, have_bulk_out, have_intr;
diff --git a/drivers/usb/scanner.h b/drivers/usb/scanner.h
index 2b03ce8f6..f7b9143bc 100644
--- a/drivers/usb/scanner.h
+++ b/drivers/usb/scanner.h
@@ -203,7 +203,7 @@ MODULE_DEVICE_TABLE (usb, scanner_device_ids);
#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
#define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
-#define USB_SCN_MINOR(X) MINOR((X)->i_rdev) - SCN_BASE_MNR
+#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
#ifdef DEBUG
#define SCN_DEBUG(X) X
@@ -243,7 +243,7 @@ struct scn_usb_data {
devfs_handle_t devfs; /* devfs device */
struct urb scn_irq;
unsigned int ifnum; /* Interface number of the USB device */
- kdev_t scn_minor; /* Scanner minor - used in disconnect() */
+ int scn_minor; /* Scanner minor - used in disconnect() */
unsigned char button; /* Front panel buffer */
char isopen; /* Not zero if the device is open */
char present; /* Not zero if device is present */
diff --git a/drivers/usb/serial/Config.in b/drivers/usb/serial/Config.in
index 62176c436..bc8302781 100644
--- a/drivers/usb/serial/Config.in
+++ b/drivers/usb/serial/Config.in
@@ -15,6 +15,7 @@ dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_
dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
+dep_tristate ' USB Compaq iPAQ Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL
dep_tristate ' USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
@@ -28,6 +29,7 @@ dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SER
dep_mbool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W $CONFIG_USB_SERIAL_KEYSPAN
dep_mbool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W $CONFIG_USB_SERIAL_KEYSPAN
dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate ' USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KLSI $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index e12f6295d..90c3dedcb 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -8,6 +8,7 @@ O_TARGET := usb-serial.o
obj-$(CONFIG_USB_SERIAL) += usbserial.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
+obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o
@@ -22,7 +23,8 @@ obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o
-
+obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
+
# Objects that export symbols.
export-objs := usbserial.o
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
new file mode 100644
index 000000000..6966bd9d5
--- /dev/null
+++ b/drivers/usb/serial/ipaq.c
@@ -0,0 +1,525 @@
+/*
+ * USB Compaq iPAQ driver
+ *
+ * Copyright (C) 2001
+ * Ganesh Varadarajan <ganesh@veritas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+ static int debug = 1;
+#else
+ static int debug = 0;
+#endif
+
+#include "usb-serial.h"
+#include "ipaq.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.1"
+#define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
+#define DRIVER_DESC "USB Compaq iPAQ driver"
+
+/* Function prototypes for an ipaq */
+static int ipaq_open (struct usb_serial_port *port, struct file *filp);
+static void ipaq_close (struct usb_serial_port *port, struct file *filp);
+static int ipaq_startup (struct usb_serial *serial);
+static void ipaq_shutdown (struct usb_serial *serial);
+static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigned char *buf,
+ int count);
+static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf,
+ int count);
+static int ipaq_write_flush(struct usb_serial_port *port);
+static void ipaq_read_bulk_callback (struct urb *urb);
+static void ipaq_write_bulk_callback(struct urb *urb);
+static int ipaq_write_room(struct usb_serial_port *port);
+static int ipaq_chars_in_buffer(struct usb_serial_port *port);
+static void ipaq_destroy_lists(struct usb_serial_port *port);
+
+
+static __devinitdata struct usb_device_id ipaq_id_table [] = {
+ { USB_DEVICE(IPAQ_VENDOR_ID, IPAQ_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, ipaq_id_table);
+
+/* All of the device info needed for the Compaq iPAQ */
+struct usb_serial_device_type ipaq_device = {
+ owner: THIS_MODULE,
+ name: "Compaq iPAQ",
+ id_table: ipaq_id_table,
+ num_interrupt_in: 0,
+ num_bulk_in: 1,
+ num_bulk_out: 1,
+ num_ports: 1,
+ open: ipaq_open,
+ close: ipaq_close,
+ startup: ipaq_startup,
+ shutdown: ipaq_shutdown,
+ write: ipaq_write,
+ write_room: ipaq_write_room,
+ chars_in_buffer: ipaq_chars_in_buffer,
+ read_bulk_callback: ipaq_read_bulk_callback,
+ write_bulk_callback: ipaq_write_bulk_callback,
+};
+
+static spinlock_t write_list_lock;
+static int bytes_in;
+static int bytes_out;
+
+static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+{
+ struct usb_serial *serial = port->serial;
+ struct ipaq_private *priv;
+ struct ipaq_packet *pkt;
+ int i, result = 0;
+
+ if (port_paranoia_check(port, __FUNCTION__)) {
+ return -ENODEV;
+ }
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ down(&port->sem);
+
+ ++port->open_count;
+
+ if (port->open_count == 1) {
+ bytes_in = 0;
+ bytes_out = 0;
+ priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
+ if (priv == NULL) {
+ err(__FUNCTION__ " - Out of memory");
+ return -ENOMEM;
+ }
+ port->private = (void *)priv;
+ priv->active = 0;
+ priv->queue_len = 0;
+ INIT_LIST_HEAD(&priv->queue);
+ INIT_LIST_HEAD(&priv->freelist);
+
+ for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) {
+ pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL);
+ if (pkt == NULL) {
+ goto enomem;
+ }
+ pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL);
+ if (pkt->data == NULL) {
+ kfree(pkt);
+ goto enomem;
+ }
+ pkt->len = 0;
+ pkt->written = 0;
+ INIT_LIST_HEAD(&pkt->list);
+ list_add(&pkt->list, &priv->freelist);
+ priv->free_len += PACKET_SIZE;
+ }
+
+ /*
+ * Force low latency on. This will immediately push data to the line
+ * discipline instead of queueing.
+ */
+
+ port->tty->low_latency = 1;
+
+ /*
+ * Lose the small buffers usbserial provides. Make larger ones.
+ */
+
+ kfree(port->bulk_in_buffer);
+ kfree(port->bulk_out_buffer);
+ port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
+ if (port->bulk_in_buffer == NULL) {
+ goto enomem;
+ }
+ port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
+ if (port->bulk_out_buffer == NULL) {
+ kfree(port->bulk_in_buffer);
+ goto enomem;
+ }
+ port->read_urb->transfer_buffer = port->bulk_in_buffer;
+ port->write_urb->transfer_buffer = port->bulk_out_buffer;
+ port->read_urb->transfer_buffer_length = URBDATA_SIZE;
+ port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
+
+ /* Start reading from the device */
+ FILL_BULK_URB(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+ ipaq_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb);
+ if (result) {
+ err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+ }
+
+ /*
+ * Send out two control messages observed in win98 sniffs. Not sure what
+ * they do.
+ */
+
+ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
+ 0x1, 0, NULL, 0, 5 * HZ);
+ if (result < 0) {
+ err(__FUNCTION__ " - failed doing control urb, error %d", result);
+ }
+ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
+ 0x1, 0, NULL, 0, 5 * HZ);
+ if (result < 0) {
+ err(__FUNCTION__ " - failed doing control urb, error %d", result);
+ }
+ }
+
+ up(&port->sem);
+
+ return result;
+
+enomem:
+ ipaq_destroy_lists(port);
+ kfree(priv);
+ err(__FUNCTION__ " - Out of memory");
+ return -ENOMEM;
+}
+
+
+static void ipaq_close(struct usb_serial_port *port, struct file *filp)
+{
+ struct usb_serial *serial;
+ struct ipaq_private *priv = port->private;
+
+ if (port_paranoia_check(port, __FUNCTION__)) {
+ return;
+ }
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ serial = get_usb_serial(port, __FUNCTION__);
+ if (!serial)
+ return;
+
+ down (&port->sem);
+
+ --port->open_count;
+
+ if (port->open_count <= 0) {
+
+ /*
+ * shut down bulk read and write
+ */
+
+ usb_unlink_urb(port->write_urb);
+ usb_unlink_urb(port->read_urb);
+ ipaq_destroy_lists(port);
+ kfree(priv);
+ port->private = NULL;
+ port->open_count = 0;
+
+ }
+ up (&port->sem);
+
+ /* Uncomment the following line if you want to see some statistics in your syslog */
+ /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
+}
+
+static void ipaq_read_bulk_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ int i, result;
+
+ if (port_paranoia_check(port, __FUNCTION__))
+ return;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ if (!serial) {
+ dbg(__FUNCTION__ " - bad serial pointer, exiting");
+ return;
+ }
+
+ if (urb->status) {
+ dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+ return;
+ }
+
+ usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+
+ tty = port->tty;
+ if (urb->actual_length) {
+ for (i = 0; i < urb->actual_length ; ++i) {
+ /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
+ if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ }
+ /* this doesn't actually push the data through unless tty->low_latency is set */
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ tty_flip_buffer_push(tty);
+ bytes_in += urb->actual_length;
+ }
+
+ /* Continue trying to always read */
+ FILL_BULK_URB(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+ ipaq_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb);
+ if (result)
+ err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+ return;
+}
+
+static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigned char *buf,
+ int count)
+{
+ const unsigned char *current_position = buf;
+ int bytes_sent = 0;
+ int transfer_size;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ usb_serial_debug_data(__FILE__, __FUNCTION__, count, buf);
+
+ while (count > 0) {
+ transfer_size = min(count, PACKET_SIZE);
+ if (ipaq_write_bulk(port, from_user, current_position, transfer_size)) {
+ break;
+ }
+ current_position += transfer_size;
+ bytes_sent += transfer_size;
+ count -= transfer_size;
+ bytes_out += transfer_size;
+ }
+
+ return bytes_sent;
+}
+
+static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf,
+ int count)
+{
+ struct ipaq_private *priv = port->private;
+ struct ipaq_packet *pkt = NULL;
+ int result = 0;
+ unsigned long flags;
+
+ if (priv->free_len <= 0) {
+ dbg(__FUNCTION__ " - we're stuffed");
+ return -EAGAIN;
+ }
+
+ spin_lock_irqsave(&write_list_lock, flags);
+ if (!list_empty(&priv->freelist)) {
+ pkt = list_entry(priv->freelist.next, struct ipaq_packet, list);
+ list_del(&pkt->list);
+ priv->free_len -= PACKET_SIZE;
+ }
+ spin_unlock_irqrestore(&write_list_lock, flags);
+ if (pkt == NULL) {
+ dbg(__FUNCTION__ " - we're stuffed");
+ return -EAGAIN;
+ }
+
+ if (from_user) {
+ copy_from_user(pkt->data, buf, count);
+ } else {
+ memcpy(pkt->data, buf, count);
+ }
+ usb_serial_debug_data(__FILE__, __FUNCTION__, count, pkt->data);
+
+ pkt->len = count;
+ pkt->written = 0;
+ spin_lock_irqsave(&write_list_lock, flags);
+ list_add_tail(&pkt->list, &priv->queue);
+ priv->queue_len += count;
+ if (priv->active == 0) {
+ priv->active = 1;
+ result = ipaq_write_flush(port);
+ }
+ spin_unlock_irqrestore(&write_list_lock, flags);
+ return result;
+}
+
+static int ipaq_write_flush(struct usb_serial_port *port)
+{
+ struct ipaq_private *priv = (struct ipaq_private *)port->private;
+ struct usb_serial *serial = port->serial;
+ int count, room, result;
+ struct ipaq_packet *pkt;
+ struct urb *urb = port->write_urb;
+ struct list_head *tmp;
+
+ if (urb->status == -EINPROGRESS) {
+ /* Should never happen */
+ err(__FUNCTION__ " - flushing while urb is active !");
+ return -EAGAIN;
+ }
+ room = URBDATA_SIZE;
+ for (tmp = priv->queue.next; tmp != &priv->queue;) {
+ pkt = list_entry(tmp, struct ipaq_packet, list);
+ tmp = tmp->next;
+ count = min(room, (int)(pkt->len - pkt->written));
+ memcpy(urb->transfer_buffer + (URBDATA_SIZE - room),
+ pkt->data + pkt->written, count);
+ room -= count;
+ pkt->written += count;
+ priv->queue_len -= count;
+ if (pkt->written == pkt->len) {
+ list_del(&pkt->list);
+ list_add(&pkt->list, &priv->freelist);
+ priv->free_len += PACKET_SIZE;
+ }
+ if (room == 0) {
+ break;
+ }
+ }
+
+ count = URBDATA_SIZE - room;
+ FILL_BULK_URB(port->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
+ port);
+ result = usb_submit_urb(urb);
+ if (result) {
+ err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+ }
+ return result;
+}
+
+static void ipaq_write_bulk_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct ipaq_private *priv = (struct ipaq_private *)port->private;
+ unsigned long flags;
+
+ if (port_paranoia_check (port, __FUNCTION__)) {
+ return;
+ }
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ if (urb->status) {
+ dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+ }
+
+ spin_lock_irqsave(&write_list_lock, flags);
+ if (!list_empty(&priv->queue)) {
+ ipaq_write_flush(port);
+ } else {
+ priv->active = 0;
+ }
+ spin_unlock_irqrestore(&write_list_lock, flags);
+ queue_task(&port->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+
+ return;
+}
+
+static int ipaq_write_room(struct usb_serial_port *port)
+{
+ struct ipaq_private *priv = (struct ipaq_private *)port->private;
+
+ dbg(__FUNCTION__ " - freelen %d", priv->free_len);
+ return priv->free_len;
+}
+
+static int ipaq_chars_in_buffer(struct usb_serial_port *port)
+{
+ struct ipaq_private *priv = (struct ipaq_private *)port->private;
+
+ dbg(__FUNCTION__ " - queuelen %d", priv->queue_len);
+ return priv->queue_len;
+}
+
+static void ipaq_destroy_lists(struct usb_serial_port *port)
+{
+ struct ipaq_private *priv = (struct ipaq_private *)port->private;
+ struct list_head *tmp;
+ struct ipaq_packet *pkt;
+
+ for (tmp = priv->queue.next; tmp != &priv->queue;) {
+ pkt = list_entry(tmp, struct ipaq_packet, list);
+ tmp = tmp->next;
+ kfree(pkt->data);
+ kfree(pkt);
+ }
+ for (tmp = priv->freelist.next; tmp != &priv->freelist;) {
+ pkt = list_entry(tmp, struct ipaq_packet, list);
+ tmp = tmp->next;
+ kfree(pkt->data);
+ kfree(pkt);
+ }
+ return;
+}
+
+
+static int ipaq_startup(struct usb_serial *serial)
+{
+ dbg(__FUNCTION__);
+ usb_set_configuration(serial->dev, 1);
+ return 0;
+}
+
+static void ipaq_shutdown(struct usb_serial *serial)
+{
+ int i;
+
+ dbg (__FUNCTION__);
+
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+ while (serial->port[i].open_count > 0) {
+ ipaq_close(&serial->port[i], NULL);
+ }
+ }
+}
+
+static int __init ipaq_init(void)
+{
+ usb_serial_register(&ipaq_device);
+ info(DRIVER_DESC " " DRIVER_VERSION);
+
+ return 0;
+}
+
+
+static void __exit ipaq_exit(void)
+{
+ usb_serial_deregister(&ipaq_device);
+}
+
+
+module_init(ipaq_init);
+module_exit(ipaq_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
diff --git a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h
new file mode 100644
index 000000000..665900d17
--- /dev/null
+++ b/drivers/usb/serial/ipaq.h
@@ -0,0 +1,60 @@
+/*
+ * USB Compaq iPAQ driver
+ *
+ * Copyright (C) 2001
+ * Ganesh Varadarajan <ganesh@veritas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *
+ */
+
+#ifndef __LINUX_USB_SERIAL_IPAQ_H
+#define __LINUX_USB_SERIAL_IPAQ_H
+
+
+#define IPAQ_VENDOR_ID 0x049f
+#define IPAQ_PRODUCT_ID 0x0003
+
+/*
+ * Since we can't queue our bulk write urbs (don't know why - it just
+ * doesn't work), we can send down only one write urb at a time. The simplistic
+ * approach taken by the generic usbserial driver will work, but it's not good
+ * for performance. Therefore, we buffer upto URBDATA_QUEUE_MAX bytes of write
+ * requests coming from the line discipline. This is done by chaining them
+ * in lists of struct ipaq_packet, each packet holding a maximum of
+ * PACKET_SIZE bytes.
+ *
+ * ipaq_write() can be called from bottom half context; hence we can't
+ * allocate memory for packets there. So we initialize a pool of packets at
+ * the first open and maintain a freelist.
+ *
+ * The value of PACKET_SIZE was empirically determined by
+ * checking the maximum write sizes sent down by the ppp ldisc.
+ * URBDATA_QUEUE_MAX is set to 64K, which is the maximum TCP window size
+ * supported by the iPAQ.
+ */
+
+struct ipaq_packet {
+ char *data;
+ size_t len;
+ size_t written;
+ struct list_head list;
+};
+
+struct ipaq_private {
+ int active;
+ int queue_len;
+ int free_len;
+ struct list_head queue;
+ struct list_head freelist;
+};
+
+#define URBDATA_SIZE 4096
+#define URBDATA_QUEUE_MAX (64 * 1024)
+#define PACKET_SIZE 256
+
+#endif
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
new file mode 100644
index 000000000..4278bcb58
--- /dev/null
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -0,0 +1,1086 @@
+/*
+ * KLSI KL5KUSB105 chip RS232 converter driver
+ *
+ * Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * All information about the device was acquired using SniffUSB ans snoopUSB
+ * on Windows98.
+ * It was written out of frustration with the PalmConnect USB Serial adapter
+ * sold by Palm Inc.
+ * Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided
+ * information that was not already available.
+ *
+ * It seems that KLSI bought some silicon-design information from ScanLogic,
+ * whose SL11R processor is at the core of the KL5KUSB chipset from KLSI.
+ * KLSI has firmware available for their devices; it is probable that the
+ * firmware differs from that used by KLSI in their products. If you have an
+ * original KLSI device and can provide some information on it, I would be
+ * most interested in adding support for it here. If you have any information
+ * on the protocol used (or find errors in my reverse-engineered stuff), please
+ * let me know.
+ *
+ * The code was only tested with a PalmConnect USB adapter; if you
+ * are adventurous, try it with any KLSI-based device and let me know how it
+ * breaks so that I can fix it!
+ */
+
+/* TODO:
+ * check modem line signals
+ * implement handshaking or decide that we do not support it
+ */
+
+/* History:
+ * 0.3a - implemented pools of write URBs
+ * 0.3 - alpha version for public testing
+ * 0.2 - TIOCMGET works, so autopilot(1) can be used!
+ * 0.1 - can be used to to pilot-xfer -p /dev/ttyUSB0 -l
+ *
+ * The driver skeleton is mainly based on mct_u232.c and various other
+ * pieces of code shamelessly copied from the drivers/usb/serial/ directory.
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+ static int debug = 1;
+#else
+ static int debug;
+#endif
+
+#include "usb-serial.h"
+#include "kl5kusb105.h"
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.3a"
+#define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>"
+#define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver"
+
+
+/*
+ * Function prototypes
+ */
+static int klsi_105_startup (struct usb_serial *serial);
+static void klsi_105_shutdown (struct usb_serial *serial);
+static int klsi_105_open (struct usb_serial_port *port,
+ struct file *filp);
+static void klsi_105_close (struct usb_serial_port *port,
+ struct file *filp);
+static int klsi_105_write (struct usb_serial_port *port,
+ int from_user,
+ const unsigned char *buf,
+ int count);
+static void klsi_105_write_bulk_callback (struct urb *urb);
+static int klsi_105_chars_in_buffer (struct usb_serial_port *port);
+static int klsi_105_write_room (struct usb_serial_port *port);
+
+static void klsi_105_read_bulk_callback (struct urb *urb);
+static void klsi_105_set_termios (struct usb_serial_port *port,
+ struct termios * old);
+static int klsi_105_ioctl (struct usb_serial_port *port,
+ struct file * file,
+ unsigned int cmd,
+ unsigned long arg);
+static void klsi_105_throttle (struct usb_serial_port *port);
+static void klsi_105_unthrottle (struct usb_serial_port *port);
+/*
+static void klsi_105_break_ctl (struct usb_serial_port *port,
+ int break_state );
+ */
+
+/*
+ * All of the device info needed for the KLSI converters.
+ */
+static __devinitdata struct usb_device_id id_table [] = {
+ { USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) },
+ { USB_DEVICE(KLSI_VID, KLSI_KL5KUSB105D_PID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+
+static struct usb_serial_device_type kl5kusb105d_device = {
+ owner: THIS_MODULE,
+ name: "KL5KUSB105D / PalmConnect",
+ id_table: id_table,
+ num_interrupt_in: 1,
+ num_bulk_in: 1,
+ num_bulk_out: 1,
+ num_ports: 1,
+ open: klsi_105_open,
+ close: klsi_105_close,
+ write: klsi_105_write,
+ write_bulk_callback: klsi_105_write_bulk_callback,
+ chars_in_buffer: klsi_105_chars_in_buffer,
+ write_room: klsi_105_write_room,
+ read_bulk_callback: klsi_105_read_bulk_callback,
+ ioctl: klsi_105_ioctl,
+ set_termios: klsi_105_set_termios,
+ /*break_ctl: klsi_105_break_ctl,*/
+ startup: klsi_105_startup,
+ shutdown: klsi_105_shutdown,
+ throttle: klsi_105_throttle,
+ unthrottle: klsi_105_unthrottle,
+};
+
+struct klsi_105_port_settings {
+ __u8 pktlen; /* always 5, it seems */
+ __u8 baudrate;
+ __u8 databits;
+ __u8 unknown1;
+ __u8 unknown2;
+} __attribute__ ((packed));
+
+/* we implement a pool of NUM_URBS urbs per usb_serial */
+#define NUM_URBS 1
+#define URB_TRANSFER_BUFFER_SIZE 64
+struct klsi_105_private {
+ struct klsi_105_port_settings cfg;
+ struct termios termios;
+ unsigned long line_state; /* modem line settings */
+ /* write pool */
+ struct urb * write_urb_pool[NUM_URBS];
+ spinlock_t write_urb_pool_lock;
+ unsigned long bytes_in;
+ unsigned long bytes_out;
+};
+
+
+/*
+ * Handle vendor specific USB requests
+ */
+
+
+#define KLSI_TIMEOUT (HZ * 5 ) /* default urb timeout */
+
+static int klsi_105_chg_port_settings(struct usb_serial *serial,
+ struct klsi_105_port_settings *settings)
+{
+ int rc;
+
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ KL5KUSB105A_SIO_SET_DATA,
+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE,
+ 0, /* value */
+ 0, /* index */
+ settings,
+ sizeof(struct klsi_105_port_settings),
+ KLSI_TIMEOUT);
+ if (rc < 0)
+ err("Change port settings failed (error = %d)", rc);
+ info(__FUNCTION__ " - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d",
+ settings->pktlen,
+ settings->baudrate, settings->databits,
+ settings->unknown1, settings->unknown2);
+ return rc;
+} /* klsi_105_chg_port_settings */
+
+/* translate a 16-bit status value from the device to linux's TIO bits */
+static unsigned long klsi_105_status2linestate(const __u16 status)
+{
+ unsigned long res = 0;
+
+ res = ((status & KL5KUSB105A_DSR) ? TIOCM_DSR : 0)
+ | ((status & KL5KUSB105A_CTS) ? TIOCM_CTS : 0)
+ ;
+
+ return res;
+}
+/*
+ * Read line control via vendor command and return result through
+ * *line_state_p
+ */
+/* It seems that the status buffer has always only 2 bytes length */
+#define KLSI_STATUSBUF_LEN 2
+static int klsi_105_get_line_state(struct usb_serial *serial,
+ unsigned long *line_state_p)
+{
+ int rc;
+ __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1};
+ __u16 status;
+
+ info(__FUNCTION__ " - sending SIO Poll request");
+ rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ KL5KUSB105A_SIO_POLL,
+ USB_TYPE_VENDOR | USB_DIR_IN,
+ 0, /* value */
+ 0, /* index */
+ status_buf, KLSI_STATUSBUF_LEN,
+ 10*HZ
+ );
+ if (rc < 0)
+ err("Reading line status failed (error = %d)", rc);
+ else {
+ status = status_buf[0] + (status_buf[1]<<8);
+
+ info(__FUNCTION__ " - read status %x %x",
+ status_buf[0], status_buf[1]);
+
+ *line_state_p = klsi_105_status2linestate(status);
+ }
+
+ return rc;
+}
+
+
+/*
+ * Driver's tty interface functions
+ */
+
+static int klsi_105_startup (struct usb_serial *serial)
+{
+ struct klsi_105_private *priv;
+ int i;
+
+ /* check if we support the product id (see keyspan.c)
+ * FIXME
+ */
+
+ /* allocate the private data structure */
+ for (i=0; i<serial->num_ports; i++) {
+ serial->port[i].private = kmalloc(sizeof(struct klsi_105_private),
+ GFP_KERNEL);
+ if (!serial->port[i].private) {
+ dbg(__FUNCTION__ "kmalloc for klsi_105_private failed.");
+ return (-1); /* error */
+ }
+ priv = (struct klsi_105_private *)serial->port[i].private;
+ /* set initial values for control structures */
+ priv->cfg.pktlen = 5;
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ priv->cfg.databits = kl5kusb105a_dtb_8;
+ priv->cfg.unknown1 = 0;
+ priv->cfg.unknown2 = 1;
+
+ priv->line_state = 0;
+
+ priv->bytes_in = 0;
+ priv->bytes_out = 0;
+
+ spin_lock_init (&priv->write_urb_pool_lock);
+ for (i=0; i<NUM_URBS; i++) {
+ struct urb* urb = usb_alloc_urb(0);
+
+ priv->write_urb_pool[i] = urb;
+ if (urb == NULL) {
+ err("No more urbs???");
+ continue;
+ }
+
+ urb->transfer_buffer = NULL;
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE,
+ GFP_KERNEL);
+ if (!urb->transfer_buffer) {
+ err (__FUNCTION__
+ " - out of memory for urb buffers.");
+ continue;
+ }
+ }
+
+ /* priv->termios is left uninitalized until port opening */
+ init_waitqueue_head(&serial->port[i].write_wait);
+ }
+
+ return (0);
+} /* klsi_105_startup */
+
+
+static void klsi_105_shutdown (struct usb_serial *serial)
+{
+ int i;
+
+ dbg (__FUNCTION__);
+
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+ struct klsi_105_private *priv =
+ (struct klsi_105_private*) serial->port[i].private;
+ unsigned long flags;
+ while (serial->port[i].open_count > 0) {
+ klsi_105_close (&serial->port[i], NULL);
+ }
+
+ if (priv) {
+ /* kill our write urb pool */
+ int j;
+ struct urb **write_urbs = priv->write_urb_pool;
+ spin_lock_irqsave(&priv->write_urb_pool_lock,flags);
+
+ for (j = 0; j < NUM_URBS; j++) {
+ if (write_urbs[j]) {
+ /* FIXME - uncomment the following
+ * usb_unlink_urb call when the host
+ * controllers get fixed to set
+ * urb->dev = NULL after the urb is
+ * finished. Otherwise this call
+ * oopses. */
+ /* usb_unlink_urb(write_urbs[j]); */
+ if (write_urbs[j]->transfer_buffer)
+ kfree(write_urbs[j]->transfer_buffer);
+ usb_free_urb (write_urbs[j]);
+ }
+ }
+
+ spin_unlock_irqrestore (&priv->write_urb_pool_lock,
+ flags);
+
+ kfree(serial->port[i].private);
+ }
+ }
+} /* klsi_105_shutdown */
+
+static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
+{
+ struct usb_serial *serial = port->serial;
+ struct klsi_105_private *priv = (struct klsi_105_private *)port->private;
+ int retval = 0;
+
+ dbg(__FUNCTION__" port %d", port->number);
+
+ down (&port->sem);
+
+ ++port->open_count;
+
+ if (port->open_count == 1) {
+ int rc;
+ int i;
+ unsigned long line_state;
+
+ /* force low_latency on so that our tty_push actually forces
+ * the data through
+ * port->tty->low_latency = 1; */
+
+ /* Do a defined restart:
+ * Set up sane default baud rate and send the 'READ_ON'
+ * vendor command.
+ * FIXME: set modem line control (how?)
+ * Then read the modem line control and store values in
+ * priv->line_state.
+ */
+ priv->cfg.pktlen = 5;
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ priv->cfg.databits = kl5kusb105a_dtb_8;
+ priv->cfg.unknown1 = 0;
+ priv->cfg.unknown2 = 1;
+ klsi_105_chg_port_settings(serial, &(priv->cfg));
+
+ /* set up termios structure */
+ priv->termios.c_iflag = port->tty->termios->c_iflag;
+ priv->termios.c_oflag = port->tty->termios->c_oflag;
+ priv->termios.c_cflag = port->tty->termios->c_cflag;
+ priv->termios.c_lflag = port->tty->termios->c_lflag;
+ for (i=0; i<NCCS; i++)
+ priv->termios.c_cc[i] = port->tty->termios->c_cc[i];
+
+
+ /* READ_ON and urb submission */
+ FILL_BULK_URB(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ klsi_105_read_bulk_callback,
+ port);
+ port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+
+ rc = usb_submit_urb(port->read_urb);
+ if (rc) {
+ err(__FUNCTION__
+ " - failed submitting read urb, error %d", rc);
+ retval = rc;
+ goto exit;
+ }
+
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0),
+ KL5KUSB105A_SIO_CONFIGURE,
+ USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,
+ KL5KUSB105A_SIO_CONFIGURE_READ_ON,
+ 0, /* index */
+ NULL,
+ 0,
+ KLSI_TIMEOUT);
+ if (rc < 0) {
+ err("Enabling read failed (error = %d)", rc);
+ retval = rc;
+ } else
+ dbg(__FUNCTION__ " - enabled reading");
+
+ rc = klsi_105_get_line_state(serial, &line_state);
+ if (rc >= 0) {
+ priv->line_state = line_state;
+ dbg(__FUNCTION__
+ " - read line state 0x%lx", line_state);
+ retval = 0;
+ } else
+ retval = rc;
+ }
+
+exit:
+ up (&port->sem);
+
+ return retval;
+} /* klsi_105_open */
+
+
+static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
+{
+ struct usb_serial *serial;
+ struct klsi_105_private *priv
+ = (struct klsi_105_private *)port->private;
+ dbg(__FUNCTION__" port %d", port->number);
+
+ serial = get_usb_serial (port, __FUNCTION__);
+
+ if(!serial)
+ return;
+
+ down (&port->sem);
+
+ --port->open_count;
+
+ if (port->open_count <= 0) {
+ /* send READ_OFF */
+ int rc = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ KL5KUSB105A_SIO_CONFIGURE,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+ 0, /* index */
+ NULL, 0,
+ KLSI_TIMEOUT);
+ if (rc < 0)
+ err("Disabling read failed (error = %d)", rc);
+
+ /* shutdown our bulk reads and writes */
+ usb_unlink_urb (port->write_urb);
+ usb_unlink_urb (port->read_urb);
+ /* unlink our write pool */
+ /* FIXME */
+ /* wgg - do I need this? I think so. */
+ usb_unlink_urb (port->interrupt_in_urb);
+ port->open_count = 0;
+ info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out);
+ }
+
+ up (&port->sem);
+} /* klsi_105_close */
+
+
+/* We need to write a complete 64-byte data block and encode the
+ * number actually sent in the first double-byte, LSB-order. That
+ * leaves at most 62 bytes of payload.
+ */
+#define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */
+
+
+static int klsi_105_write (struct usb_serial_port *port, int from_user,
+ const unsigned char *buf, int count)
+{
+ struct usb_serial *serial = port->serial;
+ struct klsi_105_private *priv =
+ (struct klsi_105_private*) port->private;
+ int result, size;
+ int bytes_sent=0;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ down (&port->sem); /* to lock against someone else trying to
+ take an URB we just selected from the pool */
+
+ while (count > 0) {
+ /* try to find a free urb (write 0 bytes if none) */
+ struct urb *urb = NULL;
+ unsigned long flags;
+ int i;
+ /* since the pool is per-port we might not need the spin lock !? */
+ spin_lock_irqsave (&priv->write_urb_pool_lock, flags);
+ for (i=0; i<NUM_URBS; i++) {
+ if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+ urb = priv->write_urb_pool[i];
+ dbg(__FUNCTION__ " - using pool URB %d", i);
+ break;
+ }
+ }
+ spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);
+
+ if (urb==NULL) {
+ dbg (__FUNCTION__ " - no more free urbs");
+ goto exit;
+ }
+
+ if (urb->transfer_buffer == NULL) {
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ if (urb->transfer_buffer == NULL) {
+ err(__FUNCTION__ " - no more kernel memory...");
+ goto exit;
+ }
+ }
+
+ size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET);
+ size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET);
+
+ if (from_user) {
+ if (copy_from_user(urb->transfer_buffer
+ + KLSI_105_DATA_OFFSET, buf, size)) {
+ up (&port->sem);
+ return -EFAULT;
+ }
+ } else {
+ memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET,
+ buf, size);
+ }
+
+ /* write payload size into transfer buffer */
+ ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF);
+ ((__u8 *)urb->transfer_buffer)[1] = (__u8) ((size & 0xFF00)>>8);
+
+ /* set up our urb */
+ FILL_BULK_URB(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
+ urb->transfer_buffer,
+ URB_TRANSFER_BUFFER_SIZE,
+ klsi_105_write_bulk_callback,
+ port);
+ urb->transfer_flags |= USB_QUEUE_BULK;
+
+
+ /* send the data out the bulk port */
+ result = usb_submit_urb(urb);
+ if (result) {
+ err(__FUNCTION__
+ " - failed submitting write urb, error %d", result);
+ goto exit;
+ }
+ buf += size;
+ bytes_sent += size;
+ count -= size;
+ }
+exit:
+ up (&port->sem);
+ priv->bytes_out+=bytes_sent;
+
+ return bytes_sent; /* that's how much we wrote */
+} /* klsi_105_write */
+
+static void klsi_105_write_bulk_callback ( struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial = port->serial;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ if (!serial) {
+ dbg(__FUNCTION__ " - bad serial pointer, exiting");
+ return;
+ }
+
+ if (urb->status) {
+ dbg(__FUNCTION__ " - nonzero write bulk status received: %d",
+ urb->status);
+ return;
+ }
+
+ /* from generic_write_bulk_callback */
+ queue_task(&port->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+
+ return;
+} /* klsi_105_write_bulk_completion_callback */
+
+
+/* return number of characters currently in the writing process */
+static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
+{
+ int chars = 0;
+ int i;
+ unsigned long flags;
+ struct klsi_105_private *priv =
+ (struct klsi_105_private*) port->private;
+
+ spin_lock_irqsave (&priv->write_urb_pool_lock, flags);
+
+ for (i = 0; i < NUM_URBS; ++i) {
+ if (priv->write_urb_pool[i]->status == -EINPROGRESS) {
+ chars += URB_TRANSFER_BUFFER_SIZE;
+ }
+ }
+
+ spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);
+
+ dbg (__FUNCTION__ " - returns %d", chars);
+ return (chars);
+}
+
+static int klsi_105_write_room (struct usb_serial_port *port)
+{
+ unsigned long flags;
+ int i;
+ int room = 0;
+ struct klsi_105_private *priv =
+ (struct klsi_105_private*) port->private;
+
+ spin_lock_irqsave (&priv->write_urb_pool_lock, flags);
+ for (i = 0; i < NUM_URBS; ++i) {
+ if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+ room += URB_TRANSFER_BUFFER_SIZE;
+ }
+ }
+
+ spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);
+
+ dbg(__FUNCTION__ " - returns %d", room);
+ return (room);
+}
+
+
+
+static void klsi_105_read_bulk_callback (struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial = port->serial;
+ struct klsi_105_private *priv =
+ (struct klsi_105_private*) port->private;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ int rc;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ /* The urb might have been killed. */
+ if (urb->status) {
+ dbg(__FUNCTION__ " - nonzero read bulk status received: %d",
+ urb->status);
+ return;
+ }
+ if (!serial) {
+ dbg(__FUNCTION__ " - bad serial pointer, exiting");
+ return;
+ }
+
+ /* The data received is again preceded by a length double-byte in LSB-
+ * first order (see klsi_105_write() )
+ */
+ if (urb->actual_length == 0) {
+ /* empty urbs seem to happen, we ignore them */
+ /* dbg(__FUNCTION__ " - emtpy URB"); */
+ ;
+ } else if (urb->actual_length <= 2) {
+ dbg(__FUNCTION__ " - size %d URB not understood",
+ urb->actual_length);
+ usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+ } else {
+ int i;
+ int bytes_sent = ((__u8 *) data)[0] +
+ ((unsigned int) ((__u8 *) data)[1] << 8);
+ tty = port->tty;
+ /* we should immediately resubmit the URB, before attempting
+ * to pass the data on to the tty layer. But that needs locking
+ * against re-entry an then mixed-up data because of
+ * intermixed tty_flip_buffer_push()s
+ * FIXME
+ */
+ usb_serial_debug_data (__FILE__, __FUNCTION__,
+ urb->actual_length, data);
+
+ if (bytes_sent + 2 > urb->actual_length) {
+ dbg(__FUNCTION__
+ " - trying to read more data than available"
+ " (%d vs. %d)",
+ bytes_sent+2, urb->actual_length);
+ /* cap at implied limit */
+ bytes_sent = urb->actual_length - 2;
+ }
+
+ for (i = 2; i < 2+bytes_sent; i++) {
+ /* if we insert more than TTY_FLIPBUF_SIZE characters,
+ * we drop them. */
+ if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ }
+ /* this doesn't actually push the data through unless
+ * tty->low_latency is set */
+ tty_insert_flip_char(tty, ((__u8*) data)[i], 0);
+ }
+ tty_flip_buffer_push(tty);
+ priv->bytes_in += bytes_sent;
+ }
+ /* Continue trying to always read */
+ FILL_BULK_URB(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ klsi_105_read_bulk_callback,
+ port);
+ rc = usb_submit_urb(port->read_urb);
+ if (rc)
+ err(__FUNCTION__
+ " - failed resubmitting read urb, error %d", rc);
+} /* klsi_105_read_bulk_callback */
+
+
+static void klsi_105_set_termios (struct usb_serial_port *port,
+ struct termios *old_termios)
+{
+ struct usb_serial *serial = port->serial;
+ struct klsi_105_private *priv = (struct klsi_105_private *)port->private;
+ unsigned int iflag = port->tty->termios->c_iflag;
+ unsigned int old_iflag = old_termios->c_iflag;
+ unsigned int cflag = port->tty->termios->c_cflag;
+ unsigned int old_cflag = old_termios->c_cflag;
+
+ /*
+ * Update baud rate
+ */
+ if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
+ /* reassert DTR and (maybe) RTS on transition from B0 */
+ if( (old_cflag & CBAUD) == B0 ) {
+ dbg(__FUNCTION__ ": baud was B0");
+#if 0
+ priv->control_state |= TIOCM_DTR;
+ /* don't set RTS if using hardware flow control */
+ if (!(old_cflag & CRTSCTS)) {
+ priv->control_state |= TIOCM_RTS;
+ }
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
+#endif
+ }
+
+ switch(cflag & CBAUD) {
+ case B0: /* handled below */
+ break;
+ case B1200: priv->cfg.baudrate = kl5kusb105a_sio_b1200;
+ break;
+ case B2400: priv->cfg.baudrate = kl5kusb105a_sio_b2400;
+ break;
+ case B4800: priv->cfg.baudrate = kl5kusb105a_sio_b4800;
+ break;
+ case B9600: priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ break;
+ case B19200: priv->cfg.baudrate = kl5kusb105a_sio_b19200;
+ break;
+ case B38400: priv->cfg.baudrate = kl5kusb105a_sio_b38400;
+ break;
+ case B57600: priv->cfg.baudrate = kl5kusb105a_sio_b57600;
+ break;
+ case B115200: priv->cfg.baudrate = kl5kusb105a_sio_b115200;
+ break;
+ default:
+ err("KLSI USB->Serial converter:"
+ " unsupported baudrate request, using default"
+ " of 9600");
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ break;
+ }
+ if ((cflag & CBAUD) == B0 ) {
+ dbg(__FUNCTION__ ": baud is B0");
+ /* Drop RTS and DTR */
+ /* maybe this should be simulated by sending read
+ * disable and read enable messages?
+ */
+ ;
+#if 0
+ priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
+#endif
+ }
+ }
+
+ if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
+ /* set the number of data bits */
+ switch (cflag & CSIZE) {
+ case CS5:
+ dbg(__FUNCTION__ " - 5 bits/byte not supported");
+ return ;
+ case CS6:
+ dbg(__FUNCTION__ " - 6 bits/byte not supported");
+ return ;
+ case CS7:
+ priv->cfg.databits = kl5kusb105a_dtb_7;
+ break;
+ case CS8:
+ priv->cfg.databits = kl5kusb105a_dtb_8;
+ break;
+ default:
+ err("CSIZE was not CS5-CS8, using default of 8");
+ priv->cfg.databits = kl5kusb105a_dtb_8;
+ break;
+ }
+ }
+
+ /*
+ * Update line control register (LCR)
+ */
+ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
+ || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
+
+#if 0
+ priv->last_lcr = 0;
+
+ /* set the parity */
+ if (cflag & PARENB)
+ priv->last_lcr |= (cflag & PARODD) ?
+ MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
+ else
+ priv->last_lcr |= MCT_U232_PARITY_NONE;
+
+ /* set the number of stop bits */
+ priv->last_lcr |= (cflag & CSTOPB) ?
+ MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
+
+ mct_u232_set_line_ctrl(serial, priv->last_lcr);
+#endif
+ ;
+ }
+
+ /*
+ * Set flow control: well, I do not really now how to handle DTR/RTS.
+ * Just do what we have seen with SniffUSB on Win98.
+ */
+ if( (iflag & IXOFF) != (old_iflag & IXOFF)
+ || (iflag & IXON) != (old_iflag & IXON)
+ || (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
+
+ /* Drop DTR/RTS if no flow control otherwise assert */
+#if 0
+ if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
+ priv->control_state |= TIOCM_DTR | TIOCM_RTS;
+ else
+ priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
+#endif
+ ;
+ }
+
+ /* now commit changes to device */
+ klsi_105_chg_port_settings(serial, &(priv->cfg));
+} /* klsi_105_set_termios */
+
+
+#if 0
+static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+{
+ struct usb_serial *serial = port->serial;
+ struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ unsigned char lcr = priv->last_lcr;
+
+ dbg (__FUNCTION__ "state=%d", break_state);
+
+ if (break_state)
+ lcr |= MCT_U232_SET_BREAK;
+
+ mct_u232_set_line_ctrl(serial, lcr);
+} /* mct_u232_break_ctl */
+#endif
+
+static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct usb_serial *serial = port->serial;
+ struct klsi_105_private *priv = (struct klsi_105_private *)port->private;
+ int mask;
+
+ dbg (__FUNCTION__ "cmd=0x%x", cmd);
+
+ /* Based on code from acm.c and others */
+ switch (cmd) {
+ case TIOCMGET: {
+ int rc;
+ unsigned long line_state;
+ dbg (__FUNCTION__ " - TIOCMGET request, just guessing");
+
+ rc = klsi_105_get_line_state(serial, &line_state);
+ if (rc < 0) {
+ err("Reading line control failed (error = %d)", rc);
+ /* better return value? EAGAIN? */
+ return -ENOIOCTLCMD;
+ } else {
+ priv->line_state = line_state;
+ dbg(__FUNCTION__ " - read line state 0x%lx", line_state);
+ }
+ return put_user(priv->line_state, (unsigned long *) arg);
+ };
+
+ case TIOCMSET: /* Turns on and off the lines as specified by the mask */
+ case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
+ case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
+ if (get_user(mask, (unsigned long *) arg))
+ return -EFAULT;
+
+ if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
+ /* RTS needs set */
+ if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
+ (cmd == TIOCMBIS) )
+ dbg (__FUNCTION__ " - set RTS not handled");
+ /* priv->control_state |= TIOCM_RTS; */
+ else
+ dbg (__FUNCTION__ " - clear RTS not handled");
+ /* priv->control_state &= ~TIOCM_RTS; */
+ }
+
+ if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
+ /* DTR needs set */
+ if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
+ (cmd == TIOCMBIS) )
+ dbg (__FUNCTION__ " - set DTR not handled");
+ /* priv->control_state |= TIOCM_DTR; */
+ else
+ dbg (__FUNCTION__ " - clear DTR not handled");
+ /* priv->control_state &= ~TIOCM_DTR; */
+ }
+ /*
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
+ */
+ break;
+
+ case TIOCMIWAIT:
+ /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
+ /* TODO */
+ dbg (__FUNCTION__ " - TIOCMIWAIT not handled");
+ return -ENOIOCTLCMD;
+
+ case TIOCGICOUNT:
+ /* return count of modemline transitions */
+ /* TODO */
+ dbg (__FUNCTION__ " - TIOCGICOUNT not handled");
+ return -ENOIOCTLCMD;
+ case TCGETS: {
+ /* return current info to caller */
+ int retval;
+
+ dbg (__FUNCTION__ " - TCGETS data faked/incomplete");
+
+ retval = verify_area(VERIFY_WRITE, (void *)arg,
+ sizeof(struct termios));
+
+ if (retval)
+ return(retval);
+
+ kernel_termios_to_user_termios((struct termios *)arg,
+ &priv->termios);
+ return(0);
+ }
+ case TCSETS: {
+ /* set port termios to the one given by the user */
+ int retval;
+
+ dbg (__FUNCTION__ " - TCSETS not handled");
+
+ retval = verify_area(VERIFY_READ, (void *)arg,
+ sizeof(struct termios));
+
+ if (retval)
+ return(retval);
+
+ user_termios_to_kernel_termios(&priv->termios,
+ (struct termios *)arg);
+ klsi_105_set_termios(port, &priv->termios);
+ return(0);
+ }
+ case TCSETSW: {
+ /* set port termios and try to wait for completion of last
+ * write operation */
+ /* We guess here. If there are not too many write urbs
+ * outstanding, we lie. */
+ /* what is the right way to wait here? schedule() ? */
+ /*
+ while (klsi_105_chars_in_buffer(port) > (NUM_URBS / 4 ) * URB_TRANSFER_BUFFER_SIZE)
+ schedule();
+ */
+ return -ENOIOCTLCMD;
+ }
+ default:
+ dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd);
+ return(-ENOIOCTLCMD);
+ break;
+ }
+ return 0;
+} /* klsi_105_ioctl */
+
+static void klsi_105_throttle (struct usb_serial_port *port)
+{
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ down (&port->sem);
+
+ usb_unlink_urb (port->read_urb);
+
+ up (&port->sem);
+
+ return;
+}
+static void klsi_105_unthrottle (struct usb_serial_port *port)
+{
+ int result;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ down (&port->sem);
+
+ port->read_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->read_urb);
+ if (result)
+ err(__FUNCTION__ " - failed submitting read urb, error %d",
+ result);
+
+ up (&port->sem);
+
+ return;
+}
+
+
+
+static int __init klsi_105_init (void)
+{
+ usb_serial_register (&kl5kusb105d_device);
+
+ info(DRIVER_DESC " " DRIVER_VERSION);
+ return 0;
+}
+
+
+static void __exit klsi_105_exit (void)
+{
+ usb_serial_deregister (&kl5kusb105d_device);
+}
+
+
+module_init (klsi_105_init);
+module_exit (klsi_105_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "enable extensive debugging messages");
+/* FIXME: implement
+MODULE_PARM(num_urbs, "i");
+MODULE_PARM_DESC(num_urbs, "number of URBs to use in write pool");
+*/
+
+/* vim: set sts=8 ts=8 sw=8: */
diff --git a/drivers/usb/serial/kl5kusb105.h b/drivers/usb/serial/kl5kusb105.h
new file mode 100644
index 000000000..2e15a2d2c
--- /dev/null
+++ b/drivers/usb/serial/kl5kusb105.h
@@ -0,0 +1,69 @@
+/*
+ * Definitions for the KLSI KL5KUSB105 serial port adapter
+ */
+
+/* vendor/product pairs that are known to contain this chipset */
+#define PALMCONNECT_VID 0x0830
+#define PALMCONNECT_PID 0x0080
+
+#define KLSI_VID 0x05e9
+#define KLSI_KL5KUSB105D_PID 0x00c0
+
+/* Vendor commands: */
+
+
+/* port table -- the chip supports up to 4 channels */
+
+/* baud rates */
+
+typedef enum {
+ kl5kusb105a_sio_b115200 = 0,
+ kl5kusb105a_sio_b57600 = 1,
+ kl5kusb105a_sio_b38400 = 2,
+ kl5kusb105a_sio_b19200 = 4,
+ kl5kusb105a_sio_b14400 = 5,
+ kl5kusb105a_sio_b9600 = 6,
+ kl5kusb105a_sio_b4800 = 8, /* unchecked */
+ kl5kusb105a_sio_b2400 = 9, /* unchecked */
+ kl5kusb105a_sio_b1200 = 0xa, /* unchecked */
+ kl5kusb105a_sio_b600 = 0xb /* unchecked */
+} KL5KUSB105A_SIO_baudrate_t;
+
+/* data bits */
+#define kl5kusb105a_dtb_7 7
+#define kl5kusb105a_dtb_8 8
+
+
+
+/* requests: */
+#define KL5KUSB105A_SIO_SET_DATA 1
+#define KL5KUSB105A_SIO_POLL 2
+#define KL5KUSB105A_SIO_CONFIGURE 3
+/* values used for request KL5KUSB105A_SIO_CONFIGURE */
+#define KL5KUSB105A_SIO_CONFIGURE_READ_ON 3
+#define KL5KUSB105A_SIO_CONFIGURE_READ_OFF 2
+
+/* Interpretation of modem status lines */
+/* These need sorting out by individually connecting pins and checking
+ * results. FIXME!
+ * When data is being sent we see 0x30 in the lower byte; this must
+ * contain DSR and CTS ...
+ */
+#define KL5KUSB105A_DSR ((1<<4) | (1<<5))
+#define KL5KUSB105A_CTS ((1<<5) | (1<<4))
+
+#define KL5KUSB105A_WANTS_TO_SEND 0x30
+//#define KL5KUSB105A_DTR /* Data Terminal Ready */
+//#define KL5KUSB105A_CTS /* Clear To Send */
+//#define KL5KUSB105A_CD /* Carrier Detect */
+//#define KL5KUSB105A_DSR /* Data Set Ready */
+//#define KL5KUSB105A_RxD /* Receive pin */
+
+//#define KL5KUSB105A_LE
+//#define KL5KUSB105A_RTS
+//#define KL5KUSB105A_ST
+//#define KL5KUSB105A_SR
+//#define KL5KUSB105A_RI /* Ring Indicator */
+
+/* vim: set ts=8 sts=8: */
+
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index db1f4ff4f..d51e1d1ef 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -116,6 +116,7 @@ struct usb_serial {
/**
* usb_serial_device_type - a structure that defines a usb serial device
+ * @owner: pointer to the module that owns this device.
* @name: pointer to a string that describes this device. This string used
* in the syslog messages when a device is inserted or removed.
* @id_table: pointer to a list of usb_device_id structures that define all
@@ -138,6 +139,7 @@ struct usb_serial {
* called, the generic serial function will be used instead.
*/
struct usb_serial_device_type {
+ struct module *owner;
char *name;
const struct usb_device_id *id_table;
char num_interrupt_in;
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index fdd07e6c7..808c82985 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -397,16 +397,16 @@ static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL
static LIST_HEAD(usb_serial_driver_list);
-static struct usb_serial *get_serial_by_minor (int minor)
+static struct usb_serial *get_serial_by_minor (unsigned int minor)
{
return serial_table[minor];
}
-static struct usb_serial *get_free_serial (int num_ports, int *minor)
+static struct usb_serial *get_free_serial (int num_ports, unsigned int *minor)
{
struct usb_serial *serial = NULL;
- int i, j;
+ unsigned int i, j;
int good_spot;
dbg(__FUNCTION__ " %d", num_ports);
@@ -505,7 +505,8 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
{
struct usb_serial *serial;
struct usb_serial_port *port;
- int portNumber;
+ unsigned int portNumber;
+ int retval;
dbg(__FUNCTION__);
@@ -513,24 +514,30 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
tty->driver_data = NULL;
/* get the serial object associated with this tty pointer */
- serial = get_serial_by_minor (MINOR(tty->device));
+ serial = get_serial_by_minor (minor(tty->device));
if (serial_paranoia_check (serial, __FUNCTION__)) {
return -ENODEV;
}
/* set up our port structure making the tty driver remember our port object, and us it */
- portNumber = MINOR(tty->device) - serial->minor;
+ portNumber = minor(tty->device) - serial->minor;
port = &serial->port[portNumber];
tty->driver_data = port;
port->tty = tty;
/* pass on to the driver specific version of this function if it is available */
if (serial->type->open) {
- return (serial->type->open(port, filp));
+ if (serial->type->owner)
+ __MOD_INC_USE_COUNT(serial->type->owner);
+ retval = serial->type->open(port, filp);
+ if (retval)
+ __MOD_DEC_USE_COUNT(serial->type->owner);
} else {
- return (generic_open(port, filp));
+ retval = generic_open(port, filp);
}
+
+ return retval;
}
@@ -553,6 +560,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
/* pass on to the driver specific version of this function if it is available */
if (serial->type->close) {
serial->type->close(port, filp);
+ if (serial->type->owner)
+ __MOD_DEC_USE_COUNT(serial->type->owner);
} else {
generic_close(port, filp);
}
@@ -1059,6 +1068,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
struct usb_serial_device_type *type = NULL;
struct list_head *tmp;
+ int retval;
int found;
int minor;
int buffer_size;
@@ -1180,9 +1190,13 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
/* if this device type has a startup function, call it */
if (type->startup) {
- if (type->startup (serial)) {
+ if (type->owner)
+ __MOD_INC_USE_COUNT(type->owner);
+ retval = type->startup (serial);
+ if (type->owner)
+ __MOD_DEC_USE_COUNT(type->owner);
+ if (retval)
goto probe_error;
- }
}
/* set up the endpoint information */
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 292101a81..ce34eb15a 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -12,6 +12,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (12/18/2001) gkh
+ * Added better Clie support for 3.5 devices. Thanks to Geoffrey Levand
+ * for the patch.
+ *
* (11/11/2001) gkh
* Added support for the m125 devices, and added check to prevent oopses
* for Clié devices that lie about the number of ports they have.
@@ -127,7 +131,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.7"
+#define DRIVER_VERSION "v1.8"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver"
@@ -145,6 +149,7 @@ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsi
static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios);
static void visor_write_bulk_callback (struct urb *urb);
static void visor_read_bulk_callback (struct urb *urb);
+static int clie_3_5_startup (struct usb_serial *serial);
static __devinitdata struct usb_device_id combined_id_table [] = {
@@ -177,6 +182,7 @@ MODULE_DEVICE_TABLE (usb, id_table);
/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
static struct usb_serial_device_type handspring_device = {
+ owner: THIS_MODULE,
name: "Handspring Visor / Palm 4.0 / Clié 4.0",
id_table: combined_id_table,
num_interrupt_in: 0,
@@ -200,6 +206,7 @@ static struct usb_serial_device_type handspring_device = {
/* device info for the Sony Clie OS version 3.5 */
static struct usb_serial_device_type clie_3_5_device = {
+ owner: THIS_MODULE,
name: "Sony Clié 3.5",
id_table: clie_id_3_5_table,
num_interrupt_in: 0,
@@ -210,6 +217,7 @@ static struct usb_serial_device_type clie_3_5_device = {
close: visor_close,
throttle: visor_throttle,
unthrottle: visor_unthrottle,
+ startup: clie_3_5_startup,
ioctl: visor_ioctl,
set_termios: visor_set_termios,
write: visor_write,
@@ -249,7 +257,6 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
down (&port->sem);
++port->open_count;
- MOD_INC_USE_COUNT;
if (port->open_count == 1) {
bytes_in = 0;
@@ -321,8 +328,6 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
/* Uncomment the following line if you want to see some statistics in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
-
- MOD_DEC_USE_COUNT;
}
@@ -644,6 +649,46 @@ static int visor_startup (struct usb_serial *serial)
return 0;
}
+static int clie_3_5_startup (struct usb_serial *serial)
+{
+ int result;
+ u8 data;
+
+ dbg(__FUNCTION__);
+
+ /*
+ * Note that PEG-300 series devices expect the following two calls.
+ */
+
+ /* get the config number */
+ result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
+ 0, 0, &data, 1, HZ * 3);
+ if (result < 0) {
+ err(__FUNCTION__ ": get config number failed: %d", result);
+ return result;
+ }
+ if (result != 1) {
+ err(__FUNCTION__ ": get config number bad return length: %d", result);
+ return -EIO;
+ }
+
+ /* get the interface number */
+ result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ USB_REQ_GET_INTERFACE,
+ USB_DIR_IN | USB_DT_DEVICE,
+ 0, 0, &data, 1, HZ * 3);
+ if (result < 0) {
+ err(__FUNCTION__ ": get interface number failed: %d", result);
+ return result;
+ }
+ if (result != 1) {
+ err(__FUNCTION__ ": get interface number bad return length: %d", result);
+ return -EIO;
+ }
+
+ return 0;
+}
static void visor_shutdown (struct usb_serial *serial)
{
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index df3721b63..d1aca3be8 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -208,7 +208,7 @@ static int datafab_read_data(struct us_data *us,
if (use_sg) {
sg = (struct scatterlist *) dest;
- buffer = kmalloc(len, GFP_KERNEL);
+ buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR;
ptr = buffer;
@@ -333,7 +333,7 @@ static int datafab_write_data(struct us_data *us,
if (use_sg) {
sg = (struct scatterlist *) src;
- buffer = kmalloc(len, GFP_KERNEL);
+ buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR;
ptr = buffer;
@@ -665,7 +665,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
};
if (!us->extra) {
- us->extra = kmalloc(sizeof(struct datafab_info), GFP_KERNEL);
+ us->extra = kmalloc(sizeof(struct datafab_info), GFP_NOIO);
if (!us->extra) {
US_DEBUGP("datafab_transport: Gah! Can't allocate storage for Datafab info struct!\n");
return USB_STOR_TRANSPORT_ERROR;
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 0a747f933..f273ea54f 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -1,6 +1,6 @@
/* Driver for Freecom USB/IDE adaptor
*
- * $Id: freecom.c,v 1.19 2001/11/11 05:42:34 mdharm Exp $
+ * $Id: freecom.c,v 1.21 2001/12/29 03:47:33 mdharm Exp $
*
* Freecom v0.1:
*
@@ -206,9 +206,7 @@ freecom_ide_write (struct us_data *us, int reg, int value)
return USB_STOR_TRANSPORT_GOOD;
}
-#endif
-#if 0 /* Unused at this time */
/* Read a value from an ide register. */
static int
freecom_ide_read (struct us_data *us, int reg, int *value)
@@ -435,7 +433,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
/* Get the status again */
fcb->Type = FCM_PACKET_STATUS;
fcb->Timeout = 0;
- memset (fcb->Atapi, 0, sizeof(fcb->Filler));
+ memset (fcb->Atapi, 0, sizeof(fcb->Atapi));
memset (fcb->Filler, 0, sizeof (fcb->Filler));
/* Send it out. */
@@ -487,10 +485,19 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
* and such will hang. */
US_DEBUGP("Device indicates that it has %d bytes available\n",
le16_to_cpu (fst->Count));
+ US_DEBUGP("SCSI requested %d\n", usb_stor_transfer_length(srb));
/* Find the length we desire to read. */
- length = usb_stor_transfer_length (srb);
- US_DEBUGP("SCSI requested %d\n", length);
+ switch (srb->cmnd[0]) {
+ case INQUIRY:
+ case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ length = fst->Count;
+ break;
+ default:
+ length = usb_stor_transfer_length (srb);
+ }
/* verify that this amount is legal */
if (length > srb->request_bufflen) {
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 6b17cd36d..94b9941cf 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -284,7 +284,7 @@ static int jumpshot_read_data(struct us_data *us,
if (use_sg) {
sg = (struct scatterlist *) dest;
- buffer = kmalloc(len, GFP_KERNEL);
+ buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR;
ptr = buffer;
@@ -399,7 +399,7 @@ static int jumpshot_write_data(struct us_data *us,
if (use_sg) {
sg = (struct scatterlist *) src;
- buffer = kmalloc(len, GFP_KERNEL);
+ buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR;
ptr = buffer;
@@ -665,7 +665,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
if (!us->extra) {
- us->extra = kmalloc(sizeof(struct jumpshot_info), GFP_KERNEL);
+ us->extra = kmalloc(sizeof(struct jumpshot_info), GFP_NOIO);
if (!us->extra) {
US_DEBUGP("jumpshot_transport: Gah! Can't allocate storage for jumpshot info struct!\n");
return USB_STOR_TRANSPORT_ERROR;
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index de35f0d33..bc14015ae 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1,6 +1,6 @@
/* Driver for SanDisk SDDR-09 SmartMedia reader
*
- * $Id: sddr09.c,v 1.21 2001/11/06 03:18:36 mdharm Exp $
+ * $Id: sddr09.c,v 1.22 2001/12/08 23:32:48 mdharm Exp $
*
* SDDR09 driver v0.1:
*
@@ -79,7 +79,7 @@ static int sddr09_send_control(struct us_data *us,
// copy the data into the buffer.
/*
if (xfer_len > 0) {
- buffer = kmalloc(xfer_len, GFP_KERNEL);
+ buffer = kmalloc(xfer_len, GFP_NOIO);
if (!(command[0] & USB_DIR_IN))
memcpy(buffer, xfer_data, xfer_len);
}
@@ -303,7 +303,7 @@ int sddr09_read_data(struct us_data *us,
if (use_sg) {
sg = (struct scatterlist *)content;
- buffer = kmalloc(len, GFP_KERNEL);
+ buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR;
ptr = buffer;
@@ -630,18 +630,18 @@ int sddr09_read_map(struct us_data *us) {
alloc_blocks = (alloc_len + (1<<17) - 1) >> 17;
sg = kmalloc(alloc_blocks*sizeof(struct scatterlist),
- GFP_KERNEL);
+ GFP_NOIO);
if (sg == NULL)
return 0;
for (i=0; i<alloc_blocks; i++) {
if (i<alloc_blocks-1) {
- char *vaddr = kmalloc(1 << 17, GFP_KERNEL);
+ char *vaddr = kmalloc(1 << 17, GFP_NOIO);
sg[i].page = virt_to_page(vaddr);
sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
sg[i].length = (1<<17);
} else {
- char *vaddr = kmalloc(alloc_len, GFP_KERNEL);
+ char *vaddr = kmalloc(alloc_len, GFP_NOIO);
sg[i].page = virt_to_page(vaddr);
sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
sg[i].length = alloc_len;
@@ -675,8 +675,8 @@ int sddr09_read_map(struct us_data *us) {
kfree(info->lba_to_pba);
if (info->pba_to_lba)
kfree(info->pba_to_lba);
- info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_KERNEL);
- info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_KERNEL);
+ info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
+ info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) {
if (info->lba_to_pba != NULL)
@@ -845,7 +845,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
if (!us->extra) {
us->extra = kmalloc(
- sizeof(struct sddr09_card_info), GFP_KERNEL);
+ sizeof(struct sddr09_card_info), GFP_NOIO);
if (!us->extra)
return USB_STOR_TRANSPORT_ERROR;
memset(us->extra, 0, sizeof(struct sddr09_card_info));
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 0592f929c..9770f9103 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1,6 +1,6 @@
/* Driver for SCM Microsystems USB-ATAPI cable
*
- * $Id: shuttle_usbat.c,v 1.14 2001/03/28 01:02:06 groovyjava Exp $
+ * $Id: shuttle_usbat.c,v 1.15 2001/12/08 23:32:48 mdharm Exp $
*
* Current development and maintenance by:
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
@@ -681,7 +681,7 @@ int usbat_handle_read10(struct us_data *us,
len = (65535/srb->transfersize) * srb->transfersize;
US_DEBUGP("Max read is %d bytes\n", len);
- buffer = kmalloc(len, GFP_KERNEL);
+ buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) // bloody hell!
return USB_STOR_TRANSPORT_FAILED;
sector = short_pack(data[7+3], data[7+2]);
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index b13c83423..b2ecee899 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: transport.c,v 1.41 2001/10/15 07:02:32 mdharm Exp $
+ * $Id: transport.c,v 1.42 2001/12/08 23:32:48 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -388,7 +388,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
devrequest *dr;
/* allocate the device request structure */
- dr = kmalloc(sizeof(devrequest), GFP_KERNEL);
+ dr = kmalloc(sizeof(devrequest), GFP_NOIO);
if (!dr)
return -ENOMEM;
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index dcdc14411..729c5ff60 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* Ununsual Devices File
*
- * $Id: unusual_devs.h,v 1.20 2001/09/02 05:12:57 mdharm Exp $
+ * $Id: unusual_devs.h,v 1.24 2001/12/29 03:12:45 mdharm Exp $
*
* Current development and maintenance by:
* (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -58,6 +58,11 @@ UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
"HP",
"CD-Writer+ 8200e",
US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
+
+UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
+ "HP",
+ "CD-Writer+ CD-4e",
+ US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
#endif
#ifdef CONFIG_USB_STORAGE_DPCM
@@ -86,6 +91,25 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210,
"FinePix 1400Zoom",
US_SC_8070, US_PR_CBI, NULL, US_FL_FIX_INQUIRY),
+/* Reported by Peter Wächtler <pwaechtler@loewe-komp.de>
+ * The device needs the flags only.
+ */
+UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074,
+ "ScanLogic",
+ "SL11R-IDE",
+ US_SC_SCSI, US_PR_BULK, NULL,
+ US_FL_FIX_INQUIRY),
+
+/* Reported by Kriston Fincher <kriston@airmail.net>
+ * Patch submitted by Sean Millichamp <sean@bruenor.org>
+ * This is to support the Panasonic PalmCam PV-SD4090
+ * This entry is needed because the device reports Sub=ff
+ */
+UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200,
+ "Panasonic",
+ "LS-120 Camera",
+ US_SC_UFI, US_PR_CBI, NULL, 0),
+
/* Most of the following entries were developed with the help of
* Shuttle/SCM directly.
*/
@@ -161,14 +185,24 @@ UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133,
US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ),
+/* Iomega Clik! Drive
+ * Reported by David Chatenay <dchatenay@hotmail.com>
+ * The reason this is needed is not fully known.
+ */
+UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
+ "Iomega",
+ "USB Clik! 40",
+ US_SC_8070, US_PR_BULK, NULL,
+ US_FL_FIX_INQUIRY | US_FL_START_STOP ),
+
/* This entry is needed because the device reports Sub=ff */
-UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0322,
+UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0422,
"Sony",
"DSC-S30/S70/S75/505V/F505",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
-/* Reported by win@geeks.nl */
+/* Reported by wim@geeks.nl */
UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100,
"Sony",
"Memorystick NW-MS7",
@@ -194,6 +228,13 @@ UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
US_SC_UFI, US_PR_CB, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP ),
+/* Submitted by Nathan Babb <nathan@lexi.com> */
+UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999,
+ "Sony",
+ "PEG Mass Storage",
+ US_SC_8070, US_PR_CBI, NULL,
+ US_FL_FIX_INQUIRY ),
+
UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299,
"Y-E Data",
"Flashbuster-U",
@@ -264,6 +305,14 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
US_FL_SINGLE_LUN | US_FL_START_STOP ),
#endif
+/* Submitted by f.brugmans@hccnet.nl
+ * Needed for START_STOP flag */
+UNUSUAL_DEV( 0x0686, 0x4007, 0x0001, 0x0001,
+ "Minolta",
+ "Dimage S304",
+ US_SC_SCSI, US_PR_BULK, NULL,
+ US_FL_START_STOP ),
+
UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100,
"Hagiwara",
"FlashGate SmartMedia",
@@ -307,7 +356,7 @@ UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999,
US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
#endif
-UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133,
"Microtech",
"USB-SCSI-DB25",
US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
@@ -374,16 +423,23 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
"Simple Tech/Datafab CF+SM Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP ),
+
+/* Submitted by Olaf Hering <olh@suse.de> */
+UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff,
+ "Datafab Systems, Inc.",
+ "USB to CF + SM Combo (LC1)",
+ US_SC_SCSI, US_PR_DATAFAB, NULL,
+ US_FL_MODE_XLATE | US_FL_START_STOP ),
#endif
-/* Casio QV 2x00/3x00/8000 digital still cameras are not conformant
+/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
* to the USB storage specification in two ways:
* - They tell us they are using transport protocol CBI. In reality they
* are using transport protocol CB.
* - They don't like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
*/
-UNUSUAL_DEV( 0x07cf, 0x1001, 0x9009, 0x9009,
+UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
"Casio",
"QV DigitalCamera",
US_SC_8070, US_PR_CB, NULL,
@@ -402,3 +458,12 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
#endif
+
+/* Reported by Dan Pilone <pilone@slac.com>
+ * The device needs the flags only.
+ */
+UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x9999,
+ "CCYU TECHNOLOGY",
+ "EasyDisk Portable Device",
+ US_SC_SCSI, US_PR_BULK, NULL,
+ US_FL_MODE_XLATE | US_FL_START_STOP),
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index e09641ee5..1d11dfb67 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1002,7 +1002,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* now register - our detect function will be called */
ss->htmplt.module = THIS_MODULE;
- scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt));
+ scsi_register_host(&ss->htmplt);
/* lock access to the data structures */
down(&us_list_semaphore);
@@ -1107,8 +1107,8 @@ void __exit usb_stor_exit(void)
* interface
*/
for (next = us_list; next; next = next->next) {
- US_DEBUGP("-- calling scsi_unregister_module()\n");
- scsi_unregister_module(MODULE_SCSI_HA, &(next->htmplt));
+ US_DEBUGP("-- calling scsi_unregister_host()\n");
+ scsi_unregister_host(&next->htmplt);
}
/* While there are still structures, free them. Note that we are
diff --git a/drivers/usb/stv680.c b/drivers/usb/stv680.c
new file mode 100644
index 000000000..c3df86637
--- /dev/null
+++ b/drivers/usb/stv680.c
@@ -0,0 +1,1633 @@
+/*
+ * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
+ *
+ * Thanks to STMicroelectronics for information on the usb commands, and
+ * to Steve Miller at STM for his help and encouragement while I was
+ * writing this driver.
+ *
+ * This driver is based heavily on the
+ * Endpoints (formerly known as AOX) se401 USB Camera Driver
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * Still somewhat based on the Linux ov511 driver.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * History:
+ * ver 0.1 October, 2001. Initial attempt.
+ *
+ * ver 0.2 November, 2001. Fixed asbility to resize, added brightness
+ * function, made more stable (?)
+ *
+ * ver 0.21 Nov, 2001. Added gamma correction and white balance,
+ * due to Alexander Schwartz. Still trying to
+ * improve stablility. Moved stuff into stv680.h
+ *
+ * ver 0.22 Nov, 2001. Added sharpen function (by Michael Sweet,
+ * mike@easysw.com) from GIMP, also used in pencam.
+ * Simple, fast, good integer math routine.
+ *
+ * ver 0.23 Dec, 2001 (gkh)
+ * Took out sharpen function, ran code through
+ * Lindent, and did other minor tweaks to get
+ * things to work properly with 2.5.1
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/wrapper.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/videodev.h>
+#include <linux/usb.h>
+
+#include "stv680.h"
+
+static int video_nr = -1;
+static int swapRGB = 0;
+
+static unsigned int debug = 0;
+
+#define PDEBUG(level, fmt, args...) \
+ do { \
+ if (debug >= level) \
+ info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args); \
+ } while (0)
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.23"
+#define DRIVER_AUTHOR "Kevin Sisson <kjsisson@bellsouth.net>"
+#define DRIVER_DESC "STV0680 USB Camera Driver"
+
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_LICENSE ("GPL");
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "Debug enabled or not");
+MODULE_PARM (swapRGB, "i");
+MODULE_PARM_DESC (swapRGB, "Swap red and blue, e.g., for xawtv");
+MODULE_PARM (video_nr, "i");
+EXPORT_NO_SYMBOLS;
+
+/********************************************************************
+ *
+ * Memory management
+ *
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.29 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
+ * there will be one, but apparentely not yet -jerdfelt
+ *
+ * So I copied it again for the ov511 driver -claudio
+ *
+ * Same for the se401 driver -Jeroen
+ *
+ * And the STV0680 driver - Kevin
+ ********************************************************************/
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva (pgd_t * pgd, unsigned long adr)
+{
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ if (!pgd_none (*pgd)) {
+ pmd = pmd_offset (pgd, adr);
+ if (!pmd_none (*pmd)) {
+ ptep = pte_offset (pmd, adr);
+ pte = *ptep;
+ if (pte_present (pte)) {
+ ret = (unsigned long) page_address (pte_page (pte));
+ ret |= (adr & (PAGE_SIZE - 1));
+ }
+ }
+ }
+ return ret;
+}
+
+/* Here we want the physical address of the memory. This is used when
+ * initializing the contents of the area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa (unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR (adr);
+ kva = uvirt_to_kva (pgd_offset_k (va), va);
+ ret = __pa (kva);
+ return ret;
+}
+
+static void *rvmalloc (unsigned long size)
+{
+ void *mem;
+ unsigned long adr, page;
+
+ /* Round it off to PAGE_SIZE */
+ size += (PAGE_SIZE - 1);
+ size &= ~(PAGE_SIZE - 1);
+
+ mem = vmalloc_32 (size);
+ if (!mem)
+ return NULL;
+
+ memset (mem, 0, size); /* Clear the ram out, no junk to the user */
+ adr = (unsigned long) mem;
+ while (size > 0) {
+ page = kvirt_to_pa (adr);
+ mem_map_reserve (virt_to_page (__va (page)));
+ adr += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+ return mem;
+}
+
+static void rvfree (void *mem, unsigned long size)
+{
+ unsigned long adr, page;
+
+ if (!mem)
+ return;
+
+ size += (PAGE_SIZE - 1);
+ size &= ~(PAGE_SIZE - 1);
+
+ adr = (unsigned long) mem;
+ while (size > 0) {
+ page = kvirt_to_pa (adr);
+ mem_map_unreserve (virt_to_page (__va (page)));
+ adr += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+ vfree (mem);
+}
+
+
+/*********************************************************************
+ * pencam read/write functions
+ ********************************************************************/
+
+static int stv_sndctrl (int set, struct usb_stv *stv680, unsigned short req, unsigned short value, unsigned char *buffer, int size)
+{
+ int ret = -1;
+
+ switch (set) {
+ case 0: /* 0xc1 */
+ ret = usb_control_msg (stv680->udev,
+ usb_rcvctrlpipe (stv680->udev, 0),
+ req,
+ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
+ value, 0, buffer, size, PENCAM_TIMEOUT);
+ break;
+
+ case 1: /* 0x41 */
+ ret = usb_control_msg (stv680->udev,
+ usb_sndctrlpipe (stv680->udev, 0),
+ req,
+ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
+ value, 0, buffer, size, PENCAM_TIMEOUT);
+ break;
+
+ case 2: /* 0x80 */
+ ret = usb_control_msg (stv680->udev,
+ usb_rcvctrlpipe (stv680->udev, 0),
+ req,
+ (USB_DIR_IN | USB_RECIP_DEVICE),
+ value, 0, buffer, size, PENCAM_TIMEOUT);
+ break;
+
+ case 3: /* 0x40 */
+ ret = usb_control_msg (stv680->udev,
+ usb_sndctrlpipe (stv680->udev, 0),
+ req,
+ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
+ value, 0, buffer, size, PENCAM_TIMEOUT);
+ break;
+
+ }
+ if ((ret < 0) && (req != 0x0a)) {
+ PDEBUG (1, "STV(e): usb_control_msg error %i, request = 0x%x, error = %i", set, req, ret);
+ }
+ return ret;
+}
+
+static int stv_set_config (struct usb_stv *dev, int configuration, int interface, int alternate)
+{
+
+ if (usb_set_configuration (dev->udev, configuration) < 0) {
+ PDEBUG (1, "STV(e): FAILED to set configuration %i", configuration);
+ return -1;
+ }
+ if (usb_set_interface (dev->udev, interface, alternate) < 0) {
+ PDEBUG (1, "STV(e): FAILED to set alternate interface %i", alternate);
+ return -1;
+ }
+ return 0;
+}
+
+static int stv_stop_video (struct usb_stv *dev)
+{
+ int i;
+ unsigned char *buf;
+
+ buf = kmalloc (40, GFP_KERNEL);
+ if (buf == NULL) {
+ PDEBUG (0, "STV(e): Out of (small buf) memory");
+ return -1;
+ }
+
+ /* this is a high priority command; it stops all lower order commands */
+ if ((i = stv_sndctrl (1, dev, 0x04, 0x0000, buf, 0x0)) < 0) {
+ i = stv_sndctrl (0, dev, 0x80, 0, buf, 0x02); /* Get Last Error; 2 = busy */
+ PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buf[0], buf[1]);
+ } else {
+ PDEBUG (1, "STV(i): Camera reset to idle mode.");
+ }
+
+ if ((i = stv_set_config (dev, 1, 0, 0)) < 0)
+ PDEBUG (1, "STV(e): Reset config during exit failed");
+
+ /* get current mode */
+ buf[0] = 0xf0;
+ if ((i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08)) != 0x08) /* get mode */
+ PDEBUG (0, "STV(e): Stop_video: problem setting original mode");
+ if (dev->origMode != buf[0]) {
+ memset (buf, 0, 8);
+ buf[0] = (unsigned char) dev->origMode;
+ if ((i = stv_sndctrl (3, dev, 0x07, 0x0100, buf, 0x08)) != 0x08) {
+ PDEBUG (0, "STV(e): Stop_video: Set_Camera_Mode failed");
+ i = -1;
+ }
+ buf[0] = 0xf0;
+ i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08);
+ if ((i != 0x08) || (buf[0] != dev->origMode)) {
+ PDEBUG (0, "STV(e): camera NOT set to original resolution.");
+ i = -1;
+ } else
+ PDEBUG (0, "STV(i): Camera set to original resolution");
+ }
+ /* origMode */
+ kfree (buf);
+ return i;
+}
+
+static int stv_set_video_mode (struct usb_stv *dev)
+{
+ int i, stop_video = 1;
+ unsigned char *buf;
+
+ buf = kmalloc (40, GFP_KERNEL);
+ if (buf == NULL) {
+ PDEBUG (0, "STV(e): Out of (small buf) memory");
+ return -1;
+ }
+
+ if ((i = stv_set_config (dev, 1, 0, 0)) < 0) {
+ kfree (buf);
+ return i;
+ }
+
+ i = stv_sndctrl (2, dev, 0x06, 0x0100, buf, 0x12);
+ if (!(i > 0) && (buf[8] == 0x53) && (buf[9] == 0x05)) {
+ PDEBUG (1, "STV(e): Could not get descriptor 0100.");
+ goto error;
+ }
+
+ /* set alternate interface 1 */
+ if ((i = stv_set_config (dev, 1, 0, 1)) < 0)
+ goto error;
+
+ if ((i = stv_sndctrl (0, dev, 0x85, 0, buf, 0x10)) != 0x10)
+ goto error;
+ PDEBUG (1, "STV(i): Setting video mode.");
+ /* Switch to Video mode: 0x0100 = VGA (640x480), 0x0000 = CIF (352x288) 0x0300 = QVGA (320x240) */
+ if ((i = stv_sndctrl (1, dev, 0x09, dev->VideoMode, buf, 0x0)) < 0) {
+ stop_video = 0;
+ goto error;
+ }
+ goto exit;
+
+error:
+ kfree (buf);
+ if (stop_video == 1)
+ stv_stop_video (dev);
+ return -1;
+
+exit:
+ kfree (buf);
+ return 0;
+}
+
+static int stv_init (struct usb_stv *stv680)
+{
+ int i = 0;
+ unsigned char *buffer;
+ unsigned long int bufsize;
+
+ buffer = kmalloc (40, GFP_KERNEL);
+ if (buffer == NULL) {
+ PDEBUG (0, "STV(e): Out of (small buf) memory");
+ return -1;
+ }
+ memset (buffer, 0, 40);
+ udelay (100);
+
+ /* set config 1, interface 0, alternate 0 */
+ if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) {
+ kfree (buffer);
+ PDEBUG (0, "STV(e): set config 1,0,0 failed");
+ return -1;
+ }
+ /* ping camera to be sure STV0680 is present */
+ if ((i = stv_sndctrl (0, stv680, 0x88, 0x5678, buffer, 0x02)) != 0x02)
+ goto error;
+ if ((buffer[0] != 0x56) || (buffer[1] != 0x78)) {
+ PDEBUG (1, "STV(e): camera ping failed!!");
+ goto error;
+ }
+
+ /* get camera descriptor */
+ if ((i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x09)) != 0x09)
+ goto error;
+ i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x22);
+ if (!(i >= 0) && (buffer[7] == 0xa0) && (buffer[8] == 0x23)) {
+ PDEBUG (1, "STV(e): Could not get descriptor 0200.");
+ goto error;
+ }
+ if ((i = stv_sndctrl (0, stv680, 0x8a, 0, buffer, 0x02)) != 0x02)
+ goto error;
+ if ((i = stv_sndctrl (0, stv680, 0x8b, 0, buffer, 0x24)) != 0x24)
+ goto error;
+ if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
+ goto error;
+
+ stv680->SupportedModes = buffer[7];
+ i = stv680->SupportedModes;
+ stv680->CIF = 0;
+ stv680->VGA = 0;
+ stv680->QVGA = 0;
+ if (i & 1)
+ stv680->CIF = 1;
+ if (i & 2)
+ stv680->VGA = 1;
+ if (i & 8)
+ stv680->QVGA = 1;
+ if (stv680->SupportedModes == 0) {
+ PDEBUG (0, "STV(e): There are NO supported STV680 modes!!");
+ i = -1;
+ goto error;
+ } else {
+ if (stv680->CIF)
+ PDEBUG (0, "STV(i): CIF is supported");
+ if (stv680->QVGA)
+ PDEBUG (0, "STV(i): QVGA is supported");
+ }
+ /* FW rev, ASIC rev, sensor ID */
+ PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]);
+ PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]);
+ PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4));
+
+ /* set alternate interface 1 */
+ if ((i = stv_set_config (stv680, 1, 0, 1)) < 0)
+ goto error;
+
+ if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
+ goto error;
+ if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08)
+ goto error;
+ i = buffer[3];
+ PDEBUG (0, "STV(i): Camera has %i pictures.", i);
+
+ /* get current mode */
+ if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08)
+ goto error;
+ stv680->origMode = buffer[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */
+
+ /* This will attemp CIF mode, if supported. If not, set to QVGA */
+ memset (buffer, 0, 8);
+ if (stv680->CIF)
+ buffer[0] = 0x00;
+ else if (stv680->QVGA)
+ buffer[0] = 0x03;
+ if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) {
+ PDEBUG (0, "STV(i): Set_Camera_Mode failed");
+ i = -1;
+ goto error;
+ }
+ buffer[0] = 0xf0;
+ stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08);
+ if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) {
+ PDEBUG (0, "STV(e): Error setting camera video mode!");
+ i = -1;
+ goto error;
+ } else {
+ if (buffer[0] == 0) {
+ stv680->VideoMode = 0x0000;
+ PDEBUG (0, "STV(i): Video Mode set to CIF");
+ }
+ if (buffer[0] == 0x03) {
+ stv680->VideoMode = 0x0300;
+ PDEBUG (0, "STV(i): Video Mode set to QVGA");
+ }
+ }
+ if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10)
+ goto error;
+ bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]);
+ stv680->cwidth = (buffer[4] << 8) | (buffer[5]); /* ->camera = 322, 356, 644 */
+ stv680->cheight = (buffer[6] << 8) | (buffer[7]); /* ->camera = 242, 292, 484 */
+ stv680->origGain = buffer[12];
+
+ goto exit;
+
+error:
+ i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02); /* Get Last Error */
+ PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buffer[0], buffer[1]);
+ kfree (buffer);
+ return -1;
+
+exit:
+ kfree (buffer);
+
+ /* video = 320x240, 352x288 */
+ if (stv680->CIF == 1) {
+ stv680->maxwidth = 352;
+ stv680->maxheight = 288;
+ stv680->vwidth = 352;
+ stv680->vheight = 288;
+ }
+ if (stv680->QVGA == 1) {
+ stv680->maxwidth = 320;
+ stv680->maxheight = 240;
+ stv680->vwidth = 320;
+ stv680->vheight = 240;
+ }
+
+ stv680->rawbufsize = bufsize; /* must be ./. by 8 */
+ stv680->maxframesize = bufsize * 3; /* RGB size */
+ PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight);
+ PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize);
+
+ /* some default values */
+ stv680->bulk_in_endpointAddr = 0x82;
+ stv680->dropped = 0;
+ stv680->error = 0;
+ stv680->framecount = 0;
+ stv680->readcount = 0;
+ stv680->streaming = 0;
+ /* bright, white, colour, hue, contrast are set by software, not in stv0680 */
+ stv680->brightness = 32767;
+ stv680->chgbright = 0;
+ stv680->whiteness = 0; /* only for greyscale */
+ stv680->colour = 32767;
+ stv680->contrast = 32767;
+ stv680->hue = 32767;
+ stv680->palette = STV_VIDEO_PALETTE;
+ stv680->depth = 24; /* rgb24 bits */
+ swapRGB = 0;
+ PDEBUG (1, "STV(i): swapRGB is OFF");
+
+ if (stv_set_video_mode (stv680) < 0) {
+ PDEBUG (0, "STV(e): Could not set video mode in stv_init");
+ return -1;
+ }
+
+ return 0;
+}
+
+/***************** last of pencam routines *******************/
+
+/********************************************************************
+ * /proc interface
+ *******************************************************************/
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+static struct proc_dir_entry *stv680_proc_entry = NULL;
+extern struct proc_dir_entry *video_proc_entry;
+
+#define YES_NO(x) ((x) ? "yes" : "no")
+
+static int stv680_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ char *out = page;
+ int len;
+ struct usb_stv *stv680 = data;
+
+ /* Stay under PAGE_SIZE or else bla bla bla.... */
+
+ out += sprintf (out, "driver_version : %s\n", DRIVER_VERSION);
+ out += sprintf (out, "model : %s\n", stv680->camera_name);
+ out += sprintf (out, "in use : %s\n", YES_NO (stv680->user));
+ out += sprintf (out, "streaming : %s\n", YES_NO (stv680->streaming));
+ out += sprintf (out, "num_frames : %d\n", STV680_NUMFRAMES);
+
+ out += sprintf (out, "Current size : %ix%i\n", stv680->vwidth, stv680->vheight);
+ out += sprintf (out, "swapRGB : %s\n", YES_NO (swapRGB));
+ out += sprintf (out, "Palette : %i", stv680->palette);
+
+ out += sprintf (out, "\n");
+
+ out += sprintf (out, "Frames total : %d\n", stv680->readcount);
+ out += sprintf (out, "Frames read : %d\n", stv680->framecount);
+ out += sprintf (out, "Packets dropped : %d\n", stv680->dropped);
+ out += sprintf (out, "Decoding Errors : %d\n", stv680->error);
+
+ len = out - page;
+ len -= off;
+ if (len < count) {
+ *eof = 1;
+ if (len <= 0)
+ return 0;
+ } else
+ len = count;
+
+ *start = page + off;
+ return len;
+}
+
+static int create_proc_stv680_cam (struct usb_stv *stv680)
+{
+ char name[9];
+ struct proc_dir_entry *ent;
+
+ if (!stv680_proc_entry || !stv680)
+ return -1;
+
+ sprintf (name, "video%d", stv680->vdev.minor);
+
+ ent = create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR, stv680_proc_entry);
+ if (!ent)
+ return -1;
+
+ ent->data = stv680;
+ ent->read_proc = stv680_read_proc;
+ stv680->proc_entry = ent;
+ return 0;
+}
+
+static void destroy_proc_stv680_cam (struct usb_stv *stv680)
+{
+ /* One to much, just to be sure :) */
+ char name[9];
+
+ if (!stv680 || !stv680->proc_entry)
+ return;
+
+ sprintf (name, "video%d", stv680->vdev.minor);
+ remove_proc_entry (name, stv680_proc_entry);
+ stv680->proc_entry = NULL;
+}
+
+static int proc_stv680_create (void)
+{
+ if (video_proc_entry == NULL) {
+ PDEBUG (0, "STV(e): /proc/video/ doesn't exist!");
+ return -1;
+ }
+ stv680_proc_entry = create_proc_entry ("stv680", S_IFDIR, video_proc_entry);
+
+ if (stv680_proc_entry) {
+ stv680_proc_entry->owner = THIS_MODULE;
+ } else {
+ PDEBUG (0, "STV(e): Unable to initialize /proc/video/stv680");
+ return -1;
+ }
+ return 0;
+}
+
+static void proc_stv680_destroy (void)
+{
+ if (stv680_proc_entry == NULL)
+ return;
+
+ remove_proc_entry ("stv", video_proc_entry);
+}
+#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
+
+/********************************************************************
+ * Camera control
+ *******************************************************************/
+
+static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p)
+{
+ /* This sets values for v4l interface. max/min = 65535/0 */
+
+ p->brightness = stv680->brightness;
+ p->whiteness = stv680->whiteness; /* greyscale */
+ p->colour = stv680->colour;
+ p->contrast = stv680->contrast;
+ p->hue = stv680->hue;
+ p->palette = stv680->palette;
+ p->depth = stv680->depth;
+ return 0;
+}
+
+static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p)
+{
+ /* See above stv680_get_pict */
+
+ if (p->palette != STV_VIDEO_PALETTE) {
+ PDEBUG (2, "STV(e): Palette set error in _set_pic");
+ return 1;
+ }
+
+ if (stv680->brightness != p->brightness) {
+ stv680->chgbright = 1;
+ stv680->brightness = p->brightness;
+ } else {
+ stv680->chgbright = 0;
+ }
+
+ stv680->whiteness = p->whiteness; /* greyscale */
+ stv680->colour = p->colour;
+ stv680->contrast = p->contrast;
+ stv680->hue = p->hue;
+ stv680->palette = p->palette;
+ stv680->depth = p->depth;
+
+ return 0;
+}
+
+static void stv680_video_irq (struct urb *urb)
+{
+ struct usb_stv *stv680 = urb->context;
+ int length = urb->actual_length;
+
+ if (length < stv680->rawbufsize)
+ PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length);
+
+ /* ohoh... */
+ if (!stv680->streaming)
+ return;
+
+ if (!stv680->udev) {
+ PDEBUG (0, "STV(e): device vapourished in video_irq");
+ return;
+ }
+
+ /* 0 sized packets happen if we are to fast, but sometimes the camera
+ keeps sending them forever...
+ */
+ if (length && !urb->status) {
+ stv680->nullpackets = 0;
+ switch (stv680->scratch[stv680->scratch_next].state) {
+ case BUFFER_READY:
+ case BUFFER_BUSY:
+ stv680->dropped++;
+ break;
+
+ case BUFFER_UNUSED:
+ memcpy (stv680->scratch[stv680->scratch_next].data,
+ (unsigned char *) urb->transfer_buffer, length);
+ stv680->scratch[stv680->scratch_next].state = BUFFER_READY;
+ stv680->scratch[stv680->scratch_next].length = length;
+ if (waitqueue_active (&stv680->wq)) {
+ wake_up_interruptible (&stv680->wq);
+ }
+ stv680->scratch_overflow = 0;
+ stv680->scratch_next++;
+ if (stv680->scratch_next >= STV680_NUMSCRATCH)
+ stv680->scratch_next = 0;;
+ break;
+ } /* switch */
+ } else {
+ stv680->nullpackets++;
+ if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
+ if (waitqueue_active (&stv680->wq)) {
+ wake_up_interruptible (&stv680->wq);
+ }
+ }
+ } /* if - else */
+
+ /* Resubmit urb for new data */
+ urb->status = 0;
+ urb->dev = stv680->udev;
+ if (usb_submit_urb (urb))
+ PDEBUG (0, "STV(e): urb burned down in video irq");
+ return;
+} /* _video_irq */
+
+static int stv680_start_stream (struct usb_stv *stv680)
+{
+ urb_t *urb;
+ int err = 0, i;
+
+ stv680->streaming = 1;
+
+ /* Do some memory allocation */
+ for (i = 0; i < STV680_NUMFRAMES; i++) {
+ stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize;
+ stv680->frame[i].curpix = 0;
+ }
+ /* packet size = 4096 */
+ for (i = 0; i < STV680_NUMSBUF; i++) {
+ stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
+ if (stv680->sbuf[i].data == NULL) {
+ PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);
+ return -1;
+ }
+ }
+
+ stv680->scratch_next = 0;
+ stv680->scratch_use = 0;
+ stv680->scratch_overflow = 0;
+ for (i = 0; i < STV680_NUMSCRATCH; i++) {
+ stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
+ if (stv680->scratch[i].data == NULL) {
+ PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);
+ return -1;
+ }
+ stv680->scratch[i].state = BUFFER_UNUSED;
+ }
+
+ for (i = 0; i < STV680_NUMSBUF; i++) {
+ urb = usb_alloc_urb (0);
+ if (!urb)
+ return ENOMEM;
+
+ /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */
+ usb_fill_bulk_urb (urb, stv680->udev,
+ usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
+ stv680->sbuf[i].data, stv680->rawbufsize,
+ stv680_video_irq, stv680);
+ urb->timeout = PENCAM_TIMEOUT * 2;
+ urb->transfer_flags |= USB_QUEUE_BULK;
+ stv680->urb[i] = urb;
+ err = usb_submit_urb (stv680->urb[i]);
+ if (err)
+ PDEBUG (0, "STV(e): urb burned down in start stream");
+ } /* i STV680_NUMSBUF */
+
+ stv680->framecount = 0;
+ return 0;
+}
+
+static int stv680_stop_stream (struct usb_stv *stv680)
+{
+ int i;
+
+ if (!stv680->streaming || !stv680->udev)
+ return 1;
+
+ stv680->streaming = 0;
+
+ for (i = 0; i < STV680_NUMSBUF; i++)
+ if (stv680->urb[i]) {
+ stv680->urb[i]->next = NULL;
+ usb_unlink_urb (stv680->urb[i]);
+ usb_free_urb (stv680->urb[i]);
+ stv680->urb[i] = NULL;
+ kfree (stv680->sbuf[i].data);
+ }
+ for (i = 0; i < STV680_NUMSCRATCH; i++) {
+ kfree (stv680->scratch[i].data);
+ stv680->scratch[i].data = NULL;
+ }
+
+ return 0;
+}
+
+static int stv680_set_size (struct usb_stv *stv680, int width, int height)
+{
+ int wasstreaming = stv680->streaming;
+
+ /* Check to see if we need to change */
+ if ((stv680->vwidth == width) && (stv680->vheight == height))
+ return 0;
+
+ PDEBUG (1, "STV(i): size request for %i x %i", width, height);
+ /* Check for a valid mode */
+ if ((!width || !height) || ((width & 1) || (height & 1))) {
+ PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
+ return 1;
+ }
+
+ if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) {
+ width = stv680->maxwidth / 2;
+ height = stv680->maxheight / 2;
+ } else if ((width >= 158) && (width <= 166)) {
+ width = 160;
+ height = 120;
+ } else if ((width >= 172) && (width <= 180)) {
+ width = 176;
+ height = 144;
+ } else if ((width >= 318) && (width <= 350)) {
+ width = 320;
+ height = 240;
+ } else if ((width >= 350) && (width <= 358)) {
+ width = 352;
+ height = 288;
+ }
+
+ /* Stop a current stream and start it again at the new size */
+ if (wasstreaming)
+ stv680_stop_stream (stv680);
+ stv680->vwidth = width;
+ stv680->vheight = height;
+ PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight);
+ if (wasstreaming)
+ stv680_start_stream (stv680);
+
+ return 0;
+}
+
+/**********************************************************************
+ * Video Decoding
+ **********************************************************************/
+
+/******* routines from the pencam program; hey, they work! ********/
+
+/*
+ * STV0680 Vision Camera Chipset Driver
+ * Copyright (C) 2000 Adam Harrison <adam@antispin.org>
+*/
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define AD(x, y, w) (((y)*(w)+(x))*3)
+
+static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer)
+{
+ int x, y, i;
+ int w = stv680->cwidth;
+ int vw = stv680->cwidth, vh = stv680->cheight, vstep = 1;
+ unsigned int p = 0;
+ int colour = 0, bayer = 0;
+ unsigned char *raw = buffer->data;
+ struct stv680_frame *frame = &stv680->frame[stv680->curframe];
+ unsigned char *output = frame->data;
+ unsigned char *temp = frame->data;
+ int offset = buffer->offset;
+
+ if (frame->curpix == 0) {
+ if (frame->grabstate == FRAME_READY) {
+ frame->grabstate = FRAME_GRABBING;
+ }
+ }
+ if (offset != frame->curpix) { /* Regard frame as lost :( */
+ frame->curpix = 0;
+ stv680->error++;
+ return;
+ }
+
+ if ((stv680->vwidth == 322) || (stv680->vwidth == 320)) {
+ vw = 320;
+ vh = 240;
+ vstep = 1;
+ }
+ if ((stv680->vwidth == 352)) {
+ vw = 352;
+ vh = 288;
+ vstep = 1;
+ }
+ if ((stv680->vwidth == 160)) {
+ vw = 160;
+ vh = 120;
+ vstep = 2;
+ }
+ if ((stv680->vwidth == 176)) {
+ vw = 176;
+ vh = 144;
+ vstep = 2;
+ }
+ memset (output, 0, 3 * vw * vh); /* clear output matrix. Maybe not necessary. */
+
+ for (y = 0; y < vh; y++) {
+ for (x = 0; x < vw; x++) {
+
+ switch (vstep) {
+ case 1:
+ if (x & 1)
+ p = *(raw + y * w + (x >> 1));
+ else
+ p = *(raw + y * w + (x >> 1) + (w >> 1));
+ break;
+
+ case 2:
+ if (x & 1)
+ p = *(raw + ((y * w) << 1) + x);
+ else
+ p = *(raw + ((y * w) << 1) + x + (w >> 1));
+ break;
+ }
+
+ if (y & 1)
+ bayer = 2;
+ else
+ bayer = 0;
+ if (x & 1)
+ bayer++;
+
+ switch (bayer) {
+ case 0:
+ case 3:
+ colour = 1;
+ break;
+ case 1:
+ colour = 0;
+ break;
+ case 2:
+ colour = 2;
+ break;
+ }
+ i = (y * vw + x) * 3; /* output already zeroed out with memset */
+ *(output + i + colour) = (unsigned char) p;
+ } /* for x */
+ } /* for y */
+
+ /****** gamma correction plus hardcoded white balance */
+ /* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code.
+ Correction values red[], green[], blue[], are generated by
+ (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255.
+ White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and
+ converted to unsigned char. Values are in stv680.h */
+ for (y = 0; y < vh; y++) {
+ for (x = 0; x < vw; x++) {
+ i = (y * vw + x) * 3;
+ *(output + i) = red[*(output + i)];
+ *(output + i + 1) = green[*(output + i + 1)];
+ *(output + i + 2) = blue[*(output + i + 2)];
+ }
+ }
+
+ /****** bayer demosaic ******/
+ for (y = 1; y < (vh - 1); y++) {
+ for (x = 1; x < (vw - 1); x++) { /* work out pixel type */
+ if (y & 1)
+ bayer = 0;
+ else
+ bayer = 2;
+ if (!(x & 1))
+ bayer++;
+
+ switch (bayer) {
+ case 0: /* green. blue lr, red tb */
+ *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y, vw) + BLUE) + (int) *(output + AD (x + 1, y, vw) + BLUE)) >> 1;
+ *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1;
+ break;
+
+ case 1: /* blue. green lrtb, red diagonals */
+ *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
+ *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2;
+ break;
+
+ case 2: /* red. green lrtb, blue diagonals */
+ *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
+ *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2;
+ break;
+
+ case 3: /* green. red lr, blue tb */
+ *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1;
+ *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1;
+ break;
+ } /* switch */
+ } /* for x */
+ } /* for y - end demosaic */
+
+ /* output is RGB; some programs want BGR */
+ if (swapRGB == 1) {
+ for (y = 0; y < vh; y++) {
+ for (x = 0; x < vw; x++) {
+ i = (y * vw + x) * 3;
+ *(temp) = *(output + i);
+ *(output + i) = *(output + i + 2);
+ *(output + i + 2) = *(temp);
+ }
+ }
+ }
+ /* brightness */
+ if (stv680->chgbright == 1) {
+ if (stv680->brightness >= 32767) {
+ p = (stv680->brightness - 32767) / 256;
+ for (x = 0; x < (vw * vh * 3); x++) {
+ if ((*(output + x) + (unsigned char) p) > 255)
+ *(output + x) = 255;
+ else
+ *(output + x) += (unsigned char) p;
+ } /* for */
+ } else {
+ p = (32767 - stv680->brightness) / 256;
+ for (x = 0; x < (vw * vh * 3); x++) {
+ if ((unsigned char) p > *(output + x))
+ *(output + x) = 0;
+ else
+ *(output + x) -= (unsigned char) p;
+ } /* for */
+ } /* else */
+ }
+ /* if */
+ frame->curpix = 0;
+ frame->curlinepix = 0;
+ frame->grabstate = FRAME_DONE;
+ stv680->framecount++;
+ stv680->readcount++;
+ if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) {
+ stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1);
+ }
+
+} /* bayer_unshuffle */
+
+/******* end routines from the pencam program *********/
+
+static int stv680_newframe (struct usb_stv *stv680, int framenr)
+{
+ int errors = 0;
+
+ while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) {
+ if (!stv680->frame[framenr].curpix) {
+ errors++;
+ }
+ wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY));
+
+ if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
+ stv680->nullpackets = 0;
+ PDEBUG (2, "STV(i): too many null length packets, restarting capture");
+ stv680_stop_stream (stv680);
+ stv680_start_stream (stv680);
+ } else {
+ if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) {
+ stv680->frame[framenr].grabstate = FRAME_ERROR;
+ PDEBUG (2, "STV(e): FRAME_ERROR in _newframe");
+ return -EIO;
+ }
+ stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY;
+
+ bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]);
+
+ stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED;
+ stv680->scratch_use++;
+ if (stv680->scratch_use >= STV680_NUMSCRATCH)
+ stv680->scratch_use = 0;
+ if (errors > STV680_MAX_ERRORS) {
+ errors = 0;
+ PDEBUG (2, "STV(i): too many errors, restarting capture");
+ stv680_stop_stream (stv680);
+ stv680_start_stream (stv680);
+ }
+ } /* else */
+ } /* while */
+ return 0;
+}
+
+/*********************************************************************
+ * Video4Linux
+ *********************************************************************/
+
+static int stv_open (struct video_device *dev, int flags)
+{
+ struct usb_stv *stv680 = (struct usb_stv *) dev;
+ int err = 0;
+
+ /* we are called with the BKL held */
+ MOD_INC_USE_COUNT;
+ stv680->user = 1;
+ err = stv_init (stv680); /* main initialization routine for camera */
+
+ if (err >= 0) {
+ stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES);
+ if (!stv680->fbuf) {
+ PDEBUG (0, "STV(e): Could not rvmalloc frame bufer");
+ err = -ENOMEM;
+ }
+ }
+ if (err) {
+ MOD_DEC_USE_COUNT;
+ stv680->user = 0;
+ }
+
+ return err;
+}
+
+static void stv_close (struct video_device *dev)
+{
+ /* called with BKL held */
+ struct usb_stv *stv680 = (struct usb_stv *) dev;
+ int i;
+
+ for (i = 0; i < STV680_NUMFRAMES; i++)
+ stv680->frame[i].grabstate = FRAME_UNUSED;
+ if (stv680->streaming)
+ stv680_stop_stream (stv680);
+
+ if ((i = stv_stop_video (stv680)) < 0)
+ PDEBUG (1, "STV(e): stop_video failed in stv_close");
+
+ rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES);
+ stv680->user = 0;
+
+ if (stv680->removed) {
+ video_unregister_device (&stv680->vdev);
+ kfree (stv680);
+ stv680 = NULL;
+ PDEBUG (0, "STV(i): device unregistered");
+ }
+ MOD_DEC_USE_COUNT;
+}
+
+static long stv680_write (struct video_device *dev, const char *buf, unsigned long count, int noblock)
+{
+ return -EINVAL;
+}
+
+static int stv680_ioctl (struct video_device *vdev, unsigned int cmd, void *arg)
+{
+ struct usb_stv *stv680 = (struct usb_stv *) vdev;
+
+ if (!stv680->udev)
+ return -EIO;
+
+ switch (cmd) {
+ case VIDIOCGCAP:{
+ struct video_capability b;
+
+ strcpy (b.name, stv680->camera_name);
+ b.type = VID_TYPE_CAPTURE;
+ b.channels = 1;
+ b.audios = 0;
+ b.maxwidth = stv680->maxwidth;
+ b.maxheight = stv680->maxheight;
+ b.minwidth = stv680->maxwidth / 2;
+ b.minheight = stv680->maxheight / 2;
+
+ if (copy_to_user (arg, &b, sizeof (b))) {
+ PDEBUG (2, "STV(e): VIDIOCGGAP failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case VIDIOCGCHAN:{
+ struct video_channel v;
+
+ if (copy_from_user (&v, arg, sizeof (v)))
+ return -EFAULT;
+ if (v.channel != 0)
+ return -EINVAL;
+
+ v.flags = 0;
+ v.tuners = 0;
+ v.type = VIDEO_TYPE_CAMERA;
+ strcpy (v.name, "STV Camera");
+
+ if (copy_to_user (arg, &v, sizeof (v))) {
+ PDEBUG (2, "STV(e): VIDIOCGCHAN failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case VIDIOCSCHAN:{
+ int v;
+
+ if (copy_from_user (&v, arg, sizeof (v))) {
+ PDEBUG (2, "STV(e): VIDIOCSCHAN failed");
+ return -EFAULT;
+ }
+ if (v != 0)
+ return -EINVAL;
+
+ return 0;
+ }
+ case VIDIOCGPICT:{
+ struct video_picture p;
+
+ stv680_get_pict (stv680, &p);
+ if (copy_to_user (arg, &p, sizeof (p))) {
+ PDEBUG (2, "STV(e): VIDIOCGPICT failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case VIDIOCSPICT:{
+ struct video_picture p;
+
+ if (copy_from_user (&p, arg, sizeof (p))) {
+ PDEBUG (2, "STV(e): VIDIOCSPICT failed");
+ return -EFAULT;
+ }
+ copy_from_user (&p, arg, sizeof (p));
+ PDEBUG (2, "STV(i): palette set to RGB in VIDIOSPICT");
+
+ if (stv680_set_pict (stv680, &p))
+ return -EINVAL;
+ return 0;
+ }
+ case VIDIOCSWIN:{
+ struct video_window vw;
+
+ if (copy_from_user (&vw, arg, sizeof (vw)))
+ return -EFAULT;
+ if (vw.flags)
+ return -EINVAL;
+ if (vw.clipcount)
+ return -EINVAL;
+ if (vw.width != stv680->vwidth) {
+ if (stv680_set_size (stv680, vw.width, vw.height)) {
+ PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN");
+ return -EINVAL;
+ }
+ }
+ return 0;
+ }
+ case VIDIOCGWIN:{
+ struct video_window vw;
+
+ vw.x = 0; /* FIXME */
+ vw.y = 0;
+ vw.chromakey = 0;
+ vw.flags = 0;
+ vw.clipcount = 0;
+ vw.width = stv680->vwidth;
+ vw.height = stv680->vheight;
+
+ if (copy_to_user (arg, &vw, sizeof (vw))) {
+ PDEBUG (2, "STV(e): VIDIOCGWIN failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case VIDIOCGMBUF:{
+ struct video_mbuf vm;
+ int i;
+
+ memset (&vm, 0, sizeof (vm));
+ vm.size = STV680_NUMFRAMES * stv680->maxframesize;
+ vm.frames = STV680_NUMFRAMES;
+ for (i = 0; i < STV680_NUMFRAMES; i++)
+ vm.offsets[i] = stv680->maxframesize * i;
+
+ if (copy_to_user ((void *) arg, (void *) &vm, sizeof (vm))) {
+ PDEBUG (2, "STV(e): VIDIOCGMBUF failed");
+ return -EFAULT;
+ }
+
+ return 0;
+ }
+ case VIDIOCMCAPTURE:{
+ struct video_mmap vm;
+
+ if (copy_from_user (&vm, arg, sizeof (vm))) {
+ PDEBUG (2, "STV(e): VIDIOCMCAPTURE failed");
+ return -EFAULT;
+ }
+ if (vm.format != STV_VIDEO_PALETTE) {
+ PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)",
+ vm.format, STV_VIDEO_PALETTE);
+ if (vm.format == 3) {
+ PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is ON");
+ /* this may fix those apps (e.g., xawtv) that want BGR */
+ swapRGB = 1;
+ }
+ return -EINVAL;
+ }
+ if (vm.frame >= STV680_NUMFRAMES) {
+ PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES");
+ return -EINVAL;
+ }
+ if (stv680->frame[vm.frame].grabstate != FRAME_UNUSED) {
+ PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate != FRAME_UNUSED");
+ return -EBUSY;
+ }
+ /* Is this according to the v4l spec??? */
+ if (stv680->vwidth != vm.width) {
+ if (stv680_set_size (stv680, vm.width, vm.height)) {
+ PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed");
+ return -EINVAL;
+ }
+ }
+ stv680->frame[vm.frame].grabstate = FRAME_READY;
+
+ if (!stv680->streaming)
+ stv680_start_stream (stv680);
+
+ return 0;
+ }
+ case VIDIOCSYNC:{
+ int frame, ret = 0;
+
+ if (copy_from_user ((void *) &frame, arg, sizeof (int))) {
+ PDEBUG (2, "STV(e): VIDIOCSYNC failed");
+ return -EFAULT;
+ }
+ if (frame < 0 || frame >= STV680_NUMFRAMES) {
+ PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC");
+ return -EINVAL;
+ }
+ ret = stv680_newframe (stv680, frame);
+ stv680->frame[frame].grabstate = FRAME_UNUSED;
+ return ret;
+ }
+ case VIDIOCGFBUF:{
+ struct video_buffer vb;
+
+ memset (&vb, 0, sizeof (vb));
+ vb.base = NULL; /* frame buffer not supported, not used */
+
+ if (copy_to_user ((void *) arg, (void *) &vb, sizeof (vb))) {
+ PDEBUG (2, "STV(e): VIDIOCSYNC failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+ case VIDIOCKEY:
+ return 0;
+ case VIDIOCCAPTURE:
+ {
+ PDEBUG (2, "STV(e): VIDIOCCAPTURE failed");
+ return -EINVAL;
+ }
+ case VIDIOCSFBUF:
+ return -EINVAL;
+ case VIDIOCGTUNER:
+ case VIDIOCSTUNER:
+ return -EINVAL;
+ case VIDIOCGFREQ:
+ case VIDIOCSFREQ:
+ return -EINVAL;
+ case VIDIOCGAUDIO:
+ case VIDIOCSAUDIO:
+ return -EINVAL;
+ default:
+ return -ENOIOCTLCMD;
+ } /* end switch */
+
+ return 0;
+}
+
+static int stv680_mmap (struct vm_area_struct *vma, struct video_device *dev, const char *adr, unsigned long size)
+{
+ struct usb_stv *stv680 = (struct usb_stv *) dev;
+ unsigned long start = (unsigned long) adr;
+ unsigned long page, pos;
+
+ down (&stv680->lock);
+
+ if (stv680->udev == NULL) {
+ up (&stv680->lock);
+ return -EIO;
+ }
+ if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)
+ & ~(PAGE_SIZE - 1))) {
+ up (&stv680->lock);
+ return -EINVAL;
+ }
+ pos = (unsigned long) stv680->fbuf;
+ while (size > 0) {
+ page = kvirt_to_pa (pos);
+ if (remap_page_range (vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+ up (&stv680->lock);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+ up (&stv680->lock);
+
+ return 0;
+}
+
+static long stv680_read (struct video_device *dev, char *buf, unsigned long count, int noblock)
+{
+ unsigned long int realcount = count;
+ int ret = 0;
+ struct usb_stv *stv680 = (struct usb_stv *) dev;
+ unsigned long int i;
+
+ if (STV680_NUMFRAMES != 2) {
+ PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!");
+ return -1;
+ }
+ if (stv680->udev == NULL)
+ return -EIO;
+ if (realcount > (stv680->vwidth * stv680->vheight * 3))
+ realcount = stv680->vwidth * stv680->vheight * 3;
+
+ /* Shouldn't happen: */
+ if (stv680->frame[0].grabstate == FRAME_GRABBING) {
+ PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read");
+ return -EBUSY;
+ }
+ stv680->frame[0].grabstate = FRAME_READY;
+ stv680->frame[1].grabstate = FRAME_UNUSED;
+ stv680->curframe = 0;
+
+ if (!stv680->streaming)
+ stv680_start_stream (stv680);
+
+ if (!stv680->streaming) {
+ ret = stv680_newframe (stv680, 0); /* ret should = 0 */
+ }
+
+ ret = stv680_newframe (stv680, 0);
+
+ if (!ret) {
+ if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) {
+ PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i);
+ return -EFAULT;
+ }
+ } else {
+ realcount = ret;
+ }
+ stv680->frame[0].grabstate = FRAME_UNUSED;
+ return realcount;
+} /* stv680_read */
+
+static int stv_init_done (struct video_device *dev)
+{
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+ if (create_proc_stv680_cam ((struct usb_stv *) dev) < 0)
+ return -1;
+#endif
+ return 0;
+}
+
+static struct video_device stv680_template = {
+ owner: THIS_MODULE,
+ name: "STV0680 USB camera",
+ type: VID_TYPE_CAPTURE,
+ hardware: VID_HARDWARE_SE401,
+ open: stv_open,
+ close: stv_close,
+ read: stv680_read,
+ write: stv680_write,
+ ioctl: stv680_ioctl,
+ mmap: stv680_mmap,
+ initialize: stv_init_done,
+};
+
+static void *__devinit stv680_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
+{
+ struct usb_interface_descriptor *interface;
+ struct usb_stv *stv680;
+ char *camera_name = NULL;
+
+ /* We don't handle multi-config cameras */
+ if (dev->descriptor.bNumConfigurations != 1) {
+ PDEBUG (0, "STV(e): Number of Configurations != 1");
+ return NULL;
+ }
+
+ interface = &dev->actconfig->interface[ifnum].altsetting[0];
+ /* Is it a STV680? */
+ if ((dev->descriptor.idVendor == USB_PENCAM_VENDOR_ID) && (dev->descriptor.idProduct == USB_PENCAM_PRODUCT_ID)) {
+ camera_name = "STV0680";
+ PDEBUG (0, "STV(i): STV0680 camera found.");
+ } else {
+ PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values.");
+ PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer.");
+ return NULL;
+ }
+ /* We found one */
+ if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {
+ PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct.");
+ return NULL;
+ }
+
+ memset (stv680, 0, sizeof (*stv680));
+
+ stv680->udev = dev;
+ stv680->camera_name = camera_name;
+
+ memcpy (&stv680->vdev, &stv680_template, sizeof (stv680_template));
+ memcpy (stv680->vdev.name, stv680->camera_name, strlen (stv680->camera_name));
+ init_waitqueue_head (&stv680->wq);
+ init_MUTEX (&stv680->lock);
+ wmb ();
+
+ if (video_register_device (&stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+ kfree (stv680);
+ PDEBUG (0, "STV(e): video_register_device failed");
+ return NULL;
+ }
+ PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev.minor);
+
+ return stv680;
+}
+
+static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
+{
+ int i;
+
+ stv680->udev = NULL;
+ stv680->frame[0].grabstate = FRAME_ERROR;
+ stv680->frame[1].grabstate = FRAME_ERROR;
+ stv680->streaming = 0;
+
+ wake_up_interruptible (&stv680->wq);
+
+ for (i = 0; i < STV680_NUMSBUF; i++)
+ if (stv680->urb[i]) {
+ stv680->urb[i]->next = NULL;
+ usb_unlink_urb (stv680->urb[i]);
+ usb_free_urb (stv680->urb[i]);
+ stv680->urb[i] = NULL;
+ kfree (stv680->sbuf[i].data);
+ }
+ for (i = 0; i < STV680_NUMSCRATCH; i++)
+ if (stv680->scratch[i].data) {
+ kfree (stv680->scratch[i].data);
+ }
+ PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+ destroy_proc_stv680_cam (stv680);
+#endif
+ /* Free the memory */
+ kfree (stv680);
+}
+
+static void stv680_disconnect (struct usb_device *dev, void *ptr)
+{
+ struct usb_stv *stv680 = (struct usb_stv *) ptr;
+
+ lock_kernel ();
+ /* We don't want people trying to open up the device */
+ if (!stv680->user) {
+ video_unregister_device (&stv680->vdev);
+ usb_stv680_remove_disconnected (stv680);
+ } else {
+ stv680->removed = 1;
+ }
+ unlock_kernel ();
+}
+
+static struct usb_driver stv680_driver = {
+ name: "stv680",
+ probe: stv680_probe,
+ disconnect: stv680_disconnect,
+ id_table: device_table
+};
+
+/********************************************************************
+ * Module routines
+ ********************************************************************/
+
+static int __init usb_stv680_init (void)
+{
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+ if (proc_stv680_create () < 0)
+ return -1;
+#endif
+ if (usb_register (&stv680_driver) < 0) {
+ PDEBUG (0, "STV(e): Could not setup STV0680 driver");
+ return -1;
+ }
+ PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION);
+
+ info(DRIVER_DESC " " DRIVER_VERSION);
+ return 0;
+}
+
+static void __exit usb_stv680_exit (void)
+{
+ usb_deregister (&stv680_driver);
+ PDEBUG (0, "STV(i): driver deregistered");
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+ proc_stv680_destroy ();
+#endif
+}
+
+module_init (usb_stv680_init);
+module_exit (usb_stv680_exit);
diff --git a/drivers/usb/stv680.h b/drivers/usb/stv680.h
new file mode 100644
index 000000000..74abaabb9
--- /dev/null
+++ b/drivers/usb/stv680.h
@@ -0,0 +1,222 @@
+/****************************************************************************
+ *
+ * Filename: stv680.h
+ *
+ * Description:
+ * This is a USB driver for STV0680 based usb video cameras.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************************/
+
+/* size of usb transfers */
+#define STV680_PACKETSIZE 4096
+
+/* number of queued bulk transfers to use, may have problems if > 1 */
+#define STV680_NUMSBUF 1
+
+/* number of frames supported by the v4l part */
+#define STV680_NUMFRAMES 2
+
+/* scratch buffers for passing data to the decoders: 2 or 4 are good */
+#define STV680_NUMSCRATCH 2
+
+/* number of nul sized packets to receive before kicking the camera */
+#define STV680_MAX_NULLPACKETS 200
+
+/* number of decoding errors before kicking the camera */
+#define STV680_MAX_ERRORS 100
+
+#define USB_PENCAM_VENDOR_ID 0x0553
+#define USB_PENCAM_PRODUCT_ID 0x0202
+#define PENCAM_TIMEOUT 1000
+/* fmt 4 */
+#define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24
+
+static __devinitdata struct usb_device_id device_table[] = {
+ {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)},
+ {}
+};
+MODULE_DEVICE_TABLE (usb, device_table);
+
+struct stv680_sbuf {
+ unsigned char *data;
+};
+
+enum {
+ FRAME_UNUSED, /* Unused (no MCAPTURE) */
+ FRAME_READY, /* Ready to start grabbing */
+ FRAME_GRABBING, /* In the process of being grabbed into */
+ FRAME_DONE, /* Finished grabbing, but not been synced yet */
+ FRAME_ERROR, /* Something bad happened while processing */
+};
+
+enum {
+ BUFFER_UNUSED,
+ BUFFER_READY,
+ BUFFER_BUSY,
+ BUFFER_DONE,
+};
+
+/* raw camera data <- sbuf (urb transfer buf) */
+struct stv680_scratch {
+ unsigned char *data;
+ volatile int state;
+ int offset;
+ int length;
+};
+
+/* processed data for display ends up here, after bayer */
+struct stv680_frame {
+ unsigned char *data; /* Frame buffer */
+ volatile int grabstate; /* State of grabbing */
+ unsigned char *curline;
+ int curlinepix;
+ int curpix;
+};
+
+/* this is almost the video structure uvd_t, with extra parameters for stv */
+struct usb_stv {
+ struct video_device vdev;
+
+ struct usb_device *udev;
+
+ unsigned char bulk_in_endpointAddr; /* __u8 the address of the bulk in endpoint */
+ char *camera_name;
+
+ unsigned int VideoMode; /* 0x0100 = VGA, 0x0000 = CIF, 0x0300 = QVGA */
+ int SupportedModes;
+ int CIF;
+ int VGA;
+ int QVGA;
+ int cwidth; /* camera width */
+ int cheight; /* camera height */
+ int maxwidth; /* max video width */
+ int maxheight; /* max video height */
+ int vwidth; /* current width for video window */
+ int vheight; /* current height for video window */
+ unsigned long int rawbufsize;
+ unsigned long int maxframesize; /* rawbufsize * 3 for RGB */
+
+ int origGain;
+ int origMode; /* original camera mode */
+
+ struct semaphore lock; /* to lock the structure */
+ int user; /* user count for exclusive use */
+ int removed; /* device disconnected */
+ int streaming; /* Are we streaming video? */
+ char *fbuf; /* Videodev buffer area */
+ urb_t *urb[STV680_NUMSBUF]; /* # of queued bulk transfers */
+ int curframe; /* Current receiving frame */
+ struct stv680_frame frame[STV680_NUMFRAMES]; /* # frames supported by v4l part */
+ int readcount;
+ int framecount;
+ int error;
+ int dropped;
+ int scratch_next;
+ int scratch_use;
+ int scratch_overflow;
+ struct stv680_scratch scratch[STV680_NUMSCRATCH]; /* for decoders */
+ struct stv680_sbuf sbuf[STV680_NUMSBUF];
+
+ unsigned int brightness;
+ unsigned int chgbright;
+ unsigned int whiteness;
+ unsigned int colour;
+ unsigned int contrast;
+ unsigned int hue;
+ unsigned int palette;
+ unsigned int depth; /* rgb24 in bits */
+
+ wait_queue_head_t wq; /* Processes waiting */
+
+ struct proc_dir_entry *proc_entry; /* /proc/stv680/videoX */
+ int nullpackets;
+};
+
+unsigned char red[256] = {
+ 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,
+ 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,
+ 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97,
+ 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113,
+ 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,
+ 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
+ 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
+ 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177,
+ 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185,
+ 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193,
+ 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200,
+ 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207,
+ 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214,
+ 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220,
+ 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
+ 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
+ 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+ 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244,
+ 245, 245, 246, 246
+};
+
+unsigned char green[256] = {
+ 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 32, 39, 45, 50, 54,
+ 58, 62, 65, 69, 71, 74, 77, 79, 83, 85, 87, 90,
+ 92, 93, 95, 98, 100, 101, 104, 106, 107, 109, 111, 113,
+ 114, 116, 118, 119, 121, 122, 124, 126, 127, 128, 129, 132,
+ 133, 134, 135, 136, 138, 140, 141, 142, 143, 145, 146, 147,
+ 148, 149, 150, 152, 153, 154, 155, 156, 157, 159, 160, 161,
+ 162, 163, 164, 166, 167, 168, 168, 169, 170, 171, 173, 174,
+ 175, 176, 176, 177, 179, 180, 181, 182, 182, 183, 184, 186,
+ 187, 187, 188, 189, 190, 191, 191, 193, 194, 195, 195, 196,
+ 197, 198, 198, 200, 201, 201, 202, 203, 204, 204, 205, 207,
+ 207, 208, 209, 209, 210, 211, 212, 212, 214, 215, 215, 216,
+ 217, 217, 218, 218, 219, 221, 221, 222, 223, 223, 224, 225,
+ 225, 226, 226, 228, 229, 229, 230, 231, 231, 232, 232, 233,
+ 235, 235, 236, 236, 237, 238, 238, 239, 239, 241, 241, 242,
+ 243, 243, 244, 244, 245, 245, 246, 248, 248, 249, 249, 250,
+ 250, 251, 251, 252, 253, 253, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255
+};
+
+unsigned char blue[256] = {
+ 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 41, 50, 57, 63, 69,
+ 74, 78, 82, 87, 90, 94, 97, 100, 105, 108, 111, 113,
+ 116, 118, 121, 124, 127, 128, 131, 134, 136, 139, 140, 143,
+ 145, 148, 149, 150, 153, 155, 156, 159, 161, 162, 164, 167,
+ 168, 170, 171, 173, 174, 177, 179, 180, 182, 183, 185, 186,
+ 187, 189, 190, 192, 193, 195, 196, 198, 199, 201, 202, 204,
+ 205, 207, 208, 210, 211, 213, 213, 214, 216, 217, 219, 220,
+ 222, 223, 223, 224, 226, 227, 229, 230, 230, 232, 233, 235,
+ 236, 236, 238, 239, 241, 242, 242, 244, 245, 247, 247, 248,
+ 250, 251, 251, 253, 254, 254, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255
+};
diff --git a/drivers/usb/usb-debug.c b/drivers/usb/usb-debug.c
index a2958fc6c..35bebc612 100644
--- a/drivers/usb/usb-debug.c
+++ b/drivers/usb/usb-debug.c
@@ -181,23 +181,23 @@ void usb_show_string(struct usb_device *dev, char *id, int index)
kfree(buf);
}
-void usb_dump_urb (purb_t purb)
+void usb_dump_urb (struct urb *urb)
{
- printk ("urb :%p\n", purb);
- printk ("next :%p\n", purb->next);
- printk ("dev :%p\n", purb->dev);
- printk ("pipe :%08X\n", purb->pipe);
- printk ("status :%d\n", purb->status);
- printk ("transfer_flags :%08X\n", purb->transfer_flags);
- printk ("transfer_buffer :%p\n", purb->transfer_buffer);
- printk ("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
- printk ("actual_length :%d\n", purb->actual_length);
- printk ("setup_packet :%p\n", purb->setup_packet);
- printk ("start_frame :%d\n", purb->start_frame);
- printk ("number_of_packets :%d\n", purb->number_of_packets);
- printk ("interval :%d\n", purb->interval);
- printk ("error_count :%d\n", purb->error_count);
- printk ("context :%p\n", purb->context);
- printk ("complete :%p\n", purb->complete);
+ printk ("urb :%p\n", urb);
+ printk ("next :%p\n", urb->next);
+ printk ("dev :%p\n", urb->dev);
+ printk ("pipe :%08X\n", urb->pipe);
+ printk ("status :%d\n", urb->status);
+ printk ("transfer_flags :%08X\n", urb->transfer_flags);
+ printk ("transfer_buffer :%p\n", urb->transfer_buffer);
+ printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
+ printk ("actual_length :%d\n", urb->actual_length);
+ printk ("setup_packet :%p\n", urb->setup_packet);
+ printk ("start_frame :%d\n", urb->start_frame);
+ printk ("number_of_packets :%d\n", urb->number_of_packets);
+ printk ("interval :%d\n", urb->interval);
+ printk ("error_count :%d\n", urb->error_count);
+ printk ("context :%p\n", urb->context);
+ printk ("complete :%p\n", urb->complete);
}
diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c
index 1003eaf52..624b30e1c 100644
--- a/drivers/usb/usb.c
+++ b/drivers/usb/usb.c
@@ -97,6 +97,8 @@ int usb_register(struct usb_driver *new_driver)
usb_scan_devices();
+ usbfs_update_special();
+
return 0;
}
@@ -148,9 +150,13 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
struct usb_interface *interface = &dev->actconfig->interface[i];
if (interface->driver == driver) {
+ if (driver->owner)
+ __MOD_INC_USE_COUNT(driver->owner);
down(&driver->serialize);
driver->disconnect(dev, interface->private_data);
up(&driver->serialize);
+ if (driver->owner)
+ __MOD_DEC_USE_COUNT(driver->owner);
/* if driver->disconnect didn't release the interface */
if (interface->driver)
usb_driver_release_interface(driver, interface);
@@ -192,6 +198,8 @@ void usb_deregister(struct usb_driver *driver)
usb_drivers_purge(driver, bus->root_hub);
}
up (&usb_bus_list_lock);
+
+ usbfs_update_special();
}
/**
@@ -421,7 +429,6 @@ struct usb_bus *usb_alloc_bus(struct usb_operations *op)
bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD(&bus->bus_list);
- INIT_LIST_HEAD(&bus->inodes);
atomic_set(&bus->refcnt, 1);
@@ -468,7 +475,7 @@ void usb_register_bus(struct usb_bus *bus)
list_add(&bus->bus_list, &usb_bus_list);
up (&usb_bus_list_lock);
- usbdevfs_add_bus(bus);
+ usbfs_add_bus(bus);
info("new USB bus registered, assigned bus number %d", bus->busnum);
}
@@ -494,7 +501,7 @@ void usb_deregister_bus(struct usb_bus *bus)
list_del(&bus->bus_list);
up (&usb_bus_list_lock);
- usbdevfs_remove_bus(bus);
+ usbfs_remove_bus(bus);
clear_bit(bus->busnum, busmap.busmap);
@@ -778,6 +785,8 @@ static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
driver = list_entry(tmp, struct usb_driver, driver_list);
tmp = tmp->next;
+ if (driver->owner)
+ __MOD_INC_USE_COUNT(driver->owner);
id = driver->id_table;
/* new style driver? */
if (id) {
@@ -801,6 +810,8 @@ static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
private = driver->probe(dev, ifnum, NULL);
up(&driver->serialize);
}
+ if (driver->owner)
+ __MOD_DEC_USE_COUNT(driver->owner);
/* probe() may have changed the config on us */
interface = dev->actconfig->interface + ifnum;
@@ -923,7 +934,7 @@ static void call_policy (char *verb, struct usb_device *dev)
/* a simple/common case: one config, one interface, one driver
* with current altsetting being a reasonable setting.
- * everything needs a smart agent and usbdevfs; or can rely on
+ * everything needs a smart agent and usbfs; or can rely on
* device-specific binding policies.
*/
envp [i++] = scratch;
@@ -1013,10 +1024,11 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
usb_bus_get(bus);
+ if (!parent)
+ dev->devpath [0] = '/';
dev->bus = bus;
dev->parent = parent;
atomic_set(&dev->refcnt, 1);
- INIT_LIST_HEAD(&dev->inodes);
INIT_LIST_HEAD(&dev->filelist);
init_MUTEX(&dev->serialize);
@@ -1883,9 +1895,13 @@ void usb_disconnect(struct usb_device **pdev)
struct usb_interface *interface = &dev->actconfig->interface[i];
struct usb_driver *driver = interface->driver;
if (driver) {
+ if (driver->owner)
+ __MOD_INC_USE_COUNT(driver->owner);
down(&driver->serialize);
driver->disconnect(dev, interface->private_data);
up(&driver->serialize);
+ if (driver->owner)
+ __MOD_DEC_USE_COUNT(driver->owner);
/* if driver->disconnect didn't release the interface */
if (interface->driver)
usb_driver_release_interface(driver, interface);
@@ -1906,7 +1922,7 @@ void usb_disconnect(struct usb_device **pdev)
/* Free the device number and remove the /proc/bus/usb entry */
if (dev->devnum > 0) {
clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
- usbdevfs_remove_device(dev);
+ usbfs_remove_device(dev);
}
/* Free up the device itself */
@@ -2579,7 +2595,7 @@ int usb_new_device(struct usb_device *dev)
#endif
/* now that the basic setup is over, add a /proc/bus/usb entry */
- usbdevfs_add_device(dev);
+ usbfs_add_device(dev);
/* find drivers willing to handle this device */
usb_find_drivers(dev);
@@ -2592,7 +2608,7 @@ int usb_new_device(struct usb_device *dev)
static int usb_open(struct inode * inode, struct file * file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct usb_driver *c = usb_minors[minor/16];
int err = -ENODEV;
struct file_operations *old_fops, *new_fops = NULL;
@@ -2660,7 +2676,7 @@ static int __init usb_init(void)
{
init_MUTEX(&usb_bus_list_lock);
usb_major_init();
- usbdevfs_init();
+ usbfs_init();
usb_hub_init();
return 0;
@@ -2672,7 +2688,7 @@ static int __init usb_init(void)
static void __exit usb_exit(void)
{
usb_major_cleanup();
- usbdevfs_cleanup();
+ usbfs_cleanup();
usb_hub_cleanup();
}
diff --git a/drivers/usb/usbnet.c b/drivers/usb/usbnet.c
index 3356d7c5c..32a358366 100644
--- a/drivers/usb/usbnet.c
+++ b/drivers/usb/usbnet.c
@@ -1571,13 +1571,13 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
struct urb *urb = 0;
struct skb_data *entry;
struct driver_info *info = dev->driver_info;
- int flags;
+ unsigned long flags;
#ifdef CONFIG_USB_NET1080
struct nc_header *header = 0;
struct nc_trailer *trailer = 0;
#endif /* CONFIG_USB_NET1080 */
- flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
+ flags = in_interrupt () ? GFP_ATOMIC : GFP_NOIO; /* might be used for nfs */
// some devices want funky USB-level framing, for
// win32 driver (usually) and/or hardware quirks
diff --git a/drivers/usb/vicam.c b/drivers/usb/vicam.c
new file mode 100644
index 000000000..dce980c1d
--- /dev/null
+++ b/drivers/usb/vicam.c
@@ -0,0 +1,986 @@
+/* -*- linux-c -*-
+ * USB ViCAM driver
+ *
+ * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx)
+ * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB
+ *
+ * Thanks to Greg Kroah-Hartman for the USB Skeleton driver
+ *
+ * TODO:
+ * - find out the ids for the Vista Imaging ViCAM
+ *
+ * History:
+ *
+ * 2001_07_07 - 0.1 - christopher: first version
+ * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try
+ while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done
+ yep, moving pictures.
+ * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun,
+ get gqcam-0.9, compile it and run. Better than dd ;-).
+ * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional)
+ kill update_params if it does not seem to work for you.
+ * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk
+
+ *
+ * FIXME: It crashes on rmmod with camera plugged.
+ */
+#define DEBUG 1
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/usb.h>
+
+#include <asm/io.h>
+#include <linux/wrapper.h>
+#include <linux/vmalloc.h>
+
+#include <linux/videodev.h>
+
+#include "vicam.h"
+#include "vicamurbs.h"
+
+/* Version Information */
+#define DRIVER_VERSION "v0"
+#define DRIVER_AUTHOR "Christopher L Cheney <ccheney@cheney.cx>, Pavel Machek <pavel@suse.cz>"
+#define DRIVER_DESC "USB ViCAM Driver"
+
+/* Define these values to match your device */
+#define USB_VICAM_VENDOR_ID 0x04C1
+#define USB_VICAM_PRODUCT_ID 0x009D
+
+/* table of devices that work with this driver */
+static struct usb_device_id vicam_table [] = {
+ { USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, vicam_table);
+
+static int video_nr = -1; /* next avail video device */
+static struct usb_driver vicam_driver;
+
+static char *buf, *buf2;
+static int change_pending = 0;
+
+static int vicam_parameters(struct usb_vicam *vicam);
+
+/******************************************************************************
+ *
+ * Memory management functions
+ *
+ * Taken from bttv-drivers.c 2.4.7-pre3
+ *
+ ******************************************************************************/
+
+/* [DaveM] I've recoded most of this so that:
+ * 1) It's easier to tell what is happening
+ * 2) It's more portable, especially for translating things
+ * out of vmalloc mapped areas in the kernel.
+ * 3) Less unnecessary translations happen.
+ *
+ * The code used to assume that the kernel vmalloc mappings
+ * existed in the page tables of every process, this is simply
+ * not guarenteed. We now use pgd_offset_k which is the
+ * defined way to get at the kernel page tables.
+ */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ if (!pgd_none(*pgd)) {
+ pmd = pmd_offset(pgd, adr);
+ if (!pmd_none(*pmd)) {
+ ptep = pte_offset(pmd, adr);
+ pte = *ptep;
+ if(pte_present(pte)) {
+ ret = (unsigned long) page_address(pte_page(pte));
+ ret |= (adr & (PAGE_SIZE - 1));
+
+ }
+ }
+ }
+ return ret;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr)
+{
+ unsigned long kva, ret;
+
+ kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
+ ret = virt_to_bus((void *)kva);
+ return ret;
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR(adr);
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+ ret = virt_to_bus((void *)kva);
+ return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR(adr);
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+ ret = __pa(kva);
+ return ret;
+}
+
+static void * rvmalloc(signed long size)
+{
+ void * mem;
+ unsigned long adr, page;
+
+ mem=vmalloc_32(size);
+ if (mem)
+ {
+ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+ adr=(unsigned long) mem;
+ while (size > 0)
+ {
+ page = kvirt_to_pa(adr);
+ mem_map_reserve(virt_to_page(__va(page)));
+ adr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ }
+ return mem;
+}
+
+static void rvfree(void * mem, signed long size)
+{
+ unsigned long adr, page;
+
+ if (mem)
+ {
+ adr=(unsigned long) mem;
+ while (size > 0)
+ {
+ page = kvirt_to_pa(adr);
+ mem_map_unreserve(virt_to_page(__va(page)));
+ adr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ vfree(mem);
+ }
+}
+
+/******************************************************************************
+ *
+ * Foo Bar
+ *
+ ******************************************************************************/
+
+/**
+ * usb_vicam_debug_data
+ */
+static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
+{
+ int i;
+
+ if (!debug)
+ return;
+
+ printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
+ function, size);
+ for (i = 0; i < size; ++i) {
+ printk ("%.2x ", data[i]);
+ }
+ printk ("\n");
+}
+
+/*****************************************************************************
+ *
+ * Send command to vicam
+ *
+ *****************************************************************************/
+
+static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
+ unsigned short value, unsigned char *cp, int size)
+{
+ int ret;
+ unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
+
+ /* Needs to return data I think, works for sending though */
+ memcpy(transfer_buffer, cp, size);
+
+ ret = usb_control_msg ( vicam->udev, set ? usb_sndctrlpipe(vicam->udev, 0) : usb_rcvctrlpipe(vicam->udev, 0), req, (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, 0, transfer_buffer, size, HZ);
+
+ kfree(transfer_buffer);
+ if (ret)
+ printk("vicam: error: %d\n", ret);
+ mdelay(100);
+ return ret;
+}
+
+
+/*****************************************************************************
+ *
+ * Video4Linux Helpers
+ *
+ *****************************************************************************/
+
+static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
+{
+ dbg("vicam_get_capability");
+
+ strcpy(b->name, vicam->camera_name);
+ b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
+ b->channels = 1;
+ b->audios = 0;
+
+ b->maxwidth = vicam->width[vicam->sizes-1];
+ b->maxheight = vicam->height[vicam->sizes-1];
+ b->minwidth = vicam->width[0];
+ b->minheight = vicam->height[0];
+
+ return 0;
+}
+
+static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
+{
+ dbg("vicam_get_channel");
+
+ if (v->channel != 0)
+ return -EINVAL;
+
+ v->flags = 0;
+ v->tuners = 0;
+ v->type = VIDEO_TYPE_CAMERA;
+ strcpy(v->name, "Camera");
+
+ return 0;
+}
+
+static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
+{
+ dbg("vicam_set_channel");
+
+ if (v->channel != 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
+{
+ int i;
+
+ dbg("vicam_get_mmapbuffer");
+
+ memset(vm, 0, sizeof(vm));
+ vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
+ vm->frames = VICAM_NUMFRAMES;
+
+ for (i=0; i<VICAM_NUMFRAMES; i++)
+ vm->offsets[i] = vicam->maxframesize * i;
+
+ return 0;
+}
+
+static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
+{
+ dbg("vicam_get_picture");
+
+ /* This is probably where that weird 0x56 call goes */
+ p->brightness = vicam->win.brightness;
+ p->hue = vicam->win.hue;
+ p->colour = vicam->win.colour;
+ p->contrast = vicam->win.contrast;
+ p->whiteness = vicam->win.whiteness;
+ p->depth = vicam->win.depth;
+ p->palette = vicam->win.palette;
+
+ return 0;
+}
+
+static void synchronize(struct usb_vicam *vicam)
+{
+ change_pending = 1;
+ interruptible_sleep_on(&vicam->wait);
+ vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
+ mdelay(10);
+ vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+ mdelay(10);
+}
+
+static void params_changed(struct usb_vicam *vicam)
+{
+#if 1
+ synchronize(vicam);
+ mdelay(10);
+ vicam_parameters(vicam);
+ printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));
+#endif
+}
+
+static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
+{
+ int changed = 0;
+ info("vicam_set_picture (%d)", p->brightness);
+
+
+#define SET(x) \
+ if (vicam->win.x != p->x) \
+ vicam->win.x = p->x, changed = 1;
+ SET(brightness);
+ SET(hue);
+ SET(colour);
+ SET(contrast);
+ SET(whiteness);
+ SET(depth);
+ SET(palette);
+ if (changed)
+ params_changed(vicam);
+
+ return 0;
+ /* Investigate what should be done maybe 0x56 type call */
+ if (p->depth != 8) return 1;
+ if (p->palette != VIDEO_PALETTE_GREY) return 1;
+
+ return 0;
+}
+
+/* FIXME - vicam_sync_frame - important */
+static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
+{
+ dbg("vicam_sync_frame");
+
+ if(frame <0 || frame >= VICAM_NUMFRAMES)
+ return -EINVAL;
+
+ /* Probably need to handle various cases */
+/* ret=vicam_newframe(vicam, frame);
+ vicam->frame[frame].grabstate=FRAME_UNUSED;
+*/
+ return 0;
+}
+
+static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
+{
+ dbg("vicam_get_window");
+
+ vw->x = 0;
+ vw->y = 0;
+ vw->chromakey = 0;
+ vw->flags = 0;
+ vw->clipcount = 0;
+ vw->width = vicam->win.width;
+ vw->height = vicam->win.height;
+
+ return 0;
+}
+
+static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
+{
+ info("vicam_set_window");
+
+ if (vw->flags)
+ return -EINVAL;
+ if (vw->clipcount)
+ return -EINVAL;
+
+ if (vicam->win.width == vw->width && vicam->win.height == vw->height)
+ return 0;
+
+ /* Pick largest mode that is smaller than specified res */
+ /* If specified res is too small reject */
+
+ /* Add urb send to device... */
+
+ vicam->win.width = vw->width;
+ vicam->win.height = vw->height;
+ params_changed(vicam);
+
+ return 0;
+}
+
+/* FIXME - vicam_mmap_capture - important */
+static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
+{
+ dbg("vicam_mmap_capture");
+
+ /* usbvideo.c looks good for using here */
+
+ /*
+ if (vm->frame >= VICAM_NUMFRAMES)
+ return -EINVAL;
+ if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
+ return -EBUSY;
+ vicam->frame[vm->frame].grabstate=FRAME_READY;
+ */
+
+ /* No need to vicam_set_window here according to Alan */
+
+ /*
+ if (!vicam->streaming)
+ vicam_start_stream(vicam);
+ */
+
+ /* set frame as ready */
+
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ * Video4Linux
+ *
+ *****************************************************************************/
+
+static int vicam_v4l_open(struct video_device *vdev, int flags)
+{
+ struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+ int err = 0;
+
+ dbg("vicam_v4l_open");
+
+ MOD_INC_USE_COUNT;
+ down(&vicam->sem);
+
+ if (vicam->open_count) /* Maybe not needed? */
+ err = -EBUSY;
+ else {
+ vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
+ if (!vicam->fbuf)
+ err=-ENOMEM;
+ else {
+ vicam->open_count = 1;
+ }
+#ifdef BLINKING
+ vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+ info ("led on");
+ vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+#endif
+ }
+
+ up(&vicam->sem);
+ if (err)
+ MOD_DEC_USE_COUNT;
+ return err;
+}
+
+static void vicam_v4l_close(struct video_device *vdev)
+{
+ struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+
+ dbg("vicam_v4l_close");
+
+ down(&vicam->sem);
+
+#ifdef BLINKING
+ info ("led off");
+ vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+// vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
+#endif
+
+ rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
+ vicam->fbuf = 0;
+ vicam->open_count=0;
+
+ up(&vicam->sem);
+ /* Why does se401.c have a usbdevice check here? */
+ /* If device is unplugged while open, I guess we only may unregister now */
+ MOD_DEC_USE_COUNT;
+}
+
+static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock)
+{
+ //struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+
+ dbg("vicam_v4l_read(%ld)", buflen);
+
+ if (!vdev || !buf)
+ return -EFAULT;
+
+ if (copy_to_user(user_buf, buf2, buflen))
+ return -EFAULT;
+ return buflen;
+}
+
+static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
+{
+ info("vicam_v4l_write");
+ return -EINVAL;
+}
+
+static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+{
+ struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+ int ret = -EL3RST;
+
+ if (!vicam->udev)
+ return -EIO;
+
+ down(&vicam->sem);
+
+ switch (cmd) {
+ case VIDIOCGCAP:
+ {
+ struct video_capability b;
+ ret = vicam_get_capability(vicam,&b);
+ dbg("name %s",b.name);
+ if (copy_to_user(arg, &b, sizeof(b)))
+ ret = -EFAULT;
+ }
+ case VIDIOCGFBUF:
+ {
+ struct video_buffer vb;
+ info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
+ /* frame buffer not supported, not used */
+ memset(&vb, 0, sizeof(vb));
+ vb.base = NULL;
+
+ /* FIXME - VIDIOCGFBUF - why the void */
+ if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
+ ret = -EFAULT;
+ ret = 0;
+ }
+ case VIDIOCGWIN:
+ {
+ struct video_window vw;
+ ret = vicam_get_window(vicam, &vw);
+ if (copy_to_user(arg, &vw, sizeof(vw)))
+ ret = -EFAULT;
+ }
+ case VIDIOCSWIN:
+ {
+ struct video_window vw;
+ if (copy_from_user(&vw, arg, sizeof(vw)))
+ ret = -EFAULT;
+ else
+ ret = vicam_set_window(vicam, &vw);
+ return ret;
+ }
+ case VIDIOCGCHAN:
+ {
+ struct video_channel v;
+
+ if (copy_from_user(&v, arg, sizeof(v)))
+ ret = -EFAULT;
+ else {
+ ret = vicam_get_channel(vicam,&v);
+ if (copy_to_user(arg, &v, sizeof(v)))
+ ret = -EFAULT;
+ }
+ }
+ case VIDIOCSCHAN:
+ {
+ struct video_channel v;
+ if (copy_from_user(&v, arg, sizeof(v)))
+ ret = -EFAULT;
+ else
+ ret = vicam_set_channel(vicam,&v);
+ }
+ case VIDIOCGPICT:
+ {
+ struct video_picture p;
+ ret = vicam_get_picture(vicam, &p);
+ if (copy_to_user(arg, &p, sizeof(p)))
+ ret = -EFAULT;
+ }
+ case VIDIOCSPICT:
+ {
+ struct video_picture p;
+ if (copy_from_user(&p, arg, sizeof(p)))
+ ret = -EFAULT;
+ else
+ ret = vicam_set_picture(vicam, &p);
+ }
+ case VIDIOCGMBUF:
+ {
+ struct video_mbuf vm;
+ ret = vicam_get_mmapbuffer(vicam,&vm);
+ /* FIXME - VIDIOCGMBUF - why the void */
+ if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+ ret = -EFAULT;
+ }
+ case VIDIOCMCAPTURE:
+ {
+ struct video_mmap vm;
+ ret = vicam_mmap_capture(vicam, &vm);
+ /* FIXME: This is probably not right */
+ }
+ case VIDIOCSYNC:
+ {
+ int frame;
+ /* FIXME - VIDIOCSYNC - why the void */
+ if (copy_from_user((void *)&frame, arg, sizeof(int)))
+ ret = -EFAULT;
+ else
+ ret = vicam_sync_frame(vicam,frame);
+ }
+
+ case VIDIOCKEY:
+ ret = 0;
+
+ case VIDIOCCAPTURE:
+ case VIDIOCSFBUF:
+ case VIDIOCGTUNER:
+ case VIDIOCSTUNER:
+ case VIDIOCGFREQ:
+ case VIDIOCSFREQ:
+ case VIDIOCGAUDIO:
+ case VIDIOCSAUDIO:
+ case VIDIOCGUNIT:
+ ret = -EINVAL;
+
+ default:
+ {
+ info("vicam_v4l_ioctl - %ui",cmd);
+ ret = -ENOIOCTLCMD;
+ }
+ } /* end switch */
+
+ up(&vicam->sem);
+ return ret;
+}
+
+static int vicam_v4l_mmap(struct vm_area_struct *vma, struct video_device *dev, const char *adr, unsigned long size)
+{
+ struct usb_vicam *vicam = (struct usb_vicam *)dev;
+ unsigned long start = (unsigned long)adr;
+ unsigned long page, pos;
+
+ down(&vicam->sem);
+
+ if (vicam->udev == NULL) {
+ up(&vicam->sem);
+ return -EIO;
+ }
+#if 0
+ if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
+ up(&vicam->sem);
+ return -EINVAL;
+ }
+#endif
+ pos = (unsigned long)vicam->fbuf;
+ while (size > 0) {
+ page = kvirt_to_pa(pos);
+ if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+ up(&vicam->sem);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+ up(&vicam->sem);
+
+ return 0;
+}
+
+/* FIXME - vicam_v4l_init */
+static int vicam_v4l_init(struct video_device *dev)
+{
+ /* stick proc fs stuff in here if wanted */
+ dbg("vicam_v4l_init");
+ return 0;
+}
+
+/* FIXME - vicam_template - important */
+static struct video_device vicam_template = {
+ name: "vicam USB camera",
+ type: VID_TYPE_CAPTURE,
+ hardware: VID_HARDWARE_SE401, /* need to ask for own id */
+ open: vicam_v4l_open,
+ close: vicam_v4l_close,
+ read: vicam_v4l_read,
+ write: vicam_v4l_write,
+ ioctl: vicam_v4l_ioctl,
+ mmap: vicam_v4l_mmap,
+ initialize: vicam_v4l_init,
+};
+
+/******************************************************************************
+ *
+ * Some Routines
+ *
+ ******************************************************************************/
+
+/*
+Flash the led
+vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+info ("led on");
+vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+info ("led off");
+vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
+*/
+
+static void vicam_bulk(struct urb *urb)
+{
+ struct usb_vicam *vicam = urb->context;
+
+ /* if (!vicam || !vicam->dev || !vicam->used)
+ return;
+ */
+
+ if (urb->status)
+ printk("vicam%d: nonzero read/write bulk status received: %d",
+ 0, urb->status);
+
+ urb->actual_length = 0;
+ urb->dev = vicam->udev;
+
+ memcpy(buf2, buf+64, 0x1e480);
+ if (vicam->fbuf)
+ memcpy(vicam->fbuf, buf+64, 0x1e480);
+
+ if (!change_pending) {
+ if (usb_submit_urb(urb))
+ dbg("failed resubmitting read urb");
+ } else {
+ change_pending = 0;
+ wake_up_interruptible(&vicam->wait);
+ }
+}
+
+static int vicam_parameters(struct usb_vicam *vicam)
+{
+ unsigned char req[0x10];
+ unsigned int shutter;
+ shutter = 10;
+
+ switch (vicam->win.width) {
+ case 512:
+ default:
+ memcpy(req, s512x242bw, 0x10);
+ break;
+ case 256:
+ memcpy(req, s256x242bw, 0x10);
+ break;
+ case 128:
+ memcpy(req, s128x122bw, 0x10);
+ break;
+ }
+
+
+ mdelay(10);
+ vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+ info ("led on");
+ vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+
+ mdelay(10);
+
+ shutter = vicam->win.contrast / 256;
+ if (shutter == 0)
+ shutter = 1;
+ printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter );
+ req[0] = vicam->win.brightness /256;
+ shutter = 15600/shutter - 1;
+ req[6] = shutter & 0xff;
+ req[7] = (shutter >> 8) & 0xff;
+ vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
+ mdelay(10);
+ vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
+ mdelay(10);
+
+ return 0;
+}
+
+static int vicam_init(struct usb_vicam *vicam)
+{
+ int width[] = {128, 256, 512};
+ int height[] = {122, 242, 242};
+
+ dbg("vicam_init");
+ buf = kmalloc(0x1e480, GFP_KERNEL);
+ buf2 = kmalloc(0x1e480, GFP_KERNEL);
+ if ((!buf) || (!buf2)) {
+ printk("Not enough memory for vicam!\n");
+ goto error;
+ }
+
+ /* do we do aspect correction in kernel or not? */
+ vicam->sizes = 3;
+ vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
+ vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
+ memcpy(vicam->width, &width, sizeof(width));
+ memcpy(vicam->height, &height, sizeof(height));
+ vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
+
+ /* Download firmware to camera */
+ vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
+ vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
+ vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+ vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
+ vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
+ vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+
+ vicam_parameters(vicam);
+
+ FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
+ buf, 0x1e480, vicam_bulk, vicam);
+ printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));
+
+ return 0;
+error:
+ if (buf)
+ kfree(buf);
+ if (buf2)
+ kfree(buf2);
+ return 1;
+}
+
+static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,
+ const struct usb_device_id *id)
+{
+ struct usb_vicam *vicam;
+ char *camera_name=NULL;
+
+ dbg("vicam_probe");
+
+ /* See if the device offered us matches what we can accept */
+ if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
+ (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
+ return NULL;
+ }
+
+ camera_name="3Com HomeConnect USB";
+ info("ViCAM camera found: %s", camera_name);
+
+ vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
+ if (vicam == NULL) {
+ err ("couldn't kmalloc vicam struct");
+ return NULL;
+ }
+ memset(vicam, 0, sizeof(*vicam));
+
+ vicam->udev = udev;
+ vicam->camera_name = camera_name;
+ vicam->win.brightness = 128;
+ vicam->win.contrast = 10;
+
+ /* FIXME */
+ if (vicam_init(vicam))
+ return NULL;
+ memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
+ memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
+
+ if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+ err("video_register_device");
+ return NULL;
+ }
+
+ info("registered new video device: video%d", vicam->vdev.minor);
+
+ init_MUTEX (&vicam->sem);
+ init_waitqueue_head(&vicam->wait);
+
+ return vicam;
+}
+
+
+/* FIXME - vicam_disconnect - important */
+static void vicam_disconnect(struct usb_device *udev, void *ptr)
+{
+ struct usb_vicam *vicam;
+
+ vicam = (struct usb_vicam *) ptr;
+
+ if (!vicam->open_count)
+ video_unregister_device(&vicam->vdev);
+ vicam->udev = NULL;
+/*
+ vicam->frame[0].grabstate = FRAME_ERROR;
+ vicam->frame[1].grabstate = FRAME_ERROR;
+*/
+
+ /* Free buffers and shit */
+
+ info("%s disconnected", vicam->camera_name);
+ synchronize(vicam);
+
+ if (!vicam->open_count) {
+ /* Other random junk */
+ kfree(vicam);
+ vicam = NULL;
+ }
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vicam_driver = {
+ name: "vicam",
+ probe: vicam_probe,
+ disconnect: vicam_disconnect,
+ id_table: vicam_table,
+};
+
+/******************************************************************************
+ *
+ * Module Routines
+ *
+ ******************************************************************************/
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* Module paramaters */
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+static int __init usb_vicam_init(void)
+{
+ int result;
+
+ printk("VICAM: initializing\n");
+ /* register this driver with the USB subsystem */
+ result = usb_register(&vicam_driver);
+ if (result < 0) {
+ err("usb_register failed for the "__FILE__" driver. Error number %d",
+ result);
+ return -1;
+ }
+
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+ return 0;
+}
+
+static void __exit usb_vicam_exit(void)
+{
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&vicam_driver);
+}
+
+module_init(usb_vicam_init);
+module_exit(usb_vicam_exit);
diff --git a/drivers/usb/vicam.h b/drivers/usb/vicam.h
new file mode 100644
index 000000000..46b4aaddf
--- /dev/null
+++ b/drivers/usb/vicam.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
+ * Christopher L Cheney (C) 2001
+ *
+ */
+
+#ifndef __LINUX_VICAM_H
+#define __LINUX_VICAM_H
+
+
+#ifdef CONFIG_USB_DEBUG
+ static int debug = 1;
+#else
+ static int debug;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
+
+#define VICAM_NUMFRAMES 30
+#define VICAM_NUMSBUF 1
+
+/* USB REQUEST NUMBERS */
+#define VICAM_REQ_VENDOR 0xff
+#define VICAM_REQ_CAMERA_POWER 0x50
+#define VICAM_REQ_CAPTURE 0x51
+#define VICAM_REQ_LED_CONTROL 0x55
+#define VICAM_REQ_GET_SOMETHIN 0x56
+
+/* not required but lets you know camera is on */
+/* camera must be on to turn on led */
+/* 0x01 always on 0x03 on when picture taken (flashes) */
+
+struct picture_parm
+{
+ int width;
+ int height;
+ int brightness;
+ int hue;
+ int colour;
+ int contrast;
+ int whiteness;
+ int depth;
+ int palette;
+};
+
+struct vicam_scratch {
+ unsigned char *data;
+ volatile int state;
+ int offset;
+ int length;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct usb_vicam
+{
+ struct video_device vdev;
+ struct usb_device *udev;
+
+ int open_count; /* number of times this port has been opened */
+ struct semaphore sem; /* locks this structure */
+ wait_queue_head_t wait; /* Processes waiting */
+
+ int streaming;
+
+ /* v4l stuff */
+ char *camera_name;
+ char *fbuf;
+ urb_t *urb[VICAM_NUMSBUF];
+ int sizes;
+ int *width;
+ int *height;
+ int maxframesize;
+ struct picture_parm win;
+ struct proc_dir_entry *proc_entry; /* /proc/se401/videoX */
+ struct urb readurb;
+};
+
+#endif
diff --git a/drivers/usb/vicamurbs.h b/drivers/usb/vicamurbs.h
new file mode 100644
index 000000000..e19efbc0d
--- /dev/null
+++ b/drivers/usb/vicamurbs.h
@@ -0,0 +1,330 @@
+/*
+ *
+ * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
+ * Christopher L Cheney (C) 2001
+ *
+ */
+
+
+#ifndef __LINUX_VICAMURBS_H
+#define __LINUX_VICAMURBS_H
+
+/* -------------------------------------------------------------------------- */
+
+/* FIXME - Figure out transfers so that this doesn't need to be here
+ *
+ * Notice: in pieces below, "0" means other code will fill it while "0x00" means this is zero */
+
+/* Request 0x51 Image Setup */
+
+/* 128x98 ? 0x3180 size */
+static unsigned char s128x98bw[] = {
+ 0, 0x34, 0xC4, 0x00, 0x00, 0x00, 0, 0,
+ 0x18, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 128x122 3D80 size */
+static unsigned char s128x122bw[] = {
+ 0, 0x34, 0xF4, 0x00, 0x00, 0x00, 0, 0,
+ 0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 256x242 ? 0xF280 size */
+static unsigned char s256x242bw[] = {
+ 0, 0x03, 0xC8, 0x03, 0x00, 0x00, 0, 0,
+ 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 512x242 0x1E480 size */
+static unsigned char s512x242bw[] = {
+ 0, 0x05, 0x90, 0x07, 0x00, 0x00, 0, 0,
+ 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* In s512x242:
+ byte 0: gain -- higher number means brighter image
+ byte 6, 7: shutter speed, little-endian; set this to 15600 * (shutter speed) - 1. (Where shutter speed is something like 1/1000).
+*/
+
+/* -------------------------------------------------------------------------- */
+
+static unsigned char fsetup[] = {
+ 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64,
+
+ 0x00, 0x00
+};
+
+static unsigned char firmware1[] = {
+ 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64,
+
+ 0xE7, 0x67, 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09,
+ 0xDE, 0x00, 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03,
+ 0xC0, 0x17, 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07,
+ 0x00, 0x00, 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
+};
+
+static unsigned char findex1[] = {
+ 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64,
+
+ 0x18, 0x00, 0x00, 0x00
+};
+
+static unsigned char firmware2[] = {
+ 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64,
+
+ 0xE7, 0x07, 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07,
+ 0x00, 0x00, 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01,
+ 0xAA, 0x00, 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00,
+ 0xE7, 0x07, 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07,
+ 0x7C, 0x00, 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00,
+ 0x18, 0x00, 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0,
+ 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07,
+ 0xFF, 0xFF, 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00,
+ 0x24, 0xC0, 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0,
+ 0xE7, 0x07, 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87,
+ 0x01, 0x00, 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09,
+ 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0,
+ 0x09, 0xC1, 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01,
+ 0xE7, 0x09, 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07,
+ 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0,
+ 0xC0, 0xDF, 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00,
+ 0x17, 0x02, 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77,
+ 0x01, 0x00, 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57,
+ 0xFF, 0xFF, 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57,
+ 0x00, 0x00, 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF,
+ 0xC6, 0x00, 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05,
+ 0xC1, 0x05, 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF,
+ 0x27, 0xDA, 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00,
+ 0x0B, 0x06, 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01,
+ 0x9F, 0xAF, 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09,
+ 0xFC, 0x05, 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06,
+ 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0,
+ 0xE7, 0x09, 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09,
+ 0x02, 0x06, 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06,
+ 0xFC, 0x05, 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06,
+ 0x27, 0xDA, 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00,
+ 0xFA, 0x05, 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF,
+ 0x9F, 0xAF, 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07,
+ 0x40, 0x00, 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05,
+ 0x9F, 0xAF, 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17,
+ 0x02, 0x00, 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06,
+ 0x9F, 0xA0, 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00,
+ 0x09, 0x06, 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57,
+ 0x01, 0x00, 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03,
+ 0xE7, 0x07, 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF,
+ 0x47, 0xAF, 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07,
+ 0x2E, 0x00, 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00,
+ 0x09, 0x06, 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00,
+ 0xC0, 0x57, 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02,
+ 0xC0, 0x57, 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57,
+ 0x55, 0x00, 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00,
+ 0x9F, 0xC0, 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02,
+ 0xC1, 0x0B, 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90,
+ 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B,
+ 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF,
+ 0x2F, 0x0E, 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07,
+ 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF,
+ 0x28, 0x05, 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E,
+ 0x02, 0x00, 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00,
+ 0x09, 0x06, 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67,
+ 0x7F, 0xFF, 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD,
+ 0x22, 0xC0, 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0,
+ 0xE7, 0x87, 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF,
+ 0xB8, 0x05, 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0,
+ 0x9F, 0xAF, 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00,
+ 0x24, 0xC0, 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0,
+ 0xC8, 0x07, 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00,
+ 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+ 0x9F, 0xAF, 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00,
+ 0x9F, 0xAF, 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE,
+ 0x24, 0xC0, 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87,
+ 0x00, 0x01, 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02,
+ 0x0F, 0xC1, 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0,
+ 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+ 0x08, 0x00, 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1,
+ 0xEF, 0x07, 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF,
+ 0xEF, 0x07, 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF,
+ 0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07,
+ 0x00, 0x00, 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF,
+ 0x09, 0x06, 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06,
+ 0xE7, 0x67, 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67,
+ 0x17, 0xD8, 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00,
+ 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0,
+ 0x97, 0xCF, 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF,
+ 0xDA, 0x02, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
+ 0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
+ 0x0E, 0x06, 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02,
+ 0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
+ 0x00, 0x80, 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C,
+ 0x02, 0x00, 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00,
+ 0x06, 0x06, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
+ 0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
+ 0xE2, 0x05, 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02,
+ 0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
+ 0x00, 0x80, 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF,
+ 0x66, 0x04, 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF,
+ 0x97, 0xCF, 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B,
+ 0x0C, 0x06, 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05,
+ 0xC0, 0x07, 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+ 0x68, 0x00, 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF,
+ 0x44, 0x05, 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00,
+ 0xE0, 0x07, 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06,
+ 0xE8, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02,
+ 0xE0, 0x07, 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF,
+ 0x97, 0xCF, 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05,
+ 0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07,
+ 0x0E, 0x06, 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06,
+ 0xFE, 0x05, 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01,
+ 0xE7, 0x07, 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07,
+ 0x07, 0x00, 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07,
+ 0x02, 0x00, 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01,
+ 0xEF, 0x77, 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0,
+ 0x14, 0x04, 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06,
+ 0x37, 0xC0, 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06,
+ 0x0F, 0xC1, 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06,
+ 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
+ 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00,
+ 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+ 0xC8, 0x07, 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05,
+ 0xC0, 0x07, 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+ 0xC1, 0x77, 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA,
+ 0x75, 0xC1, 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1,
+ 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00,
+ 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00,
+ 0x06, 0x06, 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00,
+ 0xC1, 0x07, 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+ 0xEF, 0x07, 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF,
+ 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57,
+ 0x01, 0x00, 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07,
+ 0x01, 0x00, 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF,
+ 0x28, 0x05, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
+ 0x30, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
+ 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
+ 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67,
+ 0x03, 0x00, 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0,
+ 0x08, 0xDA, 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00,
+ 0xC1, 0x07, 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00,
+ 0x06, 0x06, 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00,
+ 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00,
+ 0xC1, 0x0B, 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+ 0xC0, 0x07, 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05,
+ 0xE7, 0x09, 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8,
+ 0xFA, 0x05, 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05,
+ 0xE7, 0x07, 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07,
+ 0x40, 0x00, 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05,
+ 0x9F, 0xAF, 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B,
+ 0xE2, 0x05, 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17,
+ 0x23, 0x00, 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07,
+ 0x04, 0x00, 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF,
+ 0x28, 0x05, 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09,
+ 0xE6, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+ 0x07, 0x00, 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1,
+ 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00,
+ 0xC1, 0x09, 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+ 0xC0, 0x07, 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05,
+ 0xC1, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+ 0x0D, 0x00, 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF,
+ 0x28, 0x05, 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07,
+ 0x32, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+ 0x0F, 0x00, 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF,
+ 0x28, 0x05, 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9,
+ 0x24, 0xC0, 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00,
+ 0xC0, 0x67, 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0,
+ 0xE7, 0x87, 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67,
+ 0xFF, 0xF9, 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA,
+ 0x72, 0xC1, 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0,
+ 0x97, 0xCF, 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87,
+ 0xFF, 0x00, 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF,
+ 0x24, 0xC0, 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0,
+ 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF,
+ 0x9F, 0xAF, 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0,
+ 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+ 0x40, 0x00, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+ 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05,
+ 0xE7, 0x67, 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67,
+ 0xFF, 0xFE, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+ 0x24, 0xC0, 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87,
+ 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07,
+ 0x40, 0x00, 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67,
+ 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+ 0x24, 0xC0, 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0,
+ 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA,
+ 0xE8, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+ 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
+ 0x00, 0xDA, 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1,
+ 0xE7, 0x87, 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF,
+ 0xE7, 0x07, 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77,
+ 0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
+ 0xE7, 0x07, 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77,
+ 0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
+ 0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80,
+ 0x96, 0x09, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char findex2[] = {
+ 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64,
+
+ 0x0E, 0x00, 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00,
+ 0x26, 0x00, 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00,
+ 0x92, 0x00, 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00,
+ 0xB8, 0x00, 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00,
+ 0xCE, 0x00, 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00,
+ 0xE0, 0x00, 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00,
+ 0xEC, 0x00, 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01,
+ 0x0A, 0x01, 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01,
+ 0x22, 0x01, 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01,
+ 0x36, 0x01, 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01,
+ 0x72, 0x01, 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01,
+ 0x88, 0x01, 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01,
+ 0xA0, 0x01, 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01,
+ 0xB4, 0x01, 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01,
+ 0xF6, 0x01, 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02,
+ 0x3C, 0x02, 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02,
+ 0x56, 0x02, 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02,
+ 0x84, 0x02, 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02,
+ 0x8E, 0x02, 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02,
+ 0xAE, 0x02, 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02,
+ 0xC0, 0x02, 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02,
+ 0xD4, 0x02, 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02,
+ 0xF8, 0x02, 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03,
+ 0x24, 0x03, 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03,
+ 0x3C, 0x03, 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03,
+ 0x58, 0x03, 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03,
+ 0x7A, 0x03, 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03,
+ 0xB2, 0x03, 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03,
+ 0xD4, 0x03, 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03,
+ 0xFC, 0x03, 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04,
+ 0x32, 0x04, 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04,
+ 0x42, 0x04, 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04,
+ 0x54, 0x04, 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04,
+ 0x62, 0x04, 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04,
+ 0x80, 0x04, 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04,
+ 0x9A, 0x04, 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04,
+ 0xB4, 0x04, 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04,
+ 0x2A, 0x05, 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
+};
+
+#endif
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index ee3e4659c..076d49713 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2014,7 +2014,7 @@ found:
disp = &info->disp;
strcpy(info->fb_info.modename, atyfb_name);
- info->fb_info.node = -1;
+ info->fb_info.node = NODEV;
info->fb_info.fbops = &atyfb_ops;
info->fb_info.disp = disp;
strcpy(info->fb_info.fontname, fontname);
@@ -2927,3 +2927,4 @@ void cleanup_module(void)
}
#endif
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/dn_cfb4.c b/drivers/video/dn_cfb4.c
index 6b9d4fe78..3d1f98b41 100644
--- a/drivers/video/dn_cfb4.c
+++ b/drivers/video/dn_cfb4.c
@@ -7,7 +7,6 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
diff --git a/drivers/video/dn_cfb8.c b/drivers/video/dn_cfb8.c
index 4377561b4..6b51230a8 100644
--- a/drivers/video/dn_cfb8.c
+++ b/drivers/video/dn_cfb8.c
@@ -7,7 +7,6 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 1445e2aa3..27c380707 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -7,7 +7,6 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c
index 5e2957c7f..b3b4a09d4 100644
--- a/drivers/video/fbcon.c
+++ b/drivers/video/fbcon.c
@@ -271,10 +271,10 @@ int PROC_CONSOLE(const struct fb_info *info)
/* XXX Should report error here? */
return fgc;
- if (MINOR(current->tty->device) < 1)
+ if (minor(current->tty->device) < 1)
return fgc;
- return MINOR(current->tty->device) - 1;
+ return minor(current->tty->device) - 1;
}
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 0c00d0cde..0caef8f0d 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/tty.h>
#include <linux/console.h>
@@ -576,12 +577,13 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
return -EINVAL;
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
+ /* This is an IO map - tell maydump to skip this VMA */
+ vma->vm_flags |= VM_IO;
#if defined(__sparc_v9__)
vma->vm_flags |= (VM_SHM | VM_LOCKED);
if (io_remap_page_range(vma, vma->vm_start, off,
vma->vm_end - vma->vm_start, vma->vm_page_prot, 0))
return -EAGAIN;
- vma->vm_flags |= VM_IO;
#else
#if defined(__mc68000__)
#if defined(CONFIG_SUN3)
@@ -607,8 +609,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
#elif defined(__arm__)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- /* This is an IO map - tell maydump to skip this VMA */
- vma->vm_flags |= VM_IO;
#elif defined(__sh__)
pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
#else
@@ -625,7 +625,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
#if 1 /* to go away in 2.5.0 */
int GET_FB_IDX(kdev_t rdev)
{
- int fbidx = MINOR(rdev);
+ int fbidx = minor(rdev);
if (fbidx >= 32) {
int newfbidx = fbidx >> 5;
static int warned;
@@ -719,7 +719,7 @@ register_framebuffer(struct fb_info *fb_info)
for (i = 0 ; i < FB_MAX; i++)
if (!registered_fb[i])
break;
- fb_info->node = MKDEV(FB_MAJOR, i);
+ fb_info->node = mk_kdev(FB_MAJOR, i);
registered_fb[i] = fb_info;
if (!fb_ever_opened[i]) {
struct module *owner = fb_info->fbops->owner;
@@ -931,3 +931,5 @@ EXPORT_SYMBOL(num_registered_fb);
#if 1 /* to go away in 2.5.0 */
EXPORT_SYMBOL(GET_FB_IDX);
#endif
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index a8870f74f..458ff5d5a 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -9,7 +9,6 @@
#include <asm/uaccess.h>
#include <asm/setup.h>
-#include <asm/segment.h>
#include <asm/system.h>
/*#include <asm/irq.h>*/
#include <asm/q40_master.h>
diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c
index 3bab32a22..e218331e8 100644
--- a/drivers/video/sbusfb.c
+++ b/drivers/video/sbusfb.c
@@ -1019,7 +1019,7 @@ sizechange:
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
- fb->info.node = -1;
+ fb->info.node = NODEV;
fb->info.fbops = &sbusfb_ops;
fb->info.disp = disp;
strcpy(fb->info.fontname, fontname);
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 81ad28b98..5121d8ddc 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -648,7 +648,7 @@ int __init vesafb_init(void)
strcpy(fb_info.modename, "VESA VGA");
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &vesafb_ops;
fb_info.disp=&disp;
fb_info.switch_con=&vesafb_switch;
diff --git a/fs/Config.in b/fs/Config.in
index 976ff9fff..cf54dfdc9 100644
--- a/fs/Config.in
+++ b/fs/Config.in
@@ -45,7 +45,7 @@ if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then
fi
tristate 'Compressed ROM file system support' CONFIG_CRAMFS
bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
-tristate 'Simple RAM-based file system support' CONFIG_RAMFS
+define_bool CONFIG_RAMFS y
tristate 'ISO 9660 CDROM file system support' CONFIG_ISO9660_FS
dep_mbool ' Microsoft Joliet CDROM extensions' CONFIG_JOLIET $CONFIG_ISO9660_FS
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 9e402bcd9..5fefdd968 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -37,11 +37,8 @@ adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh, int
goto abort_toobig;
block = __adfs_block_map(inode->i_sb, inode->i_ino, block);
- if (block) {
- bh->b_dev = inode->i_dev;
- bh->b_blocknr = block;
- bh->b_state |= (1UL << BH_Mapped);
- }
+ if (block)
+ map_bh(bh, inode->i_sb, block);
return 0;
}
/* don't support allocation of blocks yet */
@@ -251,7 +248,6 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
if (!inode)
goto out;
- inode->i_version = ++event;
inode->i_uid = sb->u.adfs_sb.s_uid;
inode->i_gid = sb->u.adfs_sb.s_gid;
inode->i_ino = obj->file_id;
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index f1af56308..1b695e5d1 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -39,7 +39,7 @@ void __adfs_error(struct super_block *sb, const char *function, const char *fmt,
va_end(args);
printk(KERN_CRIT "ADFS-fs error (device %s)%s%s: %s\n",
- bdevname(sb->s_dev), function ? ": " : "",
+ sb->s_id, function ? ": " : "",
function ? function : "", error_buf);
}
@@ -308,7 +308,6 @@ struct super_block *adfs_read_super(struct super_block *sb, void *data, int sile
struct buffer_head *bh;
struct object_info root_obj;
unsigned char *b_data;
- kdev_t dev = sb->s_dev;
/* set default options */
sb->u.adfs_sb.s_uid = 0;
@@ -319,8 +318,7 @@ struct super_block *adfs_read_super(struct super_block *sb, void *data, int sile
if (parse_options(sb, data))
goto error;
- sb->s_blocksize = BLOCK_SIZE;
- set_blocksize(dev, BLOCK_SIZE);
+ sb_set_blocksize(sb, BLOCK_SIZE);
if (!(bh = sb_bread(sb, ADFS_DISCRECORD / BLOCK_SIZE))) {
adfs_error(sb, "unable to read superblock");
goto error;
@@ -331,7 +329,7 @@ struct super_block *adfs_read_super(struct super_block *sb, void *data, int sile
if (adfs_checkbblk(b_data)) {
if (!silent)
printk("VFS: Can't find an adfs filesystem on dev "
- "%s.\n", bdevname(dev));
+ "%s.\n", sb->s_id);
goto error_free_bh;
}
@@ -343,18 +341,12 @@ struct super_block *adfs_read_super(struct super_block *sb, void *data, int sile
if (adfs_checkdiscrecord(dr)) {
if (!silent)
printk("VPS: Can't find an adfs filesystem on dev "
- "%s.\n", bdevname(dev));
+ "%s.\n", sb->s_id);
goto error_free_bh;
}
- sb->s_blocksize_bits = dr->log2secsize;
- sb->s_blocksize = 1 << sb->s_blocksize_bits;
- if (sb->s_blocksize != BLOCK_SIZE &&
- (sb->s_blocksize == 512 || sb->s_blocksize == 1024 ||
- sb->s_blocksize == 2048 || sb->s_blocksize == 4096)) {
-
- brelse(bh);
- set_blocksize(dev, sb->s_blocksize);
+ brelse(bh);
+ if (sb_set_blocksize(sb, 1 << dr->log2secsize)) {
bh = sb_bread(sb, ADFS_DISCRECORD / sb->s_blocksize);
if (!bh) {
adfs_error(sb, "couldn't read superblock on "
@@ -367,12 +359,11 @@ struct super_block *adfs_read_super(struct super_block *sb, void *data, int sile
goto error_free_bh;
}
dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
- }
- if (sb->s_blocksize != bh->b_size) {
+ } else {
if (!silent)
printk(KERN_ERR "VFS: Unsupported blocksize on dev "
- "%s.\n", bdevname(dev));
- goto error_free_bh;
+ "%s.\n", sb->s_id);
+ goto error;
}
/*
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index c5803c5f4..1ac692e33 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -453,7 +453,7 @@ affs_error(struct super_block *sb, const char *function, const char *fmt, ...)
vsprintf(ErrorBuffer,fmt,args);
va_end(args);
- printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n", bdevname(sb->s_dev),
+ printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n", sb->s_id,
function,ErrorBuffer);
if (!(sb->s_flags & MS_RDONLY))
printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n");
@@ -470,7 +470,7 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
vsprintf(ErrorBuffer,fmt,args);
va_end(args);
- printk(KERN_WARNING "AFFS warning (device %s): %s(): %s\n", bdevname(sb->s_dev),
+ printk(KERN_WARNING "AFFS warning (device %s): %s(): %s\n", sb->s_id,
function,ErrorBuffer);
}
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
index c7cfd2258..697c8b47d 100644
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -282,7 +282,7 @@ affs_init_bitmap(struct super_block *sb)
if (!AFFS_ROOT_TAIL(sb, AFFS_SB->s_root_bh)->bm_flag) {
printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n",
- kdevname(sb->s_dev));
+ sb->s_id);
sb->s_flags |= MS_RDONLY;
return 0;
}
@@ -316,7 +316,7 @@ affs_init_bitmap(struct super_block *sb)
}
if (affs_checksum_block(sb, bh)) {
printk(KERN_WARNING "AFFS: Bitmap %u invalid - mounting %s read only.\n",
- bm->bm_key, kdevname(sb->s_dev));
+ bm->bm_key, sb->s_id);
sb->s_flags |= MS_RDONLY;
goto out;
}
diff --git a/fs/affs/file.c b/fs/affs/file.c
index a54289141..a09a4502e 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -355,9 +355,7 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul
ext_bh = affs_get_extblock(inode, ext);
if (IS_ERR(ext_bh))
goto err_ext;
- bh_result->b_blocknr = be32_to_cpu(AFFS_BLOCK(sb, ext_bh, block));
- bh_result->b_dev = inode->i_dev;
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, block)));
if (create) {
u32 blocknr = affs_alloc_block(inode, ext_bh->b_blocknr);
diff --git a/fs/affs/super.c b/fs/affs/super.c
index d65e44bb3..b4653c37f 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -262,7 +262,7 @@ affs_read_super(struct super_block *sb, void *data, int silent)
* blocks, we will have to change it.
*/
- blocks = blk_size[MAJOR(dev)] ? blk_size[MAJOR(dev)][MINOR(dev)] : 0;
+ blocks = blk_size[major(dev)] ? blk_size[major(dev)][minor(dev)] : 0;
if (!blocks) {
printk(KERN_ERR "AFFS: Could not determine device size\n");
goto out_error;
@@ -300,7 +300,7 @@ affs_read_super(struct super_block *sb, void *data, int silent)
for (num_bm = 0; num_bm < 2; num_bm++) {
pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, "
"size=%d, reserved=%d\n",
- kdevname(dev),
+ sb->s_id,
AFFS_SB->s_root_block + num_bm,
blocksize, size, reserved);
root_bh = affs_bread(sb, AFFS_SB->s_root_block + num_bm);
@@ -320,17 +320,13 @@ affs_read_super(struct super_block *sb, void *data, int silent)
}
if (!silent)
printk(KERN_ERR "AFFS: No valid root block on device %s\n",
- kdevname(dev));
+ sb->s_id);
goto out_error;
/* N.B. after this point bh must be released */
got_root:
root_block = AFFS_SB->s_root_block;
- sb->s_blocksize_bits = blocksize == 512 ? 9 :
- blocksize == 1024 ? 10 :
- blocksize == 2048 ? 11 : 12;
-
/* Find out which kind of FS we have */
boot_bh = sb_bread(sb, 0);
if (!boot_bh) {
@@ -347,7 +343,7 @@ got_root:
if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
|| chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) {
printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
- kdevname(dev));
+ sb->s_id);
sb->s_flags |= MS_RDONLY;
AFFS_SB->s_flags |= SF_READONLY;
}
@@ -383,7 +379,7 @@ got_root:
break;
default:
printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n",
- kdevname(dev), chksum);
+ sb->s_id, chksum);
goto out_error;
}
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index c1062cb6a..d275c5f81 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -11,6 +11,7 @@
* ------------------------------------------------------------------------- */
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/locks.h>
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 8d58e82c5..1f2d29f6d 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -308,7 +308,7 @@ struct inode *autofs4_get_inode(struct super_block *sb,
}
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
- inode->i_rdev = 0;
+ inode->i_rdev = NODEV;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
if (S_ISDIR(inf->mode)) {
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 5a8874890..266186cc3 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -28,13 +28,12 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
struct inode * dir = f->f_dentry->d_inode;
struct buffer_head * bh;
struct bfs_dirent * de;
- kdev_t dev = dir->i_dev;
unsigned int offset;
int block;
if (f->f_pos & (BFS_DIRENT_SIZE-1)) {
printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos,
- bdevname(dev), dir->i_ino);
+ dir->i_sb->s_id, dir->i_ino);
return -EBADF;
}
@@ -169,12 +168,11 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry)
goto out_brelse;
if (!inode->i_nlink) {
- printf("unlinking non-existent file %s:%lu (nlink=%d)\n", bdevname(inode->i_dev),
+ printf("unlinking non-existent file %s:%lu (nlink=%d)\n", inode->i_sb->s_id,
inode->i_ino, inode->i_nlink);
inode->i_nlink = 1;
}
de->ino = 0;
- dir->i_version = ++event;
mark_buffer_dirty(bh);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(dir);
@@ -227,7 +225,6 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
}
old_de->ino = 0;
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
- old_dir->i_version = ++event;
mark_inode_dirty(old_dir);
if (new_inode) {
new_inode->i_nlink--;
@@ -256,7 +253,6 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int
struct buffer_head * bh;
struct bfs_dirent * de;
int block, sblock, eblock, off;
- kdev_t dev;
int i;
dprintf("name=%s, namelen=%d\n", name, namelen);
@@ -266,7 +262,6 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int
if (namelen > BFS_NAMELEN)
return -ENAMETOOLONG;
- dev = dir->i_dev;
sblock = dir->iu_sblock;
eblock = dir->iu_eblock;
for (block=sblock; block<=eblock; block++) {
@@ -282,7 +277,6 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int
}
dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(dir);
- dir->i_version = ++event;
de->ino = ino;
for (i=0; i<BFS_NAMELEN; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index bb301b44e..4dbd8d694 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -25,14 +25,14 @@ struct file_operations bfs_file_operations = {
mmap: generic_file_mmap,
};
-static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
+static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
{
struct buffer_head *bh, *new;
- bh = bread(dev, from, BFS_BSIZE);
+ bh = sb_bread(sb, from);
if (!bh)
return -EIO;
- new = getblk(dev, to, BFS_BSIZE);
+ new = sb_getblk(sb, to);
memcpy(new->b_data, bh->b_data, bh->b_size);
mark_buffer_dirty(new);
bforget(bh);
@@ -40,14 +40,14 @@ static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
return 0;
}
-static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end,
+static int bfs_move_blocks(struct super_block *sb, unsigned long start, unsigned long end,
unsigned long where)
{
unsigned long i;
dprintf("%08lx-%08lx->%08lx\n", start, end, where);
for (i = start; i <= end; i++)
- if(bfs_move_block(i, where + i, dev)) {
+ if(bfs_move_block(i, where + i, sb)) {
dprintf("failed to move block %08lx -> %08lx\n", i, where + i);
return -EIO;
}
@@ -69,9 +69,7 @@ static int bfs_get_block(struct inode * inode, sector_t block,
if (!create) {
if (phys <= inode->iu_eblock) {
dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys);
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, sb, phys);
}
return 0;
}
@@ -81,9 +79,7 @@ static int bfs_get_block(struct inode * inode, sector_t block,
if (inode->i_size && phys <= inode->iu_eblock) {
dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n",
create, block, phys);
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, sb, phys);
return 0;
}
@@ -95,9 +91,7 @@ static int bfs_get_block(struct inode * inode, sector_t block,
if (inode->iu_eblock == sb->su_lf_eblk) {
dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n",
create, block, phys);
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, sb, phys);
sb->su_freeb -= phys - inode->iu_eblock;
sb->su_lf_eblk = inode->iu_eblock = phys;
mark_inode_dirty(inode);
@@ -109,7 +103,7 @@ static int bfs_get_block(struct inode * inode, sector_t block,
/* Ok, we have to move this entire file to the next free block */
phys = sb->su_lf_eblk + 1;
if (inode->iu_sblock) { /* if data starts on block 0 then there is no data */
- err = bfs_move_blocks(inode->i_dev, inode->iu_sblock,
+ err = bfs_move_blocks(inode->i_sb, inode->iu_sblock,
inode->iu_eblock, phys);
if (err) {
dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
@@ -128,9 +122,7 @@ static int bfs_get_block(struct inode * inode, sector_t block,
sb->su_freeb -= inode->iu_eblock - inode->iu_sblock + 1 - inode->i_blocks;
mark_inode_dirty(inode);
mark_buffer_dirty(sbh);
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, sb, phys);
out:
unlock_kernel();
return err;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index f83f13f56..402b936da 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -35,13 +35,12 @@ void dump_imap(const char *prefix, struct super_block * s);
static void bfs_read_inode(struct inode * inode)
{
unsigned long ino = inode->i_ino;
- kdev_t dev = inode->i_dev;
struct bfs_inode * di;
struct buffer_head * bh;
int block, off;
if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
- printf("Bad inode number %s:%08lx\n", bdevname(dev), ino);
+ printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
make_bad_inode(inode);
return;
}
@@ -49,7 +48,7 @@ static void bfs_read_inode(struct inode * inode)
block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(inode->i_sb, block);
if (!bh) {
- printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
+ printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
make_bad_inode(inode);
return;
}
@@ -88,13 +87,12 @@ static void bfs_read_inode(struct inode * inode)
static void bfs_write_inode(struct inode * inode, int unused)
{
unsigned long ino = inode->i_ino;
- kdev_t dev = inode->i_dev;
struct bfs_inode * di;
struct buffer_head * bh;
int block, off;
if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
- printf("Bad inode number %s:%08lx\n", bdevname(dev), ino);
+ printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
return;
}
@@ -102,7 +100,7 @@ static void bfs_write_inode(struct inode * inode, int unused)
block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(inode->i_sb, block);
if (!bh) {
- printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
+ printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
unlock_kernel();
return;
}
@@ -135,7 +133,6 @@ static void bfs_write_inode(struct inode * inode, int unused)
static void bfs_delete_inode(struct inode * inode)
{
unsigned long ino = inode->i_ino;
- kdev_t dev = inode->i_dev;
struct bfs_inode * di;
struct buffer_head * bh;
int block, off;
@@ -155,7 +152,7 @@ static void bfs_delete_inode(struct inode * inode)
block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(s, block);
if (!bh) {
- printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
+ printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
unlock_kernel();
return;
}
@@ -241,16 +238,12 @@ void dump_imap(const char *prefix, struct super_block * s)
static struct super_block * bfs_read_super(struct super_block * s,
void * data, int silent)
{
- kdev_t dev;
struct buffer_head * bh;
struct bfs_super_block * bfs_sb;
struct inode * inode;
int i, imap_len;
- dev = s->s_dev;
- set_blocksize(dev, BFS_BSIZE);
- s->s_blocksize = BFS_BSIZE;
- s->s_blocksize_bits = BFS_BSIZE_BITS;
+ sb_set_blocksize(s, BFS_BSIZE);
bh = sb_bread(s, 0);
if(!bh)
@@ -259,11 +252,11 @@ static struct super_block * bfs_read_super(struct super_block * s,
if (bfs_sb->s_magic != BFS_MAGIC) {
if (!silent)
printf("No BFS filesystem on %s (magic=%08x)\n",
- bdevname(dev), bfs_sb->s_magic);
+ s->s_id, bfs_sb->s_magic);
goto out;
}
if (BFS_UNCLEAN(bfs_sb, s) && !silent)
- printf("%s is unclean, continuing\n", bdevname(dev));
+ printf("%s is unclean, continuing\n", s->s_id);
s->s_magic = BFS_MAGIC;
s->su_bfs_sb = bfs_sb;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index cbeb0fb38..3a9c713fd 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -505,30 +505,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
#if 0
printk("Using ELF interpreter %s\n", elf_interpreter);
#endif
-#ifdef __sparc__
- if (ibcs2_interpreter) {
- unsigned long old_pers = current->personality;
- struct exec_domain *old_domain = current->exec_domain;
- struct exec_domain *new_domain;
- struct fs_struct *old_fs = current->fs, *new_fs;
- get_exec_domain(old_domain);
- atomic_inc(&old_fs->count);
-
- set_personality(PER_SVR4);
- interpreter = open_exec(elf_interpreter);
-
- new_domain = current->exec_domain;
- new_fs = current->fs;
- current->personality = old_pers;
- current->exec_domain = old_domain;
- current->fs = old_fs;
- put_exec_domain(new_domain);
- put_fs_struct(new_fs);
- } else
-#endif
- {
- interpreter = open_exec(elf_interpreter);
- }
+
+ SET_PERSONALITY(elf_ex, ibcs2_interpreter);
+
+ interpreter = open_exec(elf_interpreter);
retval = PTR_ERR(interpreter);
if (IS_ERR(interpreter))
goto out_free_interp;
@@ -602,10 +582,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->flags &= ~PF_FORKNOEXEC;
elf_entry = (unsigned long) elf_ex.e_entry;
- /* Do this immediately, since STACK_TOP as used in setup_arg_pages
- may depend on the personality. */
- SET_PERSONALITY(elf_ex, ibcs2_interpreter);
-
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
current->mm->rss = 0;
diff --git a/fs/bio.c b/fs/bio.c
index 906b9878d..84752e897 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -444,7 +444,10 @@ int bio_endio(struct bio *bio, int uptodate, int nr_sectors)
else
clear_bit(BIO_UPTODATE, &bio->bi_flags);
- return bio->bi_end_io(bio, nr_sectors);
+ if (bio->bi_end_io)
+ return bio->bi_end_io(bio, nr_sectors);
+
+ return 0;
}
static void __init biovec_init_pool(void)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 301a62ef5..7e04cec34 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -27,10 +27,10 @@
static unsigned long max_block(kdev_t dev)
{
unsigned int retval = ~0U;
- int major = MAJOR(dev);
+ int major = major(dev);
if (blk_size[major]) {
- int minor = MINOR(dev);
+ int minor = minor(dev);
unsigned int blocks = blk_size[major][minor];
if (blocks) {
unsigned int size = block_size(dev);
@@ -47,10 +47,10 @@ static unsigned long max_block(kdev_t dev)
static loff_t blkdev_size(kdev_t dev)
{
unsigned int blocks = ~0U;
- int major = MAJOR(dev);
+ int major = major(dev);
if (blk_size[major]) {
- int minor = MINOR(dev);
+ int minor = minor(dev);
blocks = blk_size[major][minor];
}
return (loff_t) blocks << BLOCK_SIZE_BITS;
@@ -77,31 +77,51 @@ int set_blocksize(kdev_t dev, int size)
return -EINVAL;
/* No blocksize array? Implies hardcoded BLOCK_SIZE */
- if (!blksize_size[MAJOR(dev)]) {
+ if (!blksize_size[major(dev)]) {
if (size == BLOCK_SIZE)
return 0;
return -EINVAL;
}
- oldsize = blksize_size[MAJOR(dev)][MINOR(dev)];
+ oldsize = blksize_size[major(dev)][minor(dev)];
if (oldsize == size)
return 0;
if (!oldsize && size == BLOCK_SIZE) {
- blksize_size[MAJOR(dev)][MINOR(dev)] = size;
+ blksize_size[major(dev)][minor(dev)] = size;
return 0;
}
/* Ok, we're actually changing the blocksize.. */
- bdev = bdget(dev);
+ bdev = bdget(kdev_t_to_nr(dev));
sync_buffers(dev, 2);
- blksize_size[MAJOR(dev)][MINOR(dev)] = size;
+ blksize_size[major(dev)][minor(dev)] = size;
bdev->bd_inode->i_blkbits = blksize_bits(size);
kill_bdev(bdev);
bdput(bdev);
return 0;
}
+int sb_set_blocksize(struct super_block *sb, int size)
+{
+ int bits;
+ if (set_blocksize(sb->s_dev, size) < 0)
+ return 0;
+ sb->s_blocksize = size;
+ for (bits = 9, size >>= 9; size >>= 1; bits++)
+ ;
+ sb->s_blocksize_bits = bits;
+ return sb->s_blocksize;
+}
+
+int sb_min_blocksize(struct super_block *sb, int size)
+{
+ int minsize = get_hardsect_size(sb->s_dev);
+ if (size < minsize)
+ size = minsize;
+ return sb_set_blocksize(sb, size);
+}
+
static int blkdev_get_block(struct inode * inode, sector_t iblock, struct buffer_head * bh, int create)
{
if (iblock >= max_block(inode->i_rdev))
@@ -491,15 +511,18 @@ int check_disk_change(kdev_t dev)
int i;
const struct block_device_operations * bdops = NULL;
- i = MAJOR(dev);
+ i = major(dev);
if (i < MAX_BLKDEV)
bdops = blkdevs[i].bdops;
if (bdops == NULL) {
devfs_handle_t de;
- de = devfs_find_handle (NULL, NULL, i, MINOR (dev),
+ de = devfs_find_handle (NULL, NULL, i, minor(dev),
DEVFS_SPECIAL_BLK, 0);
- if (de) bdops = devfs_get_ops (de);
+ if (de) {
+ bdops = devfs_get_ops (de);
+ devfs_put_ops (de); /* We're running in owner module */
+ }
}
if (bdops == NULL)
return 0;
@@ -540,7 +563,7 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
down(&bdev->bd_sem);
lock_kernel();
if (!bdev->bd_op)
- bdev->bd_op = get_blkfops(MAJOR(dev));
+ bdev->bd_op = get_blkfops(major(dev));
if (bdev->bd_op) {
ret = 0;
if (bdev->bd_op->owner)
@@ -663,11 +686,11 @@ struct file_operations def_blk_fops = {
const char * bdevname(kdev_t dev)
{
static char buffer[32];
- const char * name = blkdevs[MAJOR(dev)].name;
+ const char * name = blkdevs[major(dev)].name;
if (!name)
name = "unknown-block";
- sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
+ sprintf(buffer, "%s(%d,%d)", name, major(dev), minor(dev));
return buffer;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index e724f5ade..816686216 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -203,7 +203,7 @@ static int write_some_buffers(kdev_t dev)
struct buffer_head * bh = next;
next = bh->b_next_free;
- if (dev && bh->b_dev != dev)
+ if (!kdev_none(dev) && !kdev_same(bh->b_dev, dev))
continue;
if (test_and_set_bit(BH_Lock, &bh->b_state))
continue;
@@ -261,7 +261,7 @@ static int wait_for_buffers(kdev_t dev, int index, int refile)
__refile_buffer(bh);
continue;
}
- if (dev && bh->b_dev != dev)
+ if (!kdev_none(dev) && !kdev_same(bh->b_dev, dev))
continue;
get_bh(bh);
@@ -324,7 +324,7 @@ int fsync_super(struct super_block *sb)
lock_kernel();
sync_inodes_sb(sb);
- DQUOT_SYNC(dev);
+ DQUOT_SYNC(sb);
lock_super(sb);
if (sb->s_dirt && sb->s_op && sb->s_op->write_super)
sb->s_op->write_super(sb);
@@ -346,7 +346,14 @@ int fsync_dev(kdev_t dev)
lock_kernel();
sync_inodes(dev);
- DQUOT_SYNC(dev);
+ if (!kdev_none(dev)) {
+ struct super_block *sb = get_super(dev);
+ if (sb) {
+ DQUOT_SYNC(sb);
+ drop_super(sb);
+ }
+ } else
+ DQUOT_SYNC(NULL);
sync_supers(dev);
unlock_kernel();
@@ -364,7 +371,7 @@ void sync_dev(kdev_t dev)
asmlinkage long sys_sync(void)
{
- fsync_dev(0);
+ fsync_dev(NODEV);
return 0;
}
@@ -564,7 +571,7 @@ struct buffer_head * get_hash_table(kdev_t dev, sector_t block, int size)
continue;
if (bh->b_size != size)
continue;
- if (bh->b_dev != dev)
+ if (!kdev_same(bh->b_dev, dev))
continue;
get_bh(bh);
break;
@@ -668,7 +675,7 @@ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
bh_next = bh->b_next_free;
/* Another device? */
- if (bh->b_dev != dev)
+ if (!kdev_same(bh->b_dev, dev))
continue;
/* Not hashed? */
if (!bh->b_pprev)
@@ -711,7 +718,7 @@ out:
void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
{
- struct block_device *bdev = bdget(dev);
+ struct block_device *bdev = bdget(kdev_t_to_nr(dev));
if (bdev) {
invalidate_bdev(bdev, destroy_dirty_buffers);
bdput(bdev);
@@ -1444,7 +1451,7 @@ int discard_bh_page(struct page *page, unsigned long offset, int drop_pagecache)
return 1;
}
-void create_empty_buffers(struct page *page, kdev_t dev, unsigned long blocksize)
+void create_empty_buffers(struct page *page, unsigned long blocksize)
{
struct buffer_head *bh, *head, *tail;
@@ -1455,8 +1462,6 @@ void create_empty_buffers(struct page *page, kdev_t dev, unsigned long blocksize
bh = head;
do {
- bh->b_dev = dev;
- bh->b_blocknr = 0;
bh->b_end_io = NULL;
tail = bh;
bh = bh->b_this_page;
@@ -1518,7 +1523,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
BUG();
if (!page->buffers)
- create_empty_buffers(page, inode->i_dev, 1 << inode->i_blkbits);
+ create_empty_buffers(page, 1 << inode->i_blkbits);
head = page->buffers;
block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
@@ -1585,7 +1590,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
blocksize = 1 << inode->i_blkbits;
if (!page->buffers)
- create_empty_buffers(page, inode->i_dev, blocksize);
+ create_empty_buffers(page, blocksize);
head = page->buffers;
bbits = inode->i_blkbits;
@@ -1702,7 +1707,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
PAGE_BUG(page);
blocksize = 1 << inode->i_blkbits;
if (!page->buffers)
- create_empty_buffers(page, inode->i_dev, blocksize);
+ create_empty_buffers(page, blocksize);
head = page->buffers;
blocks = PAGE_CACHE_SIZE >> inode->i_blkbits;
@@ -1907,7 +1912,7 @@ int block_truncate_page(struct address_space *mapping, loff_t from, get_block_t
goto out;
if (!page->buffers)
- create_empty_buffers(page, inode->i_dev, blocksize);
+ create_empty_buffers(page, blocksize);
/* Find the buffer that contains "offset" */
bh = page->buffers;
@@ -2123,13 +2128,14 @@ int brw_page(int rw, struct page *page, kdev_t dev, sector_t b[], int size)
panic("brw_page: page not locked for I/O");
if (!page->buffers)
- create_empty_buffers(page, dev, size);
+ create_empty_buffers(page, size);
head = bh = page->buffers;
/* Stage 1: lock all the buffers */
do {
lock_buffer(bh);
bh->b_blocknr = *(b++);
+ bh->b_dev = dev;
set_bit(BH_Mapped, &bh->b_state);
set_buffer_async_io(bh);
bh = bh->b_this_page;
@@ -2390,7 +2396,7 @@ cleaned_buffers_try_again:
struct buffer_head * p = tmp;
tmp = tmp->b_this_page;
- if (p->b_dev == B_FREE) BUG();
+ if (kdev_same(p->b_dev, B_FREE)) BUG();
remove_inode_queue(p);
__remove_from_queues(p);
@@ -2556,7 +2562,7 @@ static int sync_old_buffers(void)
{
lock_kernel();
sync_unlocked_inodes();
- sync_supers(0);
+ sync_supers(NODEV);
unlock_kernel();
for (;;) {
diff --git a/fs/char_dev.c b/fs/char_dev.c
index de15221d0..e5043598f 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -6,6 +6,7 @@
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/fs.h>
#include <linux/slab.h>
#define HASH_BITS 6
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 2d8386310..03ab04df4 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -14,7 +14,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/list.h>
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index c2b797a96..837072a79 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -15,7 +15,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 6a655a243..d3bc9a225 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -16,7 +16,6 @@
#include <linux/errno.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
-#include <asm/segment.h>
#include <linux/string.h>
#include <asm/uaccess.h>
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index c7d890a37..3918709b0 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -25,7 +25,6 @@
#include <linux/fs.h>
#include <linux/vmalloc.h>
-#include <asm/segment.h>
#include <linux/coda.h>
#include <linux/coda_linux.h>
@@ -71,7 +70,7 @@ static int get_device_index(struct coda_mount_data *data)
inode = file->f_dentry->d_inode;
if(!inode || !S_ISCHR(inode->i_mode) ||
- MAJOR(inode->i_rdev) != CODA_PSDEV_MAJOR) {
+ major(inode->i_rdev) != CODA_PSDEV_MAJOR) {
if(file)
fput(file);
@@ -79,7 +78,7 @@ static int get_device_index(struct coda_mount_data *data)
return -1;
}
- idx = MINOR(inode->i_rdev);
+ idx = minor(inode->i_rdev);
fput(file);
if(idx < 0 || idx >= MAX_CODADEVS) {
@@ -152,8 +151,8 @@ static struct super_block * coda_read_super(struct super_block *sb,
goto error;
}
- printk("coda_read_super: rootinode is %ld dev %d\n",
- root->i_ino, root->i_dev);
+ printk("coda_read_super: rootinode is %ld dev %x\n",
+ root->i_ino, kdev_val(root->i_dev));
sb->s_root = d_alloc_root(root);
return sb;
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index e011c8953..861a87741 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -14,7 +14,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <linux/string.h>
#define __NO_VERSION__
#include <linux/module.h>
@@ -82,7 +81,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
}
CDEBUG(D_PIOCTL, "target ino: 0x%ld, dev: 0x%x\n",
- target_inode->i_ino, target_inode->i_dev);
+ target_inode->i_ino, kdev_val(target_inode->i_dev));
/* return if it is not a Coda inode */
if ( target_inode->i_sb != inode->i_sb ) {
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 023ce45b5..7300732d4 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -38,7 +38,6 @@
#include <linux/list.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/poll.h>
#include <asm/uaccess.h>
@@ -294,7 +293,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
int idx;
lock_kernel();
- idx = MINOR(inode->i_rdev);
+ idx = minor(inode->i_rdev);
if(idx >= MAX_CODADEVS) {
unlock_kernel();
return -ENODEV;
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index 9e60aa994..231b7713b 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -21,7 +21,6 @@
#include <linux/stat.h>
#include <linux/ctype.h>
#include <asm/bitops.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/utsname.h>
#define __NO_VERSION__
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index cf01630c6..9c87ee4de 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -15,7 +15,6 @@
*/
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/signal.h>
#include <linux/signal.h>
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 7f4afb369..2132104cd 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -115,7 +115,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
struct buffer_head * read_array[BLKS_PER_BUF];
unsigned i, blocknr, buffer, unread;
unsigned long devsize;
- int major, minor;
+ unsigned int major, minor;
char *data;
@@ -140,8 +140,8 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
}
devsize = ~0UL;
- major = MAJOR(sb->s_dev);
- minor = MINOR(sb->s_dev);
+ major = major(sb->s_dev);
+ minor = minor(sb->s_dev);
if (blk_size[major])
devsize = blk_size[major][minor] >> 2;
@@ -195,9 +195,7 @@ static struct super_block * cramfs_read_super(struct super_block *sb, void *data
unsigned long root_offset;
struct super_block * retval = NULL;
- set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb_set_blocksize(sb, PAGE_CACHE_SIZE);
/* Invalidate the read buffers on mount: think disk change.. */
for (i = 0; i < READ_BUFFERS; i++)
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 2eeb1b733..639ae7464 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -427,7 +427,7 @@
Work sponsored by SGI.
v0.92
20000306 Richard Gooch <rgooch@atnf.csiro.au>
- Added DEVFS_FL_NO_PERSISTENCE flag.
+ Added DEVFS_ FL_NO_PERSISTENCE flag.
Removed unnecessary call to <update_devfs_inode_from_entry> in
<devfs_readdir>.
Work sponsored by SGI.
@@ -562,6 +562,45 @@
20011122 Richard Gooch <rgooch@atnf.csiro.au>
Use slab cache rather than fixed buffer for devfsd events.
v1.1
+ 20011125 Richard Gooch <rgooch@atnf.csiro.au>
+ Send DEVFSD_NOTIFY_REGISTERED events in <devfs_mk_dir>.
+ 20011127 Richard Gooch <rgooch@atnf.csiro.au>
+ Fixed locking bug in <devfs_d_revalidate_wait> due to typo.
+ Do not send CREATE, CHANGE, ASYNC_OPEN or DELETE events from
+ devfsd or children.
+ v1.2
+ 20011202 Richard Gooch <rgooch@atnf.csiro.au>
+ Fixed bug in <devfsd_read>: was dereferencing freed pointer.
+ v1.3
+ 20011203 Richard Gooch <rgooch@atnf.csiro.au>
+ Fixed bug in <devfsd_close>: was dereferencing freed pointer.
+ Added process group check for devfsd privileges.
+ v1.4
+ 20011204 Richard Gooch <rgooch@atnf.csiro.au>
+ Use SLAB_ATOMIC in <devfsd_notify_de> from <devfs_d_delete>.
+ v1.5
+ 20011211 Richard Gooch <rgooch@atnf.csiro.au>
+ Return old entry in <devfs_mk_dir> for 2.4.x kernels.
+ 20011212 Richard Gooch <rgooch@atnf.csiro.au>
+ Increment refcount on module in <check_disc_changed>.
+ 20011215 Richard Gooch <rgooch@atnf.csiro.au>
+ Created <devfs_get_handle> and exported <devfs_put>.
+ Increment refcount on module in <devfs_get_ops>.
+ Created <devfs_put_ops>.
+ v1.6
+ 20011216 Richard Gooch <rgooch@atnf.csiro.au>
+ Added poisoning to <devfs_put>.
+ Improved debugging messages.
+ v1.7
+ 20011221 Richard Gooch <rgooch@atnf.csiro.au>
+ Corrected (made useful) debugging message in <unregister>.
+ Moved <kmem_cache_create> in <mount_devfs_fs> to <init_devfs_fs>
+ 20011224 Richard Gooch <rgooch@atnf.csiro.au>
+ Added magic number to guard against scribbling drivers.
+ 20011226 Richard Gooch <rgooch@atnf.csiro.au>
+ Only return old entry in <devfs_mk_dir> if a directory.
+ Defined macros for error and debug messages.
+ v1.8
*/
#include <linux/types.h>
#include <linux/errno.h>
@@ -594,13 +633,16 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
-#define DEVFS_VERSION "1.1 (20011122)"
+#define DEVFS_VERSION "1.8 (20011226)"
#define DEVFS_NAME "devfs"
#define FIRST_INODE 1
#define STRING_LENGTH 256
+#define FAKE_BLOCK_SIZE 1024
+#define POISON_PTR ( *(void **) poison_array )
+#define MAGIC_VALUE 0x327db823
#ifndef TRUE
# define TRUE 1
@@ -637,9 +679,28 @@
#define OPTION_MOUNT 0x01
#define OPTION_ONLY 0x02
-#define OOPS(format, args...) {printk (format, ## args); \
- printk ("Forcing Oops\n"); \
- BUG();}
+#define PRINTK(format, args...) \
+ {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);}
+
+#define OOPS(format, args...) \
+ {printk (KERN_CRIT "%s" format, __FUNCTION__ , ## args); \
+ printk ("Forcing Oops\n"); \
+ BUG();}
+
+#ifdef CONFIG_DEVFS_DEBUG
+# define VERIFY_ENTRY(de) \
+ {if ((de) && (de)->magic_number != MAGIC_VALUE) \
+ OOPS ("(%p): bad magic value: %x\n", (de), (de)->magic_number);}
+# define WRITE_ENTRY_MAGIC(de,magic) (de)->magic_number = (magic)
+# define DPRINTK(flag, format, args...) \
+ {if (devfs_debug & flag) \
+ printk (KERN_INFO "%s" format, __FUNCTION__ , ## args);}
+#else
+# define VERIFY_ENTRY(de)
+# define WRITE_ENTRY_MAGIC(de,magic)
+# define DPRINTK(flag, format, args...)
+#endif
+
struct directory_type
{
@@ -696,6 +757,9 @@ struct devfs_inode /* This structure is for "persistent" inode storage */
struct devfs_entry
{
+#ifdef CONFIG_DEVFS_DEBUG
+ unsigned int magic_number;
+#endif
void *info;
atomic_t refcount; /* When this drops to zero, it's unused */
union
@@ -740,6 +804,7 @@ struct fs_info /* This structure is for the mounted devfs */
struct devfsd_buf_entry *devfsd_last_event;
volatile int devfsd_sleeping;
volatile struct task_struct *devfsd_task;
+ volatile pid_t devfsd_pgrp;
volatile struct file *devfsd_file;
struct devfsd_notify_struct *devfsd_info;
volatile unsigned long devfsd_event_mask;
@@ -757,6 +822,8 @@ static spinlock_t stat_lock = SPIN_LOCK_UNLOCKED;
static unsigned int stat_num_entries;
static unsigned int stat_num_bytes;
#endif
+static unsigned char poison_array[8] =
+ {0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a};
#ifdef CONFIG_DEVFS_MOUNT
static unsigned int boot_options = OPTION_MOUNT;
@@ -802,35 +869,35 @@ static struct file_operations devfsd_fops =
static struct devfs_entry *devfs_get (struct devfs_entry *de)
{
+ VERIFY_ENTRY (de);
if (de) atomic_inc (&de->refcount);
return de;
} /* End Function devfs_get */
/**
* devfs_put - Put (release) a reference to a devfs entry.
- * @de: The devfs entry.
+ * @de: The handle to the devfs entry.
*/
-static void devfs_put (struct devfs_entry *de)
+void devfs_put (devfs_handle_t de)
{
if (!de) return;
+ VERIFY_ENTRY (de);
+ if (de->info == POISON_PTR) OOPS ("(%p): poisoned pointer\n", de);
if ( !atomic_dec_and_test (&de->refcount) ) return;
- if (de == root_entry)
- OOPS ("%s: devfs_put(): root entry being freed\n", DEVFS_NAME);
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_FREE)
- printk ("%s: devfs_put(%s): de: %p, parent: %p \"%s\"\n",
- DEVFS_NAME, de->name, de, de->parent,
- de->parent ? de->parent->name : "no parent");
-#endif
+ if (de == root_entry) OOPS ("(%p): root entry being freed\n", de);
+ DPRINTK (DEBUG_FREE, "(%s): de: %p, parent: %p \"%s\"\n",
+ de->name, de, de->parent,
+ de->parent ? de->parent->name : "no parent");
if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname);
if ( ( S_ISCHR (de->mode) || S_ISBLK (de->mode) ) && de->u.fcb.autogen )
{
devfs_dealloc_devnum ( S_ISCHR (de->mode) ? DEVFS_SPECIAL_CHR :
DEVFS_SPECIAL_BLK,
- MKDEV (de->u.fcb.u.device.major,
+ mk_kdev(de->u.fcb.u.device.major,
de->u.fcb.u.device.minor) );
}
+ WRITE_ENTRY_MAGIC (de, 0);
#ifdef CONFIG_DEVFS_DEBUG
spin_lock (&stat_lock);
--stat_num_entries;
@@ -838,6 +905,7 @@ static void devfs_put (struct devfs_entry *de)
if ( S_ISLNK (de->mode) ) stat_num_bytes -= de->u.symlink.length + 1;
spin_unlock (&stat_lock);
#endif
+ de->info = POISON_PTR;
kfree (de);
} /* End Function devfs_put */
@@ -860,7 +928,7 @@ static struct devfs_entry *_devfs_search_dir (struct devfs_entry *dir,
if ( !S_ISDIR (dir->mode) )
{
- printk ("%s: search_dir(%s): not a directory\n", DEVFS_NAME,dir->name);
+ PRINTK ("(%s): not a directory\n", dir->name);
return NULL;
}
for (curr = dir->u.dir.first; curr != NULL; curr = curr->next)
@@ -893,7 +961,7 @@ static struct devfs_entry *_devfs_alloc_entry (const char *name,
if ( name && (namelen < 1) ) namelen = strlen (name);
if ( ( new = kmalloc (sizeof *new + namelen, GFP_KERNEL) ) == NULL )
return NULL;
- memset (new, 0, sizeof *new + namelen);
+ memset (new, 0, sizeof *new + namelen); /* Will set '\0' on name */
new->mode = mode;
if ( S_ISDIR (mode) ) rwlock_init (&new->u.dir.lock);
atomic_set (&new->refcount, 1);
@@ -902,6 +970,7 @@ static struct devfs_entry *_devfs_alloc_entry (const char *name,
spin_unlock (&counter_lock);
if (name) memcpy (new->name, name, namelen);
new->namelen = namelen;
+ WRITE_ENTRY_MAGIC (new, MAGIC_VALUE);
#ifdef CONFIG_DEVFS_DEBUG
spin_lock (&stat_lock);
++stat_num_entries;
@@ -918,7 +987,7 @@ static struct devfs_entry *_devfs_alloc_entry (const char *name,
* @de: The devfs entry to append.
* @removable: If TRUE, increment the count of removable devices for %dir.
* @old_de: If an existing entry exists, it will be written here. This may
- * be %NULL.
+ * be %NULL. An implicit devfs_get() is performed on this entry.
*
* Append a devfs entry to a directory's list of children, checking first to
* see if an entry of the same name exists. The directory will be locked.
@@ -934,8 +1003,7 @@ static int _devfs_append_entry (devfs_handle_t dir, devfs_handle_t de,
if (old_de) *old_de = NULL;
if ( !S_ISDIR (dir->mode) )
{
- printk ("%s: append_entry(%s): dir: \"%s\" is not a directory\n",
- DEVFS_NAME, de->name, dir->name);
+ PRINTK ("(%s): dir: \"%s\" is not a directory\n", de->name, dir->name);
devfs_put (de);
return -ENOTDIR;
}
@@ -995,16 +1063,16 @@ static struct devfs_entry *_devfs_get_root_entry (void)
if ( ( new = _devfs_alloc_entry (".devfsd", 0, S_IFCHR |S_IRUSR |S_IWUSR) )
== NULL ) return NULL;
devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
- new->u.fcb.u.device.major = MAJOR (devnum);
- new->u.fcb.u.device.minor = MINOR (devnum);
+ new->u.fcb.u.device.major = major (devnum);
+ new->u.fcb.u.device.minor = minor (devnum);
new->u.fcb.ops = &devfsd_fops;
_devfs_append_entry (root_entry, new, FALSE, NULL);
#ifdef CONFIG_DEVFS_DEBUG
if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) )
== NULL ) return NULL;
devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
- new->u.fcb.u.device.major = MAJOR (devnum);
- new->u.fcb.u.device.minor = MINOR (devnum);
+ new->u.fcb.u.device.major = major (devnum);
+ new->u.fcb.u.device.minor = minor (devnum);
new->u.fcb.ops = &stat_fops;
_devfs_append_entry (root_entry, new, FALSE, NULL);
#endif
@@ -1105,15 +1173,13 @@ static devfs_handle_t _devfs_prepare_leaf (devfs_handle_t *dir,
if ( ( *dir = _devfs_make_parent_for_leaf (*dir, name, namelen,
&leaf_pos) ) == NULL )
{
- printk ("%s: prepare_leaf(%s): could not create parent path\n",
- DEVFS_NAME, name);
+ PRINTK ("(%s): could not create parent path\n", name);
return NULL;
}
if ( ( de = _devfs_alloc_entry (name + leaf_pos, namelen - leaf_pos,mode) )
== NULL )
{
- printk ("%s: prepare_leaf(%s): could not allocate entry\n",
- DEVFS_NAME, name);
+ PRINTK ("(%s): could not allocate entry\n", name);
devfs_put (*dir);
return NULL;
}
@@ -1160,19 +1226,20 @@ static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir,
/**
- * find_by_dev - Find a devfs entry in a directory.
+ * _devfs_find_by_dev - Find a devfs entry in a directory.
* @dir: The directory where to search
* @major: The major number to search for.
* @minor: The minor number to search for.
* @type: The type of special file to search for. This may be either
* %DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK.
*
- * Returns the devfs_entry pointer on success, else %NULL.
+ * Returns the devfs_entry pointer on success, else %NULL. An implicit
+ * devfs_get() is performed.
*/
-static struct devfs_entry *find_by_dev (struct devfs_entry *dir,
- unsigned int major, unsigned int minor,
- char type)
+static struct devfs_entry *_devfs_find_by_dev (struct devfs_entry *dir,
+ unsigned int major,
+ unsigned int minor, char type)
{
struct devfs_entry *entry, *de;
@@ -1180,7 +1247,7 @@ static struct devfs_entry *find_by_dev (struct devfs_entry *dir,
if (dir == NULL) return NULL;
if ( !S_ISDIR (dir->mode) )
{
- printk ("%s: find_by_dev(): not a directory\n", DEVFS_NAME);
+ PRINTK ("(%p): not a directory\n", dir);
devfs_put (dir);
return NULL;
}
@@ -1205,7 +1272,7 @@ static struct devfs_entry *find_by_dev (struct devfs_entry *dir,
for (entry = dir->u.dir.first; entry != NULL; entry = entry->next)
{
if ( !S_ISDIR (entry->mode) ) continue;
- de = find_by_dev (entry, major, minor, type);
+ de = _devfs_find_by_dev (entry, major, minor, type);
if (de)
{
read_unlock (&dir->u.dir.lock);
@@ -1216,51 +1283,51 @@ static struct devfs_entry *find_by_dev (struct devfs_entry *dir,
read_unlock (&dir->u.dir.lock);
devfs_put (dir);
return NULL;
-} /* End Function find_by_dev */
+} /* End Function _devfs_find_by_dev */
/**
- * find_entry - Find a devfs entry.
+ * _devfs_find_entry - Find a devfs entry.
* @dir: The handle to the parent devfs directory entry. If this is %NULL the
* name is relative to the root of the devfs.
- * @name: The name of the entry. This is ignored if @handle is not %NULL.
- * @namelen: The number of characters in @name, not including a %NULL
- * terminator. If this is 0, then @name must be %NULL-terminated and the
- * length is computed internally.
- * @major: The major number. This is used if @handle and @name are %NULL.
- * @minor: The minor number. This is used if @handle and @name are %NULL.
+ * @name: The name of the entry. This may be %NULL.
+ * @major: The major number. This is used if lookup by @name fails.
+ * @minor: The minor number. This is used if lookup by @name fails.
* NOTE: If @major and @minor are both 0, searching by major and minor
* numbers is disabled.
* @type: The type of special file to search for. This may be either
* %DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK.
* @traverse_symlink: If %TRUE then symbolic links are traversed.
*
- * Returns the devfs_entry pointer on success, else %NULL.
+ * Returns the devfs_entry pointer on success, else %NULL. An implicit
+ * devfs_get() is performed.
*/
-static struct devfs_entry *find_entry (devfs_handle_t dir,
- const char *name, unsigned int namelen,
- unsigned int major, unsigned int minor,
- char type, int traverse_symlink)
+static struct devfs_entry *_devfs_find_entry (devfs_handle_t dir,
+ const char *name,
+ unsigned int major,
+ unsigned int minor,
+ char type, int traverse_symlink)
{
struct devfs_entry *entry;
if (name != NULL)
{
- if (namelen < 1) namelen = strlen (name);
+ unsigned int namelen = strlen (name);
+
if (name[0] == '/')
{
/* Skip leading pathname component */
if (namelen < 2)
{
- printk ("%s: find_entry(%s): too short\n", DEVFS_NAME, name);
+ PRINTK ("(%s): too short\n", name);
return NULL;
}
for (++name, --namelen; (*name != '/') && (namelen > 0);
++name, --namelen);
if (namelen < 2)
{
- printk ("%s: find_entry(%s): too short\n", DEVFS_NAME, name);
+ PRINTK ("(%s): too short\n", name);
return NULL;
}
++name;
@@ -1271,12 +1338,13 @@ static struct devfs_entry *find_entry (devfs_handle_t dir,
}
/* Have to search by major and minor: slow */
if ( (major == 0) && (minor == 0) ) return NULL;
- return find_by_dev (root_entry, major, minor, type);
-} /* End Function find_entry */
+ return _devfs_find_by_dev (root_entry, major, minor, type);
+} /* End Function _devfs_find_entry */
static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode)
{
if (inode == NULL) return NULL;
+ VERIFY_ENTRY ( (struct devfs_entry *) inode->u.generic_ip );
return inode->u.generic_ip;
} /* End Function get_devfs_entry_from_vfs_inode */
@@ -1315,10 +1383,14 @@ static int is_devfsd_or_child (struct fs_info *fs_info)
{
struct task_struct *p;
- for (p = current; p != &init_task; p = p->p_opptr)
+ if (current == fs_info->devfsd_task) return (TRUE);
+ if (current->pgrp == fs_info->devfsd_pgrp) return (TRUE);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,1)
+ for (p = current->p_opptr; p != &init_task; p = p->p_opptr)
{
if (p == fs_info->devfsd_task) return (TRUE);
}
+#endif
return (FALSE);
} /* End Function is_devfsd_or_child */
@@ -1375,13 +1447,16 @@ static int wait_for_devfsd_finished (struct fs_info *fs_info)
static int devfsd_notify_de (struct devfs_entry *de,
unsigned short type, umode_t mode,
- uid_t uid, gid_t gid, struct fs_info *fs_info)
+ uid_t uid, gid_t gid, struct fs_info *fs_info,
+ int atomic)
{
struct devfsd_buf_entry *entry;
struct devfs_entry *curr;
if ( !( fs_info->devfsd_event_mask & (1 << type) ) ) return (FALSE);
- if ( ( entry = kmem_cache_alloc (devfsd_buf_cache, 0) ) == NULL )
+ if ( ( entry = kmem_cache_alloc (devfsd_buf_cache,
+ atomic ? SLAB_ATOMIC : SLAB_KERNEL) )
+ == NULL )
{
atomic_inc (&fs_info->devfsd_overrun_count);
return (FALSE);
@@ -1414,7 +1489,7 @@ static int devfsd_notify_de (struct devfs_entry *de,
static void devfsd_notify (struct devfs_entry *de,unsigned short type,int wait)
{
if (devfsd_notify_de (de, type, de->mode, current->euid,
- current->egid, &fs_info) && wait)
+ current->egid, &fs_info, 0) && wait)
wait_for_devfsd_finished (&fs_info);
} /* End Function devfsd_notify */
@@ -1451,7 +1526,7 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
if (name == NULL)
{
- printk ("%s: devfs_register(): NULL name pointer\n", DEVFS_NAME);
+ PRINTK ("(): NULL name pointer\n");
return NULL;
}
if (ops == NULL)
@@ -1459,54 +1534,48 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
if ( S_ISBLK (mode) ) ops = (void *) get_blkfops (major);
if (ops == NULL)
{
- printk ("%s: devfs_register(%s): NULL ops pointer\n",
- DEVFS_NAME, name);
+ PRINTK ("(%s): NULL ops pointer\n", name);
return NULL;
}
- printk ("%s: devfs_register(%s): NULL ops, got %p from major table\n",
- DEVFS_NAME, name, ops);
+ PRINTK ("(%s): NULL ops, got %p from major table\n", name, ops);
}
if ( S_ISDIR (mode) )
{
- printk("%s: devfs_register(%s): creating directories is not allowed\n",
- DEVFS_NAME, name);
+ PRINTK ("(%s): creating directories is not allowed\n", name);
return NULL;
}
if ( S_ISLNK (mode) )
{
- printk ("%s: devfs_register(%s): creating symlinks is not allowed\n",
- DEVFS_NAME, name);
+ PRINTK ("(%s): creating symlinks is not allowed\n", name);
return NULL;
}
if ( ( S_ISCHR (mode) || S_ISBLK (mode) ) &&
(flags & DEVFS_FL_AUTO_DEVNUM) )
{
- if ( ( devnum = devfs_alloc_devnum (devtype) ) == NODEV )
+ if ( kdev_none( devnum = devfs_alloc_devnum (devtype) ) )
{
- printk ("%s: devfs_register(%s): exhausted %s device numbers\n",
- DEVFS_NAME, name, S_ISCHR (mode) ? "char" : "block");
+ PRINTK ("(%s): exhausted %s device numbers\n",
+ name, S_ISCHR (mode) ? "char" : "block");
return NULL;
}
- major = MAJOR (devnum);
- minor = MINOR (devnum);
+ major = major (devnum);
+ minor = minor (devnum);
}
if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL )
{
- printk ("%s: devfs_register(%s): could not prepare leaf\n",
- DEVFS_NAME, name);
- if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
+ PRINTK ("(%s): could not prepare leaf\n", name);
+ if (!kdev_none(devnum)) devfs_dealloc_devnum (devtype, devnum);
return NULL;
}
if ( S_ISCHR (mode) || S_ISBLK (mode) )
{
de->u.fcb.u.device.major = major;
de->u.fcb.u.device.minor = minor;
- de->u.fcb.autogen = (devnum == NODEV) ? FALSE : TRUE;
+ de->u.fcb.autogen = kdev_none(devnum) ? FALSE : TRUE;
}
else if ( !S_ISREG (mode) )
{
- printk ("%s: devfs_register(%s): illegal mode: %x\n",
- DEVFS_NAME, name, mode);
+ PRINTK ("(%s): illegal mode: %x\n", name, mode);
devfs_put (de);
devfs_put (dir);
return (NULL);
@@ -1530,17 +1599,13 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
if ( ( err = _devfs_append_entry (dir, de, de->u.fcb.removable, NULL) )
!= 0 )
{
- printk("%s: devfs_register(%s): could not append to parent, err: %d\n",
- DEVFS_NAME, name, err);
+ PRINTK ("(%s): could not append to parent, err: %d\n", name, err);
devfs_put (dir);
- if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
+ if (!kdev_none(devnum)) devfs_dealloc_devnum (devtype, devnum);
return NULL;
}
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_REGISTER)
- printk ("%s: devfs_register(%s): de: %p dir: %p \"%s\" pp: %p\n",
- DEVFS_NAME, name, de, dir, dir->name, dir->parent);
-#endif
+ DPRINTK (DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\" pp: %p\n",
+ name, de, dir, dir->name, dir->parent);
devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, flags & DEVFS_FL_WAIT);
devfs_put (dir);
return de;
@@ -1576,7 +1641,7 @@ static int _devfs_unhook (struct devfs_entry *de)
/**
- * unregister - Unregister a device entry from it's parent.
+ * _devfs_unregister - Unregister a device entry from it's parent.
* @dir: The parent directory.
* @de: The entry to unregister.
*
@@ -1584,7 +1649,7 @@ static int _devfs_unhook (struct devfs_entry *de)
* unlocked by this function.
*/
-static void unregister (struct devfs_entry *dir, struct devfs_entry *de)
+static void _devfs_unregister (struct devfs_entry *dir, struct devfs_entry *de)
{
int unhooked = _devfs_unhook (de);
@@ -1603,34 +1668,30 @@ static void unregister (struct devfs_entry *dir, struct devfs_entry *de)
write_lock (&de->u.dir.lock);
de->u.dir.no_more_additions = TRUE;
child = de->u.dir.first;
- unregister (de, child);
+ VERIFY_ENTRY (child);
+ _devfs_unregister (de, child);
if (!child) break;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_UNREGISTER)
- printk ("%s: unregister(): child->name: \"%s\" child: %p\n",
- DEVFS_NAME, child->name, child);
-#endif
+ DPRINTK (DEBUG_UNREGISTER, "(%s): child: %p refcount: %d\n",
+ child->name, child, atomic_read (&child->refcount) );
devfs_put (child);
}
-} /* End Function unregister */
+} /* End Function _devfs_unregister */
/**
* devfs_unregister - Unregister a device entry.
* @de: A handle previously created by devfs_register() or returned from
- * devfs_find_handle(). If this is %NULL the routine does nothing.
+ * devfs_get_handle(). If this is %NULL the routine does nothing.
*/
void devfs_unregister (devfs_handle_t de)
{
+ VERIFY_ENTRY (de);
if ( (de == NULL) || (de->parent == NULL) ) return;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_UNREGISTER)
- printk ("%s: devfs_unregister(): de->name: \"%s\" de: %p\n",
- DEVFS_NAME, de->name, de);
-#endif
+ DPRINTK (DEBUG_UNREGISTER, "(%s): de: %p refcount: %d\n",
+ de->name, de, atomic_read (&de->refcount) );
write_lock (&de->parent->u.dir.lock);
- unregister (de->parent, de);
+ _devfs_unregister (de->parent, de);
devfs_put (de);
} /* End Function devfs_unregister */
@@ -1646,16 +1707,12 @@ static int devfs_do_symlink (devfs_handle_t dir, const char *name,
if (handle != NULL) *handle = NULL;
if (name == NULL)
{
- printk ("%s: devfs_do_symlink(): NULL name pointer\n", DEVFS_NAME);
+ PRINTK ("(): NULL name pointer\n");
return -EINVAL;
}
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_REGISTER)
- printk ("%s: devfs_do_symlink(%s)\n", DEVFS_NAME, name);
-#endif
if (link == NULL)
{
- printk ("%s: devfs_do_symlink(): NULL link pointer\n", DEVFS_NAME);
+ PRINTK ("(%s): NULL link pointer\n", name);
return -EINVAL;
}
linklength = strlen (link);
@@ -1666,8 +1723,7 @@ static int devfs_do_symlink (devfs_handle_t dir, const char *name,
if ( ( de = _devfs_prepare_leaf (&dir, name, S_IFLNK | S_IRUGO | S_IXUGO) )
== NULL )
{
- printk ("%s: devfs_do_symlink(%s): could not prepare leaf\n",
- DEVFS_NAME, name);
+ PRINTK ("(%s): could not prepare leaf\n", name);
kfree (newlink);
return -ENOTDIR;
}
@@ -1677,8 +1733,7 @@ static int devfs_do_symlink (devfs_handle_t dir, const char *name,
de->u.symlink.length = linklength;
if ( ( err = _devfs_append_entry (dir, de, FALSE, NULL) ) != 0 )
{
- printk ("%s: devfs_do_symlink(%s): could not append to parent, err: %d\n",
- DEVFS_NAME, name, err);
+ PRINTK ("(%s): could not append to parent, err: %d\n", name, err);
devfs_put (dir);
return err;
}
@@ -1713,6 +1768,7 @@ int devfs_mk_symlink (devfs_handle_t dir, const char *name, unsigned int flags,
devfs_handle_t de;
if (handle != NULL) *handle = NULL;
+ DPRINTK (DEBUG_REGISTER, "(%s)\n", name);
err = devfs_do_symlink (dir, name, flags, link, &de, info);
if (err) return err;
if (handle != NULL) *handle = de;
@@ -1738,39 +1794,47 @@ int devfs_mk_symlink (devfs_handle_t dir, const char *name, unsigned int flags,
devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name, void *info)
{
int err;
- struct devfs_entry *de;
+ struct devfs_entry *de, *old;
if (name == NULL)
{
- printk ("%s: devfs_mk_dir(): NULL name pointer\n", DEVFS_NAME);
+ PRINTK ("(): NULL name pointer\n");
return NULL;
}
if ( ( de = _devfs_prepare_leaf (&dir, name, MODE_DIR) ) == NULL )
{
- printk ("%s: devfs_mk_dir(%s): could not prepare leaf\n",
- DEVFS_NAME, name);
+ PRINTK ("(%s): could not prepare leaf\n", name);
return NULL;
}
de->info = info;
- if ( ( err = _devfs_append_entry (dir, de, FALSE, NULL) ) != 0 )
+ if ( ( err = _devfs_append_entry (dir, de, FALSE, &old) ) != 0 )
{
- printk ("%s: devfs_mk_dir(%s): could not append to dir: %p \"%s\", err: %d\n",
- DEVFS_NAME, name, dir, dir->name, err);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,1)
+ if ( old && S_ISDIR (old->mode) )
+ {
+ PRINTK ("(%s): using old entry in dir: %p \"%s\"\n",
+ name, dir, dir->name);
+ old->vfs_created = FALSE;
+ devfs_put (dir);
+ return old;
+ }
+#endif
+ PRINTK ("(%s): could not append to dir: %p \"%s\", err: %d\n",
+ name, dir, dir->name, err);
+ devfs_put (old);
devfs_put (dir);
return NULL;
}
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_REGISTER)
- printk ("%s: devfs_mk_dir(%s): de: %p dir: %p \"%s\"\n",
- DEVFS_NAME, name, de, dir, dir->name);
-#endif
+ DPRINTK (DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\"\n",
+ name, de, dir, dir->name);
+ devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, 0);
devfs_put (dir);
return de;
} /* End Function devfs_mk_dir */
/**
- * devfs_find_handle - Find the handle of a devfs entry.
+ * devfs_get_handle - Find the handle of a devfs entry.
* @dir: The handle to the parent devfs directory entry. If this is %NULL the
* name is relative to the root of the devfs.
* @name: The name of the entry.
@@ -1782,20 +1846,31 @@ devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name, void *info)
* traversed. Symlinks pointing out of the devfs namespace will cause a
* failure. Symlink traversal consumes stack space.
*
- * Returns a handle which may later be used in a call to devfs_unregister(),
- * devfs_get_flags(), or devfs_set_flags(). On failure %NULL is returned.
+ * Returns a handle which may later be used in a call to
+ * devfs_unregister(), devfs_get_flags(), or devfs_set_flags(). A
+ * subsequent devfs_put() is required to decrement the refcount.
+ * On failure %NULL is returned.
*/
+devfs_handle_t devfs_get_handle (devfs_handle_t dir, const char *name,
+ unsigned int major, unsigned int minor,
+ char type, int traverse_symlinks)
+{
+ if ( (name != NULL) && (name[0] == '\0') ) name = NULL;
+ return _devfs_find_entry (dir, name, major, minor, type,traverse_symlinks);
+} /* End Function devfs_get_handle */
+
+
+/* Compatibility function. Will be removed in sometime in 2.5 */
+
devfs_handle_t devfs_find_handle (devfs_handle_t dir, const char *name,
unsigned int major, unsigned int minor,
char type, int traverse_symlinks)
{
devfs_handle_t de;
- if ( (name != NULL) && (name[0] == '\0') ) name = NULL;
- de = find_entry (dir, name, 0, major, minor, type, traverse_symlinks);
- devfs_put (de); /* FIXME: in 2.5 consider dropping this and require a
- call to devfs_put() */
+ de = devfs_get_handle (dir, name, major, minor, type, traverse_symlinks);
+ devfs_put (de);
return de;
} /* End Function devfs_find_handle */
@@ -1813,6 +1888,7 @@ int devfs_get_flags (devfs_handle_t de, unsigned int *flags)
unsigned int fl = 0;
if (de == NULL) return -EINVAL;
+ VERIFY_ENTRY (de);
if (de->hide) fl |= DEVFS_FL_HIDE;
if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
{
@@ -1836,11 +1912,8 @@ int devfs_get_flags (devfs_handle_t de, unsigned int *flags)
int devfs_set_flags (devfs_handle_t de, unsigned int flags)
{
if (de == NULL) return -EINVAL;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_SET_FLAGS)
- printk ("%s: devfs_set_flags(): de->name: \"%s\"\n",
- DEVFS_NAME, de->name);
-#endif
+ VERIFY_ENTRY (de);
+ DPRINTK (DEBUG_SET_FLAGS, "(%s): flags: %x\n", de->name, flags);
de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE;
if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
{
@@ -1864,6 +1937,7 @@ int devfs_get_maj_min (devfs_handle_t de, unsigned int *major,
unsigned int *minor)
{
if (de == NULL) return -EINVAL;
+ VERIFY_ENTRY (de);
if ( S_ISDIR (de->mode) ) return -EISDIR;
if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) ) return -EINVAL;
if (major != NULL) *major = de->u.fcb.u.device.major;
@@ -1904,6 +1978,7 @@ int devfs_generate_path (devfs_handle_t de, char *path, int buflen)
#define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name )
if (de == NULL) return -EINVAL;
+ VERIFY_ENTRY (de);
if (de->namelen >= buflen) return -ENAMETOOLONG; /* Must be first */
path[buflen - 1] = '\0';
if (de->parent == NULL) return buflen - 1; /* Don't prepend root */
@@ -1925,18 +2000,57 @@ int devfs_generate_path (devfs_handle_t de, char *path, int buflen)
* @de: The handle to the device entry.
*
* Returns a pointer to the device operations on success, else NULL.
+ * The use count for the module owning the operations will be incremented.
*/
void *devfs_get_ops (devfs_handle_t de)
{
+ struct module *owner;
+
if (de == NULL) return NULL;
- if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
- return de->u.fcb.ops;
- return NULL;
+ VERIFY_ENTRY (de);
+ if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) && !S_ISREG (de->mode) )
+ return NULL;
+ if (de->u.fcb.ops == NULL) return NULL;
+ read_lock (&de->parent->u.dir.lock); /* Prevent module from unloading */
+ if (de->next == de) owner = NULL; /* Ops pointer is already stale */
+ else if ( S_ISCHR (de->mode) || S_ISREG (de->mode) )
+ owner = ( (struct file_operations *) de->u.fcb.ops )->owner;
+ else owner = ( (struct block_device_operations *) de->u.fcb.ops )->owner;
+ if ( (de->next == de) || !try_inc_mod_count (owner) )
+ { /* Entry is already unhooked or module is unloading */
+ read_unlock (&de->parent->u.dir.lock);
+ return NULL;
+ }
+ read_unlock (&de->parent->u.dir.lock); /* Module can continue unloading*/
+ return de->u.fcb.ops;
} /* End Function devfs_get_ops */
/**
+ * devfs_put_ops - Put the device operations for a devfs entry.
+ * @de: The handle to the device entry.
+ *
+ * The use count for the module owning the operations will be decremented.
+ */
+
+void devfs_put_ops (devfs_handle_t de)
+{
+ struct module *owner;
+
+ if (de == NULL) return;
+ VERIFY_ENTRY (de);
+ if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) && !S_ISREG (de->mode) )
+ return;
+ if (de->u.fcb.ops == NULL) return;
+ if ( S_ISCHR (de->mode) || S_ISREG (de->mode) )
+ owner = ( (struct file_operations *) de->u.fcb.ops )->owner;
+ else owner = ( (struct block_device_operations *) de->u.fcb.ops )->owner;
+ if (owner) __MOD_DEC_USE_COUNT (owner);
+} /* End Function devfs_put_ops */
+
+
+/**
* devfs_set_file_size - Set the file size for a devfs regular file.
* @de: The handle to the device entry.
* @size: The new file size.
@@ -1947,6 +2061,7 @@ void *devfs_get_ops (devfs_handle_t de)
int devfs_set_file_size (devfs_handle_t de, unsigned long size)
{
if (de == NULL) return -EINVAL;
+ VERIFY_ENTRY (de);
if ( !S_ISREG (de->mode) ) return -EINVAL;
if (de->u.fcb.u.file.size == size) return 0;
de->u.fcb.u.file.size = size;
@@ -1966,6 +2081,7 @@ int devfs_set_file_size (devfs_handle_t de, unsigned long size)
void *devfs_get_info (devfs_handle_t de)
{
if (de == NULL) return NULL;
+ VERIFY_ENTRY (de);
return de->info;
} /* End Function devfs_get_info */
@@ -1980,6 +2096,7 @@ void *devfs_get_info (devfs_handle_t de)
int devfs_set_info (devfs_handle_t de, void *info)
{
if (de == NULL) return -EINVAL;
+ VERIFY_ENTRY (de);
de->info = info;
return 0;
} /* End Function devfs_set_info */
@@ -1994,6 +2111,7 @@ int devfs_set_info (devfs_handle_t de, void *info)
devfs_handle_t devfs_get_parent (devfs_handle_t de)
{
if (de == NULL) return NULL;
+ VERIFY_ENTRY (de);
return de->parent;
} /* End Function devfs_get_parent */
@@ -2008,6 +2126,7 @@ devfs_handle_t devfs_get_parent (devfs_handle_t de)
devfs_handle_t devfs_get_first_child (devfs_handle_t de)
{
if (de == NULL) return NULL;
+ VERIFY_ENTRY (de);
if ( !S_ISDIR (de->mode) ) return NULL;
return de->u.dir.first;
} /* End Function devfs_get_first_child */
@@ -2023,6 +2142,7 @@ devfs_handle_t devfs_get_first_child (devfs_handle_t de)
devfs_handle_t devfs_get_next_sibling (devfs_handle_t de)
{
if (de == NULL) return NULL;
+ VERIFY_ENTRY (de);
return de->next;
} /* End Function devfs_get_next_sibling */
@@ -2038,14 +2158,15 @@ devfs_handle_t devfs_get_next_sibling (devfs_handle_t de)
void devfs_auto_unregister (devfs_handle_t master, devfs_handle_t slave)
{
if (master == NULL) return;
+ VERIFY_ENTRY (master);
+ VERIFY_ENTRY (slave);
if (master->slave != NULL)
{
/* Because of the dumbness of the layers above, ignore duplicates */
if (master->slave == slave) return;
- printk ("%s: devfs_auto_unregister(): only one slave allowed\n",
- DEVFS_NAME);
- OOPS (" master: \"%s\" old slave: \"%s\" new slave: \"%s\"\n",
- master->name, master->slave->name, slave->name);
+ PRINTK ("(%s): only one slave allowed\n", master->name);
+ OOPS ("(): old slave: \"%s\" new slave: \"%s\"\n",
+ master->slave->name, slave->name);
}
master->slave = slave;
} /* End Function devfs_auto_unregister */
@@ -2061,6 +2182,7 @@ void devfs_auto_unregister (devfs_handle_t master, devfs_handle_t slave)
devfs_handle_t devfs_get_unregister_slave (devfs_handle_t master)
{
if (master == NULL) return NULL;
+ VERIFY_ENTRY (master);
return master->slave;
} /* End Function devfs_get_unregister_slave */
@@ -2076,6 +2198,7 @@ devfs_handle_t devfs_get_unregister_slave (devfs_handle_t master)
const char *devfs_get_name (devfs_handle_t de, unsigned int *namelen)
{
if (de == NULL) return NULL;
+ VERIFY_ENTRY (de);
if (namelen != NULL) *namelen = de->namelen;
return de->name;
} /* End Function devfs_get_name */
@@ -2218,10 +2341,12 @@ static int __init devfs_setup (char *str)
__setup("devfs=", devfs_setup);
+EXPORT_SYMBOL(devfs_put);
EXPORT_SYMBOL(devfs_register);
EXPORT_SYMBOL(devfs_unregister);
EXPORT_SYMBOL(devfs_mk_symlink);
EXPORT_SYMBOL(devfs_mk_dir);
+EXPORT_SYMBOL(devfs_get_handle);
EXPORT_SYMBOL(devfs_find_handle);
EXPORT_SYMBOL(devfs_get_flags);
EXPORT_SYMBOL(devfs_set_flags);
@@ -2268,8 +2393,9 @@ static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info,
buf->parent = parent;
buf->namelen = namelen;
buf->u.name = name;
+ WRITE_ENTRY_MAGIC (buf, MAGIC_VALUE);
if ( !devfsd_notify_de (buf, DEVFSD_NOTIFY_LOOKUP, 0,
- current->euid, current->egid, fs_info) )
+ current->euid, current->egid, fs_info, 0) )
return -ENOENT;
/* Possible success */
return 0;
@@ -2286,14 +2412,17 @@ static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info,
static int check_disc_changed (struct devfs_entry *de)
{
int tmp;
- kdev_t dev = MKDEV (de->u.fcb.u.device.major, de->u.fcb.u.device.minor);
- struct block_device_operations *bdops = de->u.fcb.ops;
+ int retval = 0;
+ kdev_t dev = mk_kdev(de->u.fcb.u.device.major, de->u.fcb.u.device.minor);
+ struct block_device_operations *bdops;
extern int warn_no_part;
if ( !S_ISBLK (de->mode) ) return 0;
- if (bdops == NULL) return 0;
- if (bdops->check_media_change == NULL) return 0;
- if ( !bdops->check_media_change (dev) ) return 0;
+ bdops = devfs_get_ops (de);
+ if (!bdops) return 0;
+ if (bdops->check_media_change == NULL) goto out;
+ if ( !bdops->check_media_change (dev) ) goto out;
+ retval = 1;
printk ( KERN_DEBUG "VFS: Disk change detected on device %s\n",
kdevname (dev) );
if (invalidate_device(dev, 0))
@@ -2303,7 +2432,9 @@ static int check_disc_changed (struct devfs_entry *de)
warn_no_part = 0;
if (bdops->revalidate) bdops->revalidate (dev);
warn_no_part = tmp;
- return 1;
+out:
+ devfs_put_ops (de);
+ return retval;
} /* End Function check_disc_changed */
@@ -2375,16 +2506,10 @@ static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr)
if (retval != 0) return retval;
retval = inode_setattr (inode, iattr);
if (retval != 0) return retval;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_CHANGE)
- {
- printk ("%s: notify_change(%d): VFS inode: %p devfs_entry: %p\n",
- DEVFS_NAME, (int) inode->i_ino, inode, de);
- printk ("%s: mode: 0%o uid: %d gid: %d\n",
- DEVFS_NAME, (int) inode->i_mode,
- (int) inode->i_uid, (int) inode->i_gid);
- }
-#endif
+ DPRINTK (DEBUG_I_CHANGE, "(%d): VFS inode: %p devfs_entry: %p\n",
+ (int) inode->i_ino, inode, de);
+ DPRINTK (DEBUG_I_CHANGE, "(): mode: 0%o uid: %d gid: %d\n",
+ (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid);
/* Inode is not on hash chains, thus must save permissions here rather
than in a write_inode() method */
if ( ( !S_ISREG (inode->i_mode) && !S_ISCHR (inode->i_mode) &&
@@ -2397,16 +2522,17 @@ static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr)
de->inode.atime = inode->i_atime;
de->inode.mtime = inode->i_mtime;
de->inode.ctime = inode->i_ctime;
- if ( iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID) )
+ if ( ( iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID) ) &&
+ !is_devfsd_or_child (fs_info) )
devfsd_notify_de (de, DEVFSD_NOTIFY_CHANGE, inode->i_mode,
- inode->i_uid, inode->i_gid, fs_info);
+ inode->i_uid, inode->i_gid, fs_info, 0);
return 0;
} /* End Function devfs_notify_change */
static int devfs_statfs (struct super_block *sb, struct statfs *buf)
{
buf->f_type = DEVFS_SUPER_MAGIC;
- buf->f_bsize = PAGE_SIZE / sizeof (long);
+ buf->f_bsize = FAKE_BLOCK_SIZE;
buf->f_bfree = 0;
buf->f_bavail = 0;
buf->f_ffree = 0;
@@ -2428,7 +2554,7 @@ static struct super_operations devfs_sops =
/**
- * get_vfs_inode - Get a VFS inode.
+ * _devfs_get_vfs_inode - Get a VFS inode.
* @sb: The super block.
* @de: The devfs inode.
* @dentry: The dentry to register with the devfs inode.
@@ -2437,9 +2563,9 @@ static struct super_operations devfs_sops =
* performed if the inode is created.
*/
-static struct inode *get_vfs_inode (struct super_block *sb,
- struct devfs_entry *de,
- struct dentry *dentry)
+static struct inode *_devfs_get_vfs_inode (struct super_block *sb,
+ struct devfs_entry *de,
+ struct dentry *dentry)
{
int is_fcb = FALSE;
struct inode *inode;
@@ -2447,8 +2573,7 @@ static struct inode *get_vfs_inode (struct super_block *sb,
if (de->prev == de) return NULL; /* Quick check to see if unhooked */
if ( ( inode = new_inode (sb) ) == NULL )
{
- printk ("%s: get_vfs_inode(%s): new_inode() failed, de: %p\n",
- DEVFS_NAME, de->name, de);
+ PRINTK ("(%s): new_inode() failed, de: %p\n", de->name, de);
return NULL;
}
if (de->parent)
@@ -2465,34 +2590,30 @@ static struct inode *get_vfs_inode (struct super_block *sb,
}
inode->u.generic_ip = devfs_get (de);
inode->i_ino = de->inode.ino;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_GET)
- printk ("%s: get_vfs_inode(%d): VFS inode: %p devfs_entry: %p\n",
- DEVFS_NAME, (int) inode->i_ino, inode, de);
-#endif
+ DPRINTK (DEBUG_I_GET, "(%d): VFS inode: %p devfs_entry: %p\n",
+ (int) inode->i_ino, inode, de);
inode->i_blocks = 0;
- inode->i_blksize = 1024;
+ inode->i_blksize = FAKE_BLOCK_SIZE;
inode->i_op = &devfs_iops;
inode->i_fop = &devfs_fops;
inode->i_rdev = NODEV;
if ( S_ISCHR (de->mode) )
{
- inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
+ inode->i_rdev = mk_kdev(de->u.fcb.u.device.major,
de->u.fcb.u.device.minor);
inode->i_cdev = cdget ( kdev_t_to_nr (inode->i_rdev) );
is_fcb = TRUE;
}
else if ( S_ISBLK (de->mode) )
{
- inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
+ inode->i_rdev = mk_kdev(de->u.fcb.u.device.major,
de->u.fcb.u.device.minor);
if (bd_acquire (inode) == 0)
{
if (!inode->i_bdev->bd_op && de->u.fcb.ops)
inode->i_bdev->bd_op = de->u.fcb.ops;
}
- else printk ("%s: get_vfs_inode(%d): no block device from bdget()\n",
- DEVFS_NAME, (int) inode->i_ino);
+ else PRINTK ("(%d): no block device from bdget()\n",(int)inode->i_ino);
is_fcb = TRUE;
}
else if ( S_ISFIFO (de->mode) ) inode->i_fop = &def_fifo_fops;
@@ -2519,14 +2640,10 @@ static struct inode *get_vfs_inode (struct super_block *sb,
inode->i_atime = de->inode.atime;
inode->i_mtime = de->inode.mtime;
inode->i_ctime = de->inode.ctime;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_GET)
- printk ("%s: mode: 0%o uid: %d gid: %d\n",
- DEVFS_NAME, (int) inode->i_mode,
- (int) inode->i_uid, (int) inode->i_gid);
-#endif
+ DPRINTK (DEBUG_I_GET, "(): mode: 0%o uid: %d gid: %d\n",
+ (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid);
return inode;
-} /* End Function get_vfs_inode */
+} /* End Function _devfs_get_vfs_inode */
/* File operations for device entries follow */
@@ -2542,11 +2659,8 @@ static int devfs_readdir (struct file *file, void *dirent, filldir_t filldir)
fs_info = inode->i_sb->u.generic_sbp;
parent = get_devfs_entry_from_vfs_inode (file->f_dentry->d_inode);
if ( (long) file->f_pos < 0 ) return -EINVAL;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_F_READDIR)
- printk ("%s: readdir(): fs_info: %p pos: %ld\n", DEVFS_NAME,
- fs_info, (long) file->f_pos);
-#endif
+ DPRINTK (DEBUG_F_READDIR, "(%s): fs_info: %p pos: %ld\n",
+ parent->name, fs_info, (long) file->f_pos);
switch ( (long) file->f_pos )
{
case 0:
@@ -2637,9 +2751,9 @@ static int devfs_open (struct inode *inode, struct file *file)
inode->i_uid = current->euid;
inode->i_gid = current->egid;
}
- if (df->aopen_notify)
+ if ( df->aopen_notify && !is_devfsd_or_child (fs_info) )
devfsd_notify_de (de, DEVFSD_NOTIFY_ASYNC_OPEN, inode->i_mode,
- current->euid, current->egid, fs_info);
+ current->euid, current->egid, fs_info, 0);
return 0;
} /* End Function devfs_open */
@@ -2666,13 +2780,7 @@ static struct file_operations devfs_dir_fops =
static void devfs_d_release (struct dentry *dentry)
{
-#ifdef CONFIG_DEVFS_DEBUG
- struct inode *inode = dentry->d_inode;
-
- if (devfs_debug & DEBUG_D_RELEASE)
- printk ("%s: d_release(): dentry: %p inode: %p\n",
- DEVFS_NAME, dentry, inode);
-#endif
+ DPRINTK (DEBUG_D_RELEASE, "(%p): inode: %p\n", dentry, dentry->d_inode);
} /* End Function devfs_d_release */
/**
@@ -2686,14 +2794,11 @@ static void devfs_d_iput (struct dentry *dentry, struct inode *inode)
struct devfs_entry *de;
de = get_devfs_entry_from_vfs_inode (inode);
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_D_IPUT)
- printk ("%s: d_iput(): dentry: %p inode: %p de: %p de->dentry: %p\n",
- DEVFS_NAME, dentry, inode, de, de->inode.dentry);
-#endif
+ DPRINTK (DEBUG_D_IPUT,"(%s): dentry: %p inode: %p de: %p de->dentry: %p\n",
+ de->name, dentry, inode, de, de->inode.dentry);
if ( de->inode.dentry && (de->inode.dentry != dentry) )
- OOPS ("%s: d_iput(%s): de: %p dentry: %p de->dentry: %p\n",
- DEVFS_NAME, de->name, de, dentry, de->inode.dentry);
+ OOPS ("(%s): de: %p dentry: %p de->dentry: %p\n",
+ de->name, de, dentry, de->inode.dentry);
de->inode.dentry = NULL;
iput (inode);
devfs_put (de);
@@ -2733,20 +2838,13 @@ static int devfs_d_delete (struct dentry *dentry)
/* Unhash dentry if negative (has no inode) */
if (inode == NULL)
{
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_D_DELETE)
- printk ("%s: d_delete(): dropping negative dentry: %p\n",
- DEVFS_NAME, dentry);
-#endif
+ DPRINTK (DEBUG_D_DELETE, "(%p): dropping negative dentry\n", dentry);
return 1;
}
fs_info = inode->i_sb->u.generic_sbp;
de = get_devfs_entry_from_vfs_inode (inode);
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_D_DELETE)
- printk ("%s: d_delete(): dentry: %p inode: %p devfs_entry: %p\n",
- DEVFS_NAME, dentry, inode, de);
-#endif
+ DPRINTK (DEBUG_D_DELETE, "(%p): inode: %p devfs_entry: %p\n",
+ dentry, inode, de);
if (de == NULL) return 0;
if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) && !S_ISREG (de->mode) )
return 0;
@@ -2754,7 +2852,7 @@ static int devfs_d_delete (struct dentry *dentry)
de->u.fcb.open = FALSE;
if (de->u.fcb.aopen_notify)
devfsd_notify_de (de, DEVFSD_NOTIFY_CLOSE, inode->i_mode,
- current->euid, current->egid, fs_info);
+ current->euid, current->egid, fs_info, 1);
if (!de->u.fcb.auto_owner) return 0;
/* Change the ownership/protection back */
inode->i_mode = (de->mode & S_IFMT) | S_IRUGO | S_IWUGO;
@@ -2774,25 +2872,19 @@ static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
devfs_handle_t parent = get_devfs_entry_from_vfs_inode (dir);
struct inode *inode;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_LOOKUP)
- printk ("%s: d_revalidate(%s): dentry: %p by: \"%s\"\n",
- DEVFS_NAME, dentry->d_name.name, dentry, current->comm);
-#endif
+ DPRINTK (DEBUG_I_LOOKUP, "(%s): dentry: %p by: \"%s\"\n",
+ dentry->d_name.name, dentry, current->comm);
read_lock (&parent->u.dir.lock);
de = _devfs_search_dir (parent, dentry->d_name.name,
dentry->d_name.len);
- read_lock (&parent->u.dir.lock);
+ read_unlock (&parent->u.dir.lock);
if (de == NULL) return 1;
/* Create an inode, now that the driver information is available */
- inode = get_vfs_inode (dir->i_sb, de, dentry);
+ inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry);
devfs_put (de);
if (!inode) return 1;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_LOOKUP)
- printk ("%s: d_revalidate(): new VFS inode(%u): %p devfs_entry: %p\n",
- DEVFS_NAME, de->inode.ino, inode, de);
-#endif
+ DPRINTK (DEBUG_I_LOOKUP, "(%s): new VFS inode(%u): %p de: %p\n",
+ de->name, de->inode.ino, inode, de);
d_instantiate (dentry, inode);
return 1;
}
@@ -2805,21 +2897,17 @@ static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
{
- struct fs_info *fs_info;
+ struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
struct devfs_entry *parent, *de;
struct inode *inode;
/* Set up the dentry operations before anything else, to ensure cleaning
up on any error */
dentry->d_op = &devfs_dops;
- fs_info = dir->i_sb->u.generic_sbp;
/* First try to get the devfs entry for this directory */
parent = get_devfs_entry_from_vfs_inode (dir);
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_LOOKUP)
- printk ("%s: lookup(%s): dentry: %p parent: %p by: \"%s\"\n",
- DEVFS_NAME, dentry->d_name.name, dentry, parent,current->comm);
-#endif
+ DPRINTK (DEBUG_I_LOOKUP, "(%s): dentry: %p parent: %p by: \"%s\"\n",
+ dentry->d_name.name, dentry, parent, current->comm);
if (parent == NULL) return ERR_PTR (-ENOENT);
read_lock (&parent->u.dir.lock);
de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len);
@@ -2872,14 +2960,11 @@ static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
d_add (dentry, NULL); /* Open the floodgates */
}
/* Create an inode, now that the driver information is available */
- inode = get_vfs_inode (dir->i_sb, de, dentry);
+ inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry);
devfs_put (de);
if (!inode) return ERR_PTR (-ENOMEM);
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_LOOKUP)
- printk ("%s: lookup(): new VFS inode(%u): %p devfs_entry: %p\n",
- DEVFS_NAME, de->inode.ino, inode, de);
-#endif
+ DPRINTK (DEBUG_I_LOOKUP, "(%s): new VFS inode(%u): %p de: %p\n",
+ de->name, de->inode.ino, inode, de);
d_instantiate (dentry, inode);
if (dentry->d_op == &devfs_wait_dops)
{ /* Unlock directory semaphore, which will release any waiters. They
@@ -2897,20 +2982,19 @@ static int devfs_unlink (struct inode *dir, struct dentry *dentry)
int unhooked;
struct devfs_entry *de;
struct inode *inode = dentry->d_inode;
+ struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_UNLINK)
- printk ("%s: unlink(%s)\n", DEVFS_NAME, dentry->d_name.name);
-#endif
de = get_devfs_entry_from_vfs_inode (inode);
+ DPRINTK (DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de);
if (de == NULL) return -ENOENT;
if (!de->vfs_created) return -EPERM;
write_lock (&de->parent->u.dir.lock);
unhooked = _devfs_unhook (de);
write_unlock (&de->parent->u.dir.lock);
if (!unhooked) return -ENOENT;
- devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
- inode->i_uid, inode->i_gid, dir->i_sb->u.generic_sbp);
+ if ( !is_devfsd_or_child (fs_info) )
+ devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
+ inode->i_uid, inode->i_gid, fs_info, 0);
free_dentry (de);
devfs_put (de);
return 0;
@@ -2920,21 +3004,17 @@ static int devfs_symlink (struct inode *dir, struct dentry *dentry,
const char *symname)
{
int err;
- struct fs_info *fs_info;
+ struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
struct devfs_entry *parent, *de;
struct inode *inode;
- fs_info = dir->i_sb->u.generic_sbp;
/* First try to get the devfs entry for this directory */
parent = get_devfs_entry_from_vfs_inode (dir);
if (parent == NULL) return -ENOENT;
err = devfs_do_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE,
symname, &de, NULL);
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_DISABLED)
- printk ("%s: symlink(): errcode from <devfs_do_symlink>: %d\n",
- DEVFS_NAME, err);
-#endif
+ DPRINTK (DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n",
+ dentry->d_name.name, err);
if (err < 0) return err;
de->vfs_created = TRUE;
de->inode.uid = current->euid;
@@ -2942,28 +3022,25 @@ static int devfs_symlink (struct inode *dir, struct dentry *dentry,
de->inode.atime = CURRENT_TIME;
de->inode.mtime = CURRENT_TIME;
de->inode.ctime = CURRENT_TIME;
- if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
+ if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
return -ENOMEM;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_DISABLED)
- printk ("%s: symlink(): new VFS inode(%u): %p dentry: %p\n",
- DEVFS_NAME, de->inode.ino, inode, dentry);
-#endif
+ DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n",
+ dentry->d_name.name, de->inode.ino, inode, dentry);
d_instantiate (dentry, inode);
- devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
- inode->i_uid, inode->i_gid, fs_info);
+ if ( !is_devfsd_or_child (fs_info) )
+ devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
+ inode->i_uid, inode->i_gid, fs_info, 0);
return 0;
} /* End Function devfs_symlink */
static int devfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
{
int err;
- struct fs_info *fs_info;
+ struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
struct devfs_entry *parent, *de;
struct inode *inode;
mode = (mode & ~S_IFMT) | S_IFDIR; /* VFS doesn't pass S_IFMT part */
- fs_info = dir->i_sb->u.generic_sbp;
parent = get_devfs_entry_from_vfs_inode (dir);
if (parent == NULL) return -ENOENT;
de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
@@ -2976,16 +3053,14 @@ static int devfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
de->inode.atime = CURRENT_TIME;
de->inode.mtime = CURRENT_TIME;
de->inode.ctime = CURRENT_TIME;
- if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
+ if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
return -ENOMEM;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_DISABLED)
- printk ("%s: mkdir(): new VFS inode(%u): %p dentry: %p\n",
- DEVFS_NAME, de->inode.ino, inode, dentry);
-#endif
+ DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n",
+ dentry->d_name.name, de->inode.ino, inode, dentry);
d_instantiate (dentry, inode);
- devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
- inode->i_uid, inode->i_gid, fs_info);
+ if ( !is_devfsd_or_child (fs_info) )
+ devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
+ inode->i_uid, inode->i_gid, fs_info, 0);
return 0;
} /* End Function devfs_mkdir */
@@ -2993,11 +3068,10 @@ static int devfs_rmdir (struct inode *dir, struct dentry *dentry)
{
int err = 0;
struct devfs_entry *de;
- struct fs_info *fs_info;
+ struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
struct inode *inode = dentry->d_inode;
if (dir->i_sb->u.generic_sbp != inode->i_sb->u.generic_sbp) return -EINVAL;
- fs_info = dir->i_sb->u.generic_sbp;
de = get_devfs_entry_from_vfs_inode (inode);
if (de == NULL) return -ENOENT;
if ( !S_ISDIR (de->mode) ) return -ENOTDIR;
@@ -3013,8 +3087,9 @@ static int devfs_rmdir (struct inode *dir, struct dentry *dentry)
if ( !_devfs_unhook (de) ) err = -ENOENT;
write_unlock (&de->parent->u.dir.lock);
if (err) return err;
- devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
- inode->i_uid, inode->i_gid, fs_info);
+ if ( !is_devfsd_or_child (fs_info) )
+ devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
+ inode->i_uid, inode->i_gid, fs_info, 0);
free_dentry (de);
devfs_put (de);
return 0;
@@ -3024,16 +3099,12 @@ static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
int rdev)
{
int err;
- struct fs_info *fs_info;
+ struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
struct devfs_entry *parent, *de;
struct inode *inode;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_MKNOD)
- printk ("%s: mknod(%s): mode: 0%o dev: %d\n",
- DEVFS_NAME, dentry->d_name.name, mode, rdev);
-#endif
- fs_info = dir->i_sb->u.generic_sbp;
+ DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %d\n",
+ dentry->d_name.name, mode, rdev);
parent = get_devfs_entry_from_vfs_inode (dir);
if (parent == NULL) return -ENOENT;
de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
@@ -3051,16 +3122,14 @@ static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
de->inode.atime = CURRENT_TIME;
de->inode.mtime = CURRENT_TIME;
de->inode.ctime = CURRENT_TIME;
- if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
+ if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
return -ENOMEM;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_I_MKNOD)
- printk ("%s: new VFS inode(%u): %p dentry: %p\n",
- DEVFS_NAME, de->inode.ino, inode, dentry);
-#endif
+ DPRINTK (DEBUG_I_MKNOD, ": new VFS inode(%u): %p dentry: %p\n",
+ de->inode.ino, inode, dentry);
d_instantiate (dentry, inode);
- devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
- inode->i_uid, inode->i_gid, fs_info);
+ if ( !is_devfsd_or_child (fs_info) )
+ devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
+ inode->i_uid, inode->i_gid, fs_info, 0);
return 0;
} /* End Function devfs_mknod */
@@ -3124,15 +3193,11 @@ static struct super_block *devfs_read_super (struct super_block *sb,
sb->s_blocksize_bits = 10;
sb->s_magic = DEVFS_SUPER_MAGIC;
sb->s_op = &devfs_sops;
- if ( ( root_inode = get_vfs_inode (sb, root_entry, NULL) ) == NULL )
+ if ( ( root_inode = _devfs_get_vfs_inode (sb, root_entry, NULL) ) == NULL )
goto out_no_root;
sb->s_root = d_alloc_root (root_inode);
if (!sb->s_root) goto out_no_root;
-#ifdef CONFIG_DEVFS_DEBUG
- if (devfs_debug & DEBUG_S_READ)
- printk ("%s: read super, made devfs ptr: %p\n",
- DEVFS_NAME, sb->u.generic_sbp);
-#endif
+ DPRINTK (DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->u.generic_sbp);
return sb;
out_no_root:
@@ -3233,11 +3298,17 @@ static ssize_t devfsd_read (struct file *file, char *buf, size_t len,
tlen = rpos - *ppos;
if (done)
{
+ devfs_handle_t parent;
+
spin_lock (&fs_info->devfsd_buffer_lock);
fs_info->devfsd_first_event = entry->next;
if (entry->next == NULL) fs_info->devfsd_last_event = NULL;
spin_unlock (&fs_info->devfsd_buffer_lock);
- for (; de != NULL; de = de->parent) devfs_put (de);
+ for (; de != NULL; de = parent)
+ {
+ parent = de->parent;
+ devfs_put (de);
+ }
kmem_cache_free (devfsd_buf_cache, entry);
if (ival > 0) atomic_sub (ival, &fs_info->devfsd_overrun_count);
*ppos = 0;
@@ -3274,6 +3345,8 @@ static int devfsd_ioctl (struct inode *inode, struct file *file,
}
fs_info->devfsd_task = current;
spin_unlock (&lock);
+ fs_info->devfsd_pgrp = (current->pgrp == current->pid) ?
+ current->pgrp : 0;
fs_info->devfsd_file = file;
fs_info->devfsd_info = kmalloc (sizeof *fs_info->devfsd_info,
GFP_KERNEL);
@@ -3304,7 +3377,7 @@ static int devfsd_ioctl (struct inode *inode, struct file *file,
static int devfsd_close (struct inode *inode, struct file *file)
{
- struct devfsd_buf_entry *entry;
+ struct devfsd_buf_entry *entry, *next;
struct fs_info *fs_info = inode->i_sb->u.generic_sbp;
if (fs_info->devfsd_file != file) return 0;
@@ -3320,10 +3393,14 @@ static int devfsd_close (struct inode *inode, struct file *file)
fs_info->devfsd_info = NULL;
}
spin_unlock (&fs_info->devfsd_buffer_lock);
+ fs_info->devfsd_pgrp = 0;
fs_info->devfsd_task = NULL;
wake_up (&fs_info->revalidate_wait_queue);
- for (; entry; entry = entry->next)
+ for (; entry; entry = next)
+ {
+ next = entry->next;
kmem_cache_free (devfsd_buf_cache, entry);
+ }
return 0;
} /* End Function devfsd_close */
@@ -3353,14 +3430,15 @@ static int __init init_devfs_fs (void)
printk ("%s: v%s Richard Gooch (rgooch@atnf.csiro.au)\n",
DEVFS_NAME, DEVFS_VERSION);
+ devfsd_buf_cache = kmem_cache_create ("devfsd_event",
+ sizeof (struct devfsd_buf_entry),
+ 0, 0, NULL, NULL);
+ if (!devfsd_buf_cache) OOPS ("(): unable to allocate event slab\n");
#ifdef CONFIG_DEVFS_DEBUG
devfs_debug = devfs_debug_init;
printk ("%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
#endif
printk ("%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
- devfsd_buf_cache = kmem_cache_create ("devfsd_event",
- sizeof (struct devfsd_buf_entry),
- 0, 0, NULL, NULL);
err = register_filesystem (&devfs_fs_type);
if (!err)
{
diff --git a/fs/devfs/util.c b/fs/devfs/util.c
index db9658b8f..84f797d28 100644
--- a/fs/devfs/util.c
+++ b/fs/devfs/util.c
@@ -61,67 +61,6 @@
/* Private functions follow */
/**
- * _devfs_convert_name - Convert from an old style location-based name to new style.
- * @new: The new name will be written here.
- * @old: The old name.
- * @disc: If true, disc partitioning information should be processed.
- */
-
-static void __init _devfs_convert_name (char *new, const char *old, int disc)
-{
- int host, bus, target, lun;
- char *ptr;
- char part[8];
-
- /* Decode "c#b#t#u#" */
- if (old[0] != 'c') return;
- host = simple_strtol (old + 1, &ptr, 10);
- if (ptr[0] != 'b') return;
- bus = simple_strtol (ptr + 1, &ptr, 10);
- if (ptr[0] != 't') return;
- target = simple_strtol (ptr + 1, &ptr, 10);
- if (ptr[0] != 'u') return;
- lun = simple_strtol (ptr + 1, &ptr, 10);
- if (disc)
- {
- /* Decode "p#" */
- if (ptr[0] == 'p') sprintf (part, "part%s", ptr + 1);
- else strcpy (part, "disc");
- }
- else part[0] = '\0';
- sprintf (new, "/host%d/bus%d/target%d/lun%d/%s",
- host, bus, target, lun, part);
-} /* End Function _devfs_convert_name */
-
-
-/* Public functions follow */
-
-/**
- * devfs_make_root - Create the root FS device entry if required.
- * @name: The name of the root FS device, as passed by "root=".
- */
-
-void __init devfs_make_root (const char *name)
-{
- char dest[64];
-
- if ( (strncmp (name, "sd/", 3) == 0) || (strncmp (name, "sr/", 3) == 0) )
- {
- strcpy (dest, "../scsi");
- _devfs_convert_name (dest + 7, name + 3, (name[1] == 'd') ? 1 : 0);
- }
- else if ( (strncmp (name, "ide/hd/", 7) == 0) ||
- (strncmp (name, "ide/cd/", 7) == 0) )
- {
- strcpy (dest, "..");
- _devfs_convert_name (dest + 2, name + 7, (name[4] == 'h') ? 1 : 0);
- }
- else return;
- devfs_mk_symlink (NULL, name, DEVFS_FL_DEFAULT, dest, NULL, NULL);
-} /* End Function devfs_make_root */
-
-
-/**
* devfs_register_tape - Register a tape device in the "/dev/tapes" hierarchy.
* @de: Any tape device entry in the device directory.
*/
@@ -328,7 +267,7 @@ kdev_t devfs_alloc_devnum (char type)
if (minor >= 256) continue;
__set_bit (minor, entry->bits);
up (semaphore);
- return MKDEV (entry->major, minor);
+ return mk_kdev(entry->major, minor);
}
/* Need to allocate a new major */
if ( ( entry = kmalloc (sizeof *entry, GFP_KERNEL) ) == NULL )
@@ -350,7 +289,7 @@ kdev_t devfs_alloc_devnum (char type)
else list->last->next = entry;
list->last = entry;
up (semaphore);
- return MKDEV (entry->major, 0);
+ return mk_kdev(entry->major, 0);
} /* End Function devfs_alloc_devnum */
EXPORT_SYMBOL(devfs_alloc_devnum);
@@ -370,7 +309,7 @@ void devfs_dealloc_devnum (char type, kdev_t devnum)
struct device_list *list;
struct minor_list *entry;
- if (devnum == NODEV) return;
+ if (kdev_none(devnum)) return;
if (type == DEVFS_SPECIAL_CHR)
{
semaphore = &char_semaphore;
@@ -381,8 +320,8 @@ void devfs_dealloc_devnum (char type, kdev_t devnum)
semaphore = &block_semaphore;
list = &block_list;
}
- major = MAJOR (devnum);
- minor = MINOR (devnum);
+ major = major (devnum);
+ minor = minor (devnum);
down (semaphore);
for (entry = list->first; entry != NULL; entry = entry->next)
{
diff --git a/fs/devices.c b/fs/devices.c
index 3b4448e8d..e859ba71d 100644
--- a/fs/devices.c
+++ b/fs/devices.c
@@ -27,7 +27,7 @@
/* serial module kmod load support */
struct tty_driver *get_tty_driver(kdev_t device);
#define isa_tty_dev(ma) (ma == TTY_MAJOR || ma == TTYAUX_MAJOR)
-#define need_serial(ma,mi) (get_tty_driver(MKDEV(ma,mi)) == NULL)
+#define need_serial(ma,mi) (get_tty_driver(mk_kdev(ma,mi)) == NULL)
#endif
struct device_struct {
@@ -145,7 +145,7 @@ int chrdev_open(struct inode * inode, struct file * filp)
{
int ret = -ENODEV;
- filp->f_op = get_chrfops(MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
+ filp->f_op = get_chrfops(major(inode->i_rdev), minor(inode->i_rdev));
if (filp->f_op) {
ret = 0;
if (filp->f_op->open != NULL) {
@@ -173,18 +173,18 @@ static struct file_operations def_chr_fops = {
const char * kdevname(kdev_t dev)
{
static char buffer[32];
- sprintf(buffer, "%02x:%02x", MAJOR(dev), MINOR(dev));
+ sprintf(buffer, "%02x:%02x", major(dev), minor(dev));
return buffer;
}
const char * cdevname(kdev_t dev)
{
static char buffer[32];
- const char * name = chrdevs[MAJOR(dev)].name;
+ const char * name = chrdevs[major(dev)].name;
if (!name)
name = "unknown-char";
- sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
+ sprintf(buffer, "%s(%d,%d)", name, major(dev), minor(dev));
return buffer;
}
diff --git a/fs/dquot.c b/fs/dquot.c
index b90fe6146..a9a697a0a 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -136,14 +136,14 @@ static inline char sb_has_quota_enabled(struct super_block *sb, short type)
return is_enabled(sb_dqopt(sb), type);
}
-static inline int const hashfn(kdev_t dev, unsigned int id, short type)
+static inline int const hashfn(struct super_block *sb, unsigned int id, short type)
{
- return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
+ return((HASHDEV(sb->s_dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
}
static inline void insert_dquot_hash(struct dquot *dquot)
{
- struct list_head *head = dquot_hash + hashfn(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
+ struct list_head *head = dquot_hash + hashfn(dquot->dq_sb, dquot->dq_id, dquot->dq_type);
list_add(&dquot->dq_hash, head);
}
@@ -153,14 +153,14 @@ static inline void remove_dquot_hash(struct dquot *dquot)
INIT_LIST_HEAD(&dquot->dq_hash);
}
-static inline struct dquot *find_dquot(unsigned int hashent, kdev_t dev, unsigned int id, short type)
+static inline struct dquot *find_dquot(unsigned int hashent, struct super_block *sb, unsigned int id, short type)
{
struct list_head *head;
struct dquot *dquot;
for (head = dquot_hash[hashent].next; head != dquot_hash+hashent; head = head->next) {
dquot = list_entry(head, struct dquot, dq_hash);
- if (dquot->dq_dev == dev && dquot->dq_id == id && dquot->dq_type == type)
+ if (dquot->dq_sb == sb && dquot->dq_id == id && dquot->dq_type == type)
return dquot;
}
return NODQUOT;
@@ -289,7 +289,7 @@ static void write_dquot(struct dquot *dquot)
sizeof(struct dqblk), &offset);
if (ret != sizeof(struct dqblk))
printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
- kdevname(dquot->dq_dev));
+ kdevname(dquot->dq_sb->s_dev));
set_fs(fs);
up(sem);
@@ -359,7 +359,7 @@ restart:
}
}
-int sync_dquots(kdev_t dev, short type)
+int sync_dquots(struct super_block *sb, short type)
{
struct list_head *head;
struct dquot *dquot;
@@ -368,7 +368,7 @@ int sync_dquots(kdev_t dev, short type)
restart:
for (head = inuse_list.next; head != &inuse_list; head = head->next) {
dquot = list_entry(head, struct dquot, dq_inuse);
- if (dev && dquot->dq_dev != dev)
+ if (sb && dquot->dq_sb != sb)
continue;
if (type != -1 && dquot->dq_type != type)
continue;
@@ -440,7 +440,8 @@ static void dqput(struct dquot *dquot)
if (!dquot->dq_count) {
printk("VFS: dqput: trying to free free dquot\n");
printk("VFS: device %s, dquot of %s %d\n",
- kdevname(dquot->dq_dev), quotatypes[dquot->dq_type],
+ kdevname(dquot->dq_sb->s_dev),
+ quotatypes[dquot->dq_type],
dquot->dq_id);
return;
}
@@ -493,7 +494,7 @@ static struct dquot *get_empty_dquot(void)
static struct dquot *dqget(struct super_block *sb, unsigned int id, short type)
{
- unsigned int hashent = hashfn(sb->s_dev, id, type);
+ unsigned int hashent = hashfn(sb, id, type);
struct dquot *dquot, *empty = NODQUOT;
struct quota_mount_options *dqopt = sb_dqopt(sb);
@@ -504,7 +505,7 @@ we_slept:
return NODQUOT;
}
- if ((dquot = find_dquot(hashent, sb->s_dev, id, type)) == NODQUOT) {
+ if ((dquot = find_dquot(hashent, sb, id, type)) == NODQUOT) {
if (empty == NODQUOT) {
if ((empty = get_empty_dquot()) == NODQUOT)
schedule(); /* Try to wait for a moment... */
@@ -513,7 +514,6 @@ we_slept:
dquot = empty;
dquot->dq_id = id;
dquot->dq_type = type;
- dquot->dq_dev = sb->s_dev;
dquot->dq_sb = sb;
/* hash it first so it can be found */
insert_dquot_hash(dquot);
@@ -1471,7 +1471,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
flags |= SET_QLIMIT;
break;
case Q_SYNC:
- ret = sync_dquots(dev, type);
+ ret = sync_dquots(sb, type);
goto out;
case Q_GETSTATS:
ret = get_stats(addr);
@@ -1483,7 +1483,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
goto out;
}
- ret = -NODEV;
+ ret = -ENODEV;
if (sb && sb_has_quota_enabled(sb, type))
ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr);
out:
diff --git a/fs/efs/file.c b/fs/efs/file.c
index faa5b9f2c..06ab1955a 100644
--- a/fs/efs/file.c
+++ b/fs/efs/file.c
@@ -29,11 +29,8 @@ int efs_get_block(struct inode *inode, sector_t iblock,
return 0;
}
phys = efs_map_block(inode, iblock);
- if (phys) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- }
+ if (phys)
+ map_bh(bh_result, inode->i_sb, phys);
return 0;
}
diff --git a/fs/efs/super.c b/fs/efs/super.c
index 691f6df84..2d8f5afb9 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -132,16 +132,13 @@ static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
}
struct super_block *efs_read_super(struct super_block *s, void *d, int silent) {
- kdev_t dev = s->s_dev;
struct efs_sb_info *sb;
struct buffer_head *bh;
sb = SUPER_INFO(s);
s->s_magic = EFS_SUPER_MAGIC;
- s->s_blocksize = EFS_BLOCKSIZE;
- s->s_blocksize_bits = EFS_BLOCKSIZE_BITS;
- set_blocksize(dev, EFS_BLOCKSIZE);
+ sb_set_blocksize(s, EFS_BLOCKSIZE);
/* read the vh (volume header) block */
bh = sb_bread(s, 0);
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 46e7f2220..b492a6b22 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -393,7 +393,7 @@ repeat:
if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
inode->i_flags |= S_SYNC;
insert_inode_hash(inode);
- inode->i_generation = event++;
+ inode->i_generation = sb->u.ext2_sb.s_next_generation++;
mark_inode_dirty(inode);
unlock_super (sb);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index e96e1a014..3c3040e75 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -524,9 +524,7 @@ reread:
/* Simplest case - block found, no allocation needed */
if (!partial) {
got_it:
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = le32_to_cpu(chain[depth-1].key);
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
/* Clean up and exit */
partial = chain+depth-1; /* the whole chain */
goto cleanup;
@@ -1137,9 +1135,8 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
if (buffer_req(bh) && !buffer_uptodate(bh)) {
- printk ("IO error syncing ext2 inode ["
- "%s:%08lx]\n",
- bdevname(inode->i_dev), inode->i_ino);
+ printk ("IO error syncing ext2 inode [%s:%08lx]\n",
+ inode->i_sb->s_id, inode->i_ino);
err = -EIO;
}
}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index c9c544458..05ae46d5c 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -25,9 +25,12 @@
#include <linux/init.h>
#include <linux/locks.h>
#include <linux/blkdev.h>
+#include <linux/random.h>
#include <asm/uaccess.h>
+static void ext2_sync_super(struct super_block *sb,
+ struct ext2_super_block *es);
static char error_buf[1024];
@@ -35,13 +38,13 @@ void ext2_error (struct super_block * sb, const char * function,
const char * fmt, ...)
{
va_list args;
+ struct ext2_super_block *es = EXT2_SB(sb)->s_es;
if (!(sb->s_flags & MS_RDONLY)) {
sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
- sb->u.ext2_sb.s_es->s_state =
- cpu_to_le16(le16_to_cpu(sb->u.ext2_sb.s_es->s_state) | EXT2_ERROR_FS);
- mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
- sb->s_dirt = 1;
+ es->s_state =
+ cpu_to_le16(le16_to_cpu(es->s_state) | EXT2_ERROR_FS);
+ ext2_sync_super(sb, es);
}
va_start (args, fmt);
vsprintf (error_buf, fmt, args);
@@ -50,9 +53,9 @@ void ext2_error (struct super_block * sb, const char * function,
(le16_to_cpu(sb->u.ext2_sb.s_es->s_errors) == EXT2_ERRORS_PANIC &&
!test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_RO)))
panic ("EXT2-fs panic (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
printk (KERN_CRIT "EXT2-fs error (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
if (test_opt (sb, ERRORS_RO) ||
(le16_to_cpu(sb->u.ext2_sb.s_es->s_errors) == EXT2_ERRORS_RO &&
!test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_PANIC))) {
@@ -78,7 +81,7 @@ NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
va_end (args);
sb->s_flags |= MS_RDONLY;
panic ("EXT2-fs panic (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
void ext2_warning (struct super_block * sb, const char * function,
@@ -90,7 +93,7 @@ void ext2_warning (struct super_block * sb, const char * function,
vsprintf (error_buf, fmt, args);
va_end (args);
printk (KERN_WARNING "EXT2-fs warning (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
void ext2_update_dynamic_rev(struct super_block *sb)
@@ -124,8 +127,10 @@ void ext2_put_super (struct super_block * sb)
int i;
if (!(sb->s_flags & MS_RDONLY)) {
- sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state);
- mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
+ struct ext2_super_block *es = EXT2_SB(sb)->s_es;
+
+ es->s_state = le16_to_cpu(EXT2_SB(sb)->s_mount_state);
+ ext2_sync_super(sb, es);
}
db_count = EXT2_SB(sb)->s_gdb_count;
for (i = 0; i < db_count; i++)
@@ -305,13 +310,10 @@ static int ext2_setup_super (struct super_block * sb,
(le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME))
printk ("EXT2-fs warning: checktime reached, "
"running e2fsck is recommended\n");
- es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT2_VALID_FS);
if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
es->s_max_mnt_count = (__s16) cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
- es->s_mtime = cpu_to_le32(CURRENT_TIME);
- mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
- sb->s_dirt = 1;
+ ext2_write_super(sb);
if (test_opt (sb, DEBUG))
printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
"bpg=%lu, ipg=%lu, mo=%04lx]\n",
@@ -406,7 +408,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
unsigned short resgid = EXT2_DEF_RESGID;
unsigned long logic_sb_block = 1;
unsigned long offset = 0;
- kdev_t dev = sb->s_dev;
int blocksize = BLOCK_SIZE;
int db_count;
int i, j;
@@ -418,9 +419,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
* This is important for devices that have a hardware
* sectorsize that is larger than the default.
*/
- blocksize = get_hardsect_size(dev);
- if(blocksize < BLOCK_SIZE )
- blocksize = BLOCK_SIZE;
sb->u.ext2_sb.s_mount_opt = 0;
if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
@@ -428,11 +426,11 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
return NULL;
}
- if (set_blocksize(dev, blocksize) < 0) {
- printk ("EXT2-fs: unable to set blocksize %d\n", blocksize);
+ blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
+ if (!blocksize) {
+ printk ("EXT2-fs: unable to set blocksize\n");
return NULL;
}
- sb->s_blocksize = blocksize;
/*
* If the superblock doesn't start on a sector boundary,
@@ -458,7 +456,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
if (sb->s_magic != EXT2_SUPER_MAGIC) {
if (!silent)
printk ("VFS: Can't find ext2 filesystem on dev %s.\n",
- bdevname(dev));
+ sb->s_id);
goto failed_mount;
}
if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
@@ -475,28 +473,22 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
if ((i = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP))) {
printk("EXT2-fs: %s: couldn't mount because of "
"unsupported optional features (%x).\n",
- bdevname(dev), i);
+ sb->s_id, i);
goto failed_mount;
}
if (!(sb->s_flags & MS_RDONLY) &&
(i = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
printk("EXT2-fs: %s: couldn't mount RDWR because of "
"unsupported optional features (%x).\n",
- bdevname(dev), i);
+ sb->s_id, i);
goto failed_mount;
}
- sb->s_blocksize_bits =
- le32_to_cpu(EXT2_SB(sb)->s_es->s_log_block_size) + 10;
- sb->s_blocksize = 1 << sb->s_blocksize_bits;
-
- sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
-
+ blocksize = BLOCK_SIZE << le32_to_cpu(EXT2_SB(sb)->s_es->s_log_block_size);
/* If the blocksize doesn't match, re-read the thing.. */
if (sb->s_blocksize != blocksize) {
- blocksize = sb->s_blocksize;
brelse(bh);
- if (set_blocksize(dev, blocksize) < 0) {
+ if (!sb_set_blocksize(sb, blocksize)) {
printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n");
return NULL;
}
@@ -517,6 +509,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
}
}
+ sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
+
if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
sb->u.ext2_sb.s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
sb->u.ext2_sb.s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
@@ -563,13 +557,13 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev "
"%s.\n",
- bdevname(dev));
+ sb->s_id);
goto failed_mount;
}
if (sb->s_blocksize != bh->b_size) {
if (!silent)
printk ("VFS: Unsupported blocksize on dev "
- "%s.\n", bdevname(dev));
+ "%s.\n", sb->s_id);
goto failed_mount;
}
@@ -630,6 +624,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
sb->u.ext2_sb.s_gdb_count = db_count;
+ get_random_bytes(&sb->u.ext2_sb.s_next_generation, sizeof(u32));
/*
* set up enough so that it can read an inode
*/
@@ -664,6 +659,15 @@ static void ext2_commit_super (struct super_block * sb,
sb->s_dirt = 0;
}
+static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es)
+{
+ es->s_wtime = cpu_to_le32(CURRENT_TIME);
+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
+ ll_rw_block(WRITE, 1, &EXT2_SB(sb)->s_sbh);
+ wait_on_buffer(EXT2_SB(sb)->s_sbh);
+ sb->s_dirt = 0;
+}
+
/*
* In the second extended file system, it is not necessary to
* write the super block since we use a mapping of the
@@ -682,13 +686,14 @@ void ext2_write_super (struct super_block * sb)
if (!(sb->s_flags & MS_RDONLY)) {
es = sb->u.ext2_sb.s_es;
- ext2_debug ("setting valid to 0\n");
-
if (le16_to_cpu(es->s_state) & EXT2_VALID_FS) {
- es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT2_VALID_FS);
+ ext2_debug ("setting valid to 0\n");
+ es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) &
+ ~EXT2_VALID_FS);
es->s_mtime = cpu_to_le32(CURRENT_TIME);
- }
- ext2_commit_super (sb, es);
+ ext2_sync_super(sb, es);
+ } else
+ ext2_commit_super (sb, es);
}
sb->s_dirt = 0;
}
@@ -725,17 +730,13 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
*/
es->s_state = cpu_to_le16(sb->u.ext2_sb.s_mount_state);
es->s_mtime = cpu_to_le32(CURRENT_TIME);
- mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
- sb->s_dirt = 1;
- ext2_commit_super (sb, es);
- }
- else {
+ } else {
int ret;
if ((ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
~EXT2_FEATURE_RO_COMPAT_SUPP))) {
printk("EXT2-fs: %s: couldn't remount RDWR because of "
"unsupported optional features (%x).\n",
- bdevname(sb->s_dev), ret);
+ sb->s_id, ret);
return -EROFS;
}
/*
@@ -747,6 +748,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
if (!ext2_setup_super (sb, es, 0))
sb->s_flags &= ~MS_RDONLY;
}
+ ext2_sync_super(sb, es);
return 0;
}
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 062ed9374..0800f6845 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -189,10 +189,6 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)
struct ext3_super_block * es;
int fatal = 0, err;
- if (!inode->i_dev) {
- printk ("ext3_free_inode: inode has no device\n");
- return;
- }
if (atomic_read(&inode->i_count) > 1) {
printk ("ext3_free_inode: inode has count=%d\n",
atomic_read(&inode->i_count));
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index bd2bcf61d..e0ad97fe3 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -744,9 +744,7 @@ reread:
if (!partial) {
bh_result->b_state &= ~(1UL << BH_New);
got_it:
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = le32_to_cpu(chain[depth-1].key);
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
/* Clean up and exit */
partial = chain+depth-1; /* the whole chain */
goto cleanup;
@@ -823,9 +821,6 @@ changed:
goto reread;
}
-/*
- * The BKL is not held on entry here.
- */
static int ext3_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
@@ -1292,8 +1287,7 @@ static int ext3_writepage(struct page *page)
/* bget() all the buffers */
if (order_data) {
if (!page->buffers)
- create_empty_buffers(page,
- inode->i_dev, inode->i_sb->s_blocksize);
+ create_empty_buffers(page, inode->i_sb->s_blocksize);
page_buffers = page->buffers;
walk_page_buffers(handle, page_buffers, 0,
PAGE_CACHE_SIZE, NULL, bget_one);
@@ -1396,7 +1390,7 @@ static int ext3_block_truncate_page(handle_t *handle,
goto out;
if (!page->buffers)
- create_empty_buffers(page, inode->i_dev, blocksize);
+ create_empty_buffers(page, blocksize);
/* Find the buffer that contains "offset" */
bh = page->buffers;
@@ -2356,11 +2350,19 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int error, rc = 0;
+ const unsigned int ia_valid = attr->ia_valid;
error = inode_change_ok(inode, attr);
if (error)
return error;
-
+
+ if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
+ (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+ error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
+ if (error)
+ return error;
+ }
+
if (attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
handle_t *handle;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index b82521cad..e274aac53 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -56,10 +56,10 @@ int journal_no_write[2];
static void make_rdonly(kdev_t dev, int *no_write)
{
- if (dev) {
+ if (kdev_val(dev)) {
printk(KERN_WARNING "Turning device %s read-only\n",
bdevname(dev));
- *no_write = 0xdead0000 + dev;
+ *no_write = 0xdead0000 + kdev_val(dev);
}
}
@@ -163,7 +163,7 @@ static void ext3_handle_error(struct super_block *sb)
if (ext3_error_behaviour(sb) == EXT3_ERRORS_PANIC)
panic ("EXT3-fs (device %s): panic forced after error\n",
- bdevname(sb->s_dev));
+ sb->s_id);
if (ext3_error_behaviour(sb) == EXT3_ERRORS_RO) {
printk (KERN_CRIT "Remounting filesystem read-only\n");
@@ -183,7 +183,7 @@ void ext3_error (struct super_block * sb, const char * function,
va_end (args);
printk (KERN_CRIT "EXT3-fs error (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
ext3_handle_error(sb);
}
@@ -231,7 +231,7 @@ void __ext3_std_error (struct super_block * sb, const char * function,
const char *errstr = ext3_decode_error(sb, errno, nbuf);
printk (KERN_CRIT "EXT3-fs error (device %s) in %s: %s\n",
- bdevname(sb->s_dev), function, errstr);
+ sb->s_id, function, errstr);
ext3_handle_error(sb);
}
@@ -259,10 +259,10 @@ void ext3_abort (struct super_block * sb, const char * function,
if (ext3_error_behaviour(sb) == EXT3_ERRORS_PANIC)
panic ("EXT3-fs panic (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
printk (KERN_CRIT "EXT3-fs abort (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
if (sb->s_flags & MS_RDONLY)
return;
@@ -293,7 +293,7 @@ NORET_TYPE void ext3_panic (struct super_block * sb, const char * function,
/* AKPM: is this sufficient? */
sb->s_flags |= MS_RDONLY;
panic ("EXT3-fs panic (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
void ext3_warning (struct super_block * sb, const char * function,
@@ -305,7 +305,7 @@ void ext3_warning (struct super_block * sb, const char * function,
vsprintf (error_buf, fmt, args);
va_end (args);
printk (KERN_WARNING "EXT3-fs warning (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
void ext3_update_dynamic_rev(struct super_block *sb)
@@ -389,8 +389,8 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
list_for_each(l, &sbi->s_orphan) {
struct inode *inode = orphan_list_entry(l);
printk(KERN_ERR " "
- "inode 0x%04x:%ld at %p: mode %o, nlink %d, next %d\n",
- inode->i_dev, inode->i_ino, inode,
+ "inode %s:%ld at %p: mode %o, nlink %d, next %d\n",
+ inode->i_sb->s_id, inode->i_ino, inode,
inode->i_mode, inode->i_nlink,
le32_to_cpu(NEXT_ORPHAN(inode)));
}
@@ -430,7 +430,7 @@ void ext3_put_super (struct super_block * sb)
J_ASSERT(list_empty(&sbi->s_orphan));
invalidate_buffers(sb->s_dev);
- if (j_dev != sb->s_dev) {
+ if (!kdev_same(j_dev, sb->s_dev)) {
/*
* Invalidate the journal device's buffers. We don't want them
* floating about in memory - the physical journal device may
@@ -712,7 +712,7 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
EXT3_INODES_PER_GROUP(sb),
sbi->s_mount_opt);
printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ",
- bdevname(sb->s_dev));
+ sb->s_id);
if (EXT3_SB(sb)->s_journal->j_inode == NULL) {
printk("external journal on %s\n",
bdevname(EXT3_SB(sb)->s_journal->j_dev));
@@ -813,7 +813,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
if (s_flags & MS_RDONLY) {
printk(KERN_INFO "EXT3-fs: %s: orphan cleanup on readonly fs\n",
- bdevname(sb->s_dev));
+ sb->s_id);
sb->s_flags &= ~MS_RDONLY;
}
@@ -859,10 +859,10 @@ static void ext3_orphan_cleanup (struct super_block * sb,
if (nr_orphans)
printk(KERN_INFO "EXT3-fs: %s: %d orphan inode%s deleted\n",
- bdevname(sb->s_dev), PLURAL(nr_orphans));
+ sb->s_id, PLURAL(nr_orphans));
if (nr_truncates)
printk(KERN_INFO "EXT3-fs: %s: %d truncate%s cleaned up\n",
- bdevname(sb->s_dev), PLURAL(nr_truncates));
+ sb->s_id, PLURAL(nr_truncates));
sb->s_flags = s_flags; /* Restore MS_RDONLY status */
}
@@ -912,21 +912,14 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
* This is important for devices that have a hardware
* sectorsize that is larger than the default.
*/
- blocksize = EXT3_MIN_BLOCK_SIZE;
- hblock = get_hardsect_size(dev);
- if (blocksize < hblock)
- blocksize = hblock;
sbi->s_mount_opt = 0;
sbi->s_resuid = EXT3_DEF_RESUID;
sbi->s_resgid = EXT3_DEF_RESGID;
- if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
- sb->s_dev = 0;
+ if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0))
goto out_fail;
- }
- sb->s_blocksize = blocksize;
- set_blocksize (dev, blocksize);
+ blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
/*
* The ext3 superblock will not be buffer aligned for other than 1kB
@@ -952,7 +945,7 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
if (!silent)
printk(KERN_ERR
"VFS: Can't find ext3 filesystem on dev %s.\n",
- bdevname(dev));
+ sb->s_id);
goto failed_mount;
}
if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV &&
@@ -970,44 +963,42 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
if ((i = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP))) {
printk(KERN_ERR "EXT3-fs: %s: couldn't mount because of "
"unsupported optional features (%x).\n",
- bdevname(dev), i);
+ sb->s_id, i);
goto failed_mount;
}
if (!(sb->s_flags & MS_RDONLY) &&
(i = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))){
printk(KERN_ERR "EXT3-fs: %s: couldn't mount RDWR because of "
"unsupported optional features (%x).\n",
- bdevname(dev), i);
+ sb->s_id, i);
goto failed_mount;
}
- sb->s_blocksize_bits = le32_to_cpu(es->s_log_block_size) + 10;
- sb->s_blocksize = 1 << sb->s_blocksize_bits;
+ blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
- if (sb->s_blocksize < EXT3_MIN_BLOCK_SIZE ||
- sb->s_blocksize > EXT3_MAX_BLOCK_SIZE) {
+ if (blocksize < EXT3_MIN_BLOCK_SIZE ||
+ blocksize > EXT3_MAX_BLOCK_SIZE) {
printk(KERN_ERR
"EXT3-fs: Unsupported filesystem blocksize %d on %s.\n",
- blocksize, bdevname(dev));
+ blocksize, sb->s_id);
goto failed_mount;
}
sb->s_maxbytes = ext3_max_size(sb->s_blocksize_bits);
+ hblock = get_hardsect_size(dev);
if (sb->s_blocksize != blocksize) {
- blocksize = sb->s_blocksize;
-
/*
* Make sure the blocksize for the filesystem is larger
* than the hardware sectorsize for the machine.
*/
- if (sb->s_blocksize < hblock) {
+ if (blocksize < hblock) {
printk(KERN_ERR "EXT3-fs: blocksize %d too small for "
"device blocksize %d.\n", blocksize, hblock);
goto failed_mount;
}
brelse (bh);
- set_blocksize (dev, sb->s_blocksize);
+ sb_set_blocksize(sb, blocksize);
logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;
offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
bh = sb_bread(sb, logic_sb_block);
@@ -1142,7 +1133,7 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
if (!silent)
printk (KERN_ERR
"ext3: No journal on filesystem on %s\n",
- bdevname(dev));
+ sb->s_id);
goto failed_mount2;
}
@@ -1266,7 +1257,7 @@ static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
}
static journal_t *ext3_get_dev_journal(struct super_block *sb,
- int dev)
+ kdev_t j_dev)
{
struct buffer_head * bh;
journal_t *journal;
@@ -1275,16 +1266,15 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
int hblock, blocksize;
unsigned long sb_block;
unsigned long offset;
- kdev_t journal_dev = to_kdev_t(dev);
struct ext3_super_block * es;
struct block_device *bdev;
- bdev = ext3_blkdev_get(journal_dev);
+ bdev = ext3_blkdev_get(j_dev);
if (bdev == NULL)
return NULL;
blocksize = sb->s_blocksize;
- hblock = get_hardsect_size(journal_dev);
+ hblock = get_hardsect_size(j_dev);
if (blocksize < hblock) {
printk(KERN_ERR
"EXT3-fs: blocksize too small for journal device.\n");
@@ -1293,8 +1283,8 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
sb_block = EXT3_MIN_BLOCK_SIZE / blocksize;
offset = EXT3_MIN_BLOCK_SIZE % blocksize;
- set_blocksize(dev, blocksize);
- if (!(bh = bread(dev, sb_block, blocksize))) {
+ set_blocksize(j_dev, blocksize);
+ if (!(bh = bread(j_dev, sb_block, blocksize))) {
printk(KERN_ERR "EXT3-fs: couldn't read superblock of "
"external journal\n");
goto out_bdev;
@@ -1320,7 +1310,7 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
start = sb_block + 1;
brelse(bh); /* we're done with the superblock */
- journal = journal_init_dev(journal_dev, sb->s_dev,
+ journal = journal_init_dev(j_dev, sb->s_dev,
start, len, blocksize);
if (!journal) {
printk(KERN_ERR "EXT3-fs: failed to create device journal\n");
@@ -1352,7 +1342,7 @@ static int ext3_load_journal(struct super_block * sb,
{
journal_t *journal;
int journal_inum = le32_to_cpu(es->s_journal_inum);
- int journal_dev = le32_to_cpu(es->s_journal_dev);
+ kdev_t journal_dev = to_kdev_t(le32_to_cpu(es->s_journal_dev));
int err = 0;
int really_read_only;
@@ -1378,7 +1368,7 @@ static int ext3_load_journal(struct super_block * sb,
}
}
- if (journal_inum && journal_dev) {
+ if (journal_inum && !kdev_none(journal_dev)) {
printk(KERN_ERR "EXT3-fs: filesystem has both journal "
"and inode journals!\n");
return -EINVAL;
@@ -1662,7 +1652,7 @@ int ext3_remount (struct super_block * sb, int * flags, char * data)
printk(KERN_WARNING "EXT3-fs: %s: couldn't "
"remount RDWR because of unsupported "
"optional features (%x).\n",
- bdevname(sb->s_dev), ret);
+ sb->s_id, ret);
return -EROFS;
}
/*
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 7240bc8a2..540d9df2b 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -144,7 +144,7 @@ void fat_cache_init(void)
}
fat_cache = &cache[0];
for (count = 0; count < FAT_CACHE; count++) {
- cache[count].device = 0;
+ cache[count].sb = NULL;
cache[count].next = count == FAT_CACHE-1 ? NULL :
&cache[count+1];
}
@@ -162,7 +162,7 @@ void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
return;
spin_lock(&fat_cache_lock);
for (walk = fat_cache; walk; walk = walk->next)
- if (inode->i_dev == walk->device
+ if (inode->i_sb == walk->sb
&& walk->start_cluster == first
&& walk->file_cluster <= cluster
&& walk->file_cluster > *f_clu) {
@@ -188,8 +188,8 @@ static void list_cache(void)
struct fat_cache *walk;
for (walk = fat_cache; walk; walk = walk->next) {
- if (walk->device)
- printk("<%s,%d>(%d,%d) ", kdevname(walk->device),
+ if (walk->sb)
+ printk("<%s,%d>(%d,%d) ", walk->sb->s_dev->s_id,
walk->start_cluster, walk->file_cluster,
walk->disk_cluster);
else printk("-- ");
@@ -207,7 +207,7 @@ void fat_cache_add(struct inode *inode,int f_clu,int d_clu)
last = NULL;
spin_lock(&fat_cache_lock);
for (walk = fat_cache; walk->next; walk = (last = walk)->next)
- if (inode->i_dev == walk->device
+ if (inode->i_sb == walk->sb
&& walk->start_cluster == first
&& walk->file_cluster == f_clu) {
if (walk->disk_cluster != d_clu) {
@@ -231,7 +231,7 @@ list_cache();
spin_unlock(&fat_cache_lock);
return;
}
- walk->device = inode->i_dev;
+ walk->sb = inode->i_sb;
walk->start_cluster = first;
walk->file_cluster = f_clu;
walk->disk_cluster = d_clu;
@@ -255,21 +255,21 @@ void fat_cache_inval_inode(struct inode *inode)
spin_lock(&fat_cache_lock);
for (walk = fat_cache; walk; walk = walk->next)
- if (walk->device == inode->i_dev
+ if (walk->sb == inode->i_sb
&& walk->start_cluster == first)
- walk->device = 0;
+ walk->sb = NULL;
spin_unlock(&fat_cache_lock);
}
-void fat_cache_inval_dev(kdev_t device)
+void fat_cache_inval_dev(struct super_block *sb)
{
struct fat_cache *walk;
spin_lock(&fat_cache_lock);
for (walk = fat_cache; walk; walk = walk->next)
- if (walk->device == device)
- walk->device = 0;
+ if (walk->sb == sb)
+ walk->sb = 0;
spin_unlock(&fat_cache_lock);
}
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 8071aaf6e..9a3b45bcd 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -55,9 +55,7 @@ int fat_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_r
phys = fat_bmap(inode, iblock);
if (phys) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, inode->i_sb, phys);
return 0;
}
if (!create)
@@ -74,10 +72,8 @@ int fat_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_r
phys = fat_bmap(inode, iblock);
if (!phys)
BUG();
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
bh_result->b_state |= (1UL << BH_New);
+ map_bh(bh_result, inode->i_sb, phys);
return 0;
}
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 5bbebb08c..e6daf9dc5 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -146,6 +146,7 @@ struct inode *fat_build_inode(struct super_block *sb,
goto out;
*res = 0;
inode->i_ino = iunique(sb, MSDOS_ROOT_INO);
+ inode->i_version = 0;
fat_fill_inode(inode, de);
fat_attach(inode, ino);
insert_inode_hash(inode);
@@ -185,7 +186,7 @@ void fat_put_super(struct super_block *sb)
if (MSDOS_SB(sb)->fat_bits == 32) {
fat_clusters_flush(sb);
}
- fat_cache_inval_dev(sb->s_dev);
+ fat_cache_inval_dev(sb);
set_blocksize (sb->s_dev,BLOCK_SIZE);
if (MSDOS_SB(sb)->nls_disk) {
unload_nls(MSDOS_SB(sb)->nls_disk);
@@ -383,7 +384,7 @@ static void fat_read_root(struct inode *inode)
MSDOS_I(inode)->i_fat_inode = inode;
inode->i_uid = sbi->options.fs_uid;
inode->i_gid = sbi->options.fs_gid;
- inode->i_version = ++event;
+ inode->i_version++;
inode->i_generation = 0;
inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_umask) | S_IFDIR;
inode->i_op = sbi->dir_ops;
@@ -569,10 +570,6 @@ fat_read_super(struct super_block *sb, void *data, int silent,
sb->s_maxbytes = MAX_NON_LFS;
sb->s_op = &fat_sops;
- hard_blksize = get_hardsect_size(sb->s_dev);
- if (!hard_blksize)
- hard_blksize = 512;
-
opts.isvfat = sbi->options.isvfat;
if (!parse_options((char *) data, &fat, &debug, &opts,
cvf_format, cvf_options))
@@ -582,8 +579,7 @@ fat_read_super(struct super_block *sb, void *data, int silent,
fat_cache_init();
- sb->s_blocksize = hard_blksize;
- set_blocksize(sb->s_dev, hard_blksize);
+ sb_min_blocksize(sb, 512);
bh = sb_bread(sb, 0);
if (bh == NULL) {
printk("FAT: unable to read boot sector\n");
@@ -625,13 +621,15 @@ fat_read_super(struct super_block *sb, void *data, int silent,
goto out_invalid;
}
- if (logical_sector_size < hard_blksize) {
+ if (logical_sector_size < sb->s_blocksize) {
printk("FAT: logical sector size too small for device"
" (logical sector size = %d)\n", logical_sector_size);
brelse(bh);
goto out_invalid;
}
+ hard_blksize = sb->s_blocksize;
+
sbi->cluster_bits = ffs(logical_sector_size * sbi->cluster_size) - 1;
sbi->fats = b->fats;
sbi->fat_start = CF_LE_W(b->reserved);
@@ -716,9 +714,7 @@ fat_read_super(struct super_block *sb, void *data, int silent,
if (error)
goto out_invalid;
- sb->s_blocksize = logical_sector_size;
- sb->s_blocksize_bits = ffs(logical_sector_size) - 1;
- set_blocksize(sb->s_dev, sb->s_blocksize);
+ sb_set_blocksize(sb, logical_sector_size);
sbi->cvf_format = &default_cvf;
if (!strcmp(cvf_format, "none"))
i = -1;
@@ -781,6 +777,7 @@ fat_read_super(struct super_block *sb, void *data, int silent,
if (!root_inode)
goto out_unload_nls;
root_inode->i_ino = MSDOS_ROOT_INO;
+ root_inode->i_version = 0;
fat_read_root(root_inode);
insert_inode_hash(root_inode);
sb->s_root = d_alloc_root(root_inode);
@@ -802,7 +799,7 @@ out_unload_nls:
out_invalid:
if (!silent) {
printk("VFS: Can't find a valid FAT filesystem on dev %s.\n",
- kdevname(sb->s_dev));
+ sb->s_id);
}
out_fail:
if (opts.iocharset) {
@@ -892,7 +889,7 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
MSDOS_I(inode)->i_fat_inode = inode;
inode->i_uid = sbi->options.fs_uid;
inode->i_gid = sbi->options.fs_gid;
- inode->i_version = ++event;
+ inode->i_version++;
inode->i_generation = CURRENT_TIME;
if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {
@@ -976,7 +973,7 @@ retry:
}
lock_kernel();
if (!(bh = fat_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) {
- printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos);
+ printk("dev = %s, ino = %d\n", sb->s_id, i_pos);
fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");
unlock_kernel();
return;
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 698971211..6f175afac 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -44,7 +44,7 @@ void fat_fs_panic(struct super_block *s,const char *msg)
not_ro = !(s->s_flags & MS_RDONLY);
if (not_ro) s->s_flags |= MS_RDONLY;
- printk("Filesystem panic (dev %s).\n %s\n", kdevname(s->s_dev), msg);
+ printk("Filesystem panic (dev %s).\n %s\n", s->s_id, msg);
if (not_ro)
printk(" File system has been set read-only\n");
}
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index 16c7eb194..3811dc5e5 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -30,7 +30,7 @@
#ifndef _VXFS_SUPER_H_
#define _VXFS_SUPER_H_
-#ident "$Id: vxfs.h 1.11 2001/05/21 15:40:28 hch Exp hch $"
+#ident "$Id: vxfs.h 1.12 2001/12/28 19:48:03 hch Exp $"
/*
* Veritas filesystem driver - superblock structure.
@@ -39,6 +39,7 @@
* superblocks of the Veritas Filesystem.
*/
#include <linux/types.h>
+#include "vxfs_kcompat.h"
/*
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index fb3eeeb9f..ed31e0a06 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_bmap.c,v 1.23 2001/07/05 19:48:03 hch Exp hch $"
+#ident "$Id: vxfs_bmap.c,v 1.25 2002/01/02 23:36:55 hch Exp hch $"
/*
* Veritas filesystem driver - filesystem to disk block mapping.
@@ -64,49 +64,47 @@ vxfs_typdump(struct vxfs_typed *typ)
* The physical block number on success, else Zero.
*/
static daddr_t
-vxfs_bmap_ext4(struct inode *ip, long iblock)
+vxfs_bmap_ext4(struct inode *ip, long bn)
{
- struct vxfs_inode_info *vip = VXFS_INO(ip);
- struct super_block *sbp = ip->i_sb;
- kdev_t dev = ip->i_dev;
- u_long bsize = sbp->s_blocksize;
- long size = 0;
- int i;
+ struct super_block *sb = ip->i_sb;
+ struct vxfs_inode_info *vip = VXFS_INO(ip);
+ unsigned long bsize = sb->s_blocksize;
+ u32 indsize = vip->vii_ext4.ve4_indsize;
+ int i;
- for (i = 0; i < VXFS_NDADDR; i++) {
- struct direct *dp = vip->vii_ext4.ve4_direct + i;
-
-#ifdef DIAGNOSTIC
- printk(KERN_DEBUG "iblock: %ld, %d (size: %lu)\n", iblock, i, size);
- printk(KERN_DEBUG "dp->extent: %d, dp->size: %d\n", dp->extent, dp->size);
-#endif
+ if (indsize > sb->s_blocksize)
+ goto fail_size;
- if (iblock >= size && iblock < (size + dp->size))
- return ((iblock - size) + dp->extent);
- size += dp->size;
+ for (i = 0; i < VXFS_NDADDR; i++) {
+ struct direct *d = vip->vii_ext4.ve4_direct + i;
+ if (bn >= 0 && bn < d->size)
+ return (bn + d->extent);
+ bn -= d->size;
}
- iblock -= size;
+ if ((bn / (indsize * indsize * bsize / 4)) == 0) {
+ struct buffer_head *buf;
+ daddr_t bno;
+ u32 *indir;
- if (!(iblock / (vip->vii_ext4.ve4_indsize * vip->vii_ext4.ve4_indsize * bsize >> 2))) {
- struct buffer_head *bp;
- daddr_t pblock;
+ buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]);
+ if (!buf || !buffer_mapped(buf))
+ goto fail_buf;
- /*
- * XXX: is the second indir only used for
- * double indirect extents?
- */
- bp = bread(dev, vip->vii_ext4.ve4_indir[0],
- bsize * ((vip->vii_ext4.ve4_indsize) / bsize) + 1);
- pblock = *(bp->b_data + ((iblock / vip->vii_ext4.ve4_indsize) %
- (vip->vii_ext4.ve4_indsize * bsize)));
+ indir = (u32 *)buf->b_data;
+ bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
- brelse(bp);
- return (pblock + (iblock % vip->vii_ext4.ve4_indsize));
+ brelse(buf);
+ return bno;
} else
printk(KERN_WARNING "no matching indir?");
return 0;
+
+fail_size:
+ printk("vxfs: indirect extent to big!\n");
+fail_buf:
+ return 0;
}
/**
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 32f37e612..1f76609ee 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -30,7 +30,7 @@
#ifndef _VXFS_EXTERN_H_
#define _VXFS_EXTERN_H_
-#ident "$Id: vxfs_extern.h,v 1.21 2001/08/07 16:13:30 hch Exp hch $"
+#ident "$Id: vxfs_extern.h,v 1.22 2001/12/28 20:50:47 hch Exp hch $"
/*
* Veritas filesystem driver - external prototypes.
@@ -71,7 +71,7 @@ extern struct file_operations vxfs_dir_operations;
extern int vxfs_read_olt(struct super_block *, u_long);
/* vxfs_subr.c */
-extern struct page * vxfs_get_page(struct inode *, u_long);
+extern struct page * vxfs_get_page(struct address_space *, u_long);
extern __inline__ void vxfs_put_page(struct page *);
extern struct buffer_head * vxfs_bread(struct inode *, int);
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index 942bfa087..faf006912 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_fshead.c,v 1.19 2001/08/07 16:14:10 hch Exp hch $"
+#ident "$Id: vxfs_fshead.c,v 1.20 2002/01/02 22:02:12 hch Exp hch $"
/*
* Veritas filesystem driver - fileset header routines.
@@ -81,9 +81,9 @@ vxfs_getfsh(struct inode *ip, int which)
if (buffer_mapped(bp)) {
struct vxfs_fsh *fhp;
- if (!(fhp = kmalloc(sizeof(struct vxfs_fsh), SLAB_KERNEL)))
+ if (!(fhp = kmalloc(sizeof(*fhp), SLAB_KERNEL)))
return NULL;
- memcpy(fhp, bp->b_data, sizeof(struct vxfs_fsh));
+ memcpy(fhp, bp->b_data, sizeof(*fhp));
brelse(bp);
return (fhp);
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 363e1ac59..98060cfd5 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -27,12 +27,13 @@
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_inode.c,v 1.37 2001/08/07 16:13:30 hch Exp hch $"
+#ident "$Id: vxfs_inode.c,v 1.42 2002/01/02 23:51:36 hch Exp hch $"
/*
* Veritas filesystem driver - inode routines.
*/
#include <linux/fs.h>
+#include <linux/pagemap.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -47,6 +48,7 @@ extern struct address_space_operations vxfs_immed_aops;
extern struct inode_operations vxfs_immed_symlink_iops;
static struct file_operations vxfs_file_operations = {
+ .open = generic_file_open,
.llseek = generic_file_llseek,
.read = generic_file_read,
.mmap = generic_file_mmap,
@@ -113,7 +115,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
goto fail;
dip = (struct vxfs_dinode *)(bp->b_data + offset);
- memcpy(vip, dip, sizeof(struct vxfs_inode_info));
+ memcpy(vip, dip, sizeof(*vip));
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
@@ -145,7 +147,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
u_long offset;
offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
- pp = vxfs_get_page(ilistp, ino * VXFS_ISIZE / PAGE_SIZE);
+ pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
if (!IS_ERR(pp)) {
struct vxfs_inode_info *vip;
@@ -155,7 +157,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
goto fail;
dip = (struct vxfs_dinode *)(kaddr + offset);
- memcpy(vip, dip, sizeof(struct vxfs_inode_info));
+ memcpy(vip, dip, sizeof(*vip));
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
diff --git a/fs/freevxfs/vxfs_kcompat.h b/fs/freevxfs/vxfs_kcompat.h
new file mode 100644
index 000000000..342a4cc86
--- /dev/null
+++ b/fs/freevxfs/vxfs_kcompat.h
@@ -0,0 +1,49 @@
+#ifndef _VXFS_KCOMPAT_H
+#define _VXFS_KCOMPAT_H
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+
+#include <linux/blkdev.h>
+
+typedef long sector_t;
+
+/* From include/linux/fs.h (Linux 2.5.2-pre3) */
+static inline struct buffer_head * sb_bread(struct super_block *sb, int block)
+{
+ return bread(sb->s_dev, block, sb->s_blocksize);
+}
+
+/* Dito. */
+static inline void map_bh(struct buffer_head *bh, struct super_block *sb, int block)
+{
+ bh->b_state |= 1 << BH_Mapped;
+ bh->b_dev = sb->s_dev;
+ bh->b_blocknr = block;
+}
+
+/* From fs/block_dev.c (Linux 2.5.2-pre2) */
+static inline int sb_set_blocksize(struct super_block *sb, int size)
+{
+ int bits;
+ if (set_blocksize(sb->s_dev, size) < 0)
+ return 0;
+ sb->s_blocksize = size;
+ for (bits = 9, size >>= 9; size >>= 1; bits++)
+ ;
+ sb->s_blocksize_bits = bits;
+ return sb->s_blocksize;
+}
+
+/* Dito. */
+static inline int sb_min_blocksize(struct super_block *sb, int size)
+{
+ int minsize = get_hardsect_size(sb->s_dev);
+ if (size < minsize)
+ size = minsize;
+ return sb_set_blocksize(sb, size);
+}
+
+#endif /* Kernel 2.4 */
+#endif /* _VXFS_KCOMPAT_H */
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index bc64fd8b5..2942766f2 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_lookup.c,v 1.19 2001/05/30 19:50:20 hch Exp hch $"
+#ident "$Id: vxfs_lookup.c,v 1.21 2002/01/02 22:00:13 hch Exp hch $"
/*
* Veritas filesystem driver - lookup and other directory related code.
@@ -126,7 +126,7 @@ vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
caddr_t kaddr;
struct page *pp;
- pp = vxfs_get_page(ip, page);
+ pp = vxfs_get_page(ip->i_mapping, page);
if (IS_ERR(pp))
continue;
kaddr = (caddr_t)page_address(pp);
@@ -273,7 +273,7 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
caddr_t kaddr;
struct page *pp;
- pp = vxfs_get_page(ip, page);
+ pp = vxfs_get_page(ip->i_mapping, page);
if (IS_ERR(pp))
continue;
kaddr = (caddr_t)page_address(pp);
@@ -318,6 +318,5 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
done:
fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
out:
- fp->f_version = ip->i_version;
return 0;
}
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 44bfbd066..6b45a5a5c 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_olt.c,v 1.9 2001/08/07 16:14:45 hch Exp hch $"
+#ident "$Id: vxfs_olt.c,v 1.10 2002/01/02 23:03:58 hch Exp hch $"
/*
* Veritas filesystem driver - object location table support.
@@ -85,8 +85,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
char *oaddr, *eaddr;
- bp = bread(sbp->s_dev,
- vxfs_oblock(sbp, infp->vsi_oltext, bsize), bsize);
+ bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
if (!bp || !bp->b_data)
goto fail;
@@ -96,6 +95,16 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
goto fail;
}
+ /*
+ * It is in theory possible that vsi_oltsize is > 1.
+ * I've not seen any such filesystem yet and I'm lazy.. --hch
+ */
+ if (infp->vsi_oltsize > 1) {
+ printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
+ printk(KERN_NOTICE "vxfs: please notify hch@caldera.de\n");
+ goto fail;
+ }
+
oaddr = (char *)bp->b_data + op->olt_size;
eaddr = (char *)bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c
index 341d5c1a7..0b1a480e5 100644
--- a/fs/freevxfs/vxfs_subr.c
+++ b/fs/freevxfs/vxfs_subr.c
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_subr.c,v 1.5 2001/04/26 22:49:51 hch Exp hch $"
+#ident "$Id: vxfs_subr.c,v 1.8 2001/12/28 20:50:47 hch Exp hch $"
/*
* Veritas filesystem driver - shared subroutines.
@@ -37,6 +37,7 @@
#include <linux/slab.h>
#include <linux/pagemap.h>
+#include "vxfs_kcompat.h"
#include "vxfs_extern.h"
@@ -62,9 +63,8 @@ struct address_space_operations vxfs_aops = {
* The wanted page on success, else a NULL pointer.
*/
struct page *
-vxfs_get_page(struct inode *ip, u_long n)
+vxfs_get_page(struct address_space *mapping, u_long n)
{
- struct address_space * mapping = ip->i_mapping;
struct page * pp;
pp = read_cache_page(mapping, n,
@@ -142,10 +142,7 @@ vxfs_getblk(struct inode *ip, sector_t iblock,
pblock = vxfs_bmap1(ip, iblock);
if (pblock != 0) {
- bp->b_dev = ip->i_dev;
- bp->b_blocknr = pblock;
- bp->b_state |= (1UL << BH_Mapped);
-
+ map_bh(bp, ip->i_sb, pblock);
return 0;
}
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 99b265f0a..768e91bb3 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_super.c,v 1.26 2001/08/07 16:13:30 hch Exp hch $"
+#ident "$Id: vxfs_super.c,v 1.29 2002/01/02 22:02:12 hch Exp hch $"
/*
* Veritas filesystem driver - superblock related routines.
@@ -62,19 +62,6 @@ static struct super_operations vxfs_super_ops = {
.statfs = vxfs_statfs,
};
-static __inline__ u_long
-vxfs_validate_bsize(kdev_t dev)
-{
- u_long bsize;
-
- bsize = get_hardsect_size(dev);
- if (bsize < BLOCK_SIZE)
- bsize = BLOCK_SIZE;
-
- set_blocksize(dev, bsize);
- return (bsize);
-}
-
/**
* vxfs_put_super - free superblock resources
* @sbp: VFS superblock.
@@ -153,21 +140,24 @@ vxfs_read_super(struct super_block *sbp, void *dp, int silent)
{
struct vxfs_sb_info *infp;
struct vxfs_sb *rsbp;
- struct buffer_head *bp;
+ struct buffer_head *bp = NULL;
u_long bsize;
- kdev_t dev = sbp->s_dev;
- infp = kmalloc(sizeof(struct vxfs_sb_info), GFP_KERNEL);
+ infp = kmalloc(sizeof(*infp), GFP_KERNEL);
if (!infp) {
printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n");
return NULL;
}
- memset(infp, 0, sizeof(struct vxfs_sb_info));
+ memset(infp, 0, sizeof(*infp));
- bsize = vxfs_validate_bsize(dev);
+ bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
+ if (!bsize) {
+ printk(KERN_WARNING "vxfs: unable to set blocksize\n");
+ goto out;
+ }
- bp = bread(dev, 1, bsize);
- if (!bp) {
+ bp = sb_bread(sbp, 1);
+ if (!bp || !buffer_mapped(bp)) {
if (!silent) {
printk(KERN_WARNING
"vxfs: unable to read disk superblock\n");
@@ -194,31 +184,15 @@ vxfs_read_super(struct super_block *sbp, void *dp, int silent)
#endif
sbp->s_magic = rsbp->vs_magic;
- sbp->s_blocksize = rsbp->vs_bsize;
sbp->u.generic_sbp = (void *)infp;
infp->vsi_raw = rsbp;
infp->vsi_bp = bp;
infp->vsi_oltext = rsbp->vs_oltext[0];
infp->vsi_oltsize = rsbp->vs_oltsize;
-
- switch (rsbp->vs_bsize) {
- case 1024:
- sbp->s_blocksize_bits = 10;
- break;
- case 2048:
- sbp->s_blocksize_bits = 11;
- break;
- case 4096:
- sbp->s_blocksize_bits = 12;
- break;
- default:
- if (!silent) {
- printk(KERN_WARNING
- "vxfs: unsupported blocksise: %d\n",
- rsbp->vs_bsize);
- }
+ if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
+ printk(KERN_WARNING "vxfs: unable to set final block size\n");
goto out;
}
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 4f35c2760..595c9127a 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -69,8 +69,8 @@ static int build_key(struct hfs_cat_key *key, struct inode *dir,
/*
* update_dirs_plus()
*
- * Update the fields 'i_size', 'i_nlink', 'i_ctime', 'i_mtime' and
- * 'i_version' of the inodes associated with a directory that has
+ * Update the fields 'i_size', 'i_nlink', 'i_ctime' and 'i_mtime'
+ * of the inodes associated with a directory that has
* had a file ('is_dir'==0) or directory ('is_dir'!=0) added to it.
*/
static inline void update_dirs_plus(struct hfs_cat_entry *dir, int is_dir)
@@ -88,7 +88,6 @@ static inline void update_dirs_plus(struct hfs_cat_entry *dir, int is_dir)
++(tmp->i_nlink);
}
tmp->i_size += HFS_I(tmp)->dir_size;
- tmp->i_version = ++event;
}
tmp->i_ctime = tmp->i_mtime = CURRENT_TIME;
mark_inode_dirty(tmp);
@@ -100,7 +99,7 @@ static inline void update_dirs_plus(struct hfs_cat_entry *dir, int is_dir)
* update_dirs_minus()
*
* Update the fields 'i_size', 'i_nlink', 'i_ctime', 'i_mtime' and
- * 'i_version' of the inodes associated with a directory that has
+ * of the inodes associated with a directory that has
* had a file ('is_dir'==0) or directory ('is_dir'!=0) removed.
*/
static inline void update_dirs_minus(struct hfs_cat_entry *dir, int is_dir)
@@ -118,7 +117,6 @@ static inline void update_dirs_minus(struct hfs_cat_entry *dir, int is_dir)
--(tmp->i_nlink);
}
tmp->i_size -= HFS_I(tmp)->dir_size;
- tmp->i_version = ++event;
}
tmp->i_ctime = tmp->i_mtime = CURRENT_TIME;
mark_inode_dirty(tmp);
diff --git a/fs/hfs/file.c b/fs/hfs/file.c
index d2043ae51..f6b81d574 100644
--- a/fs/hfs/file.c
+++ b/fs/hfs/file.c
@@ -112,11 +112,9 @@ int hfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_r
phys = hfs_extent_map(HFS_I(inode)->fork, iblock, create);
if (phys) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
if (create)
bh_result->b_state |= (1UL << BH_New);
+ map_bh(bh_result, inode->i_sb, phys);
return 0;
}
@@ -312,8 +310,8 @@ hfs_s32 hfs_do_read(struct inode *inode, struct hfs_fork * fork, hfs_u32 pos,
bhb = bhe = buflist;
if (reada) {
- if (blocks < read_ahead[MAJOR(dev)] / (HFS_SECTOR_SIZE>>9)) {
- blocks = read_ahead[MAJOR(dev)] / (HFS_SECTOR_SIZE>>9);
+ if (blocks < read_ahead[major(dev)] / (HFS_SECTOR_SIZE>>9)) {
+ blocks = read_ahead[major(dev)] / (HFS_SECTOR_SIZE>>9);
}
if (block + blocks > size) {
blocks = size - block;
diff --git a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c
index 9dac8cd39..49aea8da2 100644
--- a/fs/hfs/file_cap.c
+++ b/fs/hfs/file_cap.c
@@ -103,7 +103,6 @@ static loff_t cap_info_llseek(struct file *file, loff_t offset, int origin)
if (offset != file->f_pos) {
file->f_pos = offset;
file->f_reada = 0;
- file->f_version = ++event;
}
retval = offset;
}
diff --git a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c
index eb1476068..ba3c58a2f 100644
--- a/fs/hfs/file_hdr.c
+++ b/fs/hfs/file_hdr.c
@@ -359,7 +359,6 @@ loff_t hdr_llseek(struct file *file, loff_t offset, int origin)
if (offset != file->f_pos) {
file->f_pos = offset;
file->f_reada = 0;
- file->f_version = ++event;
}
retval = offset;
}
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 034e9fca6..00e882a15 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -311,14 +311,11 @@ struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type,
return NULL;
}
- if (inode->i_dev != sb->s_dev) {
- iput(inode); /* automatically does an hfs_cat_put */
- inode = NULL;
- } else if (!inode->i_mode || (*sys_entry == NULL)) {
+ if (!inode->i_mode || (*sys_entry == NULL)) {
/* Initialize the inode */
struct hfs_sb_info *hsb = HFS_SB(sb);
- inode->i_rdev = 0;
+ inode->i_rdev = NODEV;
inode->i_ctime = inode->i_atime = inode->i_mtime =
hfs_m_to_utime(entry->modify_date);
inode->i_blksize = HFS_SECTOR_SIZE;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 6d69f71d3..90244a916 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -401,9 +401,7 @@ struct super_block *hfs_read_super(struct super_block *s, void *data,
}
/* set the device driver to 512-byte blocks */
- set_blocksize(dev, HFS_SECTOR_SIZE);
- s->s_blocksize_bits = HFS_SECTOR_SIZE_BITS;
- s->s_blocksize = HFS_SECTOR_SIZE;
+ sb_set_blocksize(s, HFS_SECTOR_SIZE);
#ifdef CONFIG_MAC_PARTITION
/* check to see if we're in a partition */
@@ -427,7 +425,7 @@ struct super_block *hfs_read_super(struct super_block *s, void *data,
if (!mdb) {
if (!silent) {
hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
- kdevname(dev));
+ s->s_id);
}
goto bail2;
}
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index bce5d5dac..a6ea7c41b 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -73,9 +73,7 @@ int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_
secno s;
s = hpfs_bmap(inode, iblock);
if (s) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = s;
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, inode->i_sb, s);
return 0;
}
if (!create) return 0;
@@ -89,9 +87,8 @@ int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_
}
inode->i_blocks++;
inode->u.hpfs_i.mmu_private += 512;
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = s;
- bh_result->b_state |= (1UL << BH_Mapped) | (1UL << BH_New);
+ bh_result->b_state |= 1UL << BH_New;
+ map_bh(bh_result, inode->i_sb, s);
return 0;
}
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 7fa8f7413..d7588317f 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -19,7 +19,6 @@
#include <linux/stat.h>
#include <linux/string.h>
#include <asm/bitops.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/smp_lock.h>
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 2972808d2..6d8f486be 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -362,7 +362,6 @@ int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
struct super_block *hpfs_read_super(struct super_block *s, void *options,
int silent)
{
- kdev_t dev;
struct buffer_head *bh0, *bh1, *bh2;
struct hpfs_boot_block *bootblock;
struct hpfs_super_block *superblock;
@@ -408,10 +407,7 @@ struct super_block *hpfs_read_super(struct super_block *s, void *options,
}
/*s->s_hpfs_mounting = 1;*/
- dev = s->s_dev;
- set_blocksize(dev, 512);
- s->s_blocksize = 512;
- s->s_blocksize_bits = 9;
+ sb_set_blocksize(s, 512);
s->s_hpfs_fs_size = -1;
if (!(bootblock = hpfs_map_sector(s, 0, &bh0, 0))) goto bail1;
if (!(superblock = hpfs_map_sector(s, 16, &bh1, 1))) goto bail2;
diff --git a/fs/inode.c b/fs/inode.c
index 184f8f19d..9d435477c 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -382,7 +382,7 @@ void sync_inodes(kdev_t dev)
/*
* Search the super_blocks array for the device(s) to sync.
*/
- if (dev) {
+ if (!kdev_none(dev)) {
if ((s = get_super(dev)) != NULL) {
sync_inodes_sb(s);
drop_super(s);
@@ -826,7 +826,7 @@ struct inode * get_empty_inode(void)
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
inode->i_sb = NULL;
- inode->i_dev = 0;
+ inode->i_dev = NODEV;
inode->i_blkbits = 0;
inode->i_ino = ++last_ino;
inode->i_flags = 0;
diff --git a/fs/intermezzo/cache.c b/fs/intermezzo/cache.c
index db9d6948b..b7ef2eb49 100644
--- a/fs/intermezzo/cache.c
+++ b/fs/intermezzo/cache.c
@@ -46,7 +46,7 @@ static struct list_head presto_caches[CACHES_SIZE];
static inline int presto_cache_hash(kdev_t dev)
{
- return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
+ return (CACHES_MASK) & ((0x000F & (kdev_val(dev))) + ((0x0F00 & (kdev_val(dev))) >>8));
}
inline void presto_cache_add(struct presto_cache *cache, kdev_t dev)
@@ -73,7 +73,7 @@ struct presto_cache *presto_find_cache(kdev_t dev)
lh = tmp = &(presto_caches[presto_cache_hash(dev)]);
while ( (tmp = lh->next) != lh ) {
cache = list_entry(tmp, struct presto_cache, cache_chain);
- if ( cache->cache_dev == dev ) {
+ if ( kdev_same(cache->cache_dev, dev) ) {
return cache;
}
}
@@ -90,7 +90,7 @@ struct presto_cache *presto_get_cache(struct inode *inode)
cache = presto_find_cache(inode->i_dev);
if ( !cache ) {
printk("WARNING: no presto cache for dev %x, ino %ld\n",
- inode->i_dev, inode->i_ino);
+ kdev_val(inode->i_dev), inode->i_ino);
EXIT;
return NULL;
}
@@ -174,7 +174,7 @@ int presto_ispresto(struct inode *inode)
cache = presto_get_cache(inode);
if ( !cache )
return 0;
- return (inode->i_dev == cache->cache_dev);
+ return (kdev_same(inode->i_dev, cache->cache_dev));
}
/* setup a cache structure when we need one */
diff --git a/fs/intermezzo/dcache.c b/fs/intermezzo/dcache.c
index d30910413..4b94a8ec3 100644
--- a/fs/intermezzo/dcache.c
+++ b/fs/intermezzo/dcache.c
@@ -16,7 +16,6 @@
#include <linux/errno.h>
#include <linux/locks.h>
#include <linux/slab.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
diff --git a/fs/intermezzo/ext_attr.c b/fs/intermezzo/ext_attr.c
index b2f4e1af0..8e32b9cb3 100644
--- a/fs/intermezzo/ext_attr.c
+++ b/fs/intermezzo/ext_attr.c
@@ -28,7 +28,6 @@
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <asm/segment.h>
#include <linux/smp_lock.h>
#include <linux/intermezzo_fs.h>
diff --git a/fs/intermezzo/inode.c b/fs/intermezzo/inode.c
index c4816a363..d756dcfc0 100644
--- a/fs/intermezzo/inode.c
+++ b/fs/intermezzo/inode.c
@@ -29,7 +29,6 @@
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <asm/segment.h>
#include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
diff --git a/fs/intermezzo/journal.c b/fs/intermezzo/journal.c
index d861e360a..df8f31533 100644
--- a/fs/intermezzo/journal.c
+++ b/fs/intermezzo/journal.c
@@ -14,7 +14,6 @@
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
diff --git a/fs/intermezzo/journal_ext2.c b/fs/intermezzo/journal_ext2.c
index 434e8fe23..ceeb9f941 100644
--- a/fs/intermezzo/journal_ext2.c
+++ b/fs/intermezzo/journal_ext2.c
@@ -12,7 +12,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/ext2_fs.h>
diff --git a/fs/intermezzo/journal_ext3.c b/fs/intermezzo/journal_ext3.c
index 1a2fea3e7..43a4740dd 100644
--- a/fs/intermezzo/journal_ext3.c
+++ b/fs/intermezzo/journal_ext3.c
@@ -17,7 +17,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
diff --git a/fs/intermezzo/journal_obdfs.c b/fs/intermezzo/journal_obdfs.c
index 6c0ea9ef7..3fdb83156 100644
--- a/fs/intermezzo/journal_obdfs.c
+++ b/fs/intermezzo/journal_obdfs.c
@@ -17,7 +17,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#ifdef CONFIG_OBDFS_FS
diff --git a/fs/intermezzo/journal_reiserfs.c b/fs/intermezzo/journal_reiserfs.c
index 233376bef..578251ff9 100644
--- a/fs/intermezzo/journal_reiserfs.c
+++ b/fs/intermezzo/journal_reiserfs.c
@@ -17,7 +17,6 @@
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#if 0
diff --git a/fs/intermezzo/journal_xfs.c b/fs/intermezzo/journal_xfs.c
index f6eacd0dc..fed141fdc 100644
--- a/fs/intermezzo/journal_xfs.c
+++ b/fs/intermezzo/journal_xfs.c
@@ -12,7 +12,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#ifdef CONFIG_FS_XFS
diff --git a/fs/intermezzo/presto.c b/fs/intermezzo/presto.c
index 3d51c30f2..1eba374ae 100644
--- a/fs/intermezzo/presto.c
+++ b/fs/intermezzo/presto.c
@@ -17,7 +17,6 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/locks.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
@@ -72,8 +71,8 @@ int presto_i2m(struct inode *inode)
cache = presto_get_cache(inode);
CDEBUG(D_PSDEV, "\n");
if ( !cache ) {
- printk("PRESTO: BAD: cannot find cache for dev %d, ino %ld\n",
- inode->i_dev, inode->i_ino);
+ printk("PRESTO: BAD: cannot find cache for dev %x, ino %ld\n",
+ kdev_val(inode->i_dev), inode->i_ino);
EXIT;
return -1;
}
diff --git a/fs/intermezzo/psdev.c b/fs/intermezzo/psdev.c
index 885b5270d..0384ab5c3 100644
--- a/fs/intermezzo/psdev.c
+++ b/fs/intermezzo/psdev.c
@@ -35,6 +35,7 @@
#include <linux/sched.h>
#include <linux/lp.h>
#include <linux/slab.h>
+#include <asm/ioctls.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
@@ -47,7 +48,6 @@
#include <linux/init.h>
#include <linux/list.h>
#include <asm/io.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/poll.h>
#include <asm/uaccess.h>
@@ -79,12 +79,12 @@ static inline struct upc_comm *presto_psdev_f2u(struct file *file)
{
int minor;
- if ( MAJOR(file->f_dentry->d_inode->i_rdev) != PRESTO_PSDEV_MAJOR ) {
+ if ( major(file->f_dentry->d_inode->i_rdev) != PRESTO_PSDEV_MAJOR ) {
EXIT;
return NULL;
}
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ minor = minor(file->f_dentry->d_inode->i_rdev);
if ( minor < 0 || minor >= MAX_PRESTODEV ) {
EXIT;
return NULL;
@@ -291,7 +291,7 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
}
len = readmount.io_len;
- minor = MINOR(dev);
+ minor = minor(dev);
PRESTO_ALLOC(tmp, char *, len);
if (!tmp) {
EXIT;
@@ -628,7 +628,7 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT;
return error;
}
- minor = MINOR(dev);
+ minor = minor(dev);
if (cmd == PRESTO_SETOPT)
error = dosetopt(minor, &kopt);
diff --git a/fs/intermezzo/super.c b/fs/intermezzo/super.c
index a0d17cbf9..2b011f171 100644
--- a/fs/intermezzo/super.c
+++ b/fs/intermezzo/super.c
@@ -159,7 +159,7 @@ static int presto_get_minor(char *dev_path, int *minor)
{
struct nameidata nd;
struct dentry *dentry;
- kdev_t devno = 0;
+ kdev_t devno = NODEV;
int error;
ENTRY;
@@ -188,19 +188,19 @@ static int presto_get_minor(char *dev_path, int *minor)
}
devno = dentry->d_inode->i_rdev;
- if ( MAJOR(devno) != PRESTO_PSDEV_MAJOR ) {
+ if ( major(devno) != PRESTO_PSDEV_MAJOR ) {
EXIT;
goto out;
}
- if ( MINOR(devno) >= MAX_PRESTODEV ) {
+ if ( minor(devno) >= MAX_PRESTODEV ) {
EXIT;
goto out;
}
EXIT;
out:
- *minor = MINOR(devno);
+ *minor = minor(devno);
path_release(&nd);
return 0;
}
diff --git a/fs/intermezzo/sysctl.c b/fs/intermezzo/sysctl.c
index 2e31a273e..212e4c19f 100644
--- a/fs/intermezzo/sysctl.c
+++ b/fs/intermezzo/sysctl.c
@@ -16,7 +16,6 @@
#include <linux/ctype.h>
#include <linux/init.h>
#include <asm/bitops.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/utsname.h>
#include <linux/blk.h>
@@ -162,15 +161,17 @@ int dosetopt(int minor, struct psdev_opt *opt)
* current presto cache.
*/
int errorval = upc_comms[minor].uc_errorval;
+ kdev_t kdev = mk_kdev(MAJOR(-errorval), MINOR(-errorval));
if (errorval < 0) {
if (newval == 0)
- set_device_ro(-errorval, 0);
+ set_device_ro(kdev, 0);
else
printk("device %s already read only\n",
- kdevname(-errorval));
+ kdevname(kdev));
} else {
+ kdev = mk_kdev(MAJOR(-newval), MINOR(-newval));
if (newval < 0)
- set_device_ro(-newval, 1);
+ set_device_ro(kdev, 1);
upc_comms[minor].uc_errorval = newval;
CDEBUG(D_PSDEV, "setting errorval to %d\n", newval);
}
@@ -225,9 +226,10 @@ int dogetopt(int minor, struct psdev_opt *opt)
#ifdef PSDEV_DEBUG
case PSDEV_ERRORVAL: {
int errorval = upc_comms[minor].uc_errorval;
- if (errorval < 0 && is_read_only(-errorval))
+ kdev_t kdev = mk_kdev(MAJOR(-errorval), MINOR(-errorval));
+ if (errorval < 0 && is_read_only(kdev))
printk(KERN_INFO "device %s has been set read-only\n",
- kdevname(-errorval));
+ kdevname(kdev));
opt->optval = upc_comms[minor].uc_errorval;
break;
}
diff --git a/fs/intermezzo/upcall.c b/fs/intermezzo/upcall.c
index ebb40c0c0..95ecdef0b 100644
--- a/fs/intermezzo/upcall.c
+++ b/fs/intermezzo/upcall.c
@@ -20,7 +20,6 @@
*/
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/signal.h>
#include <linux/signal.h>
@@ -37,7 +36,6 @@
#include <linux/string.h>
#include <asm/uaccess.h>
#include <linux/vmalloc.h>
-#include <asm/segment.h>
#include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
diff --git a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c
index 8d37756a7..f8fbdc963 100644
--- a/fs/intermezzo/vfs.c
+++ b/fs/intermezzo/vfs.c
@@ -136,7 +136,7 @@ inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
if (errorval && errorval == (long)value && !is_read_only(dev)) {
CDEBUG(D_SUPER, "setting device %s read only\n", kdevname(dev));
BLKDEV_FAIL(dev, 1);
- upc_comms[minor].uc_errorval = -dev;
+ upc_comms[minor].uc_errorval = -kdev_val(dev);
}
}
#else
@@ -602,7 +602,7 @@ int presto_do_link(struct presto_file_set *fset, struct dentry *old_dentry,
goto exit_lock;
error = -EXDEV;
- if (dir->d_inode->i_dev != inode->i_dev)
+ if (!kdev_same(dir->d_inode->i_dev, inode->i_dev))
goto exit_lock;
/*
@@ -1609,7 +1609,7 @@ int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent,
if (error)
return error;
- if (new_dir->i_dev != old_dir->i_dev)
+ if (!kdev_same(new_dir->i_dev, old_dir->i_dev))
return -EXDEV;
if (!new_dentry->d_inode)
@@ -1690,7 +1690,7 @@ int presto_rename_other(struct presto_file_set *fset, struct dentry *old_parent,
if (error)
return error;
- if (new_dir->i_dev != old_dir->i_dev)
+ if (!kdev_same(new_dir->i_dev, old_dir->i_dev))
return -EXDEV;
if (!new_dentry->d_inode)
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index cbf4cabc3..b1164e3b1 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -469,7 +469,6 @@ static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
static struct super_block *isofs_read_super(struct super_block *s, void *data,
int silent)
{
- kdev_t dev = s->s_dev;
struct buffer_head * bh = NULL, *pri_bh = NULL;
struct hs_primary_descriptor * h_pri = NULL;
struct iso_primary_descriptor * pri = NULL;
@@ -480,7 +479,6 @@ static struct super_block *isofs_read_super(struct super_block *s, void *data,
int iso_blknum, block;
int orig_zonesize;
int table;
- unsigned int blocksize, blocksize_bits;
unsigned int vol_desc_start;
unsigned long first_data_zone;
struct inode * inode;
@@ -508,26 +506,10 @@ static struct super_block *isofs_read_super(struct super_block *s, void *data,
* larger than the blocksize the user specified, then use
* that value.
*/
- blocksize = get_hardsect_size(dev);
- if(blocksize > opt.blocksize) {
- /*
- * Force the blocksize we are going to use to be the
- * hardware blocksize.
- */
- opt.blocksize = blocksize;
- }
-
- blocksize_bits = 0;
- {
- int i = opt.blocksize;
- while (i != 1){
- blocksize_bits++;
- i >>=1;
- }
- }
-
- set_blocksize(dev, opt.blocksize);
- s->s_blocksize = opt.blocksize;
+ /*
+ * What if bugger tells us to go beyond page size?
+ */
+ opt.blocksize = sb_min_blocksize(s, opt.blocksize);
s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
@@ -540,7 +522,7 @@ static struct super_block *isofs_read_super(struct super_block *s, void *data,
struct hs_volume_descriptor * hdp;
struct iso_volume_descriptor * vdp;
- block = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits);
+ block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits);
if (!(bh = sb_bread(s, block)))
goto out_no_read;
@@ -651,7 +633,7 @@ root_found:
* blocks that were 512 bytes (which should only very rarely
* happen.)
*/
- if(blocksize != 0 && orig_zonesize < blocksize)
+ if(orig_zonesize < opt.blocksize)
goto out_bad_size;
/* RDE: convert log zone size to bit shift */
@@ -734,15 +716,7 @@ root_found:
* entries. By forcing the blocksize in this way, we ensure
* that we will never be required to do this.
*/
- if ( orig_zonesize != opt.blocksize ) {
- set_blocksize(dev, orig_zonesize);
-#ifndef BEQUIET
- printk(KERN_DEBUG
- "ISOFS: Forcing new log zone size:%d\n", orig_zonesize);
-#endif
- }
- s->s_blocksize = orig_zonesize;
- s->s_blocksize_bits = s -> u.isofs_sb.s_log_zone_size;
+ sb_set_blocksize(s, orig_zonesize);
s->u.isofs_sb.s_nls_iocharset = NULL;
@@ -845,7 +819,7 @@ out_iput:
out_no_read:
printk(KERN_WARNING "isofs_read_super: "
"bread failed, dev=%s, iso_blknum=%d, block=%d\n",
- kdevname(dev), iso_blknum, block);
+ s->s_id, iso_blknum, block);
goto out_unlock;
out_bad_zone_size:
printk(KERN_WARNING "Bad logical zone size %ld\n",
@@ -853,7 +827,7 @@ out_bad_zone_size:
goto out_freebh;
out_bad_size:
printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
- orig_zonesize, blocksize);
+ orig_zonesize, opt.blocksize);
goto out_freebh;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
out_no_support:
@@ -890,7 +864,7 @@ static int isofs_statfs (struct super_block *sb, struct statfs *buf)
* (0 == error.)
*/
int isofs_get_blocks(struct inode *inode, sector_t iblock,
- struct buffer_head **bh_result, unsigned long nblocks)
+ struct buffer_head **bh, unsigned long nblocks)
{
unsigned long b_off;
unsigned offset, sect_size;
@@ -952,16 +926,14 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock,
}
}
- if ( *bh_result ) {
- (*bh_result)->b_dev = inode->i_dev;
- (*bh_result)->b_blocknr = firstext + b_off - offset;
- (*bh_result)->b_state |= (1UL << BH_Mapped);
+ if ( *bh ) {
+ map_bh(*bh, inode->i_sb, firstext + b_off - offset);
} else {
- *bh_result = sb_getblk(inode->i_sb, firstext+b_off-offset);
- if ( !*bh_result )
+ *bh = sb_getblk(inode->i_sb, firstext+b_off-offset);
+ if ( !*bh )
goto abort;
}
- bh_result++; /* Next buffer head */
+ bh++; /* Next buffer head */
b_off++; /* Next buffer offset */
nblocks--;
rv++;
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
index 427595f38..15d2370bd 100644
--- a/fs/isofs/joliet.c
+++ b/fs/isofs/joliet.c
@@ -8,7 +8,7 @@
#include <linux/string.h>
#include <linux/nls.h>
-#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/iso_fs.h>
#include <asm/unaligned.h>
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 13e79d4d5..2ee717c63 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -12,7 +12,7 @@
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
-#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/config.h> /* Joliet? */
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 6906a8eba..f5a2e2e67 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -297,9 +297,9 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
* stored in the low field, and use that.
*/
if((low & ~0xff) && high == 0) {
- inode->i_rdev = MKDEV(low >> 8, low & 0xff);
+ inode->i_rdev = mk_kdev(low >> 8, low & 0xff);
} else {
- inode->i_rdev = MKDEV(high, low);
+ inode->i_rdev = mk_kdev(high, low);
}
}
break;
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index cf381d4fa..49b7b3592 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -774,7 +774,7 @@ journal_t * journal_init_inode (struct inode *inode)
journal->j_inode = inode;
jbd_debug(1,
"journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
- journal, bdevname(inode->i_dev), inode->i_ino,
+ journal, inode->i_sb->s_id, inode->i_ino,
(long long) inode->i_size,
inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index b8e44cfed..67342dc52 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -79,9 +79,9 @@ jffs_read_super(struct super_block *sb, void *data, int silent)
struct jffs_control *c;
D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
- kdevname(dev)));
+ sb->s_id));
- if (MAJOR(dev) != MTD_BLOCK_MAJOR) {
+ if (major(dev) != MTD_BLOCK_MAJOR) {
printk(KERN_WARNING "JFFS: Trying to mount a "
"non-mtd device.\n");
return 0;
@@ -119,7 +119,7 @@ jffs_read_super(struct super_block *sb, void *data, int silent)
if (jffs_register_jffs_proc_dir(dev, c) < 0) {
printk(KERN_WARNING "JFFS: Failed to initialize the JFFS "
"proc file system for device %s.\n",
- kdevname(dev));
+ sb->s_id);
}
#endif
@@ -144,7 +144,7 @@ jffs_read_super(struct super_block *sb, void *data, int silent)
D1(printk(KERN_NOTICE "JFFS: GC thread pid=%d.\n", (int) c->thread_pid));
D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
- kdevname(dev)));
+ sb->s_id));
return sb;
jffs_sb_err3:
@@ -153,7 +153,7 @@ jffs_sb_err2:
jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
jffs_sb_err1:
printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
- kdevname(dev));
+ sb->s_id);
return 0;
}
@@ -163,7 +163,6 @@ static void
jffs_put_super(struct super_block *sb)
{
struct jffs_control *c = (struct jffs_control *) sb->u.generic_sbp;
- D1(kdev_t dev = sb->s_dev);
D2(printk("jffs_put_super()\n"));
@@ -181,7 +180,7 @@ jffs_put_super(struct super_block *sb)
jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
- kdevname(dev)));
+ sb->s_id));
}
@@ -365,7 +364,6 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
inode->i_ctime = raw_inode->ctime;
inode->i_blksize = PAGE_SIZE;
inode->i_blocks = (inode->i_size + 511) >> 9;
- inode->i_version = 0;
f = jffs_find_file(c, raw_inode->ino);
@@ -1023,7 +1021,6 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
from the in-memory file system structures. */
jffs_insert_node(c, del_f, &raw_inode, 0, del_node);
- dir->i_version = ++event;
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(dir);
inode->i_nlink--;
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 1b0c24da2..c40a8fb0a 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -795,7 +795,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in
if ((mode & S_IFMT) == S_IFBLK ||
(mode & S_IFMT) == S_IFCHR) {
- dev = (MAJOR(to_kdev_t(rdev)) << 8) | MINOR(to_kdev_t(rdev));
+ dev = (MAJOR(rdev) << 8) | MINOR(rdev);
devlen = sizeof(dev);
}
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index f9d2d257f..4771c02ee 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -105,8 +105,8 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
if ((inode->i_mode & S_IFMT) == S_IFBLK ||
(inode->i_mode & S_IFMT) == S_IFCHR) {
/* For these, we don't actually need to read the old node */
- dev = (MAJOR(to_kdev_t(dentry->d_inode->i_rdev)) << 8) |
- MINOR(to_kdev_t(dentry->d_inode->i_rdev));
+ dev = (major(dentry->d_inode->i_rdev) << 8) |
+ minor(dentry->d_inode->i_rdev);
mdata = (char *)&dev;
mdatalen = sizeof(dev);
D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 17a7fd417..4cdb28557 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -269,8 +269,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
if ((inode->i_mode & S_IFMT) == S_IFBLK ||
(inode->i_mode & S_IFMT) == S_IFCHR) {
/* For these, we don't actually need to read the old node */
- dev = (MAJOR(to_kdev_t(inode->i_rdev)) << 8) |
- MINOR(to_kdev_t(inode->i_rdev));
+ dev = (major(inode->i_rdev) << 8) |
+ minor(inode->i_rdev);
mdata = (char *)&dev;
mdatalen = sizeof(dev);
D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index c4cf15640..7e9e7bcbc 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -197,9 +197,9 @@ static struct super_block *jffs2_read_super(struct super_block *sb, void *data,
struct inode *root_i;
int i;
- D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", kdevname(sb->s_dev)));
+ D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", sb->s_id));
- if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) {
+ if (major(sb->s_dev) != MTD_BLOCK_MAJOR) {
if (!silent)
printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev));
return NULL;
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 2380914c5..e8af1895c 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -31,7 +31,7 @@
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
- * $Id: write.c,v 1.28 2001/05/01 16:25:25 dwmw2 Exp $
+ * $Id: write.c,v 1.30 2001/12/30 16:01:11 dwmw2 Exp $
*
*/
@@ -207,8 +207,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct inode *inode, struct jffs2_raw
}
raw->flash_offset = flash_ofs;
raw->totlen = PAD(ri->totlen);
- raw->next_in_ino = f->inocache->nodes;
- f->inocache->nodes = raw;
raw->next_phys = NULL;
fn->ofs = ri->offset;
@@ -222,6 +220,14 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct inode *inode, struct jffs2_raw
sizeof(*ri)+datalen, flash_ofs, ret, retlen);
/* Mark the space as dirtied */
if (retlen) {
+ /* Doesn't belong to any inode */
+ raw->next_in_ino = NULL;
+
+ /* Don't change raw->size to match retlen. We may have
+ written the node header already, and only the data will
+ seem corrupted, in which case the scan would skip over
+ any node we write before the original intended end of
+ this node */
jffs2_add_physical_node_ref(c, raw, sizeof(*ri)+datalen, 1);
jffs2_mark_node_obsolete(c, raw);
} else {
@@ -237,6 +243,11 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct inode *inode, struct jffs2_raw
}
/* Mark the space used */
jffs2_add_physical_node_ref(c, raw, retlen, 0);
+
+ /* Link into per-inode list */
+ raw->next_in_ino = f->inocache->nodes;
+ f->inocache->nodes = raw;
+
D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", flash_ofs, ri->dsize, ri->csize, ri->node_crc, ri->data_crc, ri->totlen));
if (writelen)
*writelen = retlen;
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 2b8113d74..db4be6f10 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -306,8 +306,9 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
struct nlm_block *block;
int error;
- dprintk("lockd: nlmsvc_lock(%04x/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
- file->f_file.f_dentry->d_inode->i_dev,
+ dprintk("lockd: nlmsvc_lock(%02x:%02x/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
+ major(file->f_file.f_dentry->d_inode->i_dev),
+ minor(file->f_file.f_dentry->d_inode->i_dev),
file->f_file.f_dentry->d_inode->i_ino,
lock->fl.fl_type, lock->fl.fl_pid,
(long long)lock->fl.fl_start,
@@ -385,8 +386,9 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
{
struct file_lock *fl;
- dprintk("lockd: nlmsvc_testlock(%04x/%ld, ty=%d, %Ld-%Ld)\n",
- file->f_file.f_dentry->d_inode->i_dev,
+ dprintk("lockd: nlmsvc_testlock(%02x:%02x/%ld, ty=%d, %Ld-%Ld)\n",
+ major(file->f_file.f_dentry->d_inode->i_dev),
+ minor(file->f_file.f_dentry->d_inode->i_dev),
file->f_file.f_dentry->d_inode->i_ino,
lock->fl.fl_type,
(long long)lock->fl.fl_start,
@@ -417,8 +419,9 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
{
int error;
- dprintk("lockd: nlmsvc_unlock(%04x/%ld, pi=%d, %Ld-%Ld)\n",
- file->f_file.f_dentry->d_inode->i_dev,
+ dprintk("lockd: nlmsvc_unlock(%02x:%02x/%ld, pi=%d, %Ld-%Ld)\n",
+ major(file->f_file.f_dentry->d_inode->i_dev),
+ minor(file->f_file.f_dentry->d_inode->i_dev),
file->f_file.f_dentry->d_inode->i_ino,
lock->fl.fl_pid,
(long long)lock->fl.fl_start,
@@ -445,8 +448,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
{
struct nlm_block *block;
- dprintk("lockd: nlmsvc_cancel(%04x/%ld, pi=%d, %Ld-%Ld)\n",
- file->f_file.f_dentry->d_inode->i_dev,
+ dprintk("lockd: nlmsvc_cancel(%02x:%02x/%ld, pi=%d, %Ld-%Ld)\n",
+ major(file->f_file.f_dentry->d_inode->i_dev),
+ minor(file->f_file.f_dentry->d_inode->i_dev),
file->f_file.f_dentry->d_inode->i_ino,
lock->fl.fl_pid,
(long long)lock->fl.fl_start,
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 6347bb169..9d273604a 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -74,7 +74,7 @@ void minix_free_block(struct inode * inode, int block)
bh = sb->u.minix_sb.s_zmap[zone];
if (!minix_test_and_clear_bit(bit,bh->b_data))
printk("free_block (%s:%d): bit already cleared\n",
- kdevname(sb->s_dev), block);
+ sb->s_id, block);
mark_buffer_dirty(bh);
return;
}
@@ -127,7 +127,7 @@ minix_V1_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
if (!ino || ino > sbi->s_ninodes) {
printk("Bad inode number on dev %s: %ld is out of range\n",
- bdevname(sb->s_dev), ino);
+ sb->s_id, ino);
return NULL;
}
ino--;
@@ -152,7 +152,7 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
*bh = NULL;
if (!ino || ino > sbi->s_ninodes) {
printk("Bad inode number on dev %s: %ld is out of range\n",
- bdevname(sb->s_dev), ino);
+ sb->s_id, ino);
return NULL;
}
ino--;
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 5525a48a9..7cd92b2d6 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -126,9 +126,7 @@ static struct super_block *minix_read_super(struct super_block *s, void *data,
struct buffer_head **map;
struct minix_super_block *ms;
int i, block;
- kdev_t dev = s->s_dev;
struct inode *root_inode;
- unsigned int hblock;
struct minix_sb_info *sbi = &s->u.minix_sb;
/* N.B. These should be compile-time tests.
@@ -138,13 +136,9 @@ static struct super_block *minix_read_super(struct super_block *s, void *data,
if (64 != sizeof(struct minix2_inode))
panic("bad V2 i-node size");
- hblock = get_hardsect_size(dev);
- if (hblock > BLOCK_SIZE)
+ if (!sb_set_blocksize(s, BLOCK_SIZE))
goto out_bad_hblock;
- set_blocksize(dev, BLOCK_SIZE);
- s->s_blocksize = BLOCK_SIZE;
- s->s_blocksize_bits = BLOCK_SIZE_BITS;
if (!(bh = sb_bread(s, 1)))
goto out_bad_sb;
@@ -214,7 +208,7 @@ static struct super_block *minix_read_super(struct super_block *s, void *data,
/* set up enough so that it can read an inode */
s->s_op = &minix_sops;
root_inode = iget(s, MINIX_ROOT_INO);
- if (!root_inode)
+ if (!root_inode || is_bad_inode(root_inode))
goto out_no_root;
s->s_root = d_alloc_root(root_inode);
@@ -264,7 +258,7 @@ out_no_map:
out_no_fs:
if (!silent)
printk("VFS: Can't find a Minix or Minix V2 filesystem on device "
- "%s.\n", kdevname(dev));
+ "%s.\n", s->s_id);
out_release:
brelse(bh);
goto out;
@@ -353,8 +347,10 @@ static void V1_minix_read_inode(struct inode * inode)
int i;
raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
- if (!raw_inode)
+ if (!raw_inode) {
+ make_bad_inode(inode);
return;
+ }
inode->i_mode = raw_inode->i_mode;
inode->i_uid = (uid_t)raw_inode->i_uid;
inode->i_gid = (gid_t)raw_inode->i_gid;
@@ -378,8 +374,10 @@ static void V2_minix_read_inode(struct inode * inode)
int i;
raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
- if (!raw_inode)
+ if (!raw_inode) {
+ make_bad_inode(inode);
return;
+ }
inode->i_mode = raw_inode->i_mode;
inode->i_uid = (uid_t)raw_inode->i_uid;
inode->i_gid = (gid_t)raw_inode->i_gid;
@@ -490,9 +488,8 @@ int minix_sync_inode(struct inode * inode)
wait_on_buffer(bh);
if (buffer_req(bh) && !buffer_uptodate(bh))
{
- printk ("IO error syncing minix inode ["
- "%s:%08lx]\n",
- kdevname(inode->i_dev), inode->i_ino);
+ printk ("IO error syncing minix inode [%s:%08lx]\n",
+ inode->i_sb->s_id, inode->i_ino);
err = -1;
}
}
diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c
index 373df9896..41c0acb30 100644
--- a/fs/minix/itree_common.c
+++ b/fs/minix/itree_common.c
@@ -141,7 +141,7 @@ changed:
}
static inline int get_block(struct inode * inode, sector_t block,
- struct buffer_head *bh_result, int create)
+ struct buffer_head *bh, int create)
{
int err = -EIO;
int offsets[DEPTH];
@@ -160,9 +160,7 @@ reread:
/* Simplest case - block found, no allocation needed */
if (!partial) {
got_it:
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = block_to_cpu(chain[depth-1].key);
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh, inode->i_sb, block_to_cpu(chain[depth-1].key));
/* Clean up and exit */
partial = chain+depth-1; /* the whole chain */
goto cleanup;
@@ -196,7 +194,7 @@ out:
if (splice_branch(inode, chain, partial, left) < 0)
goto changed;
- bh_result->b_state |= (1UL << BH_New);
+ bh->b_state |= (1UL << BH_New);
goto got_it;
changed:
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 448a7125d..92ece6210 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -476,7 +476,7 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
if (error)
goto out;
}
- new_dir->i_version = ++event;
+ new_dir->i_version++;
/* There we go */
@@ -491,7 +491,7 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
else
MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
mark_inode_dirty(old_inode);
- old_dir->i_version = ++event;
+ old_dir->i_version++;
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(old_dir);
if (new_inode) {
@@ -528,7 +528,7 @@ degenerate_case:
else
MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
mark_inode_dirty(old_inode);
- old_dir->i_version = ++event;
+ old_dir->i_version++;
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(old_dir);
return 0;
diff --git a/fs/namei.c b/fs/namei.c
index 590d31c4e..20d3add2c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1589,7 +1589,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
goto exit_lock;
error = -EXDEV;
- if (dir->i_dev != inode->i_dev)
+ if (dir->i_sb != inode->i_sb)
goto exit_lock;
/*
@@ -1707,7 +1707,7 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
if (error)
return error;
- if (new_dir->i_dev != old_dir->i_dev)
+ if (new_dir->i_sb != old_dir->i_sb)
return -EXDEV;
if (!new_dentry->d_inode)
@@ -1787,7 +1787,7 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
if (error)
return error;
- if (new_dir->i_dev != old_dir->i_dev)
+ if (new_dir->i_sb != old_dir->i_sb)
return -EXDEV;
if (!new_dentry->d_inode)
diff --git a/fs/namespace.c b/fs/namespace.c
index 7d08d012f..093ed8ef6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -10,27 +10,26 @@
#include <linux/config.h>
#include <linux/slab.h>
+#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/quotaops.h>
#include <linux/acct.h>
#include <linux/module.h>
#include <linux/seq_file.h>
+#include <linux/namespace.h>
#include <asm/uaccess.h>
struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
int do_remount_sb(struct super_block *sb, int flags, void * data);
void kill_super(struct super_block *sb);
+int __init init_rootfs(void);
static struct list_head *mount_hashtable;
static int hash_mask, hash_bits;
static kmem_cache_t *mnt_cache;
-static LIST_HEAD(vfsmntlist);
-static DECLARE_MUTEX(mount_sem);
-static struct vfsmount *root_vfsmnt;
-
static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
{
unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES);
@@ -96,7 +95,7 @@ static int check_mnt(struct vfsmount *mnt)
while (mnt->mnt_parent != mnt)
mnt = mnt->mnt_parent;
spin_unlock(&dcache_lock);
- return mnt == root_vfsmnt;
+ return mnt == current->namespace->root;
}
static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
@@ -164,26 +163,29 @@ void __mntput(struct vfsmount *mnt)
/* iterator */
static void *m_start(struct seq_file *m, loff_t *pos)
{
+ struct namespace *n = m->private;
struct list_head *p;
- loff_t n = *pos;
+ loff_t l = *pos;
- down(&mount_sem);
- list_for_each(p, &vfsmntlist)
- if (!n--)
+ down_read(&n->sem);
+ list_for_each(p, &n->list)
+ if (!l--)
return list_entry(p, struct vfsmount, mnt_list);
return NULL;
}
static void *m_next(struct seq_file *m, void *v, loff_t *pos)
{
+ struct namespace *n = m->private;
struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
(*pos)++;
- return p==&vfsmntlist ? NULL : list_entry(p, struct vfsmount, mnt_list);
+ return p==&n->list ? NULL : list_entry(p, struct vfsmount, mnt_list);
}
static void m_stop(struct seq_file *m, void *v)
{
- up(&mount_sem);
+ struct namespace *n = m->private;
+ up_read(&n->sem);
}
static inline void mangle(struct seq_file *m, const char *s)
@@ -329,7 +331,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
return retval;
}
- down(&mount_sem);
+ down_write(&current->namespace->sem);
spin_lock(&dcache_lock);
if (atomic_read(&sb->s_active) == 1) {
@@ -337,7 +339,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
spin_unlock(&dcache_lock);
lock_kernel();
DQUOT_OFF(sb);
- acct_auto_close(sb->s_dev);
+ acct_auto_close(sb);
unlock_kernel();
spin_lock(&dcache_lock);
}
@@ -348,7 +350,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
retval = 0;
}
spin_unlock(&dcache_lock);
- up(&mount_sem);
+ up_write(&current->namespace->sem);
return retval;
}
@@ -478,7 +480,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
struct list_head head;
attach_mnt(mnt, nd);
list_add_tail(&head, &mnt->mnt_list);
- list_splice(&head, vfsmntlist.prev);
+ list_splice(&head, current->namespace->list.prev);
mntget(mnt);
err = 0;
}
@@ -505,7 +507,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
if (err)
return err;
- down(&mount_sem);
+ down_write(&current->namespace->sem);
err = -EINVAL;
if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) {
err = -ENOMEM;
@@ -525,7 +527,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
mntput(mnt);
}
- up(&mount_sem);
+ up_write(&current->namespace->sem);
path_release(&old_nd);
return err;
}
@@ -572,7 +574,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name)
if (err)
return err;
- down(&mount_sem);
+ down_write(&current->namespace->sem);
while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
;
err = -EINVAL;
@@ -612,7 +614,7 @@ out2:
out1:
up(&nd->dentry->d_inode->i_zombie);
out:
- up(&mount_sem);
+ up_write(&current->namespace->sem);
if (!err)
path_release(&parent_nd);
path_release(&old_nd);
@@ -637,7 +639,7 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags,
if (IS_ERR(mnt))
goto out;
- down(&mount_sem);
+ down_write(&current->namespace->sem);
/* Something was mounted here while we slept */
while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
;
@@ -653,7 +655,7 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags,
mnt->mnt_flags = mnt_flags;
err = graft_tree(mnt, nd);
unlock:
- up(&mount_sem);
+ up_write(&current->namespace->sem);
mntput(mnt);
out:
return err;
@@ -753,6 +755,86 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
return retval;
}
+int copy_namespace(int flags, struct task_struct *tsk)
+{
+ struct namespace *namespace = tsk->namespace;
+ struct namespace *new_ns;
+ struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
+ struct fs_struct *fs = tsk->fs;
+
+ if (!namespace)
+ return 0;
+
+ get_namespace(namespace);
+
+ if (! (flags & CLONE_NEWNS))
+ return 0;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ put_namespace(namespace);
+ return -EPERM;
+ }
+
+ new_ns = kmalloc(sizeof(struct namespace *), GFP_KERNEL);
+ if (!new_ns)
+ goto out;
+
+ atomic_set(&new_ns->count, 1);
+ init_rwsem(&new_ns->sem);
+ new_ns->root = NULL;
+ INIT_LIST_HEAD(&new_ns->list);
+
+ down_write(&tsk->namespace->sem);
+ /* First pass: copy the tree topology */
+ new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root);
+ spin_lock(&dcache_lock);
+ list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
+ spin_unlock(&dcache_lock);
+
+ /* Second pass: switch the tsk->fs->* elements */
+ if (fs) {
+ struct vfsmount *p, *q;
+ write_lock(&fs->lock);
+
+ p = namespace->root;
+ q = new_ns->root;
+ while (p) {
+ if (p == fs->rootmnt) {
+ rootmnt = p;
+ fs->rootmnt = mntget(q);
+ }
+ if (p == fs->pwdmnt) {
+ pwdmnt = p;
+ fs->pwdmnt = mntget(q);
+ }
+ if (p == fs->altrootmnt) {
+ altrootmnt = p;
+ fs->altrootmnt = mntget(q);
+ }
+ p = next_mnt(p, namespace->root);
+ q = next_mnt(q, new_ns->root);
+ }
+ write_unlock(&fs->lock);
+ }
+ up_write(&tsk->namespace->sem);
+
+ tsk->namespace = new_ns;
+
+ if (rootmnt)
+ mntput(rootmnt);
+ if (pwdmnt)
+ mntput(pwdmnt);
+ if (altrootmnt)
+ mntput(altrootmnt);
+
+ put_namespace(namespace);
+ return 0;
+
+out:
+ put_namespace(namespace);
+ return -ENOMEM;
+}
+
asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
unsigned long flags, void * data)
{
@@ -871,7 +953,7 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
user_nd.mnt = mntget(current->fs->rootmnt);
user_nd.dentry = dget(current->fs->root);
read_unlock(&current->fs->lock);
- down(&mount_sem);
+ down_write(&current->namespace->sem);
down(&old_nd.dentry->d_inode->i_zombie);
error = -EINVAL;
if (!check_mnt(user_nd.mnt))
@@ -916,7 +998,7 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
path_release(&parent_nd);
out2:
up(&old_nd.dentry->d_inode->i_zombie);
- up(&mount_sem);
+ up_write(&current->namespace->sem);
path_release(&user_nd);
path_release(&old_nd);
out1:
@@ -929,95 +1011,34 @@ out3:
goto out2;
}
-/*
- * Absolutely minimal fake fs - only empty root directory and nothing else.
- * In 2.5 we'll use ramfs or tmpfs, but for now it's all we need - just
- * something to go with root vfsmount.
- */
-static struct inode_operations rootfs_dir_inode_operations;
-static struct file_operations rootfs_dir_operations;
-static int rootfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct inode * inode = new_inode(dir->i_sb);
- int error = -ENOSPC;
- if (inode) {
- inode->i_mode = S_IFDIR|mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
- inode->i_op = &rootfs_dir_inode_operations;
- inode->i_fop = &rootfs_dir_operations;
- d_instantiate(dentry, inode);
- dget(dentry);
- error = 0;
- }
- return error;
-}
-static int rootfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
-{
- struct inode * inode = new_inode(dir->i_sb);
- int error = -ENOSPC;
- if (inode) {
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
- init_special_inode(inode, mode, dev);
- d_instantiate(dentry, inode);
- dget(dentry);
- error = 0;
- }
- return error;
-}
-static int rootfs_unlink(struct inode * dir, struct dentry *dentry)
-{
- dentry->d_inode->i_nlink--;
- dput(dentry);
- return 0;
-}
-static struct dentry *rootfs_lookup(struct inode *dir, struct dentry *dentry)
-{
- d_add(dentry, NULL);
- return NULL;
-}
-static struct file_operations rootfs_dir_operations = {
- read: generic_read_dir,
- readdir: dcache_readdir,
-};
-static struct inode_operations rootfs_dir_inode_operations = {
- lookup: rootfs_lookup,
- mkdir: rootfs_mkdir,
- mknod: rootfs_mknod,
- unlink: rootfs_unlink,
-};
-static struct super_block *rootfs_read_super(struct super_block * sb, void * data, int silent)
+static void __init init_mount_tree(void)
{
- struct inode * inode;
- struct dentry * root;
- static struct super_operations s_ops = {};
- sb->s_op = &s_ops;
- inode = new_inode(sb);
- if (!inode)
- return NULL;
- inode->i_mode = S_IFDIR|0555;
- inode->i_uid = inode->i_gid = 0;
- inode->i_op = &rootfs_dir_inode_operations;
- inode->i_fop = &rootfs_dir_operations;
- root = d_alloc_root(inode);
- if (!root) {
- iput(inode);
- return NULL;
+ struct vfsmount *mnt;
+ struct namespace *namespace;
+ struct task_struct *p;
+
+ mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
+ if (IS_ERR(mnt))
+ panic("Can't create rootfs");
+ namespace = kmalloc(sizeof(*namespace), GFP_KERNEL);
+ if (!namespace)
+ panic("Can't allocate initial namespace");
+ atomic_set(&namespace->count, 1);
+ INIT_LIST_HEAD(&namespace->list);
+ init_rwsem(&namespace->sem);
+ list_add(&mnt->mnt_list, &namespace->list);
+ namespace->root = mnt;
+
+ init_task.namespace = namespace;
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ get_namespace(namespace);
+ p->namespace = namespace;
}
- sb->s_root = root;
- return sb;
-}
-static DECLARE_FSTYPE(root_fs_type, "rootfs", rootfs_read_super, FS_NOMOUNT);
+ read_unlock(&tasklist_lock);
-static void __init init_mount_tree(void)
-{
- register_filesystem(&root_fs_type);
- root_vfsmnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
- if (IS_ERR(root_vfsmnt))
- panic("can't allocate root vfsmount");
- set_fs_pwd(current->fs, root_vfsmnt, root_vfsmnt->mnt_root);
- set_fs_root(current->fs, root_vfsmnt, root_vfsmnt->mnt_root);
+ set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root);
+ set_fs_root(current->fs, namespace->root, namespace->root->mnt_root);
}
void __init mnt_init(unsigned long mempages)
@@ -1075,5 +1096,6 @@ void __init mnt_init(unsigned long mempages)
d++;
i--;
} while (i);
+ init_rootfs();
init_mount_tree();
}
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 37b4e581e..4054697f6 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -181,7 +181,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
inode->i_nlink = 1;
inode->i_uid = server->m.uid;
inode->i_gid = server->m.gid;
- inode->i_rdev = 0;
+ inode->i_rdev = NODEV;
inode->i_blksize = NCP_BLOCK_SIZE;
inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
index 52f095848..843aed064 100644
--- a/fs/ncpfs/symlink.c
+++ b/fs/ncpfs/symlink.c
@@ -21,7 +21,6 @@
#ifdef CONFIG_NCPFS_EXTRAS
#include <asm/uaccess.h>
-#include <asm/segment.h>
#include <linux/errno.h>
#include <linux/fs.h>
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 68513e6af..f4423fd21 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -643,8 +643,8 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
struct nfs_fh fhandle;
int error;
- dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: create(%s/%ld, %s\n", dir->i_sb->s_id,
+ dir->i_ino, dentry->d_name.name);
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
@@ -675,8 +675,8 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde
struct nfs_fh fhandle;
int error;
- dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id,
+ dir->i_ino, dentry->d_name.name);
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
@@ -701,8 +701,8 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
struct nfs_fh fhandle;
int error;
- dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: mkdir(%s/%ld, %s\n", dir->i_sb->s_id,
+ dir->i_ino, dentry->d_name.name);
attr.ia_valid = ATTR_MODE;
attr.ia_mode = mode | S_IFDIR;
@@ -730,8 +730,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
- dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: rmdir(%s/%ld, %s\n", dir->i_sb->s_id,
+ dir->i_ino, dentry->d_name.name);
nfs_zap_caches(dir);
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
@@ -877,8 +877,8 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error;
- dfprintk(VFS, "NFS: unlink(%x/%ld, %s)\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id,
+ dir->i_ino, dentry->d_name.name);
error = nfs_sillyrename(dir, dentry);
if (error && error != -EBUSY) {
@@ -900,8 +900,8 @@ nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
unsigned int maxlen;
int error;
- dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",
- dir->i_dev, dir->i_ino, dentry->d_name.name, symname);
+ dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
+ dir->i_ino, dentry->d_name.name, symname);
error = -ENAMETOOLONG;
maxlen = (NFS_PROTO(dir)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index c2587108c..1d5e7dbde 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -73,7 +73,7 @@ nfs_file_flush(struct file *file)
struct inode *inode = file->f_dentry->d_inode;
int status;
- dfprintk(VFS, "nfs: flush(%x/%ld)\n", inode->i_dev, inode->i_ino);
+ dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
/* Make sure all async reads have been sent off. We don't bother
* waiting on them though... */
@@ -132,7 +132,7 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
struct inode *inode = dentry->d_inode;
int status;
- dfprintk(VFS, "nfs: fsync(%x/%ld)\n", inode->i_dev, inode->i_ino);
+ dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
lock_kernel();
status = nfs_wb_file(inode, file);
@@ -245,8 +245,8 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
struct inode * inode = filp->f_dentry->d_inode;
int status = 0;
- dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
- inode->i_dev, inode->i_ino,
+ dprintk("NFS: nfs_lock(f=%s/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
+ inode->i_sb->s_id, inode->i_ino,
fl->fl_type, fl->fl_flags,
(long long)fl->fl_start, (long long)fl->fl_end);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 3b802b3b9..a96bfbbb5 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -104,7 +104,7 @@ nfs_read_inode(struct inode * inode)
{
inode->i_blksize = inode->i_sb->s_blocksize;
inode->i_mode = 0;
- inode->i_rdev = 0;
+ inode->i_rdev = NODEV;
/* We can't support UPDATE_ATIME(), since the server will reset it */
inode->i_flags |= S_NOATIME;
INIT_LIST_HEAD(&inode->u.nfs_i.read);
@@ -127,7 +127,7 @@ nfs_write_inode(struct inode *inode, int sync)
static void
nfs_delete_inode(struct inode * inode)
{
- dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
+ dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
/*
* The following can never actually happen...
@@ -271,6 +271,9 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
struct nfs_fsinfo fsinfo;
int tcp, version, maxlen;
+ /* We probably want something more informative here */
+ snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", major(sb->s_dev), minor(sb->s_dev));
+
memset(&sb->u.nfs_sb, 0, sizeof(sb->u.nfs_sb));
if (!data)
goto out_miss_args;
@@ -747,8 +750,9 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
goto out_no_inode;
nfs_fill_inode(inode, fh, fattr);
- dprintk("NFS: __nfs_fhget(%x/%Ld ct=%d)\n",
- inode->i_dev, (long long)NFS_FILEID(inode),
+ dprintk("NFS: __nfs_fhget(%s/%Ld ct=%d)\n",
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode),
atomic_read(&inode->i_count));
out:
@@ -902,8 +906,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
int status = -ESTALE;
struct nfs_fattr fattr;
- dfprintk(PAGECACHE, "NFS: revalidating (%x/%Ld)\n",
- inode->i_dev, (long long)NFS_FILEID(inode));
+ dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",
+ inode->i_sb->s_id, (long long)NFS_FILEID(inode));
lock_kernel();
if (!inode || is_bad_inode(inode))
@@ -924,8 +928,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
status = NFS_PROTO(inode)->getattr(inode, &fattr);
if (status) {
- dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) getattr failed, error=%d\n",
- inode->i_dev, (long long)NFS_FILEID(inode), status);
+ dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode), status);
if (status == -ESTALE) {
NFS_FLAGS(inode) |= NFS_INO_STALE;
if (inode != inode->i_sb->s_root->d_inode)
@@ -936,12 +941,14 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
status = nfs_refresh_inode(inode, &fattr);
if (status) {
- dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) refresh failed, error=%d\n",
- inode->i_dev, (long long)NFS_FILEID(inode), status);
+ dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode), status);
goto out;
}
- dfprintk(PAGECACHE, "NFS: (%x/%Ld) revalidation complete\n",
- inode->i_dev, (long long)NFS_FILEID(inode));
+ dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode));
NFS_FLAGS(inode) &= ~NFS_INO_STALE;
out:
@@ -1000,8 +1007,8 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
time_t new_atime;
int invalid = 0;
- dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d info=0x%x)\n",
- inode->i_dev, inode->i_ino,
+ dfprintk(VFS, "NFS: refresh_inode(%s/%ld ct=%d info=0x%x)\n",
+ inode->i_sb->s_id, inode->i_ino,
atomic_read(&inode->i_count), fattr->valid);
if (NFS_FSID(inode) != fattr->fsid ||
@@ -1039,7 +1046,7 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
*/
if (NFS_CACHE_ISIZE(inode) != new_size) {
#ifdef NFS_DEBUG_VERBOSE
- printk(KERN_DEBUG "NFS: isize change on %x/%ld\n", inode->i_dev, inode->i_ino);
+ printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
#endif
invalid = 1;
}
@@ -1051,7 +1058,7 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
*/
if (NFS_CACHE_MTIME(inode) != new_mtime) {
#ifdef NFS_DEBUG_VERBOSE
- printk(KERN_DEBUG "NFS: mtime change on %x/%ld\n", inode->i_dev, inode->i_ino);
+ printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
#endif
invalid = 1;
}
@@ -1100,7 +1107,7 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
inode->i_blocks = fattr->du.nfs2.blocks;
inode->i_blksize = fattr->du.nfs2.blocksize;
}
- inode->i_rdev = 0;
+ inode->i_rdev = NODEV;
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
inode->i_rdev = to_kdev_t(fattr->rdev);
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index a2373467d..617f18282 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -334,7 +334,7 @@ int __init root_nfs_init(void)
*/
int __init nfs_root_setup(char *line)
{
- ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255);
+ ROOT_DEV = mk_kdev(UNNAMED_MAJOR, 255);
if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
strncpy(nfs_root_name, line, sizeof(nfs_root_name));
nfs_root_name[sizeof(nfs_root_name)-1] = '\0';
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index de1753632..068005fa1 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -108,9 +108,10 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
if (count < rsize)
rsize = count;
- dprintk("NFS: nfs_proc_read(%s, (%x/%Ld), %Ld, %d, %p)\n",
+ dprintk("NFS: nfs_proc_read(%s, (%s/%Ld), %Ld, %d, %p)\n",
NFS_SERVER(inode)->hostname,
- inode->i_dev, (long long)NFS_FILEID(inode),
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode),
(long long)offset, rsize, buffer);
lock_kernel();
@@ -265,9 +266,10 @@ nfs_pagein_one(struct list_head *head, struct inode *inode)
msg.rpc_cred = data->cred;
/* Start the async call */
- dprintk("NFS: %4d initiated read call (req %x/%Ld count %d nriov %d.\n",
+ dprintk("NFS: %4d initiated read call (req %s/%Ld count %d nriov %d.\n",
task->tk_pid,
- inode->i_dev, (long long)NFS_FILEID(inode),
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode),
data->args.count, data->args.nriov);
rpc_clnt_sigmask(clnt, &oldset);
@@ -426,8 +428,8 @@ nfs_readpage_result(struct rpc_task *task)
kunmap(page);
UnlockPage(page);
- dprintk("NFS: read (%x/%Ld %d@%Ld)\n",
- req->wb_inode->i_dev,
+ dprintk("NFS: read (%s/%Ld %d@%Ld)\n",
+ req->wb_inode->i_sb->s_id,
(long long)NFS_FILEID(req->wb_inode),
req->wb_bytes,
(long long)(page_offset(page) + req->wb_offset));
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d67eb73a7..c53cdb7b2 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -49,7 +49,7 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/slab.h>
-#include <linux/swap.h>
+#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/file.h>
@@ -159,8 +159,9 @@ nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page,
if (!cred)
cred = get_rpccred(NFS_I(inode)->mm_cred);
- dprintk("NFS: nfs_writepage_sync(%x/%Ld %d@%Ld)\n",
- inode->i_dev, (long long)NFS_FILEID(inode),
+ dprintk("NFS: nfs_writepage_sync(%s/%Ld %d@%Ld)\n",
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode),
count, (long long)(page_offset(page) + offset));
buffer = kmap(page) + offset;
@@ -948,9 +949,9 @@ nfs_flush_one(struct list_head *head, struct inode *inode, int how)
msg.rpc_resp = &data->res;
msg.rpc_cred = data->cred;
- dprintk("NFS: %4d initiated write call (req %x/%Ld count %d nriov %d)\n",
+ dprintk("NFS: %4d initiated write call (req %s/%Ld count %d nriov %d)\n",
task->tk_pid,
- inode->i_dev,
+ inode->i_sb->s_id,
(long long)NFS_FILEID(inode),
data->args.count, data->args.nriov);
@@ -1066,8 +1067,8 @@ nfs_writeback_done(struct rpc_task *task)
kunmap(page);
- dprintk("NFS: write (%x/%Ld %d@%Ld)",
- req->wb_inode->i_dev,
+ dprintk("NFS: write (%s/%Ld %d@%Ld)",
+ req->wb_inode->i_sb->s_id,
(long long)NFS_FILEID(req->wb_inode),
req->wb_bytes,
(long long)(page_offset(page) + req->wb_offset));
@@ -1219,8 +1220,8 @@ nfs_commit_done(struct rpc_task *task)
req = nfs_list_entry(data->pages.next);
nfs_list_remove_request(req);
- dprintk("NFS: commit (%x/%Ld %d@%Ld)",
- req->wb_inode->i_dev,
+ dprintk("NFS: commit (%s/%Ld %d@%Ld)",
+ req->wb_inode->i_sb->s_id,
(long long)NFS_FILEID(req->wb_inode),
req->wb_bytes,
(long long)(page_offset(req->wb_page) + req->wb_offset));
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 537b685ce..64977e9e4 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -16,6 +16,7 @@
#include <linux/unistd.h>
#include <linux/slab.h>
+#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/in.h>
@@ -49,7 +50,7 @@ static int exp_verify_string(char *cp, int max);
#define CLIENT_HASH(a) \
((((a)>>24) ^ ((a)>>16) ^ ((a)>>8) ^(a)) & CLIENT_HASHMASK)
/* XXX: is this adequate for 32bit kdev_t ? */
-#define EXPORT_HASH(dev) ((dev) & (NFSCLNT_EXPMAX - 1))
+#define EXPORT_HASH(dev) (minor(dev) & (NFSCLNT_EXPMAX - 1))
struct svc_clnthash {
struct svc_clnthash * h_next;
@@ -75,7 +76,7 @@ exp_find(svc_client *clp, kdev_t dev)
svc_export * exp;
exp = clp->cl_export[EXPORT_HASH(dev)];
- while (exp && exp->ex_dev != dev)
+ while (exp && !kdev_same(exp->ex_dev, dev))
exp = exp->ex_next;
return exp;
}
@@ -94,7 +95,7 @@ exp_get(svc_client *clp, kdev_t dev, ino_t ino)
exp = clp->cl_export[EXPORT_HASH(dev)];
if (exp)
do {
- if (exp->ex_ino == ino && exp->ex_dev == dev)
+ if (exp->ex_ino == ino && kdev_same(exp->ex_dev, dev))
goto out;
} while (NULL != (exp = exp->ex_next));
exp = NULL;
@@ -197,9 +198,10 @@ exp_export(struct nfsctl_export *nxp)
inode = nd.dentry->d_inode;
err = -EINVAL;
- if (inode->i_dev != dev || inode->i_ino != nxp->ex_ino) {
- printk(KERN_DEBUG "exp_export: i_dev = %x, dev = %x\n",
- inode->i_dev, dev);
+ if (!kdev_same(inode->i_dev, dev) || inode->i_ino != nxp->ex_ino) {
+ printk(KERN_DEBUG "exp_export: i_dev = %02x:%02x, dev = %02x:%02x\n",
+ major(inode->i_dev), minor(inode->i_dev),
+ major(dev), minor(dev));
/* I'm just being paranoid... */
goto finish;
}
@@ -301,7 +303,7 @@ exp_do_unexport(svc_export *unexp)
dentry = unexp->ex_dentry;
mnt = unexp->ex_mnt;
inode = dentry->d_inode;
- if (unexp->ex_dev != inode->i_dev || unexp->ex_ino != inode->i_ino)
+ if (!kdev_same(unexp->ex_dev, inode->i_dev) || unexp->ex_ino != inode->i_ino)
printk(KERN_WARNING "nfsd: bad dentry in unexport!\n");
dput(dentry);
mntput(mnt);
@@ -352,9 +354,10 @@ exp_unexport(struct nfsctl_export *nxp)
err = -EINVAL;
clp = exp_getclientbyname(nxp->ex_client);
if (clp) {
- expp = clp->cl_export + EXPORT_HASH(nxp->ex_dev);
+ kdev_t ex_dev = to_kdev_t(nxp->ex_dev);
+ expp = clp->cl_export + EXPORT_HASH(ex_dev);
while ((exp = *expp) != NULL) {
- if (exp->ex_dev == nxp->ex_dev) {
+ if (kdev_same(exp->ex_dev, ex_dev)) {
if (exp->ex_ino == nxp->ex_ino) {
*expp = exp->ex_next;
exp_do_unexport(exp);
@@ -396,12 +399,13 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
dev = nd.dentry->d_inode->i_dev;
ino = nd.dentry->d_inode->i_ino;
- dprintk("nfsd: exp_rootfh(%s [%p] %s:%x/%ld)\n",
- path, nd.dentry, clp->cl_ident, dev, (long) ino);
+ dprintk("nfsd: exp_rootfh(%s [%p] %s:%02x:%02x/%ld)\n",
+ path, nd.dentry, clp->cl_ident,
+ major(dev), minor(dev), (long) ino);
exp = exp_parent(clp, dev, nd.dentry);
} else {
- dprintk("nfsd: exp_rootfh(%s:%x/%ld)\n",
- clp->cl_ident, dev, (long) ino);
+ dprintk("nfsd: exp_rootfh(%s:%02x:%02x/%ld)\n",
+ clp->cl_ident, major(dev), minor(dev), (long) ino);
if ((exp = exp_get(clp, dev, ino))) {
nd.mnt = mntget(exp->ex_mnt);
nd.dentry = dget(exp->ex_dentry);
@@ -417,11 +421,12 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
printk("exp_rootfh: Aieee, NULL d_inode\n");
goto out;
}
- if (inode->i_dev != dev || inode->i_ino != ino) {
+ if (!kdev_same(inode->i_dev, dev) || inode->i_ino != ino) {
printk("exp_rootfh: Aieee, ino/dev mismatch\n");
- printk("exp_rootfh: arg[dev(%x):ino(%ld)]"
- " inode[dev(%x):ino(%ld)]\n",
- dev, (long) ino, inode->i_dev, (long) inode->i_ino);
+ printk("exp_rootfh: arg[dev(%02x:%02x):ino(%ld)]"
+ " inode[dev(%02x:%02x):ino(%ld)]\n",
+ major(dev), minor(dev), (long) ino,
+ major(inode->i_dev), minor(inode->i_dev), (long) inode->i_ino);
}
/*
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index e3b037803..834974627 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -173,9 +173,9 @@ encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry)
p = xdr_encode_hyper(p, (u64)(inode->i_size +511)& ~511);
else
p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9);
- *p++ = htonl((u32) MAJOR(inode->i_rdev));
- *p++ = htonl((u32) MINOR(inode->i_rdev));
- p = xdr_encode_hyper(p, (u64) inode->i_dev);
+ *p++ = htonl((u32) major(inode->i_rdev));
+ *p++ = htonl((u32) minor(inode->i_rdev));
+ p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
p = xdr_encode_hyper(p, (u64) inode->i_ino);
p = encode_time3(p, inode->i_atime);
p = encode_time3(p, lease_get_mtime(inode));
@@ -203,9 +203,9 @@ encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
}
p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
- *p++ = htonl((u32) MAJOR(fhp->fh_post_rdev));
- *p++ = htonl((u32) MINOR(fhp->fh_post_rdev));
- p = xdr_encode_hyper(p, (u64) inode->i_dev);
+ *p++ = htonl((u32) major(fhp->fh_post_rdev));
+ *p++ = htonl((u32) minor(fhp->fh_post_rdev));
+ p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
p = xdr_encode_hyper(p, (u64) inode->i_ino);
p = encode_time3(p, fhp->fh_post_atime);
p = encode_time3(p, fhp->fh_post_mtime);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 7e5dc7360..25c4288bf 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -125,7 +125,7 @@ nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
- err = exp_rootfh(clp, 0, 0, data->gd_path, res, data->gd_maxlen);
+ err = exp_rootfh(clp, NODEV, 0, data->gd_path, res, data->gd_maxlen);
exp_unlock();
return err;
}
@@ -148,7 +148,7 @@ nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
- err = exp_rootfh(clp, 0, 0, data->gd_path, &fh, NFS_FHSIZE);
+ err = exp_rootfh(clp, NODEV, 0, data->gd_path, &fh, NFS_FHSIZE);
exp_unlock();
if (err == 0) {
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 417b4173c..952e01259 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -424,7 +424,8 @@ find_fh_dentry(struct super_block *sb, __u32 *datap, int len, int fhtype, int ne
/* It's a directory, or we are required to confirm the file's
* location in the tree.
*/
- dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,datap[0]);
+ dprintk("nfs_fh: need to look harder for %02x:%02x/%d\n",
+ major(sb->s_dev), minor(sb->s_dev), datap[0]);
if (!S_ISDIR(result->d_inode->i_mode)) {
nfsdstats.fh_nocache_nondir++;
@@ -556,7 +557,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
case 0:
if ((data_left-=2)<0) goto out;
nfsdev = ntohl(*datap++);
- xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
+ xdev = mk_kdev(nfsdev>>16, nfsdev&0xFFFF);
xino = *datap++;
break;
default:
@@ -788,8 +789,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
struct dentry *parent = dentry->d_parent;
__u32 *datap;
- dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)\n",
- exp->ex_dev, (long) exp->ex_ino,
+ dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
+ major(exp->ex_dev), minor(exp->ex_dev), (long) exp->ex_ino,
parent->d_name.name, dentry->d_name.name,
(inode ? inode->i_ino : 0));
@@ -811,7 +812,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
fhp->fh_handle.fh_size = NFS_FHSIZE;
fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
- fhp->fh_handle.ofh_dev = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
+ fhp->fh_handle.ofh_dev = htonl((major(exp->ex_dev)<<16)| minor(exp->ex_dev));
fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_ino);
fhp->fh_handle.ofh_dirino = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
@@ -823,7 +824,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
fhp->fh_handle.fh_fsid_type = 0;
datap = fhp->fh_handle.fh_auth+0;
/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
- *datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
+ *datap++ = htonl((major(exp->ex_dev)<<16)| minor(exp->ex_dev));
*datap++ = ino_t_to_u32(exp->ex_ino);
fhp->fh_handle.fh_size = 3*4;
if (inode) {
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index c8ac22111..8c4599d20 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -197,7 +197,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
struct inode *inode;
struct dentry *dchild;
int nfserr, type, mode;
- dev_t rdev = NODEV;
+ dev_t rdev = 0;
dprintk("nfsd: CREATE %s %.*s\n",
SVCFH_fmt(dirfhp), argp->len, argp->name);
@@ -255,7 +255,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
case S_IFCHR:
case S_IFBLK:
/* reserve rdev for later checking */
- attr->ia_size = inode->i_rdev;
+ attr->ia_size = kdev_t_to_nr(inode->i_rdev);
attr->ia_valid |= ATTR_SIZE;
/* FALLTHROUGH */
@@ -313,7 +313,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
/* Make sure the type and device matches */
nfserr = nfserr_exist;
if (inode && (type != (inode->i_mode & S_IFMT) ||
- (is_borc && inode->i_rdev != rdev)))
+ (is_borc && kdev_t_to_nr(inode->i_rdev) != rdev)))
goto out_unlock;
}
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 0ee659ed4..d557f956f 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -149,11 +149,11 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
}
*p++ = htonl((u32) inode->i_blksize);
if (S_ISCHR(type) || S_ISBLK(type))
- *p++ = htonl((u32) inode->i_rdev);
+ *p++ = htonl((u32) kdev_t_to_nr(inode->i_rdev));
else
*p++ = htonl(0xffffffff);
*p++ = htonl((u32) inode->i_blocks);
- *p++ = htonl((u32) inode->i_dev);
+ *p++ = htonl((u32) kdev_t_to_nr(inode->i_dev));
*p++ = htonl((u32) inode->i_ino);
*p++ = htonl((u32) inode->i_atime);
*p++ = 0;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 5a6b68fed..af9bd34b2 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -66,7 +66,7 @@ struct raparms {
struct raparms *p_next;
unsigned int p_count;
ino_t p_ino;
- dev_t p_dev;
+ kdev_t p_dev;
unsigned long p_reada,
p_ramax,
p_raend,
@@ -543,13 +543,13 @@ nfsd_sync_dir(struct dentry *dp)
* specified by (dev, ino).
*/
static inline struct raparms *
-nfsd_get_raparms(dev_t dev, ino_t ino)
+nfsd_get_raparms(kdev_t dev, ino_t ino)
{
struct raparms *ra, **rap, **frap = NULL;
int depth = 0;
for (rap = &raparm_cache; (ra = *rap); rap = &ra->p_next) {
- if (ra->p_ino == ino && ra->p_dev == dev)
+ if (ra->p_ino == ino && kdev_same(ra->p_dev, dev))
goto found;
depth++;
if (ra->p_count == 0)
@@ -734,7 +734,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
*/
if (EX_WGATHER(exp)) {
if (atomic_read(&inode->i_writecount) > 1
- || (last_ino == inode->i_ino && last_dev == inode->i_dev)) {
+ || (last_ino == inode->i_ino && kdev_same(last_dev, inode->i_dev))) {
dprintk("nfsd: write defer %d\n", current->pid);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((HZ+99)/100);
@@ -1249,7 +1249,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
tdir = tdentry->d_inode;
err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
- if (fdir->i_dev != tdir->i_dev)
+ if (fdir->i_sb != tdir->i_sb)
goto out;
err = nfserr_perm;
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
index 1db7ffd82..59269a4a7 100644
--- a/fs/nls/nls_base.c
+++ b/fs/nls/nls_base.c
@@ -13,7 +13,7 @@
#include <linux/string.h>
#include <linux/config.h>
#include <linux/nls.h>
-#include <linux/slab.h>
+#include <linux/kernel.h>
#include <linux/errno.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
diff --git a/fs/nls/nls_big5.c b/fs/nls/nls_big5.c
index 250098337..04849382a 100644
--- a/fs/nls/nls_big5.c
+++ b/fs/nls/nls_big5.c
@@ -42,6 +42,7 @@ static void __exit exit_nls_big5(void)
module_init(init_nls_big5)
module_exit(exit_nls_big5)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c
index d2625d50f..72c4875cc 100644
--- a/fs/nls/nls_cp932.c
+++ b/fs/nls/nls_cp932.c
@@ -7904,6 +7904,7 @@ static void __exit exit_nls_cp932(void)
module_init(init_nls_cp932)
module_exit(exit_nls_cp932)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_cp936.c b/fs/nls/nls_cp936.c
index d0d1f3826..906a8baf3 100644
--- a/fs/nls/nls_cp936.c
+++ b/fs/nls/nls_cp936.c
@@ -11024,6 +11024,7 @@ static void __exit exit_nls_cp936(void)
module_init(init_nls_cp936)
module_exit(exit_nls_cp936)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_cp949.c b/fs/nls/nls_cp949.c
index a1a869d0e..5e06469f8 100644
--- a/fs/nls/nls_cp949.c
+++ b/fs/nls/nls_cp949.c
@@ -13941,6 +13941,7 @@ static void __exit exit_nls_cp949(void)
module_init(init_nls_cp949)
module_exit(exit_nls_cp949)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_cp950.c b/fs/nls/nls_cp950.c
index 5d8cecc0e..10dcc45e6 100644
--- a/fs/nls/nls_cp950.c
+++ b/fs/nls/nls_cp950.c
@@ -9480,6 +9480,7 @@ static void __exit exit_nls_cp950(void)
module_init(init_nls_cp950)
module_exit(exit_nls_cp950)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_euc-jp.c b/fs/nls/nls_euc-jp.c
index 50743b1c8..ea4015677 100644
--- a/fs/nls/nls_euc-jp.c
+++ b/fs/nls/nls_euc-jp.c
@@ -581,6 +581,7 @@ static void __exit exit_nls_euc_jp(void)
module_init(init_nls_euc_jp)
module_exit(exit_nls_euc_jp)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_euc-kr.c b/fs/nls/nls_euc-kr.c
index f015c21bf..e7b030aa0 100644
--- a/fs/nls/nls_euc-kr.c
+++ b/fs/nls/nls_euc-kr.c
@@ -42,6 +42,7 @@ static void __exit exit_nls_euc_kr(void)
module_init(init_nls_euc_kr)
module_exit(exit_nls_euc_kr)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_gb2312.c b/fs/nls/nls_gb2312.c
index 06c184a27..dd64d84c3 100644
--- a/fs/nls/nls_gb2312.c
+++ b/fs/nls/nls_gb2312.c
@@ -42,6 +42,7 @@ static void __exit exit_nls_gb2312(void)
module_init(init_nls_gb2312)
module_exit(exit_nls_gb2312)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-1.c b/fs/nls/nls_iso8859-1.c
index 828ab9ac4..9477f418a 100644
--- a/fs/nls/nls_iso8859-1.c
+++ b/fs/nls/nls_iso8859-1.c
@@ -254,6 +254,7 @@ static void __exit exit_nls_iso8859_1(void)
module_init(init_nls_iso8859_1)
module_exit(exit_nls_iso8859_1)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-13.c b/fs/nls/nls_iso8859-13.c
index 999b1e4ad..c8e626afc 100644
--- a/fs/nls/nls_iso8859-13.c
+++ b/fs/nls/nls_iso8859-13.c
@@ -282,6 +282,7 @@ static void __exit exit_nls_iso8859_13(void)
module_init(init_nls_iso8859_13)
module_exit(exit_nls_iso8859_13)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-14.c b/fs/nls/nls_iso8859-14.c
index 5a14dbfeb..6a032a2d0 100644
--- a/fs/nls/nls_iso8859-14.c
+++ b/fs/nls/nls_iso8859-14.c
@@ -338,6 +338,7 @@ static void __exit exit_nls_iso8859_14(void)
module_init(init_nls_iso8859_14)
module_exit(exit_nls_iso8859_14)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-15.c b/fs/nls/nls_iso8859-15.c
index a2297d3e8..8cad93f09 100644
--- a/fs/nls/nls_iso8859-15.c
+++ b/fs/nls/nls_iso8859-15.c
@@ -304,6 +304,7 @@ static void __exit exit_nls_iso8859_15(void)
module_init(init_nls_iso8859_15)
module_exit(exit_nls_iso8859_15)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-2.c b/fs/nls/nls_iso8859-2.c
index 6ad040a3e..597b658bb 100644
--- a/fs/nls/nls_iso8859-2.c
+++ b/fs/nls/nls_iso8859-2.c
@@ -305,6 +305,7 @@ static void __exit exit_nls_iso8859_2(void)
module_init(init_nls_iso8859_2)
module_exit(exit_nls_iso8859_2)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-3.c b/fs/nls/nls_iso8859-3.c
index f035000e0..b49abeef4 100644
--- a/fs/nls/nls_iso8859-3.c
+++ b/fs/nls/nls_iso8859-3.c
@@ -305,6 +305,7 @@ static void __exit exit_nls_iso8859_3(void)
module_init(init_nls_iso8859_3)
module_exit(exit_nls_iso8859_3)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-4.c b/fs/nls/nls_iso8859-4.c
index 1bd6ef2bf..7f263e3f3 100644
--- a/fs/nls/nls_iso8859-4.c
+++ b/fs/nls/nls_iso8859-4.c
@@ -305,6 +305,7 @@ static void __exit exit_nls_iso8859_4(void)
module_init(init_nls_iso8859_4)
module_exit(exit_nls_iso8859_4)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-5.c b/fs/nls/nls_iso8859-5.c
index 052df9354..0edba6888 100644
--- a/fs/nls/nls_iso8859-5.c
+++ b/fs/nls/nls_iso8859-5.c
@@ -269,6 +269,7 @@ static void __exit exit_nls_iso8859_5(void)
module_init(init_nls_iso8859_5)
module_exit(exit_nls_iso8859_5)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-6.c b/fs/nls/nls_iso8859-6.c
index 785cbeec1..403b59cf0 100644
--- a/fs/nls/nls_iso8859-6.c
+++ b/fs/nls/nls_iso8859-6.c
@@ -260,6 +260,7 @@ static void __exit exit_nls_iso8859_6(void)
module_init(init_nls_iso8859_6)
module_exit(exit_nls_iso8859_6)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-7.c b/fs/nls/nls_iso8859-7.c
index 23b834b10..6dd6d55c4 100644
--- a/fs/nls/nls_iso8859-7.c
+++ b/fs/nls/nls_iso8859-7.c
@@ -314,6 +314,7 @@ static void __exit exit_nls_iso8859_7(void)
module_init(init_nls_iso8859_7)
module_exit(exit_nls_iso8859_7)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-8.c b/fs/nls/nls_iso8859-8.c
index c4eae93a5..3005f6809 100644
--- a/fs/nls/nls_iso8859-8.c
+++ b/fs/nls/nls_iso8859-8.c
@@ -42,6 +42,7 @@ static void __exit exit_nls_iso8859_8(void)
module_init(init_nls_iso8859_8)
module_exit(exit_nls_iso8859_8)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_iso8859-9.c b/fs/nls/nls_iso8859-9.c
index 47e18e6bb..dfc813e0a 100644
--- a/fs/nls/nls_iso8859-9.c
+++ b/fs/nls/nls_iso8859-9.c
@@ -269,6 +269,7 @@ static void __exit exit_nls_iso8859_9(void)
module_init(init_nls_iso8859_9)
module_exit(exit_nls_iso8859_9)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_koi8-r.c b/fs/nls/nls_koi8-r.c
index e4cf807af..5889f1f7d 100644
--- a/fs/nls/nls_koi8-r.c
+++ b/fs/nls/nls_koi8-r.c
@@ -320,6 +320,7 @@ static void __exit exit_nls_koi8_r(void)
module_init(init_nls_koi8_r)
module_exit(exit_nls_koi8_r)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_koi8-ru.c b/fs/nls/nls_koi8-ru.c
index 89574efb3..383618fe2 100644
--- a/fs/nls/nls_koi8-ru.c
+++ b/fs/nls/nls_koi8-ru.c
@@ -80,6 +80,7 @@ static void __exit exit_nls_koi8_ru(void)
module_init(init_nls_koi8_ru)
module_exit(exit_nls_koi8_ru)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_koi8-u.c b/fs/nls/nls_koi8-u.c
index f7f629fb0..c9efbffb1 100644
--- a/fs/nls/nls_koi8-u.c
+++ b/fs/nls/nls_koi8-u.c
@@ -327,6 +327,7 @@ static void __exit exit_nls_koi8_u(void)
module_init(init_nls_koi8_u)
module_exit(exit_nls_koi8_u)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_sjis.c b/fs/nls/nls_sjis.c
index 463ee02a5..024d59d19 100644
--- a/fs/nls/nls_sjis.c
+++ b/fs/nls/nls_sjis.c
@@ -42,6 +42,7 @@ static void __exit exit_nls_sjis(void)
module_init(init_nls_sjis)
module_exit(exit_nls_sjis)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_tis-620.c b/fs/nls/nls_tis-620.c
index b45098a49..b85a4f858 100644
--- a/fs/nls/nls_tis-620.c
+++ b/fs/nls/nls_tis-620.c
@@ -42,6 +42,7 @@ static void __exit exit_nls_tis_620(void)
module_init(init_nls_tis_620)
module_exit(exit_nls_tis_620)
+MODULE_LICENSE("Dual BSD/GPL");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/fs/nls/nls_utf8.c b/fs/nls/nls_utf8.c
index 017a52391..09a84d76f 100644
--- a/fs/nls/nls_utf8.c
+++ b/fs/nls/nls_utf8.c
@@ -58,3 +58,4 @@ static void __exit exit_nls_utf8(void)
module_init(init_nls_utf8)
module_exit(exit_nls_utf8)
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c
index 5076c1dac..4783aaf1e 100644
--- a/fs/ntfs/fs.c
+++ b/fs/ntfs/fs.c
@@ -1016,14 +1016,11 @@ struct super_block *ntfs_read_super(struct super_block *sb, void *options,
init_ntfs_super_block(vol);
if (!parse_options(vol, (char*)options))
goto ntfs_read_super_vol;
- blocksize = get_hardsect_size(sb->s_dev);
- if (blocksize < 512)
- blocksize = 512;
- if (set_blocksize(sb->s_dev, blocksize) < 0) {
- ntfs_error("Unable to set blocksize %d.\n", blocksize);
+ blocksize = sb_min_blocksize(sb, 512);
+ if (!blocksize) {
+ ntfs_error("Unable to set blocksize.\n");
goto ntfs_read_super_vol;
}
- sb->s_blocksize = blocksize;
/* Read the super block (boot block). */
if (!(bh = sb_bread(sb, 0))) {
ntfs_error("Reading super block failed\n");
@@ -1052,10 +1049,7 @@ struct super_block *ntfs_read_super(struct super_block *sb, void *options,
}
ntfs_debug(DEBUG_OTHER, "Done to init volume\n");
/* Inform the kernel that a device block is a NTFS cluster. */
- sb->s_blocksize = vol->cluster_size;
- sb->s_blocksize_bits = vol->cluster_size_bits;
- if (blocksize != vol->cluster_size &&
- set_blocksize(sb->s_dev, sb->s_blocksize) < 0) {
+ if (!sb_set_blocksize(sb, vol->cluster_size)) {
ntfs_error("Cluster size too small for device.\n");
goto ntfs_read_super_unl;
}
diff --git a/fs/ntfs/support.c b/fs/ntfs/support.c
index d490f2553..025c09cc8 100644
--- a/fs/ntfs/support.c
+++ b/fs/ntfs/support.c
@@ -200,7 +200,7 @@ int ntfs_getput_clusters(ntfs_volume *vol, int cluster, ntfs_size_t start_offs,
if (buffer_req(bh) && !buffer_uptodate(bh)) {
printk(KERN_ERR "IO error syncing NTFS "
"cluster [%s:%i]\n",
- bdevname(sb->s_dev), cluster);
+ sb->s_id, cluster);
brelse(bh);
error = -EIO;
goto error_ret;
diff --git a/fs/partitions/acorn.c b/fs/partitions/acorn.c
index c33f6530d..fd0f1f862 100644
--- a/fs/partitions/acorn.c
+++ b/fs/partitions/acorn.c
@@ -28,7 +28,7 @@ adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
extern void xd_set_geometry(kdev_t dev, unsigned char, unsigned char,
unsigned long, unsigned int);
- if (MAJOR(dev) == MFM_ACORN_MAJOR) {
+ if (major(dev) == MFM_ACORN_MAJOR) {
unsigned long totalblocks = hd->part[MINOR(dev)].nr_sects;
xd_set_geometry(dev, secspertrack, heads, totalblocks, 1);
}
@@ -261,7 +261,7 @@ adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
/*
* Work out start of non-adfs partition.
*/
- nr_sects = hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects - start_sect;
+ nr_sects = hd->part[minor(to_kdev_t(bdev->bd_dev))].nr_sects - start_sect;
if (start_sect) {
first_sector += start_sect;
diff --git a/fs/partitions/atari.c b/fs/partitions/atari.c
index 11a7b4a79..e01a3e461 100644
--- a/fs/partitions/atari.c
+++ b/fs/partitions/atari.c
@@ -43,7 +43,7 @@ static inline int OK_id(char *s)
int atari_partition (struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
{
- int m_lim = minor + hd->max_p;
+ int m_lim = minor + (1 << hd->minor_shift);
Sector sect;
struct rootsector *rs;
struct partition_info *pi;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 66c4d7aff..14b26548e 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -38,7 +38,8 @@
int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
-static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
+static int (*check_part[])(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sect, int first_minor) = {
#ifdef CONFIG_ACORN_PARTITION
acorn_partition,
#endif
@@ -227,26 +228,26 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor
if (first_time)
printk(KERN_INFO "Partition check:\n");
first_time = 0;
- first_sector = hd->part[MINOR(dev)].start_sect;
+ first_sector = hd->part[minor(dev)].start_sect;
/*
* This is a kludge to allow the partition check to be
* skipped for specific drives (e.g. IDE CD-ROM drives)
*/
if ((int)first_sector == -1) {
- hd->part[MINOR(dev)].start_sect = 0;
+ hd->part[minor(dev)].start_sect = 0;
return;
}
if (hd->de_arr)
- de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
+ de = hd->de_arr[minor(dev) >> hd->minor_shift];
i = devfs_generate_path (de, buf, sizeof buf);
if (i >= 0)
printk(KERN_INFO " /dev/%s:", buf + i);
else
- printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
+ printk(KERN_INFO " %s:", disk_name(hd, minor(dev), buf));
bdev = bdget(kdev_t_to_nr(dev));
- bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
+ bdev->bd_inode->i_size = (loff_t)hd->part[minor(dev)].nr_sects << 9;
bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
for (i = 0; check_part[i]; i++) {
int res;
@@ -333,11 +334,12 @@ static void devfs_register_disc (struct gendisk *dev, int minor)
void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
{
#ifdef CONFIG_DEVFS_FS
- int part;
+ int part, max_p;
if (!unregister)
devfs_register_disc (dev, minor);
- for (part = 1; part < dev->max_p; part++) {
+ max_p = (1 << dev->minor_shift);
+ for (part = 1; part < max_p; part++) {
if ( unregister || (dev->part[part + minor].nr_sects < 1) ) {
devfs_unregister (dev->part[part + minor].de);
dev->part[part + minor].de = NULL;
@@ -381,10 +383,10 @@ void grok_partitions(kdev_t dev, long size)
return;
minors = 1 << g->minor_shift;
- first_minor = MINOR(dev);
+ first_minor = minor(dev);
if (first_minor & (minors-1)) {
printk("grok_partitions: bad device 0x%02x:%02x\n",
- MAJOR(dev), first_minor);
+ major(dev), first_minor);
first_minor &= ~(minors-1);
}
end_minor = first_minor + minors;
@@ -404,7 +406,7 @@ void grok_partitions(kdev_t dev, long size)
g->sizes[i] = 0;
}
blk_size[g->major] = g->sizes;
- check_partition(g, MKDEV(g->major, first_minor), 1 + first_minor);
+ check_partition(g, mk_kdev(g->major, first_minor), 1 + first_minor);
/*
* We need to set the sizes array before we will be able to access
@@ -450,8 +452,8 @@ int wipe_partitions(kdev_t dev)
return -EINVAL;
max_p = 1 << g->minor_shift;
- major = MAJOR(dev);
- minor = MINOR(dev);
+ major = major(dev);
+ minor = minor(dev);
minor0 = minor & ~(max_p - 1);
if (minor0 != minor) /* for now only whole-disk reread */
return -EINVAL; /* %%% later.. */
@@ -459,7 +461,7 @@ int wipe_partitions(kdev_t dev)
/* invalidate stuff */
for (p = max_p - 1; p >= 0; p--) {
minor = minor0 + p;
- devp = MKDEV(major,minor);
+ devp = mk_kdev(major,minor);
#if 0 /* %%% superfluous? */
if (g->part[minor].nr_sects == 0)
continue;
diff --git a/fs/partitions/check.h b/fs/partitions/check.h
index 8ef947ba6..3f8c810c0 100644
--- a/fs/partitions/check.h
+++ b/fs/partitions/check.h
@@ -1,4 +1,5 @@
#include <linux/pagemap.h>
+#include <linux/blkdev.h>
/*
* add_gd_partition adds a partitions details to the devices partition
@@ -6,13 +7,4 @@
*/
void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
-typedef struct {struct page *v;} Sector;
-
-unsigned char *read_dev_sector(struct block_device *, unsigned long, Sector *);
-
-static inline void put_dev_sector(Sector p)
-{
- page_cache_release(p.v);
-}
-
extern int warn_no_part;
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index cc6e7470e..96706f2ce 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -125,7 +125,7 @@ ibm_partition(struct gendisk *hd, struct block_device *bdev,
return 0;
if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo);
return 0;
- blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
+ blocksize = hardsect_size[major(dev)][minor(dev)];
if ( blocksize <= 0 ) {
return 0;
}
diff --git a/fs/proc/array.c b/fs/proc/array.c
index d8738e51b..c25745603 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -335,8 +335,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
/* scale priority and nice values from timeslices to -20..20 */
/* to make it look like a "normal" Unix priority/nice value */
- priority = task->counter;
- priority = 20 - (priority * 10 + DEF_COUNTER / 2) / DEF_COUNTER;
+ priority = task->dyn_prio;
nice = task->nice;
read_lock(&tasklist_lock);
@@ -556,7 +555,7 @@ static int proc_pid_maps_get_line (char *buf, struct vm_area_struct *map)
str[3] = flags & VM_MAYSHARE ? 's' : 'p';
str[4] = 0;
- dev = 0;
+ dev = NODEV;
ino = 0;
if (map->vm_file != NULL) {
dev = map->vm_file->f_dentry->d_inode->i_dev;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 5331c73d7..ed0da13a0 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -23,6 +23,9 @@
#include <linux/init.h>
#include <linux/file.h>
#include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/namespace.h>
+#include <linux/mm.h>
/*
* For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -246,6 +249,46 @@ static struct file_operations proc_maps_operations = {
read: pid_maps_read,
};
+extern struct seq_operations mounts_op;
+static int mounts_open(struct inode *inode, struct file *file)
+{
+ struct task_struct *task = inode->u.proc_i.task;
+ int ret = seq_open(file, &mounts_op);
+
+ if (!ret) {
+ struct seq_file *m = file->private_data;
+ struct namespace *namespace;
+ task_lock(task);
+ namespace = task->namespace;
+ if (namespace)
+ get_namespace(namespace);
+ task_unlock(task);
+
+ if (namespace)
+ m->private = namespace;
+ else {
+ seq_release(inode, file);
+ ret = -EINVAL;
+ }
+ }
+ return ret;
+}
+
+static int mounts_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *m = file->private_data;
+ struct namespace *namespace = m->private;
+ put_namespace(namespace);
+ return seq_release(inode, file);
+}
+
+static struct file_operations proc_mounts_operations = {
+ open: mounts_open,
+ read: seq_read,
+ llseek: seq_lseek,
+ release: mounts_release,
+};
+
#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */
static ssize_t proc_info_read(struct file * file, char * buf,
@@ -497,6 +540,7 @@ enum pid_directory_inos {
PROC_PID_STATM,
PROC_PID_MAPS,
PROC_PID_CPU,
+ PROC_PID_MOUNTS,
PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */
};
@@ -516,6 +560,7 @@ static struct pid_entry base_stuff[] = {
E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
E(PROC_PID_ROOT, "root", S_IFLNK|S_IRWXUGO),
E(PROC_PID_EXE, "exe", S_IFLNK|S_IRWXUGO),
+ E(PROC_PID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
{0,0,NULL,0}
};
#undef E
@@ -875,6 +920,9 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
inode->i_op = &proc_mem_inode_operations;
inode->i_fop = &proc_mem_operations;
break;
+ case PROC_PID_MOUNTS:
+ inode->i_fop = &proc_mounts_operations;
+ break;
default:
printk("procfs: impossible type (%d)",p->type);
iput(inode);
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index ad6d9714d..b0cda6de4 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -500,18 +500,6 @@ static struct file_operations proc_profile_operations = {
write: write_profile,
};
-extern struct seq_operations mounts_op;
-static int mounts_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &mounts_op);
-}
-static struct file_operations proc_mounts_operations = {
- open: mounts_open,
- read: seq_read,
- llseek: seq_lseek,
- release: seq_release,
-};
-
struct proc_dir_entry *proc_root_kcore;
static void create_seq_entry(char *name, mode_t mode, struct file_operations *f)
@@ -555,11 +543,12 @@ void __init proc_misc_init(void)
for (p = simple_ones; p->name; p++)
create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
+ proc_symlink("mounts", NULL, "self/mounts");
+
/* And now for trickier ones */
entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
if (entry)
entry->proc_fops = &proc_kmsg_operations;
- create_seq_entry("mounts", 0, &proc_mounts_operations);
create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
create_seq_entry("interrupts", 0, &proc_interrupts_operations);
#ifdef CONFIG_MODULES
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 49df47d8f..5eea1e3d1 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -18,7 +18,6 @@
#include <linux/qnx4_fs.h>
#include <linux/stat.h>
-#include <asm/segment.h>
static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
diff --git a/fs/qnx4/fsync.c b/fs/qnx4/fsync.c
index 4ef5de955..7d17225f0 100644
--- a/fs/qnx4/fsync.c
+++ b/fs/qnx4/fsync.c
@@ -21,7 +21,6 @@
#include <linux/fs.h>
#include <linux/qnx4_fs.h>
-#include <asm/segment.h>
#include <asm/system.h>
/*
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index cfec8ede9..b74d341c2 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -18,8 +18,8 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/slab.h>
-#include <linux/qnx4_fs.h>
#include <linux/fs.h>
+#include <linux/qnx4_fs.h>
#include <linux/locks.h>
#include <linux/init.h>
#include <linux/highuid.h>
@@ -48,7 +48,7 @@ int qnx4_sync_inode(struct inode *inode)
if (buffer_req(bh) && !buffer_uptodate(bh))
{
printk ("IO error syncing qnx4 inode [%s:%08lx]\n",
- kdevname(inode->i_dev), inode->i_ino);
+ inode->i_sb->s_id, inode->i_ino);
err = -1;
}
brelse (bh);
@@ -89,7 +89,7 @@ static void qnx4_write_inode(struct inode *inode, int unused)
}
if (!ino) {
printk("qnx4: bad inode number on dev %s: %d is out of range\n",
- kdevname(inode->i_dev), ino);
+ inode->i_sb->s_id, ino);
return;
}
QNX4DEBUG(("qnx4: write inode 2.\n"));
@@ -97,7 +97,7 @@ static void qnx4_write_inode(struct inode *inode, int unused)
lock_kernel();
if (!(bh = sb_bread(inode->i_sb, block))) {
printk("qnx4: major problem: unable to read inode from dev "
- "%s\n", kdevname(inode->i_dev));
+ "%s\n", inode->i_sb->s_id);
unlock_kernel();
return;
}
@@ -213,9 +213,7 @@ int qnx4_get_block( struct inode *inode, sector_t iblock, struct buffer_head *bh
phys = qnx4_block_map( inode, iblock );
if ( phys ) {
// logical block is before EOF
- bh->b_dev = inode->i_dev;
- bh->b_blocknr = phys;
- bh->b_state |= (1UL << BH_Mapped);
+ map_bh(bh, inode->i_sb, phys);
} else if ( create ) {
// to be done.
}
@@ -303,7 +301,7 @@ static const char *qnx4_checkroot(struct super_block *sb)
if (*(sb->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
return "no qnx4 filesystem (no root dir).";
} else {
- QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(sb->s_dev)));
+ QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", sb->s_id));
rd = le32_to_cpu(sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk) - 1;
rl = le32_to_cpu(sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size);
for (j = 0; j < rl; j++) {
@@ -339,13 +337,10 @@ static struct super_block *qnx4_read_super(struct super_block *s,
void *data, int silent)
{
struct buffer_head *bh;
- kdev_t dev = s->s_dev;
struct inode *root;
const char *errmsg;
- set_blocksize(dev, QNX4_BLOCK_SIZE);
- s->s_blocksize = QNX4_BLOCK_SIZE;
- s->s_blocksize_bits = QNX4_BLOCK_SIZE_BITS;
+ sb_set_blocksize(s, QNX4_BLOCK_SIZE);
/* Check the boot signature. Since the qnx4 code is
dangerous, we should leave as quickly as possible
@@ -445,6 +440,7 @@ static void qnx4_read_inode(struct inode *inode)
struct buffer_head *bh;
struct qnx4_inode_entry *raw_inode;
int block, ino;
+ struct super_block *sb = inode->i_sb;
ino = inode->i_ino;
inode->i_mode = 0;
@@ -452,14 +448,14 @@ static void qnx4_read_inode(struct inode *inode)
QNX4DEBUG(("Reading inode : [%d]\n", ino));
if (!ino) {
printk("qnx4: bad inode number on dev %s: %d is out of range\n",
- kdevname(inode->i_dev), ino);
+ sb->s_id, ino);
return;
}
block = ino / QNX4_INODES_PER_BLOCK;
- if (!(bh = sb_bread(inode->i_sb, block))) {
+ if (!(bh = sb_bread(sb, block))) {
printk("qnx4: major problem: unable to read inode from dev "
- "%s\n", kdevname(inode->i_dev));
+ "%s\n", sb->s_id);
return;
}
raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
@@ -490,7 +486,7 @@ static void qnx4_read_inode(struct inode *inode)
inode->i_mapping->a_ops = &qnx4_aops;
inode->u.qnx4_i.mmu_private = inode->i_size;
} else
- printk("qnx4: bad inode %d on dev %s\n",ino,kdevname(inode->i_dev));
+ printk("qnx4: bad inode %d on dev %s\n",ino,sb->s_id);
brelse(bh);
}
diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c
index 7366b757f..f282935b7 100644
--- a/fs/qnx4/namei.c
+++ b/fs/qnx4/namei.c
@@ -21,7 +21,6 @@
#include <linux/fcntl.h>
#include <linux/errno.h>
-#include <asm/segment.h>
/*
* check if the filename is correct. For some obscure reason, qnx writes a
@@ -214,7 +213,7 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry)
retval = -EPERM;
if (!inode->i_nlink) {
QNX4DEBUG(("Deleting nonexistent file (%s:%lu), %d\n",
- kdevname(inode->i_dev),
+ inode->i_sb->s_id,
inode->i_ino, inode->i_nlink));
inode->i_nlink = 1;
}
diff --git a/fs/qnx4/truncate.c b/fs/qnx4/truncate.c
index 9dad91a17..10c312583 100644
--- a/fs/qnx4/truncate.c
+++ b/fs/qnx4/truncate.c
@@ -13,9 +13,8 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/qnx4_fs.h>
#include <linux/fs.h>
+#include <linux/qnx4_fs.h>
#include <linux/locks.h>
#include <asm/uaccess.h>
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index b93e28354..b8994583f 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -325,6 +325,7 @@ static struct super_block *ramfs_read_super(struct super_block * sb, void * data
}
static DECLARE_FSTYPE(ramfs_fs_type, "ramfs", ramfs_read_super, FS_LITTER);
+static DECLARE_FSTYPE(rootfs_fs_type, "rootfs", ramfs_read_super, FS_NOMOUNT|FS_LITTER);
static int __init init_ramfs_fs(void)
{
@@ -338,5 +339,11 @@ static void __exit exit_ramfs_fs(void)
module_init(init_ramfs_fs)
module_exit(exit_ramfs_fs)
+
+int __init init_rootfs(void)
+{
+ return register_filesystem(&rootfs_fs_type);
+}
+
MODULE_LICENSE("GPL");
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 05afd10d9..9caf73298 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -111,8 +111,8 @@ void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long
/* clear bit for the given block in bit map */
if (!reiserfs_test_and_clear_le_bit (offset, apbh[nr]->b_data)) {
reiserfs_warning ("vs-4080: reiserfs_free_block: "
- "free_block (%04x:%lu)[dev:blocknr]: bit already cleared\n",
- s->s_dev, block);
+ "free_block (%s:%lu)[dev:blocknr]: bit already cleared\n",
+ s->s_id, block);
}
journal_mark_dirty (th, s, apbh[nr]);
diff --git a/fs/reiserfs/buffer2.c b/fs/reiserfs/buffer2.c
index 26570b6d3..4ef62b2c9 100644
--- a/fs/reiserfs/buffer2.c
+++ b/fs/reiserfs/buffer2.c
@@ -47,7 +47,7 @@ void wait_buffer_until_released (const struct buffer_head * bh)
}
run_task_queue(&tq_disk);
current->policy |= SCHED_YIELD;
- /*current->counter = 0;*/
+ /* current->dyn_prio = 0; */
schedule();
}
if (repeat_counter > 30000000) {
@@ -64,12 +64,12 @@ void wait_buffer_until_released (const struct buffer_head * bh)
block. */
/* The function is NOT SCHEDULE-SAFE! */
-struct buffer_head * reiserfs_bread (struct super_block *super, int n_block, int n_size)
+struct buffer_head * reiserfs_bread (struct super_block *super, int n_block)
{
struct buffer_head *result;
PROC_EXP( unsigned int ctx_switches = kstat.context_swtch );
- result = bread (super -> s_dev, n_block, n_size);
+ result = sb_bread(super, n_block);
PROC_INFO_INC( super, breads );
PROC_EXP( if( kstat.context_swtch != ctx_switches )
PROC_INFO_INC( super, bread_miss ) );
@@ -84,9 +84,9 @@ struct buffer_head * reiserfs_bread (struct super_block *super, int n_block, in
actually get the block off of the disk. */
/* The function is NOT SCHEDULE-SAFE! */
-struct buffer_head * reiserfs_getblk (kdev_t n_dev, int n_block, int n_size)
+struct buffer_head * reiserfs_getblk(struct super_block *sb, int n_block)
{
- return getblk (n_dev, n_block, n_size);
+ return sb_getblk(sb, n_block);
}
#ifdef NEW_GET_NEW_BUFFER
@@ -114,7 +114,7 @@ static int get_new_buffer_near_blocknr(
blocknr, 1)) == NO_DISK_SPACE )
return NO_DISK_SPACE;
- *pp_s_new_bh = reiserfs_getblk(p_s_sb->s_dev, n_new_blocknumber, p_s_sb->s_blocksize);
+ *pp_s_new_bh = reiserfs_getblk(p_s_sb, n_new_blocknumber);
if ( buffer_uptodate(*pp_s_new_bh) ) {
RFALSE( buffer_dirty(*pp_s_new_bh) || (*pp_s_new_bh)->b_dev == NODEV,
@@ -149,7 +149,7 @@ static int get_new_buffer_near_blocknr(
printk("get_new_buffer(%u): counter(%d) too big", current->pid, repeat_counter);
#endif
- current->counter = 0;
+ current->time_slice = 0;
schedule();
}
@@ -291,7 +291,7 @@ int get_new_buffer(
if ( (n_repeat = reiserfs_new_unf_blocknrs (th, &n_new_blocknumber, p_s_bh->b_blocknr)) == NO_DISK_SPACE )
return NO_DISK_SPACE;
- *pp_s_new_bh = reiserfs_getblk(p_s_sb->s_dev, n_new_blocknumber, p_s_sb->s_blocksize);
+ *pp_s_new_bh = reiserfs_getblk(p_s_sb, n_new_blocknumber);
if (atomic_read (&(*pp_s_new_bh)->b_count) > 1) {
/* Free path buffers to prevent deadlock which can occur in the
situation like : this process holds p_s_path; Block
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
index 5f800a83b..2dec58fa9 100644
--- a/fs/reiserfs/fix_node.c
+++ b/fs/reiserfs/fix_node.c
@@ -806,7 +806,7 @@ static int get_empty_nodes(
RFALSE( ! *p_n_blocknr,
"PAP-8135: reiserfs_new_blocknrs failed when got new blocks");
- p_s_new_bh = reiserfs_getblk(p_s_sb->s_dev, *p_n_blocknr, p_s_sb->s_blocksize);
+ p_s_new_bh = reiserfs_getblk(p_s_sb, *p_n_blocknr);
if (atomic_read (&(p_s_new_bh->b_count)) > 1) {
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*
@@ -1926,7 +1926,7 @@ static int get_neighbors(
n_child_position = ( p_s_bh == p_s_tb->FL[n_h] ) ? p_s_tb->lkey[n_h] : B_NR_ITEMS (p_s_tb->FL[n_h]);
n_son_number = B_N_CHILD_NUM(p_s_tb->FL[n_h], n_child_position);
- p_s_bh = reiserfs_bread(p_s_sb, n_son_number, p_s_sb->s_blocksize);
+ p_s_bh = reiserfs_bread(p_s_sb, n_son_number);
if (!p_s_bh)
return IO_ERROR;
if ( FILESYSTEM_CHANGED_TB (p_s_tb) ) {
@@ -1959,7 +1959,7 @@ static int get_neighbors(
n_child_position = ( p_s_bh == p_s_tb->FR[n_h] ) ? p_s_tb->rkey[n_h] + 1 : 0;
n_son_number = B_N_CHILD_NUM(p_s_tb->FR[n_h], n_child_position);
- p_s_bh = reiserfs_bread(p_s_sb, n_son_number, p_s_sb->s_blocksize);
+ p_s_bh = reiserfs_bread(p_s_sb, n_son_number);
if (!p_s_bh)
return IO_ERROR;
if ( FILESYSTEM_CHANGED_TB (p_s_tb) ) {
@@ -2115,7 +2115,7 @@ static void tb_buffer_sanity_check (struct super_block * p_s_sb,
reiserfs_panic (p_s_sb, "tb_buffer_sanity_check(): buffer is not in tree %s[%d] (%b)\n", descr, level, p_s_bh);
}
- if (p_s_bh->b_dev != p_s_sb->s_dev ||
+ if (!kdev_same(p_s_bh->b_dev, p_s_sb->s_dev) ||
p_s_bh->b_size != p_s_sb->s_blocksize ||
p_s_bh->b_blocknr > SB_BLOCK_COUNT(p_s_sb)) {
reiserfs_panic (p_s_sb, "tb_buffer_sanity_check(): check failed for buffer %s[%d] (%b)\n", descr, level, p_s_bh);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 65ac67889..688d5c8e6 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -205,9 +205,7 @@ static inline int indirect_item_found (int retval, struct item_head * ih)
static inline void set_block_dev_mapped (struct buffer_head * bh,
b_blocknr_t block, struct inode * inode)
{
- bh->b_dev = inode->i_dev;
- bh->b_blocknr = block;
- bh->b_state |= (1UL << BH_Mapped);
+ map_bh(bh, inode->i_sb, block);
}
@@ -287,9 +285,7 @@ research:
blocknr = get_block_num(ind_item, path.pos_in_item) ;
ret = 0 ;
if (blocknr) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = blocknr;
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, inode->i_sb, blocknr);
} else if ((args & GET_BLOCK_NO_HOLE)) {
ret = -ENOENT ;
}
@@ -380,10 +376,9 @@ research:
finished:
pathrelse (&path);
- bh_result->b_blocknr = 0 ;
- bh_result->b_dev = inode->i_dev;
+ /* I _really_ doubt that you want it. Chris? */
+ map_bh(bh_result, inode->i_sb, 0);
mark_buffer_uptodate (bh_result, 1);
- bh_result->b_state |= (1UL << BH_Mapped);
return 0;
}
@@ -970,7 +965,7 @@ static void inode2sd (void * sd, struct inode * inode)
set_sd_v2_ctime(sd_v2, inode->i_ctime );
set_sd_v2_blocks(sd_v2, inode->i_blocks );
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
- set_sd_v2_rdev(sd_v2, inode->i_rdev );
+ set_sd_v2_rdev(sd_v2, kdev_t_to_nr(inode->i_rdev) );
}
else
{
@@ -994,7 +989,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode)
set_sd_v1_mtime(sd_v1, inode->i_mtime );
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- set_sd_v1_rdev(sd_v1, inode->i_rdev );
+ set_sd_v1_rdev(sd_v1, kdev_t_to_nr(inode->i_rdev) );
else
set_sd_v1_blocks(sd_v1, inode->i_blocks );
@@ -1520,7 +1515,6 @@ struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th,
// these do not go to on-disk stat data
inode->i_ino = le32_to_cpu (ih.ih_key.k_objectid);
inode->i_blksize = PAGE_SIZE;
- inode->i_dev = sb->s_dev;
// store in in-core inode the key of stat data and version all
// object items will have (directory items will have old offset
@@ -1794,7 +1788,7 @@ research:
goto research ;
}
} else {
- reiserfs_warning("clm-6003: bad item inode %lu, device %s\n", inode->i_ino, kdevname(inode->i_sb->s_dev)) ;
+ reiserfs_warning("clm-6003: bad item inode %lu, device %s\n", inode->i_ino, inode->i_sb->s_id) ;
retval = -EIO ;
goto out ;
}
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 3b70c989b..7bef738e2 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -420,7 +420,7 @@ static inline struct reiserfs_journal_cnode *get_journal_hash_dev(struct reiserf
struct reiserfs_journal_cnode *cn ;
cn = journal_hash(table, dev, bl) ;
while(cn) {
- if ((cn->blocknr == bl) && (cn->dev == dev))
+ if ((cn->blocknr == bl) && (kdev_same(cn->dev, dev)))
return cn ;
cn = cn->hnext ;
}
@@ -766,7 +766,7 @@ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct reiserfs_journa
cn = cn->hprev ;
while(cn) {
- if (cn->dev == dev && cn->blocknr == blocknr && cn->jlist) {
+ if (kdev_same(cn->dev, dev) && cn->blocknr == blocknr && cn->jlist) {
return cn->jlist ;
}
cn = cn->hprev ;
@@ -1179,7 +1179,7 @@ loop_start:
mark_buffer_notjournal_dirty(cn->bh) ;
while(walk_cn) {
if (walk_cn->bh && walk_cn->blocknr == blocknr &&
- walk_cn->dev == cn->dev) {
+ kdev_same(walk_cn->dev, cn->dev)) {
if (walk_cn->jlist) {
atomic_dec(&(walk_cn->jlist->j_nonzerolen)) ;
}
@@ -1282,7 +1282,7 @@ void remove_journal_hash(struct reiserfs_journal_cnode **table, struct reiserfs_
}
cur = *head ;
while(cur) {
- if (cur->blocknr == bh->b_blocknr && cur->dev == bh->b_dev && (jl == NULL || jl == cur->jlist) &&
+ if (cur->blocknr == bh->b_blocknr && kdev_same(cur->dev, bh->b_dev) && (jl == NULL || jl == cur->jlist) &&
(!test_bit(BLOCK_FREED, &cur->state) || remove_freed)) {
if (cur->hnext) {
cur->hnext->hprev = cur->hprev ;
@@ -1293,7 +1293,7 @@ void remove_journal_hash(struct reiserfs_journal_cnode **table, struct reiserfs_
*head = cur->hnext ;
}
cur->blocknr = 0 ;
- cur->dev = 0 ;
+ cur->dev = NODEV ;
cur->state = 0 ;
if (cur->bh && cur->jlist) /* anybody who clears the cur->bh will also dec the nonzerolen */
atomic_dec(&(cur->jlist->j_nonzerolen)) ;
@@ -1607,8 +1607,7 @@ static int journal_read(struct super_block *p_s_sb) {
int ret ;
cur_dblock = reiserfs_get_journal_block(p_s_sb) ;
- printk("reiserfs: checking transaction log (device %s) ...\n",
- kdevname(p_s_sb->s_dev)) ;
+ printk("reiserfs: checking transaction log (device %s) ...\n", p_s_sb->s_id) ;
start = CURRENT_TIME ;
/* step 1, read in the journal header block. Check the transaction it says
@@ -2302,7 +2301,7 @@ static int can_dirty(struct reiserfs_journal_cnode *cn) {
** to disk right now.
*/
while(cur && can_dirty) {
- if (cur->jlist && cur->bh && cur->blocknr && cur->dev == dev &&
+ if (cur->jlist && cur->bh && cur->blocknr && kdev_same(cur->dev, dev) &&
cur->blocknr == blocknr) {
can_dirty = 0 ;
}
@@ -2315,7 +2314,7 @@ static int can_dirty(struct reiserfs_journal_cnode *cn) {
while(cur && can_dirty) {
if (cur->jlist && cur->jlist->j_len > 0 &&
atomic_read(&(cur->jlist->j_commit_left)) > 0 && cur->bh &&
- cur->blocknr && cur->dev == dev && cur->blocknr == blocknr) {
+ cur->blocknr && kdev_same(cur->dev, dev) && cur->blocknr == blocknr) {
can_dirty = 0 ;
}
cur = cur->hnext ;
@@ -2582,7 +2581,7 @@ int journal_mark_freed(struct reiserfs_transaction_handle *th, struct super_bloc
/* find all older transactions with this block, make sure they don't try to write it out */
cn = get_journal_hash_dev(SB_JOURNAL(p_s_sb)->j_list_hash_table, p_s_sb->s_dev, blocknr, p_s_sb->s_blocksize) ;
while (cn) {
- if (p_s_sb->s_dev == cn->dev && blocknr == cn->blocknr) {
+ if (kdev_same(p_s_sb->s_dev, cn->dev) && blocknr == cn->blocknr) {
set_bit(BLOCK_FREED, &cn->state) ;
if (cn->bh) {
if (!cleaned) {
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index de5ddcca9..487975385 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -817,7 +817,7 @@ int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
if (!inode->i_nlink) {
printk("reiserfs_unlink: deleting nonexistent file (%s:%lu), %d\n",
- kdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
+ inode->i_sb->s_id, inode->i_ino, inode->i_nlink);
inode->i_nlink = 1;
}
@@ -1168,7 +1168,7 @@ int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
// FIXME: do we need this? shouldn't we simply continue?
run_task_queue(&tq_disk);
current->policy |= SCHED_YIELD;
- /*current->counter = 0;*/
+ /*current->time_slice = 0;*/
schedule();
#endif
continue;
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
index 5fce65fec..987ee487f 100644
--- a/fs/reiserfs/prints.c
+++ b/fs/reiserfs/prints.c
@@ -335,7 +335,7 @@ void reiserfs_panic (struct super_block * sb, const char * fmt, ...)
/* this is not actually called, but makes reiserfs_panic() "noreturn" */
panic ("REISERFS: panic (device %s): %s\n",
- sb ? kdevname(sb->s_dev) : "sb == 0", error_buf);
+ sb ? sb->s_id : "sb == 0", error_buf);
}
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index 3b1d6073a..5e6a45b69 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -546,14 +546,13 @@ static const char *proc_info_root_name = "fs/reiserfs";
int reiserfs_proc_info_init( struct super_block *sb )
{
spin_lock_init( & __PINFO( sb ).lock );
- sb->u.reiserfs_sb.procdir = proc_mkdir( bdevname( sb -> s_dev ),
- proc_info_root );
+ sb->u.reiserfs_sb.procdir = proc_mkdir(sb->s_id, proc_info_root);
if( sb->u.reiserfs_sb.procdir ) {
sb->u.reiserfs_sb.procdir -> owner = THIS_MODULE;
return 0;
}
reiserfs_warning( "reiserfs: cannot create /proc/%s/%s\n",
- proc_info_root_name, bdevname( sb -> s_dev ) );
+ proc_info_root_name, sb->s_id );
return 1;
}
@@ -564,7 +563,7 @@ int reiserfs_proc_info_done( struct super_block *sb )
__PINFO( sb ).exiting = 1;
spin_unlock( & __PINFO( sb ).lock );
if ( proc_info_root ) {
- remove_proc_entry( bdevname( sb -> s_dev ), proc_info_root );
+ remove_proc_entry( sb->s_id, proc_info_root );
sb->u.reiserfs_sb.procdir = NULL;
}
return 0;
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index ab7a31036..25bcca1b9 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -111,7 +111,7 @@ int reiserfs_resize (struct super_block * s, unsigned long block_count_new)
for (i = 0; i < bmap_nr; i++)
bitmap[i] = SB_AP_BITMAP(s)[i];
for (i = bmap_nr; i < bmap_nr_new; i++) {
- bitmap[i] = reiserfs_getblk(s->s_dev, i * s->s_blocksize * 8, s->s_blocksize);
+ bitmap[i] = reiserfs_getblk(s, i * s->s_blocksize * 8);
memset(bitmap[i]->b_data, 0, sb->s_blocksize);
reiserfs_test_and_set_le_bit(0, bitmap[i]->b_data);
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 327bd7311..cbdc1a349 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -395,7 +395,7 @@ static inline int key_in_buffer (
p_s_chk_path->path_length > MAX_HEIGHT,
"PAP-5050: pointer to the key(%p) is NULL or illegal path length(%d)",
p_s_key, p_s_chk_path->path_length);
- RFALSE( PATH_PLAST_BUFFER(p_s_chk_path)->b_dev == NODEV,
+ RFALSE( kdev_same(PATH_PLAST_BUFFER(p_s_chk_path)->b_dev, NODEV),
"PAP-5060: device must not be NODEV");
if ( COMP_KEYS(get_lkey(p_s_chk_path, p_s_sb), p_s_key) == 1 )
@@ -604,7 +604,7 @@ static void search_by_key_reada (struct super_block * s, int blocknr)
if (blocknr == 0)
return;
- bh = reiserfs_getblk (s->s_dev, blocknr, s->s_blocksize);
+ bh = reiserfs_getblk (s, blocknr);
if (!buffer_uptodate (bh)) {
ll_rw_block (READA, 1, &bh);
@@ -649,8 +649,7 @@ int search_by_key (struct super_block * p_s_sb,
DISK_LEAF_NODE_LEVEL */
) {
int n_block_number = SB_ROOT_BLOCK (p_s_sb),
- expected_level = SB_TREE_HEIGHT (p_s_sb),
- n_block_size = p_s_sb->s_blocksize;
+ expected_level = SB_TREE_HEIGHT (p_s_sb);
struct buffer_head * p_s_bh;
struct path_element * p_s_last_element;
int n_node_level, n_retval;
@@ -697,7 +696,7 @@ int search_by_key (struct super_block * p_s_sb,
/* Read the next tree node, and set the last element in the path to
have a pointer to it. */
if ( ! (p_s_bh = p_s_last_element->pe_buffer =
- reiserfs_bread(p_s_sb, n_block_number, n_block_size)) ) {
+ reiserfs_bread(p_s_sb, n_block_number)) ) {
p_s_search_path->path_length --;
pathrelse(p_s_search_path);
return IO_ERROR;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index f36b63582..4281c39ee 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -19,6 +19,7 @@
#include <linux/smp_lock.h>
#include <linux/locks.h>
#include <linux/init.h>
+#include <linux/blkdev.h>
#define REISERFS_OLD_BLOCKSIZE 4096
#define REISERFS_SUPER_MAGIC_STRING_OFFSET_NJ 20
@@ -220,7 +221,7 @@ static int parse_options (char * options, unsigned long * mount_options, unsigne
int reiserfs_is_super(struct super_block *s) {
- return (s->s_dev != 0 && s->s_op == &reiserfs_sops) ;
+ return (!kdev_same(s->s_dev, NODEV) && s->s_op == &reiserfs_sops) ;
}
@@ -302,11 +303,11 @@ static int read_bitmaps (struct super_block * s)
labeling scheme currently used will have enough space. Then we
need one block for the super. -Hans */
bmp = (REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */
- SB_AP_BITMAP (s)[0] = reiserfs_bread (s, bmp, s->s_blocksize);
+ SB_AP_BITMAP (s)[0] = reiserfs_bread (s, bmp);
if(!SB_AP_BITMAP(s)[0])
return 1;
for (i = 1, bmp = dl = s->s_blocksize * 8; i < sb_bmap_nr(rs); i ++) {
- SB_AP_BITMAP (s)[i] = reiserfs_bread (s, bmp, s->s_blocksize);
+ SB_AP_BITMAP (s)[i] = reiserfs_bread (s, bmp);
if (!SB_AP_BITMAP (s)[i])
return 1;
bmp += dl;
@@ -329,7 +330,7 @@ static int read_old_bitmaps (struct super_block * s)
memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * sb_bmap_nr(rs));
for (i = 0; i < sb_bmap_nr(rs); i ++) {
- SB_AP_BITMAP (s)[i] = reiserfs_bread (s, bmp1 + i, s->s_blocksize);
+ SB_AP_BITMAP (s)[i] = reiserfs_bread (s, bmp1 + i);
if (!SB_AP_BITMAP (s)[i])
return 1;
}
@@ -355,17 +356,17 @@ void check_bitmap (struct super_block * s)
free, SB_FREE_BLOCKS (s));
}
-static int read_super_block (struct super_block * s, int size, int offset)
+static int read_super_block (struct super_block * s, int offset)
{
struct buffer_head * bh;
struct reiserfs_super_block * rs;
- bh = bread (s->s_dev, offset / size, size);
+ bh = sb_bread (s, offset / s->s_blocksize);
if (!bh) {
printk ("read_super_block: "
"bread failed (dev %s, block %d, size %d)\n",
- kdevname (s->s_dev), offset / size, size);
+ s->s_id, offset / s->s_blocksize, s->s_blocksize);
return 1;
}
@@ -373,7 +374,7 @@ static int read_super_block (struct super_block * s, int size, int offset)
if (!is_reiserfs_magic_string (rs)) {
printk ("read_super_block: "
"can't find a reiserfs filesystem on (dev %s, block %lu, size %d)\n",
- kdevname(s->s_dev), bh->b_blocknr, size);
+ s->s_id, bh->b_blocknr, s->s_blocksize);
brelse (bh);
return 1;
}
@@ -381,32 +382,25 @@ static int read_super_block (struct super_block * s, int size, int offset)
//
// ok, reiserfs signature (old or new) found in at the given offset
//
- s->s_blocksize = sb_blocksize(rs);
- s->s_blocksize_bits = 0;
- while ((1 << s->s_blocksize_bits) != s->s_blocksize)
- s->s_blocksize_bits ++;
-
brelse (bh);
- if (s->s_blocksize != size)
- set_blocksize (s->s_dev, s->s_blocksize);
+ sb_set_blocksize (s, sb_blocksize(rs));
- bh = reiserfs_bread (s, offset / s->s_blocksize, s->s_blocksize);
+ bh = reiserfs_bread (s, offset / s->s_blocksize);
if (!bh) {
printk("read_super_block: "
"bread failed (dev %s, block %d, size %d)\n",
- kdevname (s->s_dev), offset / size, size);
+ s->s_id, offset / s->s_blocksize, s->s_blocksize);
return 1;
}
rs = (struct reiserfs_super_block *)bh->b_data;
- if (!is_reiserfs_magic_string (rs) ||
- sb_blocksize(rs) != s->s_blocksize) {
+ if (!is_reiserfs_magic_string (rs) || sb_blocksize(rs) != s->s_blocksize) {
printk ("read_super_block: "
"can't find a reiserfs filesystem on (dev %s, block %lu, size %d)\n",
- kdevname(s->s_dev), bh->b_blocknr, size);
+ s->s_id, bh->b_blocknr, s->s_blocksize);
brelse (bh);
- printk ("read_super_block: can't find a reiserfs filesystem on dev %s.\n", kdevname(s->s_dev));
+ printk ("read_super_block: can't find a reiserfs filesystem on dev %s.\n", s->s_id);
return 1;
}
/* must check to be sure we haven't pulled an old format super out
@@ -612,9 +606,7 @@ struct super_block * reiserfs_read_super (struct super_block * s, void * data, i
{
int size;
struct inode *root_inode;
- kdev_t dev = s->s_dev;
int j;
- extern int *blksize_size[];
struct reiserfs_transaction_handle th ;
int old_format = 0;
unsigned long blocks;
@@ -633,18 +625,14 @@ struct super_block * reiserfs_read_super (struct super_block * s, void * data, i
return NULL;
}
- if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)] != 0) {
- /* as blocksize is set for partition we use it */
- size = blksize_size[MAJOR(dev)][MINOR(dev)];
- } else {
- size = BLOCK_SIZE;
- set_blocksize (s->s_dev, BLOCK_SIZE);
- }
+ size = block_size(s->s_dev);
+ sb_set_blocksize(s, size);
/* read block (64-th 1k block), which can contain reiserfs super block */
- if (read_super_block (s, size, REISERFS_DISK_OFFSET_IN_BYTES)) {
+ if (read_super_block (s, REISERFS_DISK_OFFSET_IN_BYTES)) {
// try old format (undistributed bitmap, super block in 8-th 1k block of a device)
- if (read_super_block (s, size, REISERFS_OLD_DISK_OFFSET_IN_BYTES))
+ sb_set_blocksize(s, size);
+ if (read_super_block (s, REISERFS_OLD_DISK_OFFSET_IN_BYTES))
goto error;
else
old_format = 1;
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index 9c791cbce..0aa6ca89b 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -96,15 +96,12 @@ static struct super_block *
romfs_read_super(struct super_block *s, void *data, int silent)
{
struct buffer_head *bh;
- kdev_t dev = s->s_dev;
struct romfs_super_block *rsb;
int sz;
/* I would parse the options here, but there are none.. :) */
- set_blocksize(dev, ROMBSIZE);
- s->s_blocksize = ROMBSIZE;
- s->s_blocksize_bits = ROMBSBITS;
+ sb_set_blocksize(s, ROMBSIZE);
s->u.generic_sbp = (void *) 0;
s->s_maxbytes = 0xFFFFFFFF;
@@ -121,12 +118,12 @@ romfs_read_super(struct super_block *s, void *data, int silent)
|| sz < ROMFH_SIZE) {
if (!silent)
printk ("VFS: Can't find a romfs filesystem on dev "
- "%s.\n", kdevname(dev));
+ "%s.\n", s->s_id);
goto out;
}
if (romfs_checksum(rsb, min_t(int, sz, 512))) {
printk ("romfs: bad initial checksum on dev "
- "%s.\n", kdevname(dev));
+ "%s.\n", s->s_id);
goto out;
}
@@ -520,7 +517,9 @@ romfs_read_inode(struct inode *i)
default:
/* depending on MBZ for sock/fifos */
nextfh = ntohl(ri.spec);
- nextfh = kdev_t_to_nr(MKDEV(nextfh>>16,nextfh&0xffff));
+ /* convert back and forth for typechecking and
+ * source tagging */
+ nextfh = kdev_t_to_nr(mk_kdev(nextfh>>16,nextfh&0xffff));
init_special_inode(i, ino, nextfh);
}
}
diff --git a/fs/smbfs/ChangeLog b/fs/smbfs/ChangeLog
index 63ecf3d06..1ad88890b 100644
--- a/fs/smbfs/ChangeLog
+++ b/fs/smbfs/ChangeLog
@@ -1,5 +1,15 @@
ChangeLog for smbfs.
+2001-12-31 René Scharfe <l.s.r@web.de>
+
+ * inode.c: added smb_show_options to show mount options in /proc/mounts
+ * inode.c, getopt.c, getopt.h: merged flag and has_arg in struct option
+ * inode.c: use S_IRWXUGO where appropriate
+
+2001-12-22 Urban Widmark <urban@teststation.com>
+
+ * file.c, proc.c: Fix problems triggered by the "fsx test"
+
2001-09-17 Urban Widmark <urban@teststation.com>
* proc.c: Use 4096 (was 512) as the blocksize for better write
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index d74e32ad6..6f1214176 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -270,7 +270,6 @@ out:
static int smb_prepare_write(struct file *file, struct page *page,
unsigned offset, unsigned to)
{
- kmap(page);
return 0;
}
@@ -283,7 +282,6 @@ static int smb_commit_write(struct file *file, struct page *page,
lock_kernel();
status = smb_updatepage(file, page, offset, to-offset);
unlock_kernel();
- kunmap(page);
return status;
}
@@ -349,8 +347,14 @@ static int
smb_file_release(struct inode *inode, struct file * file)
{
lock_kernel();
- if (!--inode->u.smbfs_i.openers)
+ if (!--inode->u.smbfs_i.openers) {
+ /* We must flush any dirty pages now as we won't be able to
+ write anything after close. mmap can trigger this.
+ "openers" should perhaps include mmap'ers ... */
+ filemap_fdatasync(inode->i_mapping);
+ filemap_fdatawait(inode->i_mapping);
smb_close(inode);
+ }
unlock_kernel();
return 0;
}
diff --git a/fs/smbfs/getopt.c b/fs/smbfs/getopt.c
index 20276da09..626543fb8 100644
--- a/fs/smbfs/getopt.c
+++ b/fs/smbfs/getopt.c
@@ -46,7 +46,7 @@ int smb_getopt(char *caller, char **options, struct option *opts,
for (i = 0; opts[i].name != NULL; i++) {
if (!strcmp(opts[i].name, token)) {
- if (opts[i].has_arg && (!val || !*val)) {
+ if (!opts[i].flag && (!val || !*val)) {
printk("%s: the %s option requires an argument\n",
caller, token);
return -1;
diff --git a/fs/smbfs/getopt.h b/fs/smbfs/getopt.h
index 691f21103..146219ac7 100644
--- a/fs/smbfs/getopt.h
+++ b/fs/smbfs/getopt.h
@@ -3,7 +3,6 @@
struct option {
const char *name;
- int has_arg;
unsigned long flag;
int val;
};
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 9f5921c18..6b3648f89 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -22,6 +22,7 @@
#include <linux/dcache.h>
#include <linux/smp_lock.h>
#include <linux/nls.h>
+#include <linux/seq_file.h>
#include <linux/smb_fs.h>
#include <linux/smbno.h>
@@ -41,9 +42,12 @@
#define SMB_NLS_REMOTE ""
#endif
+#define SMB_TTL_DEFAULT 1000
+
static void smb_delete_inode(struct inode *);
static void smb_put_super(struct super_block *);
static int smb_statfs(struct super_block *, struct statfs *);
+static int smb_show_options(struct seq_file *, struct vfsmount *);
static struct super_operations smb_sops =
{
@@ -51,6 +55,7 @@ static struct super_operations smb_sops =
delete_inode: smb_delete_inode,
put_super: smb_put_super,
statfs: smb_statfs,
+ show_options: smb_show_options,
};
@@ -259,21 +264,20 @@ smb_delete_inode(struct inode *ino)
clear_inode(ino);
}
-/* FIXME: flags and has_arg could probably be merged. */
static struct option opts[] = {
- { "version", 1, 0, 'v' },
- { "win95", 0, SMB_MOUNT_WIN95, 1 },
- { "oldattr", 0, SMB_MOUNT_OLDATTR, 1 },
- { "dirattr", 0, SMB_MOUNT_DIRATTR, 1 },
- { "case", 0, SMB_MOUNT_CASE, 1 },
- { "uid", 1, 0, 'u' },
- { "gid", 1, 0, 'g' },
- { "file_mode", 1, 0, 'f' },
- { "dir_mode", 1, 0, 'd' },
- { "iocharset", 1, 0, 'i' },
- { "codepage", 1, 0, 'c' },
- { "ttl", 1, 0, 't' },
- { NULL, 0, 0, 0}
+ { "version", 0, 'v' },
+ { "win95", SMB_MOUNT_WIN95, 1 },
+ { "oldattr", SMB_MOUNT_OLDATTR, 1 },
+ { "dirattr", SMB_MOUNT_DIRATTR, 1 },
+ { "case", SMB_MOUNT_CASE, 1 },
+ { "uid", 0, 'u' },
+ { "gid", 0, 'g' },
+ { "file_mode", 0, 'f' },
+ { "dir_mode", 0, 'd' },
+ { "iocharset", 0, 'i' },
+ { "codepage", 0, 'c' },
+ { "ttl", 0, 't' },
+ { NULL, 0, 0}
};
static int
@@ -310,12 +314,10 @@ parse_options(struct smb_mount_data_kernel *mnt, char *options)
mnt->gid = value;
break;
case 'f':
- mnt->file_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
- mnt->file_mode |= S_IFREG;
+ mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
break;
case 'd':
- mnt->dir_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
- mnt->dir_mode |= S_IFDIR;
+ mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
break;
case 'i':
strncpy(mnt->codepage.local_name, optarg,
@@ -338,6 +340,45 @@ parse_options(struct smb_mount_data_kernel *mnt, char *options)
return c;
}
+/*
+ * smb_show_options() is for displaying mount options in /proc/mounts.
+ * It tries to avoid showing settings that were not changed from their
+ * defaults.
+ */
+static int
+smb_show_options(struct seq_file *s, struct vfsmount *m)
+{
+ struct smb_mount_data_kernel *mnt = m->mnt_sb->u.smbfs_sb.mnt;
+ int i;
+
+ for (i = 0; opts[i].name != NULL; i++)
+ if (mnt->flags & opts[i].flag)
+ seq_printf(s, ",%s", opts[i].name);
+
+ if (mnt->uid != 0)
+ seq_printf(s, ",uid=%d", mnt->uid);
+ if (mnt->gid != 0)
+ seq_printf(s, ",gid=%d", mnt->gid);
+ if (mnt->mounted_uid != 0)
+ seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
+
+ /*
+ * Defaults for file_mode and dir_mode are unknown to us; they
+ * depend on the current umask of the user doing the mount.
+ */
+ seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
+ seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
+
+ if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
+ seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
+ if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
+ seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
+
+ if (mnt->ttl != SMB_TTL_DEFAULT)
+ seq_printf(s, ",ttl=%d", mnt->ttl);
+
+ return 0;
+}
static void
smb_put_super(struct super_block *sb)
@@ -425,7 +466,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
strncpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
SMB_NLS_MAXNAMELEN);
- mnt->ttl = 1000;
+ mnt->ttl = SMB_TTL_DEFAULT;
if (ver == SMB_MOUNT_OLDVERSION) {
mnt->version = oldmnt->version;
@@ -434,12 +475,8 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
mnt->uid = oldmnt->uid;
mnt->gid = oldmnt->gid;
- mnt->file_mode =
- oldmnt->file_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- mnt->dir_mode =
- oldmnt->dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- mnt->file_mode |= S_IFREG;
- mnt->dir_mode |= S_IFDIR;
+ mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
+ mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
mnt->flags = (oldmnt->file_mode >> 9);
} else {
@@ -510,7 +547,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
struct smb_sb_info *server = server_from_dentry(dentry);
- unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
+ unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
int error, changed, refresh = 0;
struct smb_fattr fattr;
@@ -535,6 +572,10 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
DENTRY_PATH(dentry),
(long) inode->i_size, (long) attr->ia_size);
+
+ filemap_fdatasync(inode->i_mapping);
+ filemap_fdatawait(inode->i_mapping);
+
error = smb_open(dentry, O_WRONLY);
if (error)
goto out;
diff --git a/fs/super.c b/fs/super.c
index d8acea2b4..14f9a9a9a 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -418,7 +418,7 @@ static inline struct super_block * find_super(kdev_t dev)
list_for_each(p, &super_blocks) {
struct super_block * s = sb_entry(p);
- if (s->s_dev == dev) {
+ if (kdev_same(s->s_dev, dev)) {
s->s_count++;
return s;
}
@@ -450,7 +450,7 @@ void sync_supers(kdev_t dev)
{
struct super_block * sb;
- if (dev) {
+ if (!kdev_none(dev)) {
sb = get_super(dev);
if (sb) {
if (sb->s_dirt)
@@ -487,7 +487,7 @@ struct super_block * get_super(kdev_t dev)
{
struct super_block * s;
- if (!dev)
+ if (kdev_none(dev))
return NULL;
while (1) {
@@ -540,11 +540,11 @@ int do_remount_sb(struct super_block *sb, int flags, void *data)
{
int retval;
- if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
+ if (!(flags & MS_RDONLY) && !kdev_none(sb->s_dev) && is_read_only(sb->s_dev))
return -EACCES;
/*flags |= MS_RDONLY;*/
if (flags & MS_RDONLY)
- acct_auto_close(sb->s_dev);
+ acct_auto_close(sb);
shrink_dcache_sb(sb);
fsync_super(sb);
/* If we are remounting RDONLY, make sure there are no rw files open */
@@ -578,7 +578,7 @@ static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
static void put_anon_dev(kdev_t dev)
{
spin_lock(&unnamed_dev_lock);
- clear_bit(MINOR(dev), unnamed_dev_in_use);
+ clear_bit(minor(dev), unnamed_dev_in_use);
spin_unlock(&unnamed_dev_lock);
}
@@ -608,7 +608,7 @@ struct super_block *get_anon_super(struct file_system_type *type,
int (*compare)(struct super_block *,void *), void *data)
{
struct super_block *s = alloc_super();
- kdev_t dev;
+ int dev;
struct list_head *p;
if (!s)
@@ -637,7 +637,7 @@ retry:
return old;
}
- s->s_dev = dev;
+ s->s_dev = mk_kdev(0, dev);
insert_super(s, type);
return s;
}
@@ -648,6 +648,7 @@ static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
struct inode *inode;
struct block_device *bdev;
struct block_device_operations *bdops;
+ devfs_handle_t de;
struct super_block * s;
struct nameidata nd;
struct list_head *p;
@@ -671,13 +672,15 @@ static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
goto out;
bd_acquire(inode);
bdev = inode->i_bdev;
- bdops = devfs_get_ops ( devfs_get_handle_from_inode (inode) );
+ de = devfs_get_handle_from_inode (inode);
+ bdops = devfs_get_ops (de); /* Increments module use count */
if (bdops) bdev->bd_op = bdops;
/* Done with lookups, semaphore down */
dev = to_kdev_t(bdev->bd_dev);
if (!(flags & MS_RDONLY))
mode |= FMODE_WRITE;
error = blkdev_get(bdev, mode, 0, BDEV_FS);
+ devfs_put_ops (de); /* Decrement module use count now we're safe */
if (error)
goto out;
check_disk_change(dev);
@@ -696,7 +699,7 @@ restart:
list_for_each(p, &super_blocks) {
struct super_block *old = sb_entry(p);
- if (old->s_dev != dev)
+ if (!kdev_same(old->s_dev, dev))
continue;
if (old->s_type != fs_type ||
((flags ^ old->s_flags) & MS_RDONLY)) {
@@ -715,16 +718,17 @@ restart:
s->s_bdev = bdev;
s->s_flags = flags;
insert_super(s, fs_type);
+ strncpy(s->s_id, bdevname(dev), sizeof(s->s_id));
+ error = -EINVAL;
if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
- goto Einval;
+ goto failed;
s->s_flags |= MS_ACTIVE;
path_release(&nd);
return s;
-Einval:
+failed:
deactivate_super(s);
remove_super(s);
- error = -EINVAL;
goto out;
out1:
blkdev_put(bdev, BDEV_FS);
diff --git a/fs/sysv/ChangeLog b/fs/sysv/ChangeLog
index 399e917d9..38525d6ce 100644
--- a/fs/sysv/ChangeLog
+++ b/fs/sysv/ChangeLog
@@ -1,3 +1,50 @@
+Fri Jan 4 2001 Alexander Viro <viro@math.psu.edu>
+
+ * ialloc.c (sysv_free_inode): Use sb->s_id instead of bdevname().
+ * inode.c (sysv_read_inode): Likewise.
+ (sysv_update_inode): Likewise.
+ (sysv_sync_inode): Likewise.
+ * super.c (detect_sysv): Likewise.
+ (complete_read_super): Likewise.
+ (sysv_read_super): Likewise.
+ (v7_read_super): Likewise.
+
+Sun Dec 30 2001 Manfred Spraul <manfreds@colorfullife.com>
+
+ * dir.c (dir_commit_chunk): Do not set dir->i_version.
+ (sysv_readdir): Likewise.
+
+Thu Dec 27 2001 Alexander Viro <viro@math.psu.edu>
+
+ * itree.c (get_block): Use map_bh() to fill out bh_result.
+
+Tue Dec 25 2001 Alexander Viro <viro@math.psu.edu>
+
+ * super.c (sysv_read_super): Use sb_set_blocksize() to set blocksize.
+ (v7_read_super): Likewise.
+
+Tue Nov 27 2001 Alexander Viro <viro@math.psu.edu>
+
+ * itree.c (get_block): Change type for iblock argument to sector_t.
+ * super.c (sysv_read_super): Set s_blocksize early.
+ (v7_read_super): Likewise.
+ * balloc.c (sysv_new_block): Use sb_bread(). instead of bread().
+ (sysv_count_free_blocks): Likewise.
+ * ialloc.c (sysv_raw_inode): Likewise.
+ * itree.c (get_branch): Likewise.
+ (free_branches): Likewise.
+ * super.c (sysv_read_super): Likewise.
+ (v7_read_super): Likewise.
+
+Sat Dec 15 2001 Christoph Hellwig <hch@caldera.de>
+
+ * inode.c (sysv_read_inode): Mark inode as bad in case of failure.
+ * super.c (complete_read_super): Check for bad root inode.
+
+Wed Nov 21 2001 Andrew Morton <andrewm@uow.edu.au>
+
+ * file.c (sysv_sync_file): Call fsync_inode_data_buffers.
+
Fri Oct 26 2001 Christoph Hellwig <hch@caldera.de>
* dir.c, ialloc.c, namei.c, include/linux/sysv_fs_i.h:
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 27dd7847f..db0b23354 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -41,7 +41,6 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
struct inode *dir = (struct inode *)page->mapping->host;
int err = 0;
- dir->i_version = ++event;
page->mapping->a_ops->commit_write(NULL, page, from, to);
if (IS_SYNC(dir))
err = waitfor_one_page(page);
@@ -111,7 +110,6 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
done:
filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
- filp->f_version = inode->i_version;
UPDATE_ATIME(inode);
return 0;
}
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index 474e67ec6..4e20e5e98 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -109,7 +109,7 @@ void sysv_free_inode(struct inode * inode)
clear_inode(inode);
if (!raw_inode) {
printk("sysv_free_inode: unable to read inode block on device "
- "%s\n", bdevname(inode->i_dev));
+ "%s\n", inode->i_sb->s_id);
return;
}
lock_super(sb);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 6233aecba..15b8b321b 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -149,16 +149,15 @@ static void sysv_read_inode(struct inode *inode)
ino = inode->i_ino;
if (!ino || ino > sb->sv_ninodes) {
- printk("Bad inode number on dev %s"
- ": %d is out of range\n",
- kdevname(inode->i_dev), ino);
- return;
+ printk("Bad inode number on dev %s: %d is out of range\n",
+ inode->i_sb->s_id, ino);
+ goto bad_inode;
}
raw_inode = sysv_raw_inode(sb, ino, &bh);
if (!raw_inode) {
printk("Major problem: unable to read inode from dev %s\n",
- bdevname(inode->i_dev));
- return;
+ inode->i_sb->s_id);
+ goto bad_inode;
}
/* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */
inode->i_mode = fs16_to_cpu(sb, raw_inode->i_mode);
@@ -178,6 +177,11 @@ static void sysv_read_inode(struct inode *inode)
rdev = (u16)fs32_to_cpu(sb, inode->u.sysv_i.i_data[0]);
inode->u.sysv_i.i_dir_start_lookup = 0;
sysv_set_inode(inode, rdev);
+ return;
+
+bad_inode:
+ make_bad_inode(inode);
+ return;
}
static struct buffer_head * sysv_update_inode(struct inode * inode)
@@ -190,7 +194,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
ino = inode->i_ino;
if (!ino || ino > sb->sv_ninodes) {
printk("Bad inode number on dev %s: %d is out of range\n",
- bdevname(inode->i_dev), ino);
+ inode->i_sb->s_id, ino);
return 0;
}
raw_inode = sysv_raw_inode(sb, ino, &bh);
@@ -237,7 +241,7 @@ int sysv_sync_inode(struct inode * inode)
wait_on_buffer(bh);
if (buffer_req(bh) && !buffer_uptodate(bh)) {
printk ("IO error syncing sysv inode [%s:%08lx]\n",
- bdevname(inode->i_dev), inode->i_ino);
+ inode->i_sb->s_id, inode->i_ino);
err = -1;
}
}
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 5d4ef2979..b88cc4325 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -211,9 +211,7 @@ reread:
/* Simplest case - block found, no allocation needed */
if (!partial) {
got_it:
- bh_result->b_dev = sb->s_dev;
- bh_result->b_blocknr = block_to_cpu(sb, chain[depth-1].key);
- bh_result->b_state |= (1UL << BH_Mapped);
+ map_bh(bh_result, sb, block_to_cpu(sb, chain[depth-1].key));
/* Clean up and exit */
partial = chain+depth-1; /* the whole chain */
goto cleanup;
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 2a38452d7..7c9c82932 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -208,7 +208,7 @@ static int detect_sysv (struct super_block *sb, struct buffer_head *bh)
if (!(sb->s_flags & MS_RDONLY)) {
printk("SysV FS: SCO EAFS on %s detected, "
"forcing read-only mode.\n",
- bdevname(sb->s_dev));
+ sb->s_id);
sb->s_flags |= MS_RDONLY;
}
return sbd->s_type;
@@ -232,7 +232,7 @@ static int detect_sysv (struct super_block *sb, struct buffer_head *bh)
if (sbd->s_type >= 0x10) {
printk("SysV FS: can't handle long file names on %s, "
- "forcing read-only mode.\n", kdevname(sb->s_dev));
+ "forcing read-only mode.\n", sb->s_id);
sb->s_flags |= MS_RDONLY;
}
@@ -315,17 +315,15 @@ static int complete_read_super(struct super_block *sb, int silent, int size)
sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone)
<< sb->sv_inodes_per_block_bits;
- sb->s_blocksize = bsize;
- sb->s_blocksize_bits = n_bits;
if (!silent)
printk("VFS: Found a %s FS (block size = %ld) on device %s\n",
- found, sb->s_blocksize, bdevname(sb->s_dev));
+ found, sb->s_blocksize, sb->s_id);
sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type;
/* set up enough so that it can read an inode */
sb->s_op = &sysv_sops;
root_inode = iget(sb,SYSV_ROOT_INO);
- if (!root_inode) {
+ if (!root_inode || is_bad_inode(root_inode)) {
printk("SysV FS: get root inode failed\n");
return 0;
}
@@ -347,7 +345,6 @@ static struct super_block *sysv_read_super(struct super_block *sb,
{
struct buffer_head *bh1;
struct buffer_head *bh = NULL;
- kdev_t dev = sb->s_dev;
unsigned long blocknr;
int size = 0;
int i;
@@ -361,8 +358,7 @@ static struct super_block *sysv_read_super(struct super_block *sb,
panic("Coherent FS: bad super-block size");
if (64 != sizeof (struct sysv_inode))
panic("sysv fs: bad i-node size");
- set_blocksize(dev,BLOCK_SIZE);
- sb->s_blocksize = BLOCK_SIZE;
+ sb_set_blocksize(sb, BLOCK_SIZE);
sb->sv_block_base = 0;
for (i = 0; i < sizeof(flavours)/sizeof(flavours[0]) && !size; i++) {
@@ -380,8 +376,7 @@ static struct super_block *sysv_read_super(struct super_block *sb,
case 1:
blocknr = bh->b_blocknr << 1;
brelse(bh);
- set_blocksize(dev, 512);
- sb->s_blocksize = 512;
+ sb_set_blocksize(sb, 512);
bh1 = sb_bread(sb, blocknr);
bh = sb_bread(sb, blocknr + 1);
break;
@@ -391,8 +386,7 @@ static struct super_block *sysv_read_super(struct super_block *sb,
case 3:
blocknr = bh->b_blocknr >> 1;
brelse(bh);
- set_blocksize(dev, 2048);
- sb->s_blocksize = 2048;
+ sb_set_blocksize(sb, 2048);
bh1 = bh = sb_bread(sb, blocknr);
break;
default:
@@ -408,7 +402,7 @@ static struct super_block *sysv_read_super(struct super_block *sb,
brelse(bh1);
brelse(bh);
- set_blocksize(sb->s_dev,BLOCK_SIZE);
+ sb_set_blocksize(sb, BLOCK_SIZE);
printk("oldfs: cannot read superblock\n");
failed:
return NULL;
@@ -417,7 +411,7 @@ Eunknown:
brelse(bh);
if (!silent)
printk("VFS: unable to find oldfs superblock on device %s\n",
- bdevname(dev));
+ sb->s_id);
goto failed;
Ebadsize:
brelse(bh);
@@ -431,7 +425,6 @@ static struct super_block *v7_read_super(struct super_block *sb,void *data,
int silent)
{
struct buffer_head *bh, *bh2 = NULL;
- kdev_t dev = sb->s_dev;
struct v7_super_block *v7sb;
struct sysv_inode *v7i;
@@ -443,13 +436,12 @@ static struct super_block *v7_read_super(struct super_block *sb,void *data,
sb->sv_type = FSTYPE_V7;
sb->sv_bytesex = BYTESEX_PDP;
- set_blocksize(dev, 512);
- sb->s_blocksize = 512;
+ sb_set_blocksize(sb, 512);
if ((bh = sb_bread(sb, 1)) == NULL) {
if (!silent)
printk("VFS: unable to read V7 FS superblock on "
- "device %s.\n", bdevname(dev));
+ "device %s.\n", sb->s_id);
goto failed;
}
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 7b95bf925..edd94ec5b 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -215,7 +215,6 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
page_cache_release(page);
mark_inode_dirty(inode);
- inode->i_version ++;
}
struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
@@ -310,7 +309,6 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
mark_buffer_dirty(sbh);
udf_release_data(sbh);
mark_inode_dirty(inode);
- inode->i_version ++;
return dbh;
}
@@ -324,11 +322,7 @@ static int udf_get_block(struct inode *inode, sector_t block, struct buffer_head
{
phys = udf_block_map(inode, block);
if (phys)
- {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- }
+ map_bh(bh_result, inode->i_sb, phys);
return 0;
}
@@ -357,11 +351,9 @@ static int udf_get_block(struct inode *inode, sector_t block, struct buffer_head
if (!phys)
BUG();
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
if (new)
bh_result->b_state |= (1UL << BH_New);
+ map_bh(bh_result, inode->i_sb, phys);
abort:
unlock_kernel();
return err;
@@ -1039,7 +1031,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
long convtime_usec;
int offset, alen;
- inode->i_version = ++event;
UDF_I_NEW_INODE(inode) = 0;
fe = (struct FileEntry *)bh->b_data;
@@ -1540,7 +1531,7 @@ udf_update_inode(struct inode *inode, int do_sync)
if (buffer_req(bh) && !buffer_uptodate(bh))
{
printk("IO error syncing udf inode [%s:%08lx]\n",
- bdevname(inode->i_dev), inode->i_ino);
+ inode->i_sb->s_id, inode->i_ino);
err = -EIO;
}
}
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index b36093c81..630437f11 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -595,7 +595,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
dir->i_size += nfidlen;
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
UDF_I_LENALLOC(dir) += nfidlen;
- dir->i_version = ++event;
mark_inode_dirty(dir);
return fi;
}
@@ -654,7 +653,6 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode)
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
{
mark_inode_dirty(dir);
- dir->i_version = ++event;
}
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
@@ -692,7 +690,6 @@ static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, int r
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
{
mark_inode_dirty(dir);
- dir->i_version = ++event;
}
mark_inode_dirty(inode);
@@ -756,7 +753,6 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
cfi.fileCharacteristics |= FILE_DIRECTORY;
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
- dir->i_version = ++event;
dir->i_nlink++;
mark_inode_dirty(dir);
d_instantiate(dentry, inode);
@@ -851,14 +847,12 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
if (!empty_dir(inode))
goto end_rmdir;
retval = udf_delete_entry(dir, fi, &fibh, &cfi);
- dir->i_version = ++event;
if (retval)
goto end_rmdir;
if (inode->i_nlink != 2)
udf_warning(inode->i_sb, "udf_rmdir",
"empty directory has nlink != 2 (%d)",
inode->i_nlink);
- inode->i_version = ++event;
inode->i_nlink = 0;
inode->i_size = 0;
mark_inode_dirty(inode);
@@ -1070,7 +1064,6 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
{
mark_inode_dirty(dir);
- dir->i_version = ++event;
}
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
@@ -1123,7 +1116,6 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
{
mark_inode_dirty(dir);
- dir->i_version = ++event;
}
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
@@ -1205,7 +1197,6 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
if (!nfi)
goto end_rename;
}
- new_dir->i_version = ++event;
/*
* Like most other Unix systems, set the ctime for inodes on a
@@ -1227,7 +1218,6 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi);
udf_delete_entry(old_dir, ofi, &ofibh, &ocfi);
- old_dir->i_version = ++event;
if (new_inode)
{
new_inode->i_nlink--;
@@ -1247,7 +1237,6 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
if (UDF_I_ALLOCTYPE(old_inode) == ICB_FLAG_AD_IN_ICB)
{
mark_inode_dirty(old_inode);
- old_inode->i_version = ++event;
}
else
mark_buffer_dirty_inode(dir_bh, old_inode);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 7afbe3af2..7a06f1d27 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -357,30 +357,11 @@ udf_remount_fs(struct super_block *sb, int *flags, char *options)
static int
udf_set_blocksize(struct super_block *sb, int bsize)
{
- /* Use specified block size if specified */
- if (bsize)
- sb->s_blocksize = bsize;
- if (get_hardsect_size(sb->s_dev) > sb->s_blocksize)
- sb->s_blocksize = get_hardsect_size(sb->s_dev);
-
- /* Block size must be an even multiple of 512 */
- switch (sb->s_blocksize)
- {
- case 512: sb->s_blocksize_bits = 9; break;
- case 1024: sb->s_blocksize_bits = 10; break;
- case 2048: sb->s_blocksize_bits = 11; break;
- case 4096: sb->s_blocksize_bits = 12; break;
- case 8192: sb->s_blocksize_bits = 13; break;
- default:
- {
- udf_debug("Bad block size (%ld)\n", sb->s_blocksize);
- printk(KERN_ERR "udf: bad block size (%ld)\n", sb->s_blocksize);
- return 0;
- }
+ if (!sb_min_blocksize(sb, bsize)) {
+ udf_debug("Bad block size (%d)\n", bsize);
+ printk(KERN_ERR "udf: bad block size (%d)\n", bsize);
+ return 0;
}
-
- /* Set the block size */
- set_blocksize(sb->s_dev, sb->s_blocksize);
return sb->s_blocksize;
}
@@ -1568,7 +1549,7 @@ void udf_error(struct super_block *sb, const char *function,
vsprintf(error_buf, fmt, args);
va_end(args);
printk (KERN_CRIT "UDF-fs error (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
void udf_warning(struct super_block *sb, const char *function,
@@ -1580,7 +1561,7 @@ void udf_warning(struct super_block *sb, const char *function,
vsprintf(error_buf, fmt, args);
va_end(args);
printk(KERN_WARNING "UDF-fs warning (device %s): %s: %s\n",
- bdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
/*
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 5c3bc8f23..d2d009aee 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -310,22 +310,16 @@ out:
static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
{
- struct super_block * sb;
- struct ufs_sb_private_info * uspi;
+ struct super_block * sb = inode->i_sb;
+ struct ufs_sb_private_info * uspi = sb->u.ufs_sb.s_uspi;
struct buffer_head * bh;
int ret, err, new;
unsigned long ptr, phys;
- sb = inode->i_sb;
- uspi = sb->u.ufs_sb.s_uspi;
-
if (!create) {
phys = ufs_frag_map(inode, fragment);
- if (phys) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- }
+ if (phys)
+ map_bh(bh_result, sb, phys);
return 0;
}
@@ -392,11 +386,9 @@ get_indirect:
out:
if (err)
goto abort;
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
if (new)
bh_result->b_state |= (1UL << BH_New);
+ map_bh(bh_result, sb, phys);
abort:
unlock_kernel();
return err;
@@ -494,13 +486,13 @@ void ufs_read_inode (struct inode * inode)
if (inode->i_ino < UFS_ROOTINO ||
inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
- return;
+ goto bad_inode;
}
bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
if (!bh) {
ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
- return;
+ goto bad_inode;
}
ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino));
@@ -565,6 +557,11 @@ void ufs_read_inode (struct inode * inode)
brelse (bh);
UFSD(("EXIT\n"))
+ return;
+
+bad_inode:
+ make_bad_inode(inode);
+ return;
}
static int ufs_update_inode(struct inode * inode, int do_sync)
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 9421f5960..8d1260c60 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -203,13 +203,13 @@ void ufs_error (struct super_block * sb, const char * function,
switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_ONERROR) {
case UFS_MOUNT_ONERROR_PANIC:
panic ("UFS-fs panic (device %s): %s: %s\n",
- kdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
case UFS_MOUNT_ONERROR_LOCK:
case UFS_MOUNT_ONERROR_UMOUNT:
case UFS_MOUNT_ONERROR_REPAIR:
printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n",
- kdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
}
@@ -233,7 +233,7 @@ void ufs_panic (struct super_block * sb, const char * function,
va_end (args);
sb->s_flags |= MS_RDONLY;
printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n",
- kdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
void ufs_warning (struct super_block * sb, const char * function,
@@ -245,7 +245,7 @@ void ufs_warning (struct super_block * sb, const char * function,
vsprintf (error_buf, fmt, args);
va_end (args);
printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n",
- kdevname(sb->s_dev), function, error_buf);
+ sb->s_id, function, error_buf);
}
static int ufs_parse_options (char * options, unsigned * mount_options)
@@ -442,6 +442,7 @@ struct super_block * ufs_read_super (struct super_block * sb, void * data,
struct ufs_super_block_second * usb2;
struct ufs_super_block_third * usb3;
struct ufs_buffer_head * ubh;
+ struct inode *inode;
unsigned block_size, super_block_size;
unsigned flags;
@@ -596,8 +597,7 @@ struct super_block * ufs_read_super (struct super_block * sb, void * data,
}
again:
- set_blocksize (sb->s_dev, block_size);
- sb->s_blocksize = block_size;
+ sb_set_blocksize(sb, block_size);
/*
* read ufs super block from device
@@ -716,8 +716,6 @@ magic_found:
/*
* Read ufs_super_block into internal data structures
*/
- sb->s_blocksize = fs32_to_cpu(sb, usb1->fs_fsize);
- sb->s_blocksize_bits = fs32_to_cpu(sb, usb1->fs_fshift);
sb->s_op = &ufs_super_ops;
sb->dq_op = NULL; /***/
sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic);
@@ -790,7 +788,13 @@ magic_found:
fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_maxsymlinklen);
sb->u.ufs_sb.s_flags = flags;
- sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO));
+
+ inode = iget(sb, UFS_ROOTINO);
+ if (!inode || is_bad_inode(inode))
+ goto failed;
+ sb->s_root = d_alloc_root(inode);
+ if (!sb->s_root)
+ goto dalloc_failed;
/*
@@ -803,6 +807,8 @@ magic_found:
UFSD(("EXIT\n"))
return(sb);
+dalloc_failed:
+ iput(inode);
failed:
if (ubh) ubh_brelse_uspi (uspi);
if (uspi) kfree (uspi);
diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c
index 98009bff8..cbe1b4ee4 100644
--- a/fs/umsdos/inode.c
+++ b/fs/umsdos/inode.c
@@ -49,7 +49,7 @@ void UMSDOS_put_inode (struct inode *inode)
void UMSDOS_put_super (struct super_block *sb)
{
Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n"));
- if (saved_root && pseudo_root && sb->s_dev == ROOT_DEV) {
+ if (saved_root && pseudo_root && kdev_same(sb->s_dev, ROOT_DEV)) {
shrink_dcache_parent(saved_root);
dput(saved_root);
saved_root = NULL;
@@ -414,7 +414,7 @@ static struct dentry *check_pseudo_root(struct super_block *sb)
* must check like this, because we can be used with initrd
*/
- if (sb->s_dev != ROOT_DEV)
+ if (!kdev_same(sb->s_dev, ROOT_DEV))
goto out_noroot;
/*
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index a0019bd37..30afba540 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -1040,8 +1040,8 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
return res;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
- inode->i_version = ++event;
- dir->i_version = event;
+ inode->i_version++;
+ dir->i_version++;
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry,inode);
return 0;
@@ -1057,7 +1057,7 @@ static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
/* remove the shortname */
dir->i_mtime = CURRENT_TIME;
dir->i_atime = CURRENT_TIME;
- dir->i_version = ++event;
+ dir->i_version++;
mark_inode_dirty(dir);
de->name[0] = DELETED_FLAG;
fat_mark_buffer_dirty(sb, bh);
@@ -1138,8 +1138,8 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
goto out;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
- inode->i_version = ++event;
- dir->i_version = event;
+ inode->i_version++;
+ dir->i_version++;
dir->i_nlink++;
inode->i_nlink = 2; /* no need to mark them dirty */
res = fat_new_dir(inode, dir, 1);
@@ -1209,7 +1209,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
if (res < 0) goto rename_done;
}
- new_dir->i_version = ++event;
+ new_dir->i_version++;
/* releases old_bh */
vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
@@ -1218,7 +1218,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
fat_attach(old_inode, sinfo.ino);
mark_inode_dirty(old_inode);
- old_dir->i_version = ++event;
+ old_dir->i_version++;
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(old_dir);
if (new_inode) {
diff --git a/include/asm-arm/arch-adifcc/adi_evb.h b/include/asm-arm/arch-adifcc/adi_evb.h
new file mode 100644
index 000000000..f4b74c6fc
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/adi_evb.h
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm/arch-80200fcc/adi_evb.h
+ *
+ * ADI 80200FCC evaluation board definitions
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#define ADI_EVB__RAMBASE 0xa0000000
+#define ADI_EVB__UART 0x00400000 /* UART */
+#define ADI_EVB_7SEG_1 0x00500000 /* 7-Segment */
+
diff --git a/include/asm-arm/arch-adifcc/dma.h b/include/asm-arm/arch-adifcc/dma.h
new file mode 100644
index 000000000..19aa1dbc3
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/dma.h
@@ -0,0 +1,18 @@
+/*
+ * linux/include/asm-arm/arch-80200fcc/dma.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS 0xffffffff
+
+/* No DMA */
+#define MAX_DMA_CHANNELS 0
+
+#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-adifcc/hardware.h b/include/asm-arm/arch-adifcc/hardware.h
new file mode 100644
index 000000000..9eeb3cb50
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/hardware.h
@@ -0,0 +1,27 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/hardware.h
+ *
+ * Hardware definitions for ADI based systems
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (C) 2000-2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+
+#define PCIO_BASE 0
+
+#if defined(CONFIG_ARCH_ADI_EVB)
+#include "adi_evb.h"
+#endif
+
+#endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-adifcc/io.h b/include/asm-arm/arch-adifcc/io.h
new file mode 100644
index 000000000..bdcaec08b
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/io.h
@@ -0,0 +1,22 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/io.h
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) (PCIO_BASE + (a))
+#define __mem_pci(a) ((unsigned long)(a))
+#define __mem_isa(a) ((unsigned long)(a))
+
+#endif
diff --git a/include/asm-arm/arch-adifcc/irq.h b/include/asm-arm/arch-adifcc/irq.h
new file mode 100644
index 000000000..9477252c7
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/irq.h
@@ -0,0 +1,13 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/irq.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define fixup_irq(irq) (irq)
+
+
diff --git a/include/asm-arm/arch-adifcc/irqs.h b/include/asm-arm/arch-adifcc/irqs.h
new file mode 100644
index 000000000..fc3907537
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/irqs.h
@@ -0,0 +1,28 @@
+/*
+ * linux/include/asm-arm/arch-80200fcc/irqs.h
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ * Copyright: (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define IRQ_XS80200_BCU 0 /* Bus Control Unit */
+#define IRQ_XS80200_PMU 1 /* Performance Monitoring Unit */
+#define IRQ_XS80200_EXTIRQ 2 /* external IRQ signal */
+#define IRQ_XS80200_EXTFIQ 3 /* external IRQ signal */
+
+#define NR_XS80200_IRQS 4
+#define NR_IRQS NR_XS80200_IRQS
+
+#define IRQ_XSCALE_PMU IRQ_XS80200_PMU
+
+#ifdef CONFIG_XSCALE_ADI_EVB
+
+/* Interrupts available on the ADI Eval Board */
+
+#endif
+
+
diff --git a/include/asm-arm/arch-adifcc/memory.h b/include/asm-arm/arch-adifcc/memory.h
new file mode 100644
index 000000000..bb0307809
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/memory.h
@@ -0,0 +1,57 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/memory.h
+ *
+ * Copyright (c) 2001 MontaVista Software, Inc.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+#define TASK_SIZE_26 (0x04000000UL)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET (0xC0000000UL)
+
+/*
+ * physical vs virtual ram conversion
+ */
+#define __virt_to_phys__is_a_macro
+#define __phys_to_virt__is_a_macro
+#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ * address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ * to an address that the kernel can use.
+ *
+ * These are dummies for now.
+ */
+#define __virt_to_bus__is_a_macro
+#define __bus_to_virt__is_a_macro
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#define PHYS_TO_NID(x) 0
+
+#endif
diff --git a/include/asm-arm/arch-adifcc/param.h b/include/asm-arm/arch-adifcc/param.h
new file mode 100644
index 000000000..e825e31e0
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/param.h
@@ -0,0 +1,3 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/param.h
+ */
diff --git a/include/asm-arm/arch-adifcc/serial.h b/include/asm-arm/arch-adifcc/serial.h
new file mode 100644
index 000000000..e7555e6ab
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/serial.h
@@ -0,0 +1,36 @@
+/*
+ * include/asm-arm/arch-adifcc/serial.h
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (c) 2001 MontaVista Software, Inc.
+ */
+
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1852000 / 16 )
+
+/* Standard COM flags */
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+#ifdef CONFIG_ARCH_ADI_EVB
+
+#define RS_TABLE_SIZE 1
+
+/*
+ * One serial port, int goes to FIQ, so we run in polled mode
+ */
+#define STD_SERIAL_PORT_DEFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, BASE_BAUD, 0xff400000, 0, STD_COM_FLAGS } /* ttyS0 */
+
+#define EXTRA_SERIAL_PORT_DEFNS
+
+#endif
+
diff --git a/include/asm-arm/arch-adifcc/system.h b/include/asm-arm/arch-adifcc/system.h
new file mode 100644
index 000000000..a60025453
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/system.h
@@ -0,0 +1,29 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/system.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+static inline void arch_idle(void)
+{
+#if 0
+ if (!hlt_counter)
+ cpu_do_idle(0);
+#endif
+}
+
+
+static inline void arch_reset(char mode)
+{
+ if ( 1 && mode == 's') {
+ /* Jump into ROM at address 0 */
+ cpu_reset(0);
+ } else {
+ /* Use on-chip reset capability */
+ }
+}
+
diff --git a/include/asm-arm/arch-adifcc/time.h b/include/asm-arm/arch-adifcc/time.h
new file mode 100644
index 000000000..75e1c7eb7
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/time.h
@@ -0,0 +1,9 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/time.h
+ *
+ */
+
+/*
+ * No on board timer, implemenation @ arch/arm/kernel/xscale-time.c
+ */
+
diff --git a/include/asm-arm/arch-adifcc/timex.h b/include/asm-arm/arch-adifcc/timex.h
new file mode 100644
index 000000000..d994c8abe
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/timex.h
@@ -0,0 +1,10 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/timex.h
+ *
+ * XScale architecture timex specifications
+ */
+
+/* This is for a timer based on the XS80200's PMU counter */
+
+#define CLOCK_TICK_RATE 600000000 /* Underlying HZ */
+
diff --git a/include/asm-arm/arch-adifcc/uncompress.h b/include/asm-arm/arch-adifcc/uncompress.h
new file mode 100644
index 000000000..792b4e17a
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/uncompress.h
@@ -0,0 +1,35 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/uncompress.h
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (c) 2001 MontaVista Software, Inc.
+ *
+ */
+
+#define UART_BASE ((volatile unsigned char *)0x00400000)
+
+static __inline__ void putc(char c)
+{
+ while ((UART_BASE[5] & 0x60) != 0x60);
+ UART_BASE[0] = c;
+}
+
+/*
+ * This does not append a newline
+ */
+static void puts(const char *s)
+{
+ while (*s) {
+ putc(*s);
+ if (*s == '\n')
+ putc('\r');
+ s++;
+ }
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-adifcc/vmalloc.h b/include/asm-arm/arch-adifcc/vmalloc.h
new file mode 100644
index 000000000..0bcc35c82
--- /dev/null
+++ b/include/asm-arm/arch-adifcc/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-arm/arch-adifcc/vmalloc.h
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts. That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET (8*1024*1024)
+#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END (0xe8000000)
diff --git a/include/asm-arm/arch-anakin/io.h b/include/asm-arm/arch-anakin/io.h
index f535f6cba..5b0f4d8e5 100644
--- a/include/asm-arm/arch-anakin/io.h
+++ b/include/asm-arm/arch-anakin/io.h
@@ -17,12 +17,7 @@
#define IO_SPACE_LIMIT 0xffffffff
-#define __io(a) a
-#define __arch_getw(a) (*(volatile unsigned short *) (a))
-#define __arch_putw(b, a) (*(volatile unsigned short *) (a) = (b))
-
-#define iomem_valid_addr(i, s) 1
-#define iomem_to_phys(i) i
+#define __io(a) (a)
/*
* We don't support ins[lb]/outs[lb]. Make them fault.
diff --git a/include/asm-arm/arch-anakin/time.h b/include/asm-arm/arch-anakin/time.h
index 97717b586..88d1c6efe 100644
--- a/include/asm-arm/arch-anakin/time.h
+++ b/include/asm-arm/arch-anakin/time.h
@@ -20,8 +20,7 @@ anakin_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_timer(regs);
}
-static inline void
-setup_timer(void)
+void __init time_init(void)
{
timer_irq.handler = anakin_timer_interrupt;
timer_irq.flags = SA_INTERRUPT;
diff --git a/include/asm-arm/arch-arc/io.h b/include/asm-arm/arch-arc/io.h
index e874501c8..11c9ce687 100644
--- a/include/asm-arm/arch-arc/io.h
+++ b/include/asm-arm/arch-arc/io.h
@@ -249,4 +249,10 @@ DECLARE_IO(int,l,"")
/* the following macro is depreciated */
#define ioaddr(port) __ioaddr((port))
+/*
+ * No ioremap support here.
+ */
+#define __arch_ioremap(c,s,f) ((void *)(c))
+#define __arch_iounmap(c) do { } while (0)
+
#endif
diff --git a/include/asm-arm/arch-arc/irq.h b/include/asm-arm/arch-arc/irq.h
index 40424ea5b..4951c6995 100644
--- a/include/asm-arm/arch-arc/irq.h
+++ b/include/asm-arm/arch-arc/irq.h
@@ -6,143 +6,5 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * Changelog:
- * 24-09-1996 RMK Created
- * 10-10-1996 RMK Brought up to date with arch-sa110eval
- * 22-10-1996 RMK Changed interrupt numbers & uses new inb/outb macros
- * 11-01-1998 RMK Added mask_and_ack_irq
- * 22-08-1998 RMK Restructured IRQ routines
*/
-#include <linux/config.h>
-#include <asm/hardware/ioc.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_ARCH_ARC
-#define a_clf() clf()
-#define a_stf() stf()
-#else
-#define a_clf() do { } while (0)
-#define a_stf() do { } while (0)
-#endif
-
#define fixup_irq(x) (x)
-
-static void arc_mask_irq_ack_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- a_clf();
- val = ioc_readb(IOC_IRQMASKA);
- ioc_writeb(val & ~mask, IOC_IRQMASKA);
- ioc_writeb(mask, IOC_IRQCLRA);
- a_stf();
-}
-
-static void arc_mask_irq_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- a_clf();
- val = ioc_readb(IOC_IRQMASKA);
- ioc_writeb(val & ~mask, IOC_IRQMASKA);
- a_stf();
-}
-
-static void arc_unmask_irq_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- a_clf();
- val = ioc_readb(IOC_IRQMASKA);
- ioc_writeb(val | mask, IOC_IRQMASKA);
- a_stf();
-}
-
-static void arc_mask_irq_b(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = ioc_readb(IOC_IRQMASKB);
- ioc_writeb(val & ~mask, IOC_IRQMASKB);
-}
-
-static void arc_unmask_irq_b(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = ioc_readb(IOC_IRQMASKB);
- ioc_writeb(val | mask, IOC_IRQMASKB);
-}
-
-static void arc_mask_irq_fiq(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = ioc_readb(IOC_FIQMASK);
- ioc_writeb(val & ~mask, IOC_FIQMASK);
-}
-
-static void arc_unmask_irq_fiq(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = ioc_readb(IOC_FIQMASK);
- ioc_writeb(val | mask, IOC_FIQMASK);
-}
-
-static __inline__ void irq_init_irq(void)
-{
- int irq;
-
- ioc_writeb(0, IOC_IRQMASKA);
- ioc_writeb(0, IOC_IRQMASKB);
- ioc_writeb(0, IOC_FIQMASK);
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- switch (irq) {
- case 0 ... 6:
- irq_desc[irq].probe_ok = 1;
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
- irq_desc[irq].mask = arc_mask_irq_a;
- irq_desc[irq].unmask = arc_unmask_irq_a;
- break;
-
- case 7:
- irq_desc[irq].noautoenable = 1;
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
- irq_desc[irq].mask = arc_mask_irq_a;
- irq_desc[irq].unmask = arc_unmask_irq_a;
- break;
-
- case 9 ... 15:
- irq_desc[irq].probe_ok = 1;
- case 8:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = arc_mask_irq_b;
- irq_desc[irq].mask = arc_mask_irq_b;
- irq_desc[irq].unmask = arc_unmask_irq_b;
- break;
-
- case 64 ... 72:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = arc_mask_irq_fiq;
- irq_desc[irq].mask = arc_mask_irq_fiq;
- irq_desc[irq].unmask = arc_unmask_irq_fiq;
- break;
- }
- }
-
- irq_desc[IRQ_KEYBOARDTX].noautoenable = 1;
-
- init_FIQ();
-}
diff --git a/include/asm-arm/arch-arc/time.h b/include/asm-arm/arch-arc/time.h
index ef13a0466..394bb5388 100644
--- a/include/asm-arm/arch-arc/time.h
+++ b/include/asm-arm/arch-arc/time.h
@@ -24,7 +24,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* Set up timer interrupt.
*/
-static inline void setup_timer(void)
+void __init time_init(void)
{
ioctime_init();
diff --git a/include/asm-arm/arch-cl7500/irq.h b/include/asm-arm/arch-cl7500/irq.h
index 393efaddb..4b286331f 100644
--- a/include/asm-arm/arch-cl7500/irq.h
+++ b/include/asm-arm/arch-cl7500/irq.h
@@ -30,198 +30,3 @@ static inline int fixup_irq(unsigned int irq)
return irq;
}
-
-static void cl7500_mask_irq_ack_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- val = iomd_readb(IOMD_IRQMASKA);
- iomd_writeb(val & ~mask, IOMD_IRQMASKA);
- iomd_writeb(mask, IOMD_IRQCLRA);
-}
-
-static void cl7500_mask_irq_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- val = iomd_readb(IOMD_IRQMASKA);
- iomd_writeb(val & ~mask, IOMD_IRQMASKA);
-}
-
-static void cl7500_unmask_irq_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- val = iomd_readb(IOMD_IRQMASKA);
- iomd_writeb(val | mask, IOMD_IRQMASKA);
-}
-
-static void cl7500_mask_irq_b(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_IRQMASKB);
- iomd_writeb(val & ~mask, IOMD_IRQMASKB);
-}
-
-static void cl7500_unmask_irq_b(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_IRQMASKB);
- iomd_writeb(val | mask, IOMD_IRQMASKB);
-}
-
-static void cl7500_mask_irq_c(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_IRQMASKC);
- iomd_writeb(val & ~mask, IOMD_IRQMASKC);
-}
-
-static void cl7500_unmask_irq_c(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_IRQMASKC);
- iomd_writeb(val | mask, IOMD_IRQMASKC);
-}
-
-
-static void cl7500_mask_irq_d(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_IRQMASKD);
- iomd_writeb(val & ~mask, IOMD_IRQMASKD);
-}
-
-static void cl7500_unmask_irq_d(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_IRQMASKD);
- iomd_writeb(val | mask, IOMD_IRQMASKD);
-}
-
-static void cl7500_mask_irq_dma(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_DMAMASK);
- iomd_writeb(val & ~mask, IOMD_DMAMASK);
-}
-
-static void cl7500_unmask_irq_dma(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_DMAMASK);
- iomd_writeb(val | mask, IOMD_DMAMASK);
-}
-
-static void cl7500_mask_irq_fiq(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_FIQMASK);
- iomd_writeb(val & ~mask, IOMD_FIQMASK);
-}
-
-static void cl7500_unmask_irq_fiq(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_FIQMASK);
- iomd_writeb(val | mask, IOMD_FIQMASK);
-}
-
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
-}
-
-static struct irqaction irq_isa = { no_action, 0, 0, "isa", NULL, NULL };
-
-static __inline__ void irq_init_irq(void)
-{
- int irq;
-
- iomd_writeb(0, IOMD_IRQMASKA);
- iomd_writeb(0, IOMD_IRQMASKB);
- iomd_writeb(0, IOMD_FIQMASK);
- iomd_writeb(0, IOMD_DMAMASK);
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- switch (irq) {
- case 0 ... 6:
- irq_desc[irq].probe_ok = 1;
- case 7:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = cl7500_mask_irq_ack_a;
- irq_desc[irq].mask = cl7500_mask_irq_a;
- irq_desc[irq].unmask = cl7500_unmask_irq_a;
- break;
-
- case 9 ... 15:
- irq_desc[irq].probe_ok = 1;
- case 8:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = cl7500_mask_irq_b;
- irq_desc[irq].mask = cl7500_mask_irq_b;
- irq_desc[irq].unmask = cl7500_unmask_irq_b;
- break;
-
- case 16 ... 22:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = cl7500_mask_irq_dma;
- irq_desc[irq].mask = cl7500_mask_irq_dma;
- irq_desc[irq].unmask = cl7500_unmask_irq_dma;
- break;
-
- case 24 ... 31:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = cl7500_mask_irq_c;
- irq_desc[irq].mask = cl7500_mask_irq_c;
- irq_desc[irq].unmask = cl7500_unmask_irq_c;
- break;
-
- case 40 ... 47:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = cl7500_mask_irq_d;
- irq_desc[irq].mask = cl7500_mask_irq_d;
- irq_desc[irq].unmask = cl7500_unmask_irq_d;
- break;
-
- case 48 ... 55:
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
- irq_desc[irq].mask_ack = no_action;
- irq_desc[irq].mask = no_action;
- irq_desc[irq].unmask = no_action;
- break;
-
- case 64 ... 72:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = cl7500_mask_irq_fiq;
- irq_desc[irq].mask = cl7500_mask_irq_fiq;
- irq_desc[irq].unmask = cl7500_unmask_irq_fiq;
- break;
- }
- }
-
- setup_arm_irq(IRQ_ISA, &irq_isa);
-}
diff --git a/include/asm-arm/arch-cl7500/keyboard.h b/include/asm-arm/arch-cl7500/keyboard.h
index 55815c4cb..660b31a0e 100644
--- a/include/asm-arm/arch-cl7500/keyboard.h
+++ b/include/asm-arm/arch-cl7500/keyboard.h
@@ -6,6 +6,7 @@
*
* Copyright (C) 1998-2001 Russell King
*/
+#include <asm/irq.h>
#define NR_SCANCODES 128
extern int ps2kbd_init_hw(void);
diff --git a/include/asm-arm/arch-cl7500/time.h b/include/asm-arm/arch-cl7500/time.h
index 107763e9c..a63ea1e75 100644
--- a/include/asm-arm/arch-cl7500/time.h
+++ b/include/asm-arm/arch-cl7500/time.h
@@ -9,6 +9,8 @@
* 04-Dec-1997 RMK Updated for new arch/arm/time.c
*/
+extern void ioctime_init(void);
+
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
do_timer(regs);
@@ -29,9 +31,8 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* Set up timer interrupt.
*/
-static inline void setup_timer(void)
+void __init time_init(void)
{
- extern void ioctime_init(void);
ioctime_init();
timer_irq.handler = timer_interrupt;
diff --git a/include/asm-arm/arch-clps711x/autcpu12.h b/include/asm-arm/arch-clps711x/autcpu12.h
new file mode 100644
index 000000000..1588a365f
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/autcpu12.h
@@ -0,0 +1,78 @@
+/*
+ * AUTCPU12 specific defines
+ *
+ * (c) 2001 Thomas Gleixner, autronix automation <gleixner@autronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_AUTCPU12_H
+#define __ASM_ARCH_AUTCPU12_H
+
+/*
+ * The CS8900A ethernet chip has its I/O registers wired to chip select 2
+ * (nCS2). This is the mapping for it.
+ */
+#define AUTCPU12_PHYS_CS8900A CS2_PHYS_BASE /* physical */
+#define AUTCPU12_VIRT_CS8900A (0xfe000000) /* virtual */
+
+/*
+ * The flash bank is wired to chip select 0
+ */
+#define AUTCPU12_PHYS_FLASH CS0_PHYS_BASE /* physical */
+
+/* offset for device specific information structure */
+#define AUTCPU12_LCDINFO_OFFS (0x00010000)
+/*
+* Videomemory is the internal SRAM (CS 6)
+*/
+#define AUTCPU12_PHYS_VIDEO CS6_PHYS_BASE
+#define AUTCPU12_VIRT_VIDEO (0xfd000000)
+
+/*
+* All special IO's are tied to CS1
+*/
+#define AUTCPU12_PHYS_CHAR_LCD CS1_PHYS_BASE +0x00000000 /* physical */
+
+#define AUTCPU12_PHYS_NVRAM CS1_PHYS_BASE +0x02000000 /* physical */
+
+#define AUTCPU12_PHYS_CSAUX1 CS1_PHYS_BASE +0x04000000 /* physical */
+
+#define AUTCPU12_PHYS_SMC CS1_PHYS_BASE +0x06000000 /* physical */
+
+#define AUTCPU12_PHYS_CAN CS1_PHYS_BASE +0x08000000 /* physical */
+
+#define AUTCPU12_PHYS_TOUCH CS1_PHYS_BASE +0x0A000000 /* physical */
+
+#define AUTCPU12_PHYS_IO CS1_PHYS_BASE +0x0C000000 /* physical */
+
+#define AUTCPU12_PHYS_LPT CS1_PHYS_BASE +0x0E000000 /* physical */
+
+/*
+* defines for smartmedia card access
+*/
+#define AUTCPU12_SMC_RDY (1<<2)
+#define AUTCPU12_SMC_ALE (1<<3)
+#define AUTCPU12_SMC_CLE (1<<4)
+#define AUTCPU12_SMC_PORT_OFFSET PBDR
+#define AUTCPU12_SMC_SELECT_OFFSET 0x10
+/*
+* defines for lcd contrast
+*/
+#define AUTCPU12_DPOT_PORT_OFFSET PEDR
+#define AUTCPU12_DPOT_CS (1<<0)
+#define AUTCPU12_DPOT_CLK (1<<1)
+#define AUTCPU12_DPOT_UD (1<<2)
+
+#endif
diff --git a/include/asm-arm/arch-clps711x/dma.h b/include/asm-arm/arch-clps711x/dma.h
new file mode 100644
index 000000000..3c4c5c843
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/dma.h
@@ -0,0 +1,28 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/dma.h
+ *
+ * Copyright (C) 1997,1998 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS 0xffffffff
+
+#define MAX_DMA_CHANNELS 0
+
+#endif /* _ASM_ARCH_DMA_H */
+
diff --git a/include/asm-arm/arch-clps711x/hardware.h b/include/asm-arm/arch-clps711x/hardware.h
new file mode 100644
index 000000000..314043142
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/hardware.h
@@ -0,0 +1,179 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/hardware.h
+ *
+ * This file contains the hardware definitions of the Prospector P720T.
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+
+#define CLPS7111_VIRT_BASE 0xff000000
+#define CLPS7111_BASE CLPS7111_VIRT_BASE
+
+/*
+ * The physical addresses that the external chip select signals map to is
+ * dependent on the setting of the nMEDCHG signal on EP7211 and EP7212
+ * processors. CONFIG_EP72XX_BOOT_ROM is only available if these
+ * processors are in use.
+ */
+#ifndef CONFIG_EP72XX_ROM_BOOT
+#define CS0_PHYS_BASE (0x00000000)
+#define CS1_PHYS_BASE (0x10000000)
+#define CS2_PHYS_BASE (0x20000000)
+#define CS3_PHYS_BASE (0x30000000)
+#define CS4_PHYS_BASE (0x40000000)
+#define CS5_PHYS_BASE (0x50000000)
+#define CS6_PHYS_BASE (0x60000000)
+#define CS7_PHYS_BASE (0x70000000)
+#else
+#define CS0_PHYS_BASE (0x70000000)
+#define CS1_PHYS_BASE (0x60000000)
+#define CS2_PHYS_BASE (0x50000000)
+#define CS3_PHYS_BASE (0x40000000)
+#define CS4_PHYS_BASE (0x30000000)
+#define CS5_PHYS_BASE (0x20000000)
+#define CS6_PHYS_BASE (0x10000000)
+#define CS7_PHYS_BASE (0x00000000)
+#endif
+
+#if defined (CONFIG_ARCH_EP7211)
+
+#define EP7211_VIRT_BASE CLPS7111_VIRT_BASE
+#define EP7211_BASE CLPS7111_VIRT_BASE
+#include <asm/hardware/ep7211.h>
+
+#elif defined (CONFIG_ARCH_EP7212)
+
+#define EP7212_VIRT_BASE CLPS7111_VIRT_BASE
+#define EP7212_BASE CLPS7111_VIRT_BASE
+#include <asm/hardware/ep7212.h>
+
+
+#endif
+
+#define SYSPLD_VIRT_BASE 0xfe000000
+#define SYSPLD_BASE SYSPLD_VIRT_BASE
+
+#ifndef __ASSEMBLER__
+
+#define PCIO_BASE IO_BASE
+
+#endif
+
+
+#if defined (CONFIG_ARCH_AUTCPU12)
+
+#define CS89712_VIRT_BASE CLPS7111_VIRT_BASE
+#define CS89712_BASE CLPS7111_VIRT_BASE
+
+#include <asm/hardware/clps7111.h>
+#include <asm/hardware/ep7212.h>
+#include <asm/hardware/cs89712.h>
+
+#endif
+
+
+#if defined (CONFIG_ARCH_CDB89712)
+
+#include <asm/hardware/clps7111.h>
+#include <asm/hardware/ep7212.h>
+#include <asm/hardware/cs89712.h>
+
+/* dynamic ioremap() areas */
+#define FLASH_START 0x00000000
+#define FLASH_SIZE 0x800000
+#define FLASH_WIDTH 4
+
+#define SRAM_START 0x60000000
+#define SRAM_SIZE 0xc000
+#define SRAM_WIDTH 4
+
+#define BOOTROM_START 0x70000000
+#define BOOTROM_SIZE 0x80
+#define BOOTROM_WIDTH 4
+
+
+/* static cdb89712_map_io() areas */
+#define REGISTER_START 0x80000000
+#define REGISTER_SIZE 0x4000
+#define REGISTER_BASE 0xff000000
+
+#define ETHER_START 0x20000000
+#define ETHER_SIZE 0x1000
+#define ETHER_BASE 0xfe000000
+
+#endif
+
+
+#if defined (CONFIG_ARCH_EDB7211)
+
+/*
+ * The extra 8 lines of the keyboard matrix are wired to chip select 3 (nCS3)
+ * and repeat across it. This is the mapping for it.
+ *
+ * In jumpered boot mode, nCS3 is mapped to 0x4000000, not 0x3000000. This
+ * was cause for much consternation and headscratching. This should probably
+ * be made a compile/run time kernel option.
+ */
+#define EP7211_PHYS_EXTKBD CS3_PHYS_BASE /* physical */
+
+#define EP7211_VIRT_EXTKBD (0xfd000000) /* virtual */
+
+
+/*
+ * The CS8900A ethernet chip has its I/O registers wired to chip select 2
+ * (nCS2). This is the mapping for it.
+ *
+ * In jumpered boot mode, nCS2 is mapped to 0x5000000, not 0x2000000. This
+ * was cause for much consternation and headscratching. This should probably
+ * be made a compile/run time kernel option.
+ */
+#define EP7211_PHYS_CS8900A CS2_PHYS_BASE /* physical */
+
+#define EP7211_VIRT_CS8900A (0xfc000000) /* virtual */
+
+
+/*
+ * The two flash banks are wired to chip selects 0 and 1. This is the mapping
+ * for them.
+ *
+ * nCS0 and nCS1 are at 0x70000000 and 0x60000000, respectively, when running
+ * in jumpered boot mode.
+ */
+#define EP7211_PHYS_FLASH1 CS0_PHYS_BASE /* physical */
+#define EP7211_PHYS_FLASH2 CS1_PHYS_BASE /* physical */
+
+#define EP7211_VIRT_FLASH1 (0xfa000000) /* virtual */
+#define EP7211_VIRT_FLASH2 (0xfb000000) /* virtual */
+
+#endif /* CONFIG_ARCH_EDB7211 */
+
+
+/*
+ * Relevant bits in port D, which controls power to the various parts of
+ * the LCD on the EDB7211.
+ */
+#define EDB_PD1_LCD_DC_DC_EN (1<<1)
+#define EDB_PD2_LCDEN (1<<2)
+#define EDB_PD3_LCDBL (1<<3)
+
+
+#endif
+
diff --git a/include/asm-arm/arch-clps711x/io.h b/include/asm-arm/arch-clps711x/io.h
new file mode 100644
index 000000000..fa205d49f
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/io.h
@@ -0,0 +1,37 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/io.h
+ *
+ * Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) ((a))
+#define __mem_pci(a) ((unsigned long)(a))
+#define __mem_isa(a) ((unsigned long)(a))
+
+/*
+ * We don't support ins[lb]/outs[lb]. Make them fault.
+ */
+#define __raw_readsb(p,d,l) do { *(int *)0 = 0; } while (0)
+#define __raw_readsl(p,d,l) do { *(int *)0 = 0; } while (0)
+#define __raw_writesb(p,d,l) do { *(int *)0 = 0; } while (0)
+#define __raw_writesl(p,d,l) do { *(int *)0 = 0; } while (0)
+
+#endif
diff --git a/include/asm-arm/arch-clps711x/irq.h b/include/asm-arm/arch-clps711x/irq.h
new file mode 100644
index 000000000..7dde5e3f7
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/irq.h
@@ -0,0 +1,20 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/irq.h
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define fixup_irq(i) (i)
diff --git a/include/asm-arm/arch-clps711x/irqs.h b/include/asm-arm/arch-clps711x/irqs.h
new file mode 100644
index 000000000..76025dc87
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/irqs.h
@@ -0,0 +1,53 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/irqs.h
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Interrupts from INTSR1
+ */
+#define IRQ_CSINT 4
+#define IRQ_EINT1 5
+#define IRQ_EINT2 6
+#define IRQ_EINT3 7
+#define IRQ_TC1OI 8
+#define IRQ_TC2OI 9
+#define IRQ_RTCMI 10
+#define IRQ_TINT 11
+#define IRQ_UTXINT1 12
+#define IRQ_URXINT1 13
+#define IRQ_UMSINT 14
+#define IRQ_SSEOTI 15
+
+#define INT1_IRQS (0x0000fff0)
+#define INT1_ACK_IRQS (0x00004f10)
+
+/*
+ * Interrupts from INTSR2
+ */
+#define IRQ_KBDINT (16+0) /* bit 0 */
+#define IRQ_SS2RX (16+1) /* bit 1 */
+#define IRQ_SS2TX (16+2) /* bit 2 */
+#define IRQ_UTXINT2 (16+12) /* bit 12 */
+#define IRQ_URXINT2 (16+13) /* bit 13 */
+
+#define INT2_IRQS (0x30070000)
+#define INT2_ACK_IRQS (0x00010000)
+
+#define NR_IRQS 30
+
diff --git a/include/asm-arm/arch-clps711x/keyboard.h b/include/asm-arm/arch-clps711x/keyboard.h
new file mode 100644
index 000000000..30ab2199f
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/keyboard.h
@@ -0,0 +1,26 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/keyboard.h
+ *
+ * Copyright (C) 1998-2001 Russell King
+ */
+#include <asm/mach-types.h>
+
+#define NR_SCANCODES 128
+
+#define kbd_disable_irq() do { } while (0)
+#define kbd_enable_irq() do { } while (0)
+
+/*
+ * EDB7211 keyboard driver
+ */
+extern void edb7211_kbd_init_hw(void);
+extern void clps711x_kbd_init_hw(void);
+
+static inline void kbd_init_hw(void)
+{
+ if (machine_is_edb7211())
+ edb7211_kbd_init_hw();
+
+ if (machine_is_autcpu12())
+ clps711x_kbd_init_hw();
+}
diff --git a/include/asm-arm/arch-clps711x/memory.h b/include/asm-arm/arch-clps711x/memory.h
new file mode 100644
index 000000000..043ee9a9b
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/memory.h
@@ -0,0 +1,204 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/mmu.h
+ *
+ * Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+#define TASK_SIZE_26 (0x04000000UL)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+#define PHYS_OFFSET (0xc0000000UL)
+
+/*
+ * On integrator, the dram is contiguous
+ */
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ * address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ * to an address that the kernel can use.
+ */
+
+#if defined(CONFIG_ARCH_CDB89712)
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) (x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) (x)
+
+#elif defined (CONFIG_ARCH_AUTCPU12)
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) (x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) (x)
+
+#else
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
+
+#endif
+
+
+/*
+ * Like the SA1100, the EDB7211 has a large gap between physical RAM
+ * banks. In 2.2, the Psion (CL-PS7110) port added custom support for
+ * discontiguous physical memory. In 2.4, we can use the standard
+ * Linux NUMA support.
+ *
+ * This is not necessary for EP7211 implementations with only one used
+ * memory bank. For those systems, simply undefine CONFIG_DISCONTIGMEM.
+ */
+
+#ifdef CONFIG_ARCH_EDB7211
+
+#ifdef CONFIG_DISCONTIGMEM
+/*
+ * Because of the wide memory address space between physical RAM banks on the
+ * SA1100, it's much more convenient to use Linux's NUMA support to implement
+ * our memory map representation. Assuming all memory nodes have equal access
+ * characteristics, we then have generic discontigous memory support.
+ *
+ * Of course, all this isn't mandatory for SA1100 implementations with only
+ * one used memory bank. For those, simply undefine CONFIG_DISCONTIGMEM.
+ *
+ * The nodes are matched with the physical memory bank addresses which are
+ * incidentally the same as virtual addresses.
+ *
+ * node 0: 0xc0000000 - 0xc7ffffff
+ * node 1: 0xc8000000 - 0xcfffffff
+ * node 2: 0xd0000000 - 0xd7ffffff
+ * node 3: 0xd8000000 - 0xdfffffff
+ */
+
+#define NR_NODES 4
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) \
+ (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
+
+/*
+ * Given a physical address, convert it to a node id.
+ */
+#define PHYS_TO_NID(addr) KVADDR_TO_NID(__phys_to_virt(addr))
+
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and returns the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr) \
+ NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
+
+/*
+ * Given a kaddr, LOCAL_MAR_NR finds the owning node of the memory
+ * and returns the index corresponding to the appropriate page in the
+ * node's mem_map.
+ */
+#define LOCAL_MAP_NR(kaddr) \
+ (((unsigned long)(kaddr)-LOCAL_BASE_ADDR((kaddr))) >> PAGE_SHIFT)
+
+/*
+ * Given a kaddr, virt_to_page returns a pointer to the corresponding
+ * mem_map entry.
+ */
+#define virt_to_page(kaddr) \
+ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+
+/*
+ * VALID_PAGE returns a non-zero value if given page pointer is valid.
+ * This assumes all node's mem_maps are stored within the node they refer to.
+ */
+#define VALID_PAGE(page) \
+({ unsigned int node = KVADDR_TO_NID(page); \
+ ( (node < NR_NODES) && \
+ ((unsigned)((page) - NODE_MEM_MAP(node)) < NODE_DATA(node)->node_size) ); \
+})
+
+/*
+ * The PS7211 allows up to 256MB max per DRAM bank, but the EDB7211
+ * uses only one of the two banks (bank #1). However, even within
+ * bank #1, memory is discontiguous.
+ *
+ * The EDB7211 has two 8MB DRAM areas with 8MB of empty space between
+ * them, so we use 24 for the node max shift to get 16MB node sizes.
+ */
+#define NODE_MAX_MEM_SHIFT 24
+#define NODE_MAX_MEM_SIZE (1<<NODE_MAX_MEM_SHIFT)
+
+/*
+ * Given a mem_map_t, LOCAL_MAP_BASE finds the owning node for the
+ * physical page and returns the kaddr for the mem_map of that node.
+ */
+#define LOCAL_MAP_BASE(page) \
+ NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(page)))
+
+/*
+ * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
+ * and returns the kaddr corresponding to first physical page in the
+ * node's mem_map.
+ */
+#define LOCAL_BASE_ADDR(kaddr) ((unsigned long)(kaddr) & ~(NODE_MAX_MEM_SIZE-1))
+
+/*
+ * With discontigmem, the conceptual mem_map array starts from PAGE_OFFSET.
+ * Given a kaddr, MAP_NR returns the appropriate global mem_map index so
+ * it matches the corresponding node's local mem_map.
+ */
+#define MAP_NR(kaddr) (LOCAL_MAP_NR((kaddr)) + \
+ (((unsigned long)ADDR_TO_MAPBASE((kaddr)) - PAGE_OFFSET) / \
+ sizeof(mem_map_t)))
+
+#else
+
+#define PHYS_TO_NID(addr) (0)
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* CONFIG_ARCH_EDB7211 */
+
+#ifndef PHYS_TO_NID
+#define PHYS_TO_NID(addr) (0)
+#endif
+
+#endif
+
diff --git a/include/asm-arm/arch-clps711x/param.h b/include/asm-arm/arch-clps711x/param.h
new file mode 100644
index 000000000..c46e69ad6
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/param.h
@@ -0,0 +1,21 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/param.h
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define HZ 100
diff --git a/include/asm-arm/arch-clps711x/syspld.h b/include/asm-arm/arch-clps711x/syspld.h
new file mode 100644
index 000000000..960578a22
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/syspld.h
@@ -0,0 +1,121 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/syspld.h
+ *
+ * System Control PLD register definitions.
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_SYSPLD_H
+#define __ASM_ARCH_SYSPLD_H
+
+#define SYSPLD_PHYS_BASE (0x10000000)
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+
+#define SYSPLD_REG(type,off) (*(volatile type *)(SYSPLD_BASE + off))
+#else
+#define SYSPLD_REG(type,off) (off)
+#endif
+
+#define PLD_INT SYSPLD_REG(u32, 0x000000)
+#define PLD_INT_PENIRQ (1 << 5)
+#define PLD_INT_UCB_IRQ (1 << 1)
+#define PLD_INT_KBD_ATN (1 << 0) /* EINT1 */
+
+#define PLD_PWR SYSPLD_REG(u32, 0x000004)
+#define PLD_PWR_EXT (1 << 5)
+#define PLD_PWR_MODE (1 << 4) /* 1 = PWM, 0 = PFM */
+#define PLD_S4_ON (1 << 3) /* LCD bias voltage enable */
+#define PLD_S3_ON (1 << 2) /* LCD backlight enable */
+#define PLD_S2_ON (1 << 1) /* LCD 3V3 supply enable */
+#define PLD_S1_ON (1 << 0) /* LCD 3V supply enable */
+
+#define PLD_KBD SYSPLD_REG(u32, 0x000008)
+#define PLD_KBD_WAKE (1 << 1)
+#define PLD_KBD_EN (1 << 0)
+
+#define PLD_SPI SYSPLD_REG(u32, 0x00000c)
+#define PLD_SPI_EN (1 << 0)
+
+#define PLD_IO SYSPLD_REG(u32, 0x000010)
+#define PLD_IO_BOOTSEL (1 << 6) /* boot sel switch */
+#define PLD_IO_USER (1 << 5) /* user defined switch */
+#define PLD_IO_LED3 (1 << 4)
+#define PLD_IO_LED2 (1 << 3)
+#define PLD_IO_LED1 (1 << 2)
+#define PLD_IO_LED0 (1 << 1)
+#define PLD_IO_LEDEN (1 << 0)
+
+#define PLD_IRDA SYSPLD_REG(u32, 0x000014)
+#define PLD_IRDA_EN (1 << 0)
+
+#define PLD_COM2 SYSPLD_REG(u32, 0x000018)
+#define PLD_COM2_EN (1 << 0)
+
+#define PLD_COM1 SYSPLD_REG(u32, 0x00001c)
+#define PLD_COM1_EN (1 << 0)
+
+#define PLD_AUD SYSPLD_REG(u32, 0x000020)
+#define PLD_AUD_DIV1 (1 << 6)
+#define PLD_AUD_DIV0 (1 << 5)
+#define PLD_AUD_CLK_SEL1 (1 << 4)
+#define PLD_AUD_CLK_SEL0 (1 << 3)
+#define PLD_AUD_MIC_PWR (1 << 2)
+#define PLD_AUD_MIC_GAIN (1 << 1)
+#define PLD_AUD_CODEC_EN (1 << 0)
+
+#define PLD_CF SYSPLD_REG(u32, 0x000024)
+#define PLD_CF2_SLEEP (1 << 5)
+#define PLD_CF1_SLEEP (1 << 4)
+#define PLD_CF2_nPDREQ (1 << 3)
+#define PLD_CF1_nPDREQ (1 << 2)
+#define PLD_CF2_nIRQ (1 << 1)
+#define PLD_CF1_nIRQ (1 << 0)
+
+#define PLD_SDC SYSPLD_REG(u32, 0x000028)
+#define PLD_SDC_INT_EN (1 << 2)
+#define PLD_SDC_WP (1 << 1)
+#define PLD_SDC_CD (1 << 0)
+
+#define PLD_FPGA SYSPLD_REG(u32, 0x00002c)
+
+#define PLD_CODEC SYSPLD_REG(u32, 0x400000)
+#define PLD_CODEC_IRQ3 (1 << 4)
+#define PLD_CODEC_IRQ2 (1 << 3)
+#define PLD_CODEC_IRQ1 (1 << 2)
+#define PLD_CODEC_EN (1 << 0)
+
+#define PLD_BRITE SYSPLD_REG(u32, 0x400004)
+#define PLD_BRITE_UP (1 << 1)
+#define PLD_BRITE_DN (1 << 0)
+
+#define PLD_LCDEN SYSPLD_REG(u32, 0x400008)
+#define PLD_LCDEN_EN (1 << 0)
+
+#define PLD_ID SYSPLD_REG(u32, 0x40000c)
+
+#define PLD_TCH SYSPLD_REG(u32, 0x400010)
+#define PLD_TCH_PENIRQ (1 << 1)
+#define PLD_TCH_EN (1 << 0)
+
+#define PLD_GPIO SYSPLD_REG(u32, 0x400014)
+#define PLD_GPIO2 (1 << 2)
+#define PLD_GPIO1 (1 << 1)
+#define PLD_GPIO0 (1 << 0)
+
+#endif
diff --git a/include/asm-arm/arch-clps711x/system.h b/include/asm-arm/arch-clps711x/system.h
new file mode 100644
index 000000000..6255973eb
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/system.h
@@ -0,0 +1,38 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/system.h
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/hardware/clps7111.h>
+
+static void arch_idle(void)
+{
+ clps_writel(1, HALT);
+ __asm__ __volatile__(
+ "mov r0, r0
+ mov r0, r0");
+}
+
+static inline void arch_reset(char mode)
+{
+ cpu_reset(0);
+}
+
+#endif
diff --git a/include/asm-arm/arch-clps711x/time.h b/include/asm-arm/arch-clps711x/time.h
new file mode 100644
index 000000000..d6040c294
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/time.h
@@ -0,0 +1,43 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/time.h
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <asm/leds.h>
+#include <asm/hardware/clps7111.h>
+
+extern void clps711x_setup_timer(void);
+
+/*
+ * IRQ handler for the timer
+ */
+static void p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ do_leds();
+ do_timer(regs);
+ do_profile(regs);
+}
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init time_init(void)
+{
+ clps711x_setup_timer();
+ timer_irq.handler = p720t_timer_interrupt;
+ setup_arm_irq(IRQ_TC2OI, &timer_irq);
+}
diff --git a/include/asm-arm/arch-clps711x/timex.h b/include/asm-arm/arch-clps711x/timex.h
new file mode 100644
index 000000000..dcbb381da
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/timex.h
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/timex.h
+ *
+ * Prospector 720T architecture timex specifications
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define CLOCK_TICK_RATE 512000
diff --git a/include/asm-arm/arch-clps711x/uncompress.h b/include/asm-arm/arch-clps711x/uncompress.h
new file mode 100644
index 000000000..152fef0ee
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/uncompress.h
@@ -0,0 +1,67 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/uncompress.h
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/config.h>
+#include <asm/arch/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/hardware/clps7111.h>
+
+#undef CLPS7111_BASE
+#define CLPS7111_BASE CLPS7111_PHYS_BASE
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+#define __raw_readl(p) (*(unsigned long *)(p))
+#define __raw_writel(v,p) (*(unsigned long *)(p) = (v))
+
+#ifdef CONFIG_DEBUG_CLPS711X_UART2
+#define SYSFLGx SYSFLG2
+#define UARTDRx UARTDR2
+#else
+#define SYSFLGx SYSFLG1
+#define UARTDRx UARTDR1
+#endif
+
+/*
+ * This does not append a newline
+ */
+static void puts(const char *s)
+{
+ char c;
+
+ while ((c = *s++) != '\0') {
+ while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
+ barrier();
+ clps_writel(c, UARTDRx);
+
+ if (c == '\n') {
+ while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
+ barrier();
+ clps_writel('\r', UARTDRx);
+ }
+ }
+ while (clps_readl(SYSFLGx) & SYSFLG_UBUSY)
+ barrier();
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-clps711x/vmalloc.h b/include/asm-arm/arch-clps711x/vmalloc.h
new file mode 100644
index 000000000..5d8324ac3
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/vmalloc.h
@@ -0,0 +1,32 @@
+/*
+ * linux/include/asm-arm/arch-clps711x/vmalloc.h
+ *
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts. That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET (8*1024*1024)
+#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-ebsa110/io.h b/include/asm-arm/arch-ebsa110/io.h
index cf83e8bc7..ff7221d68 100644
--- a/include/asm-arm/arch-ebsa110/io.h
+++ b/include/asm-arm/arch-ebsa110/io.h
@@ -15,12 +15,6 @@
#define IO_SPACE_LIMIT 0xffff
-/*
- * Generic virtual read/write
- */
-#define __arch_getw(a) (*(volatile unsigned short *)(a))
-#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
-
u8 __inb(int port);
u16 __inw(int port);
u32 __inl(int port);
@@ -53,7 +47,7 @@ void __writel(u32 val, void *addr);
#define writew(v,b) __writew(v,b)
#define writel(v,b) __writel(v,b)
-#define __arch_ioremap(off,sz,c) ((void *)(off))
-#define __arch_iounmap(virt) do { } while (0)
+#define __arch_ioremap(cookie,sz,c) ((void *)(cookie))
+#define __arch_iounmap(cookie) do { } while (0)
#endif
diff --git a/include/asm-arm/arch-ebsa110/time.h b/include/asm-arm/arch-ebsa110/time.h
index 53b354720..b1bab596e 100644
--- a/include/asm-arm/arch-ebsa110/time.h
+++ b/include/asm-arm/arch-ebsa110/time.h
@@ -33,7 +33,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* Set up timer interrupt.
*/
-static inline void setup_timer(void)
+void __init time_init(void)
{
ebsa110_setup_timer();
diff --git a/include/asm-arm/arch-ebsa110/vmalloc.h b/include/asm-arm/arch-ebsa110/vmalloc.h
index 78c71c2db..da319920a 100644
--- a/include/asm-arm/arch-ebsa110/vmalloc.h
+++ b/include/asm-arm/arch-ebsa110/vmalloc.h
@@ -19,4 +19,4 @@
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END (PAGE_OFFSET + 0x1f000000)
diff --git a/include/asm-arm/arch-ebsa285/io.h b/include/asm-arm/arch-ebsa285/io.h
index a0591a8c5..aac50402b 100644
--- a/include/asm-arm/arch-ebsa285/io.h
+++ b/include/asm-arm/arch-ebsa285/io.h
@@ -42,13 +42,4 @@ static inline unsigned long ___mem_isa(unsigned long a)
#define __mem_isa(a) ___mem_isa((unsigned long)(a))
#endif
-/*
- * Generic virtual read/write
- */
-#define __arch_getw(a) (*(volatile unsigned short *)(a))
-#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
-
-#define iomem_valid_addr(iomem,sz) (1)
-#define iomem_to_phys(iomem) (iomem)
-
#endif
diff --git a/include/asm-arm/arch-ebsa285/time.h b/include/asm-arm/arch-ebsa285/time.h
index e70657d67..111bf6e30 100644
--- a/include/asm-arm/arch-ebsa285/time.h
+++ b/include/asm-arm/arch-ebsa285/time.h
@@ -199,7 +199,7 @@ static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* Set up timer interrupt.
*/
-static inline void setup_timer(void)
+void __init time_init(void)
{
int irq;
diff --git a/include/asm-arm/arch-ebsa285/vmalloc.h b/include/asm-arm/arch-ebsa285/vmalloc.h
index 823c6d794..c66b7fa88 100644
--- a/include/asm-arm/arch-ebsa285/vmalloc.h
+++ b/include/asm-arm/arch-ebsa285/vmalloc.h
@@ -6,6 +6,8 @@
* published by the Free Software Foundation.
*/
+#include <linux/config.h>
+
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
* current 8MB value just means that there will be a 8MB "hole" after the
@@ -17,4 +19,9 @@
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+#ifdef CONFIG_ARCH_FOOTBRIDGE
+#define VMALLOC_END (PAGE_OFFSET + 0x30000000)
+#else
#define VMALLOC_END (PAGE_OFFSET + 0x20000000)
+#endif
diff --git a/include/asm-arm/arch-epxa10db/ether00.h b/include/asm-arm/arch-epxa10db/ether00.h
new file mode 100644
index 000000000..29a458320
--- /dev/null
+++ b/include/asm-arm/arch-epxa10db/ether00.h
@@ -0,0 +1,482 @@
+#ifndef __ETHER00_H
+#define __ETHER00_H
+
+
+
+/*
+ * Register definitions for the Ethernet MAC
+ */
+
+/*
+ * Copyright (c) Altera Corporation 2000.
+ * All rights reserved.
+ */
+
+/*
+* Structures for the DMA controller
+*/
+typedef struct fda_desc
+ {
+ struct fda_desc * FDNext;
+ long FDSystem;
+ long FDStat;
+ short FDLength;
+ short FDCtl;
+ }FDA_DESC;
+
+typedef struct buf_desc
+ {
+ char * BuffData;
+ short BuffLength;
+ char BDStat;
+ char BDCtl;
+ }BUF_DESC;
+
+/*
+* Control masks for the DMA controller
+*/
+#define FDCTL_BDCOUNT_MSK (0x1F)
+#define FDCTL_BDCOUNT_OFST (0)
+#define FDCTL_FRMOPT_MSK (0x7C00)
+#define FDCTL_FRMOPT_OFST (10)
+#define FDCTL_COWNSFD_MSK (0x8000)
+#define FDCTL_COWNSFD_OFST (15)
+
+#define BDCTL_RXBDSEQN_MSK (0x7F)
+#define BDCTL_RXBDSEQN_OFST (0)
+#define BDCTL_COWNSBD_MSK (0x80)
+#define BDCTL_COWNSBD_OFST (7)
+
+#define FDNEXT_EOL_MSK (0x1)
+#define FDNEXT_EOL_OFST (0)
+#define FDNEXT_EOL_POINTER_MSK (0xFFFFFFF0)
+#define FDNEXT_EOL_POINTER_OFST (4)
+
+#define ETHER_ARC_SIZE (21)
+
+/*
+* Regsiter definitions and masks
+*/
+#define ETHER_DMA_CTL(base) (ETHER00_TYPE (base + 0x100))
+#define ETHER_DMA_CTL_DMBURST_OFST (2)
+#define ETHER_DMA_CTL_DMBURST_MSK (0x1FC)
+#define ETHER_DMA_CTL_POWRMGMNT_OFST (11)
+#define ETHER_DMA_CTL_POWRMGMNT_MSK (0x1000)
+#define ETHER_DMA_CTL_TXBIGE_OFST (14)
+#define ETHER_DMA_CTL_TXBIGE_MSK (0x4000)
+#define ETHER_DMA_CTL_RXBIGE_OFST (15)
+#define ETHER_DMA_CTL_RXBIGE_MSK (0x8000)
+#define ETHER_DMA_CTL_TXWAKEUP_OFST (16)
+#define ETHER_DMA_CTL_TXWAKEUP_MSK (0x10000)
+#define ETHER_DMA_CTL_SWINTREQ_OFST (17)
+#define ETHER_DMA_CTL_SWINTREQ_MSK (0x20000)
+#define ETHER_DMA_CTL_INTMASK_OFST (18)
+#define ETHER_DMA_CTL_INTMASK_MSK (0x40000)
+#define ETHER_DMA_CTL_M66ENSTAT_OFST (19)
+#define ETHER_DMA_CTL_M66ENSTAT_MSK (0x80000)
+#define ETHER_DMA_CTL_RMTXINIT_OFST (20)
+#define ETHER_DMA_CTL_RMTXINIT_MSK (0x100000)
+#define ETHER_DMA_CTL_RMRXINIT_OFST (21)
+#define ETHER_DMA_CTL_RMRXINIT_MSK (0x200000)
+#define ETHER_DMA_CTL_RXALIGN_OFST (22)
+#define ETHER_DMA_CTL_RXALIGN_MSK (0xC00000)
+#define ETHER_DMA_CTL_RMSWRQ_OFST (24)
+#define ETHER_DMA_CTL_RMSWRQ_MSK (0x1000000)
+#define ETHER_DMA_CTL_RMEMBANK_OFST (25)
+#define ETHER_DMA_CTL_RMEMBANK_MSK (0x2000000)
+
+#define ETHER_TXFRMPTR(base) (ETHER00_TYPE (base + 0x104))
+
+#define ETHER_TXTHRSH(base) (ETHER00_TYPE (base + 0x308))
+
+#define ETHER_TXPOLLCTR(base) (ETHER00_TYPE (base + 0x30c))
+
+#define ETHER_BLFRMPTR(base) (ETHER00_TYPE (base + 0x110))
+#define ETHER_BLFFRMPTR_EOL_OFST (0)
+#define ETHER_BLFFRMPTR_EOL_MSK (0x1)
+#define ETHER_BLFFRMPTR_ADDRESS_OFST (4)
+#define ETHER_BLFFRMPTR_ADDRESS_MSK (0xFFFFFFF0)
+
+#define ETHER_RXFRAGSIZE(base) (ETHER00_TYPE (base + 0x114))
+#define ETHER_RXFRAGSIZE_MINFRAG_OFST (2)
+#define ETHER_RXFRAGSIZE_MINFRAG_MSK (0xFFC)
+#define ETHER_RXFRAGSIZE_ENPACK_OFST (15)
+#define ETHER_RXFRAGSIZE_ENPACK_MSK (0x8000)
+
+#define ETHER_INT_EN(base) (ETHER00_TYPE (base + 0x118))
+#define ETHER_INT_EN_FDAEXEN_OFST (0)
+#define ETHER_INT_EN_FDAEXEN_MSK (0x1)
+#define ETHER_INT_EN_BLEXEN_OFST (1)
+#define ETHER_INT_EN_BLEXN_MSK (0x2)
+#define ETHER_INT_EN_STARGABTEN_OFST (2)
+#define ETHER_INT_EN_STARGABTEN_MSK (0x4)
+#define ETHER_INT_EN_RTARGABTEN_OFST (3)
+#define ETHER_INT_EN_RTARGABTEN_MSK (0x8)
+#define ETHER_INT_EN_RMASABTEN_OFST (4)
+#define ETHER_INT_EN_RMASABTEN_MSK (0x10)
+#define ETHER_INT_EN_SSYSERREN_OFST (5)
+#define ETHER_INT_EN_SSYSERREN_MSK (0x20)
+#define ETHER_INT_EN_DPARERREN_OFST (6)
+#define ETHER_INT_EN_DPARERREN_MSK (0x40)
+#define ETHER_INT_EN_EARNOTEN_OFST (7)
+#define ETHER_INT_EN_EARNOTEN_MSK (0x80)
+#define ETHER_INT_EN_DPARDEN_OFST (8)
+#define ETHER_INT_EN_DPARDEN_MSK (0x100)
+#define ETHER_INT_EN_DMPARERREN_OFST (9)
+#define ETHER_INT_EN_DMPARERREN_MSK (0x200)
+#define ETHER_INT_EN_TXCTLCMPEN_OFST (10)
+#define ETHER_INT_EN_TXCTLCMPEN_MSK (0x400)
+#define ETHER_INT_EN_NRABTEN_OFST (11)
+#define ETHER_INT_EN_NRABTEN_MSK (0x800)
+
+#define ETHER_FDA_BAS(base) (ETHER00_TYPE (base + 0x11C))
+#define ETHER_FDA_BAS_ADDRESS_OFST (4)
+#define ETHER_FDA_BAS_ADDRESS_MSK (0xFFFFFFF0)
+
+#define ETHER_FDA_LIM(base) (ETHER00_TYPE (base + 0x120))
+#define ETHER_FDA_LIM_COUNT_OFST (4)
+#define ETHER_FDA_LIM_COUNT_MSK (0xFFF0)
+
+#define ETHER_INT_SRC(base) (ETHER00_TYPE (base + 0x124))
+#define ETHER_INT_SRC_INTMACTX_OFST (0)
+#define ETHER_INT_SRC_INTMACTX_MSK (0x1)
+#define ETHER_INT_SRC_INTMACRX_OFST (1)
+#define ETHER_INT_SRC_INTMACRX_MSK (0x2)
+#define ETHER_INT_SRC_INTSBUS_OFST (2)
+#define ETHER_INT_SRC_INTSBUS_MSK (0x4)
+#define ETHER_INT_SRC_INTFDAEX_OFST (3)
+#define ETHER_INT_SRC_INTFDAEX_MSK (0x8)
+#define ETHER_INT_SRC_INTBLEX_OFST (4)
+#define ETHER_INT_SRC_INTBLEX_MSK (0x10)
+#define ETHER_INT_SRC_SWINT_OFST (5)
+#define ETHER_INT_SRC_SWINT_MSK (0x20)
+#define ETHER_INT_SRC_INTEARNOT_OFST (6)
+#define ETHER_INT_SRC_INTEARNOT_MSK (0x40)
+#define ETHER_INT_SRC_DMPARERR_OFST (7)
+#define ETHER_INT_SRC_DMPARERR_MSK (0x80)
+#define ETHER_INT_SRC_INTEXBD_OFST (8)
+#define ETHER_INT_SRC_INTEXBD_MSK (0x100)
+#define ETHER_INT_SRC_INTTXCTLCMP_OFST (9)
+#define ETHER_INT_SRC_INTTXCTLCMP_MSK (0x200)
+#define ETHER_INT_SRC_INTNRABT_OFST (10)
+#define ETHER_INT_SRC_INTNRABT_MSK (0x400)
+#define ETHER_INT_SRC_FDAEX_OFST (11)
+#define ETHER_INT_SRC_FDAEX_MSK (0x800)
+#define ETHER_INT_SRC_BLEX_OFST (12)
+#define ETHER_INT_SRC_BLEX_MSK (0x1000)
+#define ETHER_INT_SRC_DMPARERRSTAT_OFST (13)
+#define ETHER_INT_SRC_DMPARERRSTAT_MSK (0x2000)
+#define ETHER_INT_SRC_NRABT_OFST (14)
+#define ETHER_INT_SRC_NRABT_MSK (0x4000)
+#define ETHER_INT_SRC_INTLINK_OFST (15)
+#define ETHER_INT_SRC_INTLINK_MSK (0x8000)
+#define ETHER_INT_SRC_INTEXDEFER_OFST (16)
+#define ETHER_INT_SRC_INTEXDEFER_MSK (0x10000)
+#define ETHER_INT_SRC_INTRMON_OFST (17)
+#define ETHER_INT_SRC_INTRMON_MSK (0x20000)
+#define ETHER_INT_SRC_IRQ_MSK (0x83FF)
+
+#define ETHER_PAUSECNT(base) (ETHER00_TYPE (base + 0x40))
+#define ETHER_PAUSECNT_COUNT_OFST (0)
+#define ETHER_PAUSECNT_COUNT_MSK (0xFFFF)
+
+#define ETHER_REMPAUCNT(base) (ETHER00_TYPE (base + 0x44))
+#define ETHER_REMPAUCNT_COUNT_OFST (0)
+#define ETHER_REMPAUCNT_COUNT_MSK (0xFFFF)
+
+#define ETHER_TXCONFRMSTAT(base) (ETHER00_TYPE (base + 0x348))
+#define ETHER_TXCONFRMSTAT_TS_STAT_VALUE_OFST (0)
+#define ETHER_TXCONFRMSTAT_TS_STAT_VALUE_MSK (0x3FFFFF)
+
+#define ETHER_MAC_CTL(base) (ETHER00_TYPE (base + 0))
+#define ETHER_MAC_CTL_HALTREQ_OFST (0)
+#define ETHER_MAC_CTL_HALTREQ_MSK (0x1)
+#define ETHER_MAC_CTL_HALTIMM_OFST (1)
+#define ETHER_MAC_CTL_HALTIMM_MSK (0x2)
+#define ETHER_MAC_CTL_RESET_OFST (2)
+#define ETHER_MAC_CTL_RESET_MSK (0x4)
+#define ETHER_MAC_CTL_FULLDUP_OFST (3)
+#define ETHER_MAC_CTL_FULLDUP_MSK (0x8)
+#define ETHER_MAC_CTL_MACLOOP_OFST (4)
+#define ETHER_MAC_CTL_MACLOOP_MSK (0x10)
+#define ETHER_MAC_CTL_CONN_OFST (5)
+#define ETHER_MAC_CTL_CONN_MSK (0x60)
+#define ETHER_MAC_CTL_LOOP10_OFST (7)
+#define ETHER_MAC_CTL_LOOP10_MSK (0x80)
+#define ETHER_MAC_CTL_LNKCHG_OFST (8)
+#define ETHER_MAC_CTL_LNKCHG_MSK (0x100)
+#define ETHER_MAC_CTL_MISSROLL_OFST (10)
+#define ETHER_MAC_CTL_MISSROLL_MSK (0x400)
+#define ETHER_MAC_CTL_ENMISSROLL_OFST (13)
+#define ETHER_MAC_CTL_ENMISSROLL_MSK (0x2000)
+#define ETHER_MAC_CTL_LINK10_OFST (15)
+#define ETHER_MAC_CTL_LINK10_MSK (0x8000)
+
+#define ETHER_ARC_CTL(base) (ETHER00_TYPE (base + 0x4))
+#define ETHER_ARC_CTL_STATIONACC_OFST (0)
+#define ETHER_ARC_CTL_STATIONACC_MSK (0x1)
+#define ETHER_ARC_CTL_GROUPACC_OFST (1)
+#define ETHER_ARC_CTL_GROUPACC_MSK (0x2)
+#define ETHER_ARC_CTL_BROADACC_OFST (2)
+#define ETHER_ARC_CTL_BROADACC_MSK (0x4)
+#define ETHER_ARC_CTL_NEGARC_OFST (3)
+#define ETHER_ARC_CTL_NEGARC_MSK (0x8)
+#define ETHER_ARC_CTL_COMPEN_OFST (4)
+#define ETHER_ARC_CTL_COMPEN_MSK (0x10)
+
+#define ETHER_TX_CTL(base) (ETHER00_TYPE (base + 0x8))
+#define ETHER_TX_CTL_TXEN_OFST (0)
+#define ETHER_TX_CTL_TXEN_MSK (0x1)
+#define ETHER_TX_CTL_TXHALT_OFST (1)
+#define ETHER_TX_CTL_TXHALT_MSK (0x2)
+#define ETHER_TX_CTL_NOPAD_OFST (2)
+#define ETHER_TX_CTL_NOPAD_MSK (0x4)
+#define ETHER_TX_CTL_NOCRC_OFST (3)
+#define ETHER_TX_CTL_NOCRC_MSK (0x8)
+#define ETHER_TX_CTL_FBACK_OFST (4)
+#define ETHER_TX_CTL_FBACK_MSK (0x10)
+#define ETHER_TX_CTL_NOEXDEF_OFST (5)
+#define ETHER_TX_CTL_NOEXDEF_MSK (0x20)
+#define ETHER_TX_CTL_SDPAUSE_OFST (6)
+#define ETHER_TX_CTL_SDPAUSE_MSK (0x40)
+#define ETHER_TX_CTL_MII10_OFST (7)
+#define ETHER_TX_CTL_MII10_MSK (0x80)
+#define ETHER_TX_CTL_ENUNDER_OFST (8)
+#define ETHER_TX_CTL_ENUNDER_MSK (0x100)
+#define ETHER_TX_CTL_ENEXDEFER_OFST (9)
+#define ETHER_TX_CTL_ENEXDEFER_MSK (0x200)
+#define ETHER_TX_CTL_ENLCARR_OFST (10)
+#define ETHER_TX_CTL_ENLCARR_MSK (0x400)
+#define ETHER_TX_CTL_ENEXCOLL_OFST (11)
+#define ETHER_TX_CTL_ENEXCOLL_MSK (0x800)
+#define ETHER_TX_CTL_ENLATECOLL_OFST (12)
+#define ETHER_TX_CTL_ENLATECOLL_MSK (0x1000)
+#define ETHER_TX_CTL_ENTXPAR_OFST (13)
+#define ETHER_TX_CTL_ENTXPAR_MSK (0x2000)
+#define ETHER_TX_CTL_ENCOMP_OFST (14)
+#define ETHER_TX_CTL_ENCOMP_MSK (0x4000)
+
+#define ETHER_TX_STAT(base) (ETHER00_TYPE (base + 0xc))
+#define ETHER_TX_STAT_TXCOLL_OFST (0)
+#define ETHER_TX_STAT_TXCOLL_MSK (0xF)
+#define ETHER_TX_STAT_EXCOLL_OFST (4)
+#define ETHER_TX_STAT_EXCOLL_MSK (0x10)
+#define ETHER_TX_STAT_TXDEFER_OFST (5)
+#define ETHER_TX_STAT_TXDEFER_MSK (0x20)
+#define ETHER_TX_STAT_PAUSED_OFST (6)
+#define ETHER_TX_STAT_PAUSED_MSK (0x40)
+#define ETHER_TX_STAT_INTTX_OFST (7)
+#define ETHER_TX_STAT_INTTX_MSK (0x80)
+#define ETHER_TX_STAT_UNDER_OFST (8)
+#define ETHER_TX_STAT_UNDER_MSK (0x100)
+#define ETHER_TX_STAT_EXDEFER_OFST (9)
+#define ETHER_TX_STAT_EXDEFER_MSK (0x200)
+#define ETHER_TX_STAT_LCARR_OFST (10)
+#define ETHER_TX_STAT_LCARR_MSK (0x400)
+#define ETHER_TX_STAT_TX10STAT_OFST (11)
+#define ETHER_TX_STAT_TX10STAT_MSK (0x800)
+#define ETHER_TX_STAT_LATECOLL_OFST (12)
+#define ETHER_TX_STAT_LATECOLL_MSK (0x1000)
+#define ETHER_TX_STAT_TXPAR_OFST (13)
+#define ETHER_TX_STAT_TXPAR_MSK (0x2000)
+#define ETHER_TX_STAT_COMP_OFST (14)
+#define ETHER_TX_STAT_COMP_MSK (0x4000)
+#define ETHER_TX_STAT_TXHALTED_OFST (15)
+#define ETHER_TX_STAT_TXHALTED_MSK (0x8000)
+#define ETHER_TX_STAT_SQERR_OFST (16)
+#define ETHER_TX_STAT_SQERR_MSK (0x10000)
+#define ETHER_TX_STAT_TXMCAST_OFST (17)
+#define ETHER_TX_STAT_TXMCAST_MSK (0x20000)
+#define ETHER_TX_STAT_TXBCAST_OFST (18)
+#define ETHER_TX_STAT_TXBCAST_MSK (0x40000)
+#define ETHER_TX_STAT_VLAN_OFST (19)
+#define ETHER_TX_STAT_VLAN_MSK (0x80000)
+#define ETHER_TX_STAT_MACC_OFST (20)
+#define ETHER_TX_STAT_MACC_MSK (0x100000)
+#define ETHER_TX_STAT_TXPAUSE_OFST (21)
+#define ETHER_TX_STAT_TXPAUSE_MSK (0x200000)
+
+#define ETHER_RX_CTL(base) (ETHER00_TYPE (base + 0x10))
+#define ETHER_RX_CTL_RXEN_OFST (0)
+#define ETHER_RX_CTL_RXEN_MSK (0x1)
+#define ETHER_RX_CTL_RXHALT_OFST (1)
+#define ETHER_RX_CTL_RXHALT_MSK (0x2)
+#define ETHER_RX_CTL_LONGEN_OFST (2)
+#define ETHER_RX_CTL_LONGEN_MSK (0x4)
+#define ETHER_RX_CTL_SHORTEN_OFST (3)
+#define ETHER_RX_CTL_SHORTEN_MSK (0x8)
+#define ETHER_RX_CTL_STRIPCRC_OFST (4)
+#define ETHER_RX_CTL_STRIPCRC_MSK (0x10)
+#define ETHER_RX_CTL_PASSCTL_OFST (5)
+#define ETHER_RX_CTL_PASSCTL_MSK (0x20)
+#define ETHER_RX_CTL_IGNORECRC_OFST (6)
+#define ETHER_RX_CTL_IGNORECRC_MSK (0x40)
+#define ETHER_RX_CTL_ENALIGN_OFST (8)
+#define ETHER_RX_CTL_ENALIGN_MSK (0x100)
+#define ETHER_RX_CTL_ENCRCERR_OFST (9)
+#define ETHER_RX_CTL_ENCRCERR_MSK (0x200)
+#define ETHER_RX_CTL_ENOVER_OFST (10)
+#define ETHER_RX_CTL_ENOVER_MSK (0x400)
+#define ETHER_RX_CTL_ENLONGERR_OFST (11)
+#define ETHER_RX_CTL_ENLONGERR_MSK (0x800)
+#define ETHER_RX_CTL_ENRXPAR_OFST (13)
+#define ETHER_RX_CTL_ENRXPAR_MSK (0x2000)
+#define ETHER_RX_CTL_ENGOOD_OFST (14)
+#define ETHER_RX_CTL_ENGOOD_MSK (0x4000)
+
+#define ETHER_RX_STAT(base) (ETHER00_TYPE (base + 0x14))
+#define ETHER_RX_STAT_LENERR_OFST (4)
+#define ETHER_RX_STAT_LENERR_MSK (0x10)
+#define ETHER_RX_STAT_CTLRECD_OFST (5)
+#define ETHER_RX_STAT_CTLRECD_MSK (0x20)
+#define ETHER_RX_STAT_INTRX_OFST (6)
+#define ETHER_RX_STAT_INTRX_MSK (0x40)
+#define ETHER_RX_STAT_RX10STAT_OFST (7)
+#define ETHER_RX_STAT_RX10STAT_MSK (0x80)
+#define ETHER_RX_STAT_ALIGNERR_OFST (8)
+#define ETHER_RX_STAT_ALIGNERR_MSK (0x100)
+#define ETHER_RX_STAT_CRCERR_OFST (9)
+#define ETHER_RX_STAT_CRCERR_MSK (0x200)
+#define ETHER_RX_STAT_OVERFLOW_OFST (10)
+#define ETHER_RX_STAT_OVERFLOW_MSK (0x400)
+#define ETHER_RX_STAT_LONGERR_OFST (11)
+#define ETHER_RX_STAT_LONGERR_MSK (0x800)
+#define ETHER_RX_STAT_RXPAR_OFST (13)
+#define ETHER_RX_STAT_RXPAR_MSK (0x2000)
+#define ETHER_RX_STAT_GOOD_OFST (14)
+#define ETHER_RX_STAT_GOOD_MSK (0x4000)
+#define ETHER_RX_STAT_RXHALTED_OFST (15)
+#define ETHER_RX_STAT_RXHALTED_MSK (0x8000)
+#define ETHER_RX_STAT_RXMCAST_OFST (17)
+#define ETHER_RX_STAT_RXMCAST_MSK (0x10000)
+#define ETHER_RX_STAT_RXBCAST_OFST (18)
+#define ETHER_RX_STAT_RXBCAST_MSK (0x20000)
+#define ETHER_RX_STAT_RXVLAN_OFST (19)
+#define ETHER_RX_STAT_RXVLAN_MSK (0x40000)
+#define ETHER_RX_STAT_RXPAUSE_OFST (20)
+#define ETHER_RX_STAT_RXPAUSE_MSK (0x80000)
+#define ETHER_RX_STAT_ARCSTATUS_OFST (21)
+#define ETHER_RX_STAT_ARCSTATUS_MSK (0xF00000)
+#define ETHER_RX_STAT_ARCENT_OFST (25)
+#define ETHER_RX_STAT_ARCENT_MSK (0x1F000000)
+
+#define ETHER_MD_DATA(base) (ETHER00_TYPE (base + 0x18))
+
+#define ETHER_MD_CA(base) (ETHER00_TYPE (base + 0x1c))
+#define ETHER_MD_CA_ADDR_OFST (0)
+#define ETHER_MD_CA_ADDR_MSK (0x1F)
+#define ETHER_MD_CA_PHY_OFST (5)
+#define ETHER_MD_CA_PHY_MSK (0x3E0)
+#define ETHER_MD_CA_WR_OFST (10)
+#define ETHER_MD_CA_WR_MSK (0x400)
+#define ETHER_MD_CA_BUSY_OFST (11)
+#define ETHER_MD_CA_BUSY_MSK (0x800)
+#define ETHER_MD_CA_PRESUPP_OFST (12)
+#define ETHER_MD_CA_PRESUPP_MSK (0x1000)
+
+#define ETHER_ARC_ADR(base) (ETHER00_TYPE (base + 0x160))
+#define ETHER_ARC_ADR_ARC_LOC_OFST (2)
+#define ETHER_ARC_ADR_ARC_LOC_MSK (0xFFC)
+
+#define ETHER_ARC_DATA(base) (ETHER00_TYPE (base + 0x364))
+
+#define ETHER_ARC_ENA(base) (ETHER00_TYPE (base + 0x28))
+#define ETHER_ARC_ENA_MSK (0x1FFFFF)
+
+#define ETHER_PROM_CTL(base) (ETHER00_TYPE (base + 0x2c))
+#define ETHER_PROM_CTL_PROM_ADDR_OFST (0)
+#define ETHER_PROM_CTL_PROM_ADDR_MSK (0x3F)
+#define ETHER_PROM_CTL_OPCODE_OFST (13)
+#define ETHER_PROM_CTL_OPCODE_MSK (0x6000)
+#define ETHER_PROM_CTL_OPCODE_READ_MSK (0x4000)
+#define ETHER_PROM_CTL_OPCODE_WRITE_MSK (0x2000)
+#define ETHER_PROM_CTL_OPCODE_ERASE_MSK (0x6000)
+#define ETHER_PROM_CTL_ENABLE_MSK (0x0030)
+#define ETHER_PROM_CTL_DISABLE_MSK (0x0000)
+#define ETHER_PROM_CTL_BUSY_OFST (15)
+#define ETHER_PROM_CTL_BUSY_MSK (0x8000)
+
+#define ETHER_PROM_DATA(base) (ETHER00_TYPE (base + 0x30))
+
+#define ETHER_MISS_CNT(base) (ETHER00_TYPE (base + 0x3c))
+#define ETHER_MISS_CNT_COUNT_OFST (0)
+#define ETHER_MISS_CNT_COUNT_MSK (0xFFFF)
+
+#define ETHER_CNTDATA(base) (ETHER00_TYPE (base + 0x80))
+
+#define ETHER_CNTACC(base) (ETHER00_TYPE (base + 0x84))
+#define ETHER_CNTACC_ADDR_OFST (0)
+#define ETHER_CNTACC_ADDR_MSK (0xFF)
+#define ETHER_CNTACC_WRRDN_OFST (8)
+#define ETHER_CNTACC_WRRDN_MSK (0x100)
+#define ETHER_CNTACC_CLEAR_OFST (9)
+#define ETHER_CNTACC_CLEAR_MSK (0x200)
+
+#define ETHER_TXRMINTEN(base) (ETHER00_TYPE (base + 0x88))
+#define ETHER_TXRMINTEN_MSK (0x3FFFFFFF)
+
+#define ETHER_RXRMINTEN(base) (ETHER00_TYPE (base + 0x8C))
+#define ETHER_RXRMINTEN_MSK (0xFFFFFF)
+
+/*
+* RMON Registers
+*/
+#define RMON_COLLISION0 0x0
+#define RMON_COLLISION1 0x1
+#define RMON_COLLISION2 0x2
+#define RMON_COLLISION3 0x3
+#define RMON_COLLISION4 0x4
+#define RMON_COLLISION5 0x5
+#define RMON_COLLISION6 0x6
+#define RMON_COLLISION7 0x7
+#define RMON_COLLISION8 0x8
+#define RMON_COLLISION9 0x9
+#define RMON_COLLISION10 0xa
+#define RMON_COLLISION11 0xb
+#define RMON_COLLISION12 0xc
+#define RMON_COLLISION13 0xd
+#define RMON_COLLISION14 0xe
+#define RMON_COLLISION15 0xf
+#define RMON_COLLISION16 0x10
+#define RMON_FRAMES_WITH_DEFERRED_XMISSIONS 0x11
+#define RMON_LATE_COLLISIONS 0x12
+#define RMON_FRAMES_LOST_DUE_TO_MAC_XMIT 0x13
+#define RMON_CARRIER_SENSE_ERRORS 0x14
+#define RMON_FRAMES_WITH_EXCESSIVE_DEFERAL 0x15
+#define RMON_UNICAST_FRAMES_TRANSMITTED_OK 0x16
+#define RMON_MULTICAST_FRAMES_XMITTED_OK 0x17
+#define RMON_BROADCAST_FRAMES_XMITTED_OK 0x18
+#define RMON_SQE_TEST_ERRORS 0x19
+#define RMON_PAUSE_MACCTRL_FRAMES_XMITTED 0x1A
+#define RMON_MACCTRL_FRAMES_XMITTED 0x1B
+#define RMON_VLAN_FRAMES_XMITTED 0x1C
+#define RMON_OCTETS_XMITTED_OK 0x1D
+#define RMON_OCTETS_XMITTED_OK_HI 0x1E
+
+#define RMON_RX_PACKET_SIZES0 0x40
+#define RMON_RX_PACKET_SIZES1 0x41
+#define RMON_RX_PACKET_SIZES2 0x42
+#define RMON_RX_PACKET_SIZES3 0x43
+#define RMON_RX_PACKET_SIZES4 0x44
+#define RMON_RX_PACKET_SIZES5 0x45
+#define RMON_RX_PACKET_SIZES6 0x46
+#define RMON_RX_PACKET_SIZES7 0x47
+#define RMON_FRAME_CHECK_SEQUENCE_ERRORS 0x48
+#define RMON_ALIGNMENT_ERRORS 0x49
+#define RMON_FRAGMENTS 0x4A
+#define RMON_JABBERS 0x4B
+#define RMON_FRAMES_LOST_TO_INTMACRCVERR 0x4C
+#define RMON_UNICAST_FRAMES_RCVD_OK 0x4D
+#define RMON_MULTICAST_FRAMES_RCVD_OK 0x4E
+#define RMON_BROADCAST_FRAMES_RCVD_OK 0x4F
+#define RMON_IN_RANGE_LENGTH_ERRORS 0x50
+#define RMON_OUT_OF_RANGE_LENGTH_ERRORS 0x51
+#define RMON_VLAN_FRAMES_RCVD 0x52
+#define RMON_PAUSE_MAC_CTRL_FRAMES_RCVD 0x53
+#define RMON_MAC_CTRL_FRAMES_RCVD 0x54
+#define RMON_OCTETS_RCVD_OK 0x55
+#define RMON_OCTETS_RCVD_OK_HI 0x56
+#define RMON_OCTETS_RCVD_OTHER 0x57
+#define RMON_OCTETS_RCVD_OTHER_HI 0x58
+
+#endif /* __ETHER00_H */
diff --git a/include/asm-arm/arch-epxa10db/io.h b/include/asm-arm/arch-epxa10db/io.h
index f0c16e3f1..b93a52571 100644
--- a/include/asm-arm/arch-epxa10db/io.h
+++ b/include/asm-arm/arch-epxa10db/io.h
@@ -26,8 +26,6 @@
/*
* Generic virtual read/write
*/
-#define __arch_getw(a) (*(volatile unsigned short *)(a))
-#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
/*#define outsw __arch_writesw
#define outsl __arch_writesl
#define outsb __arch_writesb
@@ -36,20 +34,6 @@
#define insl __arch_readsl*/
#define __io(a) (a)
-#if 0
-#define __mem_pci(a) ((unsigned long)(a))
-#define __mem_isa(a) (PCI_MEMORY_VADDR + (unsigned long)(a))
-/*
- * Validate the pci memory address for ioremap.
- */
-#define iomem_valid_addr(iomem,size) \
- ((iomem) > 0 && (iomem) + (size) <= 0x20000000)
-
-/*
- * Convert PCI memory space to a CPU physical address
- */
-#define iomem_to_phys(iomem) ((iomem) + PHYS_PCI_MEM_BASE)
-
-#endif
+#define __mem_pci(a) (a)
#endif
diff --git a/include/asm-arm/arch-epxa10db/tdkphy.h b/include/asm-arm/arch-epxa10db/tdkphy.h
new file mode 100644
index 000000000..5e107bd4e
--- /dev/null
+++ b/include/asm-arm/arch-epxa10db/tdkphy.h
@@ -0,0 +1,209 @@
+/*
+ * linux/drivers/tdkphy.h
+ *
+ * Copyright (C) 2001 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __TDKPHY_H
+#define __TDKPHY_H
+
+/*
+ * Register definitions for the TDK 78Q2120 PHY
+ * which is on the Camelot board
+ */
+
+/*
+ * Copyright (c) Altera Corporation 2000.
+ * All rights reserved.
+ */
+#define PHY_CONTROL (0)
+#define PHY_CONTROL_COLT_MSK (0x80)
+#define PHY_CONTROL_COLT_OFST (7)
+#define PHY_CONTROL_DUPLEX_MSK (0x100)
+#define PHY_CONTROL_DUPLEX_OFST (8)
+#define PHY_CONTROL_RANEG_MSK (0x200)
+#define PHY_CONTROL_RANEG_OFST (9)
+#define PHY_CONTROL_ISO_MSK (0x400)
+#define PHY_CONTROL_ISO_OFST (10)
+#define PHY_CONTROL_PWRDN_MSK (0x800)
+#define PHY_CONTROL_PWRDN_OFST (11)
+#define PHY_CONTROL_ANEGEN_MSK (0x1000)
+#define PHY_CONTROL_ANEGEN_OFST (12)
+#define PHY_CONTROL_SPEEDSL_MSK (0x2000)
+#define PHY_CONTROL_SPEEDSL_OFST (13)
+#define PHY_CONTROL_LOOPBK_MSK (0x4000)
+#define PHY_CONTROL_LOOPBK_OFST (14)
+#define PHY_CONTROL_RESET_MSK (0x8000)
+#define PHY_CONTROL_RESET_OFST (15)
+
+#define PHY_STATUS (1)
+#define PHY_STATUS_ETXD_MSK (0x1)
+#define PHY_STATUS_EXTD_OFST (0)
+#define PHY_STATUS_JAB_MSK (0x2)
+#define PHY_STATUS_JAB_OFST (1)
+#define PHY_STATUS_LINK_MSK (0x4)
+#define PHY_STATUS_LINK_OFST (2)
+#define PHY_STATUS_ANEGA_MSK (0x8)
+#define PHY_STATUS_ANEGA_OFST (3)
+#define PHY_STATUS_RFAULT_MSK (0x10)
+#define PHY_STATUS_RFAULT_OFST (4)
+#define PHY_STATUS_ANEGC_MSK (0x20)
+#define PHY_STATUS_ANEGC_OFST (5)
+#define PHY_STATUS_10T_H_MSK (0x800)
+#define PHY_STATUS_10T_H_OFST (11)
+#define PHY_STATUS_10T_F_MSK (0x1000)
+#define PHY_STATUS_10T_F_OFST (12)
+#define PHY_STATUS_100_X_H_MSK (0x2000)
+#define PHY_STATUS_100_X_H_OFST (13)
+#define PHY_STATUS_100_X_F_MSK (0x4000)
+#define PHY_STATUS_100_X_F_OFST (14)
+#define PHY_STATUS_100T4_MSK (0x8000)
+#define PHY_STATUS_100T4_OFST (15)
+
+#define PHY_ID1 (2)
+#define PHY_ID1_OUI_MSK (0xFFFF)
+#define PHY_ID1_OUI_OFST (0)
+
+#define PHY_ID2 (3)
+#define PHY_ID2_RN_MSK (0xF)
+#define PHY_ID2_RN_OFST (0)
+#define PHY_ID2_MN_MSK (0x3F0)
+#define PHY_ID2_MN_OFST (4)
+#define PHY_ID2_OUI_MSK (0xFC00)
+#define PHY_ID2_OUI_OFST (10)
+
+#define PHY_AUTO_NEG_ADVERTISEMENT (4)
+#define PHY_AUTO_NEG_ADVERTISEMENT_SELECTOR_MSK (0x1F)
+#define PHY_AUTO_NEG_ADVERTISEMENT_SELECTOR_OFST (0)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A0_MSK (0x20)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A0_OFST (5)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A1_MSK (0x40)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A1_OFST (6)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A2_MSK (0x80)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A2_OFST (7)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A3_MSK (0x100)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A3_OFST (8)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A4_MSK (0x200)
+#define PHY_AUTO_NEG_ADVERTISEMENT_A4_OFST (9)
+#define PHY_AUTO_NEG_ADVERTISEMENT_TAF_MSK (0x1FE0)
+#define PHY_AUTO_NEG_ADVERTISEMENT_TAF_OFST (5)
+#define PHY_AUTO_NEG_ADVERTISEMENT_RF_MSK (0x2000)
+#define PHY_AUTO_NEG_ADVERTISEMENT_RF_OFST (13)
+#define PHY_AUTO_NEG_ADVERTISEMENT_RSVD_MSK (0x4000)
+#define PHY_AUTO_NEG_ADVERTISEMENT_RVSD_OFST (14)
+#define PHY_AUTO_NEG_ADVERTISEMENT_NP_MSK (0x8000)
+#define PHY_AUTO_NEG_ADVERTISEMENT_NP_OFST (15)
+
+#define PHY_AUTO_NEG_LINK_PARTNER (5)
+#define PHY_AUTO_NEG_LINK_PARTNER_S4_MSK (0x1F)
+#define PHY_AUTO_NEG_LINK_PARTNER_S4_OFST (0)
+#define PHY_AUTO_NEG_LINK_PARTNER_A7_MSK (0x1FE0)
+#define PHY_AUTO_NEG_LINK_PARTNER_A7_OFST (5)
+#define PHY_AUTO_NEG_LINK_PARTNER_RF_MSK (0x2000)
+#define PHY_AUTO_NEG_LINK_PARTNER_RF_OFST (13)
+#define PHY_AUTO_NEG_LINK_PARTNER_ACK_MSK (0x4000)
+#define PHY_AUTO_NEG_LINK_PARTNER_ACK_OFST (14)
+#define PHY_AUTO_NEG_LINK_PARTNER_NP_MSK (0x8000)
+#define PHY_AUTO_NEG_LINK_PARTNER_NP_OFST (15)
+
+#define PHY_AUTO_NEG_EXPANSION (6)
+#define PHY_AUTO_NEG_EXPANSION_LPANEGA_MSK (0x1)
+#define PHY_AUTO_NEG_EXPANSION_LPANEGA_OFST (0)
+#define PHY_AUTO_NEG_EXPANSION_PRX_MSK (0x2)
+#define PHY_AUTO_NEG_EXPANSION_PRX_OFST (1)
+#define PHY_AUTO_NEG_EXPANSION_NPA_MSK (0x4)
+#define PHY_AUTO_NEG_EXPANSION_NPA_OFST (2)
+#define PHY_AUTO_NEG_EXPANSION_LPNPA_MSK (0x8)
+#define PHY_AUTO_NEG_EXPANSION_LPNPA_OFST (3)
+#define PHY_AUTO_NEG_EXPANSION_PDF_MSK (0x10)
+#define PHY_AUTO_NEG_EXPANSION_PDF_OFST (4)
+
+#define PHY_VENDOR_SPECIFIC (16)
+#define PHY_VENDOR_SPECIFIC_RXCC_MSK (0x1)
+#define PHY_VENDOR_SPECIFIC_RXCC_OFST (0)
+#define PHY_VENDOR_SPECIFIC_PCSBP_MSK (0x2)
+#define PHY_VENDOR_SPECIFIC_PCSBP_OFST (1)
+#define PHY_VENDOR_SPECIFIC_RVSPOL_MSK (0x10)
+#define PHY_VENDOR_SPECIFIC_RVSPOL_OFST (4)
+#define PHY_VENDOR_SPECIFIC_APOL_MSK (0x20)
+#define PHY_VENDOR_SPECIFIC_APOL_OFST (5)
+#define PHY_VENDOR_SPECIFIC_GPIO0_DIR_MSK (0x40)
+#define PHY_VENDOR_SPECIFIC_GPIO0_DIR_OFST (6)
+#define PHY_VENDOR_SPECIFIC_GPIO0_DAT_MSK (0x80)
+#define PHY_VENDOR_SPECIFIC_GPIO0_DAT_OFST (7)
+#define PHY_VENDOR_SPECIFIC_GPIO1_DIR_MSK (0x100)
+#define PHY_VENDOR_SPECIFIC_GPIO1_DIR_OFST (8)
+#define PHY_VENDOR_SPECIFIC_GPIO1_DAT_MSK (0x200)
+#define PHY_VENDOR_SPECIFIC_GPIO1_DAT_OFST (9)
+#define PHY_VENDOR_SPECIFIC_10BT_NATURAL_LOOPBACK_DAT_MSK (0x400)
+#define PHY_VENDOR_SPECIFIC_10BT_NATURAL_LOOPBACK_DAT_OFST (10)
+#define PHY_VENDOR_SPECIFIC_10BT_SQE_TEST_INHIBIT_MSK (0x800)
+#define PHY_VENDOR_SPECIFIC_10BT_SQE_TEST_INHIBIT_OFST (11)
+#define PHY_VENDOR_SPECIFIC_TXHIM_MSK (0x1000)
+#define PHY_VENDOR_SPECIFIC_TXHIM_OFST (12)
+#define PHY_VENDOR_SPECIFIC_INT_LEVEL_MSK (0x4000)
+#define PHY_VENDOR_SPECIFIC_INT_LEVEL_OFST (14)
+#define PHY_VENDOR_SPECIFIC_RPTR_MSK (0x8000)
+#define PHY_VENDOR_SPECIFIC_RPTR_OFST (15)
+
+#define PHY_IRQ_CONTROL (17)
+#define PHY_IRQ_CONTROL_ANEG_COMP_INT_MSK (0x1)
+#define PHY_IRQ_CONTROL_ANEG_COMP_INT_OFST (0)
+#define PHY_IRQ_CONTROL_RFAULT_INT_MSK (0x2)
+#define PHY_IRQ_CONTROL_RFAULT_INT_OFST (1)
+#define PHY_IRQ_CONTROL_LS_CHG_INT_MSK (0x4)
+#define PHY_IRQ_CONTROL_LS_CHG_INT_OFST (2)
+#define PHY_IRQ_CONTROL_LP_ACK_INT_MSK (0x8)
+#define PHY_IRQ_CONTROL_LP_ACK_INT_OFST (3)
+#define PHY_IRQ_CONTROL_PDF_INT_MSK (0x10)
+#define PHY_IRQ_CONTROL_PDF_INT_OFST (4)
+#define PHY_IRQ_CONTROL_PRX_INT_MSK (0x20)
+#define PHY_IRQ_CONTROL_PRX_INT_OFST (5)
+#define PHY_IRQ_CONTROL_RXER_INT_MSK (0x40)
+#define PHY_IRQ_CONTROL_RXER_INT_OFST (6)
+#define PHY_IRQ_CONTROL_JABBER_INT_MSK (0x80)
+#define PHY_IRQ_CONTROL_JABBER_INT_OFST (7)
+#define PHY_IRQ_CONTROL_ANEG_COMP_IE_MSK (0x100)
+#define PHY_IRQ_CONTROL_ANEG_COMP_IE_OFST (8)
+#define PHY_IRQ_CONTROL_RFAULT_IE_MSK (0x200)
+#define PHY_IRQ_CONTROL_RFAULT_IE_OFST (9)
+#define PHY_IRQ_CONTROL_LS_CHG_IE_MSK (0x400)
+#define PHY_IRQ_CONTROL_LS_CHG_IE_OFST (10)
+#define PHY_IRQ_CONTROL_LP_ACK_IE_MSK (0x800)
+#define PHY_IRQ_CONTROL_LP_ACK_IE_OFST (11)
+#define PHY_IRQ_CONTROL_PDF_IE_MSK (0x1000)
+#define PHY_IRQ_CONTROL_PDF_IE_OFST (12)
+#define PHY_IRQ_CONTROL_PRX_IE_MSK (0x2000)
+#define PHY_IRQ_CONTROL_PRX_IE_OFST (13)
+#define PHY_IRQ_CONTROL_RXER_IE_MSK (0x4000)
+#define PHY_IRQ_CONTROL_RXER_IE_OFST (14)
+#define PHY_IRQ_CONTROL_JABBER_IE_MSK (0x8000)
+#define PHY_IRQ_CONTROL_JABBER_IE_OFST (15)
+
+#define PHY_DIAGNOSTIC (18)
+#define PHY_DIAGNOSTIC_RX_LOCK_MSK (0x100)
+#define PHY_DIAGNOSTIC_RX_LOCK_OFST (8)
+#define PHY_DIAGNOSTIC_RX_PASS_MSK (0x200)
+#define PHY_DIAGNOSTIC_RX_PASS_OFST (9)
+#define PHY_DIAGNOSTIC_RATE_MSK (0x400)
+#define PHY_DIAGNOSTIC_RATE_OFST (10)
+#define PHY_DIAGNOSTIC_DPLX_MSK (0x800)
+#define PHY_DIAGNOSTIC_DPLX_OFST (11)
+#define PHY_DIAGNOSTIC_ANEGF_MSK (0x1000)
+#define PHY_DIAGNOSTIC_ANEGF_OFST (12)
+
+#endif /* __TDKPHY_H */
diff --git a/include/asm-arm/arch-epxa10db/time.h b/include/asm-arm/arch-epxa10db/time.h
index ae7223429..b18453053 100644
--- a/include/asm-arm/arch-epxa10db/time.h
+++ b/include/asm-arm/arch-epxa10db/time.h
@@ -42,20 +42,17 @@ static void excalibur_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
/*
* Set up timer interrupt, and return the current time in seconds.
*/
-extern __inline__ void setup_timer(void)
+void __init time_init(void)
{
-
-
timer_irq.handler = excalibur_timer_interrupt;
-
/*
* Make irqs happen for the system timer
*/
setup_arm_irq(IRQ_TIMER0, &timer_irq);
/* Start the timer */
- *TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/50);
+ *TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/200);
*TIMER0_PRESCALE(IO_ADDRESS(EXC_TIMER00_BASE))=1;
*TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))=TIMER0_CR_IE_MSK | TIMER0_CR_S_MSK;
}
diff --git a/include/asm-arm/arch-integrator/io.h b/include/asm-arm/arch-integrator/io.h
index 607147a34..c94b78957 100644
--- a/include/asm-arm/arch-integrator/io.h
+++ b/include/asm-arm/arch-integrator/io.h
@@ -26,20 +26,4 @@
#define __mem_pci(a) ((unsigned long)(a))
#define __mem_isa(a) (PCI_MEMORY_VADDR + (unsigned long)(a))
-/*
- * Generic virtual read/write
- */
-#define __arch_getw(a) (*(volatile unsigned short *)(a))
-#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
-
-/*
- * Validate the pci memory address for ioremap.
- */
-#define iomem_valid_addr(iomem,size) (1)
-
-/*
- * Convert PCI memory space to a CPU physical address
- */
-#define iomem_to_phys(iomem) (iomem)
-
#endif
diff --git a/include/asm-arm/arch-integrator/time.h b/include/asm-arm/arch-integrator/time.h
index 878ed34e2..40b48370c 100644
--- a/include/asm-arm/arch-integrator/time.h
+++ b/include/asm-arm/arch-integrator/time.h
@@ -113,7 +113,7 @@ static void integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *re
/*
* Set up timer interrupt, and return the current time in seconds.
*/
-static inline void setup_timer(void)
+void __init time_init(void)
{
volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
diff --git a/include/asm-arm/arch-iop310/dma.h b/include/asm-arm/arch-iop310/dma.h
new file mode 100644
index 000000000..b7086571d
--- /dev/null
+++ b/include/asm-arm/arch-iop310/dma.h
@@ -0,0 +1,109 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/dma.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _IOP310_DMA_H_
+#define _IOP310_DMA_H_
+
+/* 2 DMA on primary PCI and 1 on secondary for 80310 */
+#define MAX_IOP310_DMA_CHANNEL 3
+#define MAX_DMA_DESC 64 /*128 */
+
+/*
+ * Make the generic DMA bits go away since we don't use it
+ */
+#define MAX_DMA_CHANNELS 0
+
+#define MAX_DMA_ADDRESS 0xffffffff
+
+#define IOP310_DMA_P0 0
+#define IOP310_DMA_P1 1
+#define IOP310_DMA_S0 2
+
+#define DMA_MOD_READ 0x0001
+#define DMA_MOD_WRITE 0x0002
+#define DMA_MOD_CACHED 0x0004
+#define DMA_MOD_NONCACHED 0x0008
+
+
+#define DMA_DESC_DONE 0x0010
+#define DMA_INCOMPLETE 0x0020
+#define DMA_HOLD 0x0040
+#define DMA_END_CHAIN 0x0080
+#define DMA_COMPLETE 0x0100
+#define DMA_NOTIFY 0x0200
+#define DMA_NEW_HEAD 0x0400
+
+#define DMA_USER_MASK (DMA_NOTIFY | DMA_INCOMPLETE | \
+ DMA_HOLD | DMA_COMPLETE)
+
+#define DMA_DCR_DAC 0x00000020 /* Dual Addr Cycle Enab */
+#define DMA_DCR_IE 0x00000010 /* Interrupt Enable */
+#define DMA_DCR_PCI_IOR 0x00000002 /* I/O Read */
+#define DMA_DCR_PCI_IOW 0x00000003 /* I/O Write */
+#define DMA_DCR_PCI_MR 0x00000006 /* Memory Read */
+#define DMA_DCR_PCI_MW 0x00000007 /* Memory Write */
+#define DMA_DCR_PCI_CR 0x0000000A /* Configuration Read */
+#define DMA_DCR_PCI_CW 0x0000000B /* Configuration Write */
+#define DMA_DCR_PCI_MRM 0x0000000C /* Memory Read Multiple */
+#define DMA_DCR_PCI_MRL 0x0000000E /* Memory Read Line */
+#define DMA_DCR_PCI_MWI 0x0000000F /* Mem Write and Inval */
+
+#define DMA_USER_CMD_IE 0x00000001 /* user request int */
+#define DMA_USER_END_CHAIN 0x00000002 /* end of sgl chain flag */
+
+/* ATU defines */
+#define IOP310_ATUCR_PRIM_OUT_ENAB /* Configuration */ 0x00000002
+#define IOP310_ATUCR_DIR_ADDR_ENAB /* Configuration */ 0x00000080
+
+
+typedef void (*dma_callback_t) (void *buf_context);
+/*
+ * DMA Descriptor
+ */
+typedef struct _dma_desc
+{
+ u32 NDAR; /* next descriptor adress */
+ u32 PDAR; /* PCI address */
+ u32 PUADR; /* upper PCI address */
+ u32 LADR; /* local address */
+ u32 BC; /* byte count */
+ u32 DC; /* descriptor control */
+} dma_desc_t;
+
+typedef struct _dma_sgl
+{
+ dma_desc_t dma_desc; /* DMA descriptor pointer */
+ u32 status; /* descriptor status */
+ void *data; /* local virt */
+ struct _dma_sgl *next; /* next descriptor */
+} dma_sgl_t;
+
+/* dma sgl head */
+typedef struct _dma_head
+{
+ u32 total; /* total elements in SGL */
+ u32 status; /* status of sgl */
+ u32 mode; /* read or write mode */
+ dma_sgl_t *list; /* pointer to list */
+ dma_callback_t callback; /* callback function */
+} dma_head_t;
+
+/* function prototypes */
+int dma_request(dmach_t, const char *);
+int dma_queue_buffer(dmach_t, dma_head_t *);
+int dma_suspend(dmach_t);
+int dma_resume(dmach_t);
+int dma_flush_all(dmach_t);
+void dma_free(dmach_t);
+void dma_set_irq_threshold(dmach_t, int);
+dma_sgl_t *dma_get_buffer(dmach_t, int);
+void dma_return_buffer(dmach_t, dma_sgl_t *);
+
+#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-iop310/hardware.h b/include/asm-arm/arch-iop310/hardware.h
new file mode 100644
index 000000000..4fb2bcbb1
--- /dev/null
+++ b/include/asm-arm/arch-iop310/hardware.h
@@ -0,0 +1,38 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/hardware.h
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+
+/*
+ * Note about PCI IO space mappings
+ *
+ * To make IO space accesses efficient, we store virtual addresses in
+ * the IO resources.
+ *
+ * The PCI IO space is located at virtual 0xfe000000 from physical
+ * 0x90000000. The PCI BARs must be programmed with physical addresses,
+ * but when we read them, we convert them to virtual addresses. See
+ * arch/arm/mach-iop310/iop310-pci.c
+ */
+
+#define pcibios_assign_all_busses() 1
+
+/*
+ * these are the values for the secondary PCI bus on the 80312 chip. I will
+ * have to do some fixup in the bus/dev fixup code
+ */
+#define PCIBIOS_MIN_IO 0
+#define PCIBIOS_MIN_MEM 0x88000000
+
+// Generic chipset bits
+#include "iop310.h"
+
+// Board specific
+#if defined(CONFIG_ARCH_IQ80310)
+#include "iq80310.h"
+#endif
+
+#endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-iop310/ide.h b/include/asm-arm/arch-iop310/ide.h
new file mode 100644
index 000000000..e0a6dec82
--- /dev/null
+++ b/include/asm-arm/arch-iop310/ide.h
@@ -0,0 +1,51 @@
+/*
+ * include/asm-arm/arch-iop310/ide.h
+ *
+ * Generic IDE functions for IOP310 systems
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 09/26/2001 - Sharon Baartmans
+ * Fixed so it actually works.
+ */
+
+#ifndef _ASM_ARCH_IDE_H_
+#define _ASM_ARCH_IDE_H_
+
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
+{
+ ide_ioreg_t reg;
+ int i;
+ int regincr = 1;
+
+ memset(hw, 0, sizeof(*hw));
+
+ reg = (ide_ioreg_t)data_port;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg;
+ reg += regincr;
+ }
+
+ hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
+
+ if (irq) *irq = 0;
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
+ /* There are no standard ports */
+}
+
+#endif
diff --git a/include/asm-arm/arch-iop310/io.h b/include/asm-arm/arch-iop310/io.h
new file mode 100644
index 000000000..6b5c92936
--- /dev/null
+++ b/include/asm-arm/arch-iop310/io.h
@@ -0,0 +1,20 @@
+/*
+ * linux/include/asm-arm/arch-iop310/io.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(p) ((p))
+#define __mem_pci(a) ((unsigned long)(a))
+#define __mem_isa(a) ((unsigned long)(a))
+
+#endif
diff --git a/include/asm-arm/arch-iop310/iop310.h b/include/asm-arm/arch-iop310/iop310.h
new file mode 100644
index 000000000..d2445fdf7
--- /dev/null
+++ b/include/asm-arm/arch-iop310/iop310.h
@@ -0,0 +1,247 @@
+/*
+ * linux/include/asm/arch-iop310/iop310.h
+ *
+ * Intel IOP310 Compainion Chip definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _IOP310_HW_H_
+#define _IOP310_HW_H_
+
+/*
+ * IOP310 I/O and Mem space regions for PCI autoconfiguration
+ */
+#define IOP310_PCISEC_LOWER_IO 0x90010000
+#define IOP310_PCISEC_UPPER_IO 0x9001ffff
+#define IOP310_PCISEC_LOWER_MEM 0x88000000
+#define IOP310_PCISEC_UPPER_MEM 0x8bffffff
+
+#define IOP310_PCIPRI_LOWER_IO 0x90000000
+#define IOP310_PCIPRI_UPPER_IO 0x9000ffff
+#define IOP310_PCIPRI_LOWER_MEM 0x80000000
+#define IOP310_PCIPRI_UPPER_MEM 0x83ffffff
+
+#define IOP310_PCI_WINDOW_SIZE 64 * 0x100000
+
+/*
+ * IOP310 chipset registers
+ */
+#define IOP310_VIRT_MEM_BASE 0xe8001000 /* chip virtual mem address*/
+#define IOP310_PHY_MEM_BASE 0x00001000 /* chip physical memory address */
+#define IOP310_REG_ADDR(reg) (IOP310_VIRT_MEM_BASE | IOP310_PHY_MEM_BASE | (reg))
+
+/* PCI-to-PCI Bridge Unit 0x00001000 through 0x000010FF */
+#define IOP310_VIDR (volatile u16 *)IOP310_REG_ADDR(0x00001000)
+#define IOP310_DIDR (volatile u16 *)IOP310_REG_ADDR(0x00001002)
+#define IOP310_PCR (volatile u16 *)IOP310_REG_ADDR(0x00001004)
+#define IOP310_PSR (volatile u16 *)IOP310_REG_ADDR(0x00001006)
+#define IOP310_RIDR (volatile u8 *)IOP310_REG_ADDR(0x00001008)
+#define IOP310_CCR (volatile u32 *)IOP310_REG_ADDR(0x00001009)
+#define IOP310_CLSR (volatile u8 *)IOP310_REG_ADDR(0x0000100C)
+#define IOP310_PLTR (volatile u8 *)IOP310_REG_ADDR(0x0000100D)
+#define IOP310_HTR (volatile u8 *)IOP310_REG_ADDR(0x0000100E)
+/* Reserved 0x0000100F through 0x00001017 */
+#define IOP310_PBNR (volatile u8 *)IOP310_REG_ADDR(0x00001018)
+#define IOP310_SBNR (volatile u8 *)IOP310_REG_ADDR(0x00001019)
+#define IOP310_SUBBNR (volatile u8 *)IOP310_REG_ADDR(0x0000101A)
+#define IOP310_SLTR (volatile u8 *)IOP310_REG_ADDR(0x0000101B)
+#define IOP310_IOBR (volatile u8 *)IOP310_REG_ADDR(0x0000101C)
+#define IOP310_IOLR (volatile u8 *)IOP310_REG_ADDR(0x0000101D)
+#define IOP310_SSR (volatile u16 *)IOP310_REG_ADDR(0x0000101E)
+#define IOP310_MBR (volatile u16 *)IOP310_REG_ADDR(0x00001020)
+#define IOP310_MLR (volatile u16 *)IOP310_REG_ADDR(0x00001022)
+#define IOP310_PMBR (volatile u16 *)IOP310_REG_ADDR(0x00001024)
+#define IOP310_PMLR (volatile u16 *)IOP310_REG_ADDR(0x00001026)
+/* Reserved 0x00001028 through 0x00001033 */
+#define IOP310_CAPR (volatile u8 *)IOP310_REG_ADDR(0x00001034)
+/* Reserved 0x00001035 through 0x0000103D */
+#define IOP310_BCR (volatile u16 *)IOP310_REG_ADDR(0x0000103E)
+#define IOP310_EBCR (volatile u16 *)IOP310_REG_ADDR(0x00001040)
+#define IOP310_SISR (volatile u16 *)IOP310_REG_ADDR(0x00001042)
+#define IOP310_PBISR (volatile u32 *)IOP310_REG_ADDR(0x00001044)
+#define IOP310_SBISR (volatile u32 *)IOP310_REG_ADDR(0x00001048)
+#define IOP310_SACR (volatile u32 *)IOP310_REG_ADDR(0x0000104C)
+#define IOP310_PIRSR (volatile u32 *)IOP310_REG_ADDR(0x00001050)
+#define IOP310_SIOBR (volatile u8 *)IOP310_REG_ADDR(0x00001054)
+#define IOP310_SIOLR (volatile u8 *)IOP310_REG_ADDR(0x00001055)
+#define IOP310_SCDR (volatile u8 *)IOP310_REG_ADDR(0x00001056)
+
+#define IOP310_SMBR (volatile u16 *)IOP310_REG_ADDR(0x00001058)
+#define IOP310_SMLR (volatile u16 *)IOP310_REG_ADDR(0x0000105A)
+#define IOP310_SDER (volatile u16 *)IOP310_REG_ADDR(0x0000105C)
+#define IOP310_QCR (volatile u16 *)IOP310_REG_ADDR(0x0000105E)
+#define IOP310_CAPID (volatile u8 *)IOP310_REG_ADDR(0x00001068)
+#define IOP310_NIPTR (volatile u8 *)IOP310_REG_ADDR(0x00001069)
+#define IOP310_PMCR (volatile u16 *)IOP310_REG_ADDR(0x0000106A)
+#define IOP310_PMCSR (volatile u16 *)IOP310_REG_ADDR(0x0000106C)
+#define IOP310_PMCSRBSE (volatile u8 *)IOP310_REG_ADDR(0x0000106E)
+/* Reserved 0x00001064 through 0x000010FFH */
+
+/* Performance monitoring unit 0x00001100 through 0x000011FF*/
+#define IOP310_PMONGTMR (volatile u32 *)IOP310_REG_ADDR(0x00001100)
+#define IOP310_PMONESR (volatile u32 *)IOP310_REG_ADDR(0x00001104)
+#define IOP310_PMONEMISR (volatile u32 *)IOP310_REG_ADDR(0x00001108)
+#define IOP310_PMONGTSR (volatile u32 *)IOP310_REG_ADDR(0x00001110)
+#define IOP310_PMONPECR1 (volatile u32 *)IOP310_REG_ADDR(0x00001114)
+#define IOP310_PMONPECR2 (volatile u32 *)IOP310_REG_ADDR(0x00001118)
+#define IOP310_PMONPECR3 (volatile u32 *)IOP310_REG_ADDR(0x0000111C)
+#define IOP310_PMONPECR4 (volatile u32 *)IOP310_REG_ADDR(0x00001120)
+#define IOP310_PMONPECR5 (volatile u32 *)IOP310_REG_ADDR(0x00001124)
+#define IOP310_PMONPECR6 (volatile u32 *)IOP310_REG_ADDR(0x00001128)
+#define IOP310_PMONPECR7 (volatile u32 *)IOP310_REG_ADDR(0x0000112C)
+#define IOP310_PMONPECR8 (volatile u32 *)IOP310_REG_ADDR(0x00001130)
+#define IOP310_PMONPECR9 (volatile u32 *)IOP310_REG_ADDR(0x00001134)
+#define IOP310_PMONPECR10 (volatile u32 *)IOP310_REG_ADDR(0x00001138)
+#define IOP310_PMONPECR11 (volatile u32 *)IOP310_REG_ADDR(0x0000113C)
+#define IOP310_PMONPECR12 (volatile u32 *)IOP310_REG_ADDR(0x00001140)
+#define IOP310_PMONPECR13 (volatile u32 *)IOP310_REG_ADDR(0x00001144)
+#define IOP310_PMONPECR14 (volatile u32 *)IOP310_REG_ADDR(0x00001148)
+
+/* Address Translation Unit 0x00001200 through 0x000012FF */
+#define IOP310_ATUVID (volatile u16 *)IOP310_REG_ADDR(0x00001200)
+#define IOP310_ATUDID (volatile u16 *)IOP310_REG_ADDR(0x00001202)
+#define IOP310_PATUCMD (volatile u16 *)IOP310_REG_ADDR(0x00001204)
+#define IOP310_PATUSR (volatile u16 *)IOP310_REG_ADDR(0x00001206)
+#define IOP310_ATURID (volatile u8 *)IOP310_REG_ADDR(0x00001208)
+#define IOP310_ATUCCR (volatile u32 *)IOP310_REG_ADDR(0x00001209)
+#define IOP310_ATUCLSR (volatile u8 *)IOP310_REG_ADDR(0x0000120C)
+#define IOP310_ATULT (volatile u8 *)IOP310_REG_ADDR(0x0000120D)
+#define IOP310_ATUHTR (volatile u8 *)IOP310_REG_ADDR(0x0000120E)
+
+#define IOP310_PIABAR (volatile u32 *)IOP310_REG_ADDR(0x00001210)
+/* Reserved 0x00001214 through 0x0000122B */
+#define IOP310_ASVIR (volatile u16 *)IOP310_REG_ADDR(0x0000122C)
+#define IOP310_ASIR (volatile u16 *)IOP310_REG_ADDR(0x0000122E)
+#define IOP310_ERBAR (volatile u32 *)IOP310_REG_ADDR(0x00001230)
+#define IOP310_ATUCAPPTR (volatile u8 *)IOP310_REG_ADDR(0x00001234)
+/* Reserved 0x00001235 through 0x0000123B */
+#define IOP310_ATUILR (volatile u8 *)IOP310_REG_ADDR(0x0000123C)
+#define IOP310_ATUIPR (volatile u8 *)IOP310_REG_ADDR(0x0000123D)
+#define IOP310_ATUMGNT (volatile u8 *)IOP310_REG_ADDR(0x0000123E)
+#define IOP310_ATUMLAT (volatile u8 *)IOP310_REG_ADDR(0x0000123F)
+#define IOP310_PIALR (volatile u32 *)IOP310_REG_ADDR(0x00001240)
+#define IOP310_PIATVR (volatile u32 *)IOP310_REG_ADDR(0x00001244)
+#define IOP310_SIABAR (volatile u32 *)IOP310_REG_ADDR(0x00001248)
+#define IOP310_SIALR (volatile u32 *)IOP310_REG_ADDR(0x0000124C)
+#define IOP310_SIATVR (volatile u32 *)IOP310_REG_ADDR(0x00001250)
+#define IOP310_POMWVR (volatile u32 *)IOP310_REG_ADDR(0x00001254)
+/* Reserved 0x00001258 through 0x0000125B */
+#define IOP310_POIOWVR (volatile u32 *)IOP310_REG_ADDR(0x0000125C)
+#define IOP310_PODWVR (volatile u32 *)IOP310_REG_ADDR(0x00001260)
+#define IOP310_POUDR (volatile u32 *)IOP310_REG_ADDR(0x00001264)
+#define IOP310_SOMWVR (volatile u32 *)IOP310_REG_ADDR(0x00001268)
+#define IOP310_SOIOWVR (volatile u32 *)IOP310_REG_ADDR(0x0000126C)
+/* Reserved 0x00001270 through 0x00001273*/
+#define IOP310_ERLR (volatile u32 *)IOP310_REG_ADDR(0x00001274)
+#define IOP310_ERTVR (volatile u32 *)IOP310_REG_ADDR(0x00001278)
+/* Reserved 0x00001279 through 0x0000127C*/
+#define IOP310_ATUCAPID (volatile u8 *)IOP310_REG_ADDR(0x00001280)
+#define IOP310_ATUNIPTR (volatile u8 *)IOP310_REG_ADDR(0x00001281)
+#define IOP310_APMCR (volatile u16 *)IOP310_REG_ADDR(0x00001282)
+#define IOP310_APMCSR (volatile u16 *)IOP310_REG_ADDR(0x00001284)
+/* Reserved 0x00001286 through 0x00001287 */
+#define IOP310_ATUCR (volatile u32 *)IOP310_REG_ADDR(0x00001288)
+/* Reserved 0x00001289 through 0x0000128C*/
+#define IOP310_PATUISR (volatile u32 *)IOP310_REG_ADDR(0x00001290)
+#define IOP310_SATUISR (volatile u32 *)IOP310_REG_ADDR(0x00001294)
+#define IOP310_SATUCMD (volatile u16 *)IOP310_REG_ADDR(0x00001298)
+#define IOP310_SATUSR (volatile u16 *)IOP310_REG_ADDR(0x0000129A)
+#define IOP310_SODWVR (volatile u32 *)IOP310_REG_ADDR(0x0000129C)
+#define IOP310_SOUDR (volatile u32 *)IOP310_REG_ADDR(0x000012A0)
+#define IOP310_POCCAR (volatile u32 *)IOP310_REG_ADDR(0x000012A4)
+#define IOP310_SOCCAR (volatile u32 *)IOP310_REG_ADDR(0x000012A8)
+#define IOP310_POCCDR (volatile u32 *)IOP310_REG_ADDR(0x000012AC)
+#define IOP310_SOCCDR (volatile u32 *)IOP310_REG_ADDR(0x000012B0)
+#define IOP310_PAQCR (volatile u32 *)IOP310_REG_ADDR(0x000012B4)
+#define IOP310_SAQCR (volatile u32 *)IOP310_REG_ADDR(0x000012B8)
+#define IOP310_PATUIMR (volatile u32 *)IOP310_REG_ADDR(0x000012BC)
+#define IOP310_SATUIMR (volatile u32 *)IOP310_REG_ADDR(0x000012C0)
+/* Reserved 0x000012C4 through 0x000012FF */
+/* Messaging Unit 0x00001300 through 0x000013FF */
+#define IOP310_MUIMR0 (volatile u32 *)IOP310_REG_ADDR(0x00001310)
+#define IOP310_MUIMR1 (volatile u32 *)IOP310_REG_ADDR(0x00001314)
+#define IOP310_MUOMR0 (volatile u32 *)IOP310_REG_ADDR(0x00001318)
+#define IOP310_MUOMR1 (volatile u32 *)IOP310_REG_ADDR(0x0000131C)
+#define IOP310_MUIDR (volatile u32 *)IOP310_REG_ADDR(0x00001320)
+#define IOP310_MUIISR (volatile u32 *)IOP310_REG_ADDR(0x00001324)
+#define IOP310_MUIIMR (volatile u32 *)IOP310_REG_ADDR(0x00001328)
+#define IOP310_MUODR (volatile u32 *)IOP310_REG_ADDR(0x0000132C)
+#define IOP310_MUOISR (volatile u32 *)IOP310_REG_ADDR(0x00001330)
+#define IOP310_MUOIMR (volatile u32 *)IOP310_REG_ADDR(0x00001334)
+#define IOP310_MUMUCR (volatile u32 *)IOP310_REG_ADDR(0x00001350)
+#define IOP310_MUQBAR (volatile u32 *)IOP310_REG_ADDR(0x00001354)
+#define IOP310_MUIFHPR (volatile u32 *)IOP310_REG_ADDR(0x00001360)
+#define IOP310_MUIFTPR (volatile u32 *)IOP310_REG_ADDR(0x00001364)
+#define IOP310_MUIPHPR (volatile u32 *)IOP310_REG_ADDR(0x00001368)
+#define IOP310_MUIPTPR (volatile u32 *)IOP310_REG_ADDR(0x0000136C)
+#define IOP310_MUOFHPR (volatile u32 *)IOP310_REG_ADDR(0x00001370)
+#define IOP310_MUOFTPR (volatile u32 *)IOP310_REG_ADDR(0x00001374)
+#define IOP310_MUOPHPR (volatile u32 *)IOP310_REG_ADDR(0x00001378)
+#define IOP310_MUOPTPR (volatile u32 *)IOP310_REG_ADDR(0x0000137C)
+#define IOP310_MUIAR (volatile u32 *)IOP310_REG_ADDR(0x00001380)
+/* DMA Controller 0x00001400 through 0x000014FF */
+#define IOP310_DMA0CCR (volatile u32 *)IOP310_REG_ADDR(0x00001400)
+#define IOP310_DMA0CSR (volatile u32 *)IOP310_REG_ADDR(0x00001404)
+/* Reserved 0x001408 through 0x00140B */
+#define IOP310_DMA0DAR (volatile u32 *)IOP310_REG_ADDR(0x0000140C)
+#define IOP310_DMA0NDAR (volatile u32 *)IOP310_REG_ADDR(0x00001410)
+#define IOP310_DMA0PADR (volatile u32 *)IOP310_REG_ADDR(0x00001414)
+#define IOP310_DMA0PUADR (volatile u32 *)IOP310_REG_ADDR(0x00001418)
+#define IOP310_DMA0LADR (volatile u32 *)IOP310_REG_ADDR(0x0000141C)
+#define IOP310_DMA0BCR (volatile u32 *)IOP310_REG_ADDR(0x00001420)
+#define IOP310_DMA0DCR (volatile u32 *)IOP310_REG_ADDR(0x00001424)
+/* Reserved 0x00001428 through 0x0000143F */
+#define IOP310_DMA1CCR (volatile u32 *)IOP310_REG_ADDR(0x00001440)
+#define IOP310_DMA1CSR (volatile u32 *)IOP310_REG_ADDR(0x00001444)
+/* Reserved 0x00001448 through 0x0000144B */
+#define IOP310_DMA1DAR (volatile u32 *)IOP310_REG_ADDR(0x0000144C)
+#define IOP310_DMA1NDAR (volatile u32 *)IOP310_REG_ADDR(0x00001450)
+#define IOP310_DMA1PADR (volatile u32 *)IOP310_REG_ADDR(0x00001454)
+#define IOP310_DMA1PUADR (volatile u32 *)IOP310_REG_ADDR(0x00001458)
+#define IOP310_DMA1LADR (volatile u32 *)IOP310_REG_ADDR(0x0000145C)
+#define IOP310_DMA1BCR (volatile u32 *)IOP310_REG_ADDR(0x00001460)
+#define IOP310_DMA1DCR (volatile u32 *)IOP310_REG_ADDR(0x00001464)
+/* Reserved 0x00001468 through 0x0000147F */
+#define IOP310_DMA2CCR (volatile u32 *)IOP310_REG_ADDR(0x00001480)
+#define IOP310_DMA2CSR (volatile u32 *)IOP310_REG_ADDR(0x00001484)
+/* Reserved 0x00001488 through 0x0000148B */
+#define IOP310_DMA2DAR (volatile u32 *)IOP310_REG_ADDR(0x0000148C)
+#define IOP310_DMA2NDAR (volatile u32 *)IOP310_REG_ADDR(0x00001490)
+#define IOP310_DMA2PADR (volatile u32 *)IOP310_REG_ADDR(0x00001494)
+#define IOP310_DMA2PUADR (volatile u32 *)IOP310_REG_ADDR(0x00001498)
+#define IOP310_DMA2LADR (volatile u32 *)IOP310_REG_ADDR(0x0000149C)
+#define IOP310_DMA2BCR (volatile u32 *)IOP310_REG_ADDR(0x000014A0)
+#define IOP310_DMA2DCR (volatile u32 *)IOP310_REG_ADDR(0x000014A4)
+
+/* Memory controller 0x00001500 through 0x0015FF */
+
+/* core interface unit 0x00001640 - 0x0000167F */
+#define IOP310_CIUISR (volatile u32 *)IOP310_REG_ADDR(0x00001644)
+
+/* PCI and Peripheral Interrupt Controller 0x00001700 - 0x0000171B */
+#define IOP310_IRQISR (volatile u32 *)IOP310_REG_ADDR(0x00001700)
+#define IOP310_FIQ2ISR (volatile u32 *)IOP310_REG_ADDR(0x00001704)
+#define IOP310_FIQ1ISR (volatile u32 *)IOP310_REG_ADDR(0x00001708)
+#define IOP310_PDIDR (volatile u32 *)IOP310_REG_ADDR(0x00001710)
+
+/* AAU registers. DJ 0x00001800 - 0x00001838 */
+#define IOP310_AAUACR (volatile u32 *)IOP310_REG_ADDR(0x00001800)
+#define IOP310_AAUASR (volatile u32 *)IOP310_REG_ADDR(0x00001804)
+#define IOP310_AAUADAR (volatile u32 *)IOP310_REG_ADDR(0x00001808)
+#define IOP310_AAUANDAR (volatile u32 *)IOP310_REG_ADDR(0x0000180C)
+#define IOP310_AAUSAR1 (volatile u32 *)IOP310_REG_ADDR(0x00001810)
+#define IOP310_AAUSAR2 (volatile u32 *)IOP310_REG_ADDR(0x00001814)
+#define IOP310_AAUSAR3 (volatile u32 *)IOP310_REG_ADDR(0x00001818)
+#define IOP310_AAUSAR4 (volatile u32 *)IOP310_REG_ADDR(0x0000181C)
+#define IOP310_AAUDAR (volatile u32 *)IOP310_REG_ADDR(0x00001820)
+#define IOP310_AAUABCR (volatile u32 *)IOP310_REG_ADDR(0x00001824)
+#define IOP310_AAUADCR (volatile u32 *)IOP310_REG_ADDR(0x00001828)
+#define IOP310_AAUSAR5 (volatile u32 *)IOP310_REG_ADDR(0x0000182C)
+#define IOP310_AAUSAR6 (volatile u32 *)IOP310_REG_ADDR(0x00001830)
+#define IOP310_AAUSAR7 (volatile u32 *)IOP310_REG_ADDR(0x00001834)
+#define IOP310_AAUSAR8 (volatile u32 *)IOP310_REG_ADDR(0x00001838)
+
+#endif // _IOP310_HW_H_
diff --git a/include/asm-arm/arch-iop310/iq80310.h b/include/asm-arm/arch-iop310/iq80310.h
new file mode 100644
index 000000000..85dbda84c
--- /dev/null
+++ b/include/asm-arm/arch-iop310/iq80310.h
@@ -0,0 +1,30 @@
+/*
+ * linux/include/asm/arch-iop80310/iq80310.h
+ *
+ * Intel IQ-80310 evaluation board registers
+ */
+
+#ifndef _IQ80310_H_
+#define _IQ80310_H_
+
+#define IQ80310_RAMBASE 0xa0000000
+#define IQ80310_UART1 0xfe800000 /* UART #1 */
+#define IQ80310_UART2 0xfe810000 /* UART #2 */
+#define IQ80310_INT_STAT 0xfe820000 /* Interrupt (XINT3#) Status */
+#define IQ80310_BOARD_REV 0xfe830000 /* Board revision register */
+#define IQ80310_CPLD_REV 0xfe840000 /* CPLD revision register */
+#define IQ80310_7SEG_1 0xfe840000 /* 7-Segment MSB */
+#define IQ80310_7SEG_0 0xfe850000 /* 7-Segment LSB (WO) */
+#define IQ80310_PCI_INT_STAT 0xfe850000 /* PCI Interrupt Status */
+#define IQ80310_INT_MASK 0xfe860000 /* Interrupt (XINT3#) Mask */
+#define IQ80310_BACKPLANE 0xfe870000 /* Backplane Detect */
+#define IQ80310_TIMER_LA0 0xfe880000 /* Timer LA0 */
+#define IQ80310_TIMER_LA1 0xfe890000 /* Timer LA1 */
+#define IQ80310_TIMER_LA2 0xfe8a0000 /* Timer LA2 */
+#define IQ80310_TIMER_LA3 0xfe8b0000 /* Timer LA3 */
+#define IQ80310_TIMER_EN 0xfe8c0000 /* Timer Enable */
+#define IQ80310_ROTARY_SW 0xfe8d0000 /* Rotary Switch */
+#define IQ80310_JTAG 0xfe8e0000 /* JTAG Port Access */
+#define IQ80310_BATT_STAT 0xfe8f0000 /* Battery Status */
+
+#endif // _IQ80310_H_
diff --git a/include/asm-arm/arch-iop310/irq.h b/include/asm-arm/arch-iop310/irq.h
new file mode 100644
index 000000000..33c0866c1
--- /dev/null
+++ b/include/asm-arm/arch-iop310/irq.h
@@ -0,0 +1,13 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/irq.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define fixup_irq(irq) (irq)
+
+
diff --git a/include/asm-arm/arch-iop310/irqs.h b/include/asm-arm/arch-iop310/irqs.h
new file mode 100644
index 000000000..6b671853c
--- /dev/null
+++ b/include/asm-arm/arch-iop310/irqs.h
@@ -0,0 +1,80 @@
+/*
+ * linux/include/asm-arm/arch-iop310/irqs.h
+ *
+ * Author: Nicolas Pitre
+ * Copyright: (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 06/13/01: Added 80310 on-chip interrupt sources <dsaxena@mvista.com>
+ *
+ */
+
+
+/*
+ * XS80200 specific IRQs
+ */
+#define IRQ_XS80200_BCU 0 /* Bus Control Unit */
+#define IRQ_XS80200_PMU 1 /* Performance Monitoring Unit */
+#define IRQ_XS80200_EXTIRQ 2 /* external IRQ signal */
+#define IRQ_XS80200_EXTFIQ 3 /* external IRQ signal */
+
+#define NR_XS80200_IRQS 4
+
+#define XSCALE_PMU_IRQ IRQ_XS80200_PMU
+
+/*
+ * IOP80310 chipset interrupts
+ */
+#define IOP310_IRQ_OFS NR_XS80200_IRQS
+#define IOP310_IRQ(x) (IOP310_IRQ_OFS + (x))
+
+/*
+ * On FIQ1ISR register
+ */
+#define IRQ_IOP310_DMA0 IOP310_IRQ(0) /* DMA Channel 0 */
+#define IRQ_IOP310_DMA1 IOP310_IRQ(1) /* DMA Channel 1 */
+#define IRQ_IOP310_DMA2 IOP310_IRQ(2) /* DMA Channel 2 */
+#define IRQ_IOP310_PMON IOP310_IRQ(3) /* Bus performance Unit */
+#define IRQ_IOP310_AAU IOP310_IRQ(4) /* Application Accelator Unit */
+
+/*
+ * On FIQ2ISR register
+ */
+#define IRQ_IOP310_I2C IOP310_IRQ(5) /* I2C unit */
+#define IRQ_IOP310_MU IOP310_IRQ(6) /* messaging unit */
+
+#define NR_IOP310_IRQS (IOP310_IRQ(6) + 1)
+
+#define NR_IRQS NR_IOP310_IRQS
+
+
+/*
+ * Interrupts available on the Cyclone IQ80310 board
+ */
+#ifdef CONFIG_ARCH_IQ80310
+
+#define IQ80310_IRQ_OFS NR_IOP310_IRQS
+#define IQ80310_IRQ(y) ((IQ80310_IRQ_OFS) + (y))
+
+#define IRQ_IQ80310_TIMER IQ80310_IRQ(0) /* Timer Interrupt */
+#define IRQ_IQ80310_I82559 IQ80310_IRQ(1) /* I82559 Ethernet Interrupt */
+#define IRQ_IQ80310_UART1 IQ80310_IRQ(2) /* UART1 Interrupt */
+#define IRQ_IQ80310_UART2 IQ80310_IRQ(3) /* UART2 Interrupt */
+#define IRQ_IQ80310_INTD IQ80310_IRQ(4) /* PCI INTD */
+
+
+/*
+ * ONLY AVAILABLE ON REV F OR NEWER BOARDS!
+ */
+#define IRQ_IQ80310_INTA IQ80310_IRQ(5) /* PCI INTA */
+#define IRQ_IQ80310_INTB IQ80310_IRQ(6) /* PCI INTB */
+#define IRQ_IQ80310_INTC IQ80310_IRQ(7) /* PCI INTC */
+
+#undef NR_IRQS
+#define NR_IRQS (IQ80310_IRQ(7) + 1)
+
+#endif // CONFIG_ARCH_IQ80310
+
diff --git a/include/asm-arm/arch-iop310/memory.h b/include/asm-arm/arch-iop310/memory.h
new file mode 100644
index 000000000..64c078981
--- /dev/null
+++ b/include/asm-arm/arch-iop310/memory.h
@@ -0,0 +1,58 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/memory.h
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+#define TASK_SIZE_26 (0x04000000UL)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET (0xa0000000UL)
+
+/*
+ * physical vs virtual ram conversion
+ */
+#define __virt_to_phys__is_a_macro
+#define __phys_to_virt__is_a_macro
+#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ * address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ * to an address that the kernel can use.
+ */
+#define __virt_to_bus__is_a_macro
+#define __bus_to_virt__is_a_macro
+#define __virt_to_bus(x) (((__virt_to_phys(x)) & ~(*IOP310_SIATVR)) | ((*IOP310_SIABAR) & 0xfffffff0))
+#define __bus_to_virt(x) (__phys_to_virt(((x) & ~(*IOP310_SIALR)) | ( *IOP310_SIATVR)))
+
+#define PHYS_TO_NID(x) 0
+
+/* boot mem allocate global pointer for MU circular queues QBAR */
+#ifdef CONFIG_IOP310_MU
+extern void *mu_mem;
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-iop310/param.h b/include/asm-arm/arch-iop310/param.h
new file mode 100644
index 000000000..dded3a1de
--- /dev/null
+++ b/include/asm-arm/arch-iop310/param.h
@@ -0,0 +1,3 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/param.h
+ */
diff --git a/include/asm-arm/arch-iop310/pmon.h b/include/asm-arm/arch-iop310/pmon.h
new file mode 100644
index 000000000..7f93c1054
--- /dev/null
+++ b/include/asm-arm/arch-iop310/pmon.h
@@ -0,0 +1,50 @@
+/*
+ * Definitions for XScale 80312 PMON
+ * (C) 2001 Intel Corporation
+ * Author: Chen Chen(chen.chen@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _IOP310_PMON_H_
+#define _IOP310_PMON_H_
+
+/*
+ * Different modes for Event Select Register for intel 80312
+ */
+
+#define IOP310_PMON_MODE0 0x00000000
+#define IOP310_PMON_MODE1 0x00000001
+#define IOP310_PMON_MODE2 0x00000002
+#define IOP310_PMON_MODE3 0x00000003
+#define IOP310_PMON_MODE4 0x00000004
+#define IOP310_PMON_MODE5 0x00000005
+#define IOP310_PMON_MODE6 0x00000006
+#define IOP310_PMON_MODE7 0x00000007
+
+typedef struct _iop310_pmon_result
+{
+ u32 timestamp; /* Global Time Stamp Register */
+ u32 timestamp_overflow; /* Time Stamp overflow count */
+ u32 event_count[14]; /* Programmable Event Counter
+ Registers 1-14 */
+ u32 event_overflow[14]; /* Overflow counter for PECR1-14 */
+} iop310_pmon_res_t;
+
+/* function prototypes */
+
+/* Claim IQ80312 PMON for usage */
+int iop310_pmon_claim(void);
+
+/* Start IQ80312 PMON */
+int iop310_pmon_start(int, int);
+
+/* Stop Performance Monitor Unit */
+int iop310_pmon_stop(iop310_pmon_res_t *);
+
+/* Release IQ80312 PMON */
+int iop310_pmon_release(int);
+
+#endif
diff --git a/include/asm-arm/arch-iop310/serial.h b/include/asm-arm/arch-iop310/serial.h
new file mode 100644
index 000000000..b25a5e5e9
--- /dev/null
+++ b/include/asm-arm/arch-iop310/serial.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-arm/arch-iop310/serial.h
+ */
+
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+/* Standard COM flags */
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+#ifdef CONFIG_ARCH_IQ80310
+
+#define IRQ_UART1 IRQ_IQ80310_UART1
+#define IRQ_UART2 IRQ_IQ80310_UART2
+
+#define RS_TABLE_SIZE 2
+
+#define STD_SERIAL_PORT_DEFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, BASE_BAUD, 0xfe810000, IRQ_UART2, STD_COM_FLAGS }, /* ttyS0 */ \
+ { 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS } /* ttyS1 */
+
+#endif // CONFIG_ARCH_IQ80310
+
+
+#define EXTRA_SERIAL_PORT_DEFNS
+
diff --git a/include/asm-arm/arch-iop310/system.h b/include/asm-arm/arch-iop310/system.h
new file mode 100644
index 000000000..c5ba7427a
--- /dev/null
+++ b/include/asm-arm/arch-iop310/system.h
@@ -0,0 +1,30 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/system.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+static inline void arch_idle(void)
+{
+ if (!hlt_counter)
+ {
+ cpu_do_idle(0);
+ }
+}
+
+
+static inline void arch_reset(char mode)
+{
+ if ( 1 && mode == 's') {
+ /* Jump into ROM at address 0 */
+ cpu_reset(0);
+ } else {
+ /* No on-chip reset capability */
+ cpu_reset(0);
+ }
+}
+
diff --git a/include/asm-arm/arch-iop310/time.h b/include/asm-arm/arch-iop310/time.h
new file mode 100644
index 000000000..b58ac84f9
--- /dev/null
+++ b/include/asm-arm/arch-iop310/time.h
@@ -0,0 +1,12 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/time.h
+ *
+ * Author: Nicolas Pitre
+ * Copyright: (C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
diff --git a/include/asm-arm/arch-iop310/timex.h b/include/asm-arm/arch-iop310/timex.h
new file mode 100644
index 000000000..8a085715a
--- /dev/null
+++ b/include/asm-arm/arch-iop310/timex.h
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/timex.h
+ *
+ * IOP310 architecture timex specifications
+ */
+
+
+
+#ifdef CONFIG_ARCH_IQ80310
+
+#ifndef CONFIG_XSCALE_PMU_TIMER
+/* This is for the on-board timer */
+#define CLOCK_TICK_RATE 33000000 /* Underlying HZ */
+#else
+/* This is for the underlying xs80200 PMU clock. We run the core @ 733MHz */
+#define CLOCK_TICK_RATE 733000000
+#endif
+
+#else
+
+#error "No IOP310 timex information for this architecture"
+
+#endif
diff --git a/include/asm-arm/arch-iop310/uncompress.h b/include/asm-arm/arch-iop310/uncompress.h
new file mode 100644
index 000000000..40300833c
--- /dev/null
+++ b/include/asm-arm/arch-iop310/uncompress.h
@@ -0,0 +1,33 @@
+/*
+ * linux/include/asm-arm/arch-iop80310/uncompress.h
+ */
+
+#ifdef CONFIG_ARCH_IQ80310
+#define UART1_BASE ((volatile unsigned char *)0xfe800000)
+#define UART2_BASE ((volatile unsigned char *)0xfe810000)
+#endif
+
+static __inline__ void putc(char c)
+{
+ while ((UART2_BASE[5] & 0x60) != 0x60);
+ UART2_BASE[0] = c;
+}
+
+/*
+ * This does not append a newline
+ */
+static void puts(const char *s)
+{
+ while (*s) {
+ putc(*s);
+ if (*s == '\n')
+ putc('\r');
+ s++;
+ }
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop310/vmalloc.h b/include/asm-arm/arch-iop310/vmalloc.h
new file mode 100644
index 000000000..07c8ee703
--- /dev/null
+++ b/include/asm-arm/arch-iop310/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-arm/arch-iop310/vmalloc.h
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts. That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET (8*1024*1024)
+#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END (0xe8000000)
diff --git a/include/asm-arm/arch-l7200/io.h b/include/asm-arm/arch-l7200/io.h
index 50762b011..91dfdf3cc 100644
--- a/include/asm-arm/arch-l7200/io.h
+++ b/include/asm-arm/arch-l7200/io.h
@@ -73,6 +73,4 @@ static inline void __arch_putw(unsigned int value, unsigned long a)
#define outw(v,p) outw_t(v,p)
#define outl(v,p) outl_t(v,p)
-#define __arch_ioremap __ioremap
-
#endif
diff --git a/include/asm-arm/arch-l7200/irq.h b/include/asm-arm/arch-l7200/irq.h
index 7763e2150..c605a8c28 100644
--- a/include/asm-arm/arch-l7200/irq.h
+++ b/include/asm-arm/arch-l7200/irq.h
@@ -9,60 +9,4 @@
* 04-15-2000 RS Made dependent on hardware.h
* 05-05-2000 SJH Complete rewrite
*/
-
-#include <asm/arch/hardware.h>
-
-/*
- * IRQ base register
- */
-#define IRQ_BASE (IO_BASE_2 + 0x1000)
-
-/*
- * Normal IRQ registers
- */
-#define IRQ_STATUS (*(volatile unsigned long *) (IRQ_BASE + 0x000))
-#define IRQ_RAWSTATUS (*(volatile unsigned long *) (IRQ_BASE + 0x004))
-#define IRQ_ENABLE (*(volatile unsigned long *) (IRQ_BASE + 0x008))
-#define IRQ_ENABLECLEAR (*(volatile unsigned long *) (IRQ_BASE + 0x00c))
-#define IRQ_SOFT (*(volatile unsigned long *) (IRQ_BASE + 0x010))
-#define IRQ_SOURCESEL (*(volatile unsigned long *) (IRQ_BASE + 0x018))
-
-/*
- * Fast IRQ registers
- */
-#define FIQ_STATUS (*(volatile unsigned long *) (IRQ_BASE + 0x100))
-#define FIQ_RAWSTATUS (*(volatile unsigned long *) (IRQ_BASE + 0x104))
-#define FIQ_ENABLE (*(volatile unsigned long *) (IRQ_BASE + 0x108))
-#define FIQ_ENABLECLEAR (*(volatile unsigned long *) (IRQ_BASE + 0x10c))
-#define FIQ_SOFT (*(volatile unsigned long *) (IRQ_BASE + 0x110))
-#define FIQ_SOURCESEL (*(volatile unsigned long *) (IRQ_BASE + 0x118))
-
#define fixup_irq(x) (x)
-
-static void l7200_mask_irq(unsigned int irq)
-{
- IRQ_ENABLECLEAR = 1 << irq;
-}
-
-static void l7200_unmask_irq(unsigned int irq)
-{
- IRQ_ENABLE = 1 << irq;
-}
-
-static __inline__ void irq_init_irq(void)
-{
- int irq;
-
- IRQ_ENABLECLEAR = 0xffffffff; /* clear all interrupt enables */
- FIQ_ENABLECLEAR = 0xffffffff; /* clear all fast interrupt enables */
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
- irq_desc[irq].mask_ack = l7200_mask_irq;
- irq_desc[irq].mask = l7200_mask_irq;
- irq_desc[irq].unmask = l7200_unmask_irq;
- }
-
- init_FIQ();
-}
diff --git a/include/asm-arm/arch-l7200/keyboard.h b/include/asm-arm/arch-l7200/keyboard.h
index 5e41f270c..6628bd381 100644
--- a/include/asm-arm/arch-l7200/keyboard.h
+++ b/include/asm-arm/arch-l7200/keyboard.h
@@ -17,6 +17,8 @@
#include <asm/irq.h>
+#error This needs fixing --rmk
+
/*
* Layout of L7200 keyboard registers
*/
diff --git a/include/asm-arm/arch-l7200/time.h b/include/asm-arm/arch-l7200/time.h
index 6806aa7c4..27a872c63 100644
--- a/include/asm-arm/arch-l7200/time.h
+++ b/include/asm-arm/arch-l7200/time.h
@@ -52,7 +52,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* Set up RTC timer interrupt, and return the current time in seconds.
*/
-static inline void setup_timer(void)
+void __init time_init(void)
{
RTC_RTCC = 0; /* Clear interrupt */
diff --git a/include/asm-arm/arch-nexuspci/io.h b/include/asm-arm/arch-nexuspci/io.h
index 20a360744..8afa61e6a 100644
--- a/include/asm-arm/arch-nexuspci/io.h
+++ b/include/asm-arm/arch-nexuspci/io.h
@@ -37,12 +37,6 @@ static inline unsigned long ___mem_isa(unsigned long a)
#endif
/*
- * Generic virtual read/write
- */
-#define __arch_getw(a) (*(volatile unsigned short *)(a))
-#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
-
-/*
* ioremap support - validate a PCI memory address,
* and convert a PCI memory address to a physical
* address for the page tables.
@@ -51,4 +45,15 @@ static inline unsigned long ___mem_isa(unsigned long a)
((iomem) < 0x80000000 && (iomem) + (sz) <= 0x80000000)
#define iomem_to_phys(iomem) ((iomem) + PLX_MEM_START)
+#define __arch_ioremap(off,sz,nocache) \
+ ({ \
+ unsigned long _off = (off), _size = (sz); \
+ void *_ret = (void *)0; \
+ if (iomem_valid_addr(_off, _size)) \
+ _ret = __ioremap(iomem_to_phys(_off),_size,0); \
+ _ret; \
+ })
+
+#define __arch_iounmap __iounmap
+
#endif
diff --git a/include/asm-arm/arch-nexuspci/irq.h b/include/asm-arm/arch-nexuspci/irq.h
index 292ed47b8..4690e8843 100644
--- a/include/asm-arm/arch-nexuspci/irq.h
+++ b/include/asm-arm/arch-nexuspci/irq.h
@@ -10,60 +10,5 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
-#include <asm/io.h>
-
#define fixup_irq(x) (x)
-extern unsigned long soft_irq_mask;
-
-static const unsigned char irq_cmd[] =
-{
- INTCONT_IRQ_DUART,
- INTCONT_IRQ_PLX,
- INTCONT_IRQ_D,
- INTCONT_IRQ_C,
- INTCONT_IRQ_B,
- INTCONT_IRQ_A,
- INTCONT_IRQ_SYSERR
-};
-
-static void ftvpci_mask_irq(unsigned int irq)
-{
- __raw_writel(irq_cmd[irq], INTCONT_BASE);
- soft_irq_mask &= ~(1<<irq);
-}
-
-static void ftvpci_unmask_irq(unsigned int irq)
-{
- soft_irq_mask |= (1<<irq);
- __raw_writel(irq_cmd[irq] | 1, INTCONT_BASE);
-}
-
-static __inline__ void irq_init_irq(void)
-{
- unsigned int i;
-
- /* Mask all FIQs */
- __raw_writel(INTCONT_FIQ_PLX, INTCONT_BASE);
- __raw_writel(INTCONT_FIQ_D, INTCONT_BASE);
- __raw_writel(INTCONT_FIQ_C, INTCONT_BASE);
- __raw_writel(INTCONT_FIQ_B, INTCONT_BASE);
- __raw_writel(INTCONT_FIQ_A, INTCONT_BASE);
- __raw_writel(INTCONT_FIQ_SYSERR, INTCONT_BASE);
-
- /* Disable all interrupts initially. */
- for (i = 0; i < NR_IRQS; i++) {
- if (i >= FIRST_IRQ && i <= LAST_IRQ) {
- irq_desc[i].valid = 1;
- irq_desc[i].probe_ok = 1;
- irq_desc[i].mask_ack = ftvpci_mask_irq;
- irq_desc[i].mask = ftvpci_mask_irq;
- irq_desc[i].unmask = ftvpci_unmask_irq;
- ftvpci_mask_irq(i);
- } else {
- irq_desc[i].valid = 0;
- irq_desc[i].probe_ok = 0;
- }
- }
-}
diff --git a/include/asm-arm/arch-nexuspci/time.h b/include/asm-arm/arch-nexuspci/time.h
index 19eae054f..ba453c176 100644
--- a/include/asm-arm/arch-nexuspci/time.h
+++ b/include/asm-arm/arch-nexuspci/time.h
@@ -43,7 +43,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_timer(regs);
}
-static inline void setup_timer(void)
+void __init time_init(void)
{
int tick = 3686400 / 16 / 2 / 100;
diff --git a/include/asm-arm/arch-rpc/io.h b/include/asm-arm/arch-rpc/io.h
index 19def7bff..cb39453f5 100644
--- a/include/asm-arm/arch-rpc/io.h
+++ b/include/asm-arm/arch-rpc/io.h
@@ -241,4 +241,10 @@ DECLARE_IO(int,l,"")
/* the following macro is depreciated */
#define ioaddr(port) __ioaddr((port))
+#define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l)
+#define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l)
+
+#define outsb(p,d,l) __raw_writesb(__ioaddr(p),d,l)
+#define outsw(p,d,l) __raw_writesw(__ioaddr(p),d,l)
+
#endif
diff --git a/include/asm-arm/arch-rpc/irq.h b/include/asm-arm/arch-rpc/irq.h
index 93c2ffa7f..4446afbb2 100644
--- a/include/asm-arm/arch-rpc/irq.h
+++ b/include/asm-arm/arch-rpc/irq.h
@@ -11,142 +11,4 @@
* 10-10-1996 RMK Brought up to date with arch-sa110eval
* 22-08-1998 RMK Restructured IRQ routines
*/
-#include <asm/hardware/iomd.h>
-#include <asm/io.h>
-
#define fixup_irq(x) (x)
-
-static void rpc_mask_irq_ack_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- val = iomd_readb(IOMD_IRQMASKA);
- iomd_writeb(val & ~mask, IOMD_IRQMASKA);
- iomd_writeb(mask, IOMD_IRQCLRA);
-}
-
-static void rpc_mask_irq_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- val = iomd_readb(IOMD_IRQMASKA);
- iomd_writeb(val & ~mask, IOMD_IRQMASKA);
-}
-
-static void rpc_unmask_irq_a(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << irq;
- val = iomd_readb(IOMD_IRQMASKA);
- iomd_writeb(val | mask, IOMD_IRQMASKA);
-}
-
-static void rpc_mask_irq_b(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_IRQMASKB);
- iomd_writeb(val & ~mask, IOMD_IRQMASKB);
-}
-
-static void rpc_unmask_irq_b(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_IRQMASKB);
- iomd_writeb(val | mask, IOMD_IRQMASKB);
-}
-
-static void rpc_mask_irq_dma(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_DMAMASK);
- iomd_writeb(val & ~mask, IOMD_DMAMASK);
-}
-
-static void rpc_unmask_irq_dma(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_DMAMASK);
- iomd_writeb(val | mask, IOMD_DMAMASK);
-}
-
-static void rpc_mask_irq_fiq(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_FIQMASK);
- iomd_writeb(val & ~mask, IOMD_FIQMASK);
-}
-
-static void rpc_unmask_irq_fiq(unsigned int irq)
-{
- unsigned int val, mask;
-
- mask = 1 << (irq & 7);
- val = iomd_readb(IOMD_FIQMASK);
- iomd_writeb(val | mask, IOMD_FIQMASK);
-}
-
-static __inline__ void irq_init_irq(void)
-{
- int irq;
-
- iomd_writeb(0, IOMD_IRQMASKA);
- iomd_writeb(0, IOMD_IRQMASKB);
- iomd_writeb(0, IOMD_FIQMASK);
- iomd_writeb(0, IOMD_DMAMASK);
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- switch (irq) {
- case 0 ... 6:
- irq_desc[irq].probe_ok = 1;
- case 7:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = rpc_mask_irq_ack_a;
- irq_desc[irq].mask = rpc_mask_irq_a;
- irq_desc[irq].unmask = rpc_unmask_irq_a;
- break;
-
- case 9 ... 15:
- irq_desc[irq].probe_ok = 1;
- case 8:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = rpc_mask_irq_b;
- irq_desc[irq].mask = rpc_mask_irq_b;
- irq_desc[irq].unmask = rpc_unmask_irq_b;
- break;
-
- case 16 ... 19:
- case 21:
- irq_desc[irq].noautoenable = 1;
- case 20:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = rpc_mask_irq_dma;
- irq_desc[irq].mask = rpc_mask_irq_dma;
- irq_desc[irq].unmask = rpc_unmask_irq_dma;
- break;
-
- case 64 ... 71:
- irq_desc[irq].valid = 1;
- irq_desc[irq].mask_ack = rpc_mask_irq_fiq;
- irq_desc[irq].mask = rpc_mask_irq_fiq;
- irq_desc[irq].unmask = rpc_unmask_irq_fiq;
- break;
- }
- }
-
- irq_desc[IRQ_KEYBOARDTX].noautoenable = 1;
-
- init_FIQ();
-}
diff --git a/include/asm-arm/arch-rpc/time.h b/include/asm-arm/arch-rpc/time.h
index e564892a2..4fa255bc6 100644
--- a/include/asm-arm/arch-rpc/time.h
+++ b/include/asm-arm/arch-rpc/time.h
@@ -24,7 +24,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* Set up timer interrupt.
*/
-static inline void setup_timer(void)
+void __init time_init(void)
{
ioctime_init();
diff --git a/include/asm-arm/arch-sa1100/SA-1111.h b/include/asm-arm/arch-sa1100/SA-1111.h
index d25b59b56..c38f60915 100644
--- a/include/asm-arm/arch-sa1100/SA-1111.h
+++ b/include/asm-arm/arch-sa1100/SA-1111.h
@@ -1,647 +1,5 @@
/*
- * linux/include/asm/arch/SA-1111.h
- *
- * Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
- *
- * This file contains definitions for the SA-1111 Companion Chip.
- * (Structure and naming borrowed from SA-1101.h, by Peter Danielsson.)
- *
+ * Moved to new location
*/
-
-#ifndef _ASM_ARCH_SA1111
-#define _ASM_ARCH_SA1111
-
-#include <asm/arch/bitfield.h>
-
-/*
- * Macro that calculates real address for registers in the SA-1111
- */
-
-#define _SA1111( x ) ((x) + SA1111_BASE)
-
-/*
- * 26 bits of the SA-1110 address bus are available to the SA-1111.
- * Use these when feeding target addresses to the DMA engines.
- */
-
-#define SA1111_ADDR_WIDTH (26)
-#define SA1111_ADDR_MASK ((1<<SA1111_ADDR_WIDTH)-1)
-#define SA1111_DMA_ADDR(x) ((x)&SA1111_ADDR_MASK)
-
-/*
- * Don't ask the (SAC) DMA engines to move less than this amount.
- */
-
-#define SA1111_SAC_DMA_MIN_XFER (0x800)
-
-/*
- * SA1111 register definitions.
- */
-#define __CCREG(x) __REGP(SA1111_VBASE + (x))
-
-/* System Bus Interface (SBI)
- *
- * Registers
- * SKCR Control Register
- * SMCR Shared Memory Controller Register
- * SKID ID Register
- */
-
-#define _SBI_SKCR _SA1111(0x0000)
-#define _SBI_SMCR _SA1111(0x0004)
-#define _SBI_SKID _SA1111(0x0008)
-
-#if LANGUAGE == C
-
-#define SBI_SKCR __CCREG(0x0000)
-#define SBI_SMCR __CCREG(0x0004)
-#define SBI_SKID __CCREG(0x0008)
-
-#endif /* LANGUAGE == C */
-
-#define SKCR_PLL_BYPASS (1<<0)
-#define SKCR_RCLKEN (1<<1)
-#define SKCR_SLEEP (1<<2)
-#define SKCR_DOZE (1<<3)
-#define SKCR_VCO_OFF (1<<4)
-#define SKCR_SCANTSTEN (1<<5)
-#define SKCR_CLKTSTEN (1<<6)
-#define SKCR_RDYEN (1<<7)
-#define SKCR_SELAC (1<<8)
-#define SKCR_OPPC (1<<9)
-#define SKCR_PLLTSTEN (1<<10)
-#define SKCR_USBIOTSTEN (1<<11)
-/*
- * Don't believe the specs! Take them, throw them outside. Leave them
- * there for a week. Spit on them. Walk on them. Stamp on them.
- * Pour gasoline over them and finally burn them. Now think about coding.
- * - The October 1999 errata (278260-007) says its bit 13, 1 to enable.
- * - The Feb 2001 errata (278260-010) says that the previous errata
- * (278260-009) is wrong, and its bit actually 12, fixed in spec
- * 278242-003.
- * - The SA1111 manual (278242) says bit 12, but 0 to enable.
- * - Reality is bit 13, 1 to enable.
- * -- rmk
- */
-#define SKCR_OE_EN (1<<13)
-
-#define SMCR_DTIM (1<<0)
-#define SMCR_MBGE (1<<1)
-#define SMCR_DRAC_0 (1<<2)
-#define SMCR_DRAC_1 (1<<3)
-#define SMCR_DRAC_2 (1<<4)
-#define SMCR_DRAC Fld(3, 2)
-#define SMCR_CLAT (1<<5)
-
-#define SKID_SIREV_MASK (0x000000f0)
-#define SKID_MTREV_MASK (0x0000000f)
-#define SKID_ID_MASK (0xffffff00)
-#define SKID_SA1111_ID (0x690cc200)
-
-/*
- * System Controller
- *
- * Registers
- * SKPCR Power Control Register
- * SKCDR Clock Divider Register
- * SKAUD Audio Clock Divider Register
- * SKPMC PS/2 Mouse Clock Divider Register
- * SKPTC PS/2 Track Pad Clock Divider Register
- * SKPEN0 PWM0 Enable Register
- * SKPWM0 PWM0 Clock Register
- * SKPEN1 PWM1 Enable Register
- * SKPWM1 PWM1 Clock Register
- */
-
-#define _SKPCR _SA1111(0x0200)
-#define _SKCDR _SA1111(0x0204)
-#define _SKAUD _SA1111(0x0208)
-#define _SKPMC _SA1111(0x020c)
-#define _SKPTC _SA1111(0x0210)
-#define _SKPEN0 _SA1111(0x0214)
-#define _SKPWM0 _SA1111(0x0218)
-#define _SKPEN1 _SA1111(0x021c)
-#define _SKPWM1 _SA1111(0x0220)
-
-#if LANGUAGE == C
-
-#define SKPCR __CCREG(0x0200)
-#define SKCDR __CCREG(0x0204)
-#define SKAUD __CCREG(0x0208)
-#define SKPMC __CCREG(0x020c)
-#define SKPTC __CCREG(0x0210)
-#define SKPEN0 __CCREG(0x0214)
-#define SKPWM0 __CCREG(0x0218)
-#define SKPEN1 __CCREG(0x021c)
-#define SKPWM1 __CCREG(0x0220)
-
-#endif /* LANGUAGE == C */
-
-#define SKPCR_UCLKEN (1<<0)
-#define SKPCR_ACCLKEN (1<<1)
-#define SKPCR_I2SCLKEN (1<<2)
-#define SKPCR_L3CLKEN (1<<3)
-#define SKPCR_SCLKEN (1<<4)
-#define SKPCR_PMCLKEN (1<<5)
-#define SKPCR_PTCLKEN (1<<6)
-#define SKPCR_DCLKEN (1<<7)
-#define SKPCR_PWMCLKEN (1<<8)
-
-/*
- * USB Host controller
- */
-#define _USB_OHCI_OP_BASE _SA1111( 0x400 )
-#define _USB_STATUS _SA1111( 0x518 )
-#define _USB_RESET _SA1111( 0x51c )
-#define _USB_INTERRUPTEST _SA1111( 0x520 )
-
-#define _USB_EXTENT (_USB_INTERRUPTEST - _USB_OHCI_OP_BASE + 4)
-
-#if LANGUAGE == C
-
-#define USB_OHCI_OP_BASE __CCREG(0x0400)
-#define USB_STATUS __CCREG(0x0518)
-#define USB_RESET __CCREG(0x051c)
-#define USB_INTERRUPTEST __CCReG(0x0520)
-
-#endif /* LANGUAGE == C */
-
-#define USB_RESET_FORCEIFRESET (1 << 0)
-#define USB_RESET_FORCEHCRESET (1 << 1)
-#define USB_RESET_CLKGENRESET (1 << 2)
-#define USB_RESET_SIMSCALEDOWN (1 << 3)
-#define USB_RESET_USBINTTEST (1 << 4)
-#define USB_RESET_SLEEPSTBYEN (1 << 5)
-#define USB_RESET_PWRSENSELOW (1 << 6)
-#define USB_RESET_PWRCTRLLOW (1 << 7)
-
-/*
- * Serial Audio Controller
- *
- * Registers
- * SACR0 Serial Audio Common Control Register
- * SACR1 Serial Audio Alternate Mode (I2C/MSB) Control Register
- * SACR2 Serial Audio AC-link Control Register
- * SASR0 Serial Audio I2S/MSB Interface & FIFO Status Register
- * SASR1 Serial Audio AC-link Interface & FIFO Status Register
- * SASCR Serial Audio Status Clear Register
- * L3_CAR L3 Control Bus Address Register
- * L3_CDR L3 Control Bus Data Register
- * ACCAR AC-link Command Address Register
- * ACCDR AC-link Command Data Register
- * ACSAR AC-link Status Address Register
- * ACSDR AC-link Status Data Register
- * SADTCS Serial Audio DMA Transmit Control/Status Register
- * SADTSA Serial Audio DMA Transmit Buffer Start Address A
- * SADTCA Serial Audio DMA Transmit Buffer Count Register A
- * SADTSB Serial Audio DMA Transmit Buffer Start Address B
- * SADTCB Serial Audio DMA Transmit Buffer Count Register B
- * SADRCS Serial Audio DMA Receive Control/Status Register
- * SADRSA Serial Audio DMA Receive Buffer Start Address A
- * SADRCA Serial Audio DMA Receive Buffer Count Register A
- * SADRSB Serial Audio DMA Receive Buffer Start Address B
- * SADRCB Serial Audio DMA Receive Buffer Count Register B
- * SAITR Serial Audio Interrupt Test Register
- * SADR Serial Audio Data Register (16 x 32-bit)
- */
-
-#define _SACR0 _SA1111( 0x0600 )
-#define _SACR1 _SA1111( 0x0604 )
-#define _SACR2 _SA1111( 0x0608 )
-#define _SASR0 _SA1111( 0x060c )
-#define _SASR1 _SA1111( 0x0610 )
-#define _SASCR _SA1111( 0x0618 )
-#define _L3_CAR _SA1111( 0x061c )
-#define _L3_CDR _SA1111( 0x0620 )
-#define _ACCAR _SA1111( 0x0624 )
-#define _ACCDR _SA1111( 0x0628 )
-#define _ACSAR _SA1111( 0x062c )
-#define _ACSDR _SA1111( 0x0630 )
-#define _SADTCS _SA1111( 0x0634 )
-#define _SADTSA _SA1111( 0x0638 )
-#define _SADTCA _SA1111( 0x063c )
-#define _SADTSB _SA1111( 0x0640 )
-#define _SADTCB _SA1111( 0x0644 )
-#define _SADRCS _SA1111( 0x0648 )
-#define _SADRSA _SA1111( 0x064c )
-#define _SADRCA _SA1111( 0x0650 )
-#define _SADRSB _SA1111( 0x0654 )
-#define _SADRCB _SA1111( 0x0658 )
-#define _SAITR _SA1111( 0x065c )
-#define _SADR _SA1111( 0x0680 )
-
-#if LANGUAGE == C
-
-#define SACR0 __CCREG(0x0600)
-#define SACR1 __CCREG(0x0604)
-#define SACR2 __CCREG(0x0608)
-#define SASR0 __CCREG(0x060c)
-#define SASR1 __CCREG(0x0610)
-#define SASCR __CCREG(0x0618)
-#define L3_CAR __CCREG(0x061c)
-#define L3_CDR __CCREG(0x0620)
-#define ACCAR __CCREG(0x0624)
-#define ACCDR __CCREG(0x0628)
-#define ACSAR __CCREG(0x062c)
-#define ACSDR __CCREG(0x0630)
-#define SADTCS __CCREG(0x0634)
-#define SADTSA __CCREG(0x0638)
-#define SADTCA __CCREG(0x063c)
-#define SADTSB __CCREG(0x0640)
-#define SADTCB __CCREG(0x0644)
-#define SADRCS __CCREG(0x0648)
-#define SADRSA __CCREG(0x064c)
-#define SADRCA __CCREG(0x0650)
-#define SADRSB __CCREG(0x0654)
-#define SADRCB __CCREG(0x0658)
-#define SAITR __CCREG(0x065c)
-#define SADR __CCREG(0x0680)
-
-#endif /* LANGUAGE == C */
-
-#define SACR0_ENB (1<<0)
-#define SACR0_BCKD (1<<2)
-#define SACR0_RST (1<<3)
-
-#define SACR1_AMSL (1<<0)
-#define SACR1_L3EN (1<<1)
-#define SACR1_L3MB (1<<2)
-#define SACR1_DREC (1<<3)
-#define SACR1_DRPL (1<<4)
-#define SACR1_ENLBF (1<<5)
-
-#define SACR2_TS3V (1<<0)
-#define SACR2_TS4V (1<<1)
-#define SACR2_WKUP (1<<2)
-#define SACR2_DREC (1<<3)
-#define SACR2_DRPL (1<<4)
-#define SACR2_ENLBF (1<<5)
-#define SACR2_RESET (1<<6)
-
-#define SASR0_TNF (1<<0)
-#define SASR0_RNE (1<<1)
-#define SASR0_BSY (1<<2)
-#define SASR0_TFS (1<<3)
-#define SASR0_RFS (1<<4)
-#define SASR0_TUR (1<<5)
-#define SASR0_ROR (1<<6)
-#define SASR0_L3WD (1<<16)
-#define SASR0_L3RD (1<<17)
-
-#define SASR1_TNF (1<<0)
-#define SASR1_RNE (1<<1)
-#define SASR1_BSY (1<<2)
-#define SASR1_TFS (1<<3)
-#define SASR1_RFS (1<<4)
-#define SASR1_TUR (1<<5)
-#define SASR1_ROR (1<<6)
-#define SASR1_CADT (1<<16)
-#define SASR1_SADR (1<<17)
-#define SASR1_RSTO (1<<18)
-#define SASR1_CLPM (1<<19)
-#define SASR1_CRDY (1<<20)
-#define SASR1_RS3V (1<<21)
-#define SASR1_RS4V (1<<22)
-
-#define SASCR_TUR (1<<5)
-#define SASCR_ROR (1<<6)
-#define SASCR_DTS (1<<16)
-#define SASCR_RDD (1<<17)
-#define SASCR_STO (1<<18)
-
-#define SADTCS_TDEN (1<<0)
-#define SADTCS_TDIE (1<<1)
-#define SADTCS_TDBDA (1<<3)
-#define SADTCS_TDSTA (1<<4)
-#define SADTCS_TDBDB (1<<5)
-#define SADTCS_TDSTB (1<<6)
-#define SADTCS_TBIU (1<<7)
-
-#define SADRCS_RDEN (1<<0)
-#define SADRCS_RDIE (1<<1)
-#define SADRCS_RDBDA (1<<3)
-#define SADRCS_RDSTA (1<<4)
-#define SADRCS_RDBDB (1<<5)
-#define SADRCS_RDSTB (1<<6)
-#define SADRCS_RBIU (1<<7)
-
-#define SAD_CS_DEN (1<<0)
-#define SAD_CS_DIE (1<<1) /* Not functional on metal 1 */
-#define SAD_CS_DBDA (1<<3) /* Not functional on metal 1 */
-#define SAD_CS_DSTA (1<<4)
-#define SAD_CS_DBDB (1<<5) /* Not functional on metal 1 */
-#define SAD_CS_DSTB (1<<6)
-#define SAD_CS_BIU (1<<7) /* Not functional on metal 1 */
-
-#define SAITR_TFS (1<<0)
-#define SAITR_RFS (1<<1)
-#define SAITR_TUR (1<<2)
-#define SAITR_ROR (1<<3)
-#define SAITR_CADT (1<<4)
-#define SAITR_SADR (1<<5)
-#define SAITR_RSTO (1<<6)
-#define SAITR_TDBDA (1<<8)
-#define SAITR_TDBDB (1<<9)
-#define SAITR_RDBDA (1<<10)
-#define SAITR_RDBDB (1<<11)
-
-/*
- * General-Purpose I/O Interface
- *
- * Registers
- * PA_DDR GPIO Block A Data Direction
- * PA_DRR/PA_DWR GPIO Block A Data Value Register (read/write)
- * PA_SDR GPIO Block A Sleep Direction
- * PA_SSR GPIO Block A Sleep State
- * PB_DDR GPIO Block B Data Direction
- * PB_DRR/PB_DWR GPIO Block B Data Value Register (read/write)
- * PB_SDR GPIO Block B Sleep Direction
- * PB_SSR GPIO Block B Sleep State
- * PC_DDR GPIO Block C Data Direction
- * PC_DRR/PC_DWR GPIO Block C Data Value Register (read/write)
- * PC_SDR GPIO Block C Sleep Direction
- * PC_SSR GPIO Block C Sleep State
- */
-
-#define _PA_DDR _SA1111( 0x1000 )
-#define _PA_DRR _SA1111( 0x1004 )
-#define _PA_DWR _SA1111( 0x1004 )
-#define _PA_SDR _SA1111( 0x1008 )
-#define _PA_SSR _SA1111( 0x100c )
-#define _PB_DDR _SA1111( 0x1010 )
-#define _PB_DRR _SA1111( 0x1014 )
-#define _PB_DWR _SA1111( 0x1014 )
-#define _PB_SDR _SA1111( 0x1018 )
-#define _PB_SSR _SA1111( 0x101c )
-#define _PC_DDR _SA1111( 0x1020 )
-#define _PC_DRR _SA1111( 0x1024 )
-#define _PC_DWR _SA1111( 0x1024 )
-#define _PC_SDR _SA1111( 0x1028 )
-#define _PC_SSR _SA1111( 0x102c )
-
-#if LANGUAGE == C
-
-#define PA_DDR __CCREG(0x1000)
-#define PA_DRR __CCREG(0x1004)
-#define PA_DWR __CCREG(0x1004)
-#define PA_SDR __CCREG(0x1008)
-#define PA_SSR __CCREG(0x100c)
-#define PB_DDR __CCREG(0x1010)
-#define PB_DRR __CCREG(0x1014)
-#define PB_DWR __CCREG(0x1014)
-#define PB_SDR __CCREG(0x1018)
-#define PB_SSR __CCREG(0x101c)
-#define PC_DDR __CCREG(0x1020)
-#define PC_DRR __CCREG(0x1024)
-#define PC_DWR __CCREG(0x1024)
-#define PC_SDR __CCREG(0x1028)
-#define PC_SSR __CCREG(0x102c)
-
-#endif /* LANGUAGE == C */
-
-/*
- * Interrupt Controller
- *
- * Registers
- * INTTEST0 Test register 0
- * INTTEST1 Test register 1
- * INTEN0 Interrupt Enable register 0
- * INTEN1 Interrupt Enable register 1
- * INTPOL0 Interrupt Polarity selection 0
- * INTPOL1 Interrupt Polarity selection 1
- * INTTSTSEL Interrupt source selection
- * INTSTATCLR0 Interrupt Status/Clear 0
- * INTSTATCLR1 Interrupt Status/Clear 1
- * INTSET0 Interrupt source set 0
- * INTSET1 Interrupt source set 1
- * WAKE_EN0 Wake-up source enable 0
- * WAKE_EN1 Wake-up source enable 1
- * WAKE_POL0 Wake-up polarity selection 0
- * WAKE_POL1 Wake-up polarity selection 1
- */
-
-#define _INTTEST0 _SA1111( 0x1600 )
-#define _INTTEST1 _SA1111( 0x1604 )
-#define _INTEN0 _SA1111( 0x1608 )
-#define _INTEN1 _SA1111( 0x160c )
-#define _INTPOL0 _SA1111( 0x1610 )
-#define _INTPOL1 _SA1111( 0x1614 )
-#define _INTTSTSEL _SA1111( 0x1618 )
-#define _INTSTATCLR0 _SA1111( 0x161c )
-#define _INTSTATCLR1 _SA1111( 0x1620 )
-#define _INTSET0 _SA1111( 0x1624 )
-#define _INTSET1 _SA1111( 0x1628 )
-#define _WAKE_EN0 _SA1111( 0x162c )
-#define _WAKE_EN1 _SA1111( 0x1630 )
-#define _WAKE_POL0 _SA1111( 0x1634 )
-#define _WAKE_POL1 _SA1111( 0x1638 )
-
-#if LANGUAGE == C
-
-#define INTTEST0 __CCREG(0x1600)
-#define INTTEST1 __CCREG(0x1604)
-#define INTEN0 __CCREG(0x1608)
-#define INTEN1 __CCREG(0x160c)
-#define INTPOL0 __CCREG(0x1610)
-#define INTPOL1 __CCREG(0x1614)
-#define INTTSTSEL __CCREG(0x1618)
-#define INTSTATCLR0 __CCREG(0x161c)
-#define INTSTATCLR1 __CCREG(0x1620)
-#define INTSET0 __CCREG(0x1624)
-#define INTSET1 __CCREG(0x1628)
-#define WAKE_EN0 __CCREG(0x162c)
-#define WAKE_EN1 __CCREG(0x1630)
-#define WAKE_POL0 __CCREG(0x1634)
-#define WAKE_POL1 __CCREG(0x1638)
-
-#endif /* LANGUAGE == C */
-
-/*
- * PS/2 Trackpad and Mouse Interfaces
- *
- * Registers (prefix kbd applies to trackpad interface, mse to mouse)
- * KBDCR Control Register
- * KBDSTAT Status Register
- * KBDDATA Transmit/Receive Data register
- * KBDCLKDIV Clock Division Register
- * KBDPRECNT Clock Precount Register
- * KBDTEST1 Test register 1
- * KBDTEST2 Test register 2
- * KBDTEST3 Test register 3
- * KBDTEST4 Test register 4
- * MSECR
- * MSESTAT
- * MSEDATA
- * MSECLKDIV
- * MSEPRECNT
- * MSETEST1
- * MSETEST2
- * MSETEST3
- * MSETEST4
- *
- */
-
-#define _KBD( x ) _SA1111( 0x0A00 )
-#define _MSE( x ) _SA1111( 0x0C00 )
-
-#define _KBDCR _SA1111( 0x0A00 )
-#define _KBDSTAT _SA1111( 0x0A04 )
-#define _KBDDATA _SA1111( 0x0A08 )
-#define _KBDCLKDIV _SA1111( 0x0A0C )
-#define _KBDPRECNT _SA1111( 0x0A10 )
-#define _MSECR _SA1111( 0x0C00 )
-#define _MSESTAT _SA1111( 0x0C04 )
-#define _MSEDATA _SA1111( 0x0C08 )
-#define _MSECLKDIV _SA1111( 0x0C0C )
-#define _MSEPRECNT _SA1111( 0x0C10 )
-
-#if ( LANGUAGE == C )
-
-#define KBDCR __CCREG(0x0a00)
-#define KBDSTAT __CCREG(0x0a04)
-#define KBDDATA __CCREG(0x0a08)
-#define KBDCLKDIV __CCREG(0x0a0c)
-#define KBDPRECNT __CCREG(0x0a10)
-#define MSECR __CCREG(0x0c00)
-#define MSESTAT __CCREG(0x0c04)
-#define MSEDATA __CCREG(0x0c08)
-#define MSECLKDIV __CCREG(0x0c0c)
-#define MSEPRECNT __CCREG(0x0c10)
-
-#define KBDCR_ENA 0x08
-#define KBDCR_FKD 0x02
-#define KBDCR_FKC 0x01
-
-#define KBDSTAT_TXE 0x80
-#define KBDSTAT_TXB 0x40
-#define KBDSTAT_RXF 0x20
-#define KBDSTAT_RXB 0x10
-#define KBDSTAT_ENA 0x08
-#define KBDSTAT_RXP 0x04
-#define KBDSTAT_KBD 0x02
-#define KBDSTAT_KBC 0x01
-
-#define KBDCLKDIV_DivVal Fld(4,0)
-
-#define MSECR_ENA 0x08
-#define MSECR_FKD 0x02
-#define MSECR_FKC 0x01
-
-#define MSESTAT_TXE 0x80
-#define MSESTAT_TXB 0x40
-#define MSESTAT_RXF 0x20
-#define MSESTAT_RXB 0x10
-#define MSESTAT_ENA 0x08
-#define MSESTAT_RXP 0x04
-#define MSESTAT_MSD 0x02
-#define MSESTAT_MSC 0x01
-
-#define MSECLKDIV_DivVal Fld(4,0)
-
-#define KBDTEST1_CD 0x80
-#define KBDTEST1_RC1 0x40
-#define KBDTEST1_MC 0x20
-#define KBDTEST1_C Fld(2,3)
-#define KBDTEST1_T2 0x40
-#define KBDTEST1_T1 0x20
-#define KBDTEST1_T0 0x10
-#define KBDTEST2_TICBnRES 0x08
-#define KBDTEST2_RKC 0x04
-#define KBDTEST2_RKD 0x02
-#define KBDTEST2_SEL 0x01
-#define KBDTEST3_ms_16 0x80
-#define KBDTEST3_us_64 0x40
-#define KBDTEST3_us_16 0x20
-#define KBDTEST3_DIV8 0x10
-#define KBDTEST3_DIn 0x08
-#define KBDTEST3_CIn 0x04
-#define KBDTEST3_KD 0x02
-#define KBDTEST3_KC 0x01
-#define KBDTEST4_BC12 0x80
-#define KBDTEST4_BC11 0x40
-#define KBDTEST4_TRES 0x20
-#define KBDTEST4_CLKOE 0x10
-#define KBDTEST4_CRES 0x08
-#define KBDTEST4_RXB 0x04
-#define KBDTEST4_TXB 0x02
-#define KBDTEST4_SRX 0x01
-
-#define MSETEST1_CD 0x80
-#define MSETEST1_RC1 0x40
-#define MSETEST1_MC 0x20
-#define MSETEST1_C Fld(2,3)
-#define MSETEST1_T2 0x40
-#define MSETEST1_T1 0x20
-#define MSETEST1_T0 0x10
-#define MSETEST2_TICBnRES 0x08
-#define MSETEST2_RKC 0x04
-#define MSETEST2_RKD 0x02
-#define MSETEST2_SEL 0x01
-#define MSETEST3_ms_16 0x80
-#define MSETEST3_us_64 0x40
-#define MSETEST3_us_16 0x20
-#define MSETEST3_DIV8 0x10
-#define MSETEST3_DIn 0x08
-#define MSETEST3_CIn 0x04
-#define MSETEST3_KD 0x02
-#define MSETEST3_KC 0x01
-#define MSETEST4_BC12 0x80
-#define MSETEST4_BC11 0x40
-#define MSETEST4_TRES 0x20
-#define MSETEST4_CLKOE 0x10
-#define MSETEST4_CRES 0x08
-#define MSETEST4_RXB 0x04
-#define MSETEST4_TXB 0x02
-#define MSETEST4_SRX 0x01
-
-#endif /* LANGUAGE == C */
-
-/*
- * PCMCIA Interface
- *
- * Registers
- * PCSR Status Register
- * PCCR Control Register
- * PCSSR Sleep State Register
- */
-
-#define _PCCR _SA1111( 0x1800 )
-#define _PCSSR _SA1111( 0x1804 )
-#define _PCSR _SA1111( 0x1808 )
-
-#if LANGUAGE == C
-
-#define PCCR __CCREG(0x1800)
-#define PCSSR __CCREG(0x1804)
-#define PCSR __CCREG(0x1808)
-
-#endif /* LANGUAGE == C */
-
-#define PCSR_S0_READY (1<<0)
-#define PCSR_S1_READY (1<<1)
-#define PCSR_S0_DETECT (1<<2)
-#define PCSR_S1_DETECT (1<<3)
-#define PCSR_S0_VS1 (1<<4)
-#define PCSR_S0_VS2 (1<<5)
-#define PCSR_S1_VS1 (1<<6)
-#define PCSR_S1_VS2 (1<<7)
-#define PCSR_S0_WP (1<<8)
-#define PCSR_S1_WP (1<<9)
-#define PCSR_S0_BVD1 (1<<10)
-#define PCSR_S0_BVD2 (1<<11)
-#define PCSR_S1_BVD1 (1<<12)
-#define PCSR_S1_BVD2 (1<<13)
-
-#define PCCR_S0_RST (1<<0)
-#define PCCR_S1_RST (1<<1)
-#define PCCR_S0_FLT (1<<2)
-#define PCCR_S1_FLT (1<<3)
-#define PCCR_S0_PWAITEN (1<<4)
-#define PCCR_S1_PWAITEN (1<<5)
-#define PCCR_S0_PSE (1<<6)
-#define PCCR_S1_PSE (1<<7)
-
-#define PCSSR_S0_SLEEP (1<<0)
-#define PCSSR_S1_SLEEP (1<<1)
-
-#endif /* _ASM_ARCH_SA1111 */
+#warning using old SA-1111.h - update to <asm/hardware/sa1111.h>
+#include <asm/hardware/sa1111.h>
diff --git a/include/asm-arm/arch-sa1100/assabet.h b/include/asm-arm/arch-sa1100/assabet.h
index 0292f7104..6d13df14a 100644
--- a/include/asm-arm/arch-sa1100/assabet.h
+++ b/include/asm-arm/arch-sa1100/assabet.h
@@ -29,19 +29,6 @@
#define ASSABET_BCR_BASE 0xf1000000
#define ASSABET_BCR (*(volatile unsigned int *)(ASSABET_BCR_BASE))
-#define ASSABET_BCR_DB1110 \
- (ASSABET_BCR_SPK_OFF | ASSABET_BCR_QMUTE | \
- ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \
- ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \
- ASSABET_BCR_IRDA_MD0)
-
-#define ASSABET_BCR_DB1111 \
- (ASSABET_BCR_SPK_OFF | ASSABET_BCR_QMUTE | \
- ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \
- ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \
- ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \
- ASSABET_BCR_IRDA_MD0 | ASSABET_BCR_CF_RST)
-
#define ASSABET_BCR_CF_PWR (1<<0) /* Compact Flash Power (1 = 3.3v, 0 = off) */
#define ASSABET_BCR_CF_RST (1<<1) /* Compact Flash Reset (1 = power up reset) */
#define ASSABET_BCR_GFX_RST (1<<1) /* Graphics Accelerator Reset (0 = hold reset) */
@@ -69,9 +56,15 @@
#define ASSABET_BCR_SPK_OFF (1<<23) /* 1 = Speaker amplifier power off */
extern unsigned long SCR_value;
-extern unsigned long BCR_value;
-#define ASSABET_BCR_set(x) ASSABET_BCR = (BCR_value |= (x))
-#define ASSABET_BCR_clear(x) ASSABET_BCR = (BCR_value &= ~(x))
+
+#ifdef CONFIG_SA1100_ASSABET
+extern void ASSABET_BCR_frob(unsigned int mask, unsigned int set);
+#else
+#define ASSABET_BCR_frob(x) do { } while (0)
+#endif
+
+#define ASSABET_BCR_set(x) ASSABET_BCR_frob((x), (x))
+#define ASSABET_BCR_clear(x) ASSABET_BCR_frob((x), 0)
#define ASSABET_BSR_BASE 0xf1000000
#define ASSABET_BSR (*(volatile unsigned int*)(ASSABET_BSR_BASE))
@@ -88,38 +81,26 @@ extern unsigned long BCR_value;
/* GPIOs for which the generic definition doesn't say much */
#define ASSABET_GPIO_RADIO_IRQ GPIO_GPIO (14) /* Radio interrupt request */
-#define ASSABET_GPIO_L3_I2C_SDA GPIO_GPIO (15) /* L3 and SMB control ports */
#define ASSABET_GPIO_PS_MODE_SYNC GPIO_GPIO (16) /* Power supply mode/sync */
-#define ASSABET_GPIO_L3_MODE GPIO_GPIO (17) /* L3 mode signal with LED */
-#define ASSABET_GPIO_L3_I2C_SCL GPIO_GPIO (18) /* L3 and I2C control ports */
#define ASSABET_GPIO_STEREO_64FS_CLK GPIO_GPIO (19) /* SSP UDA1341 clock input */
#define ASSABET_GPIO_CF_IRQ GPIO_GPIO (21) /* CF IRQ */
#define ASSABET_GPIO_CF_CD GPIO_GPIO (22) /* CF CD */
-#define ASSABET_GPIO_UCB1300_IRQ GPIO_GPIO (23) /* UCB GPIO and touchscreen */
#define ASSABET_GPIO_CF_BVD2 GPIO_GPIO (24) /* CF BVD */
#define ASSABET_GPIO_GFX_IRQ GPIO_GPIO (24) /* Graphics IRQ */
#define ASSABET_GPIO_CF_BVD1 GPIO_GPIO (25) /* CF BVD */
-#define ASSABET_GPIO_NEP_IRQ GPIO_GPIO (25) /* Neponset IRQ */
#define ASSABET_GPIO_BATT_LOW GPIO_GPIO (26) /* Low battery */
#define ASSABET_GPIO_RCLK GPIO_GPIO (26) /* CCLK/2 */
#define ASSABET_IRQ_GPIO_CF_IRQ IRQ_GPIO21
#define ASSABET_IRQ_GPIO_CF_CD IRQ_GPIO22
-#define ASSABET_IRQ_GPIO_UCB1300_IRQ IRQ_GPIO23
#define ASSABET_IRQ_GPIO_CF_BVD2 IRQ_GPIO24
#define ASSABET_IRQ_GPIO_CF_BVD1 IRQ_GPIO25
-#define ASSABET_IRQ_GPIO_NEP_IRQ IRQ_GPIO25
/*
* Neponset definitions:
*/
-#define SA1111_BASE (0x40000000)
-
-#define NEPONSET_ETHERNET_IRQ MISC_IRQ0
-#define NEPONSET_USAR_IRQ MISC_IRQ1
-
#define NEPONSET_CPLD_BASE (0x10000000)
#define Nep_p2v( x ) ((x) - NEPONSET_CPLD_BASE + 0xf3000000)
#define Nep_v2p( x ) ((x) - 0xf3000000 + NEPONSET_CPLD_BASE)
diff --git a/include/asm-arm/arch-sa1100/dma.h b/include/asm-arm/arch-sa1100/dma.h
index 471c41021..8927a3d26 100644
--- a/include/asm-arm/arch-sa1100/dma.h
+++ b/include/asm-arm/arch-sa1100/dma.h
@@ -28,34 +28,16 @@
*/
#define MAX_DMA_CHANNELS 0
-
/*
* The SA1100 has six internal DMA channels.
*/
-#define SA1100_DMA_CHANNELS 6
-
+#define SA1100_DMA_CHANNELS 6
/*
- * The SA-1111 SAC has two DMA channels.
+ * Maximum physical DMA buffer size
*/
-#define SA1111_SAC_DMA_CHANNELS 2
-#define SA1111_SAC_XMT_CHANNEL 0
-#define SA1111_SAC_RCV_CHANNEL 1
-
-
-/*
- * The SA-1111 SAC channels will reside in the same index space as
- * the built-in SA-1100 channels, and will take on the next available
- * identifiers after the 1100.
- */
-#define SA1111_SAC_DMA_BASE SA1100_DMA_CHANNELS
-
-#ifdef CONFIG_SA1111
-# define MAX_SA1100_DMA_CHANNELS (SA1100_DMA_CHANNELS + SA1111_SAC_DMA_CHANNELS)
-#else
-# define MAX_SA1100_DMA_CHANNELS SA1100_DMA_CHANNELS
-#endif
-
+#define MAX_DMA_SIZE 0x1fff
+#define CUT_DMA_SIZE 0x1000
/*
* All possible SA1100 devices a DMA channel can be attached to.
@@ -81,29 +63,72 @@ typedef enum {
DMA_Ser4SSPRd = DDAR_Ser4SSPRd /* Ser. port 4 SSP Read (16 bits) */
} dma_device_t;
+typedef struct {
+ volatile u_long DDAR;
+ volatile u_long SetDCSR;
+ volatile u_long ClrDCSR;
+ volatile u_long RdDCSR;
+ volatile dma_addr_t DBSA;
+ volatile u_long DBTA;
+ volatile dma_addr_t DBSB;
+ volatile u_long DBTB;
+} dma_regs_t;
+
+typedef void (*dma_callback_t)(void *data);
+
+/*
+ * DMA function prototypes
+ */
+
+extern int sa1100_request_dma( dma_device_t device, const char *device_id,
+ dma_callback_t callback, void *data,
+ dma_regs_t **regs );
+extern void sa1100_free_dma( dma_regs_t *regs );
+extern int sa1100_start_dma( dma_regs_t *regs, dma_addr_t dma_ptr, u_int size );
+extern dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs);
+extern void sa1100_reset_dma(dma_regs_t *regs);
+
+/**
+ * sa1100_stop_dma - stop DMA in progress
+ * @regs: identifier for the channel to use
+ *
+ * This stops DMA without clearing buffer pointers. Unlike
+ * sa1100_clear_dma() this allows subsequent use of sa1100_resume_dma()
+ * or sa1100_get_dma_pos().
+ *
+ * The @regs identifier is provided by a successful call to
+ * sa1100_request_dma().
+ **/
+
+#define sa1100_stop_dma(regs) ((regs)->ClrDCSR = DCSR_IE|DCSR_RUN)
+
+/**
+ * sa1100_resume_dma - resume DMA on a stopped channel
+ * @regs: identifier for the channel to use
+ *
+ * This resumes DMA on a channel previously stopped with
+ * sa1100_stop_dma().
+ *
+ * The @regs identifier is provided by a successful call to
+ * sa1100_request_dma().
+ **/
+
+#define sa1100_resume_dma(regs) ((regs)->SetDCSR = DCSR_IE|DCSR_RUN)
+
+/**
+ * sa1100_clear_dma - clear DMA pointers
+ * @regs: identifier for the channel to use
+ *
+ * This clear any DMA state so the DMA engine is ready to restart
+ * with new buffers through sa1100_start_dma(). Any buffers in flight
+ * are discarded.
+ *
+ * The @regs identifier is provided by a successful call to
+ * sa1100_request_dma().
+ **/
+
+#define sa1100_clear_dma(regs) ((regs)->ClrDCSR = DCSR_IE|DCSR_RUN|DCSR_STRTA|DCSR_STRTB)
-typedef void (*dma_callback_t)( void *buf_id, int size );
-
-
-/* SA1100 DMA API */
-extern int sa1100_request_dma( dmach_t *channel, const char *device_id,
- dma_device_t device );
-extern int sa1100_dma_set_callback( dmach_t channel, dma_callback_t cb );
-extern int sa1100_dma_set_spin( dmach_t channel, dma_addr_t addr, int size );
-extern int sa1100_dma_queue_buffer( dmach_t channel, void *buf_id,
- dma_addr_t data, int size );
-extern int sa1100_dma_get_current( dmach_t channel, void **buf_id, dma_addr_t *addr );
-extern int sa1100_dma_stop( dmach_t channel );
-extern int sa1100_dma_resume( dmach_t channel );
-extern int sa1100_dma_flush_all( dmach_t channel );
-extern void sa1100_free_dma( dmach_t channel );
-extern int sa1100_dma_sleep( dmach_t channel );
-extern int sa1100_dma_wakeup( dmach_t channel );
-
-/* Sa1111 DMA interface (all but registration uses the above) */
-extern int sa1111_sac_request_dma( dmach_t *channel, const char *device_id,
- unsigned int direction );
-extern int sa1111_check_dma_bug( dma_addr_t addr );
#ifdef CONFIG_SA1111
static inline void
diff --git a/include/asm-arm/arch-sa1100/flexanet.h b/include/asm-arm/arch-sa1100/flexanet.h
index f0b8d42f2..6dc79190c 100644
--- a/include/asm-arm/arch-sa1100/flexanet.h
+++ b/include/asm-arm/arch-sa1100/flexanet.h
@@ -1,5 +1,5 @@
/*
- * linux/include/asm-arm/arch-sa1100/flexanet.h
+ * include/asm-arm/arch-sa1100/flexanet.h
*
* Created 2001/05/04 by Jordi Colomer <jco@ict.es>
*
@@ -11,39 +11,79 @@
#error "include <asm/hardware.h> instead"
#endif
-
/* Board Control Register (virtual address) */
-#define BCR_PHYS 0x10000000
-#define BCR_VIRT 0xf0000000
-#define BCR (*(volatile unsigned int *)(BCR_VIRT))
+#define FHH_BCR_PHYS 0x10000000
+#define FHH_BCR_VIRT 0xf0000000
+#define FHH_BCR (*(volatile unsigned int *)(FHH_BCR_VIRT))
/* Power-up value */
-#define BCR_POWERUP 0x00000000
+#define FHH_BCR_POWERUP 0x00000000
/* Mandatory bits */
-#define BCR_LED_GREEN (1<<0) /* General-purpose green LED (1 = on) */
-#define BCR_GUI_NRST (1<<4) /* GUI board reset (0 = reset) */
-
-/* Board Status Register (virtual address) */
-#define BSR_BASE BCR_BASE
-#define BSR (*(volatile unsigned int *)(BSR_BASE))
-
+#define FHH_BCR_LED_GREEN (1<<0) /* General-purpose green LED (1 = on) */
+#define FHH_BCR_SPARE_1 (1<<1) /* Not defined */
+#define FHH_BCR_CF1_RST (1<<2) /* Compact Flash Slot #1 Reset (1 = reset) */
+#define FHH_BCR_CF2_RST (1<<3) /* Compact Flash Slot #2 Reset (1 = reset) */
+#define FHH_BCR_GUI_NRST (1<<4) /* GUI board reset (0 = reset) */
+#define FHH_BCR_RTS1 (1<<5) /* RS232 RTS for UART-1 */
+#define FHH_BCR_RTS3 (1<<6) /* RS232 RTS for UART-3 */
+#define FHH_BCR_XCDBG0 (1<<7) /* Not defined. Wired to XPLA3 for debug */
+
+/* BCR extension, only required by L3-bus in some audio codecs */
+#define FHH_BCR_L3MOD (1<<8) /* L3-bus MODE signal */
+#define FHH_BCR_L3DAT (1<<9) /* L3-bus DATA signal */
+#define FHH_BCR_L3CLK (1<<10) /* L3-bus CLK signal */
+#define FHH_BCR_SPARE_11 (1<<11) /* Not defined */
+#define FHH_BCR_SPARE_12 (1<<12) /* Not defined */
+#define FHH_BCR_SPARE_13 (1<<13) /* Not defined */
+#define FHH_BCR_SPARE_14 (1<<14) /* Not defined */
+#define FHH_BCR_SPARE_15 (1<<15) /* Not defined */
+
+ /* Board Status Register (virtual address) */
+#define FHH_BSR_BASE FHH_BCR_VIRT
+#define FHH_BSR (*(volatile unsigned int *)(FHH_BSR_BASE))
+
+#define FHH_BSR_CTS1 (1<<0) /* RS232 CTS for UART-1 */
+#define FHH_BSR_CTS3 (1<<1) /* RS232 CTS for UART-3 */
+#define FHH_BSR_DSR1 (1<<2) /* RS232 DSR for UART-1 */
+#define FHH_BSR_DSR3 (1<<3) /* RS232 DSR for UART-3 */
+#define FHH_BSR_ID0 (1<<4) /* Board identification */
+#define FHH_BSR_ID1 (1<<5)
+#define FHH_BSR_CFG0 (1<<6) /* Board configuration options */
+#define FHH_BSR_CFG1 (1<<7)
#ifndef __ASSEMBLY__
-extern unsigned long BCR_value; /* Image of the BCR */
-#define BCR_set( x ) BCR = (BCR_value |= (x))
-#define BCR_clear( x ) BCR = (BCR_value &= ~(x))
+extern unsigned long flexanet_BCR; /* Image of the BCR */
+#define FLEXANET_BCR_set( x ) FHH_BCR = (flexanet_BCR |= (x))
+#define FLEXANET_BCR_clear( x ) FHH_BCR = (flexanet_BCR &= ~(x))
#endif
-
/* GPIOs for which the generic definition doesn't say much */
-#define GPIO_GUI_IRQ GPIO_GPIO (23) /* IRQ from GUI board (i.e., UCB1300) */
-#define GPIO_ETH_IRQ GPIO_GPIO (24) /* IRQ from Ethernet controller */
-#define GPIO_LED_RED GPIO_GPIO (26) /* General-purpose red LED */
+#define GPIO_CF1_NCD GPIO_GPIO (14) /* Card Detect from CF slot #1 */
+#define GPIO_CF2_NCD GPIO_GPIO (15) /* Card Detect from CF slot #2 */
+#define GPIO_CF1_IRQ GPIO_GPIO (16) /* IRQ from CF slot #1 */
+#define GPIO_CF2_IRQ GPIO_GPIO (17) /* IRQ from CF slot #2 */
+#define GPIO_APP_IRQ GPIO_GPIO (18) /* Extra IRQ from application bus */
+#define GPIO_RADIO_REF GPIO_GPIO (20) /* Ref. clock for UART3 (Radio) */
+#define GPIO_CF1_BVD1 GPIO_GPIO (21) /* BVD1 from CF slot #1 */
+#define GPIO_CF2_BVD1 GPIO_GPIO (22) /* BVD1 from CF slot #2 */
+#define GPIO_GUI_IRQ GPIO_GPIO (23) /* IRQ from GUI board (i.e., UCB1300) */
+#define GPIO_ETH_IRQ GPIO_GPIO (24) /* IRQ from Ethernet controller */
+#define GPIO_INTIP_IRQ GPIO_GPIO (25) /* Measurement IRQ (INTIP) */
+#define GPIO_LED_RED GPIO_GPIO (26) /* General-purpose red LED */
/* IRQ sources from GPIOs */
-#define IRQ_GPIO_GUI IRQ_GPIO23
-#define IRQ_GPIO_ETH IRQ_GPIO24
+#define IRQ_GPIO_CF1_CD IRQ_GPIO14
+#define IRQ_GPIO_CF2_CD IRQ_GPIO15
+#define IRQ_GPIO_CF1_IRQ IRQ_GPIO16
+#define IRQ_GPIO_CF2_IRQ IRQ_GPIO17
+#define IRQ_GPIO_APP IRQ_GPIO18
+#define IRQ_GPIO_CF1_BVD1 IRQ_GPIO21
+#define IRQ_GPIO_CF2_BVD1 IRQ_GPIO22
+#define IRQ_GPIO_GUI IRQ_GPIO23
+#define IRQ_GPIO_ETH IRQ_GPIO24
+#define IRQ_GPIO_INTIP IRQ_GPIO25
+
/* On-Board Ethernet */
#define _FHH_ETH_IOBASE 0x18000000 /* I/O base (physical addr) */
@@ -58,14 +98,3 @@ extern unsigned long BCR_value; /* Image of the BCR */
#define FHH_ETH_MMBASE FHH_ETH_p2v(_FHH_ETH_MMBASE)
-/* Types of GUI */
-#ifndef __ASSEMBLY__
-extern unsigned long GUI_type;
-#endif
-
-#define FHH_GUI_ERROR 0xFFFFFFFF
-#define FHH_GUI_NONE 0x0000000F
-#define FHH_GUI_TYPE_0 0
-#define FHH_GUI_TYPE_1 1
-#define FHH_GUI_TYPE_2 2
-
diff --git a/include/asm-arm/arch-sa1100/graphicsmaster.h b/include/asm-arm/arch-sa1100/graphicsmaster.h
index 289bc255d..ae4579173 100644
--- a/include/asm-arm/arch-sa1100/graphicsmaster.h
+++ b/include/asm-arm/arch-sa1100/graphicsmaster.h
@@ -62,5 +62,3 @@
#endif
#define SA1111_BASE (0x18000000)
-
-#include "SA-1111.h"
diff --git a/include/asm-arm/arch-sa1100/h3600.h b/include/asm-arm/arch-sa1100/h3600.h
index 1ae5b77ed..d0fc9198c 100644
--- a/include/asm-arm/arch-sa1100/h3600.h
+++ b/include/asm-arm/arch-sa1100/h3600.h
@@ -1,81 +1,138 @@
/*
-*
-* Definitions for H3600 Handheld Computer
-*
-* Copyright 2000 Compaq Computer Corporation.
-*
-* Use consistent with the GNU GPL is permitted,
-* provided that this copyright notice is
-* preserved in its entirety in all copies and derived works.
-*
-* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
-* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
-* FITNESS FOR ANY PARTICULAR PURPOSE.
-*
-* Author: Jamey Hicks.
-*
-*/
+ *
+ * Definitions for H3600 Handheld Computer
+ *
+ * Copyright 2000 Compaq Computer Corporation.
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Author: Jamey Hicks.
+ *
+ * History:
+ *
+ * 2001-10-?? Andrew Christian Added support for iPAQ H3800
+ *
+ */
#ifndef _INCLUDE_H3600_H_
#define _INCLUDE_H3600_H_
-#define GPIO_H3600_NPOWER_BUTTON GPIO_GPIO (0)
-#define GPIO_H3600_ACTION_BUTTON GPIO_GPIO (18)
+/* generalized support for H3xxx series Compaq Pocket PC's */
+#define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600() || machine_is_h3800())
+
+/* Virtual memory regions corresponding to chip selects 2 & 4 (used on sleeves) */
+#define H3600_EGPIO_VIRT 0xf0000000
+#define H3600_BANK_2_VIRT 0xf1000000
+#define H3600_BANK_4_VIRT 0xf3800000
+
+/*
+ Machine-independent GPIO definitions
+ --- these are common across all current iPAQ platforms
+*/
+
+#define GPIO_H3600_NPOWER_BUTTON GPIO_GPIO (0) /* Also known as the "off button" */
+#define GPIO_H3600_MICROCONTROLLER GPIO_GPIO (1) /* From ASIC2 on H3800 */
-#define GPIO_H3600_PCMCIA_CD0 GPIO_GPIO (17)
#define GPIO_H3600_PCMCIA_CD1 GPIO_GPIO (10)
-#define GPIO_H3600_PCMCIA_IRQ0 GPIO_GPIO (21)
#define GPIO_H3600_PCMCIA_IRQ1 GPIO_GPIO (11)
-/* audio sample rate clock generator */
-#define GPIO_H3600_CLK_SET0 GPIO_GPIO (12)
-#define GPIO_H3600_CLK_SET1 GPIO_GPIO (13)
-
/* UDA1341 L3 Interface */
#define GPIO_H3600_L3_DATA GPIO_GPIO (14)
-#define GPIO_H3600_L3_CLOCK GPIO_GPIO (16)
#define GPIO_H3600_L3_MODE GPIO_GPIO (15)
+#define GPIO_H3600_L3_CLOCK GPIO_GPIO (16)
-#define GPIO_H3600_OPT_LOCK GPIO_GPIO (22)
-#define GPIO_H3600_OPT_IRQ GPIO_GPIO (24)
-#define GPIO_H3600_OPT_DET GPIO_GPIO (27)
+#define GPIO_H3600_PCMCIA_CD0 GPIO_GPIO (17)
+#define GPIO_H3600_SYS_CLK GPIO_GPIO (19)
+#define GPIO_H3600_PCMCIA_IRQ0 GPIO_GPIO (21)
#define GPIO_H3600_COM_DCD GPIO_GPIO (23)
+#define GPIO_H3600_OPT_IRQ GPIO_GPIO (24)
#define GPIO_H3600_COM_CTS GPIO_GPIO (25)
#define GPIO_H3600_COM_RTS GPIO_GPIO (26)
#define IRQ_GPIO_H3600_NPOWER_BUTTON IRQ_GPIO0
-#define IRQ_GPIO_H3600_ACTION_BUTTON IRQ_GPIO18
-#define IRQ_GPIO_H3600_PCMCIA_CD0 IRQ_GPIO17
+#define IRQ_GPIO_H3600_MICROCONTROLLER IRQ_GPIO1
#define IRQ_GPIO_H3600_PCMCIA_CD1 IRQ_GPIO10
-#define IRQ_GPIO_H3600_PCMCIA_IRQ0 IRQ_GPIO21
#define IRQ_GPIO_H3600_PCMCIA_IRQ1 IRQ_GPIO11
-#define IRQ_GPIO_H3600_OPT_IRQ IRQ_GPIO24
-#define IRQ_GPIO_H3600_OPT_DET IRQ_GPIO27
+#define IRQ_GPIO_H3600_PCMCIA_CD0 IRQ_GPIO17
+#define IRQ_GPIO_H3600_PCMCIA_IRQ0 IRQ_GPIO21
#define IRQ_GPIO_H3600_COM_DCD IRQ_GPIO23
+#define IRQ_GPIO_H3600_OPT_IRQ IRQ_GPIO24
#define IRQ_GPIO_H3600_COM_CTS IRQ_GPIO25
-#define EGPIO_H3600_VPP_ON (1 << 0)
-#define EGPIO_H3600_CARD_RESET (1 << 1) /* reset the attached pcmcia/compactflash card. active high. */
-#define EGPIO_H3600_OPT_RESET (1 << 2) /* reset the attached option pack. active high. */
-#define EGPIO_H3600_CODEC_NRESET (1 << 3) /* reset the onboard UDA1341. active low. */
-#define EGPIO_H3600_OPT_NVRAM_ON (1 << 4) /* apply power to optionpack nvram, active high. */
-#define EGPIO_H3600_OPT_ON (1 << 5) /* full power to option pack. active high. */
-#define EGPIO_H3600_LCD_ON (1 << 6) /* enable 3.3V to LCD. active high. */
-#define EGPIO_H3600_RS232_ON (1 << 7) /* UART3 transceiver force on. Active high. */
-#define EGPIO_H3600_LCD_PCI (1 << 8) /* LCD control IC enable. active high. */
-#define EGPIO_H3600_IR_ON (1 << 9) /* apply power to IR module. active high. */
-#define EGPIO_H3600_AUD_AMP_ON (1 << 10) /* apply power to audio power amp. active high. */
-#define EGPIO_H3600_AUD_PWR_ON (1 << 11) /* apply poewr to reset of audio circuit. active high. */
-#define EGPIO_H3600_QMUTE (1 << 12) /* mute control for onboard UDA1341. active high. */
-#define EGPIO_H3600_IR_FSEL (1 << 13) /* IR speed select: 1->fast, 0->slow */
-#define EGPIO_H3600_LCD_5V_ON (1 << 14) /* enable 5V to LCD. active high. */
-#define EGPIO_H3600_LVDD_ON (1 << 15) /* enable 9V and -6.5V to LCD. */
#ifndef __ASSEMBLY__
-#define H3600_EGPIO (*(volatile int *)0xf0000000)
-extern void clr_h3600_egpio(unsigned long x);
-extern void set_h3600_egpio(unsigned long x);
-#endif
+enum ipaq_model {
+ IPAQ_H3100,
+ IPAQ_H3600,
+ IPAQ_H3800
+};
+
+enum ipaq_egpio_type {
+ IPAQ_EGPIO_LCD_ON, /* Power to the LCD panel */
+ IPAQ_EGPIO_CODEC_NRESET, /* Clear to reset the audio codec (remember to return high) */
+ IPAQ_EGPIO_AUDIO_ON, /* Audio power */
+ IPAQ_EGPIO_QMUTE, /* Audio muting */
+ IPAQ_EGPIO_OPT_NVRAM_ON, /* Non-volatile RAM on extension sleeves (SPI interface) */
+ IPAQ_EGPIO_OPT_ON, /* Power to extension sleeves */
+ IPAQ_EGPIO_CARD_RESET, /* Reset PCMCIA cards on extension sleeve (???) */
+ IPAQ_EGPIO_OPT_RESET, /* Reset option pack (???) */
+ IPAQ_EGPIO_IR_ON, /* IR sensor/emitter power */
+ IPAQ_EGPIO_IR_FSEL, /* IR speed selection 1->fast, 0->slow */
+ IPAQ_EGPIO_RS232_ON, /* Maxim RS232 chip power */
+ IPAQ_EGPIO_VPP_ON, /* Turn on power to flash programming */
+};
+
+struct ipaq_model_ops {
+ enum ipaq_model model;
+ const char *generic_name;
+ void (*initialize)(void);
+ void (*control)(enum ipaq_egpio_type, int);
+ unsigned long (*read)(void);
+};
+
+extern struct ipaq_model_ops ipaq_model_ops;
+
+static __inline__ enum ipaq_model h3600_model( void ) {
+ return ipaq_model_ops.model;
+}
+
+static __inline__ const char * h3600_generic_name( void ) {
+ return ipaq_model_ops.generic_name;
+}
+
+static __inline__ void init_h3600_egpio( void ) {
+ if (ipaq_model_ops.initialize)
+ ipaq_model_ops.initialize();
+}
+
+static __inline__ void assign_h3600_egpio( enum ipaq_egpio_type x, int level ) {
+ if (ipaq_model_ops.control)
+ ipaq_model_ops.control(x,level);
+}
+
+static __inline__ void clr_h3600_egpio( enum ipaq_egpio_type x ) {
+ if (ipaq_model_ops.control)
+ ipaq_model_ops.control(x,0);
+}
+
+static __inline__ void set_h3600_egpio( enum ipaq_egpio_type x ) {
+ if (ipaq_model_ops.control)
+ ipaq_model_ops.control(x,1);
+}
+
+static __inline__ unsigned long read_h3600_egpio( void ) {
+ if (ipaq_model_ops.read)
+ return ipaq_model_ops.read();
+ return 0;
+}
+
+#endif /* ASSEMBLY */
-#endif
+#endif /* _INCLUDE_H3600_H_ */
diff --git a/include/asm-arm/arch-sa1100/h3600_gpio.h b/include/asm-arm/arch-sa1100/h3600_gpio.h
new file mode 100644
index 000000000..6b7e000a5
--- /dev/null
+++ b/include/asm-arm/arch-sa1100/h3600_gpio.h
@@ -0,0 +1,540 @@
+/*
+ *
+ * Definitions for H3600 Handheld Computer
+ *
+ * Copyright 2000 Compaq Computer Corporation.
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Author: Jamey Hicks.
+ *
+ * History:
+ *
+ * 2001-10-?? Andrew Christian Added support for iPAQ H3800
+ *
+ */
+
+#ifndef _INCLUDE_H3600_GPIO_H_
+#define _INCLUDE_H3600_GPIO_H_
+
+/*
+ * GPIO lines that are common across ALL iPAQ models are in "h3600.h"
+ * This file contains machine-specific definitions
+ */
+
+#define GPIO_H3600_SUSPEND GPIO_GPIO (0)
+/* GPIO[2:9] used by LCD on H3600/3800, used as GPIO on H3100 */
+#define GPIO_H3100_BT_ON GPIO_GPIO (2)
+#define GPIO_H3100_GPIO3 GPIO_GPIO (3)
+#define GPIO_H3100_QMUTE GPIO_GPIO (4)
+#define GPIO_H3100_LCD_3V_ON GPIO_GPIO (5)
+#define GPIO_H3100_AUD_ON GPIO_GPIO (6)
+#define GPIO_H3100_AUD_PWR_ON GPIO_GPIO (7)
+#define GPIO_H3100_IR_ON GPIO_GPIO (8)
+#define GPIO_H3100_IR_FSEL GPIO_GPIO (9)
+
+/* for H3600, audio sample rate clock generator */
+#define GPIO_H3600_CLK_SET0 GPIO_GPIO (12)
+#define GPIO_H3600_CLK_SET1 GPIO_GPIO (13)
+
+#define GPIO_H3600_ACTION_BUTTON GPIO_GPIO (18)
+#define GPIO_H3600_SOFT_RESET GPIO_GPIO (20) /* Also known as BATT_FAULT */
+#define GPIO_H3600_OPT_LOCK GPIO_GPIO (22)
+#define GPIO_H3600_OPT_DET GPIO_GPIO (27)
+
+/* H3800 specific pins */
+#define GPIO_H3800_AC_IN GPIO_GPIO (12)
+#define GPIO_H3800_COM_DSR GPIO_GPIO (13)
+#define GPIO_H3800_MMC_INT GPIO_GPIO (18)
+#define GPIO_H3800_NOPT_IND GPIO_GPIO (20) /* Almost exactly the same as GPIO_H3600_OPT_DET */
+#define GPIO_H3800_OPT_BAT_FAULT GPIO_GPIO (22)
+#define GPIO_H3800_CLK_OUT GPIO_GPIO (27)
+
+/****************************************************/
+
+#define IRQ_GPIO_H3600_ACTION_BUTTON IRQ_GPIO18
+#define IRQ_GPIO_H3600_OPT_DET IRQ_GPIO27
+
+#define IRQ_GPIO_H3800_MMC_INT IRQ_GPIO18
+#define IRQ_GPIO_H3800_NOPT_IND IRQ_GPIO20 /* almost same as OPT_DET */
+
+/* H3100 / 3600 EGPIO pins */
+#define EGPIO_H3600_VPP_ON (1 << 0)
+#define EGPIO_H3600_CARD_RESET (1 << 1) /* reset the attached pcmcia/compactflash card. active high. */
+#define EGPIO_H3600_OPT_RESET (1 << 2) /* reset the attached option pack. active high. */
+#define EGPIO_H3600_CODEC_NRESET (1 << 3) /* reset the onboard UDA1341. active low. */
+#define EGPIO_H3600_OPT_NVRAM_ON (1 << 4) /* apply power to optionpack nvram, active high. */
+#define EGPIO_H3600_OPT_ON (1 << 5) /* full power to option pack. active high. */
+#define EGPIO_H3600_LCD_ON (1 << 6) /* enable 3.3V to LCD. active high. */
+#define EGPIO_H3600_RS232_ON (1 << 7) /* UART3 transceiver force on. Active high. */
+
+/* H3600 only EGPIO pins */
+#define EGPIO_H3600_LCD_PCI (1 << 8) /* LCD control IC enable. active high. */
+#define EGPIO_H3600_IR_ON (1 << 9) /* apply power to IR module. active high. */
+#define EGPIO_H3600_AUD_AMP_ON (1 << 10) /* apply power to audio power amp. active high. */
+#define EGPIO_H3600_AUD_PWR_ON (1 << 11) /* apply power to reset of audio circuit. active high. */
+#define EGPIO_H3600_QMUTE (1 << 12) /* mute control for onboard UDA1341. active high. */
+#define EGPIO_H3600_IR_FSEL (1 << 13) /* IR speed select: 1->fast, 0->slow */
+#define EGPIO_H3600_LCD_5V_ON (1 << 14) /* enable 5V to LCD. active high. */
+#define EGPIO_H3600_LVDD_ON (1 << 15) /* enable 9V and -6.5V to LCD. */
+
+/********************* H3800, ASIC #2 ********************/
+
+#define _H3800_ASIC2_Base (H3600_EGPIO_VIRT)
+#define H3800_ASIC2_OFFSET(s,x,y) \
+ (*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC2_ ## x ## _Base + _H3800_ASIC2_ ## x ## _ ## y)))
+#define H3800_ASIC2_NOFFSET(s,x,n,y) \
+ (*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC2_ ## x ## _ ## n ## _Base + _H3800_ASIC2_ ## x ## _ ## y)))
+
+#define _H3800_ASIC2_GPIO_Base 0x0000
+#define _H3800_ASIC2_GPIO_Direction 0x0000 /* R/W, 16 bits 1:input, 0:output */
+#define _H3800_ASIC2_GPIO_InterruptType 0x0004 /* R/W, 12 bits 1:edge, 0:level */
+#define _H3800_ASIC2_GPIO_InterruptEdgeType 0x0008 /* R/W, 12 bits 1:rising, 0:falling */
+#define _H3800_ASIC2_GPIO_InterruptLevelType 0x000C /* R/W, 12 bits 1:high, 0:low */
+#define _H3800_ASIC2_GPIO_InterruptClear 0x0010 /* W, 12 bits */
+#define _H3800_ASIC2_GPIO_InterruptFlag 0x0010 /* R, 12 bits - reads int status */
+#define _H3800_ASIC2_GPIO_Data 0x0014 /* R/W, 16 bits */
+#define _H3800_ASIC2_GPIO_BattFaultOut 0x0018 /* R/W, 16 bit - sets level on batt fault */
+#define _H3800_ASIC2_GPIO_InterruptEnable 0x001c /* R/W, 12 bits 1:enable interrupt */
+#define _H3800_ASIC2_GPIO_Alternate 0x003c /* R/W, 12+1 bits - set alternate functions */
+
+#define H3800_ASIC2_GPIO_Direction H3800_ASIC2_OFFSET( u16, GPIO, Direction )
+#define H3800_ASIC2_GPIO_InterruptType H3800_ASIC2_OFFSET( u16, GPIO, InterruptType )
+#define H3800_ASIC2_GPIO_InterruptEdgeType H3800_ASIC2_OFFSET( u16, GPIO, InterruptEdgeType )
+#define H3800_ASIC2_GPIO_InterruptLevelType H3800_ASIC2_OFFSET( u16, GPIO, InterruptLevelType )
+#define H3800_ASIC2_GPIO_InterruptClear H3800_ASIC2_OFFSET( u16, GPIO, InterruptClear )
+#define H3800_ASIC2_GPIO_InterruptFlag H3800_ASIC2_OFFSET( u16, GPIO, InterruptFlag )
+#define H3800_ASIC2_GPIO_Data H3800_ASIC2_OFFSET( u16, GPIO, Data )
+#define H3800_ASIC2_GPIO_BattFaultOut H3800_ASIC2_OFFSET( u16, GPIO, BattFaultOut )
+#define H3800_ASIC2_GPIO_InterruptEnable H3800_ASIC2_OFFSET( u16, GPIO, InterruptEnable )
+#define H3800_ASIC2_GPIO_Alternate H3800_ASIC2_OFFSET( u16, GPIO, Alternate )
+
+#define GPIO_H3800_ASIC2_IN_Y1_N (1 << 0) /* Output: Touchscreen Y1 */
+#define GPIO_H3800_ASIC2_IN_X0 (1 << 1) /* Output: Touchscreen X0 */
+#define GPIO_H3800_ASIC2_IN_Y0 (1 << 2) /* Output: Touchscreen Y0 */
+#define GPIO_H3800_ASIC2_IN_X1_N (1 << 3) /* Output: Touchscreen X1 */
+#define GPIO_H3800_ASIC2_BT_RST (1 << 4) /* Output: Bluetooth reset */
+#define GPIO_H3800_ASIC2_PEN_IRQ (1 << 5) /* Input : Pen down */
+#define GPIO_H3800_ASIC2_SD_DETECT (1 << 6) /* Input : SD detect */
+#define GPIO_H3800_ASIC2_EAR_IN_N (1 << 7) /* Input : Audio jack plug inserted */
+#define GPIO_H3800_ASIC2_OPT_PCM_RESET (1 << 8) /* Output: */
+#define GPIO_H3800_ASIC2_OPT_RESET (1 << 9) /* Output: */
+#define GPIO_H3800_ASIC2_USB_DETECT_N (1 << 10) /* Input : */
+#define GPIO_H3800_ASIC2_SD_CON_SLT (1 << 11) /* Input : */
+
+#define _H3800_ASIC2_KPIO_Base 0x0200
+#define _H3800_ASIC2_KPIO_Direction 0x0000 /* R/W, 12 bits 1:input, 0:output */
+#define _H3800_ASIC2_KPIO_InterruptType 0x0004 /* R/W, 12 bits 1:edge, 0:level */
+#define _H3800_ASIC2_KPIO_InterruptEdgeType 0x0008 /* R/W, 12 bits 1:rising, 0:falling */
+#define _H3800_ASIC2_KPIO_InterruptLevelType 0x000C /* R/W, 12 bits 1:high, 0:low */
+#define _H3800_ASIC2_KPIO_InterruptClear 0x0010 /* W, 20 bits - 8 special */
+#define _H3800_ASIC2_KPIO_InterruptFlag 0x0010 /* R, 20 bits - 8 special - reads int status */
+#define _H3800_ASIC2_KPIO_Data 0x0014 /* R/W, 16 bits */
+#define _H3800_ASIC2_KPIO_BattFaultOut 0x0018 /* R/W, 16 bit - sets level on batt fault */
+#define _H3800_ASIC2_KPIO_InterruptEnable 0x001c /* R/W, 20 bits - 8 special */
+#define _H3800_ASIC2_KPIO_Alternate 0x003c /* R/W, 6 bits */
+
+#define H3800_ASIC2_KPIO_Direction H3800_ASIC2_OFFSET( u16, KPIO, Direction )
+#define H3800_ASIC2_KPIO_InterruptType H3800_ASIC2_OFFSET( u16, KPIO, InterruptType )
+#define H3800_ASIC2_KPIO_InterruptEdgeType H3800_ASIC2_OFFSET( u16, KPIO, InterruptEdgeType )
+#define H3800_ASIC2_KPIO_InterruptLevelType H3800_ASIC2_OFFSET( u16, KPIO, InterruptLevelType )
+#define H3800_ASIC2_KPIO_InterruptClear H3800_ASIC2_OFFSET( u32, KPIO, InterruptClear )
+#define H3800_ASIC2_KPIO_InterruptFlag H3800_ASIC2_OFFSET( u32, KPIO, InterruptFlag )
+#define H3800_ASIC2_KPIO_Data H3800_ASIC2_OFFSET( u16, KPIO, Data )
+#define H3800_ASIC2_KPIO_BattFaultOut H3800_ASIC2_OFFSET( u16, KPIO, BattFaultOut )
+#define H3800_ASIC2_KPIO_InterruptEnable H3800_ASIC2_OFFSET( u32, KPIO, InterruptEnable )
+#define H3800_ASIC2_KPIO_Alternate H3800_ASIC2_OFFSET( u16, KPIO, Alternate )
+
+#define H3800_ASIC2_KPIO_SPI_INT ( 1 << 16 )
+#define H3800_ASIC2_KPIO_OWM_INT ( 1 << 17 )
+#define H3800_ASIC2_KPIO_ADC_INT ( 1 << 18 )
+#define H3800_ASIC2_KPIO_UART_0_INT ( 1 << 19 )
+#define H3800_ASIC2_KPIO_UART_1_INT ( 1 << 20 )
+#define H3800_ASIC2_KPIO_TIMER_0_INT ( 1 << 21 )
+#define H3800_ASIC2_KPIO_TIMER_1_INT ( 1 << 22 )
+#define H3800_ASIC2_KPIO_TIMER_2_INT ( 1 << 23 )
+
+#define KPIO_H3800_ASIC2_RECORD_BTN_N (1 << 0) /* Record button */
+#define KPIO_H3800_ASIC2_KEY_5W1_N (1 << 1) /* Keypad */
+#define KPIO_H3800_ASIC2_KEY_5W2_N (1 << 2) /* */
+#define KPIO_H3800_ASIC2_KEY_5W3_N (1 << 3) /* */
+#define KPIO_H3800_ASIC2_KEY_5W4_N (1 << 4) /* */
+#define KPIO_H3800_ASIC2_KEY_5W5_N (1 << 5) /* */
+#define KPIO_H3800_ASIC2_KEY_LEFT_N (1 << 6) /* */
+#define KPIO_H3800_ASIC2_KEY_RIGHT_N (1 << 7) /* */
+#define KPIO_H3800_ASIC2_KEY_AP1_N (1 << 8) /* Old "Calendar" */
+#define KPIO_H3800_ASIC2_KEY_AP2_N (1 << 9) /* Old "Schedule" */
+#define KPIO_H3800_ASIC2_KEY_AP3_N (1 << 10) /* Old "Q" */
+#define KPIO_H3800_ASIC2_KEY_AP4_N (1 << 11) /* Old "Undo" */
+
+/* Alternate KPIO functions (set by default) */
+#define KPIO_ALT_H3800_ASIC2_KEY_5W1_N (1 << 1) /* Action key */
+#define KPIO_ALT_H3800_ASIC2_KEY_5W2_N (1 << 2) /* J1 of keypad input */
+#define KPIO_ALT_H3800_ASIC2_KEY_5W3_N (1 << 3) /* J2 of keypad input */
+#define KPIO_ALT_H3800_ASIC2_KEY_5W4_N (1 << 4) /* J3 of keypad input */
+#define KPIO_ALT_H3800_ASIC2_KEY_5W5_N (1 << 5) /* J4 of keypad input */
+
+#define _H3800_ASIC2_SPI_Base 0x0400
+#define _H3800_ASIC2_SPI_Control 0x0000 /* R/W 8 bits */
+#define _H3800_ASIC2_SPI_Data 0x0004 /* R/W 8 bits */
+#define _H3800_ASIC2_SPI_ChipSelectDisabled 0x0008 /* W 8 bits */
+
+#define H3800_ASIC2_SPI_Control H3800_ASIC2_OFFSET( u8, SPI, Control )
+#define H3800_ASIC2_SPI_Data H3800_ASIC2_OFFSET( u8, SPI, Data )
+#define H3800_ASIC2_SPI_ChipSelectDisabled H3800_ASIC2_OFFSET( u8, SPI, ChipSelectDisabled )
+
+#define _H3800_ASIC2_PWM_0_Base 0x0600
+#define _H3800_ASIC2_PWM_1_Base 0x0700
+#define _H3800_ASIC2_PWM_TimeBase 0x0000 /* R/W 6 bits */
+#define _H3800_ASIC2_PWM_PeriodTime 0x0004 /* R/W 12 bits */
+#define _H3800_ASIC2_PWM_DutyTime 0x0008 /* R/W 12 bits */
+
+#define H3800_ASIC2_PWM_0_TimeBase H3800_ASIC2_NOFFSET( u8, PWM, 0, TimeBase )
+#define H3800_ASIC2_PWM_0_PeriodTime H3800_ASIC2_NOFFSET( u16, PWM, 0, PeriodTime )
+#define H3800_ASIC2_PWM_0_DutyTime H3800_ASIC2_NOFFSET( u16, PWM, 0, DutyTime )
+
+#define H3800_ASIC2_PWM_1_TimeBase H3800_ASIC2_NOFFSET( u8, PWM, 1, TimeBase )
+#define H3800_ASIC2_PWM_1_PeriodTime H3800_ASIC2_NOFFSET( u16, PWM, 1, PeriodTime )
+#define H3800_ASIC2_PWM_1_DutyTime H3800_ASIC2_NOFFSET( u16, PWM, 1, DutyTime )
+
+#define H3800_ASIC2_PWM_TIMEBASE_MASK 0xf /* Low 4 bits sets time base, max = 8 */
+#define H3800_ASIC2_PWM_TIMEBASE_ENABLE ( 1 << 4 ) /* Enable clock */
+#define H3800_ASIC2_PWM_TIMEBASE_CLEAR ( 1 << 5 ) /* Clear the PWM */
+
+#define _H3800_ASIC2_LED_0_Base 0x0800
+#define _H3800_ASIC2_LED_1_Base 0x0880
+#define _H3800_ASIC2_LED_2_Base 0x0900
+#define _H3800_ASIC2_LED_TimeBase 0x0000 /* R/W 7 bits */
+#define _H3800_ASIC2_LED_PeriodTime 0x0004 /* R/W 12 bits */
+#define _H3800_ASIC2_LED_DutyTime 0x0008 /* R/W 12 bits */
+#define _H3800_ASIC2_LED_AutoStopCount 0x000c /* R/W 16 bits */
+
+#define H3800_ASIC2_LED_0_TimeBase H3800_ASIC2_NOFFSET( u8, LED, 0, TimeBase )
+#define H3800_ASIC2_LED_0_PeriodTime H3800_ASIC2_NOFFSET( u16, LED, 0, PeriodTime )
+#define H3800_ASIC2_LED_0_DutyTime H3800_ASIC2_NOFFSET( u16, LED, 0, DutyTime )
+#define H3800_ASIC2_LED_0_AutoStopClock H3800_ASIC2_NOFFSET( u16, LED, 0, AutoStopClock )
+
+#define H3800_ASIC2_LED_1_TimeBase H3800_ASIC2_NOFFSET( u8, LED, 1, TimeBase )
+#define H3800_ASIC2_LED_1_PeriodTime H3800_ASIC2_NOFFSET( u16, LED, 1, PeriodTime )
+#define H3800_ASIC2_LED_1_DutyTime H3800_ASIC2_NOFFSET( u16, LED, 1, DutyTime )
+#define H3800_ASIC2_LED_1_AutoStopClock H3800_ASIC2_NOFFSET( u16, LED, 1, AutoStopClock )
+
+#define H3800_ASIC2_LED_2_TimeBase H3800_ASIC2_NOFFSET( u8, LED, 2, TimeBase )
+#define H3800_ASIC2_LED_2_PeriodTime H3800_ASIC2_NOFFSET( u16, LED, 2, PeriodTime )
+#define H3800_ASIC2_LED_2_DutyTime H3800_ASIC2_NOFFSET( u16, LED, 2, DutyTime )
+#define H3800_ASIC2_LED_2_AutoStopClock H3800_ASIC2_NOFFSET( u16, LED, 2, AutoStopClock )
+
+#define H3800_ASIC2_LED_TIMEBASE_MASK 0x0f /* Low 4 bits sets time base, max = 13 */
+#define H3800_ASIC2_LED_TIMEBASE_BLINK ( 1 << 4 ) /* Enable blinking */
+#define H3800_ASIC2_LED_TIMEBASE_AUTOSTOP ( 1 << 5 )
+#define H3800_ASIC2_LED_TIMEBASE_ALWAYS ( 1 << 6 ) /* Enable blink always */
+
+#define _H3800_ASIC2_UART_0_Base 0x0A00
+#define _H3800_ASIC2_UART_1_Base 0x0C00
+#define _H3800_ASIC2_UART_Receive 0x0000 /* R 8 bits */
+#define _H3800_ASIC2_UART_Transmit 0x0000 /* W 8 bits */
+#define _H3800_ASIC2_UART_IntEnable 0x0004 /* R/W 8 bits */
+#define _H3800_ASIC2_UART_IntVerify 0x0008 /* R/W 8 bits */
+#define _H3800_ASIC2_UART_FIFOControl 0x000c /* R/W 8 bits */
+#define _H3800_ASIC2_UART_LineControl 0x0010 /* R/W 8 bits */
+#define _H3800_ASIC2_UART_ModemStatus 0x0014 /* R/W 8 bits */
+#define _H3800_ASIC2_UART_LineStatus 0x0018 /* R/W 8 bits */
+#define _H3800_ASIC2_UART_ScratchPad 0x001c /* R/W 8 bits */
+#define _H3800_ASIC2_UART_DivisorLatchL 0x0020 /* R/W 8 bits */
+#define _H3800_ASIC2_UART_DivisorLatchH 0x0024 /* R/W 8 bits */
+
+#define H3800_ASIC2_UART_0_Receive H3800_ASIC2_NOFFSET( u8, UART, 0, Receive )
+#define H3800_ASIC2_UART_0_Transmit H3800_ASIC2_NOFFSET( u8, UART, 0, Transmit )
+#define H3800_ASIC2_UART_0_IntEnable H3800_ASIC2_NOFFSET( u8, UART, 0, IntEnable )
+#define H3800_ASIC2_UART_0_IntVerify H3800_ASIC2_NOFFSET( u8, UART, 0, IntVerify )
+#define H3800_ASIC2_UART_0_FIFOControl H3800_ASIC2_NOFFSET( u8, UART, 0, FIFOControl )
+#define H3800_ASIC2_UART_0_LineControl H3800_ASIC2_NOFFSET( u8, UART, 0, LineControl )
+#define H3800_ASIC2_UART_0_ModemStatus H3800_ASIC2_NOFFSET( u8, UART, 0, ModemStatus )
+#define H3800_ASIC2_UART_0_LineStatus H3800_ASIC2_NOFFSET( u8, UART, 0, LineStatus )
+#define H3800_ASIC2_UART_0_ScratchPad H3800_ASIC2_NOFFSET( u8, UART, 0, ScratchPad )
+#define H3800_ASIC2_UART_0_DivisorLatchL H3800_ASIC2_NOFFSET( u8, UART, 0, DivisorLatchL )
+#define H3800_ASIC2_UART_0_DivisorLatchH H3800_ASIC2_NOFFSET( u8, UART, 0, DivisorLatchH )
+
+#define H3800_ASIC2_UART_1_Receive H3800_ASIC2_NOFFSET( u8, UART, 1, Receive )
+#define H3800_ASIC2_UART_1_Transmit H3800_ASIC2_NOFFSET( u8, UART, 1, Transmit )
+#define H3800_ASIC2_UART_1_IntEnable H3800_ASIC2_NOFFSET( u8, UART, 1, IntEnable )
+#define H3800_ASIC2_UART_1_IntVerify H3800_ASIC2_NOFFSET( u8, UART, 1, IntVerify )
+#define H3800_ASIC2_UART_1_FIFOControl H3800_ASIC2_NOFFSET( u8, UART, 1, FIFOControl )
+#define H3800_ASIC2_UART_1_LineControl H3800_ASIC2_NOFFSET( u8, UART, 1, LineControl )
+#define H3800_ASIC2_UART_1_ModemStatus H3800_ASIC2_NOFFSET( u8, UART, 1, ModemStatus )
+#define H3800_ASIC2_UART_1_LineStatus H3800_ASIC2_NOFFSET( u8, UART, 1, LineStatus )
+#define H3800_ASIC2_UART_1_ScratchPad H3800_ASIC2_NOFFSET( u8, UART, 1, ScratchPad )
+#define H3800_ASIC2_UART_1_DivisorLatchL H3800_ASIC2_NOFFSET( u8, UART, 1, DivisorLatchL )
+#define H3800_ASIC2_UART_1_DivisorLatchH H3800_ASIC2_NOFFSET( u8, UART, 1, DivisorLatchH )
+
+#define _H3800_ASIC2_TIMER_Base 0x0E00
+#define _H3800_ASIC2_TIMER_Command 0x0000 /* R/W 8 bits */
+
+#define H3800_ASIC2_TIMER_Command H3800_ASIC2_OFFSET( u8, Timer, Command )
+
+#define H3800_ASIC2_TIMER_GAT_0 ( 1 << 0 ) /* Gate enable, counter 0 */
+#define H3800_ASIC2_TIMER_GAT_1 ( 1 << 1 ) /* Gate enable, counter 1 */
+#define H3800_ASIC2_TIMER_GAT_2 ( 1 << 2 ) /* Gate enable, counter 2 */
+#define H3800_ASIC2_TIMER_CLK_0 ( 1 << 3 ) /* Clock enable, counter 0 */
+#define H3800_ASIC2_TIMER_CLK_1 ( 1 << 4 ) /* Clock enable, counter 1 */
+#define H3800_ASIC2_TIMER_CLK_2 ( 1 << 5 ) /* Clock enable, counter 2 */
+#define H3800_ASIC2_TIMER_MODE_0 ( 1 << 6 ) /* Mode 0 enable, counter 0 */
+#define H3800_ASIC2_TIMER_MODE_1 ( 1 << 7 ) /* Mode 0 enable, counter 1 */
+
+#define _H3800_ASIC2_CLOCK_Base 0x1000
+#define _H3800_ASIC2_CLOCK_Enable 0x0000 /* R/W 18 bits */
+
+#define H3800_ASIC2_CLOCK_Enable H3800_ASIC2_OFFSET( u32, CLOCK, Enable )
+
+#define H3800_ASIC2_CLOCK_AUDIO_1 0x0001 /* Enable 4.1 MHz clock for 8Khz and 4khz sample rate */
+#define H3800_ASIC2_CLOCK_AUDIO_2 0x0002 /* Enable 12.3 MHz clock for 48Khz and 32khz sample rate */
+#define H3800_ASIC2_CLOCK_AUDIO_3 0x0004 /* Enable 5.6 MHz clock for 11 kHZ sample rate */
+#define H3800_ASIC2_CLOCK_AUDIO_4 0x0008 /* Enable 11.289 MHz clock for 44 and 22 kHz sample rate */
+#define H3800_ASIC2_CLOCK_ADC ( 1 << 4 ) /* 1.024 MHz clock to ADC */
+#define H3800_ASIC2_CLOCK_SPI ( 1 << 5 ) /* 4.096 MHz clock to SPI */
+#define H3800_ASIC2_CLOCK_OWM ( 1 << 6 ) /* 4.096 MHz clock to OWM */
+#define H3800_ASIC2_CLOCK_PWM ( 1 << 7 ) /* 2.048 MHz clock to PWM */
+#define H3800_ASIC2_CLOCK_UART_1 ( 1 << 8 ) /* 24.576 MHz clock to UART1 (turn off bit 16) */
+#define H3800_ASIC2_CLOCK_UART_0 ( 1 << 9 ) /* 24.576 MHz clock to UART0 (turn off bit 17) */
+#define H3800_ASIC2_CLOCK_SD_1 ( 1 << 10 ) /* 16.934 MHz to SD */
+#define H3800_ASIC2_CLOCK_SD_2 ( 2 << 10 ) /* 24.576 MHz to SD */
+#define H3800_ASIC2_CLOCK_SD_3 ( 3 << 10 ) /* 33.869 MHz to SD */
+#define H3800_ASIC2_CLOCK_SD_4 ( 4 << 10 ) /* 49.152 MHz to SD */
+#define H3800_ASIC2_CLOCK_EX0 ( 1 << 13 ) /* Enable 32.768 kHz crystal */
+#define H3800_ASIC2_CLOCK_EX1 ( 1 << 14 ) /* Enable 24.576 MHz crystal */
+#define H3800_ASIC2_CLOCK_EX2 ( 1 << 15 ) /* Enable 33.869 MHz crystal */
+#define H3800_ASIC2_CLOCK_SLOW_UART_1 ( 1 << 16 ) /* Enable 3.686 MHz to UART1 (turn off bit 8) */
+#define H3800_ASIC2_CLOCK_SLOW_UART_0 ( 1 << 17 ) /* Enable 3.686 MHz to UART0 (turn off bit 9) */
+
+#define _H3800_ASIC2_ADC_Base 0x1200
+#define _H3800_ASIC2_ADC_Multiplexer 0x0000 /* R/W 4 bits - low 3 bits set channel */
+#define _H3800_ASIC2_ADC_ControlStatus 0x0004 /* R/W 8 bits */
+#define _H3800_ASIC2_ADC_Data 0x0008 /* R 10 bits */
+
+#define H3800_ASIC2_ADC_Multiplexer H3800_ASIC2_OFFSET( u8, ADC, Multiplexer )
+#define H3800_ASIC2_ADC_ControlStatus H3800_ASIC2_OFFSET( u8, ADC, ControlStatus )
+#define H3800_ASIC2_ADC_Data H3800_ASIC2_OFFSET( u16, ADC, Data )
+
+#define H3600_ASIC2_ADC_MUX_CHANNEL_MASK 0x07 /* Low 3 bits sets channel. max = 4 */
+#define H3600_ASIC2_ADC_MUX_CLKEN ( 1 << 3 ) /* Enable clock */
+
+#define H3600_ASIC2_ADC_CSR_ADPS_MASK 0x0f /* Low 4 bits sets prescale, max = 8 */
+#define H3600_ASIC2_ADC_CSR_FREE_RUN ( 1 << 4 )
+#define H3600_ASIC2_ADC_CSR_INT_ENABLE ( 1 << 5 )
+#define H3600_ASIC2_ADC_CSR_START ( 1 << 6 ) /* Set to start conversion. Goes to 0 when done */
+#define H3600_ASIC2_ADC_CSR_ENABLE ( 1 << 7 ) /* 1:power up ADC, 0:power down */
+
+
+#define _H3800_ASIC2_INTR_Base 0x1600
+#define _H3800_ASIC2_INTR_MaskAndFlag 0x0000 /* R/(W) 8bits */
+#define _H3800_ASIC2_INTR_ClockPrescale 0x0004 /* R/(W) 5bits */
+#define _H3800_ASIC2_INTR_TimerSet 0x0008 /* R/(W) 8bits */
+
+#define H3800_ASIC2_INTR_MaskAndFlag H3800_ASIC2_OFFSET( u8, INTR, MaskAndFlag )
+#define H3800_ASIC2_INTR_ClockPrescale H3800_ASIC2_OFFSET( u8, INTR, ClockPrescale )
+#define H3800_ASIC2_INTR_TimerSet H3800_ASIC2_OFFSET( u8, INTR, TimerSet )
+
+#define H3800_ASIC2_INTR_GLOBAL_MASK ( 1 << 0 ) /* Global interrupt mask */
+#define H3800_ASIC2_INTR_POWER_ON_RESET ( 1 << 1 ) /* 01: Power on reset (bits 1 & 2 ) */
+#define H3800_ASIC2_INTR_EXTERNAL_RESET ( 2 << 1 ) /* 10: External reset (bits 1 & 2 ) */
+#define H3800_ASIC2_INTR_MASK_UART_0 ( 1 << 4 )
+#define H3800_ASIC2_INTR_MASK_UART_1 ( 1 << 5 )
+#define H3800_ASIC2_INTR_MASK_TIMER ( 1 << 6 )
+#define H3800_ASIC2_INTR_MASK_OWM ( 1 << 7 )
+
+#define H3800_ASIC2_INTR_CLOCK_PRESCALE 0x0f /* 4 bits, max 14 */
+#define H3800_ASIC2_INTR_SET ( 1 << 4 ) /* Time base enable */
+
+
+#define _H3800_ASIC2_OWM_Base 0x1800
+#define _H3800_ASIC2_OWM_Command 0x0000 /* R/W 4 bits command register */
+#define _H3800_ASIC2_OWM_Data 0x0004 /* R/W 8 bits, transmit / receive buffer */
+#define _H3800_ASIC2_OWM_Interrupt 0x0008 /* R/W Command register */
+#define _H3800_ASIC2_OWM_InterruptEnable 0x000c /* R/W Command register */
+#define _H3800_ASIC2_OWM_ClockDivisor 0x0010 /* R/W 5 bits of divisor and pre-scale */
+
+#define H3800_ASIC2_OWM_Command H3800_ASIC2_OFFSET( u8, OWM, Command )
+#define H3800_ASIC2_OWM_Data H3800_ASIC2_OFFSET( u8, OWM, Data )
+#define H3800_ASIC2_OWM_Interrupt H3800_ASIC2_OFFSET( u8, OWM, Interrupt )
+#define H3800_ASIC2_OWM_InterruptEnable H3800_ASIC2_OFFSET( u8, OWM, InterruptEnable )
+#define H3800_ASIC2_OWM_ClockDivisor H3800_ASIC2_OFFSET( u8, OWM, ClockDivisor )
+
+#define H3800_ASIC2_OWM_CMD_ONE_WIRE_RESET ( 1 << 0 ) /* Set to force reset on 1-wire bus */
+#define H3800_ASIC2_OWM_CMD_SRA ( 1 << 1 ) /* Set to switch to Search ROM accelerator mode */
+#define H3800_ASIC2_OWM_CMD_DQ_OUTPUT ( 1 << 2 ) /* Write only - forces bus low */
+#define H3800_ASIC2_OWM_CMD_DQ_INPUT ( 1 << 3 ) /* Read only - reflects state of bus */
+
+#define H3800_ASIC2_OWM_INT_PD ( 1 << 0 ) /* Presence detect */
+#define H3800_ASIC2_OWM_INT_PDR ( 1 << 1 ) /* Presence detect result */
+#define H3800_ASIC2_OWM_INT_TBE ( 1 << 2 ) /* Transmit buffer empty */
+#define H3800_ASIC2_OWM_INT_TEMT ( 1 << 3 ) /* Transmit shift register empty */
+#define H3800_ASIC2_OWM_INT_RBF ( 1 << 4 ) /* Receive buffer full */
+
+#define H3800_ASIC2_OWM_INTEN_EPD ( 1 << 0 ) /* Enable receive buffer full interrupt */
+#define H3800_ASIC2_OWM_INTEN_IAS ( 1 << 1 ) /* Enable transmit shift register empty interrupt */
+#define H3800_ASIC2_OWM_INTEN_ETBE ( 1 << 2 ) /* Enable transmit buffer empty interrupt */
+#define H3800_ASIC2_OWM_INTEN_ETMT ( 1 << 3 ) /* INTR active state */
+#define H3800_ASIC2_OWM_INTEN_ERBF ( 1 << 4 ) /* Enable presence detect interrupt */
+
+#define _H3800_ASIC2_FlashCtl_Base 0x1A00
+
+/****************************************************/
+/* H3800, ASIC #1
+ * This ASIC is accesed through ASIC #2, and
+ * mapped into the 1c00 - 1f00 region
+ */
+
+#define H3800_ASIC1_OFFSET(s,x,y) \
+ (*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC1_ ## x ## _Base + (_H3800_ASIC1_ ## x ## _ ## y << 1))))
+
+#define _H3800_ASIC1_MMC_Base 0x1c00
+
+#define _H3800_ASIC1_MMC_StartStopClock 0x00 /* R/W 8bit */
+#define _H3800_ASIC1_MMC_Status 0x02 /* R See below, default 0x0040 */
+#define _H3800_ASIC1_MMC_ClockRate 0x04 /* R/W 8bit, low 3 bits are clock divisor */
+#define _H3800_ASIC1_MMC_SPIRegister 0x08 /* R/W 8bit, see below */
+#define _H3800_ASIC1_MMC_CmdDataCont 0x0a /* R/W 8bit, write to start MMC adapter */
+#define _H3800_ASIC1_MMC_ResponseTimeout 0x0c /* R/W 8bit, clocks before response timeout */
+#define _H3800_ASIC1_MMC_ReadTimeout 0x0e /* R/W 16bit, clocks before received data timeout */
+#define _H3800_ASIC1_MMC_BlockLength 0x10 /* R/W 10bit */
+#define _H3800_ASIC1_MMC_NumOfBlocks 0x12 /* R/W 16bit, in block mode, number of blocks */
+#define _H3800_ASIC1_MMC_InterruptMask 0x1a /* R/W 8bit */
+#define _H3800_ASIC1_MMC_CommandNumber 0x1c /* R/W 6 bits */
+#define _H3800_ASIC1_MMC_ArgumentH 0x1e /* R/W 16 bits */
+#define _H3800_ASIC1_MMC_ArgumentL 0x20 /* R/W 16 bits */
+#define _H3800_ASIC1_MMC_ResFifo 0x22 /* R 8 x 16 bits - contains response FIFO */
+#define _H3800_ASIC1_MMC_BufferPartFull 0x28 /* R/W 8 bits */
+
+#define H3800_ASIC1_MMC_StartStopClock H3800_ASIC1_OFFSET( u8, MMC, StartStopClock )
+#define H3800_ASIC1_MMC_Status H3800_ASIC1_OFFSET( u16, MMC, Status )
+#define H3800_ASIC1_MMC_ClockRate H3800_ASIC1_OFFSET( u8, MMC, ClockRate )
+#define H3800_ASIC1_MMC_SPIRegister H3800_ASIC1_OFFSET( u8, MMC, SPIRegister )
+#define H3800_ASIC1_MMC_CmdDataCont H3800_ASIC1_OFFSET( u8, MMC, CmdDataCont )
+#define H3800_ASIC1_MMC_ResponseTimeout H3800_ASIC1_OFFSET( u8, MMC, ResponseTimeout )
+#define H3800_ASIC1_MMC_ReadTimeout H3800_ASIC1_OFFSET( u16, MMC, ReadTimeout )
+#define H3800_ASIC1_MMC_BlockLength H3800_ASIC1_OFFSET( u16, MMC, BlockLength )
+#define H3800_ASIC1_MMC_NumOfBlocks H3800_ASIC1_OFFSET( u16, MMC, NumOfBlocks )
+#define H3800_ASIC1_MMC_InterruptMask H3800_ASIC1_OFFSET( u8, MMC, InterruptMask )
+#define H3800_ASIC1_MMC_CommandNumber H3800_ASIC1_OFFSET( u8, MMC, CommandNumber )
+#define H3800_ASIC1_MMC_ArgumentH H3800_ASIC1_OFFSET( u16, MMC, ArgumentH )
+#define H3800_ASIC1_MMC_ArgumentL H3800_ASIC1_OFFSET( u16, MMC, ArgumentL )
+#define H3800_ASIC1_MMC_ResFifo H3800_ASIC1_OFFSET( u16, MMC, ResFifo )
+#define H3800_ASIC1_MMC_BufferPartFull H3800_ASIC1_OFFSET( u8, MMC, BufferPartFull )
+
+#define H3800_ASIC1_MMC_STOP_CLOCK (1 << 0) /* Write to "StartStopClock" register */
+#define H3800_ASIC1_MMC_START_CLOCK (1 << 1)
+
+#define H3800_ASIC1_MMC_STATUS_READ_TIMEOUT (1 << 0)
+#define H3800_ASIC1_MMC_STATUS_RESPONSE_TIMEOUT (1 << 1)
+#define H3800_ASIC1_MMC_STATUS_CRC_WRITE_ERROR (1 << 2)
+#define H3800_ASIC1_MMC_STATUS_CRC_READ_ERROR (1 << 3)
+#define H3800_ASIC1_MMC_STATUS_SPI_READ_ERROR (1 << 4) /* SPI data token error received */
+#define H3800_ASIC1_MMC_STATUS_CRC_RESPONSE_ERROR (1 << 5)
+#define H3800_ASIC1_MMC_STATUS_FIFO_EMPTY (1 << 6)
+#define H3800_ASIC1_MMC_STATUS_FIFO_FULL (1 << 7)
+#define H3800_ASIC1_MMC_STATUS_CLOCK_ENABLE (1 << 8) /* MultiMediaCard clock stopped */
+#define H3800_ASIC1_MMC_STATUS_DATA_TRANSFER_DONE (1 << 11) /* Write operation, indicates transfer finished */
+#define H3800_ASIC1_MMC_STATUS_END_PROGRAM (1 << 12) /* End write and read operations */
+#define H3800_ASIC1_MMC_STATUS_END_COMMAND_RESPONSE (1 << 13) /* End command response */
+
+#define H3800_ASIC1_MMC_SPI_REG_SPI_ENABLE (1 << 0) /* Enables SPI mode */
+#define H3800_ASIC1_MMC_SPI_REG_CRC_ON (1 << 1) /* 1:turn on CRC */
+#define H3800_ASIC1_MMC_SPI_REG_SPI_CS_ENABLE (1 << 2) /* 1:turn on SPI CS */
+#define H3800_ASIC1_MMC_SPI_REG_CS_ADDRESS_MASK 0x38 /* Bits 3,4,5 are the SPI CS relative address */
+
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_NO_RESPONSE 0x00
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R1 0x01
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R2 0x02
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R3 0x03
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_DATA_ENABLE (1 << 2) /* This command contains a data transfer */
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_WRITE (1 << 3) /* This data transfer is a write */
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_STREAM_MODE (1 << 4) /* This data transfer is in stream mode */
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_BUSY_BIT (1 << 5) /* Busy signal expected after current cmd */
+#define H3800_ASIC1_MMC_CMD_DATA_CONT_INITIALIZE (1 << 6) /* Enables the 80 bits for initializing card */
+
+#define H3800_ASIC1_MMC_INT_MASK_DATA_TRANSFER_DONE (1 << 0)
+#define H3800_ASIC1_MMC_INT_MASK_PROGRAM_DONE (1 << 1)
+#define H3800_ASIC1_MMC_INT_MASK_END_COMMAND_RESPONSE (1 << 2)
+#define H3800_ASIC1_MMC_INT_MASK_BUFFER_READY (1 << 3)
+
+#define H3800_ASIC1_MMC_BUFFER_PART_FULL (1 << 0)
+
+/********* GPIO **********/
+
+#define _H3800_ASIC1_GPIO_Base 0x1e00
+
+#define _H3800_ASIC1_GPIO_Mask 0x30 /* R/W 0:don't mask, 1:mask interrupt */
+#define _H3800_ASIC1_GPIO_Direction 0x32 /* R/W 0:input, 1:output */
+#define _H3800_ASIC1_GPIO_Out 0x34 /* R/W 0:output low, 1:output high */
+#define _H3800_ASIC1_GPIO_TriggerType 0x36 /* R/W 0:level, 1:edge */
+#define _H3800_ASIC1_GPIO_EdgeTrigger 0x38 /* R/W 0:falling, 1:rising */
+#define _H3800_ASIC1_GPIO_LevelTrigger 0x3A /* R/W 0:low, 1:high level detect */
+#define _H3800_ASIC1_GPIO_LevelStatus 0x3C /* R/W 0:none, 1:detect */
+#define _H3800_ASIC1_GPIO_EdgeStatus 0x3E /* R/W 0:none, 1:detect */
+#define _H3800_ASIC1_GPIO_State 0x40 /* R See masks below (default 0) */
+#define _H3800_ASIC1_GPIO_Reset 0x42 /* R/W See masks below (default 0x04) */
+#define _H3800_ASIC1_GPIO_SleepMask 0x44 /* R/W 0:don't mask, 1:mask trigger in sleep mode */
+#define _H3800_ASIC1_GPIO_SleepDir 0x46 /* R/W direction 0:input, 1:ouput in sleep mode */
+#define _H3800_ASIC1_GPIO_SleepOut 0x48 /* R/W level 0:low, 1:high in sleep mode */
+#define _H3800_ASIC1_GPIO_Status 0x4A /* R Pin status */
+#define _H3800_ASIC1_GPIO_BattFaultDir 0x4C /* R/W direction 0:input, 1:output in batt_fault */
+#define _H3800_ASIC1_GPIO_BattFaultOut 0x4E /* R/W level 0:low, 1:high in batt_fault */
+
+#define H3800_ASIC1_GPIO_Mask H3800_ASIC1_OFFSET( u16, GPIO, Mask )
+#define H3800_ASIC1_GPIO_Direction H3800_ASIC1_OFFSET( u16, GPIO, Direction )
+#define H3800_ASIC1_GPIO_Out H3800_ASIC1_OFFSET( u16, GPIO, Out )
+#define H3800_ASIC1_GPIO_TriggerType H3800_ASIC1_OFFSET( u16, GPIO, TriggerType )
+#define H3800_ASIC1_GPIO_EdgeTrigger H3800_ASIC1_OFFSET( u16, GPIO, EdgeTrigger )
+#define H3800_ASIC1_GPIO_LevelTrigger H3800_ASIC1_OFFSET( u16, GPIO, LevelTrigger )
+#define H3800_ASIC1_GPIO_LevelStatus H3800_ASIC1_OFFSET( u16, GPIO, LevelStatus )
+#define H3800_ASIC1_GPIO_EdgeStatus H3800_ASIC1_OFFSET( u16, GPIO, EdgeStatus )
+#define H3800_ASIC1_GPIO_State H3800_ASIC1_OFFSET( u8, GPIO, State )
+#define H3800_ASIC1_GPIO_Reset H3800_ASIC1_OFFSET( u8, GPIO, Reset )
+#define H3800_ASIC1_GPIO_SleepMask H3800_ASIC1_OFFSET( u16, GPIO, SleepMask )
+#define H3800_ASIC1_GPIO_SleepDir H3800_ASIC1_OFFSET( u16, GPIO, SleepDir )
+#define H3800_ASIC1_GPIO_SleepOut H3800_ASIC1_OFFSET( u16, GPIO, SleepOut )
+#define H3800_ASIC1_GPIO_Status H3800_ASIC1_OFFSET( u16, GPIO, Status )
+#define H3800_ASIC1_GPIO_BattFaultDir H3800_ASIC1_OFFSET( u16, GPIO, BattFaultDir )
+#define H3800_ASIC1_GPIO_BattFaultOut H3800_ASIC1_OFFSET( u16, GPIO, BattFaultOut )
+
+#define H3800_ASIC1_GPIO_STATE_MASK (1 << 0)
+#define H3800_ASIC1_GPIO_STATE_DIRECTION (1 << 1)
+#define H3800_ASIC1_GPIO_STATE_OUT (1 << 2)
+#define H3800_ASIC1_GPIO_STATE_TRIGGER_TYPE (1 << 3)
+#define H3800_ASIC1_GPIO_STATE_EDGE_TRIGGER (1 << 4)
+#define H3800_ASIC1_GPIO_STATE_LEVEL_TRIGGER (1 << 5)
+
+#define H3800_ASIC1_GPIO_RESET_SOFTWARE (1 << 0)
+#define H3800_ASIC1_GPIO_RESET_AUTO_SLEEP (1 << 1)
+#define H3800_ASIC1_GPIO_RESET_FIRST_PWR_ON (1 << 2)
+
+/* These are all outputs */
+#define GPIO_H3800_ASIC1_IR_ON_N (1 << 0) /* Apply power to the IR Module */
+#define GPIO_H3800_ASIC1_SD_PWR_ON (1 << 1) /* Secure Digital power on */
+#define GPIO_H3800_ASIC1_RS232_ON (1 << 2) /* Turn on power to the RS232 chip ? */
+#define GPIO_H3800_ASIC1_PULSE_GEN (1 << 3) /* Goes to speaker / earphone */
+#define GPIO_H3800_ASIC1_CH_TIMER (1 << 4) /* */
+#define GPIO_H3800_ASIC1_LCD_5V_ON (1 << 5) /* Enables LCD_5V */
+#define GPIO_H3800_ASIC1_LCD_ON (1 << 6) /* Enables LCD_3V */
+#define GPIO_H3800_ASIC1_LCD_PCI (1 << 7) /* Connects to PDWN on LCD controller */
+#define GPIO_H3800_ASIC1_VGH_ON (1 << 8) /* Drives VGH on the LCD (+9??) */
+#define GPIO_H3800_ASIC1_VGL_ON (1 << 9) /* Drivers VGL on the LCD (-6??) */
+#define GPIO_H3800_ASIC1_FL_PWR_ON (1 << 10) /* Frontlight power on */
+#define GPIO_H3800_ASIC1_BT_PWR_ON (1 << 11) /* Bluetooth power on */
+#define GPIO_H3800_ASIC1_SPK_ON (1 << 12) /* */
+#define GPIO_H3800_ASIC1_EAR_ON_N (1 << 13) /* */
+#define GPIO_H3800_ASIC1_AUD_PWR_ON (1 << 14) /* */
+
+/* Write enable for the flash */
+
+#define _H3800_ASIC1_FlashWP_Base 0x1F00
+#define _H3800_ASIC1_FlashWP_VPP_ON 0x00 /* R 1: write, 0: protect */
+#define H3800_ASIC1_FlashWP_VPP_ON H3800_ASIC1_OFFSET( u8, FlashWP, VPP_ON )
+
+#endif /* _INCLUDE_H3600_GPIO_H_ */
diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
index e29df3d21..8ed40e5ef 100644
--- a/include/asm-arm/arch-sa1100/hardware.h
+++ b/include/asm-arm/arch-sa1100/hardware.h
@@ -60,6 +60,7 @@
( (((x)&0x00ffffff) | (((x)&(0x30000000>>VIO_SHIFT))<<VIO_SHIFT)) + PIO_START )
#ifndef __ASSEMBLY__
+#include <asm/types.h>
#if 0
# define __REG(x) (*((volatile u32 *)io_p2v(x)))
@@ -93,17 +94,12 @@ typedef struct { volatile u32 offset[4096]; } __regbase;
* This must be called *before* the corresponding IRQ is registered.
* Use this instead of directly setting GRER/GFER.
*/
+#define GPIO_NO_EDGES 0
#define GPIO_FALLING_EDGE 1
#define GPIO_RISING_EDGE 2
#define GPIO_BOTH_EDGES 3
#ifndef __ASSEMBLY__
extern void set_GPIO_IRQ_edge( int gpio_mask, int edge_mask );
-
-/*
- * Return the current CPU clock frequency in units of 100kHz
- */
-extern unsigned short get_cclk_frequency(void);
-
#endif
@@ -145,9 +141,7 @@ extern unsigned short get_cclk_frequency(void);
#include "empeg.h"
#endif
-#ifdef CONFIG_SA1100_H3600
#include "h3600.h"
-#endif
#ifdef CONFIG_SA1100_ITSY
#include "itsy.h"
@@ -185,6 +179,8 @@ extern unsigned short get_cclk_frequency(void);
#include "adsbitsy.h"
#endif
+#include "system3.h"
+
#ifdef CONFIG_SA1101
/*
@@ -211,19 +207,4 @@ extern unsigned short get_cclk_frequency(void);
#include "flexanet.h"
#endif
-#ifdef CONFIG_SA1111
-
-/*
- * The SA1111 is always located at virtual 0xf4000000.
- */
-
-#define SA1111_VBASE 0xf4000000
-
-#define SA1111_p2v( x ) ((x) - SA1111_BASE + SA1111_VBASE)
-#define SA1111_v2p( x ) ((x) - SA1111_VBASE + SA1111_BASE)
-
-#include "SA-1111.h"
-
-#endif
-
#endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-sa1100/io.h b/include/asm-arm/arch-sa1100/io.h
index 6b57f9e20..c7dea8038 100644
--- a/include/asm-arm/arch-sa1100/io.h
+++ b/include/asm-arm/arch-sa1100/io.h
@@ -20,13 +20,4 @@
#define __mem_pci(a) ((unsigned long)(a))
#define __mem_isa(a) ((unsigned long)(a))
-/*
- * Generic virtual read/write
- */
-#define __arch_getw(a) (*(volatile unsigned short *)(a))
-#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
-
-#define iomem_valid_addr(iomem,sz) (1)
-#define iomem_to_phys(iomem) (iomem)
-
#endif
diff --git a/include/asm-arm/arch-sa1100/irqs.h b/include/asm-arm/arch-sa1100/irqs.h
index 806efb138..cab7e59b1 100644
--- a/include/asm-arm/arch-sa1100/irqs.h
+++ b/include/asm-arm/arch-sa1100/irqs.h
@@ -4,154 +4,150 @@
* Copyright (C) 1996 Russell King
* Copyright (C) 1998 Deborah Wallach (updates for SA1100/Brutus).
* Copyright (C) 1999 Nicolas Pitre (full GPIO irq isolation)
+ *
+ * 2001/11/14 RMK Cleaned up and standardised a lot of the IRQs.
*/
-
#include <linux/config.h>
-#define SA1100_IRQ(x) (0 + (x))
-
-#define IRQ_GPIO0 SA1100_IRQ(0)
-#define IRQ_GPIO1 SA1100_IRQ(1)
-#define IRQ_GPIO2 SA1100_IRQ(2)
-#define IRQ_GPIO3 SA1100_IRQ(3)
-#define IRQ_GPIO4 SA1100_IRQ(4)
-#define IRQ_GPIO5 SA1100_IRQ(5)
-#define IRQ_GPIO6 SA1100_IRQ(6)
-#define IRQ_GPIO7 SA1100_IRQ(7)
-#define IRQ_GPIO8 SA1100_IRQ(8)
-#define IRQ_GPIO9 SA1100_IRQ(9)
-#define IRQ_GPIO10 SA1100_IRQ(10)
-#define IRQ_GPIO11_27 SA1100_IRQ(11)
-#define IRQ_LCD SA1100_IRQ(12) /* LCD controller */
-#define IRQ_Ser0UDC SA1100_IRQ(13) /* Ser. port 0 UDC */
-#define IRQ_Ser1SDLC SA1100_IRQ(14) /* Ser. port 1 SDLC */
-#define IRQ_Ser1UART SA1100_IRQ(15) /* Ser. port 1 UART */
-#define IRQ_Ser2ICP SA1100_IRQ(16) /* Ser. port 2 ICP */
-#define IRQ_Ser3UART SA1100_IRQ(17) /* Ser. port 3 UART */
-#define IRQ_Ser4MCP SA1100_IRQ(18) /* Ser. port 4 MCP */
-#define IRQ_Ser4SSP SA1100_IRQ(19) /* Ser. port 4 SSP */
-#define IRQ_DMA0 SA1100_IRQ(20) /* DMA controller channel 0 */
-#define IRQ_DMA1 SA1100_IRQ(21) /* DMA controller channel 1 */
-#define IRQ_DMA2 SA1100_IRQ(22) /* DMA controller channel 2 */
-#define IRQ_DMA3 SA1100_IRQ(23) /* DMA controller channel 3 */
-#define IRQ_DMA4 SA1100_IRQ(24) /* DMA controller channel 4 */
-#define IRQ_DMA5 SA1100_IRQ(25) /* DMA controller channel 5 */
-#define IRQ_OST0 SA1100_IRQ(26) /* OS Timer match 0 */
-#define IRQ_OST1 SA1100_IRQ(27) /* OS Timer match 1 */
-#define IRQ_OST2 SA1100_IRQ(28) /* OS Timer match 2 */
-#define IRQ_OST3 SA1100_IRQ(29) /* OS Timer match 3 */
-#define IRQ_RTC1Hz SA1100_IRQ(30) /* RTC 1 Hz clock */
-#define IRQ_RTCAlrm SA1100_IRQ(31) /* RTC Alarm */
-
-#define IRQ_GPIO_11_27(x) (32 + (x) - 11)
-
-#define IRQ_GPIO11 IRQ_GPIO_11_27(11)
-#define IRQ_GPIO12 IRQ_GPIO_11_27(12)
-#define IRQ_GPIO13 IRQ_GPIO_11_27(13)
-#define IRQ_GPIO14 IRQ_GPIO_11_27(14)
-#define IRQ_GPIO15 IRQ_GPIO_11_27(15)
-#define IRQ_GPIO16 IRQ_GPIO_11_27(16)
-#define IRQ_GPIO17 IRQ_GPIO_11_27(17)
-#define IRQ_GPIO18 IRQ_GPIO_11_27(18)
-#define IRQ_GPIO19 IRQ_GPIO_11_27(19)
-#define IRQ_GPIO20 IRQ_GPIO_11_27(20)
-#define IRQ_GPIO21 IRQ_GPIO_11_27(21)
-#define IRQ_GPIO22 IRQ_GPIO_11_27(22)
-#define IRQ_GPIO23 IRQ_GPIO_11_27(23)
-#define IRQ_GPIO24 IRQ_GPIO_11_27(24)
-#define IRQ_GPIO25 IRQ_GPIO_11_27(25)
-#define IRQ_GPIO26 IRQ_GPIO_11_27(26)
-#define IRQ_GPIO27 IRQ_GPIO_11_27(27)
-
-#define SA1100_GPIO_TO_IRQ(i) (((i) < 11) ? SA1100_IRQ(i) : IRQ_GPIO_11_27(i))
-
-/* To get the GPIO number from an IRQ number */
-#define GPIO_11_27_IRQ(i) (11 + (i) - 32)
-#define SA1100_IRQ_TO_GPIO(i) (((i) < 11) ? (i) : GPIO_11_27_IRQ(i))
-
-#define NR_IRQS (IRQ_GPIO27 + 1)
-
-
-#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || defined(CONFIG_SA1100_GRAPHICSMASTER)
-#define ADS_EXT_IRQ(x) (IRQ_GPIO27 + 1 + (x))
-#undef NR_IRQS
-#define NR_IRQS (ADS_EXT_IRQ(15) + 1)
-#endif
+#define IRQ_GPIO0 0
+#define IRQ_GPIO1 1
+#define IRQ_GPIO2 2
+#define IRQ_GPIO3 3
+#define IRQ_GPIO4 4
+#define IRQ_GPIO5 5
+#define IRQ_GPIO6 6
+#define IRQ_GPIO7 7
+#define IRQ_GPIO8 8
+#define IRQ_GPIO9 9
+#define IRQ_GPIO10 10
+#define IRQ_GPIO11_27 11
+#define IRQ_LCD 12 /* LCD controller */
+#define IRQ_Ser0UDC 13 /* Ser. port 0 UDC */
+#define IRQ_Ser1SDLC 14 /* Ser. port 1 SDLC */
+#define IRQ_Ser1UART 15 /* Ser. port 1 UART */
+#define IRQ_Ser2ICP 16 /* Ser. port 2 ICP */
+#define IRQ_Ser3UART 17 /* Ser. port 3 UART */
+#define IRQ_Ser4MCP 18 /* Ser. port 4 MCP */
+#define IRQ_Ser4SSP 19 /* Ser. port 4 SSP */
+#define IRQ_DMA0 20 /* DMA controller channel 0 */
+#define IRQ_DMA1 21 /* DMA controller channel 1 */
+#define IRQ_DMA2 22 /* DMA controller channel 2 */
+#define IRQ_DMA3 23 /* DMA controller channel 3 */
+#define IRQ_DMA4 24 /* DMA controller channel 4 */
+#define IRQ_DMA5 25 /* DMA controller channel 5 */
+#define IRQ_OST0 26 /* OS Timer match 0 */
+#define IRQ_OST1 27 /* OS Timer match 1 */
+#define IRQ_OST2 28 /* OS Timer match 2 */
+#define IRQ_OST3 29 /* OS Timer match 3 */
+#define IRQ_RTC1Hz 30 /* RTC 1 Hz clock */
+#define IRQ_RTCAlrm 31 /* RTC Alarm */
+
+#define IRQ_GPIO11 32
+#define IRQ_GPIO12 33
+#define IRQ_GPIO13 34
+#define IRQ_GPIO14 35
+#define IRQ_GPIO15 36
+#define IRQ_GPIO16 37
+#define IRQ_GPIO17 38
+#define IRQ_GPIO18 39
+#define IRQ_GPIO19 40
+#define IRQ_GPIO20 41
+#define IRQ_GPIO21 42
+#define IRQ_GPIO22 43
+#define IRQ_GPIO23 44
+#define IRQ_GPIO24 45
+#define IRQ_GPIO25 46
+#define IRQ_GPIO26 47
+#define IRQ_GPIO27 48
+/*
+ * To get the GPIO number from an IRQ number
+ */
+#define GPIO_11_27_IRQ(i) ((i) - 21)
-#if defined(CONFIG_SA1111)
+/*
+ * The next 16 interrupts are for board specific purposes. Since
+ * the kernel can only run on one machine at a time, we can re-use
+ * these. If you need more, increase IRQ_BOARD_END, but keep it
+ * within sensible limits. IRQs 49 to 64 are available.
+ */
+#define IRQ_BOARD_START 49
+#define IRQ_BOARD_END 65
+
+#define IRQ_SA1111_START (IRQ_BOARD_END)
+#define IRQ_GPAIN0 (IRQ_BOARD_END + 0)
+#define IRQ_GPAIN1 (IRQ_BOARD_END + 1)
+#define IRQ_GPAIN2 (IRQ_BOARD_END + 2)
+#define IRQ_GPAIN3 (IRQ_BOARD_END + 3)
+#define IRQ_GPBIN0 (IRQ_BOARD_END + 4)
+#define IRQ_GPBIN1 (IRQ_BOARD_END + 5)
+#define IRQ_GPBIN2 (IRQ_BOARD_END + 6)
+#define IRQ_GPBIN3 (IRQ_BOARD_END + 7)
+#define IRQ_GPBIN4 (IRQ_BOARD_END + 8)
+#define IRQ_GPBIN5 (IRQ_BOARD_END + 9)
+#define IRQ_GPCIN0 (IRQ_BOARD_END + 10)
+#define IRQ_GPCIN1 (IRQ_BOARD_END + 11)
+#define IRQ_GPCIN2 (IRQ_BOARD_END + 12)
+#define IRQ_GPCIN3 (IRQ_BOARD_END + 13)
+#define IRQ_GPCIN4 (IRQ_BOARD_END + 14)
+#define IRQ_GPCIN5 (IRQ_BOARD_END + 15)
+#define IRQ_GPCIN6 (IRQ_BOARD_END + 16)
+#define IRQ_GPCIN7 (IRQ_BOARD_END + 17)
+#define IRQ_MSTXINT (IRQ_BOARD_END + 18)
+#define IRQ_MSRXINT (IRQ_BOARD_END + 19)
+#define IRQ_MSSTOPERRINT (IRQ_BOARD_END + 20)
+#define IRQ_TPTXINT (IRQ_BOARD_END + 21)
+#define IRQ_TPRXINT (IRQ_BOARD_END + 22)
+#define IRQ_TPSTOPERRINT (IRQ_BOARD_END + 23)
+#define SSPXMTINT (IRQ_BOARD_END + 24)
+#define SSPRCVINT (IRQ_BOARD_END + 25)
+#define SSPROR (IRQ_BOARD_END + 26)
+#define AUDXMTDMADONEA (IRQ_BOARD_END + 32)
+#define AUDRCVDMADONEA (IRQ_BOARD_END + 33)
+#define AUDXMTDMADONEB (IRQ_BOARD_END + 34)
+#define AUDRCVDMADONEB (IRQ_BOARD_END + 35)
+#define AUDTFSR (IRQ_BOARD_END + 36)
+#define AUDRFSR (IRQ_BOARD_END + 37)
+#define AUDTUR (IRQ_BOARD_END + 38)
+#define AUDROR (IRQ_BOARD_END + 39)
+#define AUDDTS (IRQ_BOARD_END + 40)
+#define AUDRDD (IRQ_BOARD_END + 41)
+#define AUDSTO (IRQ_BOARD_END + 42)
+#define USBPWR (IRQ_BOARD_END + 43)
+#define NIRQHCIM (IRQ_BOARD_END + 44)
+#define IRQHCIBUFFACC (IRQ_BOARD_END + 45)
+#define IRQHCIRMTWKP (IRQ_BOARD_END + 46)
+#define NHCIMFCIR (IRQ_BOARD_END + 47)
+#define USB_PORT_RESUME (IRQ_BOARD_END + 48)
+#define S0_READY_NINT (IRQ_BOARD_END + 49)
+#define S1_READY_NINT (IRQ_BOARD_END + 50)
+#define S0_CD_VALID (IRQ_BOARD_END + 51)
+#define S1_CD_VALID (IRQ_BOARD_END + 52)
+#define S0_BVD1_STSCHG (IRQ_BOARD_END + 53)
+#define S1_BVD1_STSCHG (IRQ_BOARD_END + 54)
-#if defined(CONFIG_SA1100_GRAPHICSMASTER)
-#define SA1111_IRQ(x) (ADS_EXT_IRQ(15) + 1 + 1 + (x))
+/*
+ * Figure out the MAX IRQ number.
+ *
+ * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
+ * If graphicsclient or graphicsmaster, we don't have a SA1111.
+ * Otherwise, we have the standard IRQs only.
+ */
+#ifdef CONFIG_SA1111
+#define NR_IRQS (S1_BVD1_STSCHG + 1)
+#elif defined(CONFIG_SA1100_GRAPHICSCLIENT) || \
+ defined(CONFIG_SA1100_GRAPHICSMASTER)
+#define NR_IRQS (IRQ_BOARD_END)
#else
-#define SA1111_IRQ(x) (IRQ_GPIO27 + 1 + (x))
+#define NR_IRQS (IRQ_BOARD_START)
#endif
-#define GPAIN0 SA1111_IRQ(0)
-#define GPAIN1 SA1111_IRQ(1)
-#define GPAIN2 SA1111_IRQ(2)
-#define GPAIN3 SA1111_IRQ(3)
-#define GPBIN0 SA1111_IRQ(4)
-#define GPBIN1 SA1111_IRQ(5)
-#define GPBIN2 SA1111_IRQ(6)
-#define GPBIN3 SA1111_IRQ(7)
-#define GPBIN4 SA1111_IRQ(8)
-#define GPBIN5 SA1111_IRQ(9)
-#define GPCIN0 SA1111_IRQ(10)
-#define GPCIN1 SA1111_IRQ(11)
-#define GPCIN2 SA1111_IRQ(12)
-#define GPCIN3 SA1111_IRQ(13)
-#define GPCIN4 SA1111_IRQ(14)
-#define GPCIN5 SA1111_IRQ(15)
-#define GPCIN6 SA1111_IRQ(16)
-#define GPCIN7 SA1111_IRQ(17)
-#define MSTXINT SA1111_IRQ(18)
-#define MSRXINT SA1111_IRQ(19)
-#define MSSTOPERRINT SA1111_IRQ(20)
-#define TPTXINT SA1111_IRQ(21)
-#define TPRXINT SA1111_IRQ(22)
-#define TPSTOPERRINT SA1111_IRQ(23)
-#define SSPXMTINT SA1111_IRQ(24)
-#define SSPRCVINT SA1111_IRQ(25)
-#define SSPROR SA1111_IRQ(26)
-#define AUDXMTDMADONEA SA1111_IRQ(32)
-#define AUDRCVDMADONEA SA1111_IRQ(33)
-#define AUDXMTDMADONEB SA1111_IRQ(34)
-#define AUDRCVDMADONEB SA1111_IRQ(35)
-#define AUDTFSR SA1111_IRQ(36)
-#define AUDRFSR SA1111_IRQ(37)
-#define AUDTUR SA1111_IRQ(38)
-#define AUDROR SA1111_IRQ(39)
-#define AUDDTS SA1111_IRQ(40)
-#define AUDRDD SA1111_IRQ(41)
-#define AUDSTO SA1111_IRQ(42)
-#define USBPWR SA1111_IRQ(43)
-#define NIRQHCIM SA1111_IRQ(44)
-#define IRQHCIBUFFACC SA1111_IRQ(45)
-#define IRQHCIRMTWKP SA1111_IRQ(46)
-#define NHCIMFCIR SA1111_IRQ(47)
-#define USB_PORT_RESUME SA1111_IRQ(48)
-#define S0_READY_NINT SA1111_IRQ(49)
-#define S1_READY_NINT SA1111_IRQ(50)
-#define S0_CD_VALID SA1111_IRQ(51)
-#define S1_CD_VALID SA1111_IRQ(52)
-#define S0_BVD1_STSCHG SA1111_IRQ(53)
-#define S1_BVD1_STSCHG SA1111_IRQ(54)
-
-#define SA1111_IRQ_MAX SA1111_IRQ(54)
-
-#undef NR_IRQS
-#define NR_IRQS (SA1111_IRQ_MAX + 1)
-
-
-#ifdef CONFIG_ASSABET_NEPONSET
-
-#define MISC_IRQ0 SA1111_IRQ(55)
-#define MISC_IRQ1 SA1111_IRQ(56)
-
-#undef NR_IRQS
-#define NR_IRQS (SA1111_IRQ_MAX + 3)
-
-#endif /* CONFIG_ASSABET_NEPONSET */
+/*
+ * Board specific IRQs. Define them here.
+ * Do not surround them with ifdefs.
+ */
+#define IRQ_NEPONSET_SMC9196 (IRQ_BOARD_START + 0)
+#define IRQ_NEPONSET_USAR (IRQ_BOARD_START + 1)
-#endif /* CONFIG_SA1111 */
+/* PT Digital Board Interrupts (CONFIG_SA1100_PT_SYSTEM3) */
+#define IRQ_SYSTEM3_SMC9196 (IRQ_BOARD_START + 0)
diff --git a/include/asm-arm/arch-sa1100/keyboard.h b/include/asm-arm/arch-sa1100/keyboard.h
index 7439c09cf..0207ba65e 100644
--- a/include/asm-arm/arch-sa1100/keyboard.h
+++ b/include/asm-arm/arch-sa1100/keyboard.h
@@ -13,7 +13,7 @@
#define kbd_disable_irq() do { } while(0);
#define kbd_enable_irq() do { } while(0);
-extern void sa1111_kbd_init_hw(void);
+extern int sa1111_kbd_init_hw(void);
extern void gc_kbd_init_hw(void);
extern void smartio_kbd_init_hw(void);
extern void cerf_kbd_init_hw(void);
@@ -31,6 +31,11 @@ static inline void kbd_init_hw(void)
if (machine_is_cerf())
cerf_kbd_init_hw();
#endif
+#ifdef CONFIG_SA1100_PT_SYSTEM3
+ /* TODO: add system 3 board specific functions here */
+ if (machine_is_pt_system3())
+ sa1111_kbd_init_hw();
+#endif
}
#endif /* _SA1100_KEYBOARD_H */
diff --git a/include/asm-arm/arch-sa1100/pcmcia.h b/include/asm-arm/arch-sa1100/pcmcia.h
deleted file mode 100644
index b5c1b5676..000000000
--- a/include/asm-arm/arch-sa1100/pcmcia.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * linux/include/asm/arch/pcmcia.h
- *
- * Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
- *
- * This file contains definitions for the low-level SA-1100 kernel PCMCIA
- * interface. Please see linux/Documentation/arm/SA1100/PCMCIA for details.
- */
-
-#ifndef _ASM_ARCH_PCMCIA
-#define _ASM_ARCH_PCMCIA
-
-
-/* Ideally, we'd support up to MAX_SOCK sockets, but the SA-1100 only
- * has support for two. This shows up in lots of hardwired ways, such
- * as the fact that MECR only has enough bits to configure two sockets.
- * Since it's so entrenched in the hardware, limiting the software
- * in this way doesn't seem too terrible.
- */
-#define SA1100_PCMCIA_MAX_SOCK (2)
-
-
-#ifndef __ASSEMBLY__
-
-struct pcmcia_init {
- void (*handler)(int irq, void *dev, struct pt_regs *regs);
-};
-
-struct pcmcia_state {
- unsigned detect: 1,
- ready: 1,
- bvd1: 1,
- bvd2: 1,
- wrprot: 1,
- vs_3v: 1,
- vs_Xv: 1;
-};
-
-struct pcmcia_state_array {
- unsigned int size;
- struct pcmcia_state *state;
-};
-
-struct pcmcia_configure {
- unsigned sock: 8,
- vcc: 8,
- vpp: 8,
- output: 1,
- speaker: 1,
- reset: 1;
-};
-
-struct pcmcia_irq_info {
- unsigned int sock;
- unsigned int irq;
-};
-
-struct pcmcia_low_level {
- int (*init)(struct pcmcia_init *);
- int (*shutdown)(void);
- int (*socket_state)(struct pcmcia_state_array *);
- int (*get_irq_info)(struct pcmcia_irq_info *);
- int (*configure_socket)(const struct pcmcia_configure *);
-};
-
-extern struct pcmcia_low_level *pcmcia_low_level;
-
-#endif /* __ASSEMBLY__ */
-
-#endif
diff --git a/include/asm-arm/arch-sa1100/shannon.h b/include/asm-arm/arch-sa1100/shannon.h
new file mode 100644
index 000000000..ec27d6e12
--- /dev/null
+++ b/include/asm-arm/arch-sa1100/shannon.h
@@ -0,0 +1,43 @@
+#ifndef _INCLUDE_SHANNON_H
+#define _INCLUDE_SHANNON_H
+
+/* taken from comp.os.inferno Tue, 12 Sep 2000 09:21:50 GMT,
+ * written by <forsyth@vitanuova.com> */
+
+#define SHANNON_GPIO_SPI_FLASH GPIO_GPIO (0) /* Output - Driven low, enables SPI to flash */
+#define SHANNON_GPIO_SPI_DSP GPIO_GPIO (1) /* Output - Driven low, enables SPI to DSP */
+/* lcd lower = GPIO 2-9 */
+#define SHANNON_GPIO_SPI_OUTPUT GPIO_GPIO (10) /* Output - SPI output to DSP */
+#define SHANNON_GPIO_SPI_INPUT GPIO_GPIO (11) /* Input - SPI input from DSP */
+#define SHANNON_GPIO_SPI_CLOCK GPIO_GPIO (12) /* Output - Clock for SPI */
+#define SHANNON_GPIO_SPI_FRAME GPIO_GPIO (13) /* Output - Frame marker - not used */
+#define SHANNON_GPIO_SPI_RTS GPIO_GPIO (14) /* Input - SPI Ready to Send */
+#define SHANNON_IRQ_GPIO_SPI_RTS IRQ_GPIO14
+#define SHANNON_GPIO_SPI_CTS GPIO_GPIO (15) /* Output - SPI Clear to Send */
+#define SHANNON_GPIO_IRQ_CODEC GPIO_GPIO (16) /* in, irq from ucb1200 */
+#define SHANNON_IRQ_GPIO_IRQ_CODEC IRQ_GPIO16
+#define SHANNON_GPIO_DSP_RESET GPIO_GPIO (17) /* Output - Drive low to reset the DSP */
+#define SHANNON_GPIO_CODEC_RESET GPIO_GPIO (18) /* Output - Drive low to reset the UCB1x00 */
+#define SHANNON_GPIO_U3_RTS GPIO_GPIO (19) /* ?? */
+#define SHANNON_GPIO_U3_CTS GPIO_GPIO (20) /* ?? */
+#define SHANNON_GPIO_SENSE_12V GPIO_GPIO (21) /* Input, 12v flash unprotect detected */
+#define SHANNON_GPIO_DISP_EN GPIO_GPIO (22) /* out */
+/* XXX GPIO 23 unaccounted for */
+#define SHANNON_GPIO_EJECT_0 GPIO_GPIO (24) /* in */
+#define SHANNON_IRQ_GPIO_EJECT_0 IRQ_GPIO24
+#define SHANNON_GPIO_EJECT_1 GPIO_GPIO (25) /* in */
+#define SHANNON_IRQ_GPIO_EJECT_1 IRQ_GPIO25
+#define SHANNON_GPIO_RDY_0 GPIO_GPIO (26) /* in */
+#define SHANNON_IRQ_GPIO_RDY_0 IRQ_GPIO26
+#define SHANNON_GPIO_RDY_1 GPIO_GPIO (27) /* in */
+#define SHANNON_IRQ_GPIO_RDY_1 IRQ_GPIO27
+
+/* MCP UCB codec GPIO pins... */
+
+#define SHANNON_UCB_GPIO_BACKLIGHT 9
+#define SHANNON_UCB_GPIO_BRIGHT_MASK 7
+#define SHANNON_UCB_GPIO_BRIGHT 6
+#define SHANNON_UCB_GPIO_CONTRAST_MASK 0x3f
+#define SHANNON_UCB_GPIO_CONTRAST 0
+
+#endif
diff --git a/include/asm-arm/arch-sa1100/system3.h b/include/asm-arm/arch-sa1100/system3.h
new file mode 100644
index 000000000..11d24a5c1
--- /dev/null
+++ b/include/asm-arm/arch-sa1100/system3.h
@@ -0,0 +1,113 @@
+/*
+ * linux/include/asm-arm/arch-sa1100/system3.h
+ *
+ * Copyright (C) 2001 Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>
+ *
+ * $Id: system3.h,v 1.2.4.2 2001/12/04 14:58:50 seletz Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * $Log: system3.h,v $
+ * Revision 1.2.4.2 2001/12/04 14:58:50 seletz
+ * - removed neponset hack
+ * - removed irq definitions (now in irqs.h)
+ *
+ * Revision 1.2.4.1 2001/12/04 12:51:18 seletz
+ * - re-added from linux_2_4_8_ac12_rmk1_np1_pt1
+ *
+ * Revision 1.2.2.2 2001/11/16 13:58:43 seletz
+ * - simplified cpld register access
+ *
+ * Revision 1.2.2.1 2001/10/15 16:17:20 seletz
+ * - first revision
+ *
+ *
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error "include <asm/hardware.h> instead"
+#endif
+
+/* System 3 LCD */
+#define SYS3LCD SKPEN0
+#define SYS3LCDBACKL SKPEN1
+#define SYS3LCDBRIGHT SKPWM0
+#define SYS3LCDCONTR SKPWM1
+
+#define PT_CPLD_BASE (0x10000000)
+#define PT_SMC_BASE (0x18000000)
+#define PT_SA1111_BASE (0x40000000)
+
+#define SA1111_BASE PT_SA1111_BASE
+
+#define Ptcpld_p2v( x ) ((x) - PT_CPLD_BASE + 0xf3000000)
+#define Ptcpld_v2p( x ) ((x) - 0xf3000000 + PT_CPLD_BASE)
+
+#define _PT_SYSID ( PT_CPLD_BASE + 0x00 )
+#define _PT_IRQSR ( PT_CPLD_BASE + 0x24 )
+#define _PT_CTRL0 ( PT_CPLD_BASE + 0x90 )
+#define _PT_CTRL1 ( PT_CPLD_BASE + 0xA0 )
+#define _PT_CTRL2 ( PT_CPLD_BASE + 0xB0 )
+
+#define PT_SYSID (*((volatile u_char *)Ptcpld_p2v( _PT_SYSID )))
+#define PT_IRQSR (*((volatile u_char *)Ptcpld_p2v( _PT_IRQSR )))
+#define PT_CTRL0 (*((volatile u_char *)Ptcpld_p2v( _PT_CTRL0 )))
+#define PT_CTRL1 (*((volatile u_char *)Ptcpld_p2v( _PT_CTRL1 )))
+#define PT_CTRL2 (*((volatile u_char *)Ptcpld_p2v( _PT_CTRL2 )))
+
+#define PTCTRL0_set( x ) PT_CTRL0 |= (x)
+#define PTCTRL1_set( x ) PT_CTRL1 |= (x)
+#define PTCTRL2_set( x ) PT_CTRL2 |= (x)
+#define PTCTRL0_clear( x ) PT_CTRL0 &= ~(x)
+#define PTCTRL1_clear( x ) PT_CTRL1 &= ~(x)
+#define PTCTRL2_clear( x ) PT_CTRL2 &= ~(x)
+
+/* System ID register */
+
+/* IRQ Source Register */
+#define PT_IRQ_LAN ( 1<<0 )
+#define PT_IRQ_X ( 1<<1 )
+#define PT_IRQ_SA1111 ( 1<<2 )
+#define PT_IRQ_RS1 ( 1<<3 )
+#define PT_IRQ_RS1_RING ( 1<<4 )
+#define PT_IRQ_RS1_DCD ( 1<<5 )
+#define PT_IRQ_RS1_DSR ( 1<<6 )
+#define PT_IRQ_RS2 ( 1<<7 )
+
+/* FIXME */
+#define PT_IRQ_USAR ( 1<<1 )
+
+/* CTRL 0 */
+#define PT_CTRL0_USBSLAVE ( 1<<0 )
+#define PT_CTRL0_USBHOST ( 1<<1 )
+#define PT_CTRL0_LCD_BL ( 1<<2 )
+#define PT_CTRL0_LAN_EN ( 1<<3 ) /* active low */
+#define PT_CTRL0_IRDA_M(x) ( (((u_char)x)&0x03)<<4 )
+#define PT_CTRL0_IRDA_M0 ( 1<<4 )
+#define PT_CTRL0_IRDA_M1 ( 1<<5 )
+#define PT_CTRL0_IRDA_FSEL ( 1<<6 )
+#define PT_CTRL0_LCD_EN ( 1<<7 )
+
+#define PT_CTRL0_INIT ( PT_CTRL0_USBSLAVE | PT_CTRL0_USBHOST | \
+ PT_CTRL0_LCD_BL | PT_CTRL0_LAN_EN | PT_CTRL0_LCD_EN )
+
+/* CTRL 1 */
+#define PT_CTRL1_RS3_MUX(x) ( (((u_char)x)&0x03)<<0 )
+#define PT_CTRL1_RS3_MUX0 ( 1<<0 )
+#define PT_CTRL1_RS3_MUX1 ( 1<<1 )
+#define PT_CTRL1_RS3_RST ( 1<<2 )
+#define PT_CTRL1_RS3_RS485_TERM ( 1<<4 )
+#define PT_CTRL1_X ( 1<<4 )
+#define PT_CTRL1_PCMCIA_A0VPP ( 1<<6 )
+#define PT_CTRL1_PCMCIA_A1VPP ( 1<<7 )
+
+#define PT_RS3_MUX_ALIRS ( 0 )
+#define PT_RS3_MUX_IDATA ( 1 )
+#define PT_RS3_MUX_RADIO ( 2 )
+#define PT_RS3_MUX_RS485 ( 3 )
+
+/* CTRL 2 */
+#define PT_CTRL2_RS1_RTS ( 1<<0 )
+#define PT_CTRL2_RS1_DTR ( 1<<1 )
diff --git a/include/asm-arm/arch-sa1100/time.h b/include/asm-arm/arch-sa1100/time.h
index 701a9b94e..1f7dd3a84 100644
--- a/include/asm-arm/arch-sa1100/time.h
+++ b/include/asm-arm/arch-sa1100/time.h
@@ -10,7 +10,7 @@
*/
-#define RTC_DEF_DIVIDER 32768 - 1
+#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
static unsigned long __init sa1100_get_rtc_time(void)
@@ -63,29 +63,34 @@ static unsigned long sa1100_gettimeoffset (void)
return usec;
}
+/*
+ * We will be entered with IRQs enabled.
+ *
+ * Loop until we get ahead of the free running timer.
+ * This ensures an exact clock tick count and time acuracy.
+ * IRQs are disabled inside the loop to ensure coherence between
+ * lost_ticks (updated in do_timer()) and the match reg value, so we
+ * can use do_gettimeofday() from interrupt handlers.
+ */
static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- long flags;
- int next_match;
+ unsigned int next_match;
+ unsigned long flags;
- /* Loop until we get ahead of the free running timer.
- * This ensures an exact clock tick count and time acuracy.
- * IRQs are disabled inside the loop to ensure coherence between
- * lost_ticks (updated in do_timer()) and the match reg value, so we
- * can use do_gettimeofday() from interrupt handlers.
- */
do {
do_leds();
- do_set_rtc();
- save_flags_cli( flags );
+ local_irq_save(flags);
do_timer(regs);
OSSR = OSSR_M0; /* Clear match on timer 0 */
next_match = (OSMR0 += LATCH);
- restore_flags( flags );
- } while( (signed long)(next_match - OSCR) <= 0 );
+ local_irq_restore(flags);
+ do_set_rtc();
+ } while ((signed long)(next_match - OSCR) <= 0);
+
+ do_profile(regs);
}
-static inline void setup_timer (void)
+void __init time_init(void)
{
gettimeoffset = sa1100_gettimeoffset;
set_rtc = sa1100_set_rtc;
diff --git a/include/asm-arm/arch-shark/io.h b/include/asm-arm/arch-shark/io.h
index fd5ed3856..61abd02e5 100644
--- a/include/asm-arm/arch-shark/io.h
+++ b/include/asm-arm/arch-shark/io.h
@@ -11,9 +11,6 @@
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
-#define iomem_valid_addr(off,sz) (1)
-#define iomem_to_phys(off) (off)
-
#define IO_SPACE_LIMIT 0xffffffff
/*
@@ -182,9 +179,6 @@ DECLARE_IO(long,l,"")
#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
-#define __arch_getw(addr) (*(volatile unsigned short *)(addr))
-#define __arch_putw(b,addr) (*(volatile unsigned short *)(addr) = (b))
-
/*
* Translated address IO functions
*
diff --git a/include/asm-arm/arch-shark/irq.h b/include/asm-arm/arch-shark/irq.h
index 5618d11fa..ec5c9108b 100644
--- a/include/asm-arm/arch-shark/irq.h
+++ b/include/asm-arm/arch-shark/irq.h
@@ -7,118 +7,4 @@
* include/asm-arm/arch-ebsa110/irq.h
* Copyright (C) 1996-1998 Russell King
*/
-
-#include <asm/io.h>
#define fixup_irq(x) (x)
-
-/*
- * 8259A PIC functions to handle ISA devices:
- */
-
-/*
- * This contains the irq mask for both 8259A irq controllers,
- * Let through the cascade-interrupt no. 2 (ff-(1<<2)==fb)
- */
-static unsigned char cached_irq_mask[2] = { 0xfb, 0xff };
-
-/*
- * These have to be protected by the irq controller spinlock
- * before being called.
- */
-static void shark_disable_8259A_irq(unsigned int irq)
-{
- unsigned int mask;
- if (irq<8) {
- mask = 1 << irq;
- cached_irq_mask[0] |= mask;
- } else {
- mask = 1 << (irq-8);
- cached_irq_mask[1] |= mask;
- }
- outb(cached_irq_mask[1],0xA1);
- outb(cached_irq_mask[0],0x21);
-}
-
-static void shark_enable_8259A_irq(unsigned int irq)
-{
- unsigned int mask;
- if (irq<8) {
- mask = ~(1 << irq);
- cached_irq_mask[0] &= mask;
- } else {
- mask = ~(1 << (irq-8));
- cached_irq_mask[1] &= mask;
- }
- outb(cached_irq_mask[1],0xA1);
- outb(cached_irq_mask[0],0x21);
-}
-
-/*
- * Careful! The 8259A is a fragile beast, it pretty
- * much _has_ to be done exactly like this (mask it
- * first, _then_ send the EOI, and the order of EOI
- * to the two 8259s is important!
- */
-static void shark_mask_and_ack_8259A_irq(unsigned int irq)
-{
- if (irq & 8) {
- cached_irq_mask[1] |= 1 << (irq-8);
- inb(0xA1); /* DUMMY */
- outb(cached_irq_mask[1],0xA1);
- } else {
- cached_irq_mask[0] |= 1 << irq;
- outb(cached_irq_mask[0],0x21);
- }
-}
-
-static void bogus_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- printk("Got interrupt %i!\n",irq);
-}
-
-static struct irqaction cascade;
-
-static __inline__ void irq_init_irq(void)
-{
- int irq;
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
- irq_desc[irq].mask_ack = shark_mask_and_ack_8259A_irq;
- irq_desc[irq].mask = shark_disable_8259A_irq;
- irq_desc[irq].unmask = shark_enable_8259A_irq;
- }
-
- /* The PICs are initialized to level triggered and auto eoi!
- * If they are set to edge triggered they lose some IRQs,
- * if they are set to manual eoi they get locked up after
- * a short time
- */
-
- /* init master interrupt controller */
- outb(0x19, 0x20); /* Start init sequence, level triggered */
- outb(0x00, 0x21); /* Vector base */
- outb(0x04, 0x21); /* Cascade (slave) on IRQ2 */
- outb(0x03, 0x21); /* Select 8086 mode , auto eoi*/
- outb(0x0A, 0x20);
- /* init slave interrupt controller */
- outb(0x19, 0xA0); /* Start init sequence, level triggered */
- outb(0x08, 0xA1); /* Vector base */
- outb(0x02, 0xA1); /* Cascade (slave) on IRQ2 */
- outb(0x03, 0xA1); /* Select 8086 mode, auto eoi */
- outb(0x0A, 0xA0);
- outb(cached_irq_mask[1],0xA1);
- outb(cached_irq_mask[0],0x21);
- //request_region(0x20,0x2,"pic1");
- //request_region(0xA0,0x2,"pic2");
-
- cascade.handler = bogus_int;
- cascade.flags = 0;
- cascade.mask = 0;
- cascade.name = "cascade";
- cascade.next = NULL;
- cascade.dev_id = NULL;
- setup_arm_irq(2,&cascade);
-
-}
diff --git a/include/asm-arm/arch-shark/time.h b/include/asm-arm/arch-shark/time.h
index 50f781f9d..3d5bd8c0c 100644
--- a/include/asm-arm/arch-shark/time.h
+++ b/include/asm-arm/arch-shark/time.h
@@ -46,7 +46,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* Set up timer interrupt, and return the current time in seconds.
*/
-static inline void setup_timer(void)
+void __init time_init(void)
{
struct rtc_time r_time;
unsigned long flags;
diff --git a/include/asm-arm/arch-tbox/irq.h b/include/asm-arm/arch-tbox/irq.h
index 3e41df159..dd73ba795 100644
--- a/include/asm-arm/arch-tbox/irq.h
+++ b/include/asm-arm/arch-tbox/irq.h
@@ -10,41 +10,4 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
-#include <asm/io.h>
-
#define fixup_irq(x) (x)
-
-extern unsigned long soft_irq_mask;
-
-static void tbox_mask_irq(unsigned int irq)
-{
- __raw_writel(0, INTCONT + (irq << 2));
- soft_irq_mask &= ~(1<<irq);
-}
-
-static void tbox_unmask_irq(unsigned int irq)
-{
- soft_irq_mask |= (1<<irq);
- __raw_writel(1, INTCONT + (irq << 2));
-}
-
-static __inline__ void irq_init_irq(void)
-{
- unsigned int i;
-
- /* Disable all interrupts initially. */
- for (i = 0; i < NR_IRQS; i++) {
- if (i <= 10 || (i >= 12 && i <= 13)) {
- irq_desc[i].valid = 1;
- irq_desc[i].probe_ok = 0;
- irq_desc[i].mask_ack = tbox_mask_irq;
- irq_desc[i].mask = tbox_mask_irq;
- irq_desc[i].unmask = tbox_unmask_irq;
- tbox_mask_irq(i);
- } else {
- irq_desc[i].valid = 0;
- irq_desc[i].probe_ok = 0;
- }
- }
-}
diff --git a/include/asm-arm/arch-tbox/time.h b/include/asm-arm/arch-tbox/time.h
index 4d31c8ba6..fd0dab923 100644
--- a/include/asm-arm/arch-tbox/time.h
+++ b/include/asm-arm/arch-tbox/time.h
@@ -29,15 +29,8 @@ static void timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
do_timer(regs);
}
-static inline void setup_timer (void)
+void __init time_init(void)
{
- /*
- * Default the date to 1 Jan 1970 0:0:0
- * You will have to run a time daemon to set the
- * clock correctly at bootup
- */
- xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
-
timer_irq.handler = timer_interrupt;
setup_arm_irq(IRQ_TIMER, &timer_irq);
}
diff --git a/include/asm-arm/arch-tbox/vmalloc.h b/include/asm-arm/arch-tbox/vmalloc.h
index 31fe3e777..c2e21d5de 100644
--- a/include/asm-arm/arch-tbox/vmalloc.h
+++ b/include/asm-arm/arch-tbox/vmalloc.h
@@ -1,5 +1,5 @@
/*
- * linux/include/asm-arm/arch-rpc/vmalloc.h
+ * linux/include/asm-arm/arch-tbox/vmalloc.h
*/
/*
diff --git a/include/asm-arm/assembler.h b/include/asm-arm/assembler.h
index c3e44c921..de5f9ee4d 100644
--- a/include/asm-arm/assembler.h
+++ b/include/asm-arm/assembler.h
@@ -13,3 +13,16 @@
#include <asm/proc/ptrace.h>
#include <asm/proc/assembler.h>
+
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define pull lsr
+#define push lsl
+#define byte(x) (x*8)
+#else
+#define pull lsl
+#define push lsr
+#define byte(x) ((3-x)*8)
+#endif
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index d6419ddb4..dbb54a4d6 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -2,6 +2,8 @@
* Copyright 1995, Russell King.
* Various bits and pieces copyrights include:
* Linus Torvalds (test_bit).
+ * Big endian support: Copyright 2001, Nicolas Pitre
+ * reworked by rmk.
*
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
*
@@ -17,81 +19,271 @@
#ifdef __KERNEL__
+#include <asm/system.h>
+
#define smp_mb__before_clear_bit() do { } while (0)
#define smp_mb__after_clear_bit() do { } while (0)
/*
- * Function prototypes to keep gcc -Wall happy.
+ * These functions are the basis of our bit ops.
+ * First, the atomic bitops.
+ *
+ * The endian issue for these functions is handled by the macros below.
*/
-extern void set_bit(int nr, volatile void * addr);
+static inline void
+____atomic_set_bit_mask(unsigned int mask, volatile unsigned char *p)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *p |= mask;
+ local_irq_restore(flags);
+}
+
+static inline void
+____atomic_clear_bit_mask(unsigned int mask, volatile unsigned char *p)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *p &= ~mask;
+ local_irq_restore(flags);
+}
-static inline void __set_bit(int nr, volatile void *addr)
+static inline void
+____atomic_change_bit_mask(unsigned int mask, volatile unsigned char *p)
{
- ((unsigned char *) addr)[nr >> 3] |= (1U << (nr & 7));
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *p ^= mask;
+ local_irq_restore(flags);
}
-extern void clear_bit(int nr, volatile void * addr);
+static inline int
+____atomic_test_and_set_bit_mask(unsigned int mask, volatile unsigned char *p)
+{
+ unsigned long flags;
+ unsigned int res;
+
+ local_irq_save(flags);
+ res = *p;
+ *p = res | mask;
+ local_irq_restore(flags);
+
+ return res & mask;
+}
+
+static inline int
+____atomic_test_and_clear_bit_mask(unsigned int mask, volatile unsigned char *p)
+{
+ unsigned long flags;
+ unsigned int res;
+
+ local_irq_save(flags);
+ res = *p;
+ *p = res & ~mask;
+ local_irq_restore(flags);
+
+ return res & mask;
+}
-static inline void __clear_bit(int nr, volatile void *addr)
+static inline int
+____atomic_test_and_change_bit_mask(unsigned int mask, volatile unsigned char *p)
{
- ((unsigned char *) addr)[nr >> 3] &= ~(1U << (nr & 7));
+ unsigned long flags;
+ unsigned int res;
+
+ local_irq_save(flags);
+ res = *p;
+ *p = res ^ mask;
+ local_irq_restore(flags);
+
+ return res & mask;
}
-extern void change_bit(int nr, volatile void * addr);
+/*
+ * Now the non-atomic variants. We let the compiler handle all optimisations
+ * for these.
+ */
+static inline void ____nonatomic_set_bit(int nr, volatile void *p)
+{
+ ((unsigned char *) p)[nr >> 3] |= (1U << (nr & 7));
+}
-static inline void __change_bit(int nr, volatile void *addr)
+static inline void ____nonatomic_clear_bit(int nr, volatile void *p)
{
- ((unsigned char *) addr)[nr >> 3] ^= (1U << (nr & 7));
+ ((unsigned char *) p)[nr >> 3] &= ~(1U << (nr & 7));
}
-extern int test_and_set_bit(int nr, volatile void * addr);
+static inline void ____nonatomic_change_bit(int nr, volatile void *p)
+{
+ ((unsigned char *) p)[nr >> 3] ^= (1U << (nr & 7));
+}
-static inline int __test_and_set_bit(int nr, volatile void *addr)
+static inline int ____nonatomic_test_and_set_bit(int nr, volatile void *p)
{
unsigned int mask = 1 << (nr & 7);
unsigned int oldval;
- oldval = ((unsigned char *) addr)[nr >> 3];
- ((unsigned char *) addr)[nr >> 3] = oldval | mask;
+ oldval = ((unsigned char *) p)[nr >> 3];
+ ((unsigned char *) p)[nr >> 3] = oldval | mask;
return oldval & mask;
}
-extern int test_and_clear_bit(int nr, volatile void * addr);
-
-static inline int __test_and_clear_bit(int nr, volatile void *addr)
+static inline int ____nonatomic_test_and_clear_bit(int nr, volatile void *p)
{
unsigned int mask = 1 << (nr & 7);
unsigned int oldval;
- oldval = ((unsigned char *) addr)[nr >> 3];
- ((unsigned char *) addr)[nr >> 3] = oldval & ~mask;
+ oldval = ((unsigned char *) p)[nr >> 3];
+ ((unsigned char *) p)[nr >> 3] = oldval & ~mask;
return oldval & mask;
}
-extern int test_and_change_bit(int nr, volatile void * addr);
-
-static inline int __test_and_change_bit(int nr, volatile void *addr)
+static inline int ____nonatomic_test_and_change_bit(int nr, volatile void *p)
{
unsigned int mask = 1 << (nr & 7);
unsigned int oldval;
- oldval = ((unsigned char *) addr)[nr >> 3];
- ((unsigned char *) addr)[nr >> 3] = oldval ^ mask;
+ oldval = ((unsigned char *) p)[nr >> 3];
+ ((unsigned char *) p)[nr >> 3] = oldval ^ mask;
return oldval & mask;
}
-extern int find_first_zero_bit(void * addr, unsigned size);
-extern int find_next_zero_bit(void * addr, int size, int offset);
-
/*
* This routine doesn't need to be atomic.
*/
-static inline int test_bit(int nr, const void * addr)
+static inline int ____test_bit(int nr, const void * p)
{
- return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7));
+ return ((volatile unsigned char *) p)[nr >> 3] & (1U << (nr & 7));
}
/*
+ * A note about Endian-ness.
+ * -------------------------
+ *
+ * When the ARM is put into big endian mode via CR15, the processor
+ * merely swaps the order of bytes within words, thus:
+ *
+ * ------------ physical data bus bits -----------
+ * D31 ... D24 D23 ... D16 D15 ... D8 D7 ... D0
+ * little byte 3 byte 2 byte 1 byte 0
+ * big byte 0 byte 1 byte 2 byte 3
+ *
+ * This means that reading a 32-bit word at address 0 returns the same
+ * value irrespective of the endian mode bit.
+ *
+ * Peripheral devices should be connected with the data bus reversed in
+ * "Big Endian" mode. ARM Application Note 61 is applicable, and is
+ * available from http://www.arm.com/.
+ *
+ * The following assumes that the data bus connectivity for big endian
+ * mode has been followed.
+ *
+ * Note that bit 0 is defined to be 32-bit word bit 0, not byte 0 bit 0.
+ */
+
+/*
+ * Little endian assembly bitops. nr = 0 -> byte 0 bit 0.
+ */
+extern void _set_bit_le(int nr, volatile void * p);
+extern void _clear_bit_le(int nr, volatile void * p);
+extern void _change_bit_le(int nr, volatile void * p);
+extern int _test_and_set_bit_le(int nr, volatile void * p);
+extern int _test_and_clear_bit_le(int nr, volatile void * p);
+extern int _test_and_change_bit_le(int nr, volatile void * p);
+extern int _find_first_zero_bit_le(void * p, unsigned size);
+extern int _find_next_zero_bit_le(void * p, int size, int offset);
+
+/*
+ * Big endian assembly bitops. nr = 0 -> byte 3 bit 0.
+ */
+extern void _set_bit_be(int nr, volatile void * p);
+extern void _clear_bit_be(int nr, volatile void * p);
+extern void _change_bit_be(int nr, volatile void * p);
+extern int _test_and_set_bit_be(int nr, volatile void * p);
+extern int _test_and_clear_bit_be(int nr, volatile void * p);
+extern int _test_and_change_bit_be(int nr, volatile void * p);
+extern int _find_first_zero_bit_be(void * p, unsigned size);
+extern int _find_next_zero_bit_be(void * p, int size, int offset);
+
+
+/*
+ * The __* form of bitops are non-atomic and may be reordered.
+ */
+#define ATOMIC_BITOP_LE(name,nr,p) \
+ (__builtin_constant_p(nr) ? \
+ ____atomic_##name##_mask(1 << ((nr) & 7), \
+ ((unsigned char *)(p)) + ((nr) >> 3)) : \
+ _##name##_le(nr,p))
+
+#define ATOMIC_BITOP_BE(name,nr,p) \
+ (__builtin_constant_p(nr) ? \
+ ____atomic_##name##_mask(1 << ((nr) & 7), \
+ ((unsigned char *)(p)) + (((nr) >> 3) ^ 3)) : \
+ _##name##_be(nr,p))
+
+#define NONATOMIC_BITOP_LE(name,nr,p) \
+ (____nonatomic_##name(nr, p))
+
+#define NONATOMIC_BITOP_BE(name,nr,p) \
+ (____nonatomic_##name(nr ^ 0x18, p))
+
+#ifndef __ARMEB__
+/*
+ * These are the little endian, atomic definitions.
+ */
+#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p)
+#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p)
+#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p)
+#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
+#define test_bit(nr,p) ____test_bit(nr,p)
+#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
+#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
+
+/*
+ * These are the little endian, non-atomic definitions.
+ */
+#define __set_bit(nr,p) NONATOMIC_BITOP_LE(set_bit,nr,p)
+#define __clear_bit(nr,p) NONATOMIC_BITOP_LE(clear_bit,nr,p)
+#define __change_bit(nr,p) NONATOMIC_BITOP_LE(change_bit,nr,p)
+#define __test_and_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p)
+#define __test_and_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
+#define __test_and_change_bit(nr,p) NONATOMIC_BITOP_LE(test_and_change_bit,nr,p)
+#define __test_bit(nr,p) ____test_bit(nr,p)
+
+#else
+
+/*
+ * These are the big endian, atomic definitions.
+ */
+#define set_bit(nr,p) ATOMIC_BITOP_BE(set_bit,nr,p)
+#define clear_bit(nr,p) ATOMIC_BITOP_BE(clear_bit,nr,p)
+#define change_bit(nr,p) ATOMIC_BITOP_BE(change_bit,nr,p)
+#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
+#define test_bit(nr,p) ____test_bit((nr) ^ 0x18, p)
+#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
+#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
+
+/*
+ * These are the big endian, non-atomic definitions.
+ */
+#define __set_bit(nr,p) NONATOMIC_BITOP_BE(set_bit,nr,p)
+#define __clear_bit(nr,p) NONATOMIC_BITOP_BE(clear_bit,nr,p)
+#define __change_bit(nr,p) NONATOMIC_BITOP_BE(change_bit,nr,p)
+#define __test_and_set_bit(nr,p) NONATOMIC_BITOP_BE(test_and_set_bit,nr,p)
+#define __test_and_clear_bit(nr,p) NONATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
+#define __test_and_change_bit(nr,p) NONATOMIC_BITOP_BE(test_and_change_bit,nr,p)
+#define __test_bit(nr,p) ____test_bit((nr) ^ 0x18, p)
+
+#endif
+
+/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
*/
@@ -126,18 +318,25 @@ static inline unsigned long ffz(unsigned long word)
#define hweight16(x) generic_hweight16(x)
#define hweight8(x) generic_hweight8(x)
-#define ext2_set_bit test_and_set_bit
-#define ext2_clear_bit test_and_clear_bit
-#define ext2_test_bit test_bit
-#define ext2_find_first_zero_bit find_first_zero_bit
-#define ext2_find_next_zero_bit find_next_zero_bit
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+/*
+ * Ext2 is defined to use little-endian byte ordering.
+ * These do not need to be atomic.
+ */
+#define ext2_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p)
+#define ext2_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
+#define ext2_test_bit(nr,p) __test_bit(nr,p)
+#define ext2_find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
+#define ext2_find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
+
+/*
+ * Minix is defined to use little-endian byte ordering.
+ * These do not need to be atomic.
+ */
+#define minix_set_bit(nr,p) NONATOMIC_BITOP_LE(set_bit,nr,p)
+#define minix_test_bit(nr,p) __test_bit(nr,p)
+#define minix_test_and_set_bit(nr,p) NONATOMIC_BITOP_LE(test_and_set_bit,nr,p)
+#define minix_test_and_clear_bit(nr,p) NONATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
+#define minix_find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
#endif /* __KERNEL__ */
diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
index 342d1cf84..aa2e98d1f 100644
--- a/include/asm-arm/checksum.h
+++ b/include/asm-arm/checksum.h
@@ -55,25 +55,24 @@ ip_fast_csum(unsigned char * iph, unsigned int ihl)
unsigned int sum, tmp1;
__asm__ __volatile__(
- "ldr %0, [%1], #4 @ ip_fast_csum
- ldr %3, [%1], #4
- sub %2, %2, #5
- adds %0, %0, %3
- ldr %3, [%1], #4
- adcs %0, %0, %3
- ldr %3, [%1], #4
- adcs %0, %0, %3
-1: ldr %3, [%1], #4
- adcs %0, %0, %3
- tst %2, #15
- subne %2, %2, #1
- bne 1b
- adc %0, %0, #0
- adds %0, %0, %0, lsl #16
- addcs %0, %0, #0x10000
- mvn %0, %0
- mov %0, %0, lsr #16
- "
+ "ldr %0, [%1], #4 @ ip_fast_csum \n\
+ ldr %3, [%1], #4 \n\
+ sub %2, %2, #5 \n\
+ adds %0, %0, %3 \n\
+ ldr %3, [%1], #4 \n\
+ adcs %0, %0, %3 \n\
+ ldr %3, [%1], #4 \n\
+1: adcs %0, %0, %3 \n\
+ ldr %3, [%1], #4 \n\
+ tst %2, #15 @ do this carefully \n\
+ subne %2, %2, #1 @ without destroying \n\
+ bne 1b @ the carry flag \n\
+ adcs %0, %0, %3 \n\
+ adc %0, %0, #0 \n\
+ adds %0, %0, %0, lsl #16 \n\
+ addcs %0, %0, #0x10000 \n\
+ mvn %0, %0 \n\
+ mov %0, %0, lsr #16"
: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
: "1" (iph), "2" (ihl)
: "cc");
@@ -87,7 +86,7 @@ static inline unsigned int
csum_fold(unsigned int sum)
{
__asm__(
- "adds %0, %1, %1, lsl #16 @ csum_fold
+ "adds %0, %1, %1, lsl #16 @ csum_fold \n\
addcs %0, %0, #0x10000"
: "=r" (sum)
: "r" (sum)
@@ -100,10 +99,10 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
unsigned int proto, unsigned int sum)
{
__asm__(
- "adds %0, %1, %2 @ csum_tcpudp_nofold
- adcs %0, %0, %3
- adcs %0, %0, %4
- adcs %0, %0, %5
+ "adds %0, %1, %2 @ csum_tcpudp_nofold \n\
+ adcs %0, %0, %3 \n\
+ adcs %0, %0, %4 \n\
+ adcs %0, %0, %5 \n\
adc %0, %0, #0"
: "=&r"(sum)
: "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len) << 16), "Ir" (proto << 8)
@@ -119,13 +118,13 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
unsigned int proto, unsigned int sum)
{
__asm__(
- "adds %0, %1, %2 @ csum_tcpudp_magic
- adcs %0, %0, %3
- adcs %0, %0, %4
- adcs %0, %0, %5
- adc %0, %0, #0
- adds %0, %0, %0, lsl #16
- addcs %0, %0, #0x10000
+ "adds %0, %1, %2 @ csum_tcpudp_magic \n\
+ adcs %0, %0, %3 \n\
+ adcs %0, %0, %4 \n\
+ adcs %0, %0, %5 \n\
+ adc %0, %0, #0 \n\
+ adds %0, %0, %0, lsl #16 \n\
+ addcs %0, %0, #0x10000 \n\
mvn %0, %0"
: "=&r"(sum)
: "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len)), "Ir" (proto << 8)
diff --git a/include/asm-arm/cpu-multi32.h b/include/asm-arm/cpu-multi32.h
index 5348bb469..c7ce093e2 100644
--- a/include/asm-arm/cpu-multi32.h
+++ b/include/asm-arm/cpu-multi32.h
@@ -122,6 +122,11 @@ extern struct processor {
*/
void (*set_pte)(pte_t *ptep, pte_t pte);
} pgtable;
+
+ struct { /* other */
+ void (*clear_user_page)(void *page, unsigned long u_addr);
+ void (*copy_user_page)(void *to, void *from, unsigned long u_addr);
+ } misc;
} processor;
extern const struct processor arm6_processor_functions;
@@ -155,6 +160,9 @@ extern const struct processor sa110_processor_functions;
#define cpu_set_pmd(pmdp, pmd) processor.pgtable.set_pmd(pmdp, pmd)
#define cpu_set_pte(ptep, pte) processor.pgtable.set_pte(ptep, pte)
+#define cpu_copy_user_page(to,from,uaddr) processor.misc.copy_user_page(to,from,uaddr)
+#define cpu_clear_user_page(page,uaddr) processor.misc.clear_user_page(page,uaddr)
+
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
#define cpu_get_pgd() \
diff --git a/include/asm-arm/cpu-single.h b/include/asm-arm/cpu-single.h
index 0c561b703..974255464 100644
--- a/include/asm-arm/cpu-single.h
+++ b/include/asm-arm/cpu-single.h
@@ -11,43 +11,40 @@
* Single CPU
*/
#ifdef __STDC__
-#define __cpu_fn(name,x) cpu_##name##x
+#define __catify_fn(name,x) name##x
#else
-#define __cpu_fn(name,x) cpu_/**/name/**/x
+#define __catify_fn(name,x) name/**/x
#endif
-#define cpu_fn(name,x) __cpu_fn(name,x)
+#define __cpu_fn(name,x) __catify_fn(name,x)
/*
* If we are supporting multiple CPUs, then we must use a table of
* function pointers for this lot. Otherwise, we can optimise the
* table away.
*/
-#define cpu_data_abort cpu_fn(CPU_NAME,_data_abort)
-#define cpu_check_bugs cpu_fn(CPU_NAME,_check_bugs)
-#define cpu_proc_init cpu_fn(CPU_NAME,_proc_init)
-#define cpu_proc_fin cpu_fn(CPU_NAME,_proc_fin)
-#define cpu_reset cpu_fn(CPU_NAME,_reset)
-#define cpu_do_idle cpu_fn(CPU_NAME,_do_idle)
-
-#define cpu_cache_clean_invalidate_all cpu_fn(CPU_NAME,_cache_clean_invalidate_all)
-#define cpu_cache_clean_invalidate_range cpu_fn(CPU_NAME,_cache_clean_invalidate_range)
-#define cpu_flush_ram_page cpu_fn(CPU_NAME,_flush_ram_page)
-
-#define cpu_dcache_invalidate_range cpu_fn(CPU_NAME,_dcache_invalidate_range)
-#define cpu_dcache_clean_range cpu_fn(CPU_NAME,_dcache_clean_range)
-#define cpu_dcache_clean_page cpu_fn(CPU_NAME,_dcache_clean_page)
-#define cpu_dcache_clean_entry cpu_fn(CPU_NAME,_dcache_clean_entry)
-
-#define cpu_icache_invalidate_range cpu_fn(CPU_NAME,_icache_invalidate_range)
-#define cpu_icache_invalidate_page cpu_fn(CPU_NAME,_icache_invalidate_page)
-
-#define cpu_tlb_invalidate_all cpu_fn(CPU_NAME,_tlb_invalidate_all)
-#define cpu_tlb_invalidate_range cpu_fn(CPU_NAME,_tlb_invalidate_range)
-#define cpu_tlb_invalidate_page cpu_fn(CPU_NAME,_tlb_invalidate_page)
-
-#define cpu_set_pgd cpu_fn(CPU_NAME,_set_pgd)
-#define cpu_set_pmd cpu_fn(CPU_NAME,_set_pmd)
-#define cpu_set_pte cpu_fn(CPU_NAME,_set_pte)
+#define cpu_data_abort __cpu_fn(CPU_ABRT,_abort)
+#define cpu_check_bugs __cpu_fn(CPU_NAME,_check_bugs)
+#define cpu_proc_init __cpu_fn(CPU_NAME,_proc_init)
+#define cpu_proc_fin __cpu_fn(CPU_NAME,_proc_fin)
+#define cpu_reset __cpu_fn(CPU_NAME,_reset)
+#define cpu_do_idle __cpu_fn(CPU_NAME,_do_idle)
+#define cpu_cache_clean_invalidate_all __cpu_fn(CPU_NAME,_cache_clean_invalidate_all)
+#define cpu_cache_clean_invalidate_range __cpu_fn(CPU_NAME,_cache_clean_invalidate_range)
+#define cpu_flush_ram_page __cpu_fn(CPU_NAME,_flush_ram_page)
+#define cpu_dcache_invalidate_range __cpu_fn(CPU_NAME,_dcache_invalidate_range)
+#define cpu_dcache_clean_range __cpu_fn(CPU_NAME,_dcache_clean_range)
+#define cpu_dcache_clean_page __cpu_fn(CPU_NAME,_dcache_clean_page)
+#define cpu_dcache_clean_entry __cpu_fn(CPU_NAME,_dcache_clean_entry)
+#define cpu_icache_invalidate_range __cpu_fn(CPU_NAME,_icache_invalidate_range)
+#define cpu_icache_invalidate_page __cpu_fn(CPU_NAME,_icache_invalidate_page)
+#define cpu_tlb_invalidate_all __cpu_fn(CPU_NAME,_tlb_invalidate_all)
+#define cpu_tlb_invalidate_range __cpu_fn(CPU_NAME,_tlb_invalidate_range)
+#define cpu_tlb_invalidate_page __cpu_fn(CPU_NAME,_tlb_invalidate_page)
+#define cpu_set_pgd __cpu_fn(CPU_NAME,_set_pgd)
+#define cpu_set_pmd __cpu_fn(CPU_NAME,_set_pmd)
+#define cpu_set_pte __cpu_fn(CPU_NAME,_set_pte)
+#define cpu_copy_user_page __cpu_fn(MMU_ARCH,_copy_user_page)
+#define cpu_clear_user_page __cpu_fn(MMU_ARCH,_clear_user_page)
#ifndef __ASSEMBLY__
@@ -83,6 +80,10 @@ extern void cpu_tlb_invalidate_page(unsigned long address, int flags);
extern void cpu_set_pgd(unsigned long pgd_phys);
extern void cpu_set_pmd(pmd_t *pmdp, pmd_t pmd);
extern void cpu_set_pte(pte_t *ptep, pte_t pte);
+
+extern void cpu_copy_user_page(void *to, void *from, unsigned long u_addr);
+extern void cpu_clear_user_page(void *page, unsigned long u_addr);
+
extern volatile void cpu_reset(unsigned long addr);
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
diff --git a/include/asm-arm/hardware/clps7111.h b/include/asm-arm/hardware/clps7111.h
index 491dd73bf..8d3228dc1 100644
--- a/include/asm-arm/hardware/clps7111.h
+++ b/include/asm-arm/hardware/clps7111.h
@@ -27,8 +27,10 @@
#ifndef __ASSEMBLY__
#define clps_readb(off) __raw_readb(CLPS7111_BASE + (off))
+#define clps_readw(off) __raw_readw(CLPS7111_BASE + (off))
#define clps_readl(off) __raw_readl(CLPS7111_BASE + (off))
#define clps_writeb(val,off) __raw_writeb(val, CLPS7111_BASE + (off))
+#define clps_writew(val,off) __raw_writew(val, CLPS7111_BASE + (off))
#define clps_writel(val,off) __raw_writel(val, CLPS7111_BASE + (off))
#endif
@@ -48,6 +50,7 @@
#define INTSR1 (0x0240)
#define INTMR1 (0x0280)
#define LCDCON (0x02c0)
+#define TC1D (0x0300)
#define TC2D (0x0340)
#define RTCDR (0x0380)
#define RTCMR (0x03c0)
diff --git a/include/asm-arm/hardware/cs89712.h b/include/asm-arm/hardware/cs89712.h
new file mode 100644
index 000000000..ad99a3e1b
--- /dev/null
+++ b/include/asm-arm/hardware/cs89712.h
@@ -0,0 +1,49 @@
+/*
+ * linux/include/asm-arm/hardware/cs89712.h
+ *
+ * This file contains the hardware definitions of the CS89712
+ * additional internal registers.
+ *
+ * Copyright (C) 2001 Thomas Gleixner autronix automation <gleixner@autronix.de>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ASM_HARDWARE_CS89712_H
+#define __ASM_HARDWARE_CS89712_H
+
+/*
+* CS89712 additional registers
+*/
+
+#define PCDR 0x0002 /* Port C Data register ---------------------------- */
+#define PCDDR 0x0042 /* Port C Data Direction register ------------------ */
+#define SDCONF 0x2300 /* SDRAM Configuration register ---------------------*/
+#define SDRFPR 0x2340 /* SDRAM Refresh period register --------------------*/
+
+#define SDCONF_ACTIVE (1 << 10)
+#define SDCONF_CLKCTL (1 << 9)
+#define SDCONF_WIDTH_4 (0 << 7)
+#define SDCONF_WIDTH_8 (1 << 7)
+#define SDCONF_WIDTH_16 (2 << 7)
+#define SDCONF_WIDTH_32 (3 << 7)
+#define SDCONF_SIZE_16 (0 << 5)
+#define SDCONF_SIZE_64 (1 << 5)
+#define SDCONF_SIZE_128 (2 << 5)
+#define SDCONF_SIZE_256 (3 << 5)
+#define SDCONF_CASLAT_2 (2)
+#define SDCONF_CASLAT_3 (3)
+
+#endif /* __ASM_HARDWARE_CS89712_H */
diff --git a/include/asm-arm/hardware/ep7212.h b/include/asm-arm/hardware/ep7212.h
index 16deaf2b3..0e952e747 100644
--- a/include/asm-arm/hardware/ep7212.h
+++ b/include/asm-arm/hardware/ep7212.h
@@ -23,8 +23,6 @@
#ifndef __ASM_HARDWARE_EP7212_H
#define __ASM_HARDWARE_EP7212_H
-#include <linux/config.h>
-
/*
* define EP7212_BASE to be the base address of the region
* you want to access.
@@ -49,10 +47,6 @@
#define INTSR3 0x2240
#define INTMR3 0x2280
#define LEDFLSH 0x22c0
-#if defined (CONFIG_ARCH_CDB89712)
-#define SDCONF 0x2300
-#define SDRFPR 0x2340
-#endif
#define DAIR_DAIEN (1 << 16)
#define DAIR_ECS (1 << 17)
@@ -86,19 +80,4 @@
#define SYSCON3_FASTWAKE (1 << 8)
#define SYSCON3_DAIEN (1 << 9)
-#if defined (CONFIG_ARCH_CDB89712)
-#define SDCONF_ACTIVE (1 << 10)
-#define SDCONF_CLKCTL (1 << 9)
-#define SDCONF_WIDTH_4 (0 << 7)
-#define SDCONF_WIDTH_8 (1 << 7)
-#define SDCONF_WIDTH_16 (2 << 7)
-#define SDCONF_WIDTH_32 (3 << 7)
-#define SDCONF_SIZE_16 (0 << 5)
-#define SDCONF_SIZE_64 (1 << 5)
-#define SDCONF_SIZE_128 (2 << 5)
-#define SDCONF_SIZE_256 (3 << 5)
-#define SDCONF_CASLAT_2 (2)
-#define SDCONF_CASLAT_3 (3)
-#endif
-
#endif /* __ASM_HARDWARE_EP7212_H */
diff --git a/include/asm-arm/hardware/ioc.h b/include/asm-arm/hardware/ioc.h
index 644aebdb2..b3b46ef65 100644
--- a/include/asm-arm/hardware/ioc.h
+++ b/include/asm-arm/hardware/ioc.h
@@ -19,8 +19,8 @@
* We use __raw_base variants here so that we give the compiler the
* chance to keep IOC_BASE in a register.
*/
-#define ioc_readb(off) __raw_base_readb(IOC_BASE, (off))
-#define ioc_writeb(val,off) __raw_base_writeb(val, IOC_BASE, (off))
+#define ioc_readb(off) __raw_readb(IOC_BASE + (off))
+#define ioc_writeb(val,off) __raw_writeb(val, IOC_BASE + (off))
#endif
diff --git a/include/asm-arm/hardware/iomd.h b/include/asm-arm/hardware/iomd.h
index 91acb7787..decb1438c 100644
--- a/include/asm-arm/hardware/iomd.h
+++ b/include/asm-arm/hardware/iomd.h
@@ -21,10 +21,10 @@
* We use __raw_base variants here so that we give the compiler the
* chance to keep IOC_BASE in a register.
*/
-#define iomd_readb(off) __raw_base_readb(IOMD_BASE, (off))
-#define iomd_readl(off) __raw_base_readl(IOMD_BASE, (off))
-#define iomd_writeb(val,off) __raw_base_writeb(val, IOMD_BASE, (off))
-#define iomd_writel(val,off) __raw_base_writel(val, IOMD_BASE, (off))
+#define iomd_readb(off) __raw_readb(IOMD_BASE + (off))
+#define iomd_readl(off) __raw_readl(IOMD_BASE + (off))
+#define iomd_writeb(val,off) __raw_writeb(val, IOMD_BASE + (off))
+#define iomd_writel(val,off) __raw_writel(val, IOMD_BASE + (off))
#endif
diff --git a/include/asm-arm/hardware/linkup-l1110.h b/include/asm-arm/hardware/linkup-l1110.h
new file mode 100644
index 000000000..7ec91168a
--- /dev/null
+++ b/include/asm-arm/hardware/linkup-l1110.h
@@ -0,0 +1,48 @@
+/*
+*
+* Definitions for H3600 Handheld Computer
+*
+* Copyright 2001 Compaq Computer Corporation.
+*
+* Use consistent with the GNU GPL is permitted,
+* provided that this copyright notice is
+* preserved in its entirety in all copies and derived works.
+*
+* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+* FITNESS FOR ANY PARTICULAR PURPOSE.
+*
+* Author: Jamey Hicks.
+*
+*/
+
+/* LinkUp Systems PCCard/CompactFlash Interface for SA-1100 */
+
+/* PC Card Status Register */
+#define LINKUP_PRS_S1 (1 << 0) /* voltage control bits S1-S4 */
+#define LINKUP_PRS_S2 (1 << 1)
+#define LINKUP_PRS_S3 (1 << 2)
+#define LINKUP_PRS_S4 (1 << 3)
+#define LINKUP_PRS_BVD1 (1 << 4)
+#define LINKUP_PRS_BVD2 (1 << 5)
+#define LINKUP_PRS_VS1 (1 << 6)
+#define LINKUP_PRS_VS2 (1 << 7)
+#define LINKUP_PRS_RDY (1 << 8)
+#define LINKUP_PRS_CD1 (1 << 9)
+#define LINKUP_PRS_CD2 (1 << 10)
+
+/* PC Card Command Register */
+#define LINKUP_PRC_S1 (1 << 0)
+#define LINKUP_PRC_S2 (1 << 1)
+#define LINKUP_PRC_S3 (1 << 2)
+#define LINKUP_PRC_S4 (1 << 3)
+#define LINKUP_PRC_RESET (1 << 4)
+#define LINKUP_PRC_APOE (1 << 5) /* Auto Power Off Enable: clears S1-S4 when either nCD goes high */
+#define LINKUP_PRC_CFE (1 << 6) /* CompactFlash mode Enable: addresses A[10:0] only, A[25:11] high */
+#define LINKUP_PRC_SOE (1 << 7) /* signal output driver enable */
+#define LINKUP_PRC_SSP (1 << 8) /* sock select polarity: 0 for socket 0, 1 for socket 1 */
+#define LINKUP_PRC_MBZ (1 << 15) /* must be zero */
+
+struct linkup_l1110 {
+ volatile short prc;
+};
diff --git a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h
new file mode 100644
index 000000000..baa862392
--- /dev/null
+++ b/include/asm-arm/hardware/sa1111.h
@@ -0,0 +1,678 @@
+/*
+ * linux/include/asm-arm/hardware/SA-1111.h
+ *
+ * Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
+ *
+ * This file contains definitions for the SA-1111 Companion Chip.
+ * (Structure and naming borrowed from SA-1101.h, by Peter Danielsson.)
+ *
+ * Macro that calculates real address for registers in the SA-1111
+ */
+
+#ifndef _ASM_ARCH_SA1111
+#define _ASM_ARCH_SA1111
+
+#include <asm/arch/bitfield.h>
+
+/*
+ * The SA1111 is always located at virtual 0xf4000000, and is always
+ * "native" endian.
+ */
+
+#define SA1111_VBASE 0xf4000000
+
+/* Don't use these! */
+#define SA1111_p2v( x ) ((x) - SA1111_BASE + SA1111_VBASE)
+#define SA1111_v2p( x ) ((x) - SA1111_VBASE + SA1111_BASE)
+
+#ifndef __ASSEMBLY__
+
+extern struct resource sa1111_resource;
+#define _SA1111(x) ((x) + sa1111_resource.start)
+#endif
+
+/*
+ * 26 bits of the SA-1110 address bus are available to the SA-1111.
+ * Use these when feeding target addresses to the DMA engines.
+ */
+
+#define SA1111_ADDR_WIDTH (26)
+#define SA1111_ADDR_MASK ((1<<SA1111_ADDR_WIDTH)-1)
+#define SA1111_DMA_ADDR(x) ((x)&SA1111_ADDR_MASK)
+
+/*
+ * Don't ask the (SAC) DMA engines to move less than this amount.
+ */
+
+#define SA1111_SAC_DMA_MIN_XFER (0x800)
+
+/*
+ * SA1111 register definitions.
+ */
+#define __CCREG(x) __REGP(SA1111_VBASE + (x))
+
+/* System Bus Interface (SBI)
+ *
+ * Registers
+ * SKCR Control Register
+ * SMCR Shared Memory Controller Register
+ * SKID ID Register
+ */
+#define SA1111_SKCR 0x0000
+#define SA1111_SMCR 0x0004
+#define SA1111_SKID 0x0008
+
+#define _SBI_SKCR _SA1111(SA1111_SKCR)
+#define _SBI_SMCR _SA1111(SA1111_SMCR)
+#define _SBI_SKID _SA1111(SA1111_SKID)
+
+#if LANGUAGE == C
+
+#define SBI_SKCR __CCREG(SA1111_SKCR)
+#define SBI_SMCR __CCREG(SA1111_SMCR)
+#define SBI_SKID __CCREG(SA1111_SKID)
+
+#endif /* LANGUAGE == C */
+
+#define SKCR_PLL_BYPASS (1<<0)
+#define SKCR_RCLKEN (1<<1)
+#define SKCR_SLEEP (1<<2)
+#define SKCR_DOZE (1<<3)
+#define SKCR_VCO_OFF (1<<4)
+#define SKCR_SCANTSTEN (1<<5)
+#define SKCR_CLKTSTEN (1<<6)
+#define SKCR_RDYEN (1<<7)
+#define SKCR_SELAC (1<<8)
+#define SKCR_OPPC (1<<9)
+#define SKCR_PLLTSTEN (1<<10)
+#define SKCR_USBIOTSTEN (1<<11)
+/*
+ * Don't believe the specs! Take them, throw them outside. Leave them
+ * there for a week. Spit on them. Walk on them. Stamp on them.
+ * Pour gasoline over them and finally burn them. Now think about coding.
+ * - The October 1999 errata (278260-007) says its bit 13, 1 to enable.
+ * - The Feb 2001 errata (278260-010) says that the previous errata
+ * (278260-009) is wrong, and its bit actually 12, fixed in spec
+ * 278242-003.
+ * - The SA1111 manual (278242) says bit 12, but 0 to enable.
+ * - Reality is bit 13, 1 to enable.
+ * -- rmk
+ */
+#define SKCR_OE_EN (1<<13)
+
+#define SMCR_DTIM (1<<0)
+#define SMCR_MBGE (1<<1)
+#define SMCR_DRAC_0 (1<<2)
+#define SMCR_DRAC_1 (1<<3)
+#define SMCR_DRAC_2 (1<<4)
+#define SMCR_DRAC Fld(3, 2)
+#define SMCR_CLAT (1<<5)
+
+#define SKID_SIREV_MASK (0x000000f0)
+#define SKID_MTREV_MASK (0x0000000f)
+#define SKID_ID_MASK (0xffffff00)
+#define SKID_SA1111_ID (0x690cc200)
+
+/*
+ * System Controller
+ *
+ * Registers
+ * SKPCR Power Control Register
+ * SKCDR Clock Divider Register
+ * SKAUD Audio Clock Divider Register
+ * SKPMC PS/2 Mouse Clock Divider Register
+ * SKPTC PS/2 Track Pad Clock Divider Register
+ * SKPEN0 PWM0 Enable Register
+ * SKPWM0 PWM0 Clock Register
+ * SKPEN1 PWM1 Enable Register
+ * SKPWM1 PWM1 Clock Register
+ */
+
+#define _SKPCR _SA1111(0x0200)
+#define _SKCDR _SA1111(0x0204)
+#define _SKAUD _SA1111(0x0208)
+#define _SKPMC _SA1111(0x020c)
+#define _SKPTC _SA1111(0x0210)
+#define _SKPEN0 _SA1111(0x0214)
+#define _SKPWM0 _SA1111(0x0218)
+#define _SKPEN1 _SA1111(0x021c)
+#define _SKPWM1 _SA1111(0x0220)
+
+#if LANGUAGE == C
+
+#define SKPCR __CCREG(0x0200)
+#define SKCDR __CCREG(0x0204)
+#define SKAUD __CCREG(0x0208)
+#define SKPMC __CCREG(0x020c)
+#define SKPTC __CCREG(0x0210)
+#define SKPEN0 __CCREG(0x0214)
+#define SKPWM0 __CCREG(0x0218)
+#define SKPEN1 __CCREG(0x021c)
+#define SKPWM1 __CCREG(0x0220)
+
+#endif /* LANGUAGE == C */
+
+#define SKPCR_UCLKEN (1<<0)
+#define SKPCR_ACCLKEN (1<<1)
+#define SKPCR_I2SCLKEN (1<<2)
+#define SKPCR_L3CLKEN (1<<3)
+#define SKPCR_SCLKEN (1<<4)
+#define SKPCR_PMCLKEN (1<<5)
+#define SKPCR_PTCLKEN (1<<6)
+#define SKPCR_DCLKEN (1<<7)
+#define SKPCR_PWMCLKEN (1<<8)
+
+/*
+ * USB Host controller
+ */
+#define _USB_OHCI_OP_BASE _SA1111( 0x400 )
+#define _USB_STATUS _SA1111( 0x518 )
+#define _USB_RESET _SA1111( 0x51c )
+#define _USB_INTERRUPTEST _SA1111( 0x520 )
+
+#define _USB_EXTENT (_USB_INTERRUPTEST - _USB_OHCI_OP_BASE + 4)
+
+#if LANGUAGE == C
+
+#define USB_OHCI_OP_BASE __CCREG(0x0400)
+#define USB_STATUS __CCREG(0x0518)
+#define USB_RESET __CCREG(0x051c)
+#define USB_INTERRUPTEST __CCReG(0x0520)
+
+#endif /* LANGUAGE == C */
+
+#define USB_RESET_FORCEIFRESET (1 << 0)
+#define USB_RESET_FORCEHCRESET (1 << 1)
+#define USB_RESET_CLKGENRESET (1 << 2)
+#define USB_RESET_SIMSCALEDOWN (1 << 3)
+#define USB_RESET_USBINTTEST (1 << 4)
+#define USB_RESET_SLEEPSTBYEN (1 << 5)
+#define USB_RESET_PWRSENSELOW (1 << 6)
+#define USB_RESET_PWRCTRLLOW (1 << 7)
+
+/*
+ * Serial Audio Controller
+ *
+ * Registers
+ * SACR0 Serial Audio Common Control Register
+ * SACR1 Serial Audio Alternate Mode (I2C/MSB) Control Register
+ * SACR2 Serial Audio AC-link Control Register
+ * SASR0 Serial Audio I2S/MSB Interface & FIFO Status Register
+ * SASR1 Serial Audio AC-link Interface & FIFO Status Register
+ * SASCR Serial Audio Status Clear Register
+ * L3_CAR L3 Control Bus Address Register
+ * L3_CDR L3 Control Bus Data Register
+ * ACCAR AC-link Command Address Register
+ * ACCDR AC-link Command Data Register
+ * ACSAR AC-link Status Address Register
+ * ACSDR AC-link Status Data Register
+ * SADTCS Serial Audio DMA Transmit Control/Status Register
+ * SADTSA Serial Audio DMA Transmit Buffer Start Address A
+ * SADTCA Serial Audio DMA Transmit Buffer Count Register A
+ * SADTSB Serial Audio DMA Transmit Buffer Start Address B
+ * SADTCB Serial Audio DMA Transmit Buffer Count Register B
+ * SADRCS Serial Audio DMA Receive Control/Status Register
+ * SADRSA Serial Audio DMA Receive Buffer Start Address A
+ * SADRCA Serial Audio DMA Receive Buffer Count Register A
+ * SADRSB Serial Audio DMA Receive Buffer Start Address B
+ * SADRCB Serial Audio DMA Receive Buffer Count Register B
+ * SAITR Serial Audio Interrupt Test Register
+ * SADR Serial Audio Data Register (16 x 32-bit)
+ */
+
+#define _SACR0 _SA1111( 0x0600 )
+#define _SACR1 _SA1111( 0x0604 )
+#define _SACR2 _SA1111( 0x0608 )
+#define _SASR0 _SA1111( 0x060c )
+#define _SASR1 _SA1111( 0x0610 )
+#define _SASCR _SA1111( 0x0618 )
+#define _L3_CAR _SA1111( 0x061c )
+#define _L3_CDR _SA1111( 0x0620 )
+#define _ACCAR _SA1111( 0x0624 )
+#define _ACCDR _SA1111( 0x0628 )
+#define _ACSAR _SA1111( 0x062c )
+#define _ACSDR _SA1111( 0x0630 )
+#define _SADTCS _SA1111( 0x0634 )
+#define _SADTSA _SA1111( 0x0638 )
+#define _SADTCA _SA1111( 0x063c )
+#define _SADTSB _SA1111( 0x0640 )
+#define _SADTCB _SA1111( 0x0644 )
+#define _SADRCS _SA1111( 0x0648 )
+#define _SADRSA _SA1111( 0x064c )
+#define _SADRCA _SA1111( 0x0650 )
+#define _SADRSB _SA1111( 0x0654 )
+#define _SADRCB _SA1111( 0x0658 )
+#define _SAITR _SA1111( 0x065c )
+#define _SADR _SA1111( 0x0680 )
+
+#if LANGUAGE == C
+
+#define SACR0 __CCREG(0x0600)
+#define SACR1 __CCREG(0x0604)
+#define SACR2 __CCREG(0x0608)
+#define SASR0 __CCREG(0x060c)
+#define SASR1 __CCREG(0x0610)
+#define SASCR __CCREG(0x0618)
+#define L3_CAR __CCREG(0x061c)
+#define L3_CDR __CCREG(0x0620)
+#define ACCAR __CCREG(0x0624)
+#define ACCDR __CCREG(0x0628)
+#define ACSAR __CCREG(0x062c)
+#define ACSDR __CCREG(0x0630)
+#define SADTCS __CCREG(0x0634)
+#define SADTSA __CCREG(0x0638)
+#define SADTCA __CCREG(0x063c)
+#define SADTSB __CCREG(0x0640)
+#define SADTCB __CCREG(0x0644)
+#define SADRCS __CCREG(0x0648)
+#define SADRSA __CCREG(0x064c)
+#define SADRCA __CCREG(0x0650)
+#define SADRSB __CCREG(0x0654)
+#define SADRCB __CCREG(0x0658)
+#define SAITR __CCREG(0x065c)
+#define SADR __CCREG(0x0680)
+
+#endif /* LANGUAGE == C */
+
+#define SACR0_ENB (1<<0)
+#define SACR0_BCKD (1<<2)
+#define SACR0_RST (1<<3)
+
+#define SACR1_AMSL (1<<0)
+#define SACR1_L3EN (1<<1)
+#define SACR1_L3MB (1<<2)
+#define SACR1_DREC (1<<3)
+#define SACR1_DRPL (1<<4)
+#define SACR1_ENLBF (1<<5)
+
+#define SACR2_TS3V (1<<0)
+#define SACR2_TS4V (1<<1)
+#define SACR2_WKUP (1<<2)
+#define SACR2_DREC (1<<3)
+#define SACR2_DRPL (1<<4)
+#define SACR2_ENLBF (1<<5)
+#define SACR2_RESET (1<<6)
+
+#define SASR0_TNF (1<<0)
+#define SASR0_RNE (1<<1)
+#define SASR0_BSY (1<<2)
+#define SASR0_TFS (1<<3)
+#define SASR0_RFS (1<<4)
+#define SASR0_TUR (1<<5)
+#define SASR0_ROR (1<<6)
+#define SASR0_L3WD (1<<16)
+#define SASR0_L3RD (1<<17)
+
+#define SASR1_TNF (1<<0)
+#define SASR1_RNE (1<<1)
+#define SASR1_BSY (1<<2)
+#define SASR1_TFS (1<<3)
+#define SASR1_RFS (1<<4)
+#define SASR1_TUR (1<<5)
+#define SASR1_ROR (1<<6)
+#define SASR1_CADT (1<<16)
+#define SASR1_SADR (1<<17)
+#define SASR1_RSTO (1<<18)
+#define SASR1_CLPM (1<<19)
+#define SASR1_CRDY (1<<20)
+#define SASR1_RS3V (1<<21)
+#define SASR1_RS4V (1<<22)
+
+#define SASCR_TUR (1<<5)
+#define SASCR_ROR (1<<6)
+#define SASCR_DTS (1<<16)
+#define SASCR_RDD (1<<17)
+#define SASCR_STO (1<<18)
+
+#define SADTCS_TDEN (1<<0)
+#define SADTCS_TDIE (1<<1)
+#define SADTCS_TDBDA (1<<3)
+#define SADTCS_TDSTA (1<<4)
+#define SADTCS_TDBDB (1<<5)
+#define SADTCS_TDSTB (1<<6)
+#define SADTCS_TBIU (1<<7)
+
+#define SADRCS_RDEN (1<<0)
+#define SADRCS_RDIE (1<<1)
+#define SADRCS_RDBDA (1<<3)
+#define SADRCS_RDSTA (1<<4)
+#define SADRCS_RDBDB (1<<5)
+#define SADRCS_RDSTB (1<<6)
+#define SADRCS_RBIU (1<<7)
+
+#define SAD_CS_DEN (1<<0)
+#define SAD_CS_DIE (1<<1) /* Not functional on metal 1 */
+#define SAD_CS_DBDA (1<<3) /* Not functional on metal 1 */
+#define SAD_CS_DSTA (1<<4)
+#define SAD_CS_DBDB (1<<5) /* Not functional on metal 1 */
+#define SAD_CS_DSTB (1<<6)
+#define SAD_CS_BIU (1<<7) /* Not functional on metal 1 */
+
+#define SAITR_TFS (1<<0)
+#define SAITR_RFS (1<<1)
+#define SAITR_TUR (1<<2)
+#define SAITR_ROR (1<<3)
+#define SAITR_CADT (1<<4)
+#define SAITR_SADR (1<<5)
+#define SAITR_RSTO (1<<6)
+#define SAITR_TDBDA (1<<8)
+#define SAITR_TDBDB (1<<9)
+#define SAITR_RDBDA (1<<10)
+#define SAITR_RDBDB (1<<11)
+
+/*
+ * General-Purpose I/O Interface
+ *
+ * Registers
+ * PA_DDR GPIO Block A Data Direction
+ * PA_DRR/PA_DWR GPIO Block A Data Value Register (read/write)
+ * PA_SDR GPIO Block A Sleep Direction
+ * PA_SSR GPIO Block A Sleep State
+ * PB_DDR GPIO Block B Data Direction
+ * PB_DRR/PB_DWR GPIO Block B Data Value Register (read/write)
+ * PB_SDR GPIO Block B Sleep Direction
+ * PB_SSR GPIO Block B Sleep State
+ * PC_DDR GPIO Block C Data Direction
+ * PC_DRR/PC_DWR GPIO Block C Data Value Register (read/write)
+ * PC_SDR GPIO Block C Sleep Direction
+ * PC_SSR GPIO Block C Sleep State
+ */
+
+#define _PA_DDR _SA1111( 0x1000 )
+#define _PA_DRR _SA1111( 0x1004 )
+#define _PA_DWR _SA1111( 0x1004 )
+#define _PA_SDR _SA1111( 0x1008 )
+#define _PA_SSR _SA1111( 0x100c )
+#define _PB_DDR _SA1111( 0x1010 )
+#define _PB_DRR _SA1111( 0x1014 )
+#define _PB_DWR _SA1111( 0x1014 )
+#define _PB_SDR _SA1111( 0x1018 )
+#define _PB_SSR _SA1111( 0x101c )
+#define _PC_DDR _SA1111( 0x1020 )
+#define _PC_DRR _SA1111( 0x1024 )
+#define _PC_DWR _SA1111( 0x1024 )
+#define _PC_SDR _SA1111( 0x1028 )
+#define _PC_SSR _SA1111( 0x102c )
+
+#if LANGUAGE == C
+
+#define PA_DDR __CCREG(0x1000)
+#define PA_DRR __CCREG(0x1004)
+#define PA_DWR __CCREG(0x1004)
+#define PA_SDR __CCREG(0x1008)
+#define PA_SSR __CCREG(0x100c)
+#define PB_DDR __CCREG(0x1010)
+#define PB_DRR __CCREG(0x1014)
+#define PB_DWR __CCREG(0x1014)
+#define PB_SDR __CCREG(0x1018)
+#define PB_SSR __CCREG(0x101c)
+#define PC_DDR __CCREG(0x1020)
+#define PC_DRR __CCREG(0x1024)
+#define PC_DWR __CCREG(0x1024)
+#define PC_SDR __CCREG(0x1028)
+#define PC_SSR __CCREG(0x102c)
+
+#endif /* LANGUAGE == C */
+
+/*
+ * Interrupt Controller
+ *
+ * Registers
+ * INTTEST0 Test register 0
+ * INTTEST1 Test register 1
+ * INTEN0 Interrupt Enable register 0
+ * INTEN1 Interrupt Enable register 1
+ * INTPOL0 Interrupt Polarity selection 0
+ * INTPOL1 Interrupt Polarity selection 1
+ * INTTSTSEL Interrupt source selection
+ * INTSTATCLR0 Interrupt Status/Clear 0
+ * INTSTATCLR1 Interrupt Status/Clear 1
+ * INTSET0 Interrupt source set 0
+ * INTSET1 Interrupt source set 1
+ * WAKE_EN0 Wake-up source enable 0
+ * WAKE_EN1 Wake-up source enable 1
+ * WAKE_POL0 Wake-up polarity selection 0
+ * WAKE_POL1 Wake-up polarity selection 1
+ */
+
+#define SA1111_INTTEST0 0x1600
+#define SA1111_INTTEST1 0x1604
+#define SA1111_INTEN0 0x1608
+#define SA1111_INTEN1 0x160c
+#define SA1111_INTPOL0 0x1610
+#define SA1111_INTPOL1 0x1614
+#define SA1111_INTTSTSEL 0x1618
+#define SA1111_INTSTATCLR0 0x161c
+#define SA1111_INTSTATCLR1 0x1620
+#define SA1111_INTSET0 0x1624
+#define SA1111_INTSET1 0x1628
+#define SA1111_WAKE_EN0 0x162c
+#define SA1111_WAKE_EN1 0x1630
+#define SA1111_WAKE_POL0 0x1634
+#define SA1111_WAKE_POL1 0x1638
+
+#define _INTTEST0 _SA1111(SA1111_INTTEST0)
+#define _INTTEST1 _SA1111(SA1111_INTTEST1)
+#define _INTEN0 _SA1111(SA1111_INTEN0)
+#define _INTEN1 _SA1111(SA1111_INTEN1)
+#define _INTPOL0 _SA1111(SA1111_INTPOL0)
+#define _INTPOL1 _SA1111(SA1111_INTPOL1)
+#define _INTTSTSEL _SA1111(SA1111_INTTSTSEL)
+#define _INTSTATCLR0 _SA1111(SA1111_INTSTATCLR0)
+#define _INTSTATCLR1 _SA1111(SA1111_INTSTATCLR1)
+#define _INTSET0 _SA1111(SA1111_INTSET0)
+#define _INTSET1 _SA1111(SA1111_INTSET1)
+#define _WAKE_EN0 _SA1111(SA1111_WAKE_EN0)
+#define _WAKE_EN1 _SA1111(SA1111_WAKE_EN1)
+#define _WAKE_POL0 _SA1111(SA1111_WAKE_POL0)
+#define _WAKE_POL1 _SA1111(SA1111_WAKE_POL1)
+
+#if LANGUAGE == C
+
+#define INTTEST0 __CCREG(SA1111_INTTEST0)
+#define INTTEST1 __CCREG(SA1111_INTTEST1)
+#define INTEN0 __CCREG(SA1111_INTEN0)
+#define INTEN1 __CCREG(SA1111_INTEN1)
+#define INTPOL0 __CCREG(SA1111_INTPOL0)
+#define INTPOL1 __CCREG(SA1111_INTPOL1)
+#define INTTSTSEL __CCREG(SA1111_INTTSTSEL)
+#define INTSTATCLR0 __CCREG(SA1111_INTSTATCLR0)
+#define INTSTATCLR1 __CCREG(SA1111_INTSTATCLR1)
+#define INTSET0 __CCREG(SA1111_INTSET0)
+#define INTSET1 __CCREG(SA1111_INTSET1)
+#define WAKE_EN0 __CCREG(SA1111_WAKE_EN0)
+#define WAKE_EN1 __CCREG(SA1111_WAKE_EN1)
+#define WAKE_POL0 __CCREG(SA1111_WAKE_POL0)
+#define WAKE_POL1 __CCREG(SA1111_WAKE_POL1)
+
+#endif /* LANGUAGE == C */
+
+/*
+ * PS/2 Trackpad and Mouse Interfaces
+ *
+ * Registers (prefix kbd applies to trackpad interface, mse to mouse)
+ * KBDCR Control Register
+ * KBDSTAT Status Register
+ * KBDDATA Transmit/Receive Data register
+ * KBDCLKDIV Clock Division Register
+ * KBDPRECNT Clock Precount Register
+ * KBDTEST1 Test register 1
+ * KBDTEST2 Test register 2
+ * KBDTEST3 Test register 3
+ * KBDTEST4 Test register 4
+ * MSECR
+ * MSESTAT
+ * MSEDATA
+ * MSECLKDIV
+ * MSEPRECNT
+ * MSETEST1
+ * MSETEST2
+ * MSETEST3
+ * MSETEST4
+ *
+ */
+
+#define _KBD( x ) _SA1111( 0x0A00 )
+#define _MSE( x ) _SA1111( 0x0C00 )
+
+#define _KBDCR _SA1111( 0x0A00 )
+#define _KBDSTAT _SA1111( 0x0A04 )
+#define _KBDDATA _SA1111( 0x0A08 )
+#define _KBDCLKDIV _SA1111( 0x0A0C )
+#define _KBDPRECNT _SA1111( 0x0A10 )
+#define _MSECR _SA1111( 0x0C00 )
+#define _MSESTAT _SA1111( 0x0C04 )
+#define _MSEDATA _SA1111( 0x0C08 )
+#define _MSECLKDIV _SA1111( 0x0C0C )
+#define _MSEPRECNT _SA1111( 0x0C10 )
+
+#if ( LANGUAGE == C )
+
+#define KBDCR __CCREG(0x0a00)
+#define KBDSTAT __CCREG(0x0a04)
+#define KBDDATA __CCREG(0x0a08)
+#define KBDCLKDIV __CCREG(0x0a0c)
+#define KBDPRECNT __CCREG(0x0a10)
+#define MSECR __CCREG(0x0c00)
+#define MSESTAT __CCREG(0x0c04)
+#define MSEDATA __CCREG(0x0c08)
+#define MSECLKDIV __CCREG(0x0c0c)
+#define MSEPRECNT __CCREG(0x0c10)
+
+#define KBDCR_ENA 0x08
+#define KBDCR_FKD 0x02
+#define KBDCR_FKC 0x01
+
+#define KBDSTAT_TXE 0x80
+#define KBDSTAT_TXB 0x40
+#define KBDSTAT_RXF 0x20
+#define KBDSTAT_RXB 0x10
+#define KBDSTAT_ENA 0x08
+#define KBDSTAT_RXP 0x04
+#define KBDSTAT_KBD 0x02
+#define KBDSTAT_KBC 0x01
+
+#define KBDCLKDIV_DivVal Fld(4,0)
+
+#define MSECR_ENA 0x08
+#define MSECR_FKD 0x02
+#define MSECR_FKC 0x01
+
+#define MSESTAT_TXE 0x80
+#define MSESTAT_TXB 0x40
+#define MSESTAT_RXF 0x20
+#define MSESTAT_RXB 0x10
+#define MSESTAT_ENA 0x08
+#define MSESTAT_RXP 0x04
+#define MSESTAT_MSD 0x02
+#define MSESTAT_MSC 0x01
+
+#define MSECLKDIV_DivVal Fld(4,0)
+
+#define KBDTEST1_CD 0x80
+#define KBDTEST1_RC1 0x40
+#define KBDTEST1_MC 0x20
+#define KBDTEST1_C Fld(2,3)
+#define KBDTEST1_T2 0x40
+#define KBDTEST1_T1 0x20
+#define KBDTEST1_T0 0x10
+#define KBDTEST2_TICBnRES 0x08
+#define KBDTEST2_RKC 0x04
+#define KBDTEST2_RKD 0x02
+#define KBDTEST2_SEL 0x01
+#define KBDTEST3_ms_16 0x80
+#define KBDTEST3_us_64 0x40
+#define KBDTEST3_us_16 0x20
+#define KBDTEST3_DIV8 0x10
+#define KBDTEST3_DIn 0x08
+#define KBDTEST3_CIn 0x04
+#define KBDTEST3_KD 0x02
+#define KBDTEST3_KC 0x01
+#define KBDTEST4_BC12 0x80
+#define KBDTEST4_BC11 0x40
+#define KBDTEST4_TRES 0x20
+#define KBDTEST4_CLKOE 0x10
+#define KBDTEST4_CRES 0x08
+#define KBDTEST4_RXB 0x04
+#define KBDTEST4_TXB 0x02
+#define KBDTEST4_SRX 0x01
+
+#define MSETEST1_CD 0x80
+#define MSETEST1_RC1 0x40
+#define MSETEST1_MC 0x20
+#define MSETEST1_C Fld(2,3)
+#define MSETEST1_T2 0x40
+#define MSETEST1_T1 0x20
+#define MSETEST1_T0 0x10
+#define MSETEST2_TICBnRES 0x08
+#define MSETEST2_RKC 0x04
+#define MSETEST2_RKD 0x02
+#define MSETEST2_SEL 0x01
+#define MSETEST3_ms_16 0x80
+#define MSETEST3_us_64 0x40
+#define MSETEST3_us_16 0x20
+#define MSETEST3_DIV8 0x10
+#define MSETEST3_DIn 0x08
+#define MSETEST3_CIn 0x04
+#define MSETEST3_KD 0x02
+#define MSETEST3_KC 0x01
+#define MSETEST4_BC12 0x80
+#define MSETEST4_BC11 0x40
+#define MSETEST4_TRES 0x20
+#define MSETEST4_CLKOE 0x10
+#define MSETEST4_CRES 0x08
+#define MSETEST4_RXB 0x04
+#define MSETEST4_TXB 0x02
+#define MSETEST4_SRX 0x01
+
+#endif /* LANGUAGE == C */
+
+/*
+ * PCMCIA Interface
+ *
+ * Registers
+ * PCSR Status Register
+ * PCCR Control Register
+ * PCSSR Sleep State Register
+ */
+
+#define _PCCR _SA1111( 0x1800 )
+#define _PCSSR _SA1111( 0x1804 )
+#define _PCSR _SA1111( 0x1808 )
+
+#if LANGUAGE == C
+
+#define PCCR __CCREG(0x1800)
+#define PCSSR __CCREG(0x1804)
+#define PCSR __CCREG(0x1808)
+
+#endif /* LANGUAGE == C */
+
+#define PCSR_S0_READY (1<<0)
+#define PCSR_S1_READY (1<<1)
+#define PCSR_S0_DETECT (1<<2)
+#define PCSR_S1_DETECT (1<<3)
+#define PCSR_S0_VS1 (1<<4)
+#define PCSR_S0_VS2 (1<<5)
+#define PCSR_S1_VS1 (1<<6)
+#define PCSR_S1_VS2 (1<<7)
+#define PCSR_S0_WP (1<<8)
+#define PCSR_S1_WP (1<<9)
+#define PCSR_S0_BVD1 (1<<10)
+#define PCSR_S0_BVD2 (1<<11)
+#define PCSR_S1_BVD1 (1<<12)
+#define PCSR_S1_BVD2 (1<<13)
+
+#define PCCR_S0_RST (1<<0)
+#define PCCR_S1_RST (1<<1)
+#define PCCR_S0_FLT (1<<2)
+#define PCCR_S1_FLT (1<<3)
+#define PCCR_S0_PWAITEN (1<<4)
+#define PCCR_S1_PWAITEN (1<<5)
+#define PCCR_S0_PSE (1<<6)
+#define PCCR_S1_PSE (1<<7)
+
+#define PCSSR_S0_SLEEP (1<<0)
+#define PCSSR_S1_SLEEP (1<<1)
+
+#endif /* _ASM_ARCH_SA1111 */
diff --git a/include/asm-arm/hdreg.h b/include/asm-arm/hdreg.h
index 81bc05e16..a2d301dd5 100644
--- a/include/asm-arm/hdreg.h
+++ b/include/asm-arm/hdreg.h
@@ -7,7 +7,7 @@
#ifndef __ASMARM_HDREG_H
#define __ASMARM_HDREG_H
-typedef unsigned long ide_ioreg_t;
+typedef unsigned int ide_ioreg_t;
#endif /* __ASMARM_HDREG_H */
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index a6fb3fcda..4782df468 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -23,20 +23,14 @@
#ifdef __KERNEL__
#include <linux/types.h>
+#include <asm/byteorder.h>
#include <asm/memory.h>
#include <asm/arch/hardware.h>
/*
- * Generic virtual read/write. Note that we don't support half-word
- * read/writes. We define __arch_*[bl] here, and leave __arch_*w
- * to the architecture specific code.
+ * Generic IO read/write. These perform native-endian accesses. Note
+ * that some architectures will want to re-define __raw_{read,write}w.
*/
-#define __arch_getb(a) (*(volatile unsigned char *)(a))
-#define __arch_getl(a) (*(volatile unsigned int *)(a))
-
-#define __arch_putb(v,a) (*(volatile unsigned char *)(a) = (v))
-#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
-
extern void __raw_writesb(unsigned int addr, void *data, int bytelen);
extern void __raw_writesw(unsigned int addr, void *data, int wordlen);
extern void __raw_writesl(unsigned int addr, void *data, int longlen);
@@ -45,116 +39,85 @@ extern void __raw_readsb(unsigned int addr, void *data, int bytelen);
extern void __raw_readsw(unsigned int addr, void *data, int wordlen);
extern void __raw_readsl(unsigned int addr, void *data, int longlen);
-#define __raw_writeb(v,a) __arch_putb(v,a)
-#define __raw_writew(v,a) __arch_putw(v,a)
-#define __raw_writel(v,a) __arch_putl(v,a)
+#define __raw_writeb(v,a) (*(volatile unsigned char *)(a) = (v))
+#define __raw_writew(v,a) (*(volatile unsigned short *)(a) = (v))
+#define __raw_writel(v,a) (*(volatile unsigned int *)(a) = (v))
-#define __raw_readb(a) __arch_getb(a)
-#define __raw_readw(a) __arch_getw(a)
-#define __raw_readl(a) __arch_getl(a)
+#define __raw_readb(a) (*(volatile unsigned char *)(a))
+#define __raw_readw(a) (*(volatile unsigned short *)(a))
+#define __raw_readl(a) (*(volatile unsigned int *)(a))
/*
- * The compiler seems to be incapable of optimising constants
- * properly. Spell it out to the compiler in some cases.
- * These are only valid for small values of "off" (< 1<<12)
+ * Bad read/write accesses...
*/
-#define __raw_base_writeb(val,base,off) __arch_base_putb(val,base,off)
-#define __raw_base_writew(val,base,off) __arch_base_putw(val,base,off)
-#define __raw_base_writel(val,base,off) __arch_base_putl(val,base,off)
-
-#define __raw_base_readb(base,off) __arch_base_getb(base,off)
-#define __raw_base_readw(base,off) __arch_base_getw(base,off)
-#define __raw_base_readl(base,off) __arch_base_getl(base,off)
+extern void __readwrite_bug(const char *fn);
/*
* Now, pick up the machine-defined IO definitions
*/
#include <asm/arch/io.h>
+#ifdef __io_pci
+#warning machine class uses buggy __io_pci
+#endif
+#if defined(__arch_putb) || defined(__arch_putw) || defined(__arch_putl) || \
+ defined(__arch_getb) || defined(__arch_getw) || defined(__arch_getl)
+#warning machine class uses old __arch_putw or __arch_getw
+#endif
+
/*
- * IO definitions. We define {out,in,outs,ins}[bwl] if __io is defined
- * by the machine. Otherwise, these definitions are left for the machine
- * specific header files to pick up.
+ * IO port access primitives
+ * -------------------------
+ *
+ * The ARM doesn't have special IO access instructions; all IO is memory
+ * mapped. Note that these are defined to perform little endian accesses
+ * only. Their primary purpose is to access PCI and ISA peripherals.
+ *
+ * Note that for a big endian machine, this implies that the following
+ * big endian mode connectivity is in place, as described by numerious
+ * ARM documents:
+ *
+ * PCI: D0-D7 D8-D15 D16-D23 D24-D31
+ * ARM: D24-D31 D16-D23 D8-D15 D0-D7
+ *
+ * The machine specific io.h include defines __io to translate an "IO"
+ * address to a memory address.
*
* Note that we prevent GCC re-ordering or caching values in expressions
* by introducing sequence points into the in*() definitions. Note that
* __raw_* do not guarantee this behaviour.
*/
#ifdef __io
-#define outb(v,p) __raw_writeb(v,__io(p))
-#define outw(v,p) __raw_writew(v,__io(p))
-#define outl(v,p) __raw_writel(v,__io(p))
-
-#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; })
-#define inw(p) ({ unsigned int __v = __raw_readw(__io(p)); __v; })
-#define inl(p) ({ unsigned int __v = __raw_readl(__io(p)); __v; })
+#define outb(v,p) __raw_writeb(v,__io(p))
+#define outw(v,p) __raw_writew(cpu_to_le16(v),__io(p))
+#define outl(v,p) __raw_writel(cpu_to_le32(v),__io(p))
-#define outsb(p,d,l) __raw_writesb(__io(p),d,l)
-#define outsw(p,d,l) __raw_writesw(__io(p),d,l)
-#define outsl(p,d,l) __raw_writesl(__io(p),d,l)
-
-#define insb(p,d,l) __raw_readsb(__io(p),d,l)
-#define insw(p,d,l) __raw_readsw(__io(p),d,l)
-#define insl(p,d,l) __raw_readsl(__io(p),d,l)
-#endif
+#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; })
+#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
+#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
-#define outb_p(val,port) outb((val),(port))
-#define outw_p(val,port) outw((val),(port))
-#define outl_p(val,port) outl((val),(port))
-#define inb_p(port) inb((port))
-#define inw_p(port) inw((port))
-#define inl_p(port) inl((port))
-
-#define outsb_p(port,from,len) outsb(port,from,len)
-#define outsw_p(port,from,len) outsw(port,from,len)
-#define outsl_p(port,from,len) outsl(port,from,len)
-#define insb_p(port,to,len) insb(port,to,len)
-#define insw_p(port,to,len) insw(port,to,len)
-#define insl_p(port,to,len) insl(port,to,len)
-
-/*
- * ioremap and friends.
- *
- * ioremap takes a PCI memory address, as specified in
- * linux/Documentation/IO-mapping.txt. If you want a
- * physical address, use __ioremap instead.
- */
-extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags);
-extern void __iounmap(void *addr);
+#define outsb(p,d,l) __raw_writesb(__io(p),d,l)
+#define outsw(p,d,l) __raw_writesw(__io(p),d,l)
+#define outsl(p,d,l) __raw_writesl(__io(p),d,l)
-/*
- * Generic ioremap support.
- *
- * Define:
- * iomem_valid_addr(off,size)
- * iomem_to_phys(off)
- */
-#ifdef iomem_valid_addr
-#define __arch_ioremap(off,sz,nocache) \
- ({ \
- unsigned long _off = (off), _size = (sz); \
- void *_ret = (void *)0; \
- if (iomem_valid_addr(_off, _size)) \
- _ret = __ioremap(iomem_to_phys(_off),_size,0); \
- _ret; \
- })
-
-#define __arch_iounmap __iounmap
+#define insb(p,d,l) __raw_readsb(__io(p),d,l)
+#define insw(p,d,l) __raw_readsw(__io(p),d,l)
+#define insl(p,d,l) __raw_readsl(__io(p),d,l)
#endif
-#define ioremap(off,sz) __arch_ioremap((off),(sz),0)
-#define ioremap_nocache(off,sz) __arch_ioremap((off),(sz),1)
-#define iounmap(_addr) __arch_iounmap(_addr)
+#define outb_p(val,port) outb((val),(port))
+#define outw_p(val,port) outw((val),(port))
+#define outl_p(val,port) outl((val),(port))
+#define inb_p(port) inb((port))
+#define inw_p(port) inw((port))
+#define inl_p(port) inl((port))
-/*
- * DMA-consistent mapping functions. These allocate/free a region of
- * uncached, unwrite-buffered mapped memory space for use with DMA
- * devices. This is the "generic" version. The PCI specific version
- * is in pci.h
- */
-extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
-extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
-extern void consistent_sync(void *vaddr, size_t size, int rw);
+#define outsb_p(port,from,len) outsb(port,from,len)
+#define outsw_p(port,from,len) outsw(port,from,len)
+#define outsl_p(port,from,len) outsl(port,from,len)
+#define insb_p(port,to,len) insb(port,to,len)
+#define insw_p(port,to,len) insw(port,to,len)
+#define insl_p(port,to,len) insl(port,to,len)
/*
* String version of IO memory access ops:
@@ -163,29 +126,31 @@ extern void _memcpy_fromio(void *, unsigned long, size_t);
extern void _memcpy_toio(unsigned long, const void *, size_t);
extern void _memset_io(unsigned long, int, size_t);
-extern void __readwrite_bug(const char *fn);
-
/*
- * If this architecture has PCI memory IO, then define the read/write
- * macros. These should only be used with the cookie passed from
- * ioremap.
+ * Memory access primitives
+ * ------------------------
+ *
+ * These perform PCI memory accesses via an ioremap region. They don't
+ * take an address as such, but a cookie.
+ *
+ * Again, this are defined to perform little endian accesses. See the
+ * IO port primitives for more information.
*/
#ifdef __mem_pci
+#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
+#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
+#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
-#define readb(addr) ({ unsigned int __v = __raw_readb(__mem_pci(addr)); __v; })
-#define readw(addr) ({ unsigned int __v = __raw_readw(__mem_pci(addr)); __v; })
-#define readl(addr) ({ unsigned int __v = __raw_readl(__mem_pci(addr)); __v; })
-
-#define writeb(val,addr) __raw_writeb(val,__mem_pci(addr))
-#define writew(val,addr) __raw_writew(val,__mem_pci(addr))
-#define writel(val,addr) __raw_writel(val,__mem_pci(addr))
+#define writeb(v,c) __raw_writeb(v,__mem_pci(c))
+#define writew(v,c) __raw_writew(cpu_to_le16(v),__mem_pci(c))
+#define writel(v,c) __raw_writel(cpu_to_le32(v),__mem_pci(c))
-#define memset_io(a,b,c) _memset_io(__mem_pci(a),(b),(c))
-#define memcpy_fromio(a,b,c) _memcpy_fromio((a),__mem_pci(b),(c))
-#define memcpy_toio(a,b,c) _memcpy_toio(__mem_pci(a),(b),(c))
+#define memset_io(c,v,l) _memset_io(__mem_pci(c),(v),(l))
+#define memcpy_fromio(a,c,l) _memcpy_fromio((a),__mem_pci(c),(l))
+#define memcpy_toio(c,a,l) _memcpy_toio(__mem_pci(c),(a),(l))
-#define eth_io_copy_and_sum(a,b,c,d) \
- eth_copy_and_sum((a),__mem_pci(b),(c),(d))
+#define eth_io_copy_and_sum(s,c,l,b) \
+ eth_copy_and_sum((s),__mem_pci(c),(l),(b))
static inline int
check_signature(unsigned long io_addr, const unsigned char *signature,
@@ -206,28 +171,20 @@ out:
#elif !defined(readb)
-#define readb(addr) (__readwrite_bug("readb"),0)
-#define readw(addr) (__readwrite_bug("readw"),0)
-#define readl(addr) (__readwrite_bug("readl"),0)
-#define writeb(v,addr) __readwrite_bug("writeb")
-#define writew(v,addr) __readwrite_bug("writew")
-#define writel(v,addr) __readwrite_bug("writel")
+#define readb(c) (__readwrite_bug("readb"),0)
+#define readw(c) (__readwrite_bug("readw"),0)
+#define readl(c) (__readwrite_bug("readl"),0)
+#define writeb(v,c) __readwrite_bug("writeb")
+#define writew(v,c) __readwrite_bug("writew")
+#define writel(v,c) __readwrite_bug("writel")
-#define eth_io_copy_and_sum(a,b,c,d) __readwrite_bug("eth_io_copy_and_sum")
+#define eth_io_copy_and_sum(s,c,l,b) __readwrite_bug("eth_io_copy_and_sum")
#define check_signature(io,sig,len) (0)
#endif /* __mem_pci */
/*
- * remap a physical address `phys' of size `size' with page protection `prot'
- * into virtual address `from'
- */
-#define io_remap_page_range(vma,from,phys,size,prot) \
- remap_page_range(vma,from,phys,size,prot)
-
-
-/*
* If this architecture has ISA IO, then define the isa_read/isa_write
* macros.
*/
@@ -281,5 +238,51 @@ out:
#define isa_check_signature(io,sig,len) (0)
#endif /* __mem_isa */
+
+/*
+ * ioremap and friends.
+ *
+ * ioremap takes a PCI memory address, as specified in
+ * linux/Documentation/IO-mapping.txt.
+ */
+extern void * __ioremap(unsigned long, size_t, unsigned long, unsigned long);
+extern void __iounmap(void *addr);
+
+#ifndef __arch_ioremap
+#define ioremap(cookie,size) __ioremap(cookie,size,0,1)
+#define ioremap_nocache(cookie,size) __ioremap(cookie,size,0,1)
+#define iounmap(cookie) __iounmap(cookie)
+#else
+#define ioremap(cookie,size) __arch_ioremap((cookie),(size),0,1)
+#define ioremap_nocache(cookie,size) __arch_ioremap((cookie),(size),0,1)
+#define iounmap(cookie) __arch_iounmap(cookie)
+#endif
+
+/*
+ * DMA-consistent mapping functions. These allocate/free a region of
+ * uncached, unwrite-buffered mapped memory space for use with DMA
+ * devices. This is the "generic" version. The PCI specific version
+ * is in pci.h
+ */
+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
+extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
+extern void consistent_sync(void *vaddr, size_t size, int rw);
+
+/*
+ * FIXME: I'm sure these will need to be changed for DISCONTIG
+ */
+/*
+ * Change "struct page" to physical address.
+ */
+#define page_to_phys(page) (PHYS_OFFSET + ((page - mem_map) << PAGE_SHIFT))
+#define page_to_bus(page) (PHYS_OFFSET + ((page - mem_map) << PAGE_SHIFT))
+
+/*
+ * can the hardware map this into one segment or not, given no other
+ * constraints.
+ */
+#define BIOVEC_MERGEABLE(vec1, vec2) \
+ ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
+
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_IO_H */
diff --git a/include/asm-arm/mach/pci.h b/include/asm-arm/mach/pci.h
index f0fb5f4ec..536672408 100644
--- a/include/asm-arm/mach/pci.h
+++ b/include/asm-arm/mach/pci.h
@@ -7,7 +7,12 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+
+struct pci_sys_data;
+struct pci_bus;
+
struct hw_pci {
+ /* START OF OLD STUFF */
/* Initialise the hardware */
void (*init)(void *);
@@ -25,10 +30,55 @@ struct hw_pci {
/* IRQ mapping */
int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
+
+ /* END OF OLD STUFF */
+
+ /* NEW STUFF */
+ int nr_controllers;
+ int (*setup)(int nr, struct pci_sys_data *);
+ struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
+ void (*preinit)(void);
+ void (*postinit)(void);
+};
+
+/*
+ * Per-controller structure
+ */
+struct pci_sys_data {
+ int busnr; /* primary bus number */
+ unsigned long mem_offset; /* bus->cpu memory mapping offset */
+ unsigned long io_offset; /* bus->cpu IO mapping offset */
+ struct pci_bus *bus; /* PCI bus */
+ struct resource *resource[3]; /* Primary PCI bus resources */
+ /* Bridge swizzling */
+ u8 (*swizzle)(struct pci_dev *, u8 *);
+ /* IRQ mapping */
+ int (*map_irq)(struct pci_dev *, u8, u8);
+ struct hw_pci *hw;
};
-extern u8 no_swizzle(struct pci_dev *dev, u8 *pin);
-extern void __init dc21285_setup_resources(struct resource **resource);
-extern void __init dc21285_init(void *sysdata);
+/*
+ * This is the standard PCI-PCI bridge swizzling algorithm.
+ */
+u8 pci_std_swizzle(struct pci_dev *dev, u8 *pinp);
+
+/*
+ * PCI controllers
+ */
+extern int iop310_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *iop310_scan_bus(int nr, struct pci_sys_data *);
+
+extern int dc21285_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
+extern void dc21285_preinit(void);
+extern void dc21285_postinit(void);
+
+extern int via82c505_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *via82c505_scan_bus(int nr, struct pci_sys_data *);
extern void __init via82c505_init(void *sysdata);
+extern int pci_v3_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *);
+extern void pci_v3_preinit(void);
+extern void pci_v3_postinit(void);
+
diff --git a/include/asm-arm/mach/serial_sa1100.h b/include/asm-arm/mach/serial_sa1100.h
index 2576c1184..cac52bb74 100644
--- a/include/asm-arm/mach/serial_sa1100.h
+++ b/include/asm-arm/mach/serial_sa1100.h
@@ -18,9 +18,10 @@ struct uart_info;
*/
struct sa1100_port_fns {
void (*set_mctrl)(struct uart_port *, u_int);
- int (*get_mctrl)(struct uart_port *);
+ u_int (*get_mctrl)(struct uart_port *);
void (*enable_ms)(struct uart_port *);
void (*pm)(struct uart_port *, u_int, u_int);
+ int (*set_wake)(struct uart_port *, u_int);
int (*open)(struct uart_port *, struct uart_info *);
void (*close)(struct uart_port *, struct uart_info *);
};
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index bc3bd8275..40d2709c8 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -3,8 +3,8 @@
#include <asm/proc/page.h>
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
@@ -14,8 +14,8 @@
#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
extern void copy_page(void *to, void *from);
-#define clear_user_page(page, vaddr) clear_page(page)
-#define copy_user_page(to, from, vaddr) copy_page(to, from)
+#define clear_user_page(page, vaddr) cpu_clear_user_page(page,vaddr)
+#define copy_user_page(to, from, vaddr) cpu_copy_user_page(to,from,vaddr)
#ifdef STRICT_MM_TYPECHECKS
/*
@@ -63,11 +63,21 @@ typedef unsigned long pgprot_t;
#ifndef __ASSEMBLY__
+#ifdef CONFIG_DEBUG_BUGVERBOSE
extern void __bug(const char *file, int line, void *data);
+/* give file/line information */
#define BUG() __bug(__FILE__, __LINE__, NULL)
#define PAGE_BUG(page) __bug(__FILE__, __LINE__, page)
+#else
+
+/* these just cause an oops */
+#define BUG() (*(int *)0 = 0)
+#define PAGE_BUG(page) (*(int *)0 = 0)
+
+#endif
+
/* Pure 2^n version of get_order */
static inline int get_order(unsigned long size)
{
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index d2237b850..dca7d55b5 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -3,7 +3,14 @@
#ifdef __KERNEL__
+#include <linux/mm.h> /* bah! */
+
#include <asm/arch/hardware.h>
+#include <asm/scatterlist.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+struct pci_dev;
static inline void pcibios_set_master(struct pci_dev *dev)
{
@@ -15,10 +22,11 @@ static inline void pcibios_penalize_isa_irq(int irq)
/* We don't do dynamic PCI IRQ allocation */
}
-#include <asm/scatterlist.h>
-#include <asm/io.h>
-
-struct pci_dev;
+/* The PCI address space does equal the physical memory
+ * address space. The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS (0)
/* Allocate and map kernel buffer using consistent mode DMA for a device.
* hwdev should be valid struct pci_dev pointer for PCI devices,
@@ -133,8 +141,20 @@ pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int directi
int i;
for (i = 0; i < nents; i++, sg++) {
- consistent_sync(sg->address, sg->length, direction);
- sg->dma_address = virt_to_bus(sg->address);
+ char *virt;
+ if (sg->address && sg->page)
+ BUG();
+ else if (!sg->address && !sg->page)
+ BUG();
+
+ if (sg->address) {
+ sg->dma_address = virt_to_bus(sg->address);
+ virt = sg->address;
+ } else {
+ sg->dma_address = page_to_bus(sg->page) + sg->offset;
+ virt = page_address(sg->page) + sg->offset;
+ }
+ consistent_sync(virt, sg->length, direction);
}
return nents;
@@ -176,8 +196,15 @@ pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int d
{
int i;
- for (i = 0; i < nelems; i++, sg++)
- consistent_sync(sg->address, sg->length, direction);
+ for (i = 0; i < nelems; i++, sg++) {
+ char *virt;
+
+ if (sg->address)
+ virt = sg->address;
+ else
+ virt = page_address(sg->page) + sg->offset;
+ consistent_sync(virt, sg->length, direction);
+ }
}
/* Return whether the given PCI device DMA address mask can
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 418f738bd..e7ed8b336 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -12,6 +12,7 @@
#include <linux/config.h>
#include <asm/arch/memory.h>
+#include <asm/arch/vmalloc.h>
#include <asm/proc-fns.h>
/*
@@ -177,6 +178,13 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern void pgtable_cache_init(void);
+/*
+ * remap a physical address `phys' of size `size' with page protection `prot'
+ * into virtual address `from'
+ */
+#define io_remap_page_range(vma,from,phys,size,prot) \
+ remap_page_range(vma,from,phys,size,prot)
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASMARM_PGTABLE_H */
diff --git a/include/asm-arm/proc-armo/ptrace.h b/include/asm-arm/proc-armo/ptrace.h
index 559a36693..79d44f4f7 100644
--- a/include/asm-arm/proc-armo/ptrace.h
+++ b/include/asm-arm/proc-armo/ptrace.h
@@ -10,21 +10,21 @@
#ifndef __ASM_PROC_PTRACE_H
#define __ASM_PROC_PTRACE_H
-#define USR26_MODE 0x00
-#define FIQ26_MODE 0x01
-#define IRQ26_MODE 0x02
-#define SVC26_MODE 0x03
+#define USR26_MODE 0x00000000
+#define FIQ26_MODE 0x00000001
+#define IRQ26_MODE 0x00000002
+#define SVC26_MODE 0x00000003
#define USR_MODE USR26_MODE
#define FIQ_MODE FIQ26_MODE
#define IRQ_MODE IRQ26_MODE
#define SVC_MODE SVC26_MODE
-#define MODE_MASK 0x03
-#define F_BIT (1 << 26)
-#define I_BIT (1 << 27)
-#define CC_V_BIT (1 << 28)
-#define CC_C_BIT (1 << 29)
-#define CC_Z_BIT (1 << 30)
-#define CC_N_BIT (1 << 31)
+#define MODE_MASK 0x00000003
+#define PSR_F_BIT 0x04000000
+#define PSR_I_BIT 0x08000000
+#define PSR_V_BIT 0x10000000
+#define PSR_C_BIT 0x20000000
+#define PSR_Z_BIT 0x40000000
+#define PSR_N_BIT 0x80000000
#define PCMASK 0xfc000003
#ifndef __ASSEMBLY__
@@ -65,13 +65,13 @@ struct pt_regs {
#define thumb_mode(regs) (0)
#define interrupts_enabled(regs) \
- (!((regs)->ARM_pc & I_BIT))
+ (!((regs)->ARM_pc & PSR_I_BIT))
#define fast_interrupts_enabled(regs) \
- (!((regs)->ARM_pc & F_BIT))
+ (!((regs)->ARM_pc & PSR_F_BIT))
#define condition_codes(regs) \
- ((regs)->ARM_pc & (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT))
+ ((regs)->ARM_pc & (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT))
/* Are the current registers suitable for user mode?
* (used to maintain security in signal handlers)
@@ -79,13 +79,13 @@ struct pt_regs {
static inline int valid_user_regs(struct pt_regs *regs)
{
if (user_mode(regs) &&
- (regs->ARM_pc & (F_BIT | I_BIT)) == 0)
+ (regs->ARM_pc & (PSR_F_BIT | PSR_I_BIT)) == 0)
return 1;
/*
* force it to be something sensible
*/
- regs->ARM_pc &= ~(MODE_MASK | F_BIT | I_BIT);
+ regs->ARM_pc &= ~(MODE_MASK | PSR_F_BIT | PSR_I_BIT);
return 0;
}
diff --git a/include/asm-arm/proc-armv/assembler.h b/include/asm-arm/proc-armv/assembler.h
index 6881898f5..64916c820 100644
--- a/include/asm-arm/proc-armv/assembler.h
+++ b/include/asm-arm/proc-armv/assembler.h
@@ -40,7 +40,7 @@
*/
.macro save_and_disable_irqs, oldcpsr, temp
mrs \oldcpsr, cpsr
- mov \temp, #I_BIT | MODE_SVC
+ mov \temp, #PSR_I_BIT | MODE_SVC
msr cpsr_c, \temp
.endm
diff --git a/include/asm-arm/proc-armv/cache.h b/include/asm-arm/proc-armv/cache.h
index 6547b3dc3..2f5f206fc 100644
--- a/include/asm-arm/proc-armv/cache.h
+++ b/include/asm-arm/proc-armv/cache.h
@@ -44,13 +44,13 @@
#define flush_cache_range(_vma,_start,_end) \
do { \
- if ((_vma)->vm_mm == current->mm) \
+ if ((_vma)->vm_mm == current->active_mm) \
cpu_cache_clean_invalidate_range((_start), (_end), 1); \
} while (0)
#define flush_cache_page(_vma,_vmaddr) \
do { \
- if ((_vma)->vm_mm == current->mm) { \
+ if ((_vma)->vm_mm == current->active_mm) { \
cpu_cache_clean_invalidate_range((_vmaddr), \
(_vmaddr) + PAGE_SIZE, \
((_vma)->vm_flags & VM_EXEC)); \
@@ -62,36 +62,68 @@
* in the cache for this page. This does not invalidate either I or D caches.
*
* Called from:
- * 1. mm/filemap.c:filemap_nopage
- * 2. mm/filemap.c:filemap_nopage
- * [via do_no_page - ok]
+ * 1. fs/exec.c:put_dirty_page - ok
+ * - page came from alloc_page(), so page->mapping = NULL.
+ * - flush_dcache_page called immediately prior.
+ *
+ * 2. kernel/ptrace.c:access_one_page - flush_icache_page
+ * - flush_cache_page takes care of the user space side of the mapping.
+ * - page is either a page cache page (with page->mapping set, and
+ * hence page->mapping->i_mmap{,shared} also set) or an anonymous
+ * page. I think this is ok.
+ *
+ * 3. kernel/ptrace.c:access_one_page - bad
+ * - flush_cache_page takes care of the user space side of the mapping.
+ * - no apparant cache protection, reading the kernel virtual alias
+ *
+ * 4. mm/filemap.c:filemap_no_page - ok
+ * - add_to_page_cache_* clears PG_arch_1.
+ * - page->mapping != NULL.
+ * - i_mmap or i_mmap_shared will be non-null if mmap'd
+ * - called from (8).
*
- * 3. mm/memory.c:break_cow
- * [copy_cow_page doesn't do anything to the cache; insufficient cache
- * handling. Need to add flush_dcache_page() here]
+ * 5. mm/memory.c:break_cow,do_wp_page - {copy,clear}_user_page
+ * - need to ensure that copy_cow_page has pushed all data from the dcache
+ * to the page.
+ * - calls
+ * - clear_user_highpage -> clear_user_page
+ * - copy_user_highpage -> copy_user_page
*
- * 4. mm/memory.c:do_swap_page
- * [read_swap_cache_async doesn't do anything to the cache: insufficient
- * cache handling. Need to add flush_dcache_page() here]
+ * 6. mm/memory.c:do_swap_page - flush_icache_page
+ * - flush_icache_page called afterwards - if flush_icache_page does the
+ * same as flush_dcache_page, update_mmu_cache will do the work for us.
+ * - update_mmu_cache called.
*
- * 5. mm/memory.c:do_anonymous_page
- * [zero page, never written by kernel - ok]
+ * 7. mm/memory.c:do_anonymous_page - {copy,clear}_user_page
+ * - calls clear_user_highpage. See (5)
*
- * 6. mm/memory.c:do_no_page
- * [we will be calling update_mmu_cache, which will catch on PG_dcache_dirty]
+ * 8. mm/memory.c:do_no_page - flush_icache_page
+ * - flush_icache_page called afterwards - if flush_icache_page does the
+ * same as flush_dcache_page, update_mmu_cache will do the work for us.
+ * - update_mmu_cache called.
+ * - When we place a user mapping, we will call update_mmu_cache,
+ * which will catch PG_arch_1 set.
*
- * 7. mm/shmem.c:shmem_nopage
- * 8. mm/shmem.c:shmem_nopage
- * [via do_no_page - ok]
+ * 9. mm/shmem.c:shmem_no_page - ok
+ * - shmem_get_page clears PG_arch_1, as does add_to_page_cache (duplicate)
+ * - page->mapping != NULL.
+ * - i_mmap or i_mmap_shared will be non-null if mmap'd
+ * - called from (8).
*
- * 9. fs/exec.c:put_dirty_page
- * [we call flush_dcache_page prior to this, which will flush out the
- * kernel virtual addresses from the dcache - ok]
+ * 10. mm/swapfile.c:try_to_unuse - bad
+ * - this looks really dodgy - we're putting pages from the swap cache
+ * straight into processes, and the only cache handling appears to
+ * be flush_page_to_ram.
*/
+#define flush_page_to_ram_ok
+#ifdef flush_page_to_ram_ok
+#define flush_page_to_ram(page) do { } while (0)
+#else
static __inline__ void flush_page_to_ram(struct page *page)
{
cpu_flush_ram_page(page_address(page));
}
+#endif
/*
* D cache only
@@ -101,6 +133,8 @@ static __inline__ void flush_page_to_ram(struct page *page)
#define clean_dcache_range(_s,_e) cpu_dcache_clean_range((_s),(_e))
#define flush_dcache_range(_s,_e) cpu_cache_clean_invalidate_range((_s),(_e),0)
+#define mapping_mapped(map) ((map)->i_mmap || (map)->i_mmap_shared)
+
/*
* flush_dcache_page is used when the kernel has written to the page
* cache page at virtual address page->virtual.
@@ -116,8 +150,7 @@ static __inline__ void flush_page_to_ram(struct page *page)
*/
static inline void flush_dcache_page(struct page *page)
{
- if (page->mapping && !(page->mapping->i_mmap) &&
- !(page->mapping->i_mmap_shared))
+ if (page->mapping && !mapping_mapped(page->mapping))
set_bit(PG_dcache_dirty, &page->flags);
else {
unsigned long virt = (unsigned long)page_address(page);
@@ -125,6 +158,30 @@ static inline void flush_dcache_page(struct page *page)
}
}
+/*
+ * flush_icache_page makes the kernel page address consistent with the
+ * user space mappings. The functionality is the same as flush_dcache_page,
+ * except we can do an optimisation and only clean the caches here if
+ * vma->vm_mm == current->active_mm.
+ *
+ * This function is misnamed IMHO. There are three places where it
+ * is called, each of which is preceded immediately by a call to
+ * flush_page_to_ram:
+ */
+#ifdef flush_page_to_ram_ok
+static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ if (page->mapping && !mapping_mapped(page->mapping))
+ set_bit(PG_dcache_dirty, &page->flags);
+ else if (vma->vm_mm == current->active_mm) {
+ unsigned long virt = (unsigned long)page_address(page);
+ cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
+ }
+}
+#else
+#define flush_icache_page(vma,pg) do { } while (0)
+#endif
+
#define clean_dcache_entry(_s) cpu_dcache_clean_entry((unsigned long)(_s))
/*
@@ -143,32 +200,6 @@ static inline void flush_dcache_page(struct page *page)
} while (0)
/*
- * This function is misnamed IMHO. There are three places where it
- * is called, each of which is preceded immediately by a call to
- * flush_page_to_ram:
- *
- * 1. kernel/ptrace.c:access_one_page
- * called after we have written to the kernel view of a user page.
- * The user page has been expundged from the cache by flush_cache_page.
- * [we don't need to do anything here if we add a call to
- * flush_dcache_page]
- *
- * 2. mm/memory.c:do_swap_page
- * called after we have (possibly) written to the kernel view of a
- * user page, which has previously been removed (ie, has been through
- * the swap cache).
- * [if the flush_page_to_ram() conditions are satisfied, then ok]
- *
- * 3. mm/memory.c:do_no_page
- * [if the flush_page_to_ram() conditions are satisfied, then ok]
- *
- * Invalidating the icache at the kernels virtual page isn't really
- * going to do us much good, since we wouldn't have executed any
- * instructions there.
- */
-#define flush_icache_page(vma,pg) do { } while (0)
-
-/*
* Old ARM MEMC stuff. This supports the reversed mapping handling that
* we have on the older 26-bit machines. We don't have a MEMC chip, so...
*/
diff --git a/include/asm-arm/proc-armv/pgalloc.h b/include/asm-arm/proc-armv/pgalloc.h
index 6059f6455..f5db111e1 100644
--- a/include/asm-arm/proc-armv/pgalloc.h
+++ b/include/asm-arm/proc-armv/pgalloc.h
@@ -46,13 +46,12 @@ static inline void pte_free_slow(pte_t *pte)
* If 'mm' is the init tasks mm, then we are doing a vmalloc, and we
* need to set stuff up correctly for it.
*/
-#define pmd_populate(mm,pmdp,pte) \
- do { \
- unsigned long __prot; \
- if (mm == &init_mm) \
- __prot = _PAGE_KERNEL_TABLE; \
- else \
- __prot = _PAGE_USER_TABLE; \
- set_pmd(pmdp, __mk_pmd(pte, __prot)); \
+#define pmd_populate(mm,pmdp,pte) \
+ do { \
+ unsigned long __prot; \
+ if (mm == &init_mm) \
+ __prot = _PAGE_KERNEL_TABLE; \
+ else \
+ __prot = _PAGE_USER_TABLE; \
+ set_pmd(pmdp, __mk_pmd(pte, __prot)); \
} while (0)
-
diff --git a/include/asm-arm/proc-armv/pgtable.h b/include/asm-arm/proc-armv/pgtable.h
index 7532698e4..d0da2c4a8 100644
--- a/include/asm-arm/proc-armv/pgtable.h
+++ b/include/asm-arm/proc-armv/pgtable.h
@@ -15,9 +15,6 @@
#ifndef __ASM_PROC_PGTABLE_H
#define __ASM_PROC_PGTABLE_H
-#include <asm/proc/domain.h>
-#include <asm/arch/vmalloc.h>
-
/*
* entries per page directory level: they are two-level, so
* we don't really have any PMD directory.
@@ -26,27 +23,91 @@
#define PTRS_PER_PMD 1
#define PTRS_PER_PGD 4096
-/****************
-* PMD functions *
-****************/
-
-/* PMD types (actually level 1 descriptor) */
-#define PMD_TYPE_MASK 0x0003
-#define PMD_TYPE_FAULT 0x0000
-#define PMD_TYPE_TABLE 0x0001
-#define PMD_TYPE_SECT 0x0002
-#define PMD_UPDATABLE 0x0010
-#define PMD_SECT_CACHEABLE 0x0008
-#define PMD_SECT_BUFFERABLE 0x0004
-#define PMD_SECT_AP_WRITE 0x0400
-#define PMD_SECT_AP_READ 0x0800
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ * - common
+ */
+#define PMD_TYPE_MASK (3 << 0)
+#define PMD_TYPE_FAULT (0 << 0)
+#define PMD_TYPE_TABLE (1 << 0)
+#define PMD_TYPE_SECT (2 << 0)
+#define PMD_UPDATABLE (1 << 4)
#define PMD_DOMAIN(x) ((x) << 5)
+#define PMD_PROTECTION (1 << 9) /* v5 */
+/*
+ * - section
+ */
+#define PMD_SECT_BUFFERABLE (1 << 2)
+#define PMD_SECT_CACHEABLE (1 << 3)
+#define PMD_SECT_AP_WRITE (1 << 10)
+#define PMD_SECT_AP_READ (1 << 11)
+#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */
+/*
+ * - coarse table (not used)
+ */
+
+/*
+ * + Level 2 descriptor (PTE)
+ * - common
+ */
+#define PTE_TYPE_MASK (3 << 0)
+#define PTE_TYPE_FAULT (0 << 0)
+#define PTE_TYPE_LARGE (1 << 0)
+#define PTE_TYPE_SMALL (2 << 0)
+#define PTE_TYPE_EXT (3 << 0) /* v5 */
+#define PTE_BUFFERABLE (1 << 2)
+#define PTE_CACHEABLE (1 << 3)
+
+/*
+ * - extended small page/tiny page
+ */
+#define PTE_EXT_AP_UNO_SRO (0 << 4)
+#define PTE_EXT_AP_UNO_SRW (1 << 4)
+#define PTE_EXT_AP_URO_SRW (2 << 4)
+#define PTE_EXT_AP_URW_SRW (3 << 4)
+#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
+
+/*
+ * - small page
+ */
+#define PTE_SMALL_AP_UNO_SRO (0x00 << 4)
+#define PTE_SMALL_AP_UNO_SRW (0x55 << 4)
+#define PTE_SMALL_AP_URO_SRW (0xaa << 4)
+#define PTE_SMALL_AP_URW_SRW (0xff << 4)
+#define PTE_AP_READ PTE_SMALL_AP_URO_SRW
+#define PTE_AP_WRITE PTE_SMALL_AP_UNO_SRW
+
+/*
+ * "Linux" PTE definitions.
+ *
+ * We keep two sets of PTEs - the hardware and the linux version.
+ * This allows greater flexibility in the way we map the Linux bits
+ * onto the hardware tables, and allows us to have YOUNG and DIRTY
+ * bits.
+ *
+ * The PTE table pointer refers to the hardware entries; the "Linux"
+ * entries are stored 1024 bytes below.
+ */
+#define L_PTE_PRESENT (1 << 0)
+#define L_PTE_YOUNG (1 << 1)
+#define L_PTE_BUFFERABLE (1 << 2) /* matches PTE */
+#define L_PTE_CACHEABLE (1 << 3) /* matches PTE */
+#define L_PTE_USER (1 << 4)
+#define L_PTE_WRITE (1 << 5)
+#define L_PTE_EXEC (1 << 6)
+#define L_PTE_DIRTY (1 << 7)
+
+#ifndef __ASSEMBLY__
+
+#include <asm/proc/domain.h>
#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
#define pmd_bad(pmd) (pmd_val(pmd) & 2)
-#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp,pmd)
+#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp, pmd)
static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
{
@@ -75,49 +136,8 @@ static inline unsigned long pmd_page(pmd_t pmd)
return __phys_to_virt(ptr);
}
-/****************
-* PTE functions *
-****************/
-
-/* PTE types (actually level 2 descriptor) */
-#define PTE_TYPE_MASK 0x0003
-#define PTE_TYPE_FAULT 0x0000
-#define PTE_TYPE_LARGE 0x0001
-#define PTE_TYPE_SMALL 0x0002
-#define PTE_AP_READ 0x0aa0
-#define PTE_AP_WRITE 0x0550
-#define PTE_CACHEABLE 0x0008
-#define PTE_BUFFERABLE 0x0004
-
#define set_pte(ptep, pte) cpu_set_pte(ptep,pte)
-/* We now keep two sets of ptes - the physical and the linux version.
- * This gives us many advantages, and allows us greater flexibility.
- *
- * The Linux pte's contain:
- * bit meaning
- * 0 page present
- * 1 young
- * 2 bufferable - matches physical pte
- * 3 cacheable - matches physical pte
- * 4 user
- * 5 write
- * 6 execute
- * 7 dirty
- * 8-11 unused
- * 12-31 virtual page address
- *
- * These are stored at the pte pointer; the physical PTE is at -1024bytes
- */
-#define L_PTE_PRESENT (1 << 0)
-#define L_PTE_YOUNG (1 << 1)
-#define L_PTE_BUFFERABLE (1 << 2)
-#define L_PTE_CACHEABLE (1 << 3)
-#define L_PTE_USER (1 << 4)
-#define L_PTE_WRITE (1 << 5)
-#define L_PTE_EXEC (1 << 6)
-#define L_PTE_DIRTY (1 << 7)
-
/*
* The following macros handle the cache and bufferable bits...
*/
@@ -163,4 +183,6 @@ PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG);
*/
#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))
+#endif /* __ASSEMBLY__ */
+
#endif /* __ASM_PROC_PGTABLE_H */
diff --git a/include/asm-arm/proc-armv/ptrace.h b/include/asm-arm/proc-armv/ptrace.h
index 190caa193..fcc127811 100644
--- a/include/asm-arm/proc-armv/ptrace.h
+++ b/include/asm-arm/proc-armv/ptrace.h
@@ -12,27 +12,51 @@
#include <linux/config.h>
-#define USR26_MODE 0x00
-#define FIQ26_MODE 0x01
-#define IRQ26_MODE 0x02
-#define SVC26_MODE 0x03
-#define USR_MODE 0x10
-#define FIQ_MODE 0x11
-#define IRQ_MODE 0x12
-#define SVC_MODE 0x13
-#define ABT_MODE 0x17
-#define UND_MODE 0x1b
-#define SYSTEM_MODE 0x1f
-#define MODE_MASK 0x1f
-#define T_BIT 0x20
-#define F_BIT 0x40
-#define I_BIT 0x80
-#define CC_V_BIT (1 << 28)
-#define CC_C_BIT (1 << 29)
-#define CC_Z_BIT (1 << 30)
-#define CC_N_BIT (1 << 31)
+/*
+ * PSR bits
+ */
+#define USR26_MODE 0x00000000
+#define FIQ26_MODE 0x00000001
+#define IRQ26_MODE 0x00000002
+#define SVC26_MODE 0x00000003
+#define USR_MODE 0x00000010
+#define FIQ_MODE 0x00000011
+#define IRQ_MODE 0x00000012
+#define SVC_MODE 0x00000013
+#define ABT_MODE 0x00000017
+#define UND_MODE 0x0000001b
+#define SYSTEM_MODE 0x0000001f
+#define MODE32_BIT 0x00000010
+#define MODE_MASK 0x0000001f
+#define PSR_T_BIT 0x00000020
+#define PSR_F_BIT 0x00000040
+#define PSR_I_BIT 0x00000080
+#define PSR_J_BIT 0x01000000
+#define PSR_V_BIT 0x10000000
+#define PSR_C_BIT 0x20000000
+#define PSR_Z_BIT 0x40000000
+#define PSR_N_BIT 0x80000000
#define PCMASK 0
+/*
+ * CR1 bits
+ */
+#define CR1_M 0x00000001 /* MMU */
+#define CR1_A 0x00000002 /* Alignment fault */
+#define CR1_C 0x00000004 /* Dcache */
+#define CR1_W 0x00000008 /* Write buffer */
+#define CR1_P 0x00000010 /* Prog32 */
+#define CR1_D 0x00000020 /* Data32 */
+#define CR1_L 0x00000040 /* Late abort */
+#define CR1_B 0x00000080 /* Big endian */
+#define CR1_S 0x00000100 /* System protection */
+#define CR1_R 0x00000200 /* ROM protection */
+#define CR1_F 0x00000400
+#define CR1_Z 0x00000800 /* BTB enable */
+#define CR1_I 0x00001000 /* Icache */
+#define CR1_V 0x00002000 /* Vector relocation */
+#define CR1_RR 0x00004000 /* Round Robin */
+
#ifndef __ASSEMBLY__
/* this struct defines the way the registers are stored on the
@@ -68,7 +92,7 @@ struct pt_regs {
#ifdef CONFIG_ARM_THUMB
#define thumb_mode(regs) \
- (((regs)->ARM_cpsr & T_BIT))
+ (((regs)->ARM_cpsr & PSR_T_BIT))
#else
#define thumb_mode(regs) (0)
#endif
@@ -77,27 +101,27 @@ struct pt_regs {
((regs)->ARM_cpsr & MODE_MASK)
#define interrupts_enabled(regs) \
- (!((regs)->ARM_cpsr & I_BIT))
+ (!((regs)->ARM_cpsr & PSR_I_BIT))
#define fast_interrupts_enabled(regs) \
- (!((regs)->ARM_cpsr & F_BIT))
+ (!((regs)->ARM_cpsr & PSR_F_BIT))
#define condition_codes(regs) \
- ((regs)->ARM_cpsr & (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT))
+ ((regs)->ARM_cpsr & (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT))
/* Are the current registers suitable for user mode?
* (used to maintain security in signal handlers)
*/
static inline int valid_user_regs(struct pt_regs *regs)
{
- if ((regs->ARM_cpsr & 0xf) == 0 &&
- (regs->ARM_cpsr & (F_BIT|I_BIT)) == 0)
+ if (user_mode(regs) &&
+ (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0)
return 1;
/*
* Force CPSR to something logical...
*/
- regs->ARM_cpsr &= (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT|0x10);
+ regs->ARM_cpsr &= (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT|MODE32_BIT);
return 0;
}
diff --git a/include/asm-arm/proc-armv/uaccess.h b/include/asm-arm/proc-armv/uaccess.h
index 74c5e6992..8053f9d9f 100644
--- a/include/asm-arm/proc-armv/uaccess.h
+++ b/include/asm-arm/proc-armv/uaccess.h
@@ -54,6 +54,7 @@ static inline void set_fs (mm_segment_t fs)
: "=r" (err) \
: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
+#ifndef __ARMEB__
#define __put_user_asm_half(x,addr,err) \
({ \
unsigned long __temp = (unsigned long)(x); \
@@ -61,6 +62,15 @@ static inline void set_fs (mm_segment_t fs)
__put_user_asm_byte(__temp, __ptr, err); \
__put_user_asm_byte(__temp >> 8, __ptr + 1, err); \
})
+#else
+#define __put_user_asm_half(x,addr,err) \
+({ \
+ unsigned long __temp = (unsigned long)(x); \
+ unsigned long __ptr = (unsigned long)(addr); \
+ __put_user_asm_byte(__temp >> 8, __ptr, err); \
+ __put_user_asm_byte(__temp, __ptr + 1, err); \
+})
+#endif
#define __put_user_asm_word(x,addr,err) \
__asm__ __volatile__( \
@@ -95,6 +105,7 @@ static inline void set_fs (mm_segment_t fs)
: "=r" (err), "=&r" (x) \
: "r" (addr), "i" (-EFAULT), "0" (err))
+#ifndef __ARMEB__
#define __get_user_asm_half(x,addr,err) \
({ \
unsigned long __b1, __b2, __ptr = (unsigned long)addr; \
@@ -102,7 +113,15 @@ static inline void set_fs (mm_segment_t fs)
__get_user_asm_byte(__b2, __ptr + 1, err); \
(x) = __b1 | (__b2 << 8); \
})
-
+#else
+#define __get_user_asm_half(x,addr,err) \
+({ \
+ unsigned long __b1, __b2; \
+ __get_user_asm_byte(__b1, addr, err); \
+ __get_user_asm_byte(__b2, (int)(addr) + 1, err); \
+ (x) = (__b1 << 8) | __b2; \
+})
+#endif
#define __get_user_asm_word(x,addr,err) \
__asm__ __volatile__( \
diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
index 44f1cd429..1f212216a 100644
--- a/include/asm-arm/proc-fns.h
+++ b/include/asm-arm/proc-fns.h
@@ -26,6 +26,12 @@
# define MULTI_CPU
#endif
+/*
+ * CPU_NAME - the prefix for CPU related functions
+ * CPU_ABRT - the prefix for the CPU abort decoding function
+ * MMU_ARCH - the prefix for copy_user_page/clear_user_page
+ */
+
#ifdef CONFIG_CPU_32
# define CPU_INCLUDE_NAME "asm/cpu-multi32.h"
# ifdef CONFIG_CPU_ARM610
@@ -33,7 +39,9 @@
# undef MULTI_CPU
# define MULTI_CPU
# else
-# define CPU_NAME arm6
+# define CPU_NAME cpu_arm6
+# define CPU_ABRT cpu_arm6
+# define MMU_ARCH armv3
# endif
# endif
# ifdef CONFIG_CPU_ARM710
@@ -41,7 +49,9 @@
# undef MULTI_CPU
# define MULTI_CPU
# else
-# define CPU_NAME arm7
+# define CPU_NAME cpu_arm7
+# define CPU_ABRT cpu_arm7
+# define MMU_ARCH armv3
# endif
# endif
# ifdef CONFIG_CPU_ARM720T
@@ -49,7 +59,9 @@
# undef MULTI_CPU
# define MULTI_CPU
# else
-# define CPU_NAME arm720
+# define CPU_NAME cpu_arm720
+# define CPU_ABRT armv4t_late
+# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_ARM920T
@@ -57,7 +69,19 @@
# undef MULTI_CPU
# define MULTI_CPU
# else
-# define CPU_NAME arm920
+# define CPU_NAME cpu_arm920
+# define CPU_ABRT armv4t_early
+# define MMU_ARCH armv4
+# endif
+# endif
+# ifdef CONFIG_CPU_ARM922T
+# ifdef CPU_NAME
+# undef MULTI_CPU
+# define MULTI_CPU
+# else
+# define CPU_NAME cpu_arm922
+# define CPU_ABRT armv4t_early
+# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_ARM926T
@@ -65,7 +89,9 @@
# undef MULTI_CPU
# define MULTI_CPU
# else
-# define CPU_NAME arm926
+# define CPU_NAME cpu_arm926
+# define CPU_ABRT armv5ej_early
+# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_SA110
@@ -73,7 +99,9 @@
# undef MULTI_CPU
# define MULTI_CPU
# else
-# define CPU_NAME sa110
+# define CPU_NAME cpu_sa110
+# define CPU_ABRT armv4_early
+# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_SA1100
@@ -81,7 +109,29 @@
# undef MULTI_CPU
# define MULTI_CPU
# else
-# define CPU_NAME sa1100
+# define CPU_NAME cpu_sa1100
+# define CPU_ABRT armv4_early
+# define MMU_ARCH armv4_mc
+# endif
+# endif
+# ifdef CONFIG_CPU_ARM1020
+# ifdef CPU_NAME
+# undef MULTI_CPU
+# define MULTI_CPU
+# else
+# define CPU_NAME cpu_arm1020
+# define CPU_ABRT armv4t_early
+# define MMU_ARCH armv4
+# endif
+# endif
+# ifdef CONFIG_CPU_XSCALE
+# ifdef CPU_NAME
+# undef MULTI_CPU
+# define MULTI_CPU
+# else
+# define CPU_NAME cpu_xscale
+# define CPU_ABRT armv4t_early
+# define MMU_ARCH armv5te
# endif
# endif
#endif
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index aa0148d90..cd4a06d7c 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -68,13 +68,6 @@ struct thread_struct {
EXTRA_THREAD_STRUCT
};
-#define INIT_MMAP { \
- vm_mm: &init_mm, \
- vm_page_prot: PAGE_SHARED, \
- vm_flags: VM_READ | VM_WRITE | VM_EXEC, \
- vm_avl_height: 1, \
-}
-
#define INIT_THREAD { \
refcount: ATOMIC_INIT(1), \
EXTRA_THREAD_STRUCT_INIT \
diff --git a/include/asm-arm/scatterlist.h b/include/asm-arm/scatterlist.h
index 8b3b67099..d9c056c77 100644
--- a/include/asm-arm/scatterlist.h
+++ b/include/asm-arm/scatterlist.h
@@ -4,10 +4,11 @@
#include <asm/types.h>
struct scatterlist {
- struct page *page;
- unsigned int offset;
+ struct page *page; /* buffer page */
+ unsigned int offset; /* buffer offset */
dma_addr_t dma_address; /* dma address */
unsigned int length; /* length */
+ char *__address; /* for set_dma_addr */
};
/*
diff --git a/include/asm-arm/types.h b/include/asm-arm/types.h
index 39d5290f5..7b66b95e5 100644
--- a/include/asm-arm/types.h
+++ b/include/asm-arm/types.h
@@ -44,6 +44,7 @@ typedef unsigned long long u64;
/* Dma addresses are 32-bits wide. */
typedef u32 dma_addr_t;
+typedef u32 dma64_addr_t;
#endif /* __KERNEL__ */
diff --git a/include/asm-arm/unaligned.h b/include/asm-arm/unaligned.h
index 44aa2e3b1..a5f2abf84 100644
--- a/include/asm-arm/unaligned.h
+++ b/include/asm-arm/unaligned.h
@@ -39,24 +39,30 @@ extern int __bug_unaligned_x(void *ptr);
* out of long long >> 32, or the low word from long long << 32
*/
-#define __get_unaligned_2(__p) \
+#define __get_unaligned_2_le(__p) \
(__p[0] | __p[1] << 8)
-#define __get_unaligned_4(__p) \
+#define __get_unaligned_2_be(__p) \
+ (__p[0] << 8 | __p[1])
+
+#define __get_unaligned_4_le(__p) \
(__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
-#define get_unaligned(ptr) \
+#define __get_unaligned_4_be(__p) \
+ (__p[0] << 24 | __p[1] << 16 | __p[2] << 8 | __p[3])
+
+#define __get_unaligned_le(ptr) \
({ \
__typeof__(*(ptr)) __v; \
__u8 *__p = (__u8 *)(ptr); \
switch (sizeof(*(ptr))) { \
case 1: __v = *(ptr); break; \
- case 2: __v = __get_unaligned_2(__p); break; \
- case 4: __v = __get_unaligned_4(__p); break; \
+ case 2: __v = __get_unaligned_2_le(__p); break; \
+ case 4: __v = __get_unaligned_4_le(__p); break; \
case 8: { \
unsigned int __v1, __v2; \
- __v2 = __get_unaligned_4((__p+4)); \
- __v1 = __get_unaligned_4(__p); \
+ __v2 = __get_unaligned_4_le((__p+4)); \
+ __v1 = __get_unaligned_4_le(__p); \
__v = ((unsigned long long)__v2 << 32 | __v1); \
} \
break; \
@@ -65,44 +71,87 @@ extern int __bug_unaligned_x(void *ptr);
__v; \
})
+#define __get_unaligned_be(ptr) \
+ ({ \
+ __typeof__(*(ptr)) __v; \
+ __u8 *__p = (__u8 *)(ptr); \
+ switch (sizeof(*(ptr))) { \
+ case 1: __v = *(ptr); break; \
+ case 2: __v = __get_unaligned_2_be(__p); break; \
+ case 4: __v = __get_unaligned_4_be(__p); break; \
+ case 8: { \
+ unsigned int __v1, __v2; \
+ __v2 = __get_unaligned_4_be(__p); \
+ __v1 = __get_unaligned_4_be((__p+4)); \
+ __v = ((unsigned long long)__v2 << 32 | __v1); \
+ } \
+ break; \
+ default: __v = __bug_unaligned_x(__p); break; \
+ } \
+ __v; \
+ })
-static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
+
+static inline void __put_unaligned_2_le(__u32 __v, register __u8 *__p)
{
*__p++ = __v;
*__p++ = __v >> 8;
}
-static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
+static inline void __put_unaligned_2_be(__u32 __v, register __u8 *__p)
+{
+ *__p++ = __v >> 8;
+ *__p++ = __v;
+}
+
+static inline void __put_unaligned_4_le(__u32 __v, register __u8 *__p)
+{
+ __put_unaligned_2_le(__v >> 16, __p + 2);
+ __put_unaligned_2_le(__v, __p);
+}
+
+static inline void __put_unaligned_4_be(__u32 __v, register __u8 *__p)
{
- __put_unaligned_2(__v >> 16, __p + 2);
- __put_unaligned_2(__v, __p);
+ __put_unaligned_2_be(__v >> 16, __p);
+ __put_unaligned_2_be(__v, __p + 2);
}
-static inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p)
+static inline void __put_unaligned_8_le(const unsigned long long __v, register __u8 *__p)
{
/*
* tradeoff: 8 bytes of stack for all unaligned puts (2
* instructions), or an extra register in the long long
* case - go for the extra register.
*/
- __put_unaligned_4(__v >> 32, __p+4);
- __put_unaligned_4(__v, __p);
+ __put_unaligned_4_le(__v >> 32, __p+4);
+ __put_unaligned_4_le(__v, __p);
+}
+
+static inline void __put_unaligned_8_be(const unsigned long long __v, register __u8 *__p)
+{
+ /*
+ * tradeoff: 8 bytes of stack for all unaligned puts (2
+ * instructions), or an extra register in the long long
+ * case - go for the extra register.
+ */
+ __put_unaligned_4_be(__v >> 32, __p);
+ __put_unaligned_4_be(__v, __p+4);
}
/*
* Try to store an unaligned value as efficiently as possible.
*/
-#define put_unaligned(val,ptr) \
+#define __put_unaligned_le(val,ptr) \
({ \
switch (sizeof(*(ptr))) { \
case 1: \
*(ptr) = (val); \
break; \
- case 2: __put_unaligned_2((val),(__u8 *)(ptr)); \
+ case 2: __put_unaligned_2_le((val),(__u8 *)(ptr)); \
break; \
- case 4: __put_unaligned_4((val),(__u8 *)(ptr)); \
+ case 4: __put_unaligned_4_le((val),(__u8 *)(ptr)); \
break; \
- case 8: __put_unaligned_8((val),(__u8 *)(ptr)); \
+ case 8: __put_unaligned_8_le((val),(__u8 *)(ptr)); \
break; \
default: __bug_unaligned_x(ptr); \
break; \
@@ -110,5 +159,33 @@ static inline void __put_unaligned_8(const unsigned long long __v, register __u8
(void) 0; \
})
+#define put_unaligned_be(val,ptr) \
+ ({ \
+ switch (sizeof(*(ptr))) { \
+ case 1: \
+ *(ptr) = (val); \
+ break; \
+ case 2: __put_unaligned_2_be((val),(__u8 *)(ptr)); \
+ break; \
+ case 4: __put_unaligned_4_be((val),(__u8 *)(ptr)); \
+ break; \
+ case 8: __put_unaligned_8_be((val),(__u8 *)(ptr)); \
+ break; \
+ default: __bug_unaligned_x(ptr); \
+ break; \
+ } \
+ (void) 0; \
+ })
+
+/*
+ * Select endianness
+ */
+#ifndef __ARMEB__
+#define get_unaligned __get_unaligned_le
+#define put_unaligned __put_unaligned_le
+#else
+#define get_unaligned __get_unaligned_be
+#define put_unaligned __put_unaligned_be
+#endif
#endif
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 510cac1b8..674856b86 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -240,6 +240,10 @@
#define __NR_mincore (__NR_SYSCALL_BASE+219)
#define __NR_madvise (__NR_SYSCALL_BASE+220)
#define __NR_fcntl64 (__NR_SYSCALL_BASE+221)
+ /* 222 for tux */
+#define __NR_security (__NR_SYSCALL_BASE+223)
+#define __NR_gettid (__NR_SYSCALL_BASE+224)
+#define __NR_readahead (__NR_SYSCALL_BASE+225)
/*
* The following SWIs are ARM private.
@@ -357,6 +361,9 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
#ifdef __KERNEL_SYSCALLS__
+struct rusage;
+asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);
+
static inline long idle(void)
{
extern long sys_idle(void);
diff --git a/include/asm-arm/vt.h b/include/asm-arm/vt.h
deleted file mode 100644
index 6c3573768..000000000
--- a/include/asm-arm/vt.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _ASMARM_VT_H
-#define _ASMARM_VT_H
-
-#define VT_GETSCRINFO 0x56FD /* get screen info */
-#define VT_GETPALETTE 0x56FE /* get palette */
-#define VT_SETPALETTE 0x56FF /* set palette */
-
-#endif /* _ASMARM_VT_H */
diff --git a/include/asm-sparc/keyboard.h b/include/asm-sparc/keyboard.h
index b969308f9..5fad1ceaf 100644
--- a/include/asm-sparc/keyboard.h
+++ b/include/asm-sparc/keyboard.h
@@ -1,4 +1,4 @@
-/* $Id: keyboard.h,v 1.7 2001-08-18 09:40:46 davem Exp $
+/* $Id: keyboard.h,v 1.8 2002-01-08 16:00:20 davem Exp $
* linux/include/asm-sparc/keyboard.h
*
* sparc64 Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be)
@@ -40,7 +40,6 @@ extern unsigned char pcikbd_sysrq_xlate[128];
#define kbd_init pcikbd_init
#define compute_shiftstate pci_compute_shiftstate
-#define keyboard_wait_for_keypress pci_wait_for_keypress
#define getkeycode pci_getkeycode
#define setkeycode pci_setkeycode
#define getledstate pci_getledstate
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
index 7d9a37260..69c60a722 100644
--- a/include/asm-sparc64/elf.h
+++ b/include/asm-sparc64/elf.h
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.30 2001-08-30 23:35:38 kanoj Exp $ */
+/* $Id: elf.h,v 1.31 2002-01-08 16:00:20 davem Exp $ */
#ifndef __ASM_SPARC64_ELF_H
#define __ASM_SPARC64_ELF_H
@@ -75,24 +75,7 @@ do { unsigned char flags = current->thread.flags; \
else \
flags &= ~SPARC_FLAG_32BIT; \
if (flags != current->thread.flags) { \
- unsigned long pgd_cache = 0UL; \
- if (flags & SPARC_FLAG_32BIT) { \
- pgd_t *pgd0 = &current->mm->pgd[0]; \
- if (pgd_none (*pgd0)) { \
- pmd_t *page = pmd_alloc_one_fast(NULL, 0); \
- if (!page) \
- page = pmd_alloc_one(NULL, 0); \
- pgd_set(pgd0, page); \
- } \
- pgd_cache = pgd_val(*pgd0) << 11UL; \
- } \
- __asm__ __volatile__( \
- "stxa\t%0, [%1] %2\n\t" \
- "membar #Sync" \
- : /* no outputs */ \
- : "r" (pgd_cache), \
- "r" (TSB_REG), \
- "i" (ASI_DMMU)); \
+ /* flush_thread will update pgd cache */\
current->thread.flags = flags; \
} \
\
diff --git a/include/asm-sparc64/keyboard.h b/include/asm-sparc64/keyboard.h
index 59c09a810..653f39a6f 100644
--- a/include/asm-sparc64/keyboard.h
+++ b/include/asm-sparc64/keyboard.h
@@ -1,4 +1,4 @@
-/* $Id: keyboard.h,v 1.5 2001-08-18 09:40:46 davem Exp $
+/* $Id: keyboard.h,v 1.6 2002-01-08 16:00:20 davem Exp $
* linux/include/asm-sparc64/keyboard.h
*
* Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be)
@@ -38,7 +38,6 @@ extern unsigned char pcikbd_sysrq_xlate[128];
#define kbd_init pcikbd_init
#define compute_shiftstate pci_compute_shiftstate
-#define keyboard_wait_for_keypress pci_wait_for_keypress
#define getkeycode pci_getkeycode
#define setkeycode pci_setkeycode
#define getledstate pci_getledstate
diff --git a/include/linux/acct.h b/include/linux/acct.h
index e20b18399..fb0a19dc8 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -76,7 +76,7 @@ struct acct
#include <linux/config.h>
#ifdef CONFIG_BSD_PROCESS_ACCT
-extern void acct_auto_close(kdev_t dev);
+extern void acct_auto_close(struct super_block *sb);
extern int acct_process(long exitcode);
#else
#define acct_auto_close(x) do { } while (0)
diff --git a/include/linux/amigaffs.h b/include/linux/amigaffs.h
index 39bbdbbe4..1e7d6e8fa 100644
--- a/include/linux/amigaffs.h
+++ b/include/linux/amigaffs.h
@@ -23,8 +23,7 @@
static inline void
affs_set_blocksize(struct super_block *sb, int size)
{
- set_blocksize(sb->s_dev, size);
- sb->s_blocksize = size;
+ sb_set_blocksize(sb, size);
}
static inline struct buffer_head *
affs_bread(struct super_block *sb, int block)
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 8bbacfeeb..a34f8d7dc 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -35,6 +35,7 @@
#endif
#define BIO_MAX_SECTORS 128
+#define BIO_MAX_SIZE (BIO_MAX_SECTORS << 9)
/*
* was unsigned short, but we might as well be ready for > 64kB I/O pages
diff --git a/include/linux/blk.h b/include/linux/blk.h
index 384b2cc97..efede40e2 100644
--- a/include/linux/blk.h
+++ b/include/linux/blk.h
@@ -2,6 +2,7 @@
#define _BLK_H
#include <linux/blkdev.h>
+#include <linux/elevator.h>
#include <linux/locks.h>
#include <linux/config.h>
#include <linux/spinlock.h>
@@ -43,9 +44,10 @@ extern void end_that_request_last(struct request *);
static inline void blkdev_dequeue_request(struct request *req)
{
list_del(&req->queuelist);
-}
-#define __elv_next_request(q) (q)->elevator.elevator_next_req_fn((q))
+ if (req->q)
+ elv_remove_request(req->q, req);
+}
extern inline struct request *elv_next_request(request_queue_t *q)
{
@@ -79,21 +81,21 @@ extern inline struct request *elv_next_request(request_queue_t *q)
return rq;
}
-#define __elv_add_request_core(q, rq, where, plug) \
+#define _elv_add_request_core(q, rq, where, plug) \
do { \
if ((plug)) \
blk_plug_device((q)); \
(q)->elevator.elevator_add_req_fn((q), (rq), (where)); \
} while (0)
-#define __elv_add_request(q, rq, back, p) do { \
+#define _elv_add_request(q, rq, back, p) do { \
if ((back)) \
- __elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
+ _elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
else \
- __elv_add_request_core((q), (rq), &(q)->queue_head, 0); \
+ _elv_add_request_core((q), (rq), &(q)->queue_head, 0); \
} while (0)
-#define elv_add_request(q, rq, back) __elv_add_request((q), (rq), (back), 1)
+#define elv_add_request(q, rq, back) _elv_add_request((q), (rq), (back), 1)
#if defined(MAJOR_NR) || defined(IDE_DRIVER)
@@ -106,14 +108,14 @@ extern inline struct request *elv_next_request(request_queue_t *q)
#ifdef IDE_DRIVER
-#define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS)
+#define DEVICE_NR(device) (minor(device) >> PARTN_BITS)
#define DEVICE_NAME "ide"
#elif (MAJOR_NR == RAMDISK_MAJOR)
/* ram disk */
#define DEVICE_NAME "ramdisk"
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#define DEVICE_NO_RANDOM
#elif (MAJOR_NR == Z2RAM_MAJOR)
@@ -121,7 +123,7 @@ extern inline struct request *elv_next_request(request_queue_t *q)
/* Zorro II Ram */
#define DEVICE_NAME "Z2RAM"
#define DEVICE_REQUEST do_z2_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == FLOPPY_MAJOR)
@@ -130,7 +132,7 @@ static void floppy_off(unsigned int nr);
#define DEVICE_NAME "floppy"
#define DEVICE_INTR do_floppy
#define DEVICE_REQUEST do_fd_request
-#define DEVICE_NR(device) ( (MINOR(device) & 3) | ((MINOR(device) & 0x80 ) >> 5 ))
+#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 ))
#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
#elif (MAJOR_NR == HD_MAJOR)
@@ -140,188 +142,188 @@ static void floppy_off(unsigned int nr);
#define DEVICE_INTR do_hd
#define TIMEOUT_VALUE (6*HZ)
#define DEVICE_REQUEST do_hd_request
-#define DEVICE_NR(device) (MINOR(device)>>6)
+#define DEVICE_NR(device) (minor(device)>>6)
#elif (SCSI_DISK_MAJOR(MAJOR_NR))
#define DEVICE_NAME "scsidisk"
#define TIMEOUT_VALUE (2*HZ)
-#define DEVICE_NR(device) (((MAJOR(device) & SD_MAJOR_MASK) << (8 - 4)) + (MINOR(device) >> 4))
+#define DEVICE_NR(device) (((major(device) & SD_MAJOR_MASK) << (8 - 4)) + (minor(device) >> 4))
/* Kludge to use the same number for both char and block major numbers */
#elif (MAJOR_NR == MD_MAJOR) && defined(MD_DRIVER)
#define DEVICE_NAME "Multiple devices driver"
#define DEVICE_REQUEST do_md_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == SCSI_TAPE_MAJOR)
#define DEVICE_NAME "scsitape"
#define DEVICE_INTR do_st
-#define DEVICE_NR(device) (MINOR(device) & 0x7f)
+#define DEVICE_NR(device) (minor(device) & 0x7f)
#elif (MAJOR_NR == OSST_MAJOR)
#define DEVICE_NAME "onstream"
#define DEVICE_INTR do_osst
-#define DEVICE_NR(device) (MINOR(device) & 0x7f)
+#define DEVICE_NR(device) (minor(device) & 0x7f)
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#elif (MAJOR_NR == SCSI_CDROM_MAJOR)
#define DEVICE_NAME "CD-ROM"
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == XT_DISK_MAJOR)
#define DEVICE_NAME "xt disk"
#define DEVICE_REQUEST do_xd_request
-#define DEVICE_NR(device) (MINOR(device) >> 6)
+#define DEVICE_NR(device) (minor(device) >> 6)
#elif (MAJOR_NR == PS2ESDI_MAJOR)
#define DEVICE_NAME "PS/2 ESDI"
#define DEVICE_REQUEST do_ps2esdi_request
-#define DEVICE_NR(device) (MINOR(device) >> 6)
+#define DEVICE_NR(device) (minor(device) >> 6)
#elif (MAJOR_NR == CDU31A_CDROM_MAJOR)
#define DEVICE_NAME "CDU31A"
#define DEVICE_REQUEST do_cdu31a_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == ACSI_MAJOR) && (defined(CONFIG_ATARI_ACSI) || defined(CONFIG_ATARI_ACSI_MODULE))
#define DEVICE_NAME "ACSI"
#define DEVICE_INTR do_acsi
#define DEVICE_REQUEST do_acsi_request
-#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_NR(device) (minor(device) >> 4)
#elif (MAJOR_NR == MITSUMI_CDROM_MAJOR)
#define DEVICE_NAME "Mitsumi CD-ROM"
/* #define DEVICE_INTR do_mcd */
#define DEVICE_REQUEST do_mcd_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == MITSUMI_X_CDROM_MAJOR)
#define DEVICE_NAME "Mitsumi CD-ROM"
/* #define DEVICE_INTR do_mcdx */
#define DEVICE_REQUEST do_mcdx_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == MATSUSHITA_CDROM_MAJOR)
#define DEVICE_NAME "Matsushita CD-ROM controller #1"
#define DEVICE_REQUEST do_sbpcd_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == MATSUSHITA_CDROM2_MAJOR)
#define DEVICE_NAME "Matsushita CD-ROM controller #2"
#define DEVICE_REQUEST do_sbpcd2_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == MATSUSHITA_CDROM3_MAJOR)
#define DEVICE_NAME "Matsushita CD-ROM controller #3"
#define DEVICE_REQUEST do_sbpcd3_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == MATSUSHITA_CDROM4_MAJOR)
#define DEVICE_NAME "Matsushita CD-ROM controller #4"
#define DEVICE_REQUEST do_sbpcd4_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == AZTECH_CDROM_MAJOR)
#define DEVICE_NAME "Aztech CD-ROM"
#define DEVICE_REQUEST do_aztcd_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == CDU535_CDROM_MAJOR)
#define DEVICE_NAME "SONY-CDU535"
#define DEVICE_INTR do_cdu535
#define DEVICE_REQUEST do_cdu535_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == GOLDSTAR_CDROM_MAJOR)
#define DEVICE_NAME "Goldstar R420"
#define DEVICE_REQUEST do_gscd_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == CM206_CDROM_MAJOR)
#define DEVICE_NAME "Philips/LMS CD-ROM cm206"
#define DEVICE_REQUEST do_cm206_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == OPTICS_CDROM_MAJOR)
#define DEVICE_NAME "DOLPHIN 8000AT CD-ROM"
#define DEVICE_REQUEST do_optcd_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == SANYO_CDROM_MAJOR)
#define DEVICE_NAME "Sanyo H94A CD-ROM"
#define DEVICE_REQUEST do_sjcd_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == APBLOCK_MAJOR)
#define DEVICE_NAME "apblock"
#define DEVICE_REQUEST ap_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == DDV_MAJOR)
#define DEVICE_NAME "ddv"
#define DEVICE_REQUEST ddv_request
-#define DEVICE_NR(device) (MINOR(device)>>PARTN_BITS)
+#define DEVICE_NR(device) (minor(device)>>PARTN_BITS)
#elif (MAJOR_NR == MFM_ACORN_MAJOR)
#define DEVICE_NAME "mfm disk"
#define DEVICE_INTR do_mfm
#define DEVICE_REQUEST do_mfm_request
-#define DEVICE_NR(device) (MINOR(device) >> 6)
+#define DEVICE_NR(device) (minor(device) >> 6)
#elif (MAJOR_NR == NBD_MAJOR)
#define DEVICE_NAME "nbd"
#define DEVICE_REQUEST do_nbd_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == MDISK_MAJOR)
#define DEVICE_NAME "mdisk"
#define DEVICE_REQUEST mdisk_request
-#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_NR(device) (minor(device))
#elif (MAJOR_NR == DASD_MAJOR)
#define DEVICE_NAME "dasd"
#define DEVICE_REQUEST do_dasd_request
-#define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS)
+#define DEVICE_NR(device) (minor(device) >> PARTN_BITS)
#elif (MAJOR_NR == I2O_MAJOR)
#define DEVICE_NAME "I2O block"
#define DEVICE_REQUEST i2ob_request
-#define DEVICE_NR(device) (MINOR(device)>>4)
+#define DEVICE_NR(device) (minor(device)>>4)
#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
#define DEVICE_NAME "ida"
#define TIMEOUT_VALUE (25*HZ)
#define DEVICE_REQUEST do_ida_request
-#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_NR(device) (minor(device) >> 4)
#endif /* MAJOR_NR == whatever */
@@ -375,7 +377,7 @@ static void (DEVICE_REQUEST)(request_queue_t *);
CLEAR_INTR; \
return; \
} \
- if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \
+ if (major(CURRENT->rq_dev) != MAJOR_NR) \
panic(DEVICE_NAME ": request list destroyed"); \
if (!CURRENT->bio) \
panic(DEVICE_NAME ": no bio"); \
@@ -395,7 +397,7 @@ static inline void end_request(int uptodate)
return;
#ifndef DEVICE_NO_RANDOM
- add_blkdev_randomness(MAJOR(req->rq_dev));
+ add_blkdev_randomness(major(req->rq_dev));
#endif
DEVICE_OFF(req->rq_dev);
blkdev_dequeue_request(req);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 438dec8fd..3f11ceb30 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -6,7 +6,7 @@
#include <linux/genhd.h>
#include <linux/tqueue.h>
#include <linux/list.h>
-#include <linux/mm.h>
+#include <linux/pagemap.h>
#include <asm/scatterlist.h>
@@ -25,7 +25,7 @@ struct request {
struct list_head queuelist; /* looking for ->queue? you must _not_
* access it directly, use
* blkdev_dequeue_request! */
- int elevator_sequence;
+ void *elevator_private;
unsigned char cmd[16];
@@ -196,8 +196,7 @@ struct request_queue
#define RQ_SCSI_DISCONNECTING 0xffe0
#define QUEUE_FLAG_PLUGGED 0 /* queue is plugged */
-#define QUEUE_FLAG_NOSPLIT 1 /* can process bio over several goes */
-#define QUEUE_FLAG_CLUSTER 2 /* cluster several segments into 1 */
+#define QUEUE_FLAG_CLUSTER 1 /* cluster several segments into 1 */
#define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
#define blk_mark_plugged(q) set_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
@@ -207,6 +206,14 @@ struct request_queue
#define rq_data_dir(rq) ((rq)->flags & 1)
/*
+ * mergeable request must not have _NOMERGE or _BARRIER bit set, nor may
+ * it already be started by driver.
+ */
+#define rq_mergeable(rq) \
+ (!((rq)->flags & (REQ_NOMERGE | REQ_STARTED | REQ_BARRIER)) \
+ && ((rq)->flags & REQ_CMD))
+
+/*
* noop, requests are automagically marked as active/inactive by I/O
* scheduler -- see elv_next_request
*/
@@ -221,8 +228,8 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn;
* BLK_BOUNCE_ANY : don't bounce anything
* BLK_BOUNCE_ISA : bounce pages above ISA DMA boundary
*/
-#define BLK_BOUNCE_HIGH ((blk_max_low_pfn + 1) << PAGE_SHIFT)
-#define BLK_BOUNCE_ANY ((blk_max_pfn + 1) << PAGE_SHIFT)
+#define BLK_BOUNCE_HIGH (blk_max_low_pfn << PAGE_SHIFT)
+#define BLK_BOUNCE_ANY (blk_max_pfn << PAGE_SHIFT)
#define BLK_BOUNCE_ISA (ISA_DMA_THRESHOLD)
extern int init_emergency_isa_pool(void);
@@ -278,6 +285,11 @@ extern int block_ioctl(kdev_t, unsigned int, unsigned long);
extern int ll_10byte_cmd_build(request_queue_t *, struct request *);
/*
+ * get ready for proper ref counting
+ */
+#define blk_put_queue(q) do { } while (0)
+
+/*
* Access functions for manipulating queue properties
*/
extern int blk_init_queue(request_queue_t *, request_fn_proc *, spinlock_t *);
@@ -359,14 +371,23 @@ extern inline unsigned int blksize_bits(unsigned int size)
extern inline unsigned int block_size(kdev_t dev)
{
int retval = BLOCK_SIZE;
- int major = MAJOR(dev);
+ int major = major(dev);
if (blksize_size[major]) {
- int minor = MINOR(dev);
+ int minor = minor(dev);
if (blksize_size[major][minor])
retval = blksize_size[major][minor];
}
return retval;
}
+typedef struct {struct page *v;} Sector;
+
+unsigned char *read_dev_sector(struct block_device *, unsigned long, Sector *);
+
+static inline void put_dev_sector(Sector p)
+{
+ page_cache_release(p.v);
+}
+
#endif
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index 3329b21a2..b3a349fc3 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -792,7 +792,7 @@ static inline void devfs_plain_cdrom(struct cdrom_device_info *cdi,
sprintf (vname, "cdroms/cdrom%d", cdi->number);
cdi->de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT,
- MAJOR (cdi->dev), MINOR (cdi->dev),
+ major(cdi->dev), minor(cdi->dev),
S_IFBLK | S_IRUGO | S_IWUGO,
ops, NULL);
}
diff --git a/include/linux/console.h b/include/linux/console.h
index 0fca958bd..646e0eaa9 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -97,7 +97,6 @@ struct console
void (*write)(struct console *, const char *, unsigned);
int (*read)(struct console *, const char *, unsigned);
kdev_t (*device)(struct console *);
- int (*wait_key)(struct console *);
void (*unblank)(void);
int (*setup)(struct console *, char *);
short flags;
diff --git a/include/linux/devfs_fs.h b/include/linux/devfs_fs.h
index 08f654efb..48da59012 100644
--- a/include/linux/devfs_fs.h
+++ b/include/linux/devfs_fs.h
@@ -26,7 +26,7 @@
binary interface will change */
struct devfsd_notify_struct
-{
+{ /* Use native C types to ensure same types in kernel and user space */
unsigned int type; /* DEVFSD_NOTIFY_* value */
unsigned int mode; /* Mode of the inode or device entry */
unsigned int major; /* Major number of device entry */
diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
index c52d7eabb..327b74046 100644
--- a/include/linux/devfs_fs_kernel.h
+++ b/include/linux/devfs_fs_kernel.h
@@ -60,6 +60,7 @@ struct unique_numspace
#define UNIQUE_NUMBERSPACE_INITIALISER {SPIN_LOCK_UNLOCKED, 0, 0, 0, NULL}
+extern void devfs_put (devfs_handle_t de);
extern devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
unsigned int flags,
unsigned int major, unsigned int minor,
@@ -70,6 +71,9 @@ extern int devfs_mk_symlink (devfs_handle_t dir, const char *name,
devfs_handle_t *handle, void *info);
extern devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name,
void *info);
+extern devfs_handle_t devfs_get_handle (devfs_handle_t dir, const char *name,
+ unsigned int major,unsigned int minor,
+ char type, int traverse_symlinks);
extern devfs_handle_t devfs_find_handle (devfs_handle_t dir, const char *name,
unsigned int major,unsigned int minor,
char type, int traverse_symlinks);
@@ -80,6 +84,7 @@ extern int devfs_get_maj_min (devfs_handle_t de,
extern devfs_handle_t devfs_get_handle_from_inode (struct inode *inode);
extern int devfs_generate_path (devfs_handle_t de, char *path, int buflen);
extern void *devfs_get_ops (devfs_handle_t de);
+extern void devfs_put_ops (devfs_handle_t de);
extern int devfs_set_file_size (devfs_handle_t de, unsigned long size);
extern void *devfs_get_info (devfs_handle_t de);
extern int devfs_set_info (devfs_handle_t de, void *info);
@@ -111,7 +116,6 @@ extern void devfs_dealloc_unique_number (struct unique_numspace *space,
int number);
extern void mount_devfs_fs (void);
-extern void devfs_make_root (const char *name);
#else /* CONFIG_DEVFS_FS */
@@ -122,6 +126,10 @@ struct unique_numspace
#define UNIQUE_NUMBERSPACE_INITIALISER {0}
+static inline void devfs_put (devfs_handle_t de)
+{
+ return;
+}
static inline devfs_handle_t devfs_register (devfs_handle_t dir,
const char *name,
unsigned int flags,
@@ -147,6 +155,15 @@ static inline devfs_handle_t devfs_mk_dir (devfs_handle_t dir,
{
return NULL;
}
+static inline devfs_handle_t devfs_get_handle (devfs_handle_t dir,
+ const char *name,
+ unsigned int major,
+ unsigned int minor,
+ char type,
+ int traverse_symlinks)
+{
+ return NULL;
+}
static inline devfs_handle_t devfs_find_handle (devfs_handle_t dir,
const char *name,
unsigned int major,
@@ -182,6 +199,10 @@ static inline void *devfs_get_ops (devfs_handle_t de)
{
return NULL;
}
+static inline void devfs_put_ops (devfs_handle_t de)
+{
+ return;
+}
static inline int devfs_set_file_size (devfs_handle_t de, unsigned long size)
{
return -ENOSYS;
@@ -290,10 +311,6 @@ static inline void mount_devfs_fs (void)
{
return;
}
-static inline void devfs_make_root (const char *name)
-{
- return;
-}
#endif /* CONFIG_DEVFS_FS */
#endif /* _LINUX_DEVFS_FS_KERNEL_H */
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 95e4145aa..44cbb0e8e 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -11,36 +11,53 @@ typedef void (elevator_merge_req_fn) (struct request *, struct request *);
typedef struct request *(elevator_next_req_fn) (request_queue_t *);
typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *);
+typedef int (elevator_queue_empty_fn) (request_queue_t *);
+typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
typedef void (elevator_exit_fn) (request_queue_t *, elevator_t *);
struct elevator_s
{
- int latency[2];
-
elevator_merge_fn *elevator_merge_fn;
elevator_merge_cleanup_fn *elevator_merge_cleanup_fn;
elevator_merge_req_fn *elevator_merge_req_fn;
elevator_next_req_fn *elevator_next_req_fn;
elevator_add_req_fn *elevator_add_req_fn;
+ elevator_remove_req_fn *elevator_remove_req_fn;
+
+ elevator_queue_empty_fn *elevator_queue_empty_fn;
elevator_init_fn *elevator_init_fn;
elevator_exit_fn *elevator_exit_fn;
+
+ void *elevator_data;
};
-int elevator_noop_merge(request_queue_t *, struct request **, struct bio *);
-void elevator_noop_merge_cleanup(request_queue_t *, struct request *, int);
-void elevator_noop_merge_req(struct request *, struct request *);
+/*
+ * block elevator interface
+ */
+extern void __elv_add_request(request_queue_t *, struct request *,
+ struct list_head *);
+extern struct request *__elv_next_request(request_queue_t *);
+extern void elv_merge_cleanup(request_queue_t *, struct request *, int);
+extern int elv_merge(request_queue_t *, struct request **, struct bio *);
+extern void elv_merge_requests(request_queue_t *, struct request *,
+ struct request *);
+extern void elv_remove_request(request_queue_t *, struct request *);
+
+/*
+ * noop I/O scheduler. always merges, always inserts new request at tail
+ */
+extern elevator_t elevator_noop;
-int elevator_linus_merge(request_queue_t *, struct request **, struct bio *);
-void elevator_linus_merge_cleanup(request_queue_t *, struct request *, int);
-void elevator_linus_merge_req(struct request *, struct request *);
-int elv_linus_init(request_queue_t *, elevator_t *);
-void elv_linus_exit(request_queue_t *, elevator_t *);
-struct request *elv_next_request_fn(request_queue_t *);
-void elv_add_request_fn(request_queue_t *, struct request *,struct list_head *);
+/*
+ * elevator linus. based on linus ideas of starvation control, using
+ * sequencing to manage inserts and merges.
+ */
+extern elevator_t elevator_linus;
+#define elv_linus_sequence(rq) ((long)(rq)->elevator_private)
/*
* use the /proc/iosched interface, all the below is history ->
@@ -64,48 +81,10 @@ extern void elevator_exit(request_queue_t *, elevator_t *);
#define ELEVATOR_FRONT_MERGE 1
#define ELEVATOR_BACK_MERGE 2
-#define elevator_request_latency(e, rw) ((e)->latency[(rw) & 1])
-
/*
* will change once we move to a more complex data structure than a simple
* list for pending requests
*/
#define elv_queue_empty(q) list_empty(&(q)->queue_head)
-/*
- * elevator private data
- */
-struct elv_linus_data {
- unsigned long flags;
-};
-
-#define ELV_DAT(e) ((struct elv_linus_data *)(e)->elevator_data)
-
-#define ELV_LINUS_BACK_MERGE 1
-#define ELV_LINUS_FRONT_MERGE 2
-
-#define ELEVATOR_NOOP \
-((elevator_t) { \
- { 0, 0}, \
- elevator_noop_merge, /* elevator_merge_fn */ \
- elevator_noop_merge_cleanup, /* elevator_merge_cleanup_fn */ \
- elevator_noop_merge_req, /* elevator_merge_req_fn */ \
- elv_next_request_fn, \
- elv_add_request_fn, \
- elv_linus_init, \
- elv_linus_exit, \
- })
-
-#define ELEVATOR_LINUS \
-((elevator_t) { \
- { 8192, 16384 }, \
- elevator_linus_merge, /* elevator_merge_fn */ \
- elevator_linus_merge_cleanup, /* elevator_merge_cleanup_fn */ \
- elevator_linus_merge_req, /* elevator_merge_req_fn */ \
- elv_next_request_fn, \
- elv_add_request_fn, \
- elv_linus_init, \
- elv_linus_exit, \
- })
-
#endif
diff --git a/include/linux/ext2_fs_sb.h b/include/linux/ext2_fs_sb.h
index 2e72dfbef..47f53158e 100644
--- a/include/linux/ext2_fs_sb.h
+++ b/include/linux/ext2_fs_sb.h
@@ -56,6 +56,7 @@ struct ext2_sb_info {
int s_desc_per_block_bits;
int s_inode_size;
int s_first_ino;
+ u32 s_next_generation;
};
#endif /* _LINUX_EXT2_FS_SB */
diff --git a/include/linux/file.h b/include/linux/file.h
index 02edb29c3..0994be612 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -5,6 +5,8 @@
#ifndef __LINUX_FILE_H
#define __LINUX_FILE_H
+#include <linux/sched.h>
+
extern void FASTCALL(fput(struct file *));
extern struct file * FASTCALL(fget(unsigned int fd));
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b1e59c161..a83af6000 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -311,7 +311,6 @@ extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long
#include <linux/udf_fs_i.h>
#include <linux/ncp_fs_i.h>
#include <linux/proc_fs_i.h>
-#include <linux/usbdev_fs_i.h>
#include <linux/jffs2_fs_i.h>
#include <linux/cramfs_fs_sb.h>
@@ -502,7 +501,6 @@ struct inode {
struct ncp_inode_info ncpfs_i;
struct proc_inode_info proc_i;
struct socket socket_i;
- struct usbdev_inode_info usbdev_i;
struct jffs2_inode_info jffs2_i;
void *generic_ip;
} u;
@@ -686,7 +684,6 @@ struct quota_mount_options
#include <linux/bfs_fs_sb.h>
#include <linux/udf_fs_sb.h>
#include <linux/ncp_fs_sb.h>
-#include <linux/usbdev_fs_sb.h>
#include <linux/cramfs_fs_sb.h>
#include <linux/jffs2_fs_sb.h>
@@ -721,6 +718,8 @@ struct super_block {
struct list_head s_instances;
struct quota_mount_options s_dquot; /* Diskquota specific options */
+ char s_id[32]; /* Informational name */
+
union {
struct minix_sb_info minix_sb;
struct ext2_sb_info ext2_sb;
@@ -744,7 +743,6 @@ struct super_block {
struct bfs_sb_info bfs_sb;
struct udf_sb_info udf_sb;
struct ncp_sb_info ncpfs_sb;
- struct usbdev_sb_info usbdevfs_sb;
struct jffs2_sb_info jffs2_sb;
struct cramfs_sb_info cramfs_sb;
void *generic_sbp;
@@ -982,6 +980,7 @@ extern int unregister_filesystem(struct file_system_type *);
extern struct vfsmount *kern_mount(struct file_system_type *);
extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
+extern void umount_tree(struct vfsmount *);
#define kern_umount mntput
@@ -1102,7 +1101,7 @@ extern int fs_may_remount_ro(struct super_block *);
extern int try_to_free_buffers(struct page *, unsigned int);
extern void refile_buffer(struct buffer_head * buf);
-extern void create_empty_buffers(struct page *, kdev_t, unsigned long);
+extern void create_empty_buffers(struct page *, unsigned long);
extern void end_buffer_io_sync(struct buffer_head *bh, int uptodate);
/* reiserfs_writepage needs this */
@@ -1378,6 +1377,8 @@ static inline void bforget(struct buffer_head *buf)
__bforget(buf);
}
extern int set_blocksize(kdev_t, int);
+extern int sb_set_blocksize(struct super_block *, int);
+extern int sb_min_blocksize(struct super_block *, int);
extern struct buffer_head * bread(kdev_t, int, int);
static inline struct buffer_head * sb_bread(struct super_block *sb, int block)
{
@@ -1391,6 +1392,12 @@ static inline struct buffer_head * sb_get_hash_table(struct super_block *sb, int
{
return get_hash_table(sb->s_dev, block, sb->s_blocksize);
}
+static inline void map_bh(struct buffer_head *bh, struct super_block *sb, int block)
+{
+ bh->b_state |= 1 << BH_Mapped;
+ bh->b_dev = sb->s_dev;
+ bh->b_blocknr = block;
+}
extern void wakeup_bdflush(void);
extern void put_unused_buffer_head(struct buffer_head * bh);
extern struct buffer_head * get_unused_buffer_head(int async);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 18f8d66eb..18c981daf 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -71,13 +71,11 @@ struct gendisk {
const char *major_name; /* name of major driver */
int minor_shift; /* number of times minor is shifted to
get real minor */
- int max_p; /* maximum partitions per device */
struct hd_struct *part; /* [indexed by minor] */
int *sizes; /* [idem], device size in blocks */
int nr_real; /* number of real devices */
- void *real_devices; /* internal use */
struct gendisk *next;
struct block_device_operations *fops;
@@ -247,7 +245,7 @@ extern void devfs_register_partitions (struct gendisk *dev, int minor,
static inline unsigned int disk_index (kdev_t dev)
{
struct gendisk *g = get_gendisk(dev);
- return g ? (MINOR(dev) >> g->minor_shift) : 0;
+ return g ? (minor(dev) >> g->minor_shift) : 0;
}
#endif
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
new file mode 100644
index 000000000..63fac87d5
--- /dev/null
+++ b/include/linux/gfp.h
@@ -0,0 +1,81 @@
+#ifndef __LINUX_GFP_H
+#define __LINUX_GFP_H
+
+#include <linux/mmzone.h>
+#include <linux/stddef.h>
+#include <linux/linkage.h>
+/*
+ * GFP bitmasks..
+ */
+/* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low four bits) */
+#define __GFP_DMA 0x01
+#define __GFP_HIGHMEM 0x02
+
+/* Action modifiers - doesn't change the zoning */
+#define __GFP_WAIT 0x10 /* Can wait and reschedule? */
+#define __GFP_HIGH 0x20 /* Should access emergency pools? */
+#define __GFP_IO 0x40 /* Can start low memory physical IO? */
+#define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */
+#define __GFP_FS 0x100 /* Can call down to low-level FS? */
+
+#define GFP_NOHIGHIO (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
+#define GFP_NOIO (__GFP_HIGH | __GFP_WAIT)
+#define GFP_NOFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO)
+#define GFP_ATOMIC (__GFP_HIGH)
+#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
+#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS | __GFP_HIGHMEM)
+#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
+#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
+#define GFP_KSWAPD ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
+
+/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
+ platforms, used as appropriate on others */
+
+#define GFP_DMA __GFP_DMA
+
+/*
+ * There is only one page-allocator function, and two main namespaces to
+ * it. The alloc_page*() variants return 'struct page *' and as such
+ * can allocate highmem pages, the *get*page*() variants return
+ * virtual kernel addresses to the allocated page(s).
+ */
+extern struct page * FASTCALL(_alloc_pages(unsigned int gfp_mask, unsigned int order));
+extern struct page * FASTCALL(__alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist));
+extern struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order);
+
+static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)
+{
+ /*
+ * Gets optimized away by the compiler.
+ */
+ if (order >= MAX_ORDER)
+ return NULL;
+ return _alloc_pages(gfp_mask, order);
+}
+
+#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
+
+extern unsigned long FASTCALL(__get_free_pages(unsigned int gfp_mask, unsigned int order));
+extern unsigned long FASTCALL(get_zeroed_page(unsigned int gfp_mask));
+
+#define __get_free_page(gfp_mask) \
+ __get_free_pages((gfp_mask),0)
+
+#define __get_dma_pages(gfp_mask, order) \
+ __get_free_pages((gfp_mask) | GFP_DMA,(order))
+
+/*
+ * The old interface name will be removed in 2.5:
+ */
+#define get_free_page get_zeroed_page
+
+/*
+ * There is only one 'core' page-freeing function.
+ */
+extern void FASTCALL(__free_pages(struct page *page, unsigned int order));
+extern void FASTCALL(free_pages(unsigned long addr, unsigned int order));
+
+#define __free_page(page) __free_pages((page), 0)
+#define free_page(addr) free_pages((addr),0)
+
+#endif /* __LINUX_GFP_H */
diff --git a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h
index fa98ce32a..ab6c834d0 100644
--- a/include/linux/hfs_sysdep.h
+++ b/include/linux/hfs_sysdep.h
@@ -122,7 +122,7 @@ static inline void hfs_mdb_dirty(hfs_sysmdb sys_mdb) {
}
static inline const char *hfs_mdb_name(hfs_sysmdb sys_mdb) {
- return kdevname(sys_mdb->s_dev);
+ return sys_mdb->s_id;
}
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 5bcdab80f..a8e2d11c4 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -18,13 +18,13 @@
/*
* This is the multiple IDE interface driver, as evolved from hd.c.
- * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
+ * It supports up to four IDE interfaces, on one or more IRQs (usually 14, 15).
* There can be up to two drives per interface, as per the ATA-2 spec.
*
- * Primary i/f: ide0: major=3; (hda) minor=0; (hdb) minor=64
- * Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
- * Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64
- * Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64
+ * Primary i/f: ide0: major=3; (hda) minor=0; (hdb) minor=64
+ * Secondary i/f: ide1: major=22; (hdc) minor=0; (hdd) minor=64
+ * Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64
+ * Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64
*/
/******************************************************************************
@@ -917,6 +917,12 @@ int ide_system_bus_speed (void);
int ide_multwrite (ide_drive_t *drive, unsigned int mcount);
/*
+ * idedisk_input_data() is a wrapper around ide_input_data() which copes
+ * with byte-swapping the input data if required.
+ */
+inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+
+/*
* ide_stall_queue() can be used by a drive to give excess bandwidth back
* to the hwgroup by sleeping for timeout jiffies.
*/
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index d2afbde82..f4b23c425 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -3,12 +3,14 @@
#define _LINUX_INTERRUPT_H
#include <linux/config.h>
+#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/cache.h>
#include <asm/bitops.h>
#include <asm/atomic.h>
+#include <asm/system.h>
#include <asm/ptrace.h>
struct irqaction {
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index 0f1dda941..6f6ae5160 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -150,7 +150,6 @@ typedef struct {
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index a2ae37d44..abc0c3e7b 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -141,7 +141,6 @@ struct console;
int getkeycode(unsigned int scancode);
int setkeycode(unsigned int scancode, unsigned int keycode);
void compute_shiftstate(void);
-int keyboard_wait_for_keypress(struct console *);
/* defkeymap.c */
diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h
index 7ef189ef0..f9e74fd52 100644
--- a/include/linux/kdev_t.h
+++ b/include/linux/kdev_t.h
@@ -57,48 +57,84 @@ when some module is inserted).
aeb - 950811
*/
-/* Since MINOR(dev) is used as index in static arrays,
- the kernel is not quite ready yet for larger minors.
- However, everything runs fine with an arbitrary kdev_t type. */
+/*
+ * NOTE NOTE NOTE!
+ *
+ * The kernel-internal "kdev_t" will eventually have
+ * 20 bits for minor numbers, and 12 bits for majors.
+ *
+ * HOWEVER, the external representation is still 8+8
+ * bits, and there is no way to generate the extended
+ * "kdev_t" format yet. Which is just as well, since
+ * we still use "minor" as an index into various
+ * static arrays, and they are sized for a 8-bit index.
+ */
+typedef struct {
+ unsigned short value;
+} kdev_t;
+
+#define KDEV_MINOR_BITS 8
+#define KDEV_MAJOR_BITS 8
+
+#define __mkdev(major,minor) (((major) << KDEV_MINOR_BITS) + (minor))
+
+#define mk_kdev(major, minor) ((kdev_t) { __mkdev(major,minor) } )
+
+/*
+ * The "values" are just _cookies_, usable for
+ * internal equality comparisons and for things
+ * like NFS filehandle conversion.
+ */
+static inline unsigned int kdev_val(kdev_t dev)
+{
+ return dev.value;
+}
+
+static inline kdev_t val_to_kdev(unsigned int val)
+{
+ kdev_t dev;
+ dev.value = val;
+ return dev;
+}
+
+#define HASHDEV(dev) (kdev_val(dev))
+#define NODEV (mk_kdev(0,0))
+#define B_FREE (mk_kdev(0xff,0xff))
+
+extern const char * kdevname(kdev_t); /* note: returns pointer to static data! */
+
+static inline int kdev_same(kdev_t dev1, kdev_t dev2)
+{
+ return dev1.value == dev2.value;
+}
+
+#define kdev_none(d1) (!kdev_val(d1))
+
+/* Mask off the high bits for now.. */
+#define minor(dev) ((dev).value & 0xff)
+#define major(dev) (((dev).value >> KDEV_MINOR_BITS) & 0xff)
+
+/* These are for user-level "dev_t" */
#define MINORBITS 8
#define MINORMASK ((1U << MINORBITS) - 1)
-typedef unsigned short kdev_t;
-
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
-#define HASHDEV(dev) ((unsigned int) (dev))
-#define NODEV 0
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
-#define B_FREE 0xffff /* yuk */
-
-extern const char * kdevname(kdev_t); /* note: returns pointer to static data! */
/*
-As long as device numbers in the outside world have 16 bits only,
-we use these conversions.
-*/
+ * Conversion functions
+ */
-static inline unsigned int kdev_t_to_nr(kdev_t dev) {
- return (MAJOR(dev)<<8) | MINOR(dev);
+static inline int kdev_t_to_nr(kdev_t dev)
+{
+ return MKDEV(major(dev), minor(dev));
}
static inline kdev_t to_kdev_t(int dev)
{
- int major, minor;
-#if 0
- major = (dev >> 16);
- if (!major) {
- major = (dev >> 8);
- minor = (dev & 0xff);
- } else
- minor = (dev & 0xffff);
-#else
- major = (dev >> 8);
- minor = (dev & 0xff);
-#endif
- return MKDEV(major, minor);
+ return mk_kdev(MAJOR(dev),MINOR(dev));
}
#else /* __KERNEL__ || _LVM_H_INCLUDE */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 523e38822..8749f6f0c 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -37,16 +37,6 @@
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */
-# define NORET_TYPE /**/
-# define ATTRIB_NORET __attribute__((noreturn))
-# define NORET_AND noreturn,
-
-#ifdef __i386__
-#define FASTCALL(x) x __attribute__((regparm(3)))
-#else
-#define FASTCALL(x) x
-#endif
-
struct completion;
extern struct notifier_block *panic_notifier_list;
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
index 37cf120ae..caa66cd98 100644
--- a/include/linux/keyboard.h
+++ b/include/linux/keyboard.h
@@ -26,7 +26,6 @@ extern const int NR_TYPES;
extern const int max_vals[];
extern unsigned short *key_maps[MAX_NR_KEYMAPS];
extern unsigned short plain_map[NR_KEYS];
-extern wait_queue_head_t keypress_wait;
extern unsigned char keyboard_type;
#endif
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index 23b9ae463..e9bf89431 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -60,4 +60,14 @@
#endif
+# define NORET_TYPE /**/
+# define ATTRIB_NORET __attribute__((noreturn))
+# define NORET_AND noreturn,
+
+#ifdef __i386__
+#define FASTCALL(x) x __attribute__((regparm(3)))
+#else
+#define FASTCALL(x) x
+#endif
+
#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fd151a339..96473ba9b 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -7,6 +7,7 @@
#ifdef __KERNEL__
#include <linux/config.h>
+#include <linux/gfp.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/mmzone.h>
@@ -348,51 +349,6 @@ extern void FASTCALL(set_page_dirty(struct page *));
/* The array of struct pages */
extern mem_map_t * mem_map;
-/*
- * There is only one page-allocator function, and two main namespaces to
- * it. The alloc_page*() variants return 'struct page *' and as such
- * can allocate highmem pages, the *get*page*() variants return
- * virtual kernel addresses to the allocated page(s).
- */
-extern struct page * FASTCALL(_alloc_pages(unsigned int gfp_mask, unsigned int order));
-extern struct page * FASTCALL(__alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist));
-extern struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order);
-
-static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)
-{
- /*
- * Gets optimized away by the compiler.
- */
- if (order >= MAX_ORDER)
- return NULL;
- return _alloc_pages(gfp_mask, order);
-}
-
-#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
-
-extern unsigned long FASTCALL(__get_free_pages(unsigned int gfp_mask, unsigned int order));
-extern unsigned long FASTCALL(get_zeroed_page(unsigned int gfp_mask));
-
-#define __get_free_page(gfp_mask) \
- __get_free_pages((gfp_mask),0)
-
-#define __get_dma_pages(gfp_mask, order) \
- __get_free_pages((gfp_mask) | GFP_DMA,(order))
-
-/*
- * The old interface name will be removed in 2.5:
- */
-#define get_free_page get_zeroed_page
-
-/*
- * There is only one 'core' page-freeing function.
- */
-extern void FASTCALL(__free_pages(struct page *page, unsigned int order));
-extern void FASTCALL(free_pages(unsigned long addr, unsigned int order));
-
-#define __free_page(page) __free_pages((page), 0)
-#define free_page(addr) free_pages((addr),0)
-
extern void show_free_areas(void);
extern void show_free_areas_node(pg_data_t *pgdat);
@@ -425,6 +381,9 @@ extern int ptrace_check_attach(struct task_struct *task, int kill);
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
+int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
+ int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
+
/*
* On a two-level page table, this ends up being trivial. Thus the
* inlining and the symmetry break with pte_alloc() that does all
@@ -519,35 +478,6 @@ extern void truncate_inode_pages(struct address_space *, loff_t);
extern int filemap_sync(struct vm_area_struct *, unsigned long, size_t, unsigned int);
extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int);
-/*
- * GFP bitmasks..
- */
-/* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low four bits) */
-#define __GFP_DMA 0x01
-#define __GFP_HIGHMEM 0x02
-
-/* Action modifiers - doesn't change the zoning */
-#define __GFP_WAIT 0x10 /* Can wait and reschedule? */
-#define __GFP_HIGH 0x20 /* Should access emergency pools? */
-#define __GFP_IO 0x40 /* Can start low memory physical IO? */
-#define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */
-#define __GFP_FS 0x100 /* Can call down to low-level FS? */
-
-#define GFP_NOHIGHIO (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
-#define GFP_NOIO (__GFP_HIGH | __GFP_WAIT)
-#define GFP_NOFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO)
-#define GFP_ATOMIC (__GFP_HIGH)
-#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
-#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS | __GFP_HIGHMEM)
-#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
-#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
-#define GFP_KSWAPD ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
-
-/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
- platforms, used as appropriate on others */
-
-#define GFP_DMA __GFP_DMA
-
/* vma is the first one with address < vma->vm_end,
* and even address < vma->vm_start. Have to extend vma. */
static inline int expand_stack(struct vm_area_struct * vma, unsigned long address)
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 132b545d2..63efd4cae 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -200,7 +200,7 @@ struct vfat_slot_info {
#include <linux/nls.h>
struct fat_cache {
- kdev_t device; /* device number. 0 means unused. */
+ struct super_block *sb; /* fs in question. NULL means unused */
int start_cluster; /* first cluster of the chain. */
int file_cluster; /* cluster number in the file. */
int disk_cluster; /* cluster number on disk. */
@@ -252,7 +252,7 @@ extern void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu,
int *d_clu);
extern void fat_cache_add(struct inode *inode, int f_clu, int d_clu);
extern void fat_cache_inval_inode(struct inode *inode);
-extern void fat_cache_inval_dev(kdev_t device);
+extern void fat_cache_inval_dev(struct super_block *sb);
extern int fat_get_cluster(struct inode *inode, int cluster);
extern int fat_free(struct inode *inode, int skip);
diff --git a/include/linux/namespace.h b/include/linux/namespace.h
new file mode 100644
index 000000000..8695e5f96
--- /dev/null
+++ b/include/linux/namespace.h
@@ -0,0 +1,42 @@
+#ifndef _NAMESPACE_H_
+#define _NAMESPACE_H_
+#ifdef __KERNEL__
+
+struct namespace {
+ atomic_t count;
+ struct vfsmount * root;
+ struct list_head list;
+ struct rw_semaphore sem;
+};
+
+static inline void put_namespace(struct namespace *namespace)
+{
+ if (atomic_dec_and_test(&namespace->count)) {
+ down_write(&namespace->sem);
+ spin_lock(&dcache_lock);
+ umount_tree(namespace->root);
+ spin_unlock(&dcache_lock);
+ up_write(&namespace->sem);
+ kfree(namespace);
+ }
+}
+
+static inline void exit_namespace(struct task_struct *p)
+{
+ struct namespace *namespace = p->namespace;
+ if (namespace) {
+ task_lock(p);
+ p->namespace = NULL;
+ task_unlock(p);
+ put_namespace(namespace);
+ }
+}
+extern int copy_namespace(int, struct task_struct *);
+
+static inline void get_namespace(struct namespace *namespace)
+{
+ atomic_inc(&namespace->count);
+}
+
+#endif
+#endif
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index 11ffdacda..84c72958f 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -119,15 +119,37 @@ struct knfsd_fh {
/*
* Conversion macros for the filehandle fields.
+ *
+ * Keep the device numbers in "backwards compatible
+ * format", ie the low 16 bits contain the low 8 bits
+ * of the 20-bit minor and the 12-bit major number.
+ *
+ * The high 16 bits contain the rest (4 bits major
+ * and 12 bits minor),
*/
static inline __u32 kdev_t_to_u32(kdev_t dev)
{
- return (__u32) dev;
+ unsigned int minor = minor(dev);
+ unsigned int major = major(dev);
+ __u32 udev;
+
+ /* Create the low 16 bits.. */
+ udev = ((major & 0xff) << 8) + (minor & 0xff);
+
+ /* ..and then the rest. */
+ major >>= 8; minor >>= 8;
+ udev |= (major << 28) | (minor << 16);
+
+ return udev;
}
static inline kdev_t u32_to_kdev_t(__u32 udev)
{
- return (kdev_t) udev;
+ unsigned int minor, major;
+
+ minor = (udev & 0xff) | ((udev >> 8) & 0xfff00);
+ major = ((udev >> 8) & 0xff) | ((udev >> 20) & 0xf00);
+ return mk_kdev(major, minor);
}
static inline __u32 ino_t_to_u32(ino_t ino)
diff --git a/include/linux/parport.h b/include/linux/parport.h
index bee974807..ce82bcdb5 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -8,6 +8,7 @@
#ifndef _PARPORT_H_
#define _PARPORT_H_
+#include <linux/sched.h>
/* Start off with user-visible constants */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index d73d486ab..cbe61d619 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -946,11 +946,12 @@
#define PCI_DEVICE_ID_VIA_8233_7 0x3065
#define PCI_DEVICE_ID_VIA_82C686_6 0x3068
#define PCI_DEVICE_ID_VIA_8233_0 0x3074
-#define PCI_DEVICE_ID_VIA_8622 0x3102
-#define PCI_DEVICE_ID_VIA_8233C_0 0x3109
-#define PCI_DEVICE_ID_VIA_8361 0x3112
#define PCI_DEVICE_ID_VIA_8633_0 0x3091
#define PCI_DEVICE_ID_VIA_8367_0 0x3099
+#define PCI_DEVICE_ID_VIA_8622 0x3102
+#define PCI_DEVICE_ID_VIA_8233C_0 0x3109
+#define PCI_DEVICE_ID_VIA_8361 0x3112
+#define PCI_DEVICE_ID_VIA_8233A 0x3147
#define PCI_DEVICE_ID_VIA_86C100A 0x6100
#define PCI_DEVICE_ID_VIA_8231 0x8231
#define PCI_DEVICE_ID_VIA_8231_4 0x8235
@@ -960,7 +961,7 @@
#define PCI_DEVICE_ID_VIA_82C597_1 0x8597
#define PCI_DEVICE_ID_VIA_82C598_1 0x8598
#define PCI_DEVICE_ID_VIA_8601_1 0x8601
-#define PCI_DEVICE_ID_VIA_8505_1 0X8605
+#define PCI_DEVICE_ID_VIA_8505_1 0x8605
#define PCI_DEVICE_ID_VIA_8633_1 0xB091
#define PCI_DEVICE_ID_VIA_8367_1 0xB099
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index d6f2700e3..4688c8c90 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -3,6 +3,8 @@
#include <linux/config.h>
#include <linux/slab.h>
+#include <linux/fs.h>
+#include <asm/atomic.h>
/*
* The proc filesystem constants/structures
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 3ab244576..d155eb2bd 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -167,7 +167,6 @@ struct dquot {
/* fields after this point are cleared when invalidating */
struct super_block *dq_sb; /* superblock this applies to */
unsigned int dq_id; /* ID this applies to (uid, gid) */
- kdev_t dq_dev; /* Device this applies to */
short dq_type; /* Type of quota */
short dq_flags; /* See DQ_* */
unsigned long dq_referenced; /* Number of times this dquot was
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 485639f8d..c22d9f32e 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -23,7 +23,7 @@
extern void dquot_initialize(struct inode *inode, short type);
extern void dquot_drop(struct inode *inode);
extern int quota_off(struct super_block *sb, short type);
-extern int sync_dquots(kdev_t dev, short type);
+extern int sync_dquots(struct super_block *sb, short type);
extern int dquot_alloc_block(struct inode *inode, unsigned long number, char prealloc);
extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);
@@ -159,7 +159,7 @@ static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
return 0;
}
-#define DQUOT_SYNC(dev) sync_dquots(dev, -1)
+#define DQUOT_SYNC(sb) sync_dquots(sb, -1)
#define DQUOT_OFF(sb) quota_off(sb, -1)
#else
@@ -171,7 +171,7 @@ static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
#define DQUOT_DROP(inode) do { } while(0)
#define DQUOT_ALLOC_INODE(inode) (0)
#define DQUOT_FREE_INODE(inode) do { } while(0)
-#define DQUOT_SYNC(dev) do { } while(0)
+#define DQUOT_SYNC(sb) do { } while(0)
#define DQUOT_OFF(sb) do { } while(0)
#define DQUOT_TRANSFER(inode, iattr) (0)
extern __inline__ int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, int nr)
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index d7c321c9c..81009d605 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -77,9 +77,9 @@ extern dev_mapping_t mddev_map [MAX_MD_DEVS];
static inline mddev_t * kdev_to_mddev (kdev_t dev)
{
- if (MAJOR(dev) != MD_MAJOR)
+ if (major(dev) != MD_MAJOR)
BUG();
- return mddev_map[MINOR(dev)].mddev;
+ return mddev_map[minor(dev)].mddev;
}
/*
@@ -256,7 +256,7 @@ static inline int mdidx (mddev_t * mddev)
static inline kdev_t mddev_to_kdev(mddev_t * mddev)
{
- return MKDEV(MD_MAJOR, mdidx(mddev));
+ return mk_kdev(MD_MAJOR, mdidx(mddev));
}
extern mdk_rdev_t * find_rdev(mddev_t * mddev, kdev_t dev);
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index cc6b767a6..b50d60989 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -15,10 +15,10 @@
#include <linux/types.h>
#ifdef __KERNEL__
#include <linux/slab.h>
+#include <linux/interrupt.h>
#include <linux/tqueue.h>
#include <asm/unaligned.h>
#include <linux/bitops.h>
-#include <asm/hardirq.h>
#include <linux/proc_fs.h>
#endif
@@ -1651,7 +1651,7 @@ extern wait_queue_head_t reiserfs_commit_thread_wait ;
#define _jhashfn(dev,block) \
((((dev)<<(JBH_HASH_SHIFT - 6)) ^ ((dev)<<(JBH_HASH_SHIFT - 9))) ^ \
(((block)<<(JBH_HASH_SHIFT - 6)) ^ ((block) >> 13) ^ ((block) << (JBH_HASH_SHIFT - 12))))
-#define journal_hash(t,dev,block) ((t)[_jhashfn((dev),(block)) & JBH_HASH_MASK])
+#define journal_hash(t,dev,block) ((t)[_jhashfn((kdev_t_to_nr(dev)),(block)) & JBH_HASH_MASK])
/* finds n'th buffer with 0 being the start of this commit. Needs to go away, j_ap_blocks has changed
** since I created this. One chunk of code in journal.c needs changing before deleting it
@@ -1827,12 +1827,12 @@ void reiserfs_do_truncate (struct reiserfs_transaction_handle *th,
//void decrement_i_read_sync_counter (struct inode * p_s_inode);
-#define block_size(inode) ((inode)->i_sb->s_blocksize)
+#define i_block_size(inode) ((inode)->i_sb->s_blocksize)
#define file_size(inode) ((inode)->i_size)
-#define tail_size(inode) (file_size (inode) & (block_size (inode) - 1))
+#define tail_size(inode) (file_size (inode) & (i_block_size (inode) - 1))
#define tail_has_to_be_packed(inode) (!dont_have_tails ((inode)->i_sb) &&\
-!STORE_TAIL_IN_UNFM(file_size (inode), tail_size(inode), block_size (inode)))
+!STORE_TAIL_IN_UNFM(file_size (inode), tail_size(inode), i_block_size (inode)))
/*
int get_buffer_by_range (struct super_block * p_s_sb, struct key * p_s_range_begin, struct key * p_s_range_end,
@@ -1989,10 +1989,9 @@ int get_new_buffer (struct reiserfs_transaction_handle *th, struct buffer_head *
/* buffer2.c */
-struct buffer_head * reiserfs_getblk (kdev_t n_dev, int n_block, int n_size);
+struct buffer_head * reiserfs_getblk (struct super_block *super, int n_block);
void wait_buffer_until_released (const struct buffer_head * bh);
-struct buffer_head * reiserfs_bread (struct super_block *super, int n_block,
- int n_size);
+struct buffer_head * reiserfs_bread (struct super_block *super, int n_block);
/* fix_nodes.c */
void * reiserfs_kmalloc (size_t size, int flags, struct super_block * s);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 3a16560f1..905f26736 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -41,6 +41,7 @@ struct exec_domain;
#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
#define CLONE_THREAD 0x00010000 /* Same thread group? */
+#define CLONE_NEWNS 0x00020000 /* New namespace group? */
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
@@ -149,6 +150,7 @@ extern void trap_init(void);
extern void update_process_times(int user);
extern void update_one_process(struct task_struct *p, unsigned long user,
unsigned long system, int cpu);
+extern void expire_task(struct task_struct *p);
#define MAX_SCHEDULE_TIMEOUT LONG_MAX
extern signed long FASTCALL(schedule_timeout(signed long timeout));
@@ -165,6 +167,7 @@ extern int current_is_keventd(void);
*/
#define NR_OPEN_DEFAULT BITS_PER_LONG
+struct namespace;
/*
* Open file table structure
*/
@@ -299,7 +302,7 @@ struct task_struct {
* all fields in a single cacheline that are needed for
* the goodness() loop in schedule().
*/
- long counter;
+ unsigned long dyn_prio;
long nice;
unsigned long policy;
struct mm_struct *mm;
@@ -318,7 +321,9 @@ struct task_struct {
* that's just fine.)
*/
struct list_head run_list;
- unsigned long sleep_time;
+ long time_slice;
+ /* recalculation loop checkpoint */
+ unsigned long rcl_last;
struct task_struct *next_task, *prev_task;
struct mm_struct *active_mm;
@@ -388,6 +393,8 @@ struct task_struct {
struct fs_struct *fs;
/* open file information */
struct files_struct *files;
+/* namespace */
+ struct namespace *namespace;
/* signal handlers */
spinlock_t sigmask_lock; /* Protects signal and blocked */
struct signal_struct *sig;
@@ -425,6 +432,7 @@ struct task_struct {
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_MEMDIE 0x00001000 /* Killed for out-of-memory */
#define PF_FREE_PAGES 0x00002000 /* per process page freeing */
+#define PF_NOIO 0x00004000 /* avoid generating further I/O */
#define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */
@@ -444,8 +452,9 @@ struct task_struct {
*/
#define _STK_LIM (8*1024*1024)
-#define DEF_COUNTER (10*HZ/100) /* 100 ms time slice */
-#define MAX_COUNTER (20*HZ/100)
+#define MAX_DYNPRIO 40
+#define DEF_TSLICE (6 * HZ / 100)
+#define MAX_TSLICE (20 * HZ / 100)
#define DEF_NICE (0)
@@ -466,14 +475,16 @@ extern struct exec_domain default_exec_domain;
addr_limit: KERNEL_DS, \
exec_domain: &default_exec_domain, \
lock_depth: -1, \
- counter: DEF_COUNTER, \
+ dyn_prio: 0, \
nice: DEF_NICE, \
policy: SCHED_OTHER, \
mm: NULL, \
active_mm: &init_mm, \
cpus_runnable: -1, \
cpus_allowed: -1, \
- run_list: LIST_HEAD_INIT(tsk.run_list), \
+ run_list: { NULL, NULL }, \
+ rcl_last: 0, \
+ time_slice: DEF_TSLICE, \
next_task: &tsk, \
prev_task: &tsk, \
p_opptr: &tsk, \
@@ -874,7 +885,6 @@ do { \
static inline void del_from_runqueue(struct task_struct * p)
{
nr_running--;
- p->sleep_time = jiffies;
list_del(&p->run_list);
p->run_list.next = NULL;
}
diff --git a/include/linux/shm.h b/include/linux/shm.h
index 4ccdd749d..be3351619 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -80,7 +80,6 @@ asmlinkage long sys_shmget (key_t key, size_t size, int flag);
asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, unsigned long *addr);
asmlinkage long sys_shmdt (char *shmaddr);
asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
-extern void shm_unuse(swp_entry_t entry, struct page *page);
#endif /* __KERNEL__ */
diff --git a/include/linux/slab.h b/include/linux/slab.h
index ed4ff4839..ceff3509f 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -11,8 +11,8 @@
typedef struct kmem_cache_s kmem_cache_t;
-#include <linux/mm.h>
-#include <linux/cache.h>
+#include <linux/gfp.h>
+#include <linux/types.h>
/* flags for kmem_cache_alloc() */
#define SLAB_NOFS GFP_NOFS
@@ -64,6 +64,7 @@ extern void kfree(const void *);
extern int FASTCALL(kmem_cache_reap(int));
extern int slabinfo_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data);
+struct file;
extern int slabinfo_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 231cd23ca..be4c52c62 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -15,6 +15,7 @@
#include <linux/sunrpc/auth.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/xdr.h>
+#include <asm/signal.h>
/*
* This defines an RPC port mapping
diff --git a/include/linux/threads.h b/include/linux/threads.h
index b6ed9116c..880b990f8 100644
--- a/include/linux/threads.h
+++ b/include/linux/threads.h
@@ -5,7 +5,7 @@
/*
* The default limit for the nr of threads is now in
- * /proc/sys/kernel/max-threads.
+ * /proc/sys/kernel/threads-max.
*/
#ifdef CONFIG_SMP
diff --git a/include/linux/tpqic02.h b/include/linux/tpqic02.h
index e7e3cc625..2972cb2f8 100644
--- a/include/linux/tpqic02.h
+++ b/include/linux/tpqic02.h
@@ -587,10 +587,10 @@
* |___________________ Reserved for diagnostics during debugging.
*/
-#define TP_REWCLOSE(d) ((MINOR(d)&0x01) == 1) /* rewind bit */
+#define TP_REWCLOSE(d) ((minor(d)&0x01) == 1) /* rewind bit */
/* rewind is only done if data has been transferred */
-#define TP_DENS(dev) ((MINOR(dev) >> 1) & 0x07) /* tape density */
-#define TP_UNIT(dev) ((MINOR(dev) >> 4) & 0x07) /* unit number */
+#define TP_DENS(dev) ((minor(dev) >> 1) & 0x07) /* tape density */
+#define TP_UNIT(dev) ((minor(dev) >> 4) & 0x07) /* unit number */
/* print excessive diagnostics */
#define TP_DIAGS(dev) (QIC02_TAPE_DEBUG & TPQD_DIAGS)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 7af47915e..6194ad03b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -460,6 +460,7 @@ struct usb_device_id {
/**
* struct usb_driver - identifies USB driver to usbcore
+ * @owner: pointer to the module owner of this driver
* @name: The driver name should be unique among USB drivers
* @probe: Called to see if the driver is willing to manage a particular
* interface on a device. The probe routine returns a handle that
@@ -502,6 +503,7 @@ struct usb_device_id {
* well as cancel any I/O requests that are still pending.
*/
struct usb_driver {
+ struct module *owner;
const char *name;
void *(*probe)(
@@ -521,7 +523,7 @@ struct usb_driver {
struct semaphore serialize;
- /* ioctl -- userspace apps can talk to drivers through usbdevfs */
+ /* ioctl -- userspace apps can talk to drivers through usbfs */
int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);
/* support for "new-style" USB hotplugging */
@@ -567,7 +569,7 @@ typedef struct
unsigned int length; /* expected length */
unsigned int actual_length;
unsigned int status;
-} iso_packet_descriptor_t, *piso_packet_descriptor_t;
+} iso_packet_descriptor_t;
struct urb;
@@ -629,7 +631,7 @@ typedef void (*usb_complete_t)(struct urb *);
*
* This structure identifies USB transfer requests. URBs may be allocated
* in any way, although usb_alloc_urb() is often convenient. Initialization
- * may be done using various FILL_*_URB() macros. URBs are submitted
+ * may be done using various usb_fill_*_urb() functions. URBs are submitted
* using usb_submit_urb(), and pending requests may be canceled using
* usb_unlink_urb().
*
@@ -729,87 +731,7 @@ struct urb
iso_packet_descriptor_t iso_frame_desc[0]; /* (in) ISO ONLY */
};
-typedef struct urb urb_t, *purb_t;
-
-/**
- * FILL_CONTROL_URB - macro to help initialize a control urb
- * @URB: pointer to the urb to initialize.
- * @DEV: pointer to the struct usb_device for this urb.
- * @PIPE: the endpoint pipe
- * @SETUP_PACKET: pointer to the setup_packet buffer
- * @TRANSFER_BUFFER: pointer to the transfer buffer
- * @BUFFER_LENGTH: length of the transfer buffer
- * @COMPLETE: pointer to the usb_complete_t function
- * @CONTEXT: what to set the urb context to.
- *
- * Initializes a control urb with the proper information needed to submit
- * it to a device. This macro is depreciated, the usb_fill_control_urb()
- * function should be used instead.
- */
-#define FILL_CONTROL_URB(URB,DEV,PIPE,SETUP_PACKET,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
- do {\
- spin_lock_init(&(URB)->lock);\
- (URB)->dev=DEV;\
- (URB)->pipe=PIPE;\
- (URB)->setup_packet=SETUP_PACKET;\
- (URB)->transfer_buffer=TRANSFER_BUFFER;\
- (URB)->transfer_buffer_length=BUFFER_LENGTH;\
- (URB)->complete=COMPLETE;\
- (URB)->context=CONTEXT;\
- } while (0)
-
-/**
- * FILL_BULK_URB - macro to help initialize a bulk urb
- * @URB: pointer to the urb to initialize.
- * @DEV: pointer to the struct usb_device for this urb.
- * @PIPE: the endpoint pipe
- * @TRANSFER_BUFFER: pointer to the transfer buffer
- * @BUFFER_LENGTH: length of the transfer buffer
- * @COMPLETE: pointer to the usb_complete_t function
- * @CONTEXT: what to set the urb context to.
- *
- * Initializes a bulk urb with the proper information needed to submit it
- * to a device. This macro is depreciated, the usb_fill_bulk_urb()
- * function should be used instead.
- */
-#define FILL_BULK_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
- do {\
- spin_lock_init(&(URB)->lock);\
- (URB)->dev=DEV;\
- (URB)->pipe=PIPE;\
- (URB)->transfer_buffer=TRANSFER_BUFFER;\
- (URB)->transfer_buffer_length=BUFFER_LENGTH;\
- (URB)->complete=COMPLETE;\
- (URB)->context=CONTEXT;\
- } while (0)
-
-/**
- * FILL_INT_URB - macro to help initialize a interrupt urb
- * @URB: pointer to the urb to initialize.
- * @DEV: pointer to the struct usb_device for this urb.
- * @PIPE: the endpoint pipe
- * @TRANSFER_BUFFER: pointer to the transfer buffer
- * @BUFFER_LENGTH: length of the transfer buffer
- * @COMPLETE: pointer to the usb_complete_t function
- * @CONTEXT: what to set the urb context to.
- * @INTERVAL: what to set the urb interval to.
- *
- * Initializes a interrupt urb with the proper information needed to submit
- * it to a device. This macro is depreciated, the usb_fill_int_urb()
- * function should be used instead.
- */
-#define FILL_INT_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT,INTERVAL) \
- do {\
- spin_lock_init(&(URB)->lock);\
- (URB)->dev=DEV;\
- (URB)->pipe=PIPE;\
- (URB)->transfer_buffer=TRANSFER_BUFFER;\
- (URB)->transfer_buffer_length=BUFFER_LENGTH;\
- (URB)->complete=COMPLETE;\
- (URB)->context=CONTEXT;\
- (URB)->interval=INTERVAL;\
- (URB)->start_frame=-1;\
- } while (0)
+typedef struct urb urb_t;
/**
* usb_fill_control_urb - initializes a control urb
@@ -908,11 +830,22 @@ static inline void usb_fill_int_urb (struct urb *urb,
urb->interval = interval;
urb->start_frame = -1;
}
-
+
+/*
+ * old style macros to enable 2.4 and 2.2 drivers to build
+ * properly. Please do not use these for new USB drivers.
+ */
+#define FILL_CONTROL_URB(URB,DEV,PIPE,SETUP_PACKET,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
+ usb_fill_control_urb(URB,DEV,PIPE,SETUP_PACKET,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT)
+#define FILL_BULK_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
+ usb_fill_bulk_urb(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT)
+#define FILL_INT_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT,INTERVAL) \
+ usb_fill_int_urb(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT,INTERVAL)
+
extern struct urb *usb_alloc_urb(int iso_packets);
-extern void usb_free_urb(struct urb *purb);
-extern int usb_submit_urb(struct urb *purb);
-extern int usb_unlink_urb(struct urb *purb);
+extern void usb_free_urb(struct urb *urb);
+extern int usb_submit_urb(struct urb *urb);
+extern int usb_unlink_urb(struct urb *urb);
/*-------------------------------------------------------------------*
* SYNCHRONOUS CALL SUPPORT *
@@ -959,8 +892,8 @@ struct usb_operations {
int (*allocate)(struct usb_device *);
int (*deallocate)(struct usb_device *);
int (*get_frame_number) (struct usb_device *usb_dev);
- int (*submit_urb) (struct urb* purb);
- int (*unlink_urb) (struct urb* purb);
+ int (*submit_urb) (struct urb *urb);
+ int (*unlink_urb) (struct urb *urb);
};
#define DEVNUM_ROUND_ROBIN /***** OPTION *****/
@@ -989,8 +922,7 @@ struct usb_bus {
int bandwidth_int_reqs; /* number of Interrupt requesters */
int bandwidth_isoc_reqs; /* number of Isoc. requesters */
- /* usbdevfs inode list */
- struct list_head inodes;
+ struct dentry *dentry; /* usbfs dentry entry for the bus */
atomic_t refcnt;
};
@@ -1028,6 +960,21 @@ extern int usb_root_hub_string(int id, int serial,
#define NS_TO_US(ns) ((ns + 500L) / 1000L)
/* convert & round nanoseconds to microseconds */
+/*
+ * As of USB 2.0, full/low speed devices are segregated into trees.
+ * One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
+ * The other type grows from high speed hubs when they connect to
+ * full/low speed devices using "Transaction Translators" (TTs).
+ *
+ * TTs should only be known to the hub driver, and high speed bus
+ * drivers (only EHCI for now). They affect periodic scheduling and
+ * sometimes control/bulk error recovery.
+ */
+struct usb_tt {
+ struct usb_device *hub; /* upstream highspeed hub */
+ int multi; /* true means one TT per port */
+};
+
/* -------------------------------------------------------------------------- */
@@ -1056,7 +1003,8 @@ extern int usb_set_address(struct usb_device *dev);
#define USB_MAXCHILDREN (16)
struct usb_device {
- int devnum; /* Device number on USB bus */
+ int devnum; /* Address on USB bus */
+ char devpath [16]; /* Use in messages: /port/port/... */
enum {
USB_SPEED_UNKNOWN = 0, /* enumerating */
@@ -1064,8 +1012,8 @@ struct usb_device {
USB_SPEED_HIGH /* usb 2.0 */
} speed;
- struct usb_device *tt; /* usb1.1 device on usb2.0 bus */
- int ttport; /* device/hub port on that tt */
+ struct usb_tt *tt; /* low/full speed dev, highspeed hub */
+ int ttport; /* device port on that tt hub */
atomic_t refcnt; /* Reference count */
struct semaphore serialize;
@@ -1090,9 +1038,8 @@ struct usb_device {
void *hcpriv; /* Host Controller private data */
- /* usbdevfs inode list */
- struct list_head inodes;
struct list_head filelist;
+ struct dentry *dentry; /* usbfs dentry entry for the device */
/*
* Child devices - these can be either new devices
@@ -1254,7 +1201,7 @@ void usb_show_string(struct usb_device *dev, char *id, int index);
/*
* bus and driver list
- * exported only for usbdevfs (not visible outside usbcore)
+ * exported only for usbfs (not visible outside usbcore)
*/
extern struct list_head usb_driver_list;
@@ -1271,23 +1218,25 @@ extern struct semaphore usb_bus_list_lock;
* these are expected to be called from the USB core/hub thread
* with the kernel lock held
*/
-extern void usbdevfs_add_bus(struct usb_bus *bus);
-extern void usbdevfs_remove_bus(struct usb_bus *bus);
-extern void usbdevfs_add_device(struct usb_device *dev);
-extern void usbdevfs_remove_device(struct usb_device *dev);
+extern void usbfs_add_bus(struct usb_bus *bus);
+extern void usbfs_remove_bus(struct usb_bus *bus);
+extern void usbfs_add_device(struct usb_device *dev);
+extern void usbfs_remove_device(struct usb_device *dev);
+extern void usbfs_update_special (void);
-extern int usbdevfs_init(void);
-extern void usbdevfs_cleanup(void);
+extern int usbfs_init(void);
+extern void usbfs_cleanup(void);
#else /* CONFIG_USB_DEVICEFS */
-static inline void usbdevfs_add_bus(struct usb_bus *bus) {}
-static inline void usbdevfs_remove_bus(struct usb_bus *bus) {}
-static inline void usbdevfs_add_device(struct usb_device *dev) {}
-static inline void usbdevfs_remove_device(struct usb_device *dev) {}
+static inline void usbfs_add_bus(struct usb_bus *bus) {}
+static inline void usbfs_remove_bus(struct usb_bus *bus) {}
+static inline void usbfs_add_device(struct usb_device *dev) {}
+static inline void usbfs_remove_device(struct usb_device *dev) {}
+static inline void usbfs_update_special (void) {}
-static inline int usbdevfs_init(void) { return 0; }
-static inline void usbdevfs_cleanup(void) { }
+static inline int usbfs_init(void) { return 0; }
+static inline void usbfs_cleanup(void) { }
#endif /* CONFIG_USB_DEVICEFS */
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index fd8a34b45..69008e236 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -150,17 +150,6 @@ struct usbdevfs_hub_portinfo {
#include <linux/list.h>
#include <asm/semaphore.h>
-/*
- * inode number macros
- */
-#define ITYPE(x) ((x)&(0xf<<28))
-#define ISPECIAL (0<<28)
-#define IBUS (1<<28)
-#define IDEVICE (2<<28)
-#define IBUSNR(x) (((x)>>8)&0xff)
-#define IDEVNR(x) ((x)&0xff)
-
-#define IROOT 1
struct dev_state {
struct list_head list; /* state list */
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 3503fd222..186f03f01 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -19,24 +19,11 @@
#include <asm/page.h>
#include <asm/processor.h>
-/*
- * Debug control. Slow but useful.
- */
-#if defined(CONFIG_DEBUG_WAITQ)
-#define WAITQUEUE_DEBUG 1
-#else
-#define WAITQUEUE_DEBUG 0
-#endif
-
struct __wait_queue {
unsigned int flags;
#define WQ_FLAG_EXCLUSIVE 0x01
struct task_struct * task;
struct list_head task_list;
-#if WAITQUEUE_DEBUG
- long __magic;
- long __waker;
-#endif
};
typedef struct __wait_queue wait_queue_t;
@@ -77,129 +64,47 @@ typedef struct __wait_queue wait_queue_t;
struct __wait_queue_head {
wq_lock_t lock;
struct list_head task_list;
-#if WAITQUEUE_DEBUG
- long __magic;
- long __creator;
-#endif
};
typedef struct __wait_queue_head wait_queue_head_t;
/*
- * Debugging macros. We eschew `do { } while (0)' because gcc can generate
- * spurious .aligns.
- */
-#if WAITQUEUE_DEBUG
-#define WQ_BUG() BUG()
-#define CHECK_MAGIC(x) \
- do { \
- if ((x) != (long)&(x)) { \
- printk("bad magic %lx (should be %lx), ", \
- (long)x, (long)&(x)); \
- WQ_BUG(); \
- } \
- } while (0)
-#define CHECK_MAGIC_WQHEAD(x) \
- do { \
- if ((x)->__magic != (long)&((x)->__magic)) { \
- printk("bad magic %lx (should be %lx, creator %lx), ", \
- (x)->__magic, (long)&((x)->__magic), (x)->__creator); \
- WQ_BUG(); \
- } \
- } while (0)
-#define WQ_CHECK_LIST_HEAD(list) \
- do { \
- if (!(list)->next || !(list)->prev) \
- WQ_BUG(); \
- } while(0)
-#define WQ_NOTE_WAKER(tsk) \
- do { \
- (tsk)->__waker = (long)__builtin_return_address(0); \
- } while (0)
-#else
-#define WQ_BUG()
-#define CHECK_MAGIC(x)
-#define CHECK_MAGIC_WQHEAD(x)
-#define WQ_CHECK_LIST_HEAD(list)
-#define WQ_NOTE_WAKER(tsk)
-#endif
-
-/*
* Macros for declaration and initialisaton of the datatypes
*/
-#if WAITQUEUE_DEBUG
-# define __WAITQUEUE_DEBUG_INIT(name) (long)&(name).__magic, 0
-# define __WAITQUEUE_HEAD_DEBUG_INIT(name) (long)&(name).__magic, (long)&(name).__magic
-#else
-# define __WAITQUEUE_DEBUG_INIT(name)
-# define __WAITQUEUE_HEAD_DEBUG_INIT(name)
-#endif
-
#define __WAITQUEUE_INITIALIZER(name, tsk) { \
task: tsk, \
- task_list: { NULL, NULL }, \
- __WAITQUEUE_DEBUG_INIT(name)}
+ task_list: { NULL, NULL } }
#define DECLARE_WAITQUEUE(name, tsk) \
wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
lock: WAITQUEUE_RW_LOCK_UNLOCKED, \
- task_list: { &(name).task_list, &(name).task_list }, \
- __WAITQUEUE_HEAD_DEBUG_INIT(name)}
+ task_list: { &(name).task_list, &(name).task_list } }
#define DECLARE_WAIT_QUEUE_HEAD(name) \
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
static inline void init_waitqueue_head(wait_queue_head_t *q)
{
-#if WAITQUEUE_DEBUG
- if (!q)
- WQ_BUG();
-#endif
q->lock = WAITQUEUE_RW_LOCK_UNLOCKED;
INIT_LIST_HEAD(&q->task_list);
-#if WAITQUEUE_DEBUG
- q->__magic = (long)&q->__magic;
- q->__creator = (long)current_text_addr();
-#endif
}
static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
{
-#if WAITQUEUE_DEBUG
- if (!q || !p)
- WQ_BUG();
-#endif
q->flags = 0;
q->task = p;
-#if WAITQUEUE_DEBUG
- q->__magic = (long)&q->__magic;
-#endif
}
static inline int waitqueue_active(wait_queue_head_t *q)
{
-#if WAITQUEUE_DEBUG
- if (!q)
- WQ_BUG();
- CHECK_MAGIC_WQHEAD(q);
-#endif
-
return !list_empty(&q->task_list);
}
static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
{
-#if WAITQUEUE_DEBUG
- if (!head || !new)
- WQ_BUG();
- CHECK_MAGIC_WQHEAD(head);
- CHECK_MAGIC(new->__magic);
- if (!head->task_list.next || !head->task_list.prev)
- WQ_BUG();
-#endif
list_add(&new->task_list, &head->task_list);
}
@@ -209,25 +114,12 @@ static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
static inline void __add_wait_queue_tail(wait_queue_head_t *head,
wait_queue_t *new)
{
-#if WAITQUEUE_DEBUG
- if (!head || !new)
- WQ_BUG();
- CHECK_MAGIC_WQHEAD(head);
- CHECK_MAGIC(new->__magic);
- if (!head->task_list.next || !head->task_list.prev)
- WQ_BUG();
-#endif
list_add_tail(&new->task_list, &head->task_list);
}
static inline void __remove_wait_queue(wait_queue_head_t *head,
wait_queue_t *old)
{
-#if WAITQUEUE_DEBUG
- if (!old)
- WQ_BUG();
- CHECK_MAGIC(old->__magic);
-#endif
list_del(&old->task_list);
}
diff --git a/include/scsi/scsicam.h b/include/scsi/scsicam.h
index a9f00e229..8b0a3c197 100644
--- a/include/scsi/scsicam.h
+++ b/include/scsi/scsicam.h
@@ -14,6 +14,7 @@
#define SCSICAM_H
#include <linux/kdev_t.h>
extern int scsicam_bios_param (Disk *disk, kdev_t dev, int *ip);
-extern int scsi_partsize(struct buffer_head *bh, unsigned long capacity,
+extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds, unsigned int *secs);
+extern unsigned char *scsi_bios_ptable(kdev_t dev);
#endif /* def SCSICAM_H */
diff --git a/init/do_mounts.c b/init/do_mounts.c
index dee7dffee..d954d493e 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -1,11 +1,14 @@
#define __KERNEL_SYSCALLS__
#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/unistd.h>
#include <linux/ctype.h>
#include <linux/blk.h>
#include <linux/fd.h>
+#include <linux/tty.h>
#include <linux/init.h>
#include <linux/nfs_fs.h>
@@ -18,7 +21,6 @@
#define BUILD_CRAMDISK
extern int get_filesystem_list(char * buf);
-extern void wait_for_keypress(void);
asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type,
unsigned long flags, void *data);
@@ -352,8 +354,8 @@ static int __init create_dev(char *name, kdev_t dev, char *devfs_name)
if (!do_devfs)
return sys_mknod(name, S_IFBLK|0600, kdev_t_to_nr(dev));
- handle = devfs_find_handle(NULL, dev ? NULL : devfs_name,
- MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1);
+ handle = devfs_find_handle(NULL, kdev_none(dev) ? devfs_name : NULL,
+ major(dev), minor(dev), DEVFS_SPECIAL_BLK, 1);
if (!handle)
return -1;
n = devfs_generate_path(handle, path + 5, sizeof (path) - 5);
@@ -364,8 +366,9 @@ static int __init create_dev(char *name, kdev_t dev, char *devfs_name)
static void __init change_floppy(char *fmt, ...)
{
- extern void wait_for_keypress(void);
+ struct termios termios;
char buf[80];
+ char c;
int fd;
va_list args;
va_start(args, fmt);
@@ -377,7 +380,16 @@ static void __init change_floppy(char *fmt, ...)
close(fd);
}
printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf);
- wait_for_keypress();
+ fd = open("/dev/console", O_RDWR, 0);
+ if (fd >= 0) {
+ sys_ioctl(fd, TCGETS, (long)&termios);
+ termios.c_lflag &= ~ICANON;
+ sys_ioctl(fd, TCSETSF, (long)&termios);
+ read(fd, &c, 1);
+ termios.c_lflag |= ICANON;
+ sys_ioctl(fd, TCSETSF, (long)&termios);
+ close(fd);
+ }
}
#ifdef CONFIG_BLK_DEV_RAM
@@ -619,15 +631,72 @@ static int __init rd_load_disk(int n)
#ifdef CONFIG_BLK_DEV_RAM
if (rd_prompt)
change_floppy("root floppy disk to be loaded into RAM disk");
- create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL);
+ create_dev("/dev/ram", mk_kdev(RAMDISK_MAJOR, n), NULL);
#endif
return rd_load_image("/dev/root");
}
+#ifdef CONFIG_DEVFS_FS
+
+static void __init convert_name(char *prefix, char *name, char *p, int part)
+{
+ int host, bus, target, lun;
+ char dest[64];
+ char src[64];
+ char *base = p - 1;
+
+ /* Decode "c#b#t#u#" */
+ if (*p++ != 'c')
+ return;
+ host = simple_strtol(p, &p, 10);
+ if (*p++ != 'b')
+ return;
+ bus = simple_strtol(p, &p, 10);
+ if (*p++ != 't')
+ return;
+ target = simple_strtol(p, &p, 10);
+ if (*p++ != 'u')
+ return;
+ lun = simple_strtol(p, &p, 10);
+ if (!part)
+ sprintf(dest, "%s/host%d/bus%d/target%d/lun%d",
+ prefix, host, bus, target, lun);
+ else if (*p++ == 'p')
+ sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/part%s",
+ prefix, host, bus, target, lun, p);
+ else
+ sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/disc",
+ prefix, host, bus, target, lun);
+ *base = '\0';
+ sprintf(src, "/dev/%s", name);
+ sys_mkdir(src, 0755);
+ *base = '/';
+ sprintf(src, "/dev/%s", name);
+ sys_symlink(dest, src);
+}
+
+static void __init devfs_make_root(char *name)
+{
+
+ if (!strncmp(name, "sd/", 3))
+ convert_name("../scsi", name, name+3, 1);
+ else if (!strncmp(name, "sr/", 3))
+ convert_name("../scsi", name, name+3, 0);
+ else if (!strncmp(name, "ide/hd/", 7))
+ convert_name("..", name, name + 7, 1);
+ else if (!strncmp(name, "ide/cd/", 7))
+ convert_name("..", name, name + 7, 0);
+}
+#else
+static void __init devfs_make_root(char *name)
+{
+}
+#endif
+
static void __init mount_root(void)
{
#ifdef CONFIG_ROOT_NFS
- if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+ if (major(ROOT_DEV) == UNNAMED_MAJOR) {
if (mount_nfs_root()) {
sys_chdir("/root");
ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
@@ -635,17 +704,17 @@ static void __init mount_root(void)
return;
}
printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
- ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
+ ROOT_DEV = mk_kdev(FLOPPY_MAJOR, 0);
}
#endif
devfs_make_root(root_device_name);
create_dev("/dev/root", ROOT_DEV, root_device_name);
#ifdef CONFIG_BLK_DEV_FD
- if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
+ if (major(ROOT_DEV) == FLOPPY_MAJOR) {
/* rd_doload is 2 for a dual initrd/ramload setup */
if (rd_doload==2) {
if (rd_load_disk(1)) {
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 1);
+ ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 1);
create_dev("/dev/root", ROOT_DEV, NULL);
}
} else
@@ -680,7 +749,7 @@ static int do_linuxrc(void * shell)
static void __init handle_initrd(void)
{
#ifdef CONFIG_BLK_DEV_INITRD
- int ram0 = kdev_t_to_nr(MKDEV(RAMDISK_MAJOR,0));
+ kdev_t ram0 = mk_kdev(RAMDISK_MAJOR,0);
int error;
int i, pid;
@@ -700,12 +769,12 @@ static void __init handle_initrd(void)
sys_mount("..", ".", NULL, MS_MOVE, NULL);
sys_umount("/old/dev", 0);
- if (real_root_dev == ram0) {
+ if (real_root_dev == kdev_t_to_nr(ram0)) {
sys_chdir("/old");
return;
}
- ROOT_DEV = real_root_dev;
+ ROOT_DEV = to_kdev_t(real_root_dev);
mount_root();
printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
@@ -732,8 +801,8 @@ static void __init handle_initrd(void)
static int __init initrd_load(void)
{
#ifdef CONFIG_BLK_DEV_INITRD
- create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL);
- create_dev("/dev/initrd", MKDEV(RAMDISK_MAJOR, INITRD_MINOR), NULL);
+ create_dev("/dev/ram", mk_kdev(RAMDISK_MAJOR, 0), NULL);
+ create_dev("/dev/initrd", mk_kdev(RAMDISK_MAJOR, INITRD_MINOR), NULL);
#endif
return rd_load_image("/dev/initrd");
}
@@ -743,14 +812,15 @@ static int __init initrd_load(void)
*/
void prepare_namespace(void)
{
- int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+ int is_floppy = major(ROOT_DEV) == FLOPPY_MAJOR;
#ifdef CONFIG_BLK_DEV_INITRD
if (!initrd_start)
mount_initrd = 0;
- real_root_dev = ROOT_DEV;
+ real_root_dev = kdev_t_to_nr(ROOT_DEV);
#endif
sys_mkdir("/dev", 0700);
sys_mkdir("/root", 0700);
+ sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1));
#ifdef CONFIG_DEVFS_FS
sys_mount("devfs", "/dev", "devfs", 0, NULL);
do_devfs = 1;
@@ -758,12 +828,12 @@ void prepare_namespace(void)
create_dev("/dev/root", ROOT_DEV, NULL);
if (mount_initrd) {
- if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) {
+ if (initrd_load() && kdev_same(ROOT_DEV, mk_kdev(RAMDISK_MAJOR, 0))) {
handle_initrd();
goto out;
}
} else if (is_floppy && rd_doload && rd_load_disk(0))
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0);
mount_root();
out:
sys_umount("/dev", 0);
diff --git a/ipc/shm.c b/ipc/shm.c
index 25b3ae86e..7a1335327 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -17,6 +17,7 @@
#include <linux/config.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/shm.h>
#include <linux/init.h>
#include <linux/file.h>
diff --git a/kernel/acct.c b/kernel/acct.c
index 3e21f9fce..a314da8b0 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -213,10 +213,10 @@ out_err:
goto out;
}
-void acct_auto_close(kdev_t dev)
+void acct_auto_close(struct super_block *sb)
{
lock_kernel();
- if (acct_file && acct_file->f_dentry->d_inode->i_dev == dev)
+ if (acct_file && acct_file->f_dentry->d_inode->i_sb == sb)
sys_acct(NULL);
unlock_kernel();
}
diff --git a/kernel/device.c b/kernel/device.c
index 16fe11cf5..8b7c9e47e 100644
--- a/kernel/device.c
+++ b/kernel/device.c
@@ -732,15 +732,10 @@ device_write_power(const char * buf, size_t count, loff_t off, void * data)
error = -EINVAL;
- if (!num_args) {
- printk("have no arguments\n");
+ if (!num_args)
goto done;
- }
if (!strnicmp(str_command,"suspend",7)) {
-
- printk("%s: we know it's a suspend action\n",__FUNCTION__);
-
if (num_args != 3)
goto done;
if (!strnicmp(str_stage,"notify",6))
@@ -775,8 +770,7 @@ device_write_power(const char * buf, size_t count, loff_t off, void * data)
error = dev->driver->resume(dev,int_stage);
else
error = 0;
- } else
- printk("%s: couldn't find any thing to do\n",__FUNCTION__);
+ }
done:
put_device(dev);
diff --git a/kernel/exit.c b/kernel/exit.c
index c2c97c1eb..a3490404f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -5,6 +5,7 @@
*/
#include <linux/config.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
@@ -12,6 +13,7 @@
#include <linux/completion.h>
#include <linux/personality.h>
#include <linux/tty.h>
+#include <linux/namespace.h>
#ifdef CONFIG_BSD_PROCESS_ACCT
#include <linux/acct.h>
#endif
@@ -62,9 +64,9 @@ static void release_task(struct task_struct * p)
* timeslices, because any timeslice recovered here
* was given away by the parent in the first place.)
*/
- current->counter += p->counter;
- if (current->counter >= MAX_COUNTER)
- current->counter = MAX_COUNTER;
+ current->time_slice += p->time_slice;
+ if (current->time_slice > MAX_TSLICE)
+ current->time_slice = MAX_TSLICE;
p->pid = 0;
free_task_struct(p);
} else {
@@ -452,6 +454,7 @@ fake_volatile:
sem_exit();
__exit_files(tsk);
__exit_fs(tsk);
+ exit_namespace(tsk);
exit_sighand(tsk);
exit_thread();
diff --git a/kernel/fork.c b/kernel/fork.c
index 8a39c6adb..4c3114eef 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/completion.h>
+#include <linux/namespace.h>
#include <linux/personality.h>
#include <asm/pgtable.h>
@@ -566,6 +567,9 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
struct task_struct *p;
struct completion vfork;
+ if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
+ return -EINVAL;
+
retval = -EPERM;
/*
@@ -585,8 +589,10 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
*p = *current;
retval = -EAGAIN;
- if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur)
- goto bad_fork_free;
+ if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur) {
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
+ goto bad_fork_free;
+ }
atomic_inc(&p->user->__count);
atomic_inc(&p->user->processes);
@@ -661,9 +667,11 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
goto bad_fork_cleanup_fs;
if (copy_mm(clone_flags, p))
goto bad_fork_cleanup_sighand;
+ if (copy_namespace(clone_flags, p))
+ goto bad_fork_cleanup_mm;
retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
if (retval)
- goto bad_fork_cleanup_mm;
+ goto bad_fork_cleanup_namespace;
p->semundo = NULL;
/* Our parent execution domain becomes current domain
@@ -682,9 +690,9 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
* more scheduling fairness. This is only important in the first
* timeslice, on the long run the scheduling behaviour is unchanged.
*/
- p->counter = (current->counter + 1) >> 1;
- current->counter >>= 1;
- if (!current->counter)
+ p->time_slice = (current->time_slice + 1) >> 1;
+ current->time_slice >>= 1;
+ if (!current->time_slice)
current->need_resched = 1;
/*
@@ -730,6 +738,8 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
fork_out:
return retval;
+bad_fork_cleanup_namespace:
+ exit_namespace(p);
bad_fork_cleanup_mm:
exit_mm(p);
bad_fork_cleanup_sighand:
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 553e9c663..9cbf417c1 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -24,6 +24,8 @@
#include <linux/unistd.h>
#include <linux/kmod.h>
#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/namespace.h>
#include <linux/completion.h>
#include <asm/uaccess.h>
@@ -36,6 +38,7 @@ use_init_fs_context(void)
struct fs_struct *our_fs, *init_fs;
struct dentry *root, *pwd;
struct vfsmount *rootmnt, *pwdmnt;
+ struct namespace *our_ns, *init_ns;
/*
* Make modprobe's fs context be a copy of init's.
@@ -55,6 +58,11 @@ use_init_fs_context(void)
*/
init_fs = init_task.fs;
+ init_ns = init_task.namespace;
+ get_namespace(init_ns);
+ our_ns = current->namespace;
+ current->namespace = init_ns;
+ put_namespace(our_ns);
read_lock(&init_fs->lock);
rootmnt = mntget(init_fs->rootmnt);
root = dget(init_fs->root);
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index 90b6cbbd8..56dd5a66a 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -189,6 +189,8 @@ EXPORT_SYMBOL(inode_change_ok);
EXPORT_SYMBOL(write_inode_now);
EXPORT_SYMBOL(notify_change);
EXPORT_SYMBOL(set_blocksize);
+EXPORT_SYMBOL(sb_set_blocksize);
+EXPORT_SYMBOL(sb_min_blocksize);
EXPORT_SYMBOL(getblk);
EXPORT_SYMBOL(cdget);
EXPORT_SYMBOL(cdput);
@@ -306,6 +308,7 @@ EXPORT_SYMBOL(blkdev_put);
EXPORT_SYMBOL(ioctl_by_bdev);
EXPORT_SYMBOL(grok_partitions);
EXPORT_SYMBOL(register_disk);
+EXPORT_SYMBOL(read_dev_sector);
EXPORT_SYMBOL(tq_disk);
EXPORT_SYMBOL(init_buffer);
EXPORT_SYMBOL(refile_buffer);
diff --git a/kernel/pm.c b/kernel/pm.c
index b5ff82ce1..a33e7b26e 100644
--- a/kernel/pm.c
+++ b/kernel/pm.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/pm.h>
#include <linux/interrupt.h>
diff --git a/kernel/sched.c b/kernel/sched.c
index aa3546552..dc5eea2af 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -51,25 +51,16 @@ extern void mem_use(void);
* NOTE! The unix "nice" value influences how long a process
* gets. The nice value ranges from -20 to +19, where a -20
* is a "high-priority" task, and a "+10" is a low-priority
- * task.
- *
- * We want the time-slice to be around 50ms or so, so this
- * calculation depends on the value of HZ.
+ * task. The default time slice for zero-nice tasks will be 37ms.
*/
-#if HZ < 200
-#define TICK_SCALE(x) ((x) >> 2)
-#elif HZ < 400
-#define TICK_SCALE(x) ((x) >> 1)
-#elif HZ < 800
-#define TICK_SCALE(x) (x)
-#elif HZ < 1600
-#define TICK_SCALE(x) ((x) << 1)
-#else
-#define TICK_SCALE(x) ((x) << 2)
-#endif
+#define NICE_RANGE 40
+#define MIN_NICE_TSLICE 10000
+#define MAX_NICE_TSLICE 90000
+#define TASK_TIMESLICE(p) ((int) ts_table[19 - (p)->nice])
-#define NICE_TO_TICKS(nice) (TICK_SCALE(20-(nice))+1)
+static unsigned char ts_table[NICE_RANGE];
+#define MM_AFFINITY_BONUS 1
/*
* Init task must be ok at boot for the ix86 as we will check its signals
@@ -94,6 +85,8 @@ rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; /* outer */
static LIST_HEAD(runqueue_head);
+static unsigned long rcl_curr;
+
/*
* We align per-CPU scheduling data on cacheline boundaries,
* to prevent cacheline ping-pong.
@@ -165,10 +158,11 @@ static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struc
* Don't do any other calculations if the time slice is
* over..
*/
- weight = p->counter;
- if (!weight)
- goto out;
-
+ if (!p->time_slice)
+ return 0;
+
+ weight = p->dyn_prio + 1;
+
#ifdef CONFIG_SMP
/* Give a largish advantage to the same processor... */
/* (this is equivalent to penalizing other processors) */
@@ -178,7 +172,7 @@ static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struc
/* .. and a slight advantage to the current MM */
if (p->mm == this_mm || !p->mm)
- weight += 1;
+ weight += MM_AFFINITY_BONUS;
weight += 20 - p->nice;
goto out;
}
@@ -324,6 +318,10 @@ send_now_idle:
*/
static inline void add_to_runqueue(struct task_struct * p)
{
+ p->dyn_prio += rcl_curr - p->rcl_last;
+ p->rcl_last = rcl_curr;
+ if (p->dyn_prio > MAX_DYNPRIO)
+ p->dyn_prio = MAX_DYNPRIO;
list_add(&p->run_list, &runqueue_head);
nr_running++;
}
@@ -376,9 +374,7 @@ inline int wake_up_process(struct task_struct * p)
static void process_timeout(unsigned long __data)
{
- struct task_struct * p = (struct task_struct *) __data;
-
- wake_up_process(p);
+ wake_up_process((struct task_struct *)__data);
}
/**
@@ -536,6 +532,19 @@ asmlinkage void schedule_tail(struct task_struct *prev)
__schedule_tail(prev);
}
+void expire_task(struct task_struct *p)
+{
+ if (unlikely(!p->time_slice))
+ goto need_resched;
+
+ if (!--p->time_slice) {
+ if (p->dyn_prio)
+ p->dyn_prio--;
+need_resched:
+ p->need_resched = 1;
+ }
+}
+
/*
* 'schedule()' is the scheduler function. It's a very simple and nice
* scheduler: it's not perfect, but certainly works for most things.
@@ -578,20 +587,20 @@ need_resched_back:
/* move an exhausted RR process to be last.. */
if (unlikely(prev->policy == SCHED_RR))
- if (!prev->counter) {
- prev->counter = NICE_TO_TICKS(prev->nice);
+ if (!prev->time_slice) {
+ prev->time_slice = TASK_TIMESLICE(prev);
move_last_runqueue(prev);
}
switch (prev->state) {
- case TASK_INTERRUPTIBLE:
- if (signal_pending(prev)) {
- prev->state = TASK_RUNNING;
- break;
- }
- default:
- del_from_runqueue(prev);
- case TASK_RUNNING:;
+ case TASK_INTERRUPTIBLE:
+ if (signal_pending(prev)) {
+ prev->state = TASK_RUNNING;
+ break;
+ }
+ default:
+ del_from_runqueue(prev);
+ case TASK_RUNNING:;
}
prev->need_resched = 0;
@@ -616,14 +625,12 @@ repeat_schedule:
/* Do we need to re-calculate counters? */
if (unlikely(!c)) {
- struct task_struct *p;
-
- spin_unlock_irq(&runqueue_lock);
- read_lock(&tasklist_lock);
- for_each_task(p)
- p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice);
- read_unlock(&tasklist_lock);
- spin_lock_irq(&runqueue_lock);
+ rcl_curr++;
+ list_for_each(tmp, &runqueue_head) {
+ p = list_entry(tmp, struct task_struct, run_list);
+ p->time_slice = TASK_TIMESLICE(p);
+ p->rcl_last = rcl_curr;
+ }
goto repeat_schedule;
}
@@ -719,21 +726,17 @@ static inline void __wake_up_common (wait_queue_head_t *q, unsigned int mode,
struct list_head *tmp;
struct task_struct *p;
- CHECK_MAGIC_WQHEAD(q);
- WQ_CHECK_LIST_HEAD(&q->task_list);
-
list_for_each(tmp,&q->task_list) {
unsigned int state;
- wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
+ wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
- CHECK_MAGIC(curr->__magic);
p = curr->task;
state = p->state;
- if (state & mode) {
- WQ_NOTE_WAKER(curr);
- if (try_to_wake_up(p, sync) && (curr->flags&WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
- break;
- }
+ if ((state & mode) &&
+ try_to_wake_up(p, sync) &&
+ ((curr->flags & WQ_FLAG_EXCLUSIVE) &&
+ !--nr_exclusive))
+ break;
}
}
@@ -891,11 +894,7 @@ asmlinkage long sys_nice(int increment)
static inline struct task_struct *find_process_by_pid(pid_t pid)
{
- struct task_struct *tsk = current;
-
- if (pid)
- tsk = find_task_by_pid(pid);
- return tsk;
+ return pid ? find_task_by_pid(pid) : current;
}
static int setscheduler(pid_t pid, int policy,
@@ -1064,9 +1063,9 @@ asmlinkage long sys_sched_yield(void)
current->policy |= SCHED_YIELD;
current->need_resched = 1;
- spin_lock_irq(&runqueue_lock);
- move_last_runqueue(current);
- spin_unlock_irq(&runqueue_lock);
+ current->time_slice = 0;
+ if (++current->dyn_prio > MAX_DYNPRIO)
+ current->dyn_prio = MAX_DYNPRIO;
}
return 0;
}
@@ -1115,7 +1114,7 @@ asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval)
read_lock(&tasklist_lock);
p = find_process_by_pid(pid);
if (p)
- jiffies_to_timespec(p->policy & SCHED_FIFO ? 0 : NICE_TO_TICKS(p->nice),
+ jiffies_to_timespec(p->policy & SCHED_FIFO ? 0 : TASK_TIMESLICE(p),
&t);
read_unlock(&tasklist_lock);
if (p)
@@ -1231,35 +1230,33 @@ void show_state(void)
*/
void reparent_to_init(void)
{
- struct task_struct *this_task = current;
-
write_lock_irq(&tasklist_lock);
/* Reparent to init */
- REMOVE_LINKS(this_task);
- this_task->p_pptr = child_reaper;
- this_task->p_opptr = child_reaper;
- SET_LINKS(this_task);
+ REMOVE_LINKS(current);
+ current->p_pptr = child_reaper;
+ current->p_opptr = child_reaper;
+ SET_LINKS(current);
/* Set the exit signal to SIGCHLD so we signal init on exit */
- this_task->exit_signal = SIGCHLD;
+ current->exit_signal = SIGCHLD;
/* We also take the runqueue_lock while altering task fields
* which affect scheduling decisions */
spin_lock(&runqueue_lock);
- this_task->ptrace = 0;
- this_task->nice = DEF_NICE;
- this_task->policy = SCHED_OTHER;
+ current->ptrace = 0;
+ current->nice = DEF_NICE;
+ current->policy = SCHED_OTHER;
/* cpus_allowed? */
/* rt_priority? */
/* signals? */
- this_task->cap_effective = CAP_INIT_EFF_SET;
- this_task->cap_inheritable = CAP_INIT_INH_SET;
- this_task->cap_permitted = CAP_FULL_SET;
- this_task->keep_capabilities = 0;
- memcpy(this_task->rlim, init_task.rlim, sizeof(*(this_task->rlim)));
- this_task->user = INIT_USER;
+ current->cap_effective = CAP_INIT_EFF_SET;
+ current->cap_inheritable = CAP_INIT_INH_SET;
+ current->cap_permitted = CAP_FULL_SET;
+ current->keep_capabilities = 0;
+ memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim)));
+ current->user = INIT_USER;
spin_unlock(&runqueue_lock);
write_unlock_irq(&tasklist_lock);
@@ -1306,9 +1303,10 @@ void __init init_idle(void)
if (current != &init_task && task_on_runqueue(current)) {
printk("UGH! (%d:%d) was on the runqueue, removing.\n",
- smp_processor_id(), current->pid);
+ smp_processor_id(), current->pid);
del_from_runqueue(current);
}
+ current->dyn_prio = 0;
sched_data->curr = current;
sched_data->last_schedule = get_cycles();
clear_bit(current->processor, &wait_init_idle);
@@ -1316,6 +1314,18 @@ void __init init_idle(void)
extern void init_timervecs (void);
+static void fill_tslice_map(void)
+{
+ int i;
+
+ for (i = 0; i < NICE_RANGE; i++) {
+ ts_table[i] = ((MIN_NICE_TSLICE +
+ ((MAX_NICE_TSLICE -
+ MIN_NICE_TSLICE) / (NICE_RANGE - 1)) * i) * HZ) / 1000000;
+ if (!ts_table[i]) ts_table[i] = 1;
+ }
+}
+
void __init sched_init(void)
{
/*
@@ -1330,6 +1340,8 @@ void __init sched_init(void)
for(nr = 0; nr < PIDHASH_SZ; nr++)
pidhash[nr] = NULL;
+ fill_tslice_map();
+
init_timervecs();
init_bh(TIMER_BH, timer_bh);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index e8ebdc156..50f855bdc 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -19,6 +19,7 @@
*/
#include <linux/config.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/swapctl.h>
diff --git a/kernel/timer.c b/kernel/timer.c
index a6e2b0fc0..c56ec37ea 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -583,10 +583,7 @@ void update_process_times(int user_tick)
update_one_process(p, user_tick, system, cpu);
if (p->pid) {
- if (--p->counter <= 0) {
- p->counter = 0;
- p->need_resched = 1;
- }
+ expire_task(p);
if (p->nice > 0)
kstat.per_cpu_nice[cpu] += user_tick;
else
diff --git a/mm/filemap.c b/mm/filemap.c
index 3f807b05c..fa5ec9d7a 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1138,9 +1138,9 @@ static void profile_readahead(int async, struct file *filp)
static inline int get_max_readahead(struct inode * inode)
{
- if (!inode->i_dev || !max_readahead[MAJOR(inode->i_dev)])
+ if (kdev_none(inode->i_dev) || !max_readahead[major(inode->i_dev)])
return vm_max_readahead;
- return max_readahead[MAJOR(inode->i_dev)][MINOR(inode->i_dev)];
+ return max_readahead[major(inode->i_dev)][minor(inode->i_dev)];
}
static void generic_file_readahead(int reada_ok,
diff --git a/mm/highmem.c b/mm/highmem.c
index 606b7d2e0..672500e52 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -25,7 +25,9 @@ static mempool_t *page_pool, *isa_page_pool;
static void *page_pool_alloc(int gfp_mask, void *data)
{
- return alloc_page(gfp_mask);
+ int gfp = gfp_mask | (int) (long) data;
+
+ return alloc_page(gfp);
}
static void page_pool_free(void *page, void *data)
@@ -252,7 +254,7 @@ int init_emergency_isa_pool(void)
if (isa_page_pool)
return 0;
- isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc, page_pool_free, NULL);
+ isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc, page_pool_free, (void *) __GFP_DMA);
if (!isa_page_pool)
BUG();
@@ -272,7 +274,7 @@ static inline void copy_to_high_bio_irq(struct bio *to, struct bio *from)
int i;
__bio_for_each_segment(tovec, to, i, 0) {
- fromvec = &from->bi_io_vec[i];
+ fromvec = from->bi_io_vec + i;
/*
* not bounced
@@ -301,7 +303,7 @@ static inline int bounce_end_io (struct bio *bio, int nr_sectors, mempool_t *poo
* free up bounce indirect pages used
*/
__bio_for_each_segment(bvec, bio, i, 0) {
- org_vec = &bio_orig->bi_io_vec[i];
+ org_vec = bio_orig->bi_io_vec + i;
if (bvec->bv_page == org_vec->bv_page)
continue;
@@ -394,7 +396,7 @@ void create_bounce(unsigned long pfn, int gfp, struct bio **bio_orig)
if (!bio)
bio = bio_alloc(bio_gfp, (*bio_orig)->bi_vcnt);
- to = &bio->bi_io_vec[i];
+ to = bio->bi_io_vec + i;
to->bv_page = mempool_alloc(pool, gfp);
to->bv_len = from->bv_len;
diff --git a/mm/mempool.c b/mm/mempool.c
index ecf1acc80..b9b6ae8c5 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -8,6 +8,7 @@
* started by Ingo Molnar, Copyright (C) 2001
*/
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mempool.h>
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 1d4c86872..895ba466e 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -3,6 +3,7 @@
*
* (C) Copyright 1994 Linus Torvalds
*/
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/shm.h>
diff --git a/mm/mremap.c b/mm/mremap.c
index 68d770043..0a42e05cb 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -4,6 +4,7 @@
* (C) Copyright 1996 Linus Torvalds
*/
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/shm.h>
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 880de784f..25a0a67e0 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -149,7 +149,8 @@ void oom_kill_task(struct task_struct *p)
* all the memory it needs. That way it should be able to
* exit() and clear out its resources quickly...
*/
- p->counter = 5 * HZ;
+ p->time_slice = 2 * MAX_TSLICE;
+ p->dyn_prio = MAX_DYNPRIO + 1;
p->flags |= PF_MEMALLOC | PF_MEMDIE;
/* This process has hardware access, be more careful. */
diff --git a/mm/page_io.c b/mm/page_io.c
index feb74055d..79700f304 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -38,7 +38,7 @@ static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
unsigned long offset;
sector_t zones[PAGE_SIZE/512];
int zones_used;
- kdev_t dev = 0;
+ kdev_t dev = NODEV;
int block_size;
struct inode *swapf = 0;
@@ -49,7 +49,7 @@ static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
kstat.pswpout++;
get_swaphandle_info(entry, &offset, &dev, &swapf);
- if (dev) {
+ if (!kdev_none(dev)) {
zones[0] = offset;
zones_used = 1;
block_size = PAGE_SIZE;
diff --git a/mm/slab.c b/mm/slab.c
index b91f65323..821918109 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -70,6 +70,8 @@
#include <linux/config.h>
#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/cache.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/compiler.h>
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 5d8c5d52a..ff9a8e1f0 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -5,6 +5,7 @@
* Swap reorganised 29.12.95, Stephen Tweedie
*/
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/kernel_stat.h>
@@ -773,7 +774,7 @@ asmlinkage long sys_swapoff(const char * specialfile)
swap_list_unlock();
goto out_dput;
}
- if (p->swap_device)
+ if (!kdev_none(p->swap_device))
blkdev_put(p->swap_file->d_inode->i_bdev, BDEV_SWAP);
path_release(&nd);
@@ -783,7 +784,7 @@ asmlinkage long sys_swapoff(const char * specialfile)
nd.dentry = p->swap_file;
p->swap_vfsmnt = NULL;
p->swap_file = NULL;
- p->swap_device = 0;
+ p->swap_device = NODEV;
p->max = 0;
swap_map = p->swap_map;
p->swap_map = NULL;
@@ -825,7 +826,7 @@ int get_swaparea_info(char *buf)
}
len += sprintf(buf + len, "%-39s %s\t%d\t%d\t%d\n",
path,
- ptr->swap_device ? "partition" : "file\t",
+ kdev_none(ptr->swap_device) ? "file\t" : "partition",
ptr->pages << (PAGE_SHIFT - 10),
usedswap << (PAGE_SHIFT - 10),
ptr->prio);
@@ -841,7 +842,7 @@ int is_swap_partition(kdev_t dev) {
for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
if (ptr->flags & SWP_USED)
- if (ptr->swap_device == dev)
+ if (kdev_same(ptr->swap_device, dev))
return 1;
}
return 0;
@@ -887,7 +888,7 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
p->flags = SWP_USED;
p->swap_file = NULL;
p->swap_vfsmnt = NULL;
- p->swap_device = 0;
+ p->swap_device = NODEV;
p->swap_map = NULL;
p->lowest_bit = 0;
p->highest_bit = 0;
@@ -913,26 +914,29 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
if (S_ISBLK(swap_inode->i_mode)) {
kdev_t dev = swap_inode->i_rdev;
struct block_device_operations *bdops;
+ devfs_handle_t de;
p->swap_device = dev;
set_blocksize(dev, PAGE_SIZE);
bd_acquire(swap_inode);
bdev = swap_inode->i_bdev;
- bdops = devfs_get_ops(devfs_get_handle_from_inode(swap_inode));
+ de = devfs_get_handle_from_inode(swap_inode);
+ bdops = devfs_get_ops(de); /* Increments module use count */
if (bdops) bdev->bd_op = bdops;
error = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_SWAP);
+ devfs_put_ops(de);/*Decrement module use count now we're safe*/
if (error)
goto bad_swap_2;
set_blocksize(dev, PAGE_SIZE);
error = -ENODEV;
- if (!dev || (blk_size[MAJOR(dev)] &&
- !blk_size[MAJOR(dev)][MINOR(dev)]))
+ if (kdev_none(dev) || (blk_size[major(dev)] &&
+ !blk_size[major(dev)][minor(dev)]))
goto bad_swap;
swapfilesize = 0;
- if (blk_size[MAJOR(dev)])
- swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
+ if (blk_size[major(dev)])
+ swapfilesize = blk_size[major(dev)][minor(dev)]
>> (PAGE_SHIFT - 10);
} else if (S_ISREG(swap_inode->i_mode))
swapfilesize = swap_inode->i_size >> PAGE_SHIFT;
@@ -1088,7 +1092,7 @@ bad_swap_2:
swap_map = p->swap_map;
nd.mnt = p->swap_vfsmnt;
nd.dentry = p->swap_file;
- p->swap_device = 0;
+ p->swap_device = NODEV;
p->swap_file = NULL;
p->swap_vfsmnt = NULL;
p->swap_map = NULL;
@@ -1241,7 +1245,7 @@ void get_swaphandle_info(swp_entry_t entry, unsigned long *offset,
return;
}
- if (p->swap_device) {
+ if (!kdev_none(p->swap_device)) {
*dev = p->swap_device;
} else if (p->swap_file) {
*swapf = p->swap_file->d_inode;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 9b1745314..8d6d9ffa1 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -11,6 +11,7 @@
* Multiqueue VM started 5.8.00, Rik van Riel.
*/
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/kernel_stat.h>
#include <linux/swap.h>
diff --git a/net/802/fddi.c b/net/802/fddi.c
index 7edee2bef..7ef4f823c 100644
--- a/net/802/fddi.c
+++ b/net/802/fddi.c
@@ -27,7 +27,6 @@
*/
#include <linux/config.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/net/802/hippi.c b/net/802/hippi.c
index 2e160f2c1..e451c2d5b 100644
--- a/net/802/hippi.c
+++ b/net/802/hippi.c
@@ -36,7 +36,6 @@
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/checksum.h>
-#include <asm/segment.h>
#include <asm/system.h>
/*
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index c934515e5..5c994e1a1 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -25,7 +25,6 @@
#include <linux/mm.h> /* verify_area(), etc. */
#include <linux/string.h> /* inline mem*, str* functions */
#include <linux/init.h> /* __initfunc et al. */
-#include <asm/segment.h> /* kernel <-> user copy */
#include <asm/byteorder.h> /* htons(), etc. */
#include <asm/uaccess.h> /* copy_to_user */
#include <asm/io.h>
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 23b9fcd92..2249f9b54 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/bitops.h>
#include <net/sock.h> /* for struct sock */
-#include <asm/segment.h> /* for get_fs_long and put_fs_long */
#include "common.h"
#include "resources.h"
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index bc17c49cb..ca33e3274 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -113,7 +113,6 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat
#include <linux/route.h>
#include <linux/netfilter.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/ioctls.h>
#include <linux/mm.h>
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index dfec1c9b2..b028a3ba0 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -59,7 +59,6 @@
#include <linux/inet.h>
#include <linux/route.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index 5e8482ce0..76faff30e 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -51,7 +51,6 @@
#include <linux/inet.h>
#include <linux/route.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 6de1d6103..852967b89 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -1,5 +1,5 @@
/*
- * $Id: ipconfig.c,v 1.44 2001-12-11 04:55:54 davem Exp $
+ * $Id: ipconfig.c,v 1.45 2002-01-08 16:00:20 davem Exp $
*
* Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or
* user-supplied information to configure own IP address and routes.
@@ -1145,7 +1145,7 @@ static int __init ip_auto_config(void)
*/
if (ic_myaddr == INADDR_NONE ||
#ifdef CONFIG_ROOT_NFS
- (MAJOR(ROOT_DEV) == UNNAMED_MAJOR
+ (major(ROOT_DEV) == UNNAMED_MAJOR
&& root_server_addr == INADDR_NONE
&& ic_servaddr == INADDR_NONE) ||
#endif
@@ -1170,7 +1170,7 @@ static int __init ip_auto_config(void)
* -- Chip
*/
#ifdef CONFIG_ROOT_NFS
- if (ROOT_DEV == MKDEV(UNNAMED_MAJOR, 255)) {
+ if (kdev_same(ROOT_DEV, mk_kdev(UNNAMED_MAJOR, 255))) {
printk(KERN_ERR
"IP-Config: Retrying forever (NFS root)...\n");
goto try_try_again;
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 7104eb14b..8271b50fa 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -38,7 +38,6 @@
#include <linux/tty.h>
#include <linux/interrupt.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <net/irda/irda.h>
@@ -387,13 +386,13 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
{
struct ircomm_tty_cb *self;
- int line;
+ unsigned int line;
int ret;
IRDA_DEBUG(2, __FUNCTION__ "()\n");
MOD_INC_USE_COUNT;
- line = MINOR(tty->device) - tty->driver.minor_start;
+ line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
MOD_DEC_USE_COUNT;
return -ENODEV;
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index c10bec1d4..92541bbab 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -35,7 +35,6 @@
#include <linux/tty.h>
#include <linux/serial.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <net/irda/irda.h>
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 1bb82ed57..133a5c30e 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -44,7 +44,6 @@
#include <linux/spinlock.h>
#include <asm/ioctls.h>
-#include <asm/segment.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
#include <asm/io.h>
diff --git a/net/irda/irsyms.c b/net/irda/irsyms.c
index 8936c66a9..04f4f996a 100644
--- a/net/irda/irsyms.c
+++ b/net/irda/irsyms.c
@@ -31,7 +31,6 @@
#include <linux/proc_fs.h>
#include <linux/smp_lock.h>
-#include <asm/segment.h>
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c
index 7a73ad8ed..c9b05fe9d 100644
--- a/net/irda/irsysctl.c
+++ b/net/irda/irsysctl.c
@@ -27,7 +27,6 @@
#include <linux/mm.h>
#include <linux/ctype.h>
#include <linux/sysctl.h>
-#include <asm/segment.h>
#include <net/irda/irda.h>
#include <net/irda/irias_object.h>
diff --git a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c
index fb9861692..8c13461ed 100644
--- a/net/netlink/netlink_dev.c
+++ b/net/netlink/netlink_dev.c
@@ -41,7 +41,7 @@ static struct socket *netlink_user[MAX_LINKS];
static unsigned int netlink_poll(struct file *file, poll_table * wait)
{
- struct socket *sock = netlink_user[MINOR(file->f_dentry->d_inode->i_rdev)];
+ struct socket *sock = netlink_user[minor(file->f_dentry->d_inode->i_rdev)];
if (sock->ops->poll==NULL)
return 0;
@@ -56,7 +56,7 @@ static ssize_t netlink_write(struct file * file, const char * buf,
size_t count, loff_t *pos)
{
struct inode *inode = file->f_dentry->d_inode;
- struct socket *sock = netlink_user[MINOR(inode->i_rdev)];
+ struct socket *sock = netlink_user[minor(inode->i_rdev)];
struct msghdr msg;
struct iovec iov;
@@ -80,7 +80,7 @@ static ssize_t netlink_read(struct file * file, char * buf,
size_t count, loff_t *pos)
{
struct inode *inode = file->f_dentry->d_inode;
- struct socket *sock = netlink_user[MINOR(inode->i_rdev)];
+ struct socket *sock = netlink_user[minor(inode->i_rdev)];
struct msghdr msg;
struct iovec iov;
@@ -105,7 +105,7 @@ static loff_t netlink_lseek(struct file * file, loff_t offset, int origin)
static int netlink_open(struct inode * inode, struct file * file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct socket *sock;
struct sockaddr_nl nladdr;
int err;
@@ -137,7 +137,7 @@ out:
static int netlink_release(struct inode * inode, struct file * file)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
struct socket *sock;
sock = netlink_user[minor];
@@ -151,7 +151,7 @@ static int netlink_release(struct inode * inode, struct file * file)
static int netlink_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- unsigned int minor = MINOR(inode->i_rdev);
+ unsigned int minor = minor(inode->i_rdev);
int retval = 0;
if (minor >= MAX_LINKS)
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index c3fea8fe7..d721721e8 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -44,7 +44,6 @@
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index 8c45fbe65..e50bda038 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -32,7 +32,6 @@
#include <linux/if_ether.h> /* For the statistics structure. */
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <linux/inet.h>
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 38fb76c1b..03a0cb9b1 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -38,7 +38,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/ip.h> /* For ip_rcv */
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index 2c793e4e6..1cd86a1d6 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -29,7 +29,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c
index 8f9855df7..c91e96d5c 100644
--- a/net/rose/rose_out.c
+++ b/net/rose/rose_out.c
@@ -30,7 +30,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 387e6ac7c..67eef2cdf 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -36,7 +36,6 @@
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c
index 98658b439..e38b4dd46 100644
--- a/net/rose/rose_subr.c
+++ b/net/rose/rose_subr.c
@@ -30,7 +30,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index 8bd30424d..7eeb43897 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -30,7 +30,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 17e8370a0..8f71439ad 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -7,11 +7,11 @@
*/
#include <linux/types.h>
-#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/utsname.h>
#include <linux/sunrpc/clnt.h>
+#include <linux/sched.h>
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index cb0804f2e..fc42c873a 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -7,7 +7,7 @@
*/
#include <linux/types.h>
-#include <linux/slab.h>
+#include <linux/sched.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/sunrpc/clnt.h>
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index d2336b8bb..cbd52721c 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -46,7 +46,6 @@
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 1abb28358..c6e13a2c2 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -33,7 +33,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index adf757e56..95411fa4b 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -32,7 +32,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index 73a567e89..93fa6d7ef 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -37,7 +37,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/ip.h> /* For ip_rcv */
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index 37c96d681..cce5b6a3a 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -34,7 +34,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c
index fdf555474..e56b2d1ee 100644
--- a/net/x25/x25_out.c
+++ b/net/x25/x25_out.c
@@ -35,7 +35,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c
index a4651699e..2a816b274 100644
--- a/net/x25/x25_route.c
+++ b/net/x25/x25_route.c
@@ -33,7 +33,6 @@
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index a5804fa30..0c41d5c60 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -34,7 +34,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c
index cf9b42606..b808490b3 100644
--- a/net/x25/x25_timer.c
+++ b/net/x25/x25_timer.c
@@ -32,7 +32,6 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>